From mboxrd@z Thu Jan 1 00:00:00 1970 From: andreas.herrmann@calxeda.com (Andreas Herrmann) Date: Fri, 31 Jan 2014 00:55:52 +0100 Subject: iommu/arm-smmu: Regression (sleeping function called from invalid context) Message-ID: <20140130235552.GL13543@alberich> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hi Will, Seems that commit a44a9791e778d9ccda50d5534028ed4057a9a45b (iommu/arm-smmu: use mutex instead of spinlock for locking page tables) introduced a regression. At least I've hit BUG: scheduling while atomic: ksoftirqd/0/3/0x00000100 and after turning on CONFIG_DEBUG_ATOMIC_SLEEP I get BUG: sleeping function called from invalid context at kernel/locking/mutex.c:96 in_atomic(): 1, irqs_disabled(): 128, pid: 1, name: swapper/0 CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.13.0-00013-gd414667 #411 [] (unwind_backtrace+0x0/0xf8) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (dump_stack+0x74/0xa8) [] (dump_stack+0x74/0xa8) from [] (mutex_lock+0x18/0x64) [] (mutex_lock+0x18/0x64) from [] (arm_smmu_handle_mapping+0xfc/0x644) [] (arm_smmu_handle_mapping+0xfc/0x644) from [] (iommu_map+0xf0/0x148) [] (iommu_map+0xf0/0x148) from [] (__map_sg_chunk+0x208/0x414) [] (__map_sg_chunk+0x208/0x414) from [] (__iommu_map_sg+0x17c/0x208) [] (__iommu_map_sg+0x17c/0x208) from [] (arm_iommu_map_sg+0x1c/0x24) [] (arm_iommu_map_sg+0x1c/0x24) from [] (ata_qc_issue+0x258/0x370) [] (ata_qc_issue+0x258/0x370) from [] (ata_scsi_translate+0x90/0x150) [] (ata_scsi_translate+0x90/0x150) from [] (ata_scsi_queuecmd+0x84/0x248) [] (ata_scsi_queuecmd+0x84/0x248) from [] (scsi_dispatch_cmd+0x94/0x134) [] (scsi_dispatch_cmd+0x94/0x134) from [] (scsi_request_fn+0x3dc/0x5dc) [] (scsi_request_fn+0x3dc/0x5dc) from [] (__blk_run_queue+0x34/0x44) [] (__blk_run_queue+0x34/0x44) from [] (blk_queue_bio+0x178/0x26c) [] (blk_queue_bio+0x178/0x26c) from [] (generic_make_request+0xa8/0xc8) [] (generic_make_request+0xa8/0xc8) from [] (submit_bio+0x88/0x134) [] (submit_bio+0x88/0x134) from [] (_submit_bh+0x1a4/0x254) [] (_submit_bh+0x1a4/0x254) from [] (ll_rw_block+0x94/0xec) [] (ll_rw_block+0x94/0xec) from [] (__breadahead+0x30/0x48) [] (__breadahead+0x30/0x48) from [] (__ext4_get_inode_loc+0x3c4/0x450) [] (__ext4_get_inode_loc+0x3c4/0x450) from [] (ext4_iget+0x60/0x96c) [] (ext4_iget+0x60/0x96c) from [] (ext4_lookup+0x74/0x164) [] (ext4_lookup+0x74/0x164) from [] (lookup_real+0x20/0x50) [] (lookup_real+0x20/0x50) from [] (__lookup_hash+0x34/0x44) [] (__lookup_hash+0x34/0x44) from [] (lookup_slow+0x38/0x9c) [] (lookup_slow+0x38/0x9c) from [] (link_path_walk+0x308/0x7f0) [] (link_path_walk+0x308/0x7f0) from [] (path_openat+0x8c/0x63c) [] (path_openat+0x8c/0x63c) from [] (do_filp_open+0x2c/0x80) [] (do_filp_open+0x2c/0x80) from [] (open_exec+0x2c/0xf8) [] (open_exec+0x2c/0xf8) from [] (do_execve+0x1a4/0x5a4) [] (do_execve+0x1a4/0x5a4) from [] (try_to_run_init_process+0x1c/0x50) [] (try_to_run_init_process+0x1c/0x50) from [] (kernel_init+0xa8/0x110) [] (kernel_init+0xa8/0x110) from [] (ret_from_fork+0x14/0x3c) After reverting commit a44a9791e778d9ccda50d5534028ed4057a9a45b I have fewer warnings/errors but still I've seen: BUG: sleeping function called from invalid context at mm/page_alloc.c:2679 in_atomic(): 1, irqs_disabled(): 128, pid: 0, name: swapper/0 CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.13.0-00016-g6e90346 #413 [] (unwind_backtrace+0x0/0xf8) from [] (show_stack+0x10/0x14) [] (show_stack+0x10/0x14) from [] (dump_stack+0x74/0xa8) [] (dump_stack+0x74/0xa8) from [] (__alloc_pages_nodemask+0x174/0x930) [] (__alloc_pages_nodemask+0x174/0x930) from [] (arm_smmu_handle_mapping+0x470/0x66c) [] (arm_smmu_handle_mapping+0x470/0x66c) from [] (iommu_map+0xf0/0x148) [] (iommu_map+0xf0/0x148) from [] (__map_sg_chunk+0x198/0x2d4) [] (__map_sg_chunk+0x198/0x2d4) from [] (__iommu_map_sg+0x17c/0x208) [] (__iommu_map_sg+0x17c/0x208) from [] (arm_iommu_map_sg+0x1c/0x24) [] (arm_iommu_map_sg+0x1c/0x24) from [] (ata_qc_issue+0x258/0x370) [] (ata_qc_issue+0x258/0x370) from [] (ata_scsi_translate+0x90/0x150) [] (ata_scsi_translate+0x90/0x150) from [] (ata_scsi_queuecmd+0x84/0x248) [] (ata_scsi_queuecmd+0x84/0x248) from [] (scsi_dispatch_cmd+0x94/0x134) [] (scsi_dispatch_cmd+0x94/0x134) from [] (scsi_request_fn+0x3dc/0x5dc) [] (scsi_request_fn+0x3dc/0x5dc) from [] (__blk_run_queue+0x34/0x44) [] (__blk_run_queue+0x34/0x44) from [] (blk_run_queue+0x1c/0x2c) [] (blk_run_queue+0x1c/0x2c) from [] (scsi_run_queue+0xc4/0x240) [] (scsi_run_queue+0xc4/0x240) from [] (scsi_next_command+0x2c/0x38) [] (scsi_next_command+0x2c/0x38) from [] (scsi_io_completion+0x1fc/0x630) [] (scsi_io_completion+0x1fc/0x630) from [] (blk_done_softirq+0x74/0x8c) [] (blk_done_softirq+0x74/0x8c) from [] (__do_softirq+0xe4/0x210) [] (__do_softirq+0xe4/0x210) from [] (irq_exit+0xa0/0xec) [] (irq_exit+0xa0/0xec) from [] (handle_IRQ+0x3c/0x90) [] (handle_IRQ+0x3c/0x90) from [] (gic_handle_irq+0x28/0x5c) [] (gic_handle_irq+0x28/0x5c) from [] (__irq_svc+0x40/0x50) Maybe that was the reason why the offending commit was introduced(?). I think with the current code "atomic allocations" should be used when IO page tables are created. With below patch I've not triggered above errors. diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 429c95e..0418d69 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1398,7 +1398,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, if (pmd_none(*pmd)) { /* Allocate a new set of tables */ - pgtable_t table = alloc_page(PGALLOC_GFP); + pgtable_t table = alloc_page(GFP_ATOMIC); if (!table) return -ENOMEM; @@ -1503,7 +1503,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, #ifndef __PAGETABLE_PMD_FOLDED if (pud_none(*pud)) { - pmd = pmd_alloc_one(NULL, addr); + pmd = (pmd_t *) get_zeroed_page(GFP_ATOMIC); if (!pmd) return -ENOMEM; } else @@ -1532,7 +1532,7 @@ static int arm_smmu_alloc_init_pud(struct arm_smmu_device *smmu, pgd_t *pgd, #ifndef __PAGETABLE_PUD_FOLDED if (pgd_none(*pgd)) { - pud = pud_alloc_one(NULL, addr); + pud = (pud_t *) get_zeroed_page(GFP_ATOMIC); if (!pud) return -ENOMEM; } else