aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2014-09-03 12:57:19 -0400
committerChristoph Hellwig <hch@lst.de>2014-09-16 12:10:10 -0400
commit12838e74f5164054fd7d5f5201a846ebb9755471 (patch)
treebc4a17eba4e0670723735ebf1701ea0bcc97ef58 /drivers/scsi/lpfc
parent2f6fa2c911167e7a3fda130689a36f55b39ed86d (diff)
lpfc: fix race between LOGO/PLOGI handling causing NULL pointer
Fix race between LOGO/PLOGI handling causing NULL pointer Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: Dick Kennedy <dick.kennedy@emulex.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c19
3 files changed, 30 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 1a6fe524940d..6977027979be 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -78,7 +78,8 @@ struct lpfc_nodelist {
78 struct list_head nlp_listp; 78 struct list_head nlp_listp;
79 struct lpfc_name nlp_portname; 79 struct lpfc_name nlp_portname;
80 struct lpfc_name nlp_nodename; 80 struct lpfc_name nlp_nodename;
81 uint32_t nlp_flag; /* entry flags */ 81 uint32_t nlp_flag; /* entry flags */
82 uint32_t nlp_add_flag; /* additional flags */
82 uint32_t nlp_DID; /* FC D_ID of entry */ 83 uint32_t nlp_DID; /* FC D_ID of entry */
83 uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ 84 uint32_t nlp_last_elscmd; /* Last ELS cmd sent */
84 uint16_t nlp_type; 85 uint16_t nlp_type;
@@ -157,6 +158,9 @@ struct lpfc_node_rrq {
157#define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ 158#define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */
158#define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ 159#define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */
159 160
161/* Defines for nlp_add_flag (uint32) */
162#define NLP_IN_DEV_LOSS 0x00000001 /* Dev Loss processing in progress */
163
160/* ndlp usage management macros */ 164/* ndlp usage management macros */
161#define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ 165#define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \
162 & NLP_USG_NODE_ACT_BIT) \ 166 & NLP_USG_NODE_ACT_BIT) \
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 30ec80f32d1a..9d03e7250fb4 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -6693,6 +6693,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
6693 6693
6694 phba->fc_stat.elsRcvFrame++; 6694 phba->fc_stat.elsRcvFrame++;
6695 6695
6696 /*
6697 * Do not process any unsolicited ELS commands
6698 * if the ndlp is in DEV_LOSS
6699 */
6700 if (ndlp->nlp_add_flag & NLP_IN_DEV_LOSS)
6701 goto dropit;
6702
6696 elsiocb->context1 = lpfc_nlp_get(ndlp); 6703 elsiocb->context1 = lpfc_nlp_get(ndlp);
6697 elsiocb->vport = vport; 6704 elsiocb->vport = vport;
6698 6705
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index d178aee02b49..2d929a5e8354 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -153,6 +153,16 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
153 put_device(&rport->dev); 153 put_device(&rport->dev);
154 return; 154 return;
155 } 155 }
156
157 put_node = rdata->pnode != NULL;
158 put_rport = ndlp->rport != NULL;
159 rdata->pnode = NULL;
160 ndlp->rport = NULL;
161 if (put_node)
162 lpfc_nlp_put(ndlp);
163 if (put_rport)
164 put_device(&rport->dev);
165 return;
156 } 166 }
157 167
158 evtp = &ndlp->dev_loss_evt; 168 evtp = &ndlp->dev_loss_evt;
@@ -161,6 +171,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
161 return; 171 return;
162 172
163 evtp->evt_arg1 = lpfc_nlp_get(ndlp); 173 evtp->evt_arg1 = lpfc_nlp_get(ndlp);
174 ndlp->nlp_add_flag |= NLP_IN_DEV_LOSS;
164 175
165 spin_lock_irq(&phba->hbalock); 176 spin_lock_irq(&phba->hbalock);
166 /* We need to hold the node by incrementing the reference 177 /* We need to hold the node by incrementing the reference
@@ -201,8 +212,10 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
201 212
202 rport = ndlp->rport; 213 rport = ndlp->rport;
203 214
204 if (!rport) 215 if (!rport) {
216 ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
205 return fcf_inuse; 217 return fcf_inuse;
218 }
206 219
207 rdata = rport->dd_data; 220 rdata = rport->dd_data;
208 name = (uint8_t *) &ndlp->nlp_portname; 221 name = (uint8_t *) &ndlp->nlp_portname;
@@ -235,6 +248,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
235 put_rport = ndlp->rport != NULL; 248 put_rport = ndlp->rport != NULL;
236 rdata->pnode = NULL; 249 rdata->pnode = NULL;
237 ndlp->rport = NULL; 250 ndlp->rport = NULL;
251 ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
238 if (put_node) 252 if (put_node)
239 lpfc_nlp_put(ndlp); 253 lpfc_nlp_put(ndlp);
240 if (put_rport) 254 if (put_rport)
@@ -250,6 +264,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
250 *name, *(name+1), *(name+2), *(name+3), 264 *name, *(name+1), *(name+2), *(name+3),
251 *(name+4), *(name+5), *(name+6), *(name+7), 265 *(name+4), *(name+5), *(name+6), *(name+7),
252 ndlp->nlp_DID); 266 ndlp->nlp_DID);
267 ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
253 return fcf_inuse; 268 return fcf_inuse;
254 } 269 }
255 270
@@ -259,6 +274,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
259 put_rport = ndlp->rport != NULL; 274 put_rport = ndlp->rport != NULL;
260 rdata->pnode = NULL; 275 rdata->pnode = NULL;
261 ndlp->rport = NULL; 276 ndlp->rport = NULL;
277 ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
262 if (put_node) 278 if (put_node)
263 lpfc_nlp_put(ndlp); 279 lpfc_nlp_put(ndlp);
264 if (put_rport) 280 if (put_rport)
@@ -297,6 +313,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
297 put_rport = ndlp->rport != NULL; 313 put_rport = ndlp->rport != NULL;
298 rdata->pnode = NULL; 314 rdata->pnode = NULL;
299 ndlp->rport = NULL; 315 ndlp->rport = NULL;
316 ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS;
300 if (put_node) 317 if (put_node)
301 lpfc_nlp_put(ndlp); 318 lpfc_nlp_put(ndlp);
302 if (put_rport) 319 if (put_rport)