aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2006-04-15 11:53:05 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-04-19 20:48:58 -0400
commit82d9a2a2900b17223117dc10b56503acc678c337 (patch)
tree757f398e585a6bbe64ebedae98b0957cab770279 /drivers/scsi/lpfc
parent4b0b91d4611aba058c16440f9841906853741330 (diff)
[SCSI] lpfc 8.1.5 : Fixed FC protocol violation in handling of PRLO.
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>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c18
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c32
3 files changed, 38 insertions, 14 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 45abc76ff898..e3d8b7f47f12 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1913,6 +1913,7 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
1913 uint8_t *pcmd; 1913 uint8_t *pcmd;
1914 uint16_t cmdsize; 1914 uint16_t cmdsize;
1915 int rc; 1915 int rc;
1916 ELS_PKT *els_pkt_ptr;
1916 1917
1917 psli = &phba->sli; 1918 psli = &phba->sli;
1918 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */ 1919 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
@@ -1951,6 +1952,23 @@ lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
1951 pcmd += sizeof (uint32_t); 1952 pcmd += sizeof (uint32_t);
1952 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm)); 1953 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
1953 break; 1954 break;
1955 case ELS_CMD_PRLO:
1956 cmdsize = sizeof (uint32_t) + sizeof (PRLO);
1957 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1958 ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
1959 if (!elsiocb)
1960 return 1;
1961
1962 icmd = &elsiocb->iocb;
1963 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1964 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1965
1966 memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
1967 sizeof (uint32_t) + sizeof (PRLO));
1968 *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
1969 els_pkt_ptr = (ELS_PKT *) pcmd;
1970 els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
1971 break;
1954 default: 1972 default:
1955 return 1; 1973 return 1;
1956 } 1974 }
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index b12569eefd1c..eedf98801366 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -449,6 +449,7 @@ struct serv_parm { /* Structure is in Big Endian format */
449#define ELS_CMD_RRQ 0x12000000 449#define ELS_CMD_RRQ 0x12000000
450#define ELS_CMD_PRLI 0x20100014 450#define ELS_CMD_PRLI 0x20100014
451#define ELS_CMD_PRLO 0x21100014 451#define ELS_CMD_PRLO 0x21100014
452#define ELS_CMD_PRLO_ACC 0x02100014
452#define ELS_CMD_PDISC 0x50000000 453#define ELS_CMD_PDISC 0x50000000
453#define ELS_CMD_FDISC 0x51000000 454#define ELS_CMD_FDISC 0x51000000
454#define ELS_CMD_ADISC 0x52000000 455#define ELS_CMD_ADISC 0x52000000
@@ -484,6 +485,7 @@ struct serv_parm { /* Structure is in Big Endian format */
484#define ELS_CMD_RRQ 0x12 485#define ELS_CMD_RRQ 0x12
485#define ELS_CMD_PRLI 0x14001020 486#define ELS_CMD_PRLI 0x14001020
486#define ELS_CMD_PRLO 0x14001021 487#define ELS_CMD_PRLO 0x14001021
488#define ELS_CMD_PRLO_ACC 0x14001002
487#define ELS_CMD_PDISC 0x50 489#define ELS_CMD_PDISC 0x50
488#define ELS_CMD_FDISC 0x51 490#define ELS_CMD_FDISC 0x51
489#define ELS_CMD_ADISC 0x52 491#define ELS_CMD_ADISC 0x52
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index adebe626a23f..27d60ad897cd 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -465,14 +465,18 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
465static int 465static int
466lpfc_rcv_logo(struct lpfc_hba * phba, 466lpfc_rcv_logo(struct lpfc_hba * phba,
467 struct lpfc_nodelist * ndlp, 467 struct lpfc_nodelist * ndlp,
468 struct lpfc_iocbq *cmdiocb) 468 struct lpfc_iocbq *cmdiocb,
469 uint32_t els_cmd)
469{ 470{
470 /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */ 471 /* Put ndlp on NPR list with 1 sec timeout for plogi, ACC logo */
471 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary 472 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
472 * PLOGIs during LOGO storms from a device. 473 * PLOGIs during LOGO storms from a device.
473 */ 474 */
474 ndlp->nlp_flag |= NLP_LOGO_ACC; 475 ndlp->nlp_flag |= NLP_LOGO_ACC;
475 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); 476 if (els_cmd == ELS_CMD_PRLO)
477 lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
478 else
479 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
476 480
477 if (!(ndlp->nlp_type & NLP_FABRIC) || 481 if (!(ndlp->nlp_type & NLP_FABRIC) ||
478 (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { 482 (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
@@ -681,7 +685,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
681 /* software abort outstanding PLOGI */ 685 /* software abort outstanding PLOGI */
682 lpfc_els_abort(phba, ndlp, 1); 686 lpfc_els_abort(phba, ndlp, 1);
683 687
684 lpfc_rcv_logo(phba, ndlp, cmdiocb); 688 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
685 return ndlp->nlp_state; 689 return ndlp->nlp_state;
686} 690}
687 691
@@ -907,7 +911,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
907 /* software abort outstanding ADISC */ 911 /* software abort outstanding ADISC */
908 lpfc_els_abort(phba, ndlp, 0); 912 lpfc_els_abort(phba, ndlp, 0);
909 913
910 lpfc_rcv_logo(phba, ndlp, cmdiocb); 914 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
911 return ndlp->nlp_state; 915 return ndlp->nlp_state;
912} 916}
913 917
@@ -934,7 +938,7 @@ lpfc_rcv_prlo_adisc_issue(struct lpfc_hba * phba,
934 cmdiocb = (struct lpfc_iocbq *) arg; 938 cmdiocb = (struct lpfc_iocbq *) arg;
935 939
936 /* Treat like rcv logo */ 940 /* Treat like rcv logo */
937 lpfc_rcv_logo(phba, ndlp, cmdiocb); 941 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
938 return ndlp->nlp_state; 942 return ndlp->nlp_state;
939} 943}
940 944
@@ -1056,7 +1060,7 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
1056 1060
1057 cmdiocb = (struct lpfc_iocbq *) arg; 1061 cmdiocb = (struct lpfc_iocbq *) arg;
1058 1062
1059 lpfc_rcv_logo(phba, ndlp, cmdiocb); 1063 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
1060 return ndlp->nlp_state; 1064 return ndlp->nlp_state;
1061} 1065}
1062 1066
@@ -1081,7 +1085,7 @@ lpfc_rcv_prlo_reglogin_issue(struct lpfc_hba * phba,
1081 struct lpfc_iocbq *cmdiocb; 1085 struct lpfc_iocbq *cmdiocb;
1082 1086
1083 cmdiocb = (struct lpfc_iocbq *) arg; 1087 cmdiocb = (struct lpfc_iocbq *) arg;
1084 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); 1088 lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
1085 return ndlp->nlp_state; 1089 return ndlp->nlp_state;
1086} 1090}
1087 1091
@@ -1200,7 +1204,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
1200 /* Software abort outstanding PRLI before sending acc */ 1204 /* Software abort outstanding PRLI before sending acc */
1201 lpfc_els_abort(phba, ndlp, 1); 1205 lpfc_els_abort(phba, ndlp, 1);
1202 1206
1203 lpfc_rcv_logo(phba, ndlp, cmdiocb); 1207 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
1204 return ndlp->nlp_state; 1208 return ndlp->nlp_state;
1205} 1209}
1206 1210
@@ -1228,7 +1232,7 @@ lpfc_rcv_prlo_prli_issue(struct lpfc_hba * phba,
1228 struct lpfc_iocbq *cmdiocb; 1232 struct lpfc_iocbq *cmdiocb;
1229 1233
1230 cmdiocb = (struct lpfc_iocbq *) arg; 1234 cmdiocb = (struct lpfc_iocbq *) arg;
1231 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); 1235 lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
1232 return ndlp->nlp_state; 1236 return ndlp->nlp_state;
1233} 1237}
1234 1238
@@ -1371,7 +1375,7 @@ lpfc_rcv_logo_unmap_node(struct lpfc_hba * phba,
1371 1375
1372 cmdiocb = (struct lpfc_iocbq *) arg; 1376 cmdiocb = (struct lpfc_iocbq *) arg;
1373 1377
1374 lpfc_rcv_logo(phba, ndlp, cmdiocb); 1378 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
1375 return ndlp->nlp_state; 1379 return ndlp->nlp_state;
1376} 1380}
1377 1381
@@ -1395,7 +1399,7 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_hba * phba,
1395 1399
1396 cmdiocb = (struct lpfc_iocbq *) arg; 1400 cmdiocb = (struct lpfc_iocbq *) arg;
1397 1401
1398 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); 1402 lpfc_els_rsp_acc(phba, ELS_CMD_PRLO, cmdiocb, ndlp, NULL, 0);
1399 return ndlp->nlp_state; 1403 return ndlp->nlp_state;
1400} 1404}
1401 1405
@@ -1444,7 +1448,7 @@ lpfc_rcv_logo_mapped_node(struct lpfc_hba * phba,
1444 1448
1445 cmdiocb = (struct lpfc_iocbq *) arg; 1449 cmdiocb = (struct lpfc_iocbq *) arg;
1446 1450
1447 lpfc_rcv_logo(phba, ndlp, cmdiocb); 1451 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
1448 return ndlp->nlp_state; 1452 return ndlp->nlp_state;
1449} 1453}
1450 1454
@@ -1476,7 +1480,7 @@ lpfc_rcv_prlo_mapped_node(struct lpfc_hba * phba,
1476 spin_unlock_irq(phba->host->host_lock); 1480 spin_unlock_irq(phba->host->host_lock);
1477 1481
1478 /* Treat like rcv logo */ 1482 /* Treat like rcv logo */
1479 lpfc_rcv_logo(phba, ndlp, cmdiocb); 1483 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_PRLO);
1480 return ndlp->nlp_state; 1484 return ndlp->nlp_state;
1481} 1485}
1482 1486
@@ -1571,7 +1575,7 @@ lpfc_rcv_logo_npr_node(struct lpfc_hba * phba,
1571 1575
1572 cmdiocb = (struct lpfc_iocbq *) arg; 1576 cmdiocb = (struct lpfc_iocbq *) arg;
1573 1577
1574 lpfc_rcv_logo(phba, ndlp, cmdiocb); 1578 lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
1575 return ndlp->nlp_state; 1579 return ndlp->nlp_state;
1576} 1580}
1577 1581