Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7f09ae5 authored by Miquel van Smoorenburg's avatar Miquel van Smoorenburg Committed by Ingo Molnar
Browse files

x86, pci-dma.c: don't always add __GFP_NORETRY to gfp



Currently arch/x86/kernel/pci-dma.c always adds __GFP_NORETRY
to the allocation flags, because it wants to be reasonably
sure not to deadlock when calling alloc_pages().

But really that should only be done in two cases:
- when allocating memory in the lower 16 MB DMA zone.
  If there's no free memory there, waiting or OOM killing is of no use
- when optimistically trying an allocation in the DMA32 zone
  when dma_mask < DMA_32BIT_MASK hoping that the allocation
  happens to fall within the limits of the dma_mask

Also blindly adding __GFP_NORETRY to the the gfp variable might
not be a good idea since we then also use it when calling
dma_ops->alloc_coherent(). Clearing it might also not be a
good idea, dma_alloc_coherent()'s caller might have set it
on purpose. The gfp variable should not be clobbered.

[ mingo@elte.hu: converted to delta patch ontop of previous version. ]

Signed-off-by: default avatarMiquel van Smoorenburg <miquels@cistron.nl>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent f529626a
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -378,6 +378,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
	struct page *page;
	unsigned long dma_mask = 0;
	dma_addr_t bus;
	int noretry = 0;

	/* ignore region specifiers */
	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
@@ -397,19 +398,25 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
	if (dev->dma_mask == NULL)
		return NULL;

	/* Don't invoke OOM killer or retry in lower 16MB DMA zone */
	if (gfp & __GFP_DMA)
		noretry = 1;

#ifdef CONFIG_X86_64
	/* Why <=? Even when the mask is smaller than 4GB it is often
	   larger than 16MB and in this case we have a chance of
	   finding fitting memory in the next higher zone first. If
	   not retry with true GFP_DMA. -AK */
	if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA))
	if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
		gfp |= GFP_DMA32;
		if (dma_mask < DMA_32BIT_MASK)
			noretry = 1;
	}
#endif

 again:
	/* Don't invoke OOM killer or retry in lower 16MB DMA zone */
	page = dma_alloc_pages(dev,
		(gfp & GFP_DMA) ? gfp | __GFP_NORETRY : gfp, get_order(size));
		noretry ? gfp | __GFP_NORETRY : gfp, get_order(size));
	if (page == NULL)
		return NULL;