The upper 32-bit physical address gets truncated inadvertently when dma_direct_get_required_mask() invokes phys_to_dma_direct(). This results in dma_addressing_limited() return incorrect value when used in platforms with LPAE enabled. Fix it here by explicitly type casting 'max_pfn' to phys_addr_t in order to prevent overflow of intermediate value while evaluating '(max_pfn - 1) << PAGE_SHIFT'.
Signed-off-by: Kishon Vijay Abraham I <kis...@ti.com> --- Fixes the following WARN DUMP (and hang thereafter) observed when connecting NVMe card to a platform with ARM LPAE enabled nvme 0000:01:00.0: overflow 0x000000027b3be000+270336 of DMA mask ffffffffffffffff bus limit ffffffff -----------[ cut here ]----------- WARNING: CPU: 0 PID: 26 at kernel/dma/direct.c:35 report_addr+0xf0/0xf4 Modules linked in: CPU: 0 PID: 26 Comm: kworker/u4:1 Not tainted 5.5.0-00002-g1383adf7b819 #2 Hardware name: Generic DRA74X (Flattened Device Tree) Workqueue: writeback wb_workfn (flush-259:0) (unwind_backtrace) from [<c020b494>] (show_stack+0x10/0x14) (show_stack) from [<c0a2ae24>] (dump_stack+0x94/0xa8) (dump_stack) from [<c022bbd8>] (__warn+0xbc/0xd8) (__warn) from [<c022bc54>] (warn_slowpath_fmt+0x60/0xb8) (warn_slowpath_fmt) from [<c0299928>] (report_addr+0xf0/0xf4) (report_addr) from [<c0299ab8>] (dma_direct_map_page+0x18c/0x19c) (dma_direct_map_page) from [<c0299b2c>] (dma_direct_map_sg+0x64/0xb4) (dma_direct_map_sg) from [<c071b12c>] (nvme_queue_rq+0x778/0x9ec) (nvme_queue_rq) from [<c050c8c8>] (__blk_mq_try_issue_directly+0x130/0x1bc) (__blk_mq_try_issue_directly) from [<c050d1b8>] (blk_mq_request_issue_directly+0x48/0x78) (blk_mq_request_issue_directly) from [<c050d22c>] (blk_mq_try_issue_list_directly+0x44/0xb8) (blk_mq_try_issue_list_directly) from [<c0511620>] (blk_mq_sched_insert_requests+0xe0/0x154) (blk_mq_sched_insert_requests) from [<c050d13c>] (blk_mq_flush_plug_list+0x150/0x184) (blk_mq_flush_plug_list) from [<c0502ec4>] (blk_flush_plug_list+0xc8/0xe4) (blk_flush_plug_list) from [<c050cc44>] (blk_mq_make_request+0x24c/0x3f0) (blk_mq_make_request) from [<c0501acc>] (generic_make_request+0xb0/0x2d4) (generic_make_request) from [<c0501d34>] (submit_bio+0x44/0x180) (submit_bio) from [<c039ad10>] (mpage_writepages+0xac/0xe8) (mpage_writepages) from [<c02f96dc>] (do_writepages+0x44/0xdc) (do_writepages) from [<c0384830>] (__writeback_single_inode+0x2c/0x1bc) (__writeback_single_inode) from [<c0384b98>] (writeback_sb_inodes+0x1d8/0x404) (writeback_sb_inodes) from [<c0384e1c>] (__writeback_inodes_wb+0x58/0x9c) (__writeback_inodes_wb) from [<c0384ff4>] (wb_writeback+0x194/0x1d8) (wb_writeback) from [<c0386104>] (wb_workfn+0x244/0x33c) (wb_workfn) from [<c0244ff8>] (process_one_work+0x204/0x458) (process_one_work) from [<c0245290>] (worker_thread+0x44/0x598) (worker_thread) from [<c024ab30>] (kthread+0x14c/0x150) (kthread) from [<c02010d8>] (ret_from_fork+0x14/0x3c) kernel/dma/direct.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c index ac7956c38f69..4b24275e306a 100644 --- a/kernel/dma/direct.c +++ b/kernel/dma/direct.c @@ -39,7 +39,8 @@ static inline struct page *dma_direct_to_page(struct device *dev, u64 dma_direct_get_required_mask(struct device *dev) { - u64 max_dma = phys_to_dma_direct(dev, (max_pfn - 1) << PAGE_SHIFT); + phys_addr_t phys = (phys_addr_t)(max_pfn - 1) << PAGE_SHIFT; + u64 max_dma = phys_to_dma_direct(dev, phys); return (1ULL << (fls64(max_dma) - 1)) * 2 - 1; } -- 2.17.1 _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu