Linux kernel DMA超时的原因是什么?

Linux kernel DMA超时的原因是什么?,linux-kernel,dma,Linux Kernel,Dma,我在尝试分配DMA内存区域时看到超时。虽然我可以通过使用GFP_原子而不是GFP_内核als GFP标志来消除此错误,以便DMA分配变得不可中断,但我想知道出现这种超时的原因是什么?系统总线不知道请求的内存区域?公共汽车饱和了吗 [ 87.400000] [<c0138eec>] (schedule_bug) from [<c05a0774>] (schedule+0x3c/0x528) [ 87.410000] [<c05a0774>] (__sch

我在尝试分配DMA内存区域时看到超时。虽然我可以通过使用GFP_原子而不是GFP_内核als GFP标志来消除此错误,以便DMA分配变得不可中断,但我想知道出现这种超时的原因是什么?系统总线不知道请求的内存区域?公共汽车饱和了吗

[   87.400000] [<c0138eec>] (schedule_bug) from [<c05a0774>] (schedule+0x3c/0x528)
[   87.410000] [<c05a0774>] (__schedule) from [<c05a0d0c>] (schedule+0xac/0xcc)
[   87.410000] [<c05a0d0c>] (schedule) from [<c05a3e20>] (schedule_timeout+0x20/0x2b8)
[   87.420000] [<c05a3e20>] (schedule_timeout) from [<c05a1804>] (wait_for_common+0xf8/0x1a8)
[   87.430000] [<c05a1804>] (wait_for_common) from [<c012c540>] (flush_work+0x174/0x1ac)
[   87.450000] [<c012c540>] (flush_work) from [<c01a0648>] (drain_all_pages+0x108/0x130)
[   87.460000] [<c01a0648>] (drain_all_pages) from [<c01d6d34>] (start_isolate_page_range+0xbc/0x284)
[   87.470000] [<c01d6d34>] (start_isolate_page_range) from [<c01a3310>] (alloc_contig_range+0xdc/0x330)
[   87.480000] [<c01a3310>] (alloc_contig_range) from [<c01d7658>] (cma_alloc+0x170/0x308)
[   87.490000] [<c01d7658>] (cma_alloc) from [<c011142c>] (__alloc_from_contiguous+0x40/0xd8)
[   87.500000] [<c011142c>] (__alloc_from_contiguous) from    [<c0111500>] (cma_allocator_alloc+0x3c/0x44)
[   87.510000] [<c0111500>] (cma_allocator_alloc) from [<c010f86c>] (__dma_alloc+0x1d4/0x2fc)
[   87.520000] [<c010f86c>] (__dma_alloc) from [<c010fa0c>] (arm_dma_alloc+0x3c/0x48)
[   87.530000] [<c010fa0c>] (arm_dma_alloc) from [<c03ae018>] (tsg_ioctl+0x3e4/0x954)
[87.400000][](计划错误)来自[](计划+0x3c/0x528)
[87.410000][](计划表)从[](计划表+0xac/0xcc)
[87.410000][](计划)从[](计划超时+0x20/0x2b8)
[87.420000][](计划超时)从[](等待公共+0xf8/0x1a8)
[87.430000][](等待公用)从[](冲洗工作+0x174/0x1ac)
[87.450000][](冲洗工作)从[](排空所有页面+0x108/0x130)
[87.460000][](从[](开始隔离页面范围+0xbc/0x284)中排出所有页面)
[87.470000][](开始隔离页面范围)从[](所有重叠范围+0xdc/0x330)
[87.480000][](分配范围)从[](cma\u分配+0x170/0x308)
[87.490000][](cma_alloc)from[](_alloc_from_continuous+0x40/0xd8)
[87.500000][](u alloc_from_continuous)from[](cma_分配器_alloc+0x3c/0x44)
[87.510000][](cma_分配器_分配程序_分配)来自[](_dma_分配+0x1d4/0x2fc)
[87.520000][](自[](arm\U dma\U alloc+0x3c/0x48)
[87.530000][](arm_dma_alloc)从[](tsg_ioctl+0x3e4/0x954)

最有可能的原因是,您正在从禁止睡眠的原子上下文调用支持睡眠的函数(
arm\u dma\u alloc
)。可能您是在
旋转锁定
下进行此分配的。
spin_lock
调用,这意味着不可能重新安排。这就是
spin\u lock
的工作原理。无论如何,如果在
spin\u lock/spin\u unlock
中调用sleep原语并发生重新调度,内核调度程序子系统将警告您,您已在原子上下文中重新调度(这是您在该消息中看到的)。

最有可能的原因是您正在调用支持睡眠的函数(
arm\u dma\u alloc
)来自禁止睡眠的原子上下文。可能您是在
spin\u lock
下进行此分配的。
spin\u lock
调用,这意味着不可能进行重新调度。这就是
spin\u lock
的工作方式。无论如何,如果您在
spin\u lock/spin\u unlock
中调用休眠原语并进行重新调度,内核调度程序子系统将警告您已在原子上下文中重新调度(这就是您在此消息中看到的内容)。

提供完整的堆栈跟踪和一段代码片段(带上下文),说明如何调用arm_dma_alloc。最可能的原因是您正在调用支持睡眠的函数(arm_dma_alloc)从原子上下文来看,睡眠是被禁止的。也许你是在自旋锁下进行分配的。你说得对,我在自旋锁保持的情况下打电话。但这是发生超时的唯一原因吗?是的,这就是原因。正如你所看到的,这是一个调度错误。有关更多详细信息,请参阅我的答案。这可能会有用,提供完整的堆栈跟踪和您如何调用arm_dma_alloc的代码片段(带有上下文)。最可能的原因是您正在调用支持睡眠的函数(arm_dma_alloc)从原子上下文来看,睡眠是被禁止的。也许你是在自旋锁下进行分配的。你是对的,我在自旋锁保持的情况下打电话来的。但是这是导致超时的唯一原因吗?是的,这就是原因。正如你所看到的,这是一个时间表错误。有关更多详细信息,请参阅我的答案。这可能会有用