scsi: lpfc: Introduce rrq_list_lock to protect active_rrq_list
authorJustin Tee <justin.tee@broadcom.com>
Mon, 29 Apr 2024 22:15:43 +0000 (15:15 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 7 May 2024 01:53:58 +0000 (21:53 -0400)
Instead of using the generic object wide phba->hbalock, an explicit lock
should be used to synchronize mutations to the phba->active_rrq_list.

Update all accesses to the phba->active_rrq_list with a new
phba->rrq_list_lock.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240429221547.6842-5-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nvmet.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c

index 98ca7df003efb377427ceed6ac431b0c1e6a97d5..44a7155daf61f206c6b1a89872ab0f3211ed4ffb 100644 (file)
@@ -1284,6 +1284,7 @@ struct lpfc_hba {
        uint32_t total_scsi_bufs;
        struct list_head lpfc_iocb_list;
        uint32_t total_iocbq_bufs;
+       spinlock_t rrq_list_lock;       /* lock for active_rrq_list */
        struct list_head active_rrq_list;
        spinlock_t hbalock;
        struct work_struct  unblock_request_work; /* SCSI layer unblock IOs */
index f7a0aa3625f4e1b63d0254a925b0cc00f7bf40ad..bd8f97cab2c6b328976868f68153e773b5a3106e 100644 (file)
@@ -14812,6 +14812,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_unset_pci_mem_s4;
        }
 
+       spin_lock_init(&phba->rrq_list_lock);
        INIT_LIST_HEAD(&phba->active_rrq_list);
        INIT_LIST_HEAD(&phba->fcf.fcf_pri_list);
 
index 8258b771bd009e2fe4dbc610db2b56971e3a6f4e..f612a4bfe9fb4fd9e1c05a13a2516546765c64dd 100644 (file)
@@ -1811,7 +1811,9 @@ lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
                ctxp->flag &= ~LPFC_NVME_XBUSY;
                spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
 
+               spin_lock_irqsave(&phba->rrq_list_lock, iflag);
                rrq_empty = list_empty(&phba->active_rrq_list);
+               spin_unlock_irqrestore(&phba->rrq_list_lock, iflag);
                ndlp = lpfc_findnode_did(phba->pport, ctxp->sid);
                if (ndlp &&
                    (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE ||
index 89a622e3053e01528a7011f8dc08fbbf583446f6..8ff39cd9c7e27e0cc9621708f091dbe2d0f2ab21 100644 (file)
@@ -474,9 +474,11 @@ lpfc_sli4_io_xri_aborted(struct lpfc_hba *phba,
                                ndlp = psb->rdata->pnode;
                        else
                                ndlp = NULL;
+                       spin_unlock_irqrestore(&phba->hbalock, iflag);
 
+                       spin_lock_irqsave(&phba->rrq_list_lock, iflag);
                        rrq_empty = list_empty(&phba->active_rrq_list);
-                       spin_unlock_irqrestore(&phba->hbalock, iflag);
+                       spin_unlock_irqrestore(&phba->rrq_list_lock, iflag);
                        if (ndlp && !offline) {
                                lpfc_set_rrq_active(phba, ndlp,
                                        psb->cur_iocbq.sli4_lxritag, rxid, 1);
index fa3d458af1931e77a5fac53c3e5824ae221c731c..c64151cd205edbb6b6c0adfccd803af0fdcd33bd 100644 (file)
@@ -1026,7 +1026,10 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba)
 
        spin_lock_irqsave(&phba->hbalock, iflags);
        phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+       spin_unlock_irqrestore(&phba->hbalock, iflags);
+
        next_time = jiffies + msecs_to_jiffies(1000 * (phba->fc_ratov + 1));
+       spin_lock_irqsave(&phba->rrq_list_lock, iflags);
        list_for_each_entry_safe(rrq, nextrrq,
                                 &phba->active_rrq_list, list) {
                if (time_after(jiffies, rrq->rrq_stop_time))
@@ -1034,7 +1037,7 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba)
                else if (time_before(rrq->rrq_stop_time, next_time))
                        next_time = rrq->rrq_stop_time;
        }
-       spin_unlock_irqrestore(&phba->hbalock, iflags);
+       spin_unlock_irqrestore(&phba->rrq_list_lock, iflags);
        if ((!list_empty(&phba->active_rrq_list)) &&
            (!test_bit(FC_UNLOADING, &phba->pport->load_flag)))
                mod_timer(&phba->rrq_tmr, next_time);
@@ -1072,16 +1075,16 @@ lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did)
 
        if (phba->sli_rev != LPFC_SLI_REV4)
                return NULL;
-       spin_lock_irqsave(&phba->hbalock, iflags);
+       spin_lock_irqsave(&phba->rrq_list_lock, iflags);
        list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
                if (rrq->vport == vport && rrq->xritag == xri &&
                                rrq->nlp_DID == did){
                        list_del(&rrq->list);
-                       spin_unlock_irqrestore(&phba->hbalock, iflags);
+                       spin_unlock_irqrestore(&phba->rrq_list_lock, iflags);
                        return rrq;
                }
        }
-       spin_unlock_irqrestore(&phba->hbalock, iflags);
+       spin_unlock_irqrestore(&phba->rrq_list_lock, iflags);
        return NULL;
 }
 
@@ -1109,7 +1112,7 @@ lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                lpfc_sli4_vport_delete_els_xri_aborted(vport);
                lpfc_sli4_vport_delete_fcp_xri_aborted(vport);
        }
-       spin_lock_irqsave(&phba->hbalock, iflags);
+       spin_lock_irqsave(&phba->rrq_list_lock, iflags);
        list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
                if (rrq->vport != vport)
                        continue;
@@ -1118,7 +1121,7 @@ lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
                        list_move(&rrq->list, &rrq_list);
 
        }
-       spin_unlock_irqrestore(&phba->hbalock, iflags);
+       spin_unlock_irqrestore(&phba->rrq_list_lock, iflags);
 
        list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
                list_del(&rrq->list);
@@ -1213,11 +1216,16 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
        rrq->nlp_DID = ndlp->nlp_DID;
        rrq->vport = ndlp->vport;
        rrq->rxid = rxid;
-       spin_lock_irqsave(&phba->hbalock, iflags);
+
+       spin_lock_irqsave(&phba->rrq_list_lock, iflags);
        empty = list_empty(&phba->active_rrq_list);
        list_add_tail(&rrq->list, &phba->active_rrq_list);
+       spin_unlock_irqrestore(&phba->rrq_list_lock, iflags);
+
+       spin_lock_irqsave(&phba->hbalock, iflags);
        phba->hba_flag |= HBA_RRQ_ACTIVE;
        spin_unlock_irqrestore(&phba->hbalock, iflags);
+
        if (empty)
                lpfc_worker_wake_up(phba);
        return 0;