aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_ct.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-06-17 20:56:37 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-06-17 23:06:27 -0400
commited957684294618602b48f1950b0c9bbcb036583f (patch)
tree4e88dbb2e55013f973ad94099e2963dd507ea719 /drivers/scsi/lpfc/lpfc_ct.c
parent2e0fef85e098f6794956b8b80b111179fbb4cbb7 (diff)
[SCSI] lpfc: NPIV: add SLI-3 interface
NPIV support is only available via new adapter interface extensions, termed SLI-3. This interface changes some of the basic behaviors such as command and response ring element sizes and data structures, as well as a change in buffer posting. Note: the new firmware extensions are found only on our mid-range and enterprise 4Gig adapters - so NPIV support is available only on these newer adapters. The latest firmware can be downloaded from the Emulex support page. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_ct.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c183
1 files changed, 107 insertions, 76 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index dc25a53524c4..e8ed5d7ccf9f 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -58,25 +58,66 @@ static char *lpfc_release_version = LPFC_DRIVER_VERSION;
58/* 58/*
59 * lpfc_ct_unsol_event 59 * lpfc_ct_unsol_event
60 */ 60 */
61static void
62lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
63 struct lpfc_dmabuf *mp, uint32_t size)
64{
65 if (!mp) {
66 printk(KERN_ERR "%s (%d): Unsolited CT, no buffer, "
67 "piocbq = %p, status = x%x, mp = %p, size = %d\n",
68 __FUNCTION__, __LINE__,
69 piocbq, piocbq->iocb.ulpStatus, mp, size);
70 }
71
72 printk(KERN_ERR "%s (%d): Ignoring unsolicted CT piocbq = %p, "
73 "buffer = %p, size = %d, status = x%x\n",
74 __FUNCTION__, __LINE__,
75 piocbq, mp, size,
76 piocbq->iocb.ulpStatus);
77}
78
79static void
80lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
81 struct hbq_dmabuf *sp, uint32_t size)
82{
83 struct lpfc_dmabuf *mp = NULL;
84
85 mp = sp ? &sp->dbuf : NULL;
86 if (!mp) {
87 printk(KERN_ERR "%s (%d): Unsolited CT, no "
88 "HBQ buffer, piocbq = %p, status = x%x\n",
89 __FUNCTION__, __LINE__,
90 piocbq, piocbq->iocb.ulpStatus);
91 } else {
92 lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
93 printk(KERN_ERR "%s (%d): Ignoring unsolicted CT "
94 "piocbq = %p, buffer = %p, size = %d, "
95 "status = x%x\n",
96 __FUNCTION__, __LINE__,
97 piocbq, mp, size, piocbq->iocb.ulpStatus);
98 }
99}
100
61void 101void
62lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 102lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
63 struct lpfc_iocbq *piocbq) 103 struct lpfc_iocbq *piocbq)
64{ 104{
65 105 struct lpfc_dmabuf *mp = NULL;
66 struct lpfc_iocbq *next_piocbq; 106 struct hbq_dmabuf *sp = NULL;
67 struct lpfc_dmabuf *pmbuf = NULL;
68 struct lpfc_dmabuf *matp = NULL, *next_matp;
69 uint32_t ctx = 0, size = 0, cnt = 0;
70 IOCB_t *icmd = &piocbq->iocb; 107 IOCB_t *icmd = &piocbq->iocb;
71 IOCB_t *save_icmd = icmd; 108 int i;
72 int i, go_exit = 0; 109 struct lpfc_iocbq *iocbq;
73 struct list_head head; 110 dma_addr_t paddr;
111 uint32_t size;
74 112
75 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && 113 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
76 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { 114 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
77 /* Not enough posted buffers; Try posting more buffers */ 115 /* Not enough posted buffers; Try posting more buffers */
78 phba->fc_stat.NoRcvBuf++; 116 phba->fc_stat.NoRcvBuf++;
79 lpfc_post_buffer(phba, pring, 0, 1); 117 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
118 lpfc_sli_hbqbuf_fill_hbq(phba);
119 else
120 lpfc_post_buffer(phba, pring, 0, 1);
80 return; 121 return;
81 } 122 }
82 123
@@ -86,62 +127,62 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
86 if (icmd->ulpBdeCount == 0) 127 if (icmd->ulpBdeCount == 0)
87 return; 128 return;
88 129
89 INIT_LIST_HEAD(&head); 130 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
90 list_add_tail(&head, &piocbq->list); 131 list_for_each_entry(iocbq, &piocbq->list, list) {
91 132 icmd = &iocbq->iocb;
92 list_for_each_entry_safe(piocbq, next_piocbq, &head, list) { 133 if (icmd->ulpBdeCount == 0) {
93 icmd = &piocbq->iocb; 134 printk(KERN_ERR "%s (%d): Unsolited CT, no "
94 if (ctx == 0) 135 "BDE, iocbq = %p, status = x%x\n",
95 ctx = (uint32_t) (icmd->ulpContext); 136 __FUNCTION__, __LINE__,
96 if (icmd->ulpBdeCount == 0) 137 iocbq, iocbq->iocb.ulpStatus);
97 continue; 138 continue;
98
99 for (i = 0; i < icmd->ulpBdeCount; i++) {
100 matp = lpfc_sli_ringpostbuf_get(phba, pring,
101 getPaddr(icmd->un.
102 cont64[i].
103 addrHigh,
104 icmd->un.
105 cont64[i].
106 addrLow));
107 if (!matp) {
108 /* Insert lpfc log message here */
109 lpfc_post_buffer(phba, pring, cnt, 1);
110 go_exit = 1;
111 goto ct_unsol_event_exit_piocbq;
112 } 139 }
113 140
114 /* Typically for Unsolicited CT requests */ 141 size = icmd->un.cont64[0].tus.f.bdeSize;
115 if (!pmbuf) { 142 sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[3]);
116 pmbuf = matp; 143 if (sp)
117 INIT_LIST_HEAD(&pmbuf->list); 144 phba->hbq_buff_count--;
118 } else 145 lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp, size);
119 list_add_tail(&matp->list, &pmbuf->list); 146 lpfc_sli_free_hbq(phba, sp);
147 if (icmd->ulpBdeCount == 2) {
148 sp = lpfc_sli_hbqbuf_find(phba,
149 icmd->un.ulpWord[15]);
150 if (sp)
151 phba->hbq_buff_count--;
152 lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp,
153 size);
154 lpfc_sli_free_hbq(phba, sp);
155 }
120 156
121 size += icmd->un.cont64[i].tus.f.bdeSize;
122 cnt++;
123 } 157 }
158 lpfc_sli_hbqbuf_fill_hbq(phba);
159 } else {
160 struct lpfc_iocbq *next;
161
162 list_for_each_entry_safe(iocbq, next, &piocbq->list, list) {
163 icmd = &iocbq->iocb;
164 if (icmd->ulpBdeCount == 0) {
165 printk(KERN_ERR "%s (%d): Unsolited CT, no "
166 "BDE, iocbq = %p, status = x%x\n",
167 __FUNCTION__, __LINE__,
168 iocbq, iocbq->iocb.ulpStatus);
169 continue;
170 }
124 171
125 icmd->ulpBdeCount = 0; 172 for (i = 0; i < icmd->ulpBdeCount; i++) {
126 } 173 paddr = getPaddr(icmd->un.cont64[i].addrHigh,
127 174 icmd->un.cont64[i].addrLow);
128 lpfc_post_buffer(phba, pring, cnt, 1); 175 mp = lpfc_sli_ringpostbuf_get(phba, pring,
129 if (save_icmd->ulpStatus) { 176 paddr);
130 go_exit = 1; 177 size = icmd->un.cont64[i].tus.f.bdeSize;
131 } 178 lpfc_ct_unsol_buffer(phba, piocbq, mp, size);
132 179 lpfc_mbuf_free(phba, mp->virt, mp->phys);
133ct_unsol_event_exit_piocbq: 180 kfree(mp);
134 list_del(&head); 181 }
135 if (pmbuf) { 182 list_del(&iocbq->list);
136 list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) { 183 lpfc_sli_release_iocbq(phba, iocbq);
137 lpfc_mbuf_free(phba, matp->virt, matp->phys);
138 list_del(&matp->list);
139 kfree(matp);
140 } 184 }
141 lpfc_mbuf_free(phba, pmbuf->virt, pmbuf->phys);
142 kfree(pmbuf);
143 } 185 }
144 return;
145} 186}
146 187
147static void 188static void
@@ -364,9 +405,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
364 vport->fc_flag, 405 vport->fc_flag,
365 vport->fc_rscn_id_cnt); 406 vport->fc_rscn_id_cnt);
366 } else { 407 } else {
367 lpfc_printf_log(phba, 408 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
368 KERN_INFO,
369 LOG_DISCOVERY,
370 "%d:0239 Skip x%x NameServer " 409 "%d:0239 Skip x%x NameServer "
371 "Rsp Data: x%x x%x x%x\n", 410 "Rsp Data: x%x x%x x%x\n",
372 phba->brd_no, 411 phba->brd_no,
@@ -717,12 +756,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
717 ndlp = lpfc_findnode_did(vport, FDMI_DID); 756 ndlp = lpfc_findnode_did(vport, FDMI_DID);
718 if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { 757 if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
719 /* FDMI rsp failed */ 758 /* FDMI rsp failed */
720 lpfc_printf_log(phba, 759 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
721 KERN_INFO, 760 "%d:0220 FDMI rsp failed Data: x%x\n",
722 LOG_DISCOVERY, 761 phba->brd_no, be16_to_cpu(fdmi_cmd));
723 "%d:0220 FDMI rsp failed Data: x%x\n",
724 phba->brd_no,
725 be16_to_cpu(fdmi_cmd));
726 } 762 }
727 763
728 switch (be16_to_cpu(fdmi_cmd)) { 764 switch (be16_to_cpu(fdmi_cmd)) {
@@ -791,9 +827,7 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
791 INIT_LIST_HEAD(&bmp->list); 827 INIT_LIST_HEAD(&bmp->list);
792 828
793 /* FDMI request */ 829 /* FDMI request */
794 lpfc_printf_log(phba, 830 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
795 KERN_INFO,
796 LOG_DISCOVERY,
797 "%d:0218 FDMI Request Data: x%x x%x x%x\n", 831 "%d:0218 FDMI Request Data: x%x x%x x%x\n",
798 phba->brd_no, 832 phba->brd_no,
799 vport->fc_flag, vport->port_state, cmdcode); 833 vport->fc_flag, vport->port_state, cmdcode);
@@ -1120,12 +1154,9 @@ fdmi_cmd_free_mp:
1120 kfree(mp); 1154 kfree(mp);
1121fdmi_cmd_exit: 1155fdmi_cmd_exit:
1122 /* Issue FDMI request failed */ 1156 /* Issue FDMI request failed */
1123 lpfc_printf_log(phba, 1157 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
1124 KERN_INFO,
1125 LOG_DISCOVERY,
1126 "%d:0244 Issue FDMI request failed Data: x%x\n", 1158 "%d:0244 Issue FDMI request failed Data: x%x\n",
1127 phba->brd_no, 1159 phba->brd_no, cmdcode);
1128 cmdcode);
1129 return 1; 1160 return 1;
1130} 1161}
1131 1162