aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2012-01-18 16:24:06 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 09:08:52 -0500
commit6b5151fd7baec6812fece993ddd7a2cf9fd0125f (patch)
treefeef3e1904163b444f90d834e16931cdb74f0088 /drivers/scsi/lpfc/lpfc_nportdisc.c
parent3ef6d24cd9f473518dd7941e86cc2a5f8992eed0 (diff)
[SCSI] lpfc 8.3.29: SLI related fixes
SLI related fixes: - Fix REG_RPI fails on SLI4 HBA putting NPort into NPR state (126230) - Fix ELS FDISC failing with local reject / invalid RPI. (126350) - Fix reset port when reset is needed during fw_dump (125807) - Fix unbounded firmware revision string from port cause panic (126560) - Fix driver behavior when receiving an ADISC (126654) - Fix driver not returning when bad ndlp found in abts error event handling (126209) - Add more driver logs in area of SLI4 port error attention and reset recovery (126813, 124466) - Fix failure in handling large CQ/EQ identifiers in an IOV environment (126856) - Fix for driver using duplicate RPIs after lancer port reset (126723) - Clear vport->fc_myDID in lpfc_els_issue_fdisc to guarentee a zero SID (126779, 126897) - Fix for SLI4 Port delivery for BLS ABORT ACC (126289) Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com> Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c76
1 files changed, 73 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index e8bb00559943..32b6d72cd98d 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -48,6 +48,10 @@ static int
48lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 48lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
49 struct lpfc_name *nn, struct lpfc_name *pn) 49 struct lpfc_name *nn, struct lpfc_name *pn)
50{ 50{
51 /* First, we MUST have a RPI registered */
52 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
53 return 0;
54
51 /* Compare the ADISC rsp WWNN / WWPN matches our internal node 55 /* Compare the ADISC rsp WWNN / WWPN matches our internal node
52 * table entry for that node. 56 * table entry for that node.
53 */ 57 */
@@ -385,6 +389,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
385 if (!mbox) 389 if (!mbox)
386 goto out; 390 goto out;
387 391
392 /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
393 if (phba->sli_rev == LPFC_SLI_REV4)
394 lpfc_unreg_rpi(vport, ndlp);
395
388 rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID, 396 rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
389 (uint8_t *) sp, mbox, ndlp->nlp_rpi); 397 (uint8_t *) sp, mbox, ndlp->nlp_rpi);
390 if (rc) { 398 if (rc) {
@@ -445,11 +453,42 @@ out:
445 return 0; 453 return 0;
446} 454}
447 455
456/**
457 * lpfc_mbx_cmpl_resume_rpi - Resume RPI completion routine
458 * @phba: pointer to lpfc hba data structure.
459 * @mboxq: pointer to mailbox object
460 *
461 * This routine is invoked to issue a completion to a rcv'ed
462 * ADISC or PDISC after the paused RPI has been resumed.
463 **/
464static void
465lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
466{
467 struct lpfc_vport *vport;
468 struct lpfc_iocbq *elsiocb;
469 struct lpfc_nodelist *ndlp;
470 uint32_t cmd;
471
472 elsiocb = (struct lpfc_iocbq *)mboxq->context1;
473 ndlp = (struct lpfc_nodelist *) mboxq->context2;
474 vport = mboxq->vport;
475 cmd = elsiocb->drvrTimeout;
476
477 if (cmd == ELS_CMD_ADISC) {
478 lpfc_els_rsp_adisc_acc(vport, elsiocb, ndlp);
479 } else {
480 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb,
481 ndlp, NULL);
482 }
483 kfree(elsiocb);
484}
485
448static int 486static int
449lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, 487lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
450 struct lpfc_iocbq *cmdiocb) 488 struct lpfc_iocbq *cmdiocb)
451{ 489{
452 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 490 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
491 struct lpfc_iocbq *elsiocb;
453 struct lpfc_dmabuf *pcmd; 492 struct lpfc_dmabuf *pcmd;
454 struct serv_parm *sp; 493 struct serv_parm *sp;
455 struct lpfc_name *pnn, *ppn; 494 struct lpfc_name *pnn, *ppn;
@@ -475,12 +514,43 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
475 514
476 icmd = &cmdiocb->iocb; 515 icmd = &cmdiocb->iocb;
477 if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) { 516 if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
517
518 /*
519 * As soon as we send ACC, the remote NPort can
520 * start sending us data. Thus, for SLI4 we must
521 * resume the RPI before the ACC goes out.
522 */
523 if (vport->phba->sli_rev == LPFC_SLI_REV4) {
524 elsiocb = kmalloc(sizeof(struct lpfc_iocbq),
525 GFP_KERNEL);
526 if (elsiocb) {
527
528 /* Save info from cmd IOCB used in rsp */
529 memcpy((uint8_t *)elsiocb, (uint8_t *)cmdiocb,
530 sizeof(struct lpfc_iocbq));
531
532 /* Save the ELS cmd */
533 elsiocb->drvrTimeout = cmd;
534
535 lpfc_sli4_resume_rpi(ndlp,
536 lpfc_mbx_cmpl_resume_rpi, elsiocb);
537 goto out;
538 }
539 }
540
478 if (cmd == ELS_CMD_ADISC) { 541 if (cmd == ELS_CMD_ADISC) {
479 lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp); 542 lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
480 } else { 543 } else {
481 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, 544 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
482 NULL); 545 ndlp, NULL);
483 } 546 }
547out:
548 /* If we are authenticated, move to the proper state */
549 if (ndlp->nlp_type & NLP_FCP_TARGET)
550 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
551 else
552 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
553
484 return 1; 554 return 1;
485 } 555 }
486 /* Reject this request because invalid parameters */ 556 /* Reject this request because invalid parameters */
@@ -1229,7 +1299,7 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
1229 } 1299 }
1230 1300
1231 if (phba->sli_rev == LPFC_SLI_REV4) { 1301 if (phba->sli_rev == LPFC_SLI_REV4) {
1232 rc = lpfc_sli4_resume_rpi(ndlp); 1302 rc = lpfc_sli4_resume_rpi(ndlp, NULL, NULL);
1233 if (rc) { 1303 if (rc) {
1234 /* Stay in state and retry. */ 1304 /* Stay in state and retry. */
1235 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; 1305 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;