xref: /freebsd/sys/dev/enic/enic_res.c (revision 9c067b844f85a224f0416e6eb46ba3ef82aec5c4)
1*9c067b84SDoug Ambrisko /* SPDX-License-Identifier: BSD-3-Clause
2*9c067b84SDoug Ambrisko  * Copyright 2008-2017 Cisco Systems, Inc.  All rights reserved.
3*9c067b84SDoug Ambrisko  * Copyright 2007 Nuova Systems, Inc.  All rights reserved.
4*9c067b84SDoug Ambrisko  */
5*9c067b84SDoug Ambrisko 
6*9c067b84SDoug Ambrisko #include "enic.h"
7*9c067b84SDoug Ambrisko #include "enic_compat.h"
8*9c067b84SDoug Ambrisko #include "wq_enet_desc.h"
9*9c067b84SDoug Ambrisko #include "rq_enet_desc.h"
10*9c067b84SDoug Ambrisko #include "cq_enet_desc.h"
11*9c067b84SDoug Ambrisko #include "vnic_resource.h"
12*9c067b84SDoug Ambrisko #include "vnic_enet.h"
13*9c067b84SDoug Ambrisko #include "vnic_dev.h"
14*9c067b84SDoug Ambrisko #include "vnic_wq.h"
15*9c067b84SDoug Ambrisko #include "vnic_rq.h"
16*9c067b84SDoug Ambrisko #include "vnic_cq.h"
17*9c067b84SDoug Ambrisko #include "vnic_intr.h"
18*9c067b84SDoug Ambrisko #include "vnic_stats.h"
19*9c067b84SDoug Ambrisko #include "vnic_nic.h"
20*9c067b84SDoug Ambrisko #include "vnic_rss.h"
21*9c067b84SDoug Ambrisko #include "enic_res.h"
22*9c067b84SDoug Ambrisko #include "enic.h"
23*9c067b84SDoug Ambrisko 
24*9c067b84SDoug Ambrisko int enic_get_vnic_config(struct enic *enic)
25*9c067b84SDoug Ambrisko {
26*9c067b84SDoug Ambrisko 	struct vnic_enet_config *c = &enic->config;
27*9c067b84SDoug Ambrisko 	int err;
28*9c067b84SDoug Ambrisko 	err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr);
29*9c067b84SDoug Ambrisko 	if (err) {
30*9c067b84SDoug Ambrisko 		dev_err(enic_get_dev(enic),
31*9c067b84SDoug Ambrisko 			"Error getting MAC addr, %d\n", err);
32*9c067b84SDoug Ambrisko 		return err;
33*9c067b84SDoug Ambrisko 	}
34*9c067b84SDoug Ambrisko 
35*9c067b84SDoug Ambrisko #define GET_CONFIG(m) \
36*9c067b84SDoug Ambrisko 	do { \
37*9c067b84SDoug Ambrisko 		err = vnic_dev_spec(enic->vdev, \
38*9c067b84SDoug Ambrisko 			offsetof(struct vnic_enet_config, m), \
39*9c067b84SDoug Ambrisko 			sizeof(c->m), &c->m); \
40*9c067b84SDoug Ambrisko 		if (err) { \
41*9c067b84SDoug Ambrisko 			dev_err(enic_get_dev(enic), \
42*9c067b84SDoug Ambrisko 				"Error getting %s, %d\n", #m, err); \
43*9c067b84SDoug Ambrisko 			return err; \
44*9c067b84SDoug Ambrisko 		} \
45*9c067b84SDoug Ambrisko 	} while (0)
46*9c067b84SDoug Ambrisko 
47*9c067b84SDoug Ambrisko 	GET_CONFIG(flags);
48*9c067b84SDoug Ambrisko 	GET_CONFIG(wq_desc_count);
49*9c067b84SDoug Ambrisko 	GET_CONFIG(rq_desc_count);
50*9c067b84SDoug Ambrisko 	GET_CONFIG(mtu);
51*9c067b84SDoug Ambrisko 	GET_CONFIG(intr_timer_type);
52*9c067b84SDoug Ambrisko 	GET_CONFIG(intr_mode);
53*9c067b84SDoug Ambrisko 	GET_CONFIG(intr_timer_usec);
54*9c067b84SDoug Ambrisko 	GET_CONFIG(loop_tag);
55*9c067b84SDoug Ambrisko 	GET_CONFIG(num_arfs);
56*9c067b84SDoug Ambrisko 	GET_CONFIG(max_pkt_size);
57*9c067b84SDoug Ambrisko 
58*9c067b84SDoug Ambrisko 	/* max packet size is only defined in newer VIC firmware
59*9c067b84SDoug Ambrisko 	 * and will be 0 for legacy firmware and VICs
60*9c067b84SDoug Ambrisko 	 */
61*9c067b84SDoug Ambrisko 	if (c->max_pkt_size > ENIC_DEFAULT_RX_MAX_PKT_SIZE)
62*9c067b84SDoug Ambrisko 		enic->max_mtu = c->max_pkt_size - (ETHER_HDR_LEN + 4);
63*9c067b84SDoug Ambrisko 	else
64*9c067b84SDoug Ambrisko 		enic->max_mtu = ENIC_DEFAULT_RX_MAX_PKT_SIZE
65*9c067b84SDoug Ambrisko 				- (ETHER_HDR_LEN + 4);
66*9c067b84SDoug Ambrisko 	if (c->mtu == 0)
67*9c067b84SDoug Ambrisko 		c->mtu = 1500;
68*9c067b84SDoug Ambrisko 
69*9c067b84SDoug Ambrisko 	enic->adv_filters = vnic_dev_capable_adv_filters(enic->vdev);
70*9c067b84SDoug Ambrisko 
71*9c067b84SDoug Ambrisko 	err = vnic_dev_capable_filter_mode(enic->vdev, &enic->flow_filter_mode,
72*9c067b84SDoug Ambrisko 					   &enic->filter_actions);
73*9c067b84SDoug Ambrisko 	if (err) {
74*9c067b84SDoug Ambrisko 		dev_err(enic_get_dev(enic),
75*9c067b84SDoug Ambrisko 			"Error getting filter modes, %d\n", err);
76*9c067b84SDoug Ambrisko 		return err;
77*9c067b84SDoug Ambrisko 	}
78*9c067b84SDoug Ambrisko 	vnic_dev_capable_udp_rss_weak(enic->vdev, &enic->nic_cfg_chk,
79*9c067b84SDoug Ambrisko 				      &enic->udp_rss_weak);
80*9c067b84SDoug Ambrisko 
81*9c067b84SDoug Ambrisko 	c->wq_desc_count =
82*9c067b84SDoug Ambrisko 		min_t(u32, ENIC_MAX_WQ_DESCS,
83*9c067b84SDoug Ambrisko 		max_t(u32, ENIC_MIN_WQ_DESCS,
84*9c067b84SDoug Ambrisko 		c->wq_desc_count));
85*9c067b84SDoug Ambrisko 	c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
86*9c067b84SDoug Ambrisko 
87*9c067b84SDoug Ambrisko 	c->rq_desc_count =
88*9c067b84SDoug Ambrisko 		min_t(u32, ENIC_MAX_RQ_DESCS,
89*9c067b84SDoug Ambrisko 		max_t(u32, ENIC_MIN_RQ_DESCS,
90*9c067b84SDoug Ambrisko 		c->rq_desc_count));
91*9c067b84SDoug Ambrisko 	c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
92*9c067b84SDoug Ambrisko 
93*9c067b84SDoug Ambrisko 	c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
94*9c067b84SDoug Ambrisko 		vnic_dev_get_intr_coal_timer_max(enic->vdev));
95*9c067b84SDoug Ambrisko 
96*9c067b84SDoug Ambrisko 	dev_info(enic_get_dev(enic),
97*9c067b84SDoug Ambrisko 		"vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
98*9c067b84SDoug Ambrisko 		"wq/rq %d/%d mtu d, max mtu:%d\n",
99*9c067b84SDoug Ambrisko 		enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2],
100*9c067b84SDoug Ambrisko 		enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5],
101*9c067b84SDoug Ambrisko 		c->wq_desc_count, c->rq_desc_count,
102*9c067b84SDoug Ambrisko 		 /* enic->rte_dev->data->mtu, */ enic->max_mtu);
103*9c067b84SDoug Ambrisko 	dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
104*9c067b84SDoug Ambrisko 		"rss %s intr mode %s type %s timer %d usec "
105*9c067b84SDoug Ambrisko 		"loopback tag 0x%04x\n",
106*9c067b84SDoug Ambrisko 		ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
107*9c067b84SDoug Ambrisko 		ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
108*9c067b84SDoug Ambrisko 		ENIC_SETTING(enic, RSS) ?
109*9c067b84SDoug Ambrisko 			(ENIC_SETTING(enic, RSSHASH_UDPIPV4) ? "+UDP" :
110*9c067b84SDoug Ambrisko 			((enic->udp_rss_weak ? "+udp" :
111*9c067b84SDoug Ambrisko 			"yes"))) : "no",
112*9c067b84SDoug Ambrisko 		c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
113*9c067b84SDoug Ambrisko 		c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
114*9c067b84SDoug Ambrisko 		c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
115*9c067b84SDoug Ambrisko 		"unknown",
116*9c067b84SDoug Ambrisko 		c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
117*9c067b84SDoug Ambrisko 		c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
118*9c067b84SDoug Ambrisko 		"unknown",
119*9c067b84SDoug Ambrisko 		c->intr_timer_usec,
120*9c067b84SDoug Ambrisko 		c->loop_tag);
121*9c067b84SDoug Ambrisko 
122*9c067b84SDoug Ambrisko 	/* RSS settings from vNIC */
123*9c067b84SDoug Ambrisko 	enic->reta_size = ENIC_RSS_RETA_SIZE;
124*9c067b84SDoug Ambrisko 	enic->hash_key_size = ENIC_RSS_HASH_KEY_SIZE;
125*9c067b84SDoug Ambrisko 	enic->flow_type_rss_offloads = 0;
126*9c067b84SDoug Ambrisko 
127*9c067b84SDoug Ambrisko 	/* Zero offloads if RSS is not enabled */
128*9c067b84SDoug Ambrisko 	if (!ENIC_SETTING(enic, RSS))
129*9c067b84SDoug Ambrisko 		enic->flow_type_rss_offloads = 0;
130*9c067b84SDoug Ambrisko 
131*9c067b84SDoug Ambrisko 	enic->vxlan = ENIC_SETTING(enic, VXLAN) &&
132*9c067b84SDoug Ambrisko 		vnic_dev_capable_vxlan(enic->vdev);
133*9c067b84SDoug Ambrisko 	/*
134*9c067b84SDoug Ambrisko 	 * Default hardware capabilities. enic_dev_init() may add additional
135*9c067b84SDoug Ambrisko 	 * flags if it enables overlay offloads.
136*9c067b84SDoug Ambrisko 	 */
137*9c067b84SDoug Ambrisko 	enic->tx_queue_offload_capa = 0;
138*9c067b84SDoug Ambrisko 	return 0;
139*9c067b84SDoug Ambrisko }
140*9c067b84SDoug Ambrisko 
141*9c067b84SDoug Ambrisko int enic_add_vlan(struct enic *enic, u16 vlanid)
142*9c067b84SDoug Ambrisko {
143*9c067b84SDoug Ambrisko 	u64 a0 = vlanid, a1 = 0;
144*9c067b84SDoug Ambrisko 	int wait = 1000;
145*9c067b84SDoug Ambrisko 	int err;
146*9c067b84SDoug Ambrisko 
147*9c067b84SDoug Ambrisko 	err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait);
148*9c067b84SDoug Ambrisko 	if (err)
149*9c067b84SDoug Ambrisko 		dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err);
150*9c067b84SDoug Ambrisko 
151*9c067b84SDoug Ambrisko 	return err;
152*9c067b84SDoug Ambrisko }
153*9c067b84SDoug Ambrisko 
154*9c067b84SDoug Ambrisko int enic_del_vlan(struct enic *enic, u16 vlanid)
155*9c067b84SDoug Ambrisko {
156*9c067b84SDoug Ambrisko 	u64 a0 = vlanid, a1 = 0;
157*9c067b84SDoug Ambrisko 	int wait = 1000;
158*9c067b84SDoug Ambrisko 	int err;
159*9c067b84SDoug Ambrisko 
160*9c067b84SDoug Ambrisko 	err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait);
161*9c067b84SDoug Ambrisko 	if (err)
162*9c067b84SDoug Ambrisko 		dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err);
163*9c067b84SDoug Ambrisko 
164*9c067b84SDoug Ambrisko 	return err;
165*9c067b84SDoug Ambrisko }
166*9c067b84SDoug Ambrisko 
167*9c067b84SDoug Ambrisko int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
168*9c067b84SDoug Ambrisko 	u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
169*9c067b84SDoug Ambrisko 	u8 ig_vlan_strip_en)
170*9c067b84SDoug Ambrisko {
171*9c067b84SDoug Ambrisko 	enum vnic_devcmd_cmd cmd;
172*9c067b84SDoug Ambrisko 	u64 a0, a1;
173*9c067b84SDoug Ambrisko 	u32 nic_cfg;
174*9c067b84SDoug Ambrisko 	int wait = 1000;
175*9c067b84SDoug Ambrisko 
176*9c067b84SDoug Ambrisko 	vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
177*9c067b84SDoug Ambrisko 		rss_hash_type, rss_hash_bits, rss_base_cpu,
178*9c067b84SDoug Ambrisko 		rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
179*9c067b84SDoug Ambrisko 
180*9c067b84SDoug Ambrisko 	a0 = nic_cfg;
181*9c067b84SDoug Ambrisko 	a1 = 0;
182*9c067b84SDoug Ambrisko 	cmd = enic->nic_cfg_chk ? CMD_NIC_CFG_CHK : CMD_NIC_CFG;
183*9c067b84SDoug Ambrisko 	return vnic_dev_cmd(enic->vdev, cmd, &a0, &a1, wait);
184*9c067b84SDoug Ambrisko }
185*9c067b84SDoug Ambrisko 
186*9c067b84SDoug Ambrisko void enic_get_res_counts(struct enic *enic)
187*9c067b84SDoug Ambrisko {
188*9c067b84SDoug Ambrisko 	enic->conf_wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
189*9c067b84SDoug Ambrisko 	enic->conf_rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
190*9c067b84SDoug Ambrisko 	enic->conf_cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
191*9c067b84SDoug Ambrisko 	enic->conf_intr_count = vnic_dev_get_res_count(enic->vdev,
192*9c067b84SDoug Ambrisko 		RES_TYPE_INTR_CTRL);
193*9c067b84SDoug Ambrisko 
194*9c067b84SDoug Ambrisko 	dev_info(enic_get_dev(enic),
195*9c067b84SDoug Ambrisko 		"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
196*9c067b84SDoug Ambrisko 		enic->conf_wq_count, enic->conf_rq_count,
197*9c067b84SDoug Ambrisko 		enic->conf_cq_count, enic->conf_intr_count);
198*9c067b84SDoug Ambrisko 	enic->conf_rq_count = min(enic->conf_rq_count, enic->conf_wq_count);
199*9c067b84SDoug Ambrisko 	enic->conf_wq_count = enic->conf_rq_count;
200*9c067b84SDoug Ambrisko 	enic->conf_cq_count = enic->conf_rq_count + enic->conf_wq_count;
201*9c067b84SDoug Ambrisko 	dev_info(enic_get_dev(enic),
202*9c067b84SDoug Ambrisko 		"vNIC resources iflib: wq %d rq %d cq %d intr %d\n",
203*9c067b84SDoug Ambrisko 		enic->conf_wq_count, enic->conf_rq_count,
204*9c067b84SDoug Ambrisko 		enic->conf_cq_count, enic->conf_intr_count);
205*9c067b84SDoug Ambrisko 	dev_info(enic_get_dev(enic),
206*9c067b84SDoug Ambrisko 		"vNIC resources avail: wq_desc %d rq_desc %d\n",
207*9c067b84SDoug Ambrisko 		enic->config.wq_desc_count, enic->config.rq_desc_count);
208*9c067b84SDoug Ambrisko 
209*9c067b84SDoug Ambrisko 	enic->wq_count = enic->conf_wq_count;
210*9c067b84SDoug Ambrisko 	enic->rq_count = enic->conf_rq_count;
211*9c067b84SDoug Ambrisko 	enic->cq_count = enic->conf_cq_count;
212*9c067b84SDoug Ambrisko }
213