diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-02-08 18:49:26 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-11 18:52:57 -0500 |
commit | e47c9093531d3406a8ae38acca4ce207ef70cc0e (patch) | |
tree | cb115ec0b7981a100ef39ecfc68a36aa7e3e0f2e /drivers/scsi/lpfc/lpfc_ct.c | |
parent | 4660c8ed5aaed99d82785499f034a8cc9199866d (diff) |
[SCSI] lpfc 8.2.5 : Correct ndlp referencing issues
Correct ndlp referencing issues:
- Fix ndlp kref issues due to race conditions between threads
- Fix cancel els delay retry event which missed an ndlp reference count
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_ct.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 92441ce610ed..aea8d33f6d09 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2007 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2008 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -294,7 +294,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
294 | /* Save for completion so we can release these resources */ | 294 | /* Save for completion so we can release these resources */ |
295 | geniocb->context1 = (uint8_t *) inp; | 295 | geniocb->context1 = (uint8_t *) inp; |
296 | geniocb->context2 = (uint8_t *) outp; | 296 | geniocb->context2 = (uint8_t *) outp; |
297 | geniocb->context_un.ndlp = ndlp; | 297 | geniocb->context_un.ndlp = lpfc_nlp_get(ndlp); |
298 | 298 | ||
299 | /* Fill in payload, bp points to frame payload */ | 299 | /* Fill in payload, bp points to frame payload */ |
300 | icmd->ulpCommand = CMD_GEN_REQUEST64_CR; | 300 | icmd->ulpCommand = CMD_GEN_REQUEST64_CR; |
@@ -489,8 +489,10 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
489 | */ | 489 | */ |
490 | ndlp = lpfc_findnode_did(vport, | 490 | ndlp = lpfc_findnode_did(vport, |
491 | Did); | 491 | Did); |
492 | if (ndlp && (ndlp->nlp_type & | 492 | if (ndlp && |
493 | NLP_FCP_TARGET)) | 493 | NLP_CHK_NODE_ACT(ndlp) |
494 | && (ndlp->nlp_type & | ||
495 | NLP_FCP_TARGET)) | ||
494 | lpfc_setup_disc_node | 496 | lpfc_setup_disc_node |
495 | (vport, Did); | 497 | (vport, Did); |
496 | else if (lpfc_ns_cmd(vport, | 498 | else if (lpfc_ns_cmd(vport, |
@@ -1064,7 +1066,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1064 | int rc = 0; | 1066 | int rc = 0; |
1065 | 1067 | ||
1066 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 1068 | ndlp = lpfc_findnode_did(vport, NameServer_DID); |
1067 | if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { | 1069 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) |
1070 | || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) { | ||
1068 | rc=1; | 1071 | rc=1; |
1069 | goto ns_cmd_exit; | 1072 | goto ns_cmd_exit; |
1070 | } | 1073 | } |
@@ -1213,8 +1216,9 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1213 | cmpl = lpfc_cmpl_ct_cmd_rff_id; | 1216 | cmpl = lpfc_cmpl_ct_cmd_rff_id; |
1214 | break; | 1217 | break; |
1215 | } | 1218 | } |
1216 | lpfc_nlp_get(ndlp); | 1219 | /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count |
1217 | 1220 | * to hold ndlp reference for the corresponding callback function. | |
1221 | */ | ||
1218 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { | 1222 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) { |
1219 | /* On success, The cmpl function will free the buffers */ | 1223 | /* On success, The cmpl function will free the buffers */ |
1220 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | 1224 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, |
@@ -1222,9 +1226,13 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1222 | cmdcode, ndlp->nlp_DID, 0); | 1226 | cmdcode, ndlp->nlp_DID, 0); |
1223 | return 0; | 1227 | return 0; |
1224 | } | 1228 | } |
1225 | |||
1226 | rc=6; | 1229 | rc=6; |
1230 | |||
1231 | /* Decrement ndlp reference count to release ndlp reference held | ||
1232 | * for the failed command's callback function. | ||
1233 | */ | ||
1227 | lpfc_nlp_put(ndlp); | 1234 | lpfc_nlp_put(ndlp); |
1235 | |||
1228 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1236 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
1229 | ns_cmd_free_bmp: | 1237 | ns_cmd_free_bmp: |
1230 | kfree(bmp); | 1238 | kfree(bmp); |
@@ -1271,6 +1279,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1271 | } | 1279 | } |
1272 | 1280 | ||
1273 | ndlp = lpfc_findnode_did(vport, FDMI_DID); | 1281 | ndlp = lpfc_findnode_did(vport, FDMI_DID); |
1282 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) | ||
1283 | goto fail_out; | ||
1284 | |||
1274 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 1285 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { |
1275 | /* FDMI rsp failed */ | 1286 | /* FDMI rsp failed */ |
1276 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 1287 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
@@ -1294,6 +1305,8 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1294 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); | 1305 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); |
1295 | break; | 1306 | break; |
1296 | } | 1307 | } |
1308 | |||
1309 | fail_out: | ||
1297 | lpfc_ct_free_iocb(phba, cmdiocb); | 1310 | lpfc_ct_free_iocb(phba, cmdiocb); |
1298 | return; | 1311 | return; |
1299 | } | 1312 | } |
@@ -1650,12 +1663,18 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1650 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 1663 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
1651 | 1664 | ||
1652 | cmpl = lpfc_cmpl_ct_cmd_fdmi; | 1665 | cmpl = lpfc_cmpl_ct_cmd_fdmi; |
1653 | lpfc_nlp_get(ndlp); | ||
1654 | 1666 | ||
1667 | /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count | ||
1668 | * to hold ndlp reference for the corresponding callback function. | ||
1669 | */ | ||
1655 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) | 1670 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) |
1656 | return 0; | 1671 | return 0; |
1657 | 1672 | ||
1673 | /* Decrement ndlp reference count to release ndlp reference held | ||
1674 | * for the failed command's callback function. | ||
1675 | */ | ||
1658 | lpfc_nlp_put(ndlp); | 1676 | lpfc_nlp_put(ndlp); |
1677 | |||
1659 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1678 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
1660 | fdmi_cmd_free_bmp: | 1679 | fdmi_cmd_free_bmp: |
1661 | kfree(bmp); | 1680 | kfree(bmp); |
@@ -1698,7 +1717,7 @@ lpfc_fdmi_timeout_handler(struct lpfc_vport *vport) | |||
1698 | struct lpfc_nodelist *ndlp; | 1717 | struct lpfc_nodelist *ndlp; |
1699 | 1718 | ||
1700 | ndlp = lpfc_findnode_did(vport, FDMI_DID); | 1719 | ndlp = lpfc_findnode_did(vport, FDMI_DID); |
1701 | if (ndlp) { | 1720 | if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { |
1702 | if (init_utsname()->nodename[0] != '\0') | 1721 | if (init_utsname()->nodename[0] != '\0') |
1703 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); | 1722 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); |
1704 | else | 1723 | else |