1/*
2 * Copyright 2008 Cisco Systems, Inc.  All rights reserved.
3 * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
4 *
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.
8 *
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
16 * SOFTWARE.
17 */
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"
25#include "vnic_dev.h"
26#include "vnic_wq.h"
27#include "vnic_rq.h"
28#include "vnic_cq.h"
29#include "vnic_intr.h"
30#include "vnic_stats.h"
31#include "vnic_nic.h"
32#include "fnic.h"
33
34int fnic_get_vnic_config(struct fnic *fnic)
35{
36	struct vnic_fc_config *c = &fnic->config;
37	int err;
38
39#define GET_CONFIG(m) \
40	do { \
41		err = vnic_dev_spec(fnic->vdev, \
42				    offsetof(struct vnic_fc_config, m), \
43				    sizeof(c->m), &c->m); \
44		if (err) { \
45			shost_printk(KERN_ERR, fnic->lport->host, \
46				     "Error getting %s, %d\n", #m, \
47				     err); \
48			return err; \
49		} \
50	} while (0);
51
52	GET_CONFIG(node_wwn);
53	GET_CONFIG(port_wwn);
54	GET_CONFIG(wq_enet_desc_count);
55	GET_CONFIG(wq_copy_desc_count);
56	GET_CONFIG(rq_desc_count);
57	GET_CONFIG(maxdatafieldsize);
58	GET_CONFIG(ed_tov);
59	GET_CONFIG(ra_tov);
60	GET_CONFIG(intr_timer);
61	GET_CONFIG(intr_timer_type);
62	GET_CONFIG(flags);
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);
72
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);
78
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);
84
85	c->rq_desc_count =
86		min_t(u32, VNIC_FNIC_RQ_DESCS_MAX,
87		      max_t(u32, VNIC_FNIC_RQ_DESCS_MIN,
88			    c->rq_desc_count));
89	c->rq_desc_count = ALIGN(c->rq_desc_count, 16);
90
91	c->maxdatafieldsize =
92		min_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MAX,
93		      max_t(u16, VNIC_FNIC_MAXDATAFIELDSIZE_MIN,
94			    c->maxdatafieldsize));
95	c->ed_tov =
96		min_t(u32, VNIC_FNIC_EDTOV_MAX,
97		      max_t(u32, VNIC_FNIC_EDTOV_MIN,
98			    c->ed_tov));
99
100	c->ra_tov =
101		min_t(u32, VNIC_FNIC_RATOV_MAX,
102		      max_t(u32, VNIC_FNIC_RATOV_MIN,
103			    c->ra_tov));
104
105	c->flogi_retries =
106		min_t(u32, VNIC_FNIC_FLOGI_RETRIES_MAX, c->flogi_retries);
107
108	c->flogi_timeout =
109		min_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MAX,
110		      max_t(u32, VNIC_FNIC_FLOGI_TIMEOUT_MIN,
111			    c->flogi_timeout));
112
113	c->plogi_retries =
114		min_t(u32, VNIC_FNIC_PLOGI_RETRIES_MAX, c->plogi_retries);
115
116	c->plogi_timeout =
117		min_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MAX,
118		      max_t(u32, VNIC_FNIC_PLOGI_TIMEOUT_MIN,
119			    c->plogi_timeout));
120
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));
125
126	c->link_down_timeout =
127		min_t(u32, VNIC_FNIC_LINK_DOWN_TIMEOUT_MAX,
128		      c->link_down_timeout);
129
130	c->port_down_timeout =
131		min_t(u32, VNIC_FNIC_PORT_DOWN_TIMEOUT_MAX,
132		      c->port_down_timeout);
133
134	c->port_down_io_retries =
135		min_t(u32, VNIC_FNIC_PORT_DOWN_IO_RETRIES_MAX,
136		      c->port_down_io_retries);
137
138	c->luns_per_tgt =
139		min_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MAX,
140		      max_t(u32, VNIC_FNIC_LUNS_PER_TARGET_MIN,
141			    c->luns_per_tgt));
142
143	c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
144	c->intr_timer_type = c->intr_timer_type;
145
146	shost_printk(KERN_INFO, fnic->lport->host,
147		     "vNIC MAC addr %pM "
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,
151		     c->rq_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);
176
177	return 0;
178}
179
180int fnic_set_nic_config(struct fnic *fnic, u8 rss_default_cpu,
181			u8 rss_hash_type,
182			u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable,
183			u8 tso_ipid_split_en, u8 ig_vlan_strip_en)
184{
185	u64 a0, a1;
186	u32 nic_cfg;
187	int wait = 1000;
188
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);
192
193	a0 = nic_cfg;
194	a1 = 0;
195
196	return vnic_dev_cmd(fnic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
197}
198
199void fnic_get_res_counts(struct fnic *fnic)
200{
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,
207		RES_TYPE_INTR_CTRL);
208}
209
210void fnic_free_vnic_resources(struct fnic *fnic)
211{
212	unsigned int i;
213
214	for (i = 0; i < fnic->raw_wq_count; i++)
215		vnic_wq_free(&fnic->wq[i]);
216
217	for (i = 0; i < fnic->wq_copy_count; i++)
218		vnic_wq_copy_free(&fnic->wq_copy[i]);
219
220	for (i = 0; i < fnic->rq_count; i++)
221		vnic_rq_free(&fnic->rq[i]);
222
223	for (i = 0; i < fnic->cq_count; i++)
224		vnic_cq_free(&fnic->cq[i]);
225
226	for (i = 0; i < fnic->intr_count; i++)
227		vnic_intr_free(&fnic->intr[i]);
228}
229
230int fnic_alloc_vnic_resources(struct fnic *fnic)
231{
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;
239	int err;
240
241	intr_mode = vnic_dev_get_intr_mode(fnic->vdev);
242
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");
248
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);
253
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));
259		if (err)
260			goto err_out_cleanup;
261	}
262
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));
269		if (err)
270			goto err_out_cleanup;
271	}
272
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));
278		if (err)
279			goto err_out_cleanup;
280	}
281
282	/* CQ for each RQ */
283	for (i = 0; i < fnic->rq_count; i++) {
284		cq_index = 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));
289		if (err)
290			goto err_out_cleanup;
291	}
292
293	/* CQ for each WQ */
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));
299		if (err)
300			goto err_out_cleanup;
301	}
302
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],
308			cq_index,
309			wq_copy_cq_desc_count,
310			sizeof(struct fcpio_fw_req));
311		if (err)
312			goto err_out_cleanup;
313	}
314
315	for (i = 0; i < fnic->intr_count; i++) {
316		err = vnic_intr_alloc(fnic->vdev, &fnic->intr[i], i);
317		if (err)
318			goto err_out_cleanup;
319	}
320
321	fnic->legacy_pba = vnic_dev_get_res(fnic->vdev,
322				RES_TYPE_INTR_PBA_LEGACY, 0);
323
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");
327		err = -ENODEV;
328		goto err_out_cleanup;
329	}
330
331	/*
332	 * Init RQ/WQ resources.
333	 *
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]
337	 *
338	 * Note for copy wq we always initialize with cq_index = 0
339	 *
340	 * Error interrupt is not enabled for MSI.
341	 */
342
343	switch (intr_mode) {
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;
348		break;
349	default:
350		error_interrupt_enable = 0;
351		error_interrupt_offset = 0;
352		break;
353	}
354
355	for (i = 0; i < fnic->rq_count; i++) {
356		cq_index = i;
357		vnic_rq_init(&fnic->rq[i],
358			     cq_index,
359			     error_interrupt_enable,
360			     error_interrupt_offset);
361	}
362
363	for (i = 0; i < fnic->raw_wq_count; i++) {
364		cq_index = i + fnic->rq_count;
365		vnic_wq_init(&fnic->wq[i],
366			     cq_index,
367			     error_interrupt_enable,
368			     error_interrupt_offset);
369	}
370
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);
376	}
377
378	for (i = 0; i < fnic->cq_count; i++) {
379
380		switch (intr_mode) {
381		case VNIC_DEV_INTR_MODE_MSIX:
382			interrupt_offset = i;
383			break;
384		default:
385			interrupt_offset = 0;
386			break;
387		}
388
389		vnic_cq_init(&fnic->cq[i],
390			0 /* flow_control_enable */,
391			1 /* color_enable */,
392			0 /* cq_head */,
393			0 /* cq_tail */,
394			1 /* cq_tail_color */,
395			1 /* interrupt_enable */,
396			1 /* cq_entry_enable */,
397			0 /* cq_message_enable */,
398			interrupt_offset,
399			0 /* cq_message_addr */);
400	}
401
402	/*
403	 * Init INTR resources
404	 *
405	 * mask_on_assertion is not used for INTx due to the level-
406	 * triggered nature of INTx
407	 */
408
409	switch (intr_mode) {
410	case VNIC_DEV_INTR_MODE_MSI:
411	case VNIC_DEV_INTR_MODE_MSIX:
412		mask_on_assertion = 1;
413		break;
414	default:
415		mask_on_assertion = 0;
416		break;
417	}
418
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,
423			mask_on_assertion);
424	}
425
426	/* init the stats memory by making the first call here */
427	err = vnic_dev_stats_dump(fnic->vdev, &fnic->stats);
428	if (err) {
429		shost_printk(KERN_ERR, fnic->lport->host,
430			     "vnic_dev_stats_dump failed - x%x\n", err);
431		goto err_out_cleanup;
432	}
433
434	/* Clear LIF stats */
435	vnic_dev_stats_clear(fnic->vdev);
436
437	return 0;
438
439err_out_cleanup:
440	fnic_free_vnic_resources(fnic);
441
442	return err;
443}
444