| From 1cf389df090194a0976dc867b7fffe99d9d490cb Mon Sep 17 00:00:00 2001 |
| From: Nishanth Aravamudan <nacc@linux.vnet.ibm.com> |
| Date: Tue, 1 Oct 2013 14:04:53 -0700 |
| Subject: powerpc/iommu: Use GFP_KERNEL instead of GFP_ATOMIC in iommu_init_table() |
| |
| From: Nishanth Aravamudan <nacc@linux.vnet.ibm.com> |
| |
| commit 1cf389df090194a0976dc867b7fffe99d9d490cb upstream. |
| |
| Under heavy (DLPAR?) stress, we tripped this panic() in |
| arch/powerpc/kernel/iommu.c::iommu_init_table(): |
| |
| page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); |
| if (!page) |
| panic("iommu_init_table: Can't allocate %ld bytes\n", sz); |
| |
| Before the panic() we got a page allocation failure for an order-2 |
| allocation. There appears to be memory free, but perhaps not in the |
| ATOMIC context. I looked through all the call-sites of |
| iommu_init_table() and didn't see any obvious reason to need an ATOMIC |
| allocation. Most call-sites in fact have an explicit GFP_KERNEL |
| allocation shortly before the call to iommu_init_table(), indicating we |
| are not in an atomic context. There is some indirection for some paths, |
| but I didn't see any locks indicating that GFP_KERNEL is inappropriate. |
| |
| With this change under the same conditions, we have not been able to |
| reproduce the panic. |
| |
| Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com> |
| Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/kernel/iommu.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/arch/powerpc/kernel/iommu.c |
| +++ b/arch/powerpc/kernel/iommu.c |
| @@ -661,7 +661,7 @@ struct iommu_table *iommu_init_table(str |
| /* number of bytes needed for the bitmap */ |
| sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long); |
| |
| - page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); |
| + page = alloc_pages_node(nid, GFP_KERNEL, get_order(sz)); |
| if (!page) |
| panic("iommu_init_table: Can't allocate %ld bytes\n", sz); |
| tbl->it_map = page_address(page); |