dfu: don't keep freeing/reallocating
authorStephen Warren <swarren@nvidia.com>
Sat, 5 Sep 2015 04:03:46 +0000 (22:03 -0600)
committerTom Rini <trini@konsulko.com>
Fri, 11 Sep 2015 21:15:23 +0000 (17:15 -0400)
commit806bd245b1ab392245e6adc56522c3473edbc805
treea0ca1c507428488a18eb610df2ff3a315bacb11d
parentd56b2015e6d5695d009d8e5e3930cbf34c3b5da0
dfu: don't keep freeing/reallocating

DFU currently allocates buffer memory at the start of each data transfer
operation and frees it at the end. Especially since memalign() is used to
allocate the buffer, and various other allocations happen during the
transfer, this can expose the code to heap fragmentation, which prevents
the allocation from succeeding on subsequent transfers.

Fix the code to allocate the buffer once when DFU mode is initialized,
and free the buffer once when DFU mode is exited, to reduce the exposure
to heap fragmentation.

The failure mode is:

// Internally to memalign(), this allocates a lot more than s to guarantee
// that alignment can occur, then returns chunks of memory at the start/
// end of the allocated buffer to the heap.
p = memalign(a, s);
// Various other malloc()s occur here, some of which allocate the RAM
// immediately before/after "p".
//
// DFU transfer is complete, so buffer is released.
free(p);
// By chance, no other malloc()/free() here, in DFU at least.
//
// A new DFU transfer starts, so the buffer is allocated again.
// In theory this should succeed since we just free()d a buffer of the
// same size. However, this fails because memalign() internally attempts
// to allocate much more than "s", yet free(p) above only free()d a
// little more than "s".
p = memalign(a, s);

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
drivers/dfu/dfu.c