mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-20 18:54:09 +08:00
186dfc9d69
When we boot a kdump kernel in high memory, there is by default only 72MB of low memory available. The swiotlb code takes 64MB of it (by default) so that there are only 8MB left to allocate from. On systems with many devices this causes page allocator warnings from dma_generic_alloc_coherent(): systemd-udevd: page allocation failure: order:0, mode:0x280d4 CPU: 0 PID: 197 Comm: systemd-udevd Tainted: G W 3.12.28-4-default #1 Hardware name: HP ProLiant DL980 G7, BIOS P66 07/30/2012 ffff8800781335e0 ffffffff8150b1db 00000000000280d4 ffffffff8113af90 0000000000000000 0000000000000000 ffff88007efdbb00 0000000100000000 0000000000000000 0000000000000000 0000000000000000 0000000000000001 Call Trace: dump_trace+0x7d/0x2d0 show_stack_log_lvl+0x94/0x170 show_stack+0x21/0x50 dump_stack+0x41/0x51 warn_alloc_failed+0xf0/0x160 __alloc_pages_slowpath+0x72f/0x796 __alloc_pages_nodemask+0x1ea/0x210 dma_generic_alloc_coherent+0x96/0x140 x86_swiotlb_alloc_coherent+0x1c/0x50 ttm_dma_pool_alloc_new_pages+0xab/0x320 [ttm] ttm_dma_populate+0x3ce/0x640 [ttm] ttm_tt_bind+0x36/0x60 [ttm] ttm_bo_handle_move_mem+0x55f/0x5c0 [ttm] ttm_bo_move_buffer+0x105/0x130 [ttm] ttm_bo_validate+0xc1/0x130 [ttm] ttm_bo_init+0x24b/0x400 [ttm] radeon_bo_create+0x16c/0x200 [radeon] radeon_ring_init+0x11e/0x2b0 [radeon] r100_cp_init+0x123/0x5b0 [radeon] r100_startup+0x194/0x230 [radeon] r100_init+0x223/0x410 [radeon] radeon_device_init+0x6af/0x830 [radeon] radeon_driver_load_kms+0x89/0x180 [radeon] drm_get_pci_dev+0x121/0x2f0 [drm] local_pci_probe+0x39/0x60 pci_device_probe+0xa9/0x120 driver_probe_device+0x9d/0x3d0 __driver_attach+0x8b/0x90 bus_for_each_dev+0x5b/0x90 bus_add_driver+0x1f8/0x2c0 driver_register+0x5b/0xe0 do_one_initcall+0xf2/0x1a0 load_module+0x1207/0x1c70 SYSC_finit_module+0x75/0xa0 system_call_fastpath+0x16/0x1b 0x7fac533d2788 After these warnings the code enters a fall-back path and allocated directly from the swiotlb aperture in the end. So remove these warnings as this is not a fatal error. Signed-off-by: Joerg Roedel <jroedel@suse.de> [ Simplify, reflow comment. ] Signed-off-by: Borislav Petkov <bp@suse.de> Acked-by: Baoquan He <bhe@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Young <dyoung@redhat.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jörg Rödel <joro@8bytes.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: kexec@lists.infradead.org Link: http://lkml.kernel.org/r/1433500202-25531-3-git-send-email-joro@8bytes.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
120 lines
2.9 KiB
C
120 lines
2.9 KiB
C
/* Glue code to lib/swiotlb.c */
|
|
|
|
#include <linux/pci.h>
|
|
#include <linux/cache.h>
|
|
#include <linux/module.h>
|
|
#include <linux/swiotlb.h>
|
|
#include <linux/bootmem.h>
|
|
#include <linux/dma-mapping.h>
|
|
|
|
#include <asm/iommu.h>
|
|
#include <asm/swiotlb.h>
|
|
#include <asm/dma.h>
|
|
#include <asm/xen/swiotlb-xen.h>
|
|
#include <asm/iommu_table.h>
|
|
int swiotlb __read_mostly;
|
|
|
|
void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
|
|
dma_addr_t *dma_handle, gfp_t flags,
|
|
struct dma_attrs *attrs)
|
|
{
|
|
void *vaddr;
|
|
|
|
/*
|
|
* Don't print a warning when the first allocation attempt fails.
|
|
* swiotlb_alloc_coherent() will print a warning when the DMA
|
|
* memory allocation ultimately failed.
|
|
*/
|
|
flags |= __GFP_NOWARN;
|
|
|
|
vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags,
|
|
attrs);
|
|
if (vaddr)
|
|
return vaddr;
|
|
|
|
return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags);
|
|
}
|
|
|
|
void x86_swiotlb_free_coherent(struct device *dev, size_t size,
|
|
void *vaddr, dma_addr_t dma_addr,
|
|
struct dma_attrs *attrs)
|
|
{
|
|
if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr)))
|
|
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
|
|
else
|
|
dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs);
|
|
}
|
|
|
|
static struct dma_map_ops swiotlb_dma_ops = {
|
|
.mapping_error = swiotlb_dma_mapping_error,
|
|
.alloc = x86_swiotlb_alloc_coherent,
|
|
.free = x86_swiotlb_free_coherent,
|
|
.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
|
|
.sync_single_for_device = swiotlb_sync_single_for_device,
|
|
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
|
|
.sync_sg_for_device = swiotlb_sync_sg_for_device,
|
|
.map_sg = swiotlb_map_sg_attrs,
|
|
.unmap_sg = swiotlb_unmap_sg_attrs,
|
|
.map_page = swiotlb_map_page,
|
|
.unmap_page = swiotlb_unmap_page,
|
|
.dma_supported = NULL,
|
|
};
|
|
|
|
/*
|
|
* pci_swiotlb_detect_override - set swiotlb to 1 if necessary
|
|
*
|
|
* This returns non-zero if we are forced to use swiotlb (by the boot
|
|
* option).
|
|
*/
|
|
int __init pci_swiotlb_detect_override(void)
|
|
{
|
|
int use_swiotlb = swiotlb | swiotlb_force;
|
|
|
|
if (swiotlb_force)
|
|
swiotlb = 1;
|
|
|
|
return use_swiotlb;
|
|
}
|
|
IOMMU_INIT_FINISH(pci_swiotlb_detect_override,
|
|
pci_xen_swiotlb_detect,
|
|
pci_swiotlb_init,
|
|
pci_swiotlb_late_init);
|
|
|
|
/*
|
|
* if 4GB or more detected (and iommu=off not set) return 1
|
|
* and set swiotlb to 1.
|
|
*/
|
|
int __init pci_swiotlb_detect_4gb(void)
|
|
{
|
|
/* don't initialize swiotlb if iommu=off (no_iommu=1) */
|
|
#ifdef CONFIG_X86_64
|
|
if (!no_iommu && max_pfn > MAX_DMA32_PFN)
|
|
swiotlb = 1;
|
|
#endif
|
|
return swiotlb;
|
|
}
|
|
IOMMU_INIT(pci_swiotlb_detect_4gb,
|
|
pci_swiotlb_detect_override,
|
|
pci_swiotlb_init,
|
|
pci_swiotlb_late_init);
|
|
|
|
void __init pci_swiotlb_init(void)
|
|
{
|
|
if (swiotlb) {
|
|
swiotlb_init(0);
|
|
dma_ops = &swiotlb_dma_ops;
|
|
}
|
|
}
|
|
|
|
void __init pci_swiotlb_late_init(void)
|
|
{
|
|
/* An IOMMU turned us off. */
|
|
if (!swiotlb)
|
|
swiotlb_free();
|
|
else {
|
|
printk(KERN_INFO "PCI-DMA: "
|
|
"Using software bounce buffering for IO (SWIOTLB)\n");
|
|
swiotlb_print_info();
|
|
}
|
|
}
|