1*e6550b3eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a6a5580cSJeff Kirsher /*
3a6a5580cSJeff Kirsher  * Copyright 2008-2010 Cisco Systems, Inc.  All rights reserved.
4a6a5580cSJeff Kirsher  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
5a6a5580cSJeff Kirsher  */
6a6a5580cSJeff Kirsher 
7a6a5580cSJeff Kirsher #include <linux/kernel.h>
8a6a5580cSJeff Kirsher #include <linux/errno.h>
9a6a5580cSJeff Kirsher #include <linux/types.h>
10a6a5580cSJeff Kirsher #include <linux/pci.h>
11a6a5580cSJeff Kirsher #include <linux/netdevice.h>
12a6a5580cSJeff Kirsher 
13a6a5580cSJeff Kirsher #include "wq_enet_desc.h"
14a6a5580cSJeff Kirsher #include "rq_enet_desc.h"
15a6a5580cSJeff Kirsher #include "cq_enet_desc.h"
16a6a5580cSJeff Kirsher #include "vnic_resource.h"
17a6a5580cSJeff Kirsher #include "vnic_enet.h"
18a6a5580cSJeff Kirsher #include "vnic_dev.h"
19a6a5580cSJeff Kirsher #include "vnic_wq.h"
20a6a5580cSJeff Kirsher #include "vnic_rq.h"
21a6a5580cSJeff Kirsher #include "vnic_cq.h"
22a6a5580cSJeff Kirsher #include "vnic_intr.h"
23a6a5580cSJeff Kirsher #include "vnic_stats.h"
24a6a5580cSJeff Kirsher #include "vnic_nic.h"
25a6a5580cSJeff Kirsher #include "vnic_rss.h"
26a6a5580cSJeff Kirsher #include "enic_res.h"
27a6a5580cSJeff Kirsher #include "enic.h"
28a6a5580cSJeff Kirsher 
enic_get_vnic_config(struct enic * enic)29a6a5580cSJeff Kirsher int enic_get_vnic_config(struct enic *enic)
30a6a5580cSJeff Kirsher {
31a6a5580cSJeff Kirsher 	struct vnic_enet_config *c = &enic->config;
32a6a5580cSJeff Kirsher 	int err;
33a6a5580cSJeff Kirsher 
34b13423eeSRoopa Prabhu 	err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr);
35a6a5580cSJeff Kirsher 	if (err) {
36a6a5580cSJeff Kirsher 		dev_err(enic_get_dev(enic),
37a6a5580cSJeff Kirsher 			"Error getting MAC addr, %d\n", err);
38a6a5580cSJeff Kirsher 		return err;
39a6a5580cSJeff Kirsher 	}
40a6a5580cSJeff Kirsher 
41a6a5580cSJeff Kirsher #define GET_CONFIG(m) \
42a6a5580cSJeff Kirsher 	do { \
43a6a5580cSJeff Kirsher 		err = vnic_dev_spec(enic->vdev, \
44a6a5580cSJeff Kirsher 			offsetof(struct vnic_enet_config, m), \
45a6a5580cSJeff Kirsher 			sizeof(c->m), &c->m); \
46a6a5580cSJeff Kirsher 		if (err) { \
47a6a5580cSJeff Kirsher 			dev_err(enic_get_dev(enic), \
48a6a5580cSJeff Kirsher 				"Error getting %s, %d\n", #m, err); \
49a6a5580cSJeff Kirsher 			return err; \
50a6a5580cSJeff Kirsher 		} \
51a6a5580cSJeff Kirsher 	} while (0)
52a6a5580cSJeff Kirsher 
53a6a5580cSJeff Kirsher 	GET_CONFIG(flags);
54a6a5580cSJeff Kirsher 	GET_CONFIG(wq_desc_count);
55a6a5580cSJeff Kirsher 	GET_CONFIG(rq_desc_count);
56a6a5580cSJeff Kirsher 	GET_CONFIG(mtu);
57a6a5580cSJeff Kirsher 	GET_CONFIG(intr_timer_type);
58a6a5580cSJeff Kirsher 	GET_CONFIG(intr_mode);
59a6a5580cSJeff Kirsher 	GET_CONFIG(intr_timer_usec);
60a6a5580cSJeff Kirsher 	GET_CONFIG(loop_tag);
61a145df23SGovindarajulu Varadarajan 	GET_CONFIG(num_arfs);
62a6a5580cSJeff Kirsher 
63a6a5580cSJeff Kirsher 	c->wq_desc_count =
64a6a5580cSJeff Kirsher 		min_t(u32, ENIC_MAX_WQ_DESCS,
65a6a5580cSJeff Kirsher 		max_t(u32, ENIC_MIN_WQ_DESCS,
66a6a5580cSJeff Kirsher 		c->wq_desc_count));
67a6a5580cSJeff Kirsher 	c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
68a6a5580cSJeff Kirsher 
69a6a5580cSJeff Kirsher 	c->rq_desc_count =
70a6a5580cSJeff Kirsher 		min_t(u32, ENIC_MAX_RQ_DESCS,
71a6a5580cSJeff Kirsher 		max_t(u32, ENIC_MIN_RQ_DESCS,
72a6a5580cSJeff Kirsher 		c->rq_desc_count));
73a6a5580cSJeff Kirsher 	c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
74a6a5580cSJeff Kirsher 
75a6a5580cSJeff Kirsher 	if (c->mtu == 0)
76a6a5580cSJeff Kirsher 		c->mtu = 1500;
77a6a5580cSJeff Kirsher 	c->mtu = min_t(u16, ENIC_MAX_MTU,
78a6a5580cSJeff Kirsher 		max_t(u16, ENIC_MIN_MTU,
79a6a5580cSJeff Kirsher 		c->mtu));
80a6a5580cSJeff Kirsher 
81a6a5580cSJeff Kirsher 	c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
82a6a5580cSJeff Kirsher 		vnic_dev_get_intr_coal_timer_max(enic->vdev));
83a6a5580cSJeff Kirsher 
84a6a5580cSJeff Kirsher 	dev_info(enic_get_dev(enic),
85a6a5580cSJeff Kirsher 		"vNIC MAC addr %pM wq/rq %d/%d mtu %d\n",
86a6a5580cSJeff Kirsher 		enic->mac_addr, c->wq_desc_count, c->rq_desc_count, c->mtu);
87a6a5580cSJeff Kirsher 
88a6a5580cSJeff Kirsher 	dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
89a6a5580cSJeff Kirsher 		"tso/lro %s/%s rss %s intr mode %s type %s timer %d usec "
90a6a5580cSJeff Kirsher 		"loopback tag 0x%04x\n",
91a6a5580cSJeff Kirsher 		ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
92a6a5580cSJeff Kirsher 		ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
93a6a5580cSJeff Kirsher 		ENIC_SETTING(enic, TSO) ? "yes" : "no",
94a6a5580cSJeff Kirsher 		ENIC_SETTING(enic, LRO) ? "yes" : "no",
95a6a5580cSJeff Kirsher 		ENIC_SETTING(enic, RSS) ? "yes" : "no",
96a6a5580cSJeff Kirsher 		c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
97a6a5580cSJeff Kirsher 		c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
98a6a5580cSJeff Kirsher 		c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
99a6a5580cSJeff Kirsher 		"unknown",
100a6a5580cSJeff Kirsher 		c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
101a6a5580cSJeff Kirsher 		c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
102a6a5580cSJeff Kirsher 		"unknown",
103a6a5580cSJeff Kirsher 		c->intr_timer_usec,
104a6a5580cSJeff Kirsher 		c->loop_tag);
105a6a5580cSJeff Kirsher 
106a6a5580cSJeff Kirsher 	return 0;
107a6a5580cSJeff Kirsher }
108a6a5580cSJeff Kirsher 
enic_add_vlan(struct enic * enic,u16 vlanid)109a6a5580cSJeff Kirsher int enic_add_vlan(struct enic *enic, u16 vlanid)
110a6a5580cSJeff Kirsher {
111a6a5580cSJeff Kirsher 	u64 a0 = vlanid, a1 = 0;
112a6a5580cSJeff Kirsher 	int wait = 1000;
113a6a5580cSJeff Kirsher 	int err;
114a6a5580cSJeff Kirsher 
115a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait);
116a6a5580cSJeff Kirsher 	if (err)
117a6a5580cSJeff Kirsher 		dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err);
118a6a5580cSJeff Kirsher 
119a6a5580cSJeff Kirsher 	return err;
120a6a5580cSJeff Kirsher }
121a6a5580cSJeff Kirsher 
enic_del_vlan(struct enic * enic,u16 vlanid)122a6a5580cSJeff Kirsher int enic_del_vlan(struct enic *enic, u16 vlanid)
123a6a5580cSJeff Kirsher {
124a6a5580cSJeff Kirsher 	u64 a0 = vlanid, a1 = 0;
125a6a5580cSJeff Kirsher 	int wait = 1000;
126a6a5580cSJeff Kirsher 	int err;
127a6a5580cSJeff Kirsher 
128a6a5580cSJeff Kirsher 	err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait);
129a6a5580cSJeff Kirsher 	if (err)
130a6a5580cSJeff Kirsher 		dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err);
131a6a5580cSJeff Kirsher 
132a6a5580cSJeff Kirsher 	return err;
133a6a5580cSJeff Kirsher }
134a6a5580cSJeff Kirsher 
enic_set_nic_cfg(struct enic * enic,u8 rss_default_cpu,u8 rss_hash_type,u8 rss_hash_bits,u8 rss_base_cpu,u8 rss_enable,u8 tso_ipid_split_en,u8 ig_vlan_strip_en)135a6a5580cSJeff Kirsher int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
136a6a5580cSJeff Kirsher 	u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
137a6a5580cSJeff Kirsher 	u8 ig_vlan_strip_en)
138a6a5580cSJeff Kirsher {
1394016a7f1SGovindarajulu Varadarajan 	enum vnic_devcmd_cmd cmd = CMD_NIC_CFG;
140a6a5580cSJeff Kirsher 	u64 a0, a1;
141a6a5580cSJeff Kirsher 	u32 nic_cfg;
142a6a5580cSJeff Kirsher 	int wait = 1000;
143a6a5580cSJeff Kirsher 
144a6a5580cSJeff Kirsher 	vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
145a6a5580cSJeff Kirsher 		rss_hash_type, rss_hash_bits, rss_base_cpu,
146a6a5580cSJeff Kirsher 		rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
147a6a5580cSJeff Kirsher 
148a6a5580cSJeff Kirsher 	a0 = nic_cfg;
149a6a5580cSJeff Kirsher 	a1 = 0;
150a6a5580cSJeff Kirsher 
1514016a7f1SGovindarajulu Varadarajan 	if (rss_hash_type & (NIC_CFG_RSS_HASH_TYPE_UDP_IPV4 |
1524016a7f1SGovindarajulu Varadarajan 			     NIC_CFG_RSS_HASH_TYPE_UDP_IPV6))
1534016a7f1SGovindarajulu Varadarajan 		cmd = CMD_NIC_CFG_CHK;
1544016a7f1SGovindarajulu Varadarajan 
1554016a7f1SGovindarajulu Varadarajan 	return vnic_dev_cmd(enic->vdev, cmd, &a0, &a1, wait);
156a6a5580cSJeff Kirsher }
157a6a5580cSJeff Kirsher 
enic_set_rss_key(struct enic * enic,dma_addr_t key_pa,u64 len)158a6a5580cSJeff Kirsher int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len)
159a6a5580cSJeff Kirsher {
160a6a5580cSJeff Kirsher 	u64 a0 = (u64)key_pa, a1 = len;
161a6a5580cSJeff Kirsher 	int wait = 1000;
162a6a5580cSJeff Kirsher 
163a6a5580cSJeff Kirsher 	return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait);
164a6a5580cSJeff Kirsher }
165a6a5580cSJeff Kirsher 
enic_set_rss_cpu(struct enic * enic,dma_addr_t cpu_pa,u64 len)166a6a5580cSJeff Kirsher int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len)
167a6a5580cSJeff Kirsher {
168a6a5580cSJeff Kirsher 	u64 a0 = (u64)cpu_pa, a1 = len;
169a6a5580cSJeff Kirsher 	int wait = 1000;
170a6a5580cSJeff Kirsher 
171a6a5580cSJeff Kirsher 	return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait);
172a6a5580cSJeff Kirsher }
173a6a5580cSJeff Kirsher 
enic_free_vnic_resources(struct enic * enic)174a6a5580cSJeff Kirsher void enic_free_vnic_resources(struct enic *enic)
175a6a5580cSJeff Kirsher {
176a6a5580cSJeff Kirsher 	unsigned int i;
177a6a5580cSJeff Kirsher 
178a6a5580cSJeff Kirsher 	for (i = 0; i < enic->wq_count; i++)
179a6a5580cSJeff Kirsher 		vnic_wq_free(&enic->wq[i]);
180a6a5580cSJeff Kirsher 	for (i = 0; i < enic->rq_count; i++)
181a6a5580cSJeff Kirsher 		vnic_rq_free(&enic->rq[i]);
182a6a5580cSJeff Kirsher 	for (i = 0; i < enic->cq_count; i++)
183a6a5580cSJeff Kirsher 		vnic_cq_free(&enic->cq[i]);
184a6a5580cSJeff Kirsher 	for (i = 0; i < enic->intr_count; i++)
185a6a5580cSJeff Kirsher 		vnic_intr_free(&enic->intr[i]);
186a6a5580cSJeff Kirsher }
187a6a5580cSJeff Kirsher 
enic_get_res_counts(struct enic * enic)188a6a5580cSJeff Kirsher void enic_get_res_counts(struct enic *enic)
189a6a5580cSJeff Kirsher {
190a6a5580cSJeff Kirsher 	enic->wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
191a6a5580cSJeff Kirsher 	enic->rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
192a6a5580cSJeff Kirsher 	enic->cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
193a6a5580cSJeff Kirsher 	enic->intr_count = vnic_dev_get_res_count(enic->vdev,
194a6a5580cSJeff Kirsher 		RES_TYPE_INTR_CTRL);
195a6a5580cSJeff Kirsher 
196a6a5580cSJeff Kirsher 	dev_info(enic_get_dev(enic),
197a6a5580cSJeff Kirsher 		"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
198a6a5580cSJeff Kirsher 		enic->wq_count, enic->rq_count,
199a6a5580cSJeff Kirsher 		enic->cq_count, enic->intr_count);
200a6a5580cSJeff Kirsher }
201a6a5580cSJeff Kirsher 
enic_init_vnic_resources(struct enic * enic)202a6a5580cSJeff Kirsher void enic_init_vnic_resources(struct enic *enic)
203a6a5580cSJeff Kirsher {
204a6a5580cSJeff Kirsher 	enum vnic_dev_intr_mode intr_mode;
205a6a5580cSJeff Kirsher 	unsigned int mask_on_assertion;
206a6a5580cSJeff Kirsher 	unsigned int interrupt_offset;
207a6a5580cSJeff Kirsher 	unsigned int error_interrupt_enable;
208a6a5580cSJeff Kirsher 	unsigned int error_interrupt_offset;
209a6a5580cSJeff Kirsher 	unsigned int cq_index;
210a6a5580cSJeff Kirsher 	unsigned int i;
211a6a5580cSJeff Kirsher 
212a6a5580cSJeff Kirsher 	intr_mode = vnic_dev_get_intr_mode(enic->vdev);
213a6a5580cSJeff Kirsher 
214a6a5580cSJeff Kirsher 	/* Init RQ/WQ resources.
215a6a5580cSJeff Kirsher 	 *
216a6a5580cSJeff Kirsher 	 * RQ[0 - n-1] point to CQ[0 - n-1]
217a6a5580cSJeff Kirsher 	 * WQ[0 - m-1] point to CQ[n - n+m-1]
218a6a5580cSJeff Kirsher 	 *
219a6a5580cSJeff Kirsher 	 * Error interrupt is not enabled for MSI.
220a6a5580cSJeff Kirsher 	 */
221a6a5580cSJeff Kirsher 
222a6a5580cSJeff Kirsher 	switch (intr_mode) {
223a6a5580cSJeff Kirsher 	case VNIC_DEV_INTR_MODE_INTX:
224a6a5580cSJeff Kirsher 	case VNIC_DEV_INTR_MODE_MSIX:
225a6a5580cSJeff Kirsher 		error_interrupt_enable = 1;
226a6a5580cSJeff Kirsher 		error_interrupt_offset = enic->intr_count - 2;
227a6a5580cSJeff Kirsher 		break;
228a6a5580cSJeff Kirsher 	default:
229a6a5580cSJeff Kirsher 		error_interrupt_enable = 0;
230a6a5580cSJeff Kirsher 		error_interrupt_offset = 0;
231a6a5580cSJeff Kirsher 		break;
232a6a5580cSJeff Kirsher 	}
233a6a5580cSJeff Kirsher 
234a6a5580cSJeff Kirsher 	for (i = 0; i < enic->rq_count; i++) {
235a6a5580cSJeff Kirsher 		cq_index = i;
236a6a5580cSJeff Kirsher 		vnic_rq_init(&enic->rq[i],
237a6a5580cSJeff Kirsher 			cq_index,
238a6a5580cSJeff Kirsher 			error_interrupt_enable,
239a6a5580cSJeff Kirsher 			error_interrupt_offset);
240a6a5580cSJeff Kirsher 	}
241a6a5580cSJeff Kirsher 
242a6a5580cSJeff Kirsher 	for (i = 0; i < enic->wq_count; i++) {
243a6a5580cSJeff Kirsher 		cq_index = enic->rq_count + i;
244a6a5580cSJeff Kirsher 		vnic_wq_init(&enic->wq[i],
245a6a5580cSJeff Kirsher 			cq_index,
246a6a5580cSJeff Kirsher 			error_interrupt_enable,
247a6a5580cSJeff Kirsher 			error_interrupt_offset);
248a6a5580cSJeff Kirsher 	}
249a6a5580cSJeff Kirsher 
250a6a5580cSJeff Kirsher 	/* Init CQ resources
251a6a5580cSJeff Kirsher 	 *
252a6a5580cSJeff Kirsher 	 * CQ[0 - n+m-1] point to INTR[0] for INTx, MSI
253a6a5580cSJeff Kirsher 	 * CQ[0 - n+m-1] point to INTR[0 - n+m-1] for MSI-X
254a6a5580cSJeff Kirsher 	 */
255a6a5580cSJeff Kirsher 
256a6a5580cSJeff Kirsher 	for (i = 0; i < enic->cq_count; i++) {
257a6a5580cSJeff Kirsher 
258a6a5580cSJeff Kirsher 		switch (intr_mode) {
259a6a5580cSJeff Kirsher 		case VNIC_DEV_INTR_MODE_MSIX:
260a6a5580cSJeff Kirsher 			interrupt_offset = i;
261a6a5580cSJeff Kirsher 			break;
262a6a5580cSJeff Kirsher 		default:
263a6a5580cSJeff Kirsher 			interrupt_offset = 0;
264a6a5580cSJeff Kirsher 			break;
265a6a5580cSJeff Kirsher 		}
266a6a5580cSJeff Kirsher 
267a6a5580cSJeff Kirsher 		vnic_cq_init(&enic->cq[i],
268a6a5580cSJeff Kirsher 			0 /* flow_control_enable */,
269a6a5580cSJeff Kirsher 			1 /* color_enable */,
270a6a5580cSJeff Kirsher 			0 /* cq_head */,
271a6a5580cSJeff Kirsher 			0 /* cq_tail */,
272a6a5580cSJeff Kirsher 			1 /* cq_tail_color */,
273a6a5580cSJeff Kirsher 			1 /* interrupt_enable */,
274a6a5580cSJeff Kirsher 			1 /* cq_entry_enable */,
275a6a5580cSJeff Kirsher 			0 /* cq_message_enable */,
276a6a5580cSJeff Kirsher 			interrupt_offset,
277a6a5580cSJeff Kirsher 			0 /* cq_message_addr */);
278a6a5580cSJeff Kirsher 	}
279a6a5580cSJeff Kirsher 
280a6a5580cSJeff Kirsher 	/* Init INTR resources
281a6a5580cSJeff Kirsher 	 *
282a6a5580cSJeff Kirsher 	 * mask_on_assertion is not used for INTx due to the level-
283a6a5580cSJeff Kirsher 	 * triggered nature of INTx
284a6a5580cSJeff Kirsher 	 */
285a6a5580cSJeff Kirsher 
286a6a5580cSJeff Kirsher 	switch (intr_mode) {
287a6a5580cSJeff Kirsher 	case VNIC_DEV_INTR_MODE_MSI:
288a6a5580cSJeff Kirsher 	case VNIC_DEV_INTR_MODE_MSIX:
289a6a5580cSJeff Kirsher 		mask_on_assertion = 1;
290a6a5580cSJeff Kirsher 		break;
291a6a5580cSJeff Kirsher 	default:
292a6a5580cSJeff Kirsher 		mask_on_assertion = 0;
293a6a5580cSJeff Kirsher 		break;
294a6a5580cSJeff Kirsher 	}
295a6a5580cSJeff Kirsher 
296a6a5580cSJeff Kirsher 	for (i = 0; i < enic->intr_count; i++) {
297a6a5580cSJeff Kirsher 		vnic_intr_init(&enic->intr[i],
298a6a5580cSJeff Kirsher 			enic->config.intr_timer_usec,
299a6a5580cSJeff Kirsher 			enic->config.intr_timer_type,
300a6a5580cSJeff Kirsher 			mask_on_assertion);
301a6a5580cSJeff Kirsher 	}
302a6a5580cSJeff Kirsher }
303a6a5580cSJeff Kirsher 
enic_alloc_vnic_resources(struct enic * enic)304a6a5580cSJeff Kirsher int enic_alloc_vnic_resources(struct enic *enic)
305a6a5580cSJeff Kirsher {
306a6a5580cSJeff Kirsher 	enum vnic_dev_intr_mode intr_mode;
307a6a5580cSJeff Kirsher 	unsigned int i;
308a6a5580cSJeff Kirsher 	int err;
309a6a5580cSJeff Kirsher 
310a6a5580cSJeff Kirsher 	intr_mode = vnic_dev_get_intr_mode(enic->vdev);
311a6a5580cSJeff Kirsher 
312a6a5580cSJeff Kirsher 	dev_info(enic_get_dev(enic), "vNIC resources used:  "
313a6a5580cSJeff Kirsher 		"wq %d rq %d cq %d intr %d intr mode %s\n",
314a6a5580cSJeff Kirsher 		enic->wq_count, enic->rq_count,
315a6a5580cSJeff Kirsher 		enic->cq_count, enic->intr_count,
316a6a5580cSJeff Kirsher 		intr_mode == VNIC_DEV_INTR_MODE_INTX ? "legacy PCI INTx" :
317a6a5580cSJeff Kirsher 		intr_mode == VNIC_DEV_INTR_MODE_MSI ? "MSI" :
318a6a5580cSJeff Kirsher 		intr_mode == VNIC_DEV_INTR_MODE_MSIX ? "MSI-X" :
319a6a5580cSJeff Kirsher 		"unknown");
320a6a5580cSJeff Kirsher 
321a6a5580cSJeff Kirsher 	/* Allocate queue resources
322a6a5580cSJeff Kirsher 	 */
323a6a5580cSJeff Kirsher 
324a6a5580cSJeff Kirsher 	for (i = 0; i < enic->wq_count; i++) {
325a6a5580cSJeff Kirsher 		err = vnic_wq_alloc(enic->vdev, &enic->wq[i], i,
326a6a5580cSJeff Kirsher 			enic->config.wq_desc_count,
327a6a5580cSJeff Kirsher 			sizeof(struct wq_enet_desc));
328a6a5580cSJeff Kirsher 		if (err)
329a6a5580cSJeff Kirsher 			goto err_out_cleanup;
330a6a5580cSJeff Kirsher 	}
331a6a5580cSJeff Kirsher 
332a6a5580cSJeff Kirsher 	for (i = 0; i < enic->rq_count; i++) {
333a6a5580cSJeff Kirsher 		err = vnic_rq_alloc(enic->vdev, &enic->rq[i], i,
334a6a5580cSJeff Kirsher 			enic->config.rq_desc_count,
335a6a5580cSJeff Kirsher 			sizeof(struct rq_enet_desc));
336a6a5580cSJeff Kirsher 		if (err)
337a6a5580cSJeff Kirsher 			goto err_out_cleanup;
338a6a5580cSJeff Kirsher 	}
339a6a5580cSJeff Kirsher 
340a6a5580cSJeff Kirsher 	for (i = 0; i < enic->cq_count; i++) {
341a6a5580cSJeff Kirsher 		if (i < enic->rq_count)
342a6a5580cSJeff Kirsher 			err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
343a6a5580cSJeff Kirsher 				enic->config.rq_desc_count,
344a6a5580cSJeff Kirsher 				sizeof(struct cq_enet_rq_desc));
345a6a5580cSJeff Kirsher 		else
346a6a5580cSJeff Kirsher 			err = vnic_cq_alloc(enic->vdev, &enic->cq[i], i,
347a6a5580cSJeff Kirsher 				enic->config.wq_desc_count,
348a6a5580cSJeff Kirsher 				sizeof(struct cq_enet_wq_desc));
349a6a5580cSJeff Kirsher 		if (err)
350a6a5580cSJeff Kirsher 			goto err_out_cleanup;
351a6a5580cSJeff Kirsher 	}
352a6a5580cSJeff Kirsher 
353a6a5580cSJeff Kirsher 	for (i = 0; i < enic->intr_count; i++) {
354a6a5580cSJeff Kirsher 		err = vnic_intr_alloc(enic->vdev, &enic->intr[i], i);
355a6a5580cSJeff Kirsher 		if (err)
356a6a5580cSJeff Kirsher 			goto err_out_cleanup;
357a6a5580cSJeff Kirsher 	}
358a6a5580cSJeff Kirsher 
359a6a5580cSJeff Kirsher 	/* Hook remaining resource
360a6a5580cSJeff Kirsher 	 */
361a6a5580cSJeff Kirsher 
362a6a5580cSJeff Kirsher 	enic->legacy_pba = vnic_dev_get_res(enic->vdev,
363a6a5580cSJeff Kirsher 		RES_TYPE_INTR_PBA_LEGACY, 0);
364a6a5580cSJeff Kirsher 	if (!enic->legacy_pba && intr_mode == VNIC_DEV_INTR_MODE_INTX) {
365a6a5580cSJeff Kirsher 		dev_err(enic_get_dev(enic),
366a6a5580cSJeff Kirsher 			"Failed to hook legacy pba resource\n");
367a6a5580cSJeff Kirsher 		err = -ENODEV;
368a6a5580cSJeff Kirsher 		goto err_out_cleanup;
369a6a5580cSJeff Kirsher 	}
370a6a5580cSJeff Kirsher 
371a6a5580cSJeff Kirsher 	return 0;
372a6a5580cSJeff Kirsher 
373a6a5580cSJeff Kirsher err_out_cleanup:
374a6a5580cSJeff Kirsher 	enic_free_vnic_resources(enic);
375a6a5580cSJeff Kirsher 
376a6a5580cSJeff Kirsher 	return err;
377a6a5580cSJeff Kirsher }
378