Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc()

The following calltrace was seen:

BUG: sleeping function called from invalid context at mm/slab.h:494
...
Call Trace:
dump_stack+0x9a/0xf0
___might_sleep.cold.63+0x13d/0x178
slab_pre_alloc_hook+0x6a/0x90
kmem_cache_alloc_trace+0x3a/0x2d0
lpfc_sli4_nvmet_alloc+0x4c/0x280 [lpfc]
lpfc_post_rq_buffer+0x2e7/0xa60 [lpfc]
lpfc_sli4_hba_setup+0x6b4c/0xa4b0 [lpfc]
lpfc_pci_probe_one_s4.isra.15+0x14f8/0x2280 [lpfc]
lpfc_pci_probe_one+0x260/0x2880 [lpfc]
local_pci_probe+0xd4/0x180
work_for_cpu_fn+0x51/0xa0
process_one_work+0x8f0/0x17b0
worker_thread+0x536/0xb50
kthread+0x30c/0x3d0
ret_from_fork+0x3a/0x50

A prior patch introduced a spin_lock_irqsave(hbalock) in the
lpfc_post_rq_buffer() routine. Call trace is seen as the hbalock is held
with interrupts disabled during a GFP_KERNEL allocation in
lpfc_sli4_nvmet_alloc().

Fix by reordering locking so that hbalock not held when calling
sli4_nvmet_alloc() (aka rqb_buf_list()).

Link: https://lore.kernel.org/r/20201020202719.54726-2-james.smart@broadcom.com
Fixes: 411de511c694 ("scsi: lpfc: Fix RQ empty firmware trap")
Cc: <stable@vger.kernel.org> # v4.17+
Co-developed-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
62e3a931 c8ed1ff8

+9 -5
+1 -3
drivers/scsi/lpfc/lpfc_mem.c
··· 588 588 * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI 589 589 * pool along a non-DMA-mapped container for it. 590 590 * 591 - * Notes: Not interrupt-safe. Must be called with no locks held. 592 - * 593 591 * Returns: 594 592 * pointer to HBQ on success 595 593 * NULL on failure ··· 597 599 { 598 600 struct rqb_dmabuf *dma_buf; 599 601 600 - dma_buf = kzalloc(sizeof(struct rqb_dmabuf), GFP_KERNEL); 602 + dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); 601 603 if (!dma_buf) 602 604 return NULL; 603 605
+8 -2
drivers/scsi/lpfc/lpfc_sli.c
··· 7248 7248 struct rqb_dmabuf *rqb_buffer; 7249 7249 LIST_HEAD(rqb_buf_list); 7250 7250 7251 - spin_lock_irqsave(&phba->hbalock, flags); 7252 7251 rqbp = hrq->rqbp; 7253 7252 for (i = 0; i < count; i++) { 7253 + spin_lock_irqsave(&phba->hbalock, flags); 7254 7254 /* IF RQ is already full, don't bother */ 7255 - if (rqbp->buffer_count + i >= rqbp->entry_count - 1) 7255 + if (rqbp->buffer_count + i >= rqbp->entry_count - 1) { 7256 + spin_unlock_irqrestore(&phba->hbalock, flags); 7256 7257 break; 7258 + } 7259 + spin_unlock_irqrestore(&phba->hbalock, flags); 7260 + 7257 7261 rqb_buffer = rqbp->rqb_alloc_buffer(phba); 7258 7262 if (!rqb_buffer) 7259 7263 break; ··· 7266 7262 rqb_buffer->idx = idx; 7267 7263 list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list); 7268 7264 } 7265 + 7266 + spin_lock_irqsave(&phba->hbalock, flags); 7269 7267 while (!list_empty(&rqb_buf_list)) { 7270 7268 list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf, 7271 7269 hbuf.list);