[SCSI] lpfc 8.1.5 : Fixed FC protocol violation in handling of PRLO.
authorJames Smart <James.Smart@Emulex.Com>
Sat, 15 Apr 2006 15:53:05 +0000 (11:53 -0400)
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>
Thu, 20 Apr 2006 00:48:58 +0000 (20:48 -0400)
Fixed FC protocol violation in handling of PRLO.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_nportdisc.c

index 45abc76..e3d8b7f 100644 (file)
@@ -1913,6 +1913,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
        uint8_t *pcmd;
        uint16_t cmdsize;
        int rc;
+       ELS_PKT *els_pkt_ptr;
 
        psli = &phba->sli;
        pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
@@ -1951,6 +1952,23 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
                pcmd += sizeof (uint32_t);
                memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
                break;
+       case ELS_CMD_PRLO:
+               cmdsize = sizeof (uint32_t) + sizeof (PRLO);
+               elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
+                                            ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
+               if (!elsiocb)
+                       return 1;
+
+               icmd = &elsiocb->iocb;
+               icmd->ulpContext = oldcmd->ulpContext; /* Xri */
+               pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
+
+               memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
+                      sizeof (uint32_t) + sizeof (PRLO));
+               *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
+               els_pkt_ptr = (ELS_PKT *) pcmd;
+               els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+               break;
        default:
                return 1;
        }
index b12569e..eedf988 100644 (file)
@@ -449,6 +449,7 @@ struct serv_parm {  /* Structure is in Big Endian format */
 #define ELS_CMD_RRQ       0x12000000
 #define ELS_CMD_PRLI      0x20100014
 #define ELS_CMD_PRLO      0x21100014
+#define ELS_CMD_PRLO_ACC  0x02100014
 #define ELS_CMD_PDISC     0x50000000
 #define ELS_CMD_FDISC     0x51000000
 #define ELS_CMD_ADISC     0x52000000
@@ -484,6 +485,7 @@ struct serv_parm {  /* Structure is in Big Endian format */
 #define ELS_CMD_RRQ       0x12
 #define ELS_CMD_PRLI      0x14001020
 #define ELS_CMD_PRLO      0x14001021
+#define ELS_CMD_PRLO_ACC  0x14001002
 #define ELS_CMD_PDISC     0x50
 #define ELS_CMD_FDISC     0x51
 #define ELS_CMD_ADISC     0x52
index adebe62..27d60ad 100644 (file)
@@ -465,14 +465,18 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
 static int
 lpfc_rcv_logo(struct lpfc_hba * phba,
                      struct lpfc_nodelist * ndlp,
-                     struct lpfc_iocbq *cmdiocb)
+                     struct lpfc_iocbq *cmdiocb,
+                     uint32_t els_cmd)
 {
        /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
        /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
         * PLOGIs during LOGO storms from a device.
         */
        ndlp->nlp_flag |= NLP_LOGO_ACC;
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       if (els_cmd == ELS_CMD_PRLO)
+               lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
+       else
+               lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
 
        if (!(ndlp->nlp_type & NLP_FABRIC) ||
                (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
@@ -681,7 +685,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
        /* software abort outstanding PLOGI */
        lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -907,7 +911,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
        /* software abort outstanding ADISC */
        lpfc_els_abort(phba, ndlp, 0);
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -934,7 +938,7 @@ lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
        cmdiocb = (struct lpfc_iocbq *) arg;
 
        /* Treat like rcv logo */
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
        return ndlp->nlp_state;
 }
 
@@ -1056,7 +1060,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1081,7 +1085,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
        struct lpfc_iocbq *cmdiocb;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
        return ndlp->nlp_state;
 }
 
@@ -1200,7 +1204,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
        /* Software abort outstanding PRLI before sending acc */
        lpfc_els_abort(phba, ndlp, 1);
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1228,7 +1232,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
        struct lpfc_iocbq *cmdiocb;
 
        cmdiocb = (struct lpfc_iocbq *) arg;
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
        return ndlp->nlp_state;
 }
 
@@ -1371,7 +1375,7 @@ lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1395,7 +1399,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+       lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
        return ndlp->nlp_state;
 }
 
@@ -1444,7 +1448,7 @@ lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }
 
@@ -1476,7 +1480,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
        spin_unlock_irq(phba->host->host_lock);
 
        /* Treat like rcv logo */
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
        return ndlp->nlp_state;
 }
 
@@ -1571,7 +1575,7 @@ lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
 
        cmdiocb = (struct lpfc_iocbq *) arg;
 
-       lpfc_rcv_logo(phba, ndlp, cmdiocb);
+       lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
        return ndlp->nlp_state;
 }