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
,
147 "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
148 "wq/wq_copy/rq %d/%d/%d\n",
149 fnic
->mac_addr
[0], fnic
->mac_addr
[1], fnic
->mac_addr
[2],
150 fnic
->mac_addr
[3], fnic
->mac_addr
[4], fnic
->mac_addr
[5],
151 c
->wq_enet_desc_count
, c
->wq_copy_desc_count
,
153 shost_printk(KERN_INFO
, fnic
->lport
->host
,
154 "vNIC node wwn %llx port wwn %llx\n",
155 c
->node_wwn
, c
->port_wwn
);
156 shost_printk(KERN_INFO
, fnic
->lport
->host
,
157 "vNIC ed_tov %d ra_tov %d\n",
158 c
->ed_tov
, c
->ra_tov
);
159 shost_printk(KERN_INFO
, fnic
->lport
->host
,
160 "vNIC mtu %d intr timer %d\n",
161 c
->maxdatafieldsize
, c
->intr_timer
);
162 shost_printk(KERN_INFO
, fnic
->lport
->host
,
163 "vNIC flags 0x%x luns per tgt %d\n",
164 c
->flags
, c
->luns_per_tgt
);
165 shost_printk(KERN_INFO
, fnic
->lport
->host
,
166 "vNIC flogi_retries %d flogi timeout %d\n",
167 c
->flogi_retries
, c
->flogi_timeout
);
168 shost_printk(KERN_INFO
, fnic
->lport
->host
,
169 "vNIC plogi retries %d plogi timeout %d\n",
170 c
->plogi_retries
, c
->plogi_timeout
);
171 shost_printk(KERN_INFO
, fnic
->lport
->host
,
172 "vNIC io throttle count %d link dn timeout %d\n",
173 c
->io_throttle_count
, c
->link_down_timeout
);
174 shost_printk(KERN_INFO
, fnic
->lport
->host
,
175 "vNIC port dn io retries %d port dn timeout %d\n",
176 c
->port_down_io_retries
, c
->port_down_timeout
);
181 int fnic_set_nic_config(struct fnic
*fnic
, u8 rss_default_cpu
,
183 u8 rss_hash_bits
, u8 rss_base_cpu
, u8 rss_enable
,
184 u8 tso_ipid_split_en
, u8 ig_vlan_strip_en
)
190 vnic_set_nic_cfg(&nic_cfg
, rss_default_cpu
,
191 rss_hash_type
, rss_hash_bits
, rss_base_cpu
,
192 rss_enable
, tso_ipid_split_en
, ig_vlan_strip_en
);
197 return vnic_dev_cmd(fnic
->vdev
, CMD_NIC_CFG
, &a0
, &a1
, wait
);
200 void fnic_get_res_counts(struct fnic
*fnic
)
202 fnic
->wq_count
= vnic_dev_get_res_count(fnic
->vdev
, RES_TYPE_WQ
);
203 fnic
->raw_wq_count
= fnic
->wq_count
- 1;
204 fnic
->wq_copy_count
= fnic
->wq_count
- fnic
->raw_wq_count
;
205 fnic
->rq_count
= vnic_dev_get_res_count(fnic
->vdev
, RES_TYPE_RQ
);
206 fnic
->cq_count
= vnic_dev_get_res_count(fnic
->vdev
, RES_TYPE_CQ
);
207 fnic
->intr_count
= vnic_dev_get_res_count(fnic
->vdev
,
211 void fnic_free_vnic_resources(struct fnic
*fnic
)
215 for (i
= 0; i
< fnic
->raw_wq_count
; i
++)
216 vnic_wq_free(&fnic
->wq
[i
]);
218 for (i
= 0; i
< fnic
->wq_copy_count
; i
++)
219 vnic_wq_copy_free(&fnic
->wq_copy
[i
]);
221 for (i
= 0; i
< fnic
->rq_count
; i
++)
222 vnic_rq_free(&fnic
->rq
[i
]);
224 for (i
= 0; i
< fnic
->cq_count
; i
++)
225 vnic_cq_free(&fnic
->cq
[i
]);
227 for (i
= 0; i
< fnic
->intr_count
; i
++)
228 vnic_intr_free(&fnic
->intr
[i
]);
231 int fnic_alloc_vnic_resources(struct fnic
*fnic
)
233 enum vnic_dev_intr_mode intr_mode
;
234 unsigned int mask_on_assertion
;
235 unsigned int interrupt_offset
;
236 unsigned int error_interrupt_enable
;
237 unsigned int error_interrupt_offset
;
238 unsigned int i
, cq_index
;
239 unsigned int wq_copy_cq_desc_count
;
242 intr_mode
= vnic_dev_get_intr_mode(fnic
->vdev
);
244 shost_printk(KERN_INFO
, fnic
->lport
->host
, "vNIC interrupt mode: %s\n",
245 intr_mode
== VNIC_DEV_INTR_MODE_INTX
? "legacy PCI INTx" :
246 intr_mode
== VNIC_DEV_INTR_MODE_MSI
? "MSI" :
247 intr_mode
== VNIC_DEV_INTR_MODE_MSIX
?
248 "MSI-X" : "unknown");
250 shost_printk(KERN_INFO
, fnic
->lport
->host
, "vNIC resources avail: "
251 "wq %d cp_wq %d raw_wq %d rq %d cq %d intr %d\n",
252 fnic
->wq_count
, fnic
->wq_copy_count
, fnic
->raw_wq_count
,
253 fnic
->rq_count
, fnic
->cq_count
, fnic
->intr_count
);
255 /* Allocate Raw WQ used for FCS frames */
256 for (i
= 0; i
< fnic
->raw_wq_count
; i
++) {
257 err
= vnic_wq_alloc(fnic
->vdev
, &fnic
->wq
[i
], i
,
258 fnic
->config
.wq_enet_desc_count
,
259 sizeof(struct wq_enet_desc
));
261 goto err_out_cleanup
;
264 /* Allocate Copy WQs used for SCSI IOs */
265 for (i
= 0; i
< fnic
->wq_copy_count
; i
++) {
266 err
= vnic_wq_copy_alloc(fnic
->vdev
, &fnic
->wq_copy
[i
],
267 (fnic
->raw_wq_count
+ i
),
268 fnic
->config
.wq_copy_desc_count
,
269 sizeof(struct fcpio_host_req
));
271 goto err_out_cleanup
;
274 /* RQ for receiving FCS frames */
275 for (i
= 0; i
< fnic
->rq_count
; i
++) {
276 err
= vnic_rq_alloc(fnic
->vdev
, &fnic
->rq
[i
], i
,
277 fnic
->config
.rq_desc_count
,
278 sizeof(struct rq_enet_desc
));
280 goto err_out_cleanup
;
284 for (i
= 0; i
< fnic
->rq_count
; i
++) {
286 err
= vnic_cq_alloc(fnic
->vdev
,
287 &fnic
->cq
[cq_index
], cq_index
,
288 fnic
->config
.rq_desc_count
,
289 sizeof(struct cq_enet_rq_desc
));
291 goto err_out_cleanup
;
295 for (i
= 0; i
< fnic
->raw_wq_count
; i
++) {
296 cq_index
= fnic
->rq_count
+ i
;
297 err
= vnic_cq_alloc(fnic
->vdev
, &fnic
->cq
[cq_index
], cq_index
,
298 fnic
->config
.wq_enet_desc_count
,
299 sizeof(struct cq_enet_wq_desc
));
301 goto err_out_cleanup
;
304 /* CQ for each COPY WQ */
305 wq_copy_cq_desc_count
= (fnic
->config
.wq_copy_desc_count
* 3);
306 for (i
= 0; i
< fnic
->wq_copy_count
; i
++) {
307 cq_index
= fnic
->raw_wq_count
+ fnic
->rq_count
+ i
;
308 err
= vnic_cq_alloc(fnic
->vdev
, &fnic
->cq
[cq_index
],
310 wq_copy_cq_desc_count
,
311 sizeof(struct fcpio_fw_req
));
313 goto err_out_cleanup
;
316 for (i
= 0; i
< fnic
->intr_count
; i
++) {
317 err
= vnic_intr_alloc(fnic
->vdev
, &fnic
->intr
[i
], i
);
319 goto err_out_cleanup
;
322 fnic
->legacy_pba
= vnic_dev_get_res(fnic
->vdev
,
323 RES_TYPE_INTR_PBA_LEGACY
, 0);
325 if (!fnic
->legacy_pba
&& intr_mode
== VNIC_DEV_INTR_MODE_INTX
) {
326 shost_printk(KERN_ERR
, fnic
->lport
->host
,
327 "Failed to hook legacy pba resource\n");
329 goto err_out_cleanup
;
333 * Init RQ/WQ resources.
335 * RQ[0 to n-1] point to CQ[0 to n-1]
336 * WQ[0 to m-1] point to CQ[n to n+m-1]
337 * WQ_COPY[0 to k-1] points to CQ[n+m to n+m+k-1]
339 * Note for copy wq we always initialize with cq_index = 0
341 * Error interrupt is not enabled for MSI.
345 case VNIC_DEV_INTR_MODE_INTX
:
346 case VNIC_DEV_INTR_MODE_MSIX
:
347 error_interrupt_enable
= 1;
348 error_interrupt_offset
= fnic
->err_intr_offset
;
351 error_interrupt_enable
= 0;
352 error_interrupt_offset
= 0;
356 for (i
= 0; i
< fnic
->rq_count
; i
++) {
358 vnic_rq_init(&fnic
->rq
[i
],
360 error_interrupt_enable
,
361 error_interrupt_offset
);
364 for (i
= 0; i
< fnic
->raw_wq_count
; i
++) {
365 cq_index
= i
+ fnic
->rq_count
;
366 vnic_wq_init(&fnic
->wq
[i
],
368 error_interrupt_enable
,
369 error_interrupt_offset
);
372 for (i
= 0; i
< fnic
->wq_copy_count
; i
++) {
373 vnic_wq_copy_init(&fnic
->wq_copy
[i
],
374 0 /* cq_index 0 - always */,
375 error_interrupt_enable
,
376 error_interrupt_offset
);
379 for (i
= 0; i
< fnic
->cq_count
; i
++) {
382 case VNIC_DEV_INTR_MODE_MSIX
:
383 interrupt_offset
= i
;
386 interrupt_offset
= 0;
390 vnic_cq_init(&fnic
->cq
[i
],
391 0 /* flow_control_enable */,
392 1 /* color_enable */,
395 1 /* cq_tail_color */,
396 1 /* interrupt_enable */,
397 1 /* cq_entry_enable */,
398 0 /* cq_message_enable */,
400 0 /* cq_message_addr */);
404 * Init INTR resources
406 * mask_on_assertion is not used for INTx due to the level-
407 * triggered nature of INTx
411 case VNIC_DEV_INTR_MODE_MSI
:
412 case VNIC_DEV_INTR_MODE_MSIX
:
413 mask_on_assertion
= 1;
416 mask_on_assertion
= 0;
420 for (i
= 0; i
< fnic
->intr_count
; i
++) {
421 vnic_intr_init(&fnic
->intr
[i
],
422 fnic
->config
.intr_timer
,
423 fnic
->config
.intr_timer_type
,
427 /* init the stats memory by making the first call here */
428 err
= vnic_dev_stats_dump(fnic
->vdev
, &fnic
->stats
);
430 shost_printk(KERN_ERR
, fnic
->lport
->host
,
431 "vnic_dev_stats_dump failed - x%x\n", err
);
432 goto err_out_cleanup
;
435 /* Clear LIF stats */
436 vnic_dev_stats_clear(fnic
->vdev
);
441 fnic_free_vnic_resources(fnic
);