xref: /freebsd/sys/dev/cxgbe/common/t4vf_hw.c (revision 5bb3134a8c21cb87b30e135ef168483f0333dabb)
1 /*-
2  * Copyright (c) 2016 Chelsio Communications, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include "common.h"
31 #include "t4_regs.h"
32 #include "t4_regs_values.h"
33 
34 #undef msleep
35 #define msleep(x) do { \
36 	if (cold) \
37 		DELAY((x) * 1000); \
38 	else \
39 		pause("t4hw", (x) * hz / 1000); \
40 } while (0)
41 
42 /*
43  * Wait for the device to become ready (signified by our "who am I" register
44  * returning a value other than all 1's).  Return an error if it doesn't
45  * become ready ...
46  */
47 int t4vf_wait_dev_ready(struct adapter *adapter)
48 {
49 	const u32 whoami = VF_PL_REG(A_PL_VF_WHOAMI);
50 	const u32 notready1 = 0xffffffff;
51 	const u32 notready2 = 0xeeeeeeee;
52 	u32 val;
53 
54 	val = t4_read_reg(adapter, whoami);
55 	if (val != notready1 && val != notready2)
56 		return 0;
57 	msleep(500);
58 	val = t4_read_reg(adapter, whoami);
59 	if (val != notready1 && val != notready2)
60 		return 0;
61 	else
62 		return -EIO;
63 }
64 
65 
66 /**
67  *      t4vf_fw_reset - issue a reset to FW
68  *      @adapter: the adapter
69  *
70  *	Issues a reset command to FW.  For a Physical Function this would
71  *	result in the Firmware reseting all of its state.  For a Virtual
72  *	Function this just resets the state associated with the VF.
73  */
74 int t4vf_fw_reset(struct adapter *adapter)
75 {
76 	struct fw_reset_cmd cmd;
77 
78 	memset(&cmd, 0, sizeof(cmd));
79 	cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RESET_CMD) |
80 				      F_FW_CMD_WRITE);
81 	cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(FW_LEN16(cmd)));
82 	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
83 }
84 
85 /**
86  *	t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
87  *	@adapter: the adapter
88  *
89  *	Retrieves various core SGE parameters in the form of hardware SGE
90  *	register values.  The caller is responsible for decoding these as
91  *	needed.  The SGE parameters are stored in @adapter->params.sge.
92  */
93 int t4vf_get_sge_params(struct adapter *adapter)
94 {
95 	struct sge_params *sp = &adapter->params.sge;
96 	u32 params[7], vals[7];
97 	u32 whoami;
98 	unsigned int pf, s_hps;
99 	int i, v;
100 
101 	params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
102 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL));
103 	params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
104 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE));
105 	params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
106 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1));
107 	params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
108 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3));
109 	params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
110 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5));
111 	params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
112 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL));
113 	params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
114 		     V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD));
115 	v = t4vf_query_params(adapter, 7, params, vals);
116 	if (v != FW_SUCCESS)
117 		return v;
118 
119 	sp->sge_control = vals[0];
120 	sp->counter_val[0] = G_THRESHOLD_0(vals[6]);
121 	sp->counter_val[1] = G_THRESHOLD_1(vals[6]);
122 	sp->counter_val[2] = G_THRESHOLD_2(vals[6]);
123 	sp->counter_val[3] = G_THRESHOLD_3(vals[6]);
124 	sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2]));
125 	sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2]));
126 	sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3]));
127 	sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3]));
128 	sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4]));
129 	sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4]));
130 
131 	sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1;
132 	if (is_t4(adapter))
133 		sp->fl_starve_threshold2 = sp->fl_starve_threshold;
134 	else if (is_t5(adapter))
135 		sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1;
136 	else
137 		sp->fl_starve_threshold2 = G_T6_EGRTHRESHOLDPACKING(vals[5]) * 2 + 1;
138 
139 	/*
140 	 * We need the Queues/Page and Host Page Size for our VF.
141 	 * This is based on the PF from which we're instantiated.
142 	 */
143 	whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI));
144 	pf = G_SOURCEPF(whoami);
145 
146 	s_hps = (S_HOSTPAGESIZEPF0 +
147 	    (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf);
148 	sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10;
149 
150 	for (i = 0; i < SGE_FLBUF_SIZES; i++) {
151 		params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
152 		    V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i)));
153 		v = t4vf_query_params(adapter, 1, params, vals);
154 		if (v != FW_SUCCESS)
155 			return v;
156 
157 		sp->sge_fl_buffer_size[i] = vals[0];
158 	}
159 
160 	/*
161 	 * T4 uses a single control field to specify both the PCIe Padding and
162 	 * Packing Boundary.  T5 introduced the ability to specify these
163 	 * separately with the Padding Boundary in SGE_CONTROL and and Packing
164 	 * Boundary in SGE_CONTROL2.  So for T5 and later we need to grab
165 	 * SGE_CONTROL in order to determine how ingress packet data will be
166 	 * laid out in Packed Buffer Mode.  Unfortunately, older versions of
167 	 * the firmware won't let us retrieve SGE_CONTROL2 so if we get a
168 	 * failure grabbing it we throw an error since we can't figure out the
169 	 * right value.
170 	 */
171 	sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64;
172 	sp->fl_pktshift = G_PKTSHIFT(sp->sge_control);
173 	if (chip_id(adapter) <= CHELSIO_T5) {
174 		sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) +
175 		    X_INGPADBOUNDARY_SHIFT);
176 	} else {
177 		sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) +
178 		    X_T6_INGPADBOUNDARY_SHIFT);
179 	}
180 	if (is_t4(adapter))
181 		sp->pack_boundary = sp->pad_boundary;
182 	else {
183 		params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
184 			     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2));
185 		v = t4vf_query_params(adapter, 1, params, vals);
186 		if (v != FW_SUCCESS) {
187 			CH_ERR(adapter, "Unable to get SGE Control2; "
188 			       "probably old firmware.\n");
189 			return v;
190 		}
191 		if (G_INGPACKBOUNDARY(vals[0]) == 0)
192 			sp->pack_boundary = 16;
193 		else
194 			sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) +
195 			    5);
196 	}
197 
198 	/*
199 	 * For T5 and later we want to use the new BAR2 Doorbells.
200 	 * Unfortunately, older firmware didn't allow the this register to be
201 	 * read.
202 	 */
203 	if (!is_t4(adapter)) {
204 		unsigned int s_qpp;
205 
206 		params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
207 			     V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF));
208 		params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
209 			     V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF));
210 		v = t4vf_query_params(adapter, 2, params, vals);
211 		if (v != FW_SUCCESS) {
212 			CH_WARN(adapter, "Unable to get VF SGE Queues/Page; "
213 				"probably old firmware.\n");
214 			return v;
215 		}
216 
217 		s_qpp = (S_QUEUESPERPAGEPF0 +
218 			 (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf);
219 		sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0);
220 		sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0);
221 	}
222 
223 	return 0;
224 }
225 
226 /**
227  *	t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration
228  *	@adapter: the adapter
229  *
230  *	Retrieves global RSS mode and parameters with which we have to live
231  *	and stores them in the @adapter's RSS parameters.
232  */
233 int t4vf_get_rss_glb_config(struct adapter *adapter)
234 {
235 	struct rss_params *rss = &adapter->params.rss;
236 	struct fw_rss_glb_config_cmd cmd, rpl;
237 	int v;
238 
239 	/*
240 	 * Execute an RSS Global Configuration read command to retrieve
241 	 * our RSS configuration.
242 	 */
243 	memset(&cmd, 0, sizeof(cmd));
244 	cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
245 				      F_FW_CMD_REQUEST |
246 				      F_FW_CMD_READ);
247 	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
248 	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
249 	if (v != FW_SUCCESS)
250 		return v;
251 
252 	/*
253 	 * Transate the big-endian RSS Global Configuration into our
254 	 * cpu-endian format based on the RSS mode.  We also do first level
255 	 * filtering at this point to weed out modes which don't support
256 	 * VF Drivers ...
257 	 */
258 	rss->mode = G_FW_RSS_GLB_CONFIG_CMD_MODE(
259 			be32_to_cpu(rpl.u.manual.mode_pkd));
260 	switch (rss->mode) {
261 	case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: {
262 		u32 word = be32_to_cpu(
263 				rpl.u.basicvirtual.synmapen_to_hashtoeplitz);
264 
265 		rss->u.basicvirtual.synmapen =
266 			((word & F_FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0);
267 		rss->u.basicvirtual.syn4tupenipv6 =
268 			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0);
269 		rss->u.basicvirtual.syn2tupenipv6 =
270 			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0);
271 		rss->u.basicvirtual.syn4tupenipv4 =
272 			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0);
273 		rss->u.basicvirtual.syn2tupenipv4 =
274 			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0);
275 
276 		rss->u.basicvirtual.ofdmapen =
277 			((word & F_FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0);
278 
279 		rss->u.basicvirtual.tnlmapen =
280 			((word & F_FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0);
281 		rss->u.basicvirtual.tnlalllookup =
282 			((word  & F_FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0);
283 
284 		rss->u.basicvirtual.hashtoeplitz =
285 			((word & F_FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0);
286 
287 		/* we need at least Tunnel Map Enable to be set */
288 		if (!rss->u.basicvirtual.tnlmapen)
289 			return -EINVAL;
290 		break;
291 	}
292 
293 	default:
294 		/* all unknown/unsupported RSS modes result in an error */
295 		return -EINVAL;
296 	}
297 
298 	return 0;
299 }
300 
301 /**
302  *	t4vf_get_vfres - retrieve VF resource limits
303  *	@adapter: the adapter
304  *
305  *	Retrieves configured resource limits and capabilities for a virtual
306  *	function.  The results are stored in @adapter->vfres.
307  */
308 int t4vf_get_vfres(struct adapter *adapter)
309 {
310 	struct vf_resources *vfres = &adapter->params.vfres;
311 	struct fw_pfvf_cmd cmd, rpl;
312 	int v;
313 	u32 word;
314 
315 	/*
316 	 * Execute PFVF Read command to get VF resource limits; bail out early
317 	 * with error on command failure.
318 	 */
319 	memset(&cmd, 0, sizeof(cmd));
320 	cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) |
321 				    F_FW_CMD_REQUEST |
322 				    F_FW_CMD_READ);
323 	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
324 	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
325 	if (v != FW_SUCCESS)
326 		return v;
327 
328 	/*
329 	 * Extract VF resource limits and return success.
330 	 */
331 	word = be32_to_cpu(rpl.niqflint_niq);
332 	vfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word);
333 	vfres->niq = G_FW_PFVF_CMD_NIQ(word);
334 
335 	word = be32_to_cpu(rpl.type_to_neq);
336 	vfres->neq = G_FW_PFVF_CMD_NEQ(word);
337 	vfres->pmask = G_FW_PFVF_CMD_PMASK(word);
338 
339 	word = be32_to_cpu(rpl.tc_to_nexactf);
340 	vfres->tc = G_FW_PFVF_CMD_TC(word);
341 	vfres->nvi = G_FW_PFVF_CMD_NVI(word);
342 	vfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word);
343 
344 	word = be32_to_cpu(rpl.r_caps_to_nethctrl);
345 	vfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word);
346 	vfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word);
347 	vfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word);
348 
349 	return 0;
350 }
351 
352 /**
353  */
354 int t4vf_prep_adapter(struct adapter *adapter)
355 {
356 	int err;
357 
358 	/*
359 	 * Wait for the device to become ready before proceeding ...
360 	 */
361 	err = t4vf_wait_dev_ready(adapter);
362 	if (err)
363 		return err;
364 
365 	adapter->params.chipid = pci_get_device(adapter->dev) >> 12;
366 	if (adapter->params.chipid >= 0xa) {
367 		adapter->params.chipid -= (0xa - 0x4);
368 		adapter->params.fpga = 1;
369 	}
370 
371 	/*
372 	 * Default port and clock for debugging in case we can't reach
373 	 * firmware.
374 	 */
375 	adapter->params.nports = 1;
376 	adapter->params.vfres.pmask = 1;
377 	adapter->params.vpd.cclk = 50000;
378 
379 	adapter->chip_params = t4_get_chip_params(chip_id(adapter));
380 	if (adapter->chip_params == NULL)
381 		return -EINVAL;
382 
383 	return 0;
384 }
385 
386 /*
387  *	t4vf_get_vf_mac - Get the MAC address to be set to the VI of this VF.
388  *	@adapter: The adapter
389  *	@port: The port associated with vf
390  *	@naddr: the number of ACL MAC addresses returned in addr
391  *	@addr: Placeholder for MAC addresses
392  *
393  *	Find the MAC address to be set to the VF's VI. The requested MAC address
394  *	is from the host OS via callback in the PF driver.
395  */
396 int t4vf_get_vf_mac(struct adapter *adapter, unsigned int port,
397 		    unsigned int *naddr, u8 *addr)
398 {
399 	struct fw_acl_mac_cmd cmd;
400 	int ret;
401 
402 	memset(&cmd, 0, sizeof(cmd));
403 	cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_ACL_MAC_CMD) |
404 			      F_FW_CMD_REQUEST |
405 			      F_FW_CMD_READ);
406 	cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
407 	ret = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &cmd);
408 	if (ret)
409 		return ret;
410 
411 	if (cmd.nmac < *naddr)
412 		*naddr = cmd.nmac;
413 
414 	switch (port) {
415 	case 3:
416 		memcpy(addr, cmd.macaddr3, sizeof(cmd.macaddr3));
417 		break;
418 	case 2:
419 		memcpy(addr, cmd.macaddr2, sizeof(cmd.macaddr2));
420 		break;
421 	case 1:
422 		memcpy(addr, cmd.macaddr1, sizeof(cmd.macaddr1));
423 		break;
424 	case 0:
425 		memcpy(addr, cmd.macaddr0, sizeof(cmd.macaddr0));
426 		break;
427 	}
428 
429 	return ret;
430 }
431