2 * Copyright 2008 Cisco Systems, Inc. All rights reserved.
3 * Copyright 2007 Nuova Systems, Inc. All rights reserved.
5 * This program is free software; you may redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
10 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
11 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
12 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
13 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
14 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
15 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
18 #include <linux/errno.h>
19 #include <linux/types.h>
20 #include <linux/pci.h>
21 #include "wq_enet_desc.h"
22 #include "rq_enet_desc.h"
23 #include "cq_enet_desc.h"
24 #include "vnic_resource.h"
29 #include "vnic_intr.h"
30 #include "vnic_stats.h"
34 int fnic_get_vnic_config(struct fnic
*fnic
)
36 struct vnic_fc_config
*c
= &fnic
->config
;
39 #define GET_CONFIG(m) \
41 err = vnic_dev_spec(fnic->vdev, \
42 offsetof(struct vnic_fc_config, m), \
43 sizeof(c->m), &c->m); \
45 shost_printk(KERN_ERR, fnic->lport->host, \
46 "Error getting %s, %d\n", #m, \
54 GET_CONFIG(wq_enet_desc_count
);
55 GET_CONFIG(wq_copy_desc_count
);
56 GET_CONFIG(rq_desc_count
);
57 GET_CONFIG(maxdatafieldsize
);
60 GET_CONFIG(intr_timer
);
61 GET_CONFIG(intr_timer_type
);
63 GET_CONFIG(flogi_retries
);
64 GET_CONFIG(flogi_timeout
);
65 GET_CONFIG(plogi_retries
);
66 GET_CONFIG(plogi_timeout
);
67 GET_CONFIG(io_throttle_count
);
68 GET_CONFIG(link_down_timeout
);
69 GET_CONFIG(port_down_timeout
);
70 GET_CONFIG(port_down_io_retries
);
71 GET_CONFIG(luns_per_tgt
);
73 c
->wq_enet_desc_count
=
74 min_t(u32
, VNIC_FNIC_WQ_DESCS_MAX
,
75 max_t(u32
, VNIC_FNIC_WQ_DESCS_MIN
,
76 c
->wq_enet_desc_count
));
77 c
->wq_enet_desc_count
= ALIGN(c
->wq_enet_desc_count
, 16);
79 c
->wq_copy_desc_count
=
80 min_t(u32
, VNIC_FNIC_WQ_COPY_DESCS_MAX
,
81 max_t(u32
, VNIC_FNIC_WQ_COPY_DESCS_MIN
,
82 c
->wq_copy_desc_count
));
83 c
->wq_copy_desc_count
= ALIGN(c
->wq_copy_desc_count
, 16);
86 min_t(u32
, VNIC_FNIC_RQ_DESCS_MAX
,
87 max_t(u32
, VNIC_FNIC_RQ_DESCS_MIN
,
89 c
->rq_desc_count
= ALIGN(c
->rq_desc_count
, 16);
92 min_t(u16
, VNIC_FNIC_MAXDATAFIELDSIZE_MAX
,
93 max_t(u16
, VNIC_FNIC_MAXDATAFIELDSIZE_MIN
,
94 c
->maxdatafieldsize
));
96 min_t(u32
, VNIC_FNIC_EDTOV_MAX
,
97 max_t(u32
, VNIC_FNIC_EDTOV_MIN
,
101 min_t(u32
, VNIC_FNIC_RATOV_MAX
,
102 max_t(u32
, VNIC_FNIC_RATOV_MIN
,
106 min_t(u32
, VNIC_FNIC_FLOGI_RETRIES_MAX
, c
->flogi_retries
);
109 min_t(u32
, VNIC_FNIC_FLOGI_TIMEOUT_MAX
,
110 max_t(u32
, VNIC_FNIC_FLOGI_TIMEOUT_MIN
,
114 min_t(u32
, VNIC_FNIC_PLOGI_RETRIES_MAX
, c
->plogi_retries
);
117 min_t(u32
, VNIC_FNIC_PLOGI_TIMEOUT_MAX
,
118 max_t(u32
, VNIC_FNIC_PLOGI_TIMEOUT_MIN
,
121 c
->io_throttle_count
=
122 min_t(u32
, VNIC_FNIC_IO_THROTTLE_COUNT_MAX
,
123 max_t(u32
, VNIC_FNIC_IO_THROTTLE_COUNT_MIN
,
124 c
->io_throttle_count
));
126 c
->link_down_timeout
=
127 min_t(u32
, VNIC_FNIC_LINK_DOWN_TIMEOUT_MAX
,
128 c
->link_down_timeout
);
130 c
->port_down_timeout
=
131 min_t(u32
, VNIC_FNIC_PORT_DOWN_TIMEOUT_MAX
,
132 c
->port_down_timeout
);
134 c
->port_down_io_retries
=
135 min_t(u32
, VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX
,
136 c
->port_down_io_retries
);
139 min_t(u32
, VNIC_FNIC_LUNS_PER_TARGET_MAX
,
140 max_t(u32
, VNIC_FNIC_LUNS_PER_TARGET_MIN
,
143 c
->intr_timer
= min_t(u16
, VNIC_INTR_TIMER_MAX
, c
->intr_timer
);
144 c
->intr_timer_type
= c
->intr_timer_type
;
146 shost_printk(KERN_INFO
, fnic
->lport
->host
,
148 "wq/wq_copy/rq %d/%d/%d\n",
149 fnic
->ctlr
.ctl_src_addr
,
150 c
->wq_enet_desc_count
, c
->wq_copy_desc_count
,
152 shost_printk(KERN_INFO
, fnic
->lport
->host
,
153 "vNIC node wwn %llx port wwn %llx\n",
154 c
->node_wwn
, c
->port_wwn
);
155 shost_printk(KERN_INFO
, fnic
->lport
->host
,
156 "vNIC ed_tov %d ra_tov %d\n",
157 c
->ed_tov
, c
->ra_tov
);
158 shost_printk(KERN_INFO
, fnic
->lport
->host
,
159 "vNIC mtu %d intr timer %d\n",
160 c
->maxdatafieldsize
, c
->intr_timer
);
161 shost_printk(KERN_INFO
, fnic
->lport
->host
,
162 "vNIC flags 0x%x luns per tgt %d\n",
163 c
->flags
, c
->luns_per_tgt
);
164 shost_printk(KERN_INFO
, fnic
->lport
->host
,
165 "vNIC flogi_retries %d flogi timeout %d\n",
166 c
->flogi_retries
, c
->flogi_timeout
);
167 shost_printk(KERN_INFO
, fnic
->lport
->host
,
168 "vNIC plogi retries %d plogi timeout %d\n",
169 c
->plogi_retries
, c
->plogi_timeout
);
170 shost_printk(KERN_INFO
, fnic
->lport
->host
,
171 "vNIC io throttle count %d link dn timeout %d\n",
172 c
->io_throttle_count
, c
->link_down_timeout
);
173 shost_printk(KERN_INFO
, fnic
->lport
->host
,
174 "vNIC port dn io retries %d port dn timeout %d\n",
175 c
->port_down_io_retries
, c
->port_down_timeout
);
180 int fnic_set_nic_config(struct fnic
*fnic
, u8 rss_default_cpu
,
182 u8 rss_hash_bits
, u8 rss_base_cpu
, u8 rss_enable
,
183 u8 tso_ipid_split_en
, u8 ig_vlan_strip_en
)
189 vnic_set_nic_cfg(&nic_cfg
, rss_default_cpu
,
190 rss_hash_type
, rss_hash_bits
, rss_base_cpu
,
191 rss_enable
, tso_ipid_split_en
, ig_vlan_strip_en
);
196 return vnic_dev_cmd(fnic
->vdev
, CMD_NIC_CFG
, &a0
, &a1
, wait
);
199 void fnic_get_res_counts(struct fnic
*fnic
)
201 fnic
->wq_count
= vnic_dev_get_res_count(fnic
->vdev
, RES_TYPE_WQ
);
202 fnic
->raw_wq_count
= fnic
->wq_count
- 1;
203 fnic
->wq_copy_count
= fnic
->wq_count
- fnic
->raw_wq_count
;
204 fnic
->rq_count
= vnic_dev_get_res_count(fnic
->vdev
, RES_TYPE_RQ
);
205 fnic
->cq_count
= vnic_dev_get_res_count(fnic
->vdev
, RES_TYPE_CQ
);
206 fnic
->intr_count
= vnic_dev_get_res_count(fnic
->vdev
,
210 void fnic_free_vnic_resources(struct fnic
*fnic
)
214 for (i
= 0; i
< fnic
->raw_wq_count
; i
++)
215 vnic_wq_free(&fnic
->wq
[i
]);
217 for (i
= 0; i
< fnic
->wq_copy_count
; i
++)
218 vnic_wq_copy_free(&fnic
->wq_copy
[i
]);
220 for (i
= 0; i
< fnic
->rq_count
; i
++)
221 vnic_rq_free(&fnic
->rq
[i
]);
223 for (i
= 0; i
< fnic
->cq_count
; i
++)
224 vnic_cq_free(&fnic
->cq
[i
]);
226 for (i
= 0; i
< fnic
->intr_count
; i
++)
227 vnic_intr_free(&fnic
->intr
[i
]);
230 int fnic_alloc_vnic_resources(struct fnic
*fnic
)
232 enum vnic_dev_intr_mode intr_mode
;
233 unsigned int mask_on_assertion
;
234 unsigned int interrupt_offset
;
235 unsigned int error_interrupt_enable
;
236 unsigned int error_interrupt_offset
;
237 unsigned int i
, cq_index
;
238 unsigned int wq_copy_cq_desc_count
;
241 intr_mode
= vnic_dev_get_intr_mode(fnic
->vdev
);
243 shost_printk(KERN_INFO
, fnic
->lport
->host
, "vNIC interrupt mode: %s\n",
244 intr_mode
== VNIC_DEV_INTR_MODE_INTX
? "legacy PCI INTx" :
245 intr_mode
== VNIC_DEV_INTR_MODE_MSI
? "MSI" :
246 intr_mode
== VNIC_DEV_INTR_MODE_MSIX
?
247 "MSI-X" : "unknown");
249 shost_printk(KERN_INFO
, fnic
->lport
->host
, "vNIC resources avail: "
250 "wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
251 fnic
->wq_count
, fnic
->wq_copy_count
, fnic
->raw_wq_count
,
252 fnic
->rq_count
, fnic
->cq_count
, fnic
->intr_count
);
254 /* Allocate Raw WQ used for FCS frames */
255 for (i
= 0; i
< fnic
->raw_wq_count
; i
++) {
256 err
= vnic_wq_alloc(fnic
->vdev
, &fnic
->wq
[i
], i
,
257 fnic
->config
.wq_enet_desc_count
,
258 sizeof(struct wq_enet_desc
));
260 goto err_out_cleanup
;
263 /* Allocate Copy WQs used for SCSI IOs */
264 for (i
= 0; i
< fnic
->wq_copy_count
; i
++) {
265 err
= vnic_wq_copy_alloc(fnic
->vdev
, &fnic
->wq_copy
[i
],
266 (fnic
->raw_wq_count
+ i
),
267 fnic
->config
.wq_copy_desc_count
,
268 sizeof(struct fcpio_host_req
));
270 goto err_out_cleanup
;
273 /* RQ for receiving FCS frames */
274 for (i
= 0; i
< fnic
->rq_count
; i
++) {
275 err
= vnic_rq_alloc(fnic
->vdev
, &fnic
->rq
[i
], i
,
276 fnic
->config
.rq_desc_count
,
277 sizeof(struct rq_enet_desc
));
279 goto err_out_cleanup
;
283 for (i
= 0; i
< fnic
->rq_count
; i
++) {
285 err
= vnic_cq_alloc(fnic
->vdev
,
286 &fnic
->cq
[cq_index
], cq_index
,
287 fnic
->config
.rq_desc_count
,
288 sizeof(struct cq_enet_rq_desc
));
290 goto err_out_cleanup
;
294 for (i
= 0; i
< fnic
->raw_wq_count
; i
++) {
295 cq_index
= fnic
->rq_count
+ i
;
296 err
= vnic_cq_alloc(fnic
->vdev
, &fnic
->cq
[cq_index
], cq_index
,
297 fnic
->config
.wq_enet_desc_count
,
298 sizeof(struct cq_enet_wq_desc
));
300 goto err_out_cleanup
;
303 /* CQ for each COPY WQ */
304 wq_copy_cq_desc_count
= (fnic
->config
.wq_copy_desc_count
* 3);
305 for (i
= 0; i
< fnic
->wq_copy_count
; i
++) {
306 cq_index
= fnic
->raw_wq_count
+ fnic
->rq_count
+ i
;
307 err
= vnic_cq_alloc(fnic
->vdev
, &fnic
->cq
[cq_index
],
309 wq_copy_cq_desc_count
,
310 sizeof(struct fcpio_fw_req
));
312 goto err_out_cleanup
;
315 for (i
= 0; i
< fnic
->intr_count
; i
++) {
316 err
= vnic_intr_alloc(fnic
->vdev
, &fnic
->intr
[i
], i
);
318 goto err_out_cleanup
;
321 fnic
->legacy_pba
= vnic_dev_get_res(fnic
->vdev
,
322 RES_TYPE_INTR_PBA_LEGACY
, 0);
324 if (!fnic
->legacy_pba
&& intr_mode
== VNIC_DEV_INTR_MODE_INTX
) {
325 shost_printk(KERN_ERR
, fnic
->lport
->host
,
326 "Failed to hook legacy pba resource\n");
328 goto err_out_cleanup
;
332 * Init RQ/WQ resources.
334 * RQ[0 to n-1] point to CQ[0 to n-1]
335 * WQ[0 to m-1] point to CQ[n to n+m-1]
336 * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1]
338 * Note for copy wq we always initialize with cq_index = 0
340 * Error interrupt is not enabled for MSI.
344 case VNIC_DEV_INTR_MODE_INTX
:
345 case VNIC_DEV_INTR_MODE_MSIX
:
346 error_interrupt_enable
= 1;
347 error_interrupt_offset
= fnic
->err_intr_offset
;
350 error_interrupt_enable
= 0;
351 error_interrupt_offset
= 0;
355 for (i
= 0; i
< fnic
->rq_count
; i
++) {
357 vnic_rq_init(&fnic
->rq
[i
],
359 error_interrupt_enable
,
360 error_interrupt_offset
);
363 for (i
= 0; i
< fnic
->raw_wq_count
; i
++) {
364 cq_index
= i
+ fnic
->rq_count
;
365 vnic_wq_init(&fnic
->wq
[i
],
367 error_interrupt_enable
,
368 error_interrupt_offset
);
371 for (i
= 0; i
< fnic
->wq_copy_count
; i
++) {
372 vnic_wq_copy_init(&fnic
->wq_copy
[i
],
373 0 /* cq_index 0 - always */,
374 error_interrupt_enable
,
375 error_interrupt_offset
);
378 for (i
= 0; i
< fnic
->cq_count
; i
++) {
381 case VNIC_DEV_INTR_MODE_MSIX
:
382 interrupt_offset
= i
;
385 interrupt_offset
= 0;
389 vnic_cq_init(&fnic
->cq
[i
],
390 0 /* flow_control_enable */,
391 1 /* color_enable */,
394 1 /* cq_tail_color */,
395 1 /* interrupt_enable */,
396 1 /* cq_entry_enable */,
397 0 /* cq_message_enable */,
399 0 /* cq_message_addr */);
403 * Init INTR resources
405 * mask_on_assertion is not used for INTx due to the level-
406 * triggered nature of INTx
410 case VNIC_DEV_INTR_MODE_MSI
:
411 case VNIC_DEV_INTR_MODE_MSIX
:
412 mask_on_assertion
= 1;
415 mask_on_assertion
= 0;
419 for (i
= 0; i
< fnic
->intr_count
; i
++) {
420 vnic_intr_init(&fnic
->intr
[i
],
421 fnic
->config
.intr_timer
,
422 fnic
->config
.intr_timer_type
,
426 /* init the stats memory by making the first call here */
427 err
= vnic_dev_stats_dump(fnic
->vdev
, &fnic
->stats
);
429 shost_printk(KERN_ERR
, fnic
->lport
->host
,
430 "vnic_dev_stats_dump failed - x%x\n", err
);
431 goto err_out_cleanup
;
434 /* Clear LIF stats */
435 vnic_dev_stats_clear(fnic
->vdev
);
440 fnic_free_vnic_resources(fnic
);