diff options
author | James Smart <james.smart@avagotech.com> | 2015-05-21 13:55:28 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-06-06 01:40:19 -0400 |
commit | 466e840b7809e00ab3a1af9b4a5b5751e681730d (patch) | |
tree | 149a3be013344fda727df0f00086b77d5b0bc07b | |
parent | e5abba4c6aa7f094d32c0115193516697da60df8 (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>
-rw-r--r-- | drivers/scsi/lpfc/lpfc_disc.h | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 145 |
3 files changed, 79 insertions, 82 deletions
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h index 6977027979be..361f5b3d9d93 100644 --- a/drivers/scsi/lpfc/lpfc_disc.h +++ b/drivers/scsi/lpfc/lpfc_disc.h | |||
@@ -79,7 +79,6 @@ struct lpfc_nodelist { | |||
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 */ | ||
83 | uint32_t nlp_DID; /* FC D_ID of entry */ | 82 | uint32_t nlp_DID; /* FC D_ID of entry */ |
84 | uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ | 83 | uint32_t nlp_last_elscmd; /* Last ELS cmd sent */ |
85 | uint16_t nlp_type; | 84 | uint16_t nlp_type; |
@@ -147,6 +146,7 @@ struct lpfc_node_rrq { | |||
147 | #define NLP_LOGO_ACC 0x00100000 /* Process LOGO after ACC completes */ | 146 | #define NLP_LOGO_ACC 0x00100000 /* Process LOGO after ACC completes */ |
148 | #define NLP_TGT_NO_SCSIID 0x00200000 /* good PRLI but no binding for scsid */ | 147 | #define NLP_TGT_NO_SCSIID 0x00200000 /* good PRLI but no binding for scsid */ |
149 | #define NLP_ISSUE_LOGO 0x00400000 /* waiting to issue a LOGO */ | 148 | #define NLP_ISSUE_LOGO 0x00400000 /* waiting to issue a LOGO */ |
149 | #define NLP_IN_DEV_LOSS 0x00800000 /* devloss in progress */ | ||
150 | #define NLP_ACC_REGLOGIN 0x01000000 /* Issue Reg Login after successful | 150 | #define NLP_ACC_REGLOGIN 0x01000000 /* Issue Reg Login after successful |
151 | ACC */ | 151 | ACC */ |
152 | #define NLP_NPR_ADISC 0x02000000 /* Issue ADISC when dq'ed from | 152 | #define NLP_NPR_ADISC 0x02000000 /* Issue ADISC when dq'ed from |
@@ -158,8 +158,6 @@ struct lpfc_node_rrq { | |||
158 | #define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ | 158 | #define NLP_FIRSTBURST 0x40000000 /* Target supports FirstBurst */ |
159 | #define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ | 159 | #define NLP_RPI_REGISTERED 0x80000000 /* nlp_rpi is valid */ |
160 | 160 | ||
161 | /* Defines for nlp_add_flag (uint32) */ | ||
162 | #define NLP_IN_DEV_LOSS 0x00000001 /* Dev Loss processing in progress */ | ||
163 | 161 | ||
164 | /* ndlp usage management macros */ | 162 | /* ndlp usage management macros */ |
165 | #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ | 163 | #define NLP_CHK_NODE_ACT(ndlp) (((ndlp)->nlp_usg_map \ |
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, | |||
1624 | if (rport) { | 1624 | if (rport) { |
1625 | rdata = rport->dd_data; | 1625 | rdata = rport->dd_data; |
1626 | if (rdata->pnode == ndlp) { | 1626 | if (rdata->pnode == ndlp) { |
1627 | lpfc_nlp_put(ndlp); | 1627 | /* break the link before dropping the ref */ |
1628 | ndlp->rport = NULL; | 1628 | ndlp->rport = NULL; |
1629 | lpfc_nlp_put(ndlp); | ||
1629 | rdata->pnode = lpfc_nlp_get(new_ndlp); | 1630 | rdata->pnode = lpfc_nlp_get(new_ndlp); |
1630 | new_ndlp->rport = rport; | 1631 | new_ndlp->rport = rport; |
1631 | } | 1632 | } |
@@ -3674,6 +3675,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3674 | * Remove the ndlp reference if it's a fabric node that has | 3675 | * Remove the ndlp reference if it's a fabric node that has |
3675 | * sent us an unsolicted LOGO. | 3676 | * sent us an unsolicted LOGO. |
3676 | */ | 3677 | */ |
3678 | /* FIXME: this one frees ndlp before breaking rport link */ | ||
3677 | if (ndlp->nlp_type & NLP_FABRIC) | 3679 | if (ndlp->nlp_type & NLP_FABRIC) |
3678 | lpfc_nlp_put(ndlp); | 3680 | lpfc_nlp_put(ndlp); |
3679 | 3681 | ||
@@ -7351,8 +7353,13 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7351 | * Do not process any unsolicited ELS commands | 7353 | * Do not process any unsolicited ELS commands |
7352 | * if the ndlp is in DEV_LOSS | 7354 | * if the ndlp is in DEV_LOSS |
7353 | */ | 7355 | */ |
7354 | if (ndlp->nlp_add_flag & NLP_IN_DEV_LOSS) | 7356 | shost = lpfc_shost_from_vport(vport); |
7357 | spin_lock_irq(shost->host_lock); | ||
7358 | if (ndlp->nlp_flag & NLP_IN_DEV_LOSS) { | ||
7359 | spin_unlock_irq(shost->host_lock); | ||
7355 | goto dropit; | 7360 | goto dropit; |
7361 | } | ||
7362 | spin_unlock_irq(shost->host_lock); | ||
7356 | 7363 | ||
7357 | elsiocb->context1 = lpfc_nlp_get(ndlp); | 7364 | elsiocb->context1 = lpfc_nlp_get(ndlp); |
7358 | elsiocb->vport = vport; | 7365 | elsiocb->vport = vport; |
@@ -7396,7 +7403,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
7396 | rjt_exp = LSEXP_NOTHING_MORE; | 7403 | rjt_exp = LSEXP_NOTHING_MORE; |
7397 | break; | 7404 | break; |
7398 | } | 7405 | } |
7399 | shost = lpfc_shost_from_vport(vport); | ||
7400 | if (vport->port_state < LPFC_DISC_AUTH) { | 7406 | if (vport->port_state < LPFC_DISC_AUTH) { |
7401 | if (!(phba->pport->fc_flag & FC_PT2PT) || | 7407 | if (!(phba->pport->fc_flag & FC_PT2PT) || |
7402 | (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { | 7408 | (phba->pport->fc_flag & FC_PT2PT_PLOGI)) { |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0dfa56604c91..88af258147d0 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -106,6 +106,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
106 | struct lpfc_rport_data *rdata; | 106 | struct lpfc_rport_data *rdata; |
107 | struct lpfc_nodelist * ndlp; | 107 | struct lpfc_nodelist * ndlp; |
108 | struct lpfc_vport *vport; | 108 | struct lpfc_vport *vport; |
109 | struct Scsi_Host *shost; | ||
109 | struct lpfc_hba *phba; | 110 | struct lpfc_hba *phba; |
110 | struct lpfc_work_evt *evtp; | 111 | struct lpfc_work_evt *evtp; |
111 | int put_node; | 112 | int put_node; |
@@ -146,49 +147,32 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport) | |||
146 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) | 147 | if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) |
147 | return; | 148 | return; |
148 | 149 | ||
149 | if (ndlp->nlp_type & NLP_FABRIC) { | 150 | if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn)) |
150 | 151 | lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, | |
151 | /* If the WWPN of the rport and ndlp don't match, ignore it */ | 152 | "6789 rport name %llx != node port name %llx", |
152 | if (rport->port_name != wwn_to_u64(ndlp->nlp_portname.u.wwn)) { | 153 | rport->port_name, |
153 | lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, | 154 | wwn_to_u64(ndlp->nlp_portname.u.wwn)); |
154 | "6789 rport name %lx != node port name %lx", | ||
155 | (unsigned long)rport->port_name, | ||
156 | (unsigned long)wwn_to_u64( | ||
157 | ndlp->nlp_portname.u.wwn)); | ||
158 | put_node = rdata->pnode != NULL; | ||
159 | put_rport = ndlp->rport != NULL; | ||
160 | rdata->pnode = NULL; | ||
161 | ndlp->rport = NULL; | ||
162 | if (put_node) | ||
163 | lpfc_nlp_put(ndlp); | ||
164 | if (put_rport) | ||
165 | put_device(&rport->dev); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | put_node = rdata->pnode != NULL; | ||
170 | put_rport = ndlp->rport != NULL; | ||
171 | rdata->pnode = NULL; | ||
172 | ndlp->rport = NULL; | ||
173 | if (put_node) | ||
174 | lpfc_nlp_put(ndlp); | ||
175 | if (put_rport) | ||
176 | put_device(&rport->dev); | ||
177 | return; | ||
178 | } | ||
179 | 155 | ||
180 | evtp = &ndlp->dev_loss_evt; | 156 | evtp = &ndlp->dev_loss_evt; |
181 | 157 | ||
182 | if (!list_empty(&evtp->evt_listp)) | 158 | if (!list_empty(&evtp->evt_listp)) { |
159 | lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE, | ||
160 | "6790 rport name %llx dev_loss_evt pending", | ||
161 | rport->port_name); | ||
183 | return; | 162 | return; |
163 | } | ||
184 | 164 | ||
185 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | 165 | shost = lpfc_shost_from_vport(vport); |
186 | ndlp->nlp_add_flag |= NLP_IN_DEV_LOSS; | 166 | spin_lock_irq(shost->host_lock); |
167 | ndlp->nlp_flag |= NLP_IN_DEV_LOSS; | ||
168 | spin_unlock_irq(shost->host_lock); | ||
187 | 169 | ||
188 | spin_lock_irq(&phba->hbalock); | ||
189 | /* We need to hold the node by incrementing the reference | 170 | /* We need to hold the node by incrementing the reference |
190 | * count until this queued work is done | 171 | * count until this queued work is done |
191 | */ | 172 | */ |
173 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | ||
174 | |||
175 | spin_lock_irq(&phba->hbalock); | ||
192 | if (evtp->evt_arg1) { | 176 | if (evtp->evt_arg1) { |
193 | evtp->evt = LPFC_EVT_DEV_LOSS; | 177 | evtp->evt = LPFC_EVT_DEV_LOSS; |
194 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 178 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
@@ -216,22 +200,24 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
216 | struct fc_rport *rport; | 200 | struct fc_rport *rport; |
217 | struct lpfc_vport *vport; | 201 | struct lpfc_vport *vport; |
218 | struct lpfc_hba *phba; | 202 | struct lpfc_hba *phba; |
203 | struct Scsi_Host *shost; | ||
219 | uint8_t *name; | 204 | uint8_t *name; |
220 | int put_node; | 205 | int put_node; |
221 | int put_rport; | ||
222 | int warn_on = 0; | 206 | int warn_on = 0; |
223 | int fcf_inuse = 0; | 207 | int fcf_inuse = 0; |
224 | 208 | ||
225 | rport = ndlp->rport; | 209 | rport = ndlp->rport; |
210 | vport = ndlp->vport; | ||
211 | shost = lpfc_shost_from_vport(vport); | ||
226 | 212 | ||
227 | if (!rport) { | 213 | spin_lock_irq(shost->host_lock); |
228 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | 214 | ndlp->nlp_flag &= ~NLP_IN_DEV_LOSS; |
215 | spin_unlock_irq(shost->host_lock); | ||
216 | |||
217 | if (!rport) | ||
229 | return fcf_inuse; | 218 | return fcf_inuse; |
230 | } | ||
231 | 219 | ||
232 | rdata = rport->dd_data; | ||
233 | name = (uint8_t *) &ndlp->nlp_portname; | 220 | name = (uint8_t *) &ndlp->nlp_portname; |
234 | vport = ndlp->vport; | ||
235 | phba = vport->phba; | 221 | phba = vport->phba; |
236 | 222 | ||
237 | if (phba->sli_rev == LPFC_SLI_REV4) | 223 | if (phba->sli_rev == LPFC_SLI_REV4) |
@@ -245,6 +231,13 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
245 | "3182 dev_loss_tmo_handler x%06x, rport %p flg x%x\n", | 231 | "3182 dev_loss_tmo_handler x%06x, rport %p flg x%x\n", |
246 | ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag); | 232 | ndlp->nlp_DID, ndlp->rport, ndlp->nlp_flag); |
247 | 233 | ||
234 | /* | ||
235 | * lpfc_nlp_remove if reached with dangling rport drops the | ||
236 | * reference. To make sure that does not happen clear rport | ||
237 | * pointer in ndlp before lpfc_nlp_put. | ||
238 | */ | ||
239 | rdata = rport->dd_data; | ||
240 | |||
248 | /* Don't defer this if we are in the process of deleting the vport | 241 | /* Don't defer this if we are in the process of deleting the vport |
249 | * or unloading the driver. The unload will cleanup the node | 242 | * or unloading the driver. The unload will cleanup the node |
250 | * appropriately we just need to cleanup the ndlp rport info here. | 243 | * appropriately we just need to cleanup the ndlp rport info here. |
@@ -257,14 +250,12 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
257 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); | 250 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); |
258 | } | 251 | } |
259 | put_node = rdata->pnode != NULL; | 252 | put_node = rdata->pnode != NULL; |
260 | put_rport = ndlp->rport != NULL; | ||
261 | rdata->pnode = NULL; | 253 | rdata->pnode = NULL; |
262 | ndlp->rport = NULL; | 254 | ndlp->rport = NULL; |
263 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
264 | if (put_node) | 255 | if (put_node) |
265 | lpfc_nlp_put(ndlp); | 256 | lpfc_nlp_put(ndlp); |
266 | if (put_rport) | 257 | put_device(&rport->dev); |
267 | put_device(&rport->dev); | 258 | |
268 | return fcf_inuse; | 259 | return fcf_inuse; |
269 | } | 260 | } |
270 | 261 | ||
@@ -276,28 +267,21 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
276 | *name, *(name+1), *(name+2), *(name+3), | 267 | *name, *(name+1), *(name+2), *(name+3), |
277 | *(name+4), *(name+5), *(name+6), *(name+7), | 268 | *(name+4), *(name+5), *(name+6), *(name+7), |
278 | ndlp->nlp_DID); | 269 | ndlp->nlp_DID); |
279 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
280 | return fcf_inuse; | 270 | return fcf_inuse; |
281 | } | 271 | } |
282 | 272 | ||
283 | if (ndlp->nlp_type & NLP_FABRIC) { | 273 | put_node = rdata->pnode != NULL; |
284 | /* We will clean up these Nodes in linkup */ | 274 | rdata->pnode = NULL; |
285 | put_node = rdata->pnode != NULL; | 275 | ndlp->rport = NULL; |
286 | put_rport = ndlp->rport != NULL; | 276 | if (put_node) |
287 | rdata->pnode = NULL; | 277 | lpfc_nlp_put(ndlp); |
288 | ndlp->rport = NULL; | 278 | put_device(&rport->dev); |
289 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | 279 | |
290 | if (put_node) | 280 | if (ndlp->nlp_type & NLP_FABRIC) |
291 | lpfc_nlp_put(ndlp); | ||
292 | if (put_rport) | ||
293 | put_device(&rport->dev); | ||
294 | return fcf_inuse; | 281 | return fcf_inuse; |
295 | } | ||
296 | 282 | ||
297 | if (ndlp->nlp_sid != NLP_NO_SID) { | 283 | if (ndlp->nlp_sid != NLP_NO_SID) { |
298 | warn_on = 1; | 284 | warn_on = 1; |
299 | /* flush the target */ | ||
300 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
301 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], | 285 | lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring], |
302 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); | 286 | ndlp->nlp_sid, 0, LPFC_CTX_TGT); |
303 | } | 287 | } |
@@ -322,16 +306,6 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp) | |||
322 | ndlp->nlp_state, ndlp->nlp_rpi); | 306 | ndlp->nlp_state, ndlp->nlp_rpi); |
323 | } | 307 | } |
324 | 308 | ||
325 | put_node = rdata->pnode != NULL; | ||
326 | put_rport = ndlp->rport != NULL; | ||
327 | rdata->pnode = NULL; | ||
328 | ndlp->rport = NULL; | ||
329 | ndlp->nlp_add_flag &= ~NLP_IN_DEV_LOSS; | ||
330 | if (put_node) | ||
331 | lpfc_nlp_put(ndlp); | ||
332 | if (put_rport) | ||
333 | put_device(&rport->dev); | ||
334 | |||
335 | if (!(vport->load_flag & FC_UNLOADING) && | 309 | if (!(vport->load_flag & FC_UNLOADING) && |
336 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && | 310 | !(ndlp->nlp_flag & NLP_DELAY_TMO) && |
337 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && | 311 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC) && |
@@ -3919,9 +3893,17 @@ lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
3919 | * registered port, drop the reference that we took the last time we | 3893 | * registered port, drop the reference that we took the last time we |
3920 | * registered the port. | 3894 | * registered the port. |
3921 | */ | 3895 | */ |
3922 | if (ndlp->rport && ndlp->rport->dd_data && | 3896 | rport = ndlp->rport; |
3923 | ((struct lpfc_rport_data *) ndlp->rport->dd_data)->pnode == ndlp) | 3897 | if (rport) { |
3924 | lpfc_nlp_put(ndlp); | 3898 | rdata = rport->dd_data; |
3899 | /* break the link before dropping the ref */ | ||
3900 | ndlp->rport = NULL; | ||
3901 | if (rdata && rdata->pnode == ndlp) | ||
3902 | lpfc_nlp_put(ndlp); | ||
3903 | rdata->pnode = NULL; | ||
3904 | /* drop reference for earlier registeration */ | ||
3905 | put_device(&rport->dev); | ||
3906 | } | ||
3925 | 3907 | ||
3926 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, | 3908 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT, |
3927 | "rport add: did:x%x flg:x%x type x%x", | 3909 | "rport add: did:x%x flg:x%x type x%x", |
@@ -4762,6 +4744,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4762 | { | 4744 | { |
4763 | struct lpfc_hba *phba = vport->phba; | 4745 | struct lpfc_hba *phba = vport->phba; |
4764 | struct lpfc_rport_data *rdata; | 4746 | struct lpfc_rport_data *rdata; |
4747 | struct fc_rport *rport; | ||
4765 | LPFC_MBOXQ_t *mbox; | 4748 | LPFC_MBOXQ_t *mbox; |
4766 | int rc; | 4749 | int rc; |
4767 | 4750 | ||
@@ -4799,14 +4782,24 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4799 | lpfc_cleanup_node(vport, ndlp); | 4782 | lpfc_cleanup_node(vport, ndlp); |
4800 | 4783 | ||
4801 | /* | 4784 | /* |
4802 | * We can get here with a non-NULL ndlp->rport because when we | 4785 | * ndlp->rport must be set to NULL before it reaches here |
4803 | * unregister a rport we don't break the rport/node linkage. So if we | 4786 | * i.e. break rport/node link before doing lpfc_nlp_put for |
4804 | * do, make sure we don't leaving any dangling pointers behind. | 4787 | * registered rport and then drop the reference of rport. |
4805 | */ | 4788 | */ |
4806 | if (ndlp->rport) { | 4789 | if (ndlp->rport) { |
4807 | rdata = ndlp->rport->dd_data; | 4790 | /* |
4791 | * extra lpfc_nlp_put dropped the reference of ndlp | ||
4792 | * for registered rport so need to cleanup rport | ||
4793 | */ | ||
4794 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, | ||
4795 | "0940 removed node x%p DID x%x " | ||
4796 | " rport not null %p\n", | ||
4797 | ndlp, ndlp->nlp_DID, ndlp->rport); | ||
4798 | rport = ndlp->rport; | ||
4799 | rdata = rport->dd_data; | ||
4808 | rdata->pnode = NULL; | 4800 | rdata->pnode = NULL; |
4809 | ndlp->rport = NULL; | 4801 | ndlp->rport = NULL; |
4802 | put_device(&rport->dev); | ||
4810 | } | 4803 | } |
4811 | } | 4804 | } |
4812 | 4805 | ||