summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_els.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@avagotech.com>2015-05-21 13:55:28 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-06-05 22:40:19 -0700
commit466e840b7809e00ab3a1af9b4a5b5751e681730d (patch)
tree149a3be013344fda727df0f00086b77d5b0bc07b /drivers/scsi/lpfc/lpfc_els.c
parente5abba4c6aa7f094d32c0115193516697da60df8 (diff)
lpfc: Fix rport leak.
Correct locking and refcounting in tracking our rports Signed-off-by: Dick Kennedy <dick.kennedy@avagotech.com> Signed-off-by: James Smart <james.smart@avagotech.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 4d3d931b177a..011c8d8dba0b 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1624,8 +1624,9 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
if (rport) {
rdata = rport->dd_data;
if (rdata->pnode == ndlp) {
- lpfc_nlp_put(ndlp);
+ /* break the link before dropping the ref */
ndlp->rport = NULL;
+ lpfc_nlp_put(ndlp);
rdata->pnode = lpfc_nlp_get(new_ndlp);
new_ndlp->rport = rport;
}
@@ -3674,6 +3675,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
* Remove the ndlp reference if it's a fabric node that has
* sent us an unsolicted LOGO.
*/
+ /* FIXME: this one frees ndlp before breaking rport link */
if (ndlp->nlp_type & NLP_FABRIC)
lpfc_nlp_put(ndlp);
@@ -7351,8 +7353,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* Do not process any unsolicited ELS commands
* if the ndlp is in DEV_LOSS
*/
- if (ndlp->nlp_add_flag & NLP_IN_DEV_LOSS)
+ shost = lpfc_shost_from_vport(vport);
+ spin_lock_irq(shost->host_lock);
+ if (ndlp->nlp_flag & NLP_IN_DEV_LOSS) {
+ spin_unlock_irq(shost->host_lock);
goto dropit;
+ }
+ spin_unlock_irq(shost->host_lock);
elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->vport = vport;
@@ -7396,7 +7403,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
rjt_exp = LSEXP_NOTHING_MORE;
break;
}
- shost = lpfc_shost_from_vport(vport);
if (vport->port_state < LPFC_DISC_AUTH) {
if (!(phba->pport->fc_flag & FC_PT2PT) ||
(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {