diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:37 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:06:27 -0400 |
commit | ed957684294618602b48f1950b0c9bbcb036583f (patch) | |
tree | 4e88dbb2e55013f973ad94099e2963dd507ea719 /drivers/scsi/lpfc/lpfc_ct.c | |
parent | 2e0fef85e098f6794956b8b80b111179fbb4cbb7 (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.c | 183 |
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 | */ |
61 | static void | ||
62 | lpfc_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 | |||
79 | static void | ||
80 | lpfc_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 | |||
61 | void | 101 | void |
62 | lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 102 | lpfc_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); | |
133 | ct_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 | ||
147 | static void | 188 | static 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); |
1121 | fdmi_cmd_exit: | 1155 | fdmi_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 | ||