diff options
author | James Smart <james.smart@emulex.com> | 2012-01-18 16:24:06 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 09:08:52 -0500 |
commit | 6b5151fd7baec6812fece993ddd7a2cf9fd0125f (patch) | |
tree | feef3e1904163b444f90d834e16931cdb74f0088 /drivers/scsi/lpfc/lpfc_nportdisc.c | |
parent | 3ef6d24cd9f473518dd7941e86cc2a5f8992eed0 (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.c | 76 |
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 | |||
48 | lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 48 | lpfc_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 | **/ | ||
464 | static void | ||
465 | lpfc_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 | |||
448 | static int | 486 | static int |
449 | lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 487 | lpfc_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 | } |
547 | out: | ||
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; |