diff options
author | James Smart <jsmart2021@gmail.com> | 2018-09-10 10:30:46 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-09-11 20:37:33 -0400 |
commit | 523128e53b1e82a7eb422168eddd0c566973520d (patch) | |
tree | 919c6490bfb70ba9f8b91db59827c215a3691249 /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | 0ef01a2d95fd62bb4f536e7ce4d5e8e74b97a244 (diff) | |
download | linux-523128e53b1e82a7eb422168eddd0c566973520d.tar.gz linux-523128e53b1e82a7eb422168eddd0c566973520d.tar.bz2 linux-523128e53b1e82a7eb422168eddd0c566973520d.zip |
scsi: lpfc: Correct irq handling via locks when taking adapter offline
When taking the board offline while performing i/o, unsafe locking errors
occurred and irq level isn't properly managed.
In lpfc_sli_hba_down, spin_lock_irqsave(&phba->hbalock, flags) does not
disable softirqs raised from timer expiry. It is possible that a softirq is
raised from the lpfc_els_retry_delay routine and recursively requests the same
phba->hbalock spinlock causing deadlock.
Address the deadlocks by creating a new port_list lock. The softirq behavior
can then be managed a level deeper into the calling sequences.
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>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 235abd50e530..f9a038ec5256 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -5938,14 +5938,14 @@ lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi) } } - spin_lock_irqsave(&phba->hbalock, flags); + spin_lock_irqsave(&phba->port_list_lock, flags); list_for_each_entry(vport, &phba->port_list, listentry) { if (vport->vpi == i) { - spin_unlock_irqrestore(&phba->hbalock, flags); + spin_unlock_irqrestore(&phba->port_list_lock, flags); return vport; } } - spin_unlock_irqrestore(&phba->hbalock, flags); + spin_unlock_irqrestore(&phba->port_list_lock, flags); return NULL; } |