[SCSI] lpfc 8.2.2 : Miscellaneous Bug Fixes

- Fix vport ndlp ref counting errors
- Fix use after free of ndlp structure
- Use the correct flag to check for LOADING setting.
- Fix driver unload bugs (related to shost references) after link down or rscn
- Fix up HBQ initialization
- Fix port_list locking around driver unload.
- Fix references to hostdata as a phba
- Fix GFFID type offset to work correctly with big endian structure.
- Only call pci_disable_msi if the pci_enable_msi succeeded
- Fix vport_delete wait/fail if in discovery
- Put a reference on the nameservers ndlp when performing CT traffic.
- Remove unbalanced hba unlock.
- Fix up HBQ processing
- Fix lpfc debugfs discovery trace output for ELS rsp cmpl
- Send ADISC when rpi is 0
- Stop FDISC retrying forever
- Unable to retrieve correct config parameter for vport
- Fix sli_validate_fcp_iocb, sli_sum_iocb, sli_abort_iocb to be vport-aware.
- Fix index-out-of-range error in iocb. Spotted by Coverity.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
James Smart
2007-08-02 11:10:31 -04:00
committed by James Bottomley
parent 78b2d852a8
commit 51ef4c2689
16 changed files with 342 additions and 246 deletions

View File

@@ -196,9 +196,7 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
bpl->tus.w = le32_to_cpu(bpl->tus.w);
}
/* Save for completion so we can release these resources */
if (elscmd != ELS_CMD_LS_RJT)
elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->context2 = pcmd;
elsiocb->context3 = pbuflist;
elsiocb->retry = retry;
@@ -1809,8 +1807,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
"retrying...\n");
lpfc_mbx_unreg_vpi(vport);
retry = 1;
/* Always retry for this case */
cmdiocb->retry = 0;
/* FDISC retry policy */
maxretry = 48;
if (cmdiocb->retry >= 32)
delay = 1000;
}
break;
@@ -1886,8 +1886,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
delay = 1000;
maxretry = 48;
} else if (cmd == ELS_CMD_FDISC) {
/* Always retry for this case */
cmdiocb->retry = 0;
/* FDISC retry policy */
maxretry = 48;
if (cmdiocb->retry >= 32)
delay = 1000;
}
retry = 1;
break;
@@ -2121,9 +2123,9 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"ACC cmpl: status:x%x/x%x did:x%x",
"ELS rsp cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->un.rcvels.remoteID);
cmdiocb->iocb.un.elsreq64.remoteID);
/* ELS response tag <ulpIoTag> completes */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0110 ELS response tag x%x completes "
@@ -2184,7 +2186,7 @@ out:
int
lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
LPFC_MBOXQ_t *mbox, uint8_t newnode)
LPFC_MBOXQ_t *mbox)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
@@ -2270,11 +2272,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
default:
return 1;
}
if (newnode) {
lpfc_nlp_put(ndlp);
elsiocb->context1 = NULL;
}
/* Xmit ELS ACC response tag <ulpIoTag> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
@@ -2333,10 +2330,8 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
pcmd += sizeof(uint32_t);
*((uint32_t *) (pcmd)) = rejectError;
if (mbox) {
if (mbox)
elsiocb->context_un.mbox = mbox;
elsiocb->context1 = lpfc_nlp_get(ndlp);
}
/* Xmit ELS RJT <err> response tag <ulpIoTag> */
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
@@ -2353,6 +2348,15 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
phba->fc_stat.elsXmitLSRJT++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
/* If the node is in the UNUSED state, and we are sending
* a reject, we are done with it. Release driver reference
* count here. The outstanding els will release its reference on
* completion and the node can be freed then.
*/
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
lpfc_nlp_put(ndlp);
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
return 1;
@@ -2747,7 +2751,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
static int
lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp, uint8_t newnode)
struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
@@ -2781,8 +2785,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
"RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
newnode);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
return 0;
}
@@ -2814,7 +2817,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
ndlp->nlp_flag);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
ndlp, NULL, newnode);
ndlp, NULL);
return 0;
}
}
@@ -2870,8 +2873,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
vport->port_state);
}
/* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
newnode);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
/* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport);
@@ -2896,7 +2898,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_set_disctmo(vport);
/* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
/* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport);
@@ -2965,7 +2967,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
static int
lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp, uint8_t newnode)
struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
@@ -3048,7 +3050,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
}
/* Send back ACC */
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
return 0;
}
@@ -3409,7 +3411,7 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0600 FARP-RSP received from DID x%x\n", did);
/* ACCEPT the Farp resp request */
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
return 0;
}
@@ -3791,7 +3793,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
did, vport->port_state, ndlp->nlp_flag);
phba->fc_stat.elsRcvFLOGI++;
lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
if (newnode)
lpfc_drop_node(vport, ndlp);
break;
@@ -3821,7 +3823,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
break;
case ELS_CMD_RSCN:
phba->fc_stat.elsRcvRSCN++;
lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode);
lpfc_els_rcv_rscn(vport, elsiocb, ndlp);
if (newnode)
lpfc_drop_node(vport, ndlp);
break;
@@ -3951,8 +3953,6 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
NULL);
if (newnode)
lpfc_drop_node(vport, ndlp);
}
return;