forked from luck/tmp_suning_uos_patched
iommu/dma: Avoid unlikely high-order allocations
Doug reports that the equivalent page allocator on 32-bit ARM exhibits particularly pathalogical behaviour under memory pressure when fragmentation is high, where allocating a 4MB buffer takes tens of seconds and the number of calls to alloc_pages() is over 9000![1] We can drastically improve that situation without losing the other benefits of high-order allocations when they would succeed, by assuming memory pressure is relatively constant over the course of an allocation, and not retrying allocations at orders we know to have failed before. This way, the best-case behaviour remains unchanged, and in the worst case we should see at most a dozen or so (MAX_ORDER - 1) failed attempts before falling back to single pages for the remainder of the buffer. [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2015-December/394660.html Reported-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
5b11e9cd42
commit
0a9afeda80
|
@ -194,6 +194,7 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp)
|
|||
{
|
||||
struct page **pages;
|
||||
unsigned int i = 0, array_size = count * sizeof(*pages);
|
||||
unsigned int order = MAX_ORDER;
|
||||
|
||||
if (array_size <= PAGE_SIZE)
|
||||
pages = kzalloc(array_size, GFP_KERNEL);
|
||||
|
@ -207,14 +208,15 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp)
|
|||
|
||||
while (count) {
|
||||
struct page *page = NULL;
|
||||
int j, order = __fls(count);
|
||||
int j;
|
||||
|
||||
/*
|
||||
* Higher-order allocations are a convenience rather
|
||||
* than a necessity, hence using __GFP_NORETRY until
|
||||
* falling back to single-page allocations.
|
||||
*/
|
||||
for (order = min(order, MAX_ORDER); order > 0; order--) {
|
||||
for (order = min_t(unsigned int, order, __fls(count));
|
||||
order > 0; order--) {
|
||||
page = alloc_pages(gfp | __GFP_NORETRY, order);
|
||||
if (!page)
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue
Block a user