Messages in this thread Patch in this message | | | From | Wen Yang <> | Subject | [PATCH] scsi: wd719x: Fix sleeping under a spinlock | Date | Wed, 5 Dec 2018 12:21:44 +0800 |
| |
Currently, dma_alloc_coherent is being called with a GFP_KERNEL flag which allows it to sleep with a spinlock held. The call tree is: wd719x_host_reset() holds wd->sh->host_lock -> wd719x_chip_init() -> dma_alloc_coherent() uses GFP_KERNEL
This patch introduces a can_sleep parameter into the wd719x_chip_init() function. When we have spinlock and can't sleep, we pass in 0; in other cases, we pass in 1.
Signed-off-by: Wen Yang <wen.yang99@zte.com.cn> CC: "James E.J. Bottomley" <jejb@linux.ibm.com> CC: "Martin K. Petersen" <martin.petersen@oracle.com> CC: linux-scsi@vger.kernel.org CC: linux-kernel@vger.kernel.org --- drivers/scsi/wd719x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c index 808ba8e952db..e1dac0115947 100644 --- a/drivers/scsi/wd719x.c +++ b/drivers/scsi/wd719x.c @@ -289,7 +289,7 @@ static int wd719x_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) return 0; } -static int wd719x_chip_init(struct wd719x *wd) +static int wd719x_chip_init(struct wd719x *wd, int can_sleep) { int i, ret; u32 risc_init[3]; @@ -318,7 +318,8 @@ static int wd719x_chip_init(struct wd719x *wd) if (!wd->fw_virt) wd->fw_virt = dma_alloc_coherent(&wd->pdev->dev, wd->fw_size, - &wd->fw_phys, GFP_KERNEL); + &wd->fw_phys, can_sleep ? + GFP_KERNEL : GFP_ATOMIC); if (!wd->fw_virt) { ret = -ENOMEM; goto wd719x_init_end; @@ -510,7 +511,7 @@ static int wd719x_host_reset(struct scsi_cmnd *cmd) dev_info(&wd->pdev->dev, "host reset requested\n"); spin_lock_irqsave(wd->sh->host_lock, flags); /* Try to reinit the RISC */ - if (wd719x_chip_init(wd) == 0) + if (wd719x_chip_init(wd, 0) == 0) result = SUCCESS; else result = FAILED; @@ -834,7 +835,7 @@ static int wd719x_board_found(struct Scsi_Host *sh) /* read parameters from EEPROM */ wd719x_read_eeprom(wd); - ret = wd719x_chip_init(wd); + ret = wd719x_chip_init(wd, 1); if (ret) goto fail_free_irq; -- 2.19.1
| |