t4vf_hw.c revision 306664
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: stable/11/sys/dev/cxgbe/common/t4vf_hw.c 306664 2016-10-03 23:49:05Z jhb $");
29
30#include "common.h"
31#include "t4_regs.h"
32
33#undef msleep
34#define msleep(x) do { \
35	if (cold) \
36		DELAY((x) * 1000); \
37	else \
38		pause("t4hw", (x) * hz / 1000); \
39} while (0)
40
41/*
42 * Wait for the device to become ready (signified by our "who am I" register
43 * returning a value other than all 1's).  Return an error if it doesn't
44 * become ready ...
45 */
46int t4vf_wait_dev_ready(struct adapter *adapter)
47{
48	const u32 whoami = VF_PL_REG(A_PL_VF_WHOAMI);
49	const u32 notready1 = 0xffffffff;
50	const u32 notready2 = 0xeeeeeeee;
51	u32 val;
52
53	val = t4_read_reg(adapter, whoami);
54	if (val != notready1 && val != notready2)
55		return 0;
56	msleep(500);
57	val = t4_read_reg(adapter, whoami);
58	if (val != notready1 && val != notready2)
59		return 0;
60	else
61		return -EIO;
62}
63
64
65/**
66 *      t4vf_fw_reset - issue a reset to FW
67 *      @adapter: the adapter
68 *
69 *	Issues a reset command to FW.  For a Physical Function this would
70 *	result in the Firmware reseting all of its state.  For a Virtual
71 *	Function this just resets the state associated with the VF.
72 */
73int t4vf_fw_reset(struct adapter *adapter)
74{
75	struct fw_reset_cmd cmd;
76
77	memset(&cmd, 0, sizeof(cmd));
78	cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RESET_CMD) |
79				      F_FW_CMD_WRITE);
80	cmd.retval_len16 = cpu_to_be32(V_FW_CMD_LEN16(FW_LEN16(cmd)));
81	return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
82}
83
84/**
85 *	t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
86 *	@adapter: the adapter
87 *
88 *	Retrieves various core SGE parameters in the form of hardware SGE
89 *	register values.  The caller is responsible for decoding these as
90 *	needed.  The SGE parameters are stored in @adapter->params.sge.
91 */
92int t4vf_get_sge_params(struct adapter *adapter)
93{
94	struct sge_params *sp = &adapter->params.sge;
95	u32 params[7], vals[7];
96	u32 whoami;
97	unsigned int pf, s_hps;
98	int i, v;
99
100	params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
101		     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL));
102	params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
103		     V_FW_PARAMS_PARAM_XYZ(A_SGE_HOST_PAGE_SIZE));
104	params[2] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
105		     V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_0_AND_1));
106	params[3] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
107		     V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_2_AND_3));
108	params[4] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
109		     V_FW_PARAMS_PARAM_XYZ(A_SGE_TIMER_VALUE_4_AND_5));
110	params[5] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
111		     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONM_CTRL));
112	params[6] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
113		     V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_RX_THRESHOLD));
114	v = t4vf_query_params(adapter, 7, params, vals);
115	if (v != FW_SUCCESS)
116		return v;
117
118	sp->sge_control = vals[0];
119	sp->counter_val[0] = G_THRESHOLD_0(vals[6]);
120	sp->counter_val[1] = G_THRESHOLD_1(vals[6]);
121	sp->counter_val[2] = G_THRESHOLD_2(vals[6]);
122	sp->counter_val[3] = G_THRESHOLD_3(vals[6]);
123	sp->timer_val[0] = core_ticks_to_us(adapter, G_TIMERVALUE0(vals[2]));
124	sp->timer_val[1] = core_ticks_to_us(adapter, G_TIMERVALUE1(vals[2]));
125	sp->timer_val[2] = core_ticks_to_us(adapter, G_TIMERVALUE2(vals[3]));
126	sp->timer_val[3] = core_ticks_to_us(adapter, G_TIMERVALUE3(vals[3]));
127	sp->timer_val[4] = core_ticks_to_us(adapter, G_TIMERVALUE4(vals[4]));
128	sp->timer_val[5] = core_ticks_to_us(adapter, G_TIMERVALUE5(vals[4]));
129
130	sp->fl_starve_threshold = G_EGRTHRESHOLD(vals[5]) * 2 + 1;
131	if (is_t4(adapter))
132		sp->fl_starve_threshold2 = sp->fl_starve_threshold;
133	else
134		sp->fl_starve_threshold2 = G_EGRTHRESHOLDPACKING(vals[5]) * 2 +
135		    1;
136
137	/*
138	 * We need the Queues/Page and Host Page Size for our VF.
139	 * This is based on the PF from which we're instantiated.
140	 */
141	whoami = t4_read_reg(adapter, VF_PL_REG(A_PL_VF_WHOAMI));
142	pf = G_SOURCEPF(whoami);
143
144	s_hps = (S_HOSTPAGESIZEPF0 +
145	    (S_HOSTPAGESIZEPF1 - S_HOSTPAGESIZEPF0) * pf);
146	sp->page_shift = ((vals[1] >> s_hps) & M_HOSTPAGESIZEPF0) + 10;
147
148	for (i = 0; i < SGE_FLBUF_SIZES; i++) {
149		params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
150		    V_FW_PARAMS_PARAM_XYZ(A_SGE_FL_BUFFER_SIZE0 + (4 * i)));
151		v = t4vf_query_params(adapter, 1, params, vals);
152		if (v != FW_SUCCESS)
153			return v;
154
155		sp->sge_fl_buffer_size[i] = vals[0];
156	}
157
158	/*
159	 * T4 uses a single control field to specify both the PCIe Padding and
160	 * Packing Boundary.  T5 introduced the ability to specify these
161	 * separately with the Padding Boundary in SGE_CONTROL and and Packing
162	 * Boundary in SGE_CONTROL2.  So for T5 and later we need to grab
163	 * SGE_CONTROL in order to determine how ingress packet data will be
164	 * laid out in Packed Buffer Mode.  Unfortunately, older versions of
165	 * the firmware won't let us retrieve SGE_CONTROL2 so if we get a
166	 * failure grabbing it we throw an error since we can't figure out the
167	 * right value.
168	 */
169	sp->spg_len = sp->sge_control & F_EGRSTATUSPAGESIZE ? 128 : 64;
170	sp->fl_pktshift = G_PKTSHIFT(sp->sge_control);
171	sp->pad_boundary = 1 << (G_INGPADBOUNDARY(sp->sge_control) + 5);
172	if (is_t4(adapter))
173		sp->pack_boundary = sp->pad_boundary;
174	else {
175		params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
176			     V_FW_PARAMS_PARAM_XYZ(A_SGE_CONTROL2));
177		v = t4vf_query_params(adapter, 1, params, vals);
178		if (v != FW_SUCCESS) {
179			CH_ERR(adapter, "Unable to get SGE Control2; "
180			       "probably old firmware.\n");
181			return v;
182		}
183		if (G_INGPACKBOUNDARY(vals[0]) == 0)
184			sp->pack_boundary = 16;
185		else
186			sp->pack_boundary = 1 << (G_INGPACKBOUNDARY(vals[0]) +
187			    5);
188	}
189
190	/*
191	 * For T5 and later we want to use the new BAR2 Doorbells.
192	 * Unfortunately, older firmware didn't allow the this register to be
193	 * read.
194	 */
195	if (!is_t4(adapter)) {
196		unsigned int s_qpp;
197
198		params[0] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
199			     V_FW_PARAMS_PARAM_XYZ(A_SGE_EGRESS_QUEUES_PER_PAGE_VF));
200		params[1] = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_REG) |
201			     V_FW_PARAMS_PARAM_XYZ(A_SGE_INGRESS_QUEUES_PER_PAGE_VF));
202		v = t4vf_query_params(adapter, 2, params, vals);
203		if (v != FW_SUCCESS) {
204			CH_WARN(adapter, "Unable to get VF SGE Queues/Page; "
205				"probably old firmware.\n");
206			return v;
207		}
208
209		s_qpp = (S_QUEUESPERPAGEPF0 +
210			 (S_QUEUESPERPAGEPF1 - S_QUEUESPERPAGEPF0) * pf);
211		sp->eq_s_qpp = ((vals[0] >> s_qpp) & M_QUEUESPERPAGEPF0);
212		sp->iq_s_qpp = ((vals[1] >> s_qpp) & M_QUEUESPERPAGEPF0);
213	}
214
215	return 0;
216}
217
218/**
219 *	t4vf_get_rss_glb_config - retrieve adapter RSS Global Configuration
220 *	@adapter: the adapter
221 *
222 *	Retrieves global RSS mode and parameters with which we have to live
223 *	and stores them in the @adapter's RSS parameters.
224 */
225int t4vf_get_rss_glb_config(struct adapter *adapter)
226{
227	struct rss_params *rss = &adapter->params.rss;
228	struct fw_rss_glb_config_cmd cmd, rpl;
229	int v;
230
231	/*
232	 * Execute an RSS Global Configuration read command to retrieve
233	 * our RSS configuration.
234	 */
235	memset(&cmd, 0, sizeof(cmd));
236	cmd.op_to_write = cpu_to_be32(V_FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
237				      F_FW_CMD_REQUEST |
238				      F_FW_CMD_READ);
239	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
240	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
241	if (v != FW_SUCCESS)
242		return v;
243
244	/*
245	 * Transate the big-endian RSS Global Configuration into our
246	 * cpu-endian format based on the RSS mode.  We also do first level
247	 * filtering at this point to weed out modes which don't support
248	 * VF Drivers ...
249	 */
250	rss->mode = G_FW_RSS_GLB_CONFIG_CMD_MODE(
251			be32_to_cpu(rpl.u.manual.mode_pkd));
252	switch (rss->mode) {
253	case FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL: {
254		u32 word = be32_to_cpu(
255				rpl.u.basicvirtual.synmapen_to_hashtoeplitz);
256
257		rss->u.basicvirtual.synmapen =
258			((word & F_FW_RSS_GLB_CONFIG_CMD_SYNMAPEN) != 0);
259		rss->u.basicvirtual.syn4tupenipv6 =
260			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV6) != 0);
261		rss->u.basicvirtual.syn2tupenipv6 =
262			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV6) != 0);
263		rss->u.basicvirtual.syn4tupenipv4 =
264			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN4TUPENIPV4) != 0);
265		rss->u.basicvirtual.syn2tupenipv4 =
266			((word & F_FW_RSS_GLB_CONFIG_CMD_SYN2TUPENIPV4) != 0);
267
268		rss->u.basicvirtual.ofdmapen =
269			((word & F_FW_RSS_GLB_CONFIG_CMD_OFDMAPEN) != 0);
270
271		rss->u.basicvirtual.tnlmapen =
272			((word & F_FW_RSS_GLB_CONFIG_CMD_TNLMAPEN) != 0);
273		rss->u.basicvirtual.tnlalllookup =
274			((word  & F_FW_RSS_GLB_CONFIG_CMD_TNLALLLKP) != 0);
275
276		rss->u.basicvirtual.hashtoeplitz =
277			((word & F_FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ) != 0);
278
279		/* we need at least Tunnel Map Enable to be set */
280		if (!rss->u.basicvirtual.tnlmapen)
281			return -EINVAL;
282		break;
283	}
284
285	default:
286		/* all unknown/unsupported RSS modes result in an error */
287		return -EINVAL;
288	}
289
290	return 0;
291}
292
293/**
294 *	t4vf_get_vfres - retrieve VF resource limits
295 *	@adapter: the adapter
296 *
297 *	Retrieves configured resource limits and capabilities for a virtual
298 *	function.  The results are stored in @adapter->vfres.
299 */
300int t4vf_get_vfres(struct adapter *adapter)
301{
302	struct vf_resources *vfres = &adapter->params.vfres;
303	struct fw_pfvf_cmd cmd, rpl;
304	int v;
305	u32 word;
306
307	/*
308	 * Execute PFVF Read command to get VF resource limits; bail out early
309	 * with error on command failure.
310	 */
311	memset(&cmd, 0, sizeof(cmd));
312	cmd.op_to_vfn = cpu_to_be32(V_FW_CMD_OP(FW_PFVF_CMD) |
313				    F_FW_CMD_REQUEST |
314				    F_FW_CMD_READ);
315	cmd.retval_len16 = cpu_to_be32(FW_LEN16(cmd));
316	v = t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), &rpl);
317	if (v != FW_SUCCESS)
318		return v;
319
320	/*
321	 * Extract VF resource limits and return success.
322	 */
323	word = be32_to_cpu(rpl.niqflint_niq);
324	vfres->niqflint = G_FW_PFVF_CMD_NIQFLINT(word);
325	vfres->niq = G_FW_PFVF_CMD_NIQ(word);
326
327	word = be32_to_cpu(rpl.type_to_neq);
328	vfres->neq = G_FW_PFVF_CMD_NEQ(word);
329	vfres->pmask = G_FW_PFVF_CMD_PMASK(word);
330
331	word = be32_to_cpu(rpl.tc_to_nexactf);
332	vfres->tc = G_FW_PFVF_CMD_TC(word);
333	vfres->nvi = G_FW_PFVF_CMD_NVI(word);
334	vfres->nexactf = G_FW_PFVF_CMD_NEXACTF(word);
335
336	word = be32_to_cpu(rpl.r_caps_to_nethctrl);
337	vfres->r_caps = G_FW_PFVF_CMD_R_CAPS(word);
338	vfres->wx_caps = G_FW_PFVF_CMD_WX_CAPS(word);
339	vfres->nethctrl = G_FW_PFVF_CMD_NETHCTRL(word);
340
341	return 0;
342}
343
344/**
345 */
346int t4vf_prep_adapter(struct adapter *adapter)
347{
348	int err;
349
350	/*
351	 * Wait for the device to become ready before proceeding ...
352	 */
353	err = t4vf_wait_dev_ready(adapter);
354	if (err)
355		return err;
356
357	adapter->params.chipid = pci_get_device(adapter->dev) >> 12;
358	if (adapter->params.chipid >= 0xa) {
359		adapter->params.chipid -= (0xa - 0x4);
360		adapter->params.fpga = 1;
361	}
362
363	/*
364	 * Default port and clock for debugging in case we can't reach
365	 * firmware.
366	 */
367	adapter->params.nports = 1;
368	adapter->params.vfres.pmask = 1;
369	adapter->params.vpd.cclk = 50000;
370
371	adapter->chip_params = t4_get_chip_params(chip_id(adapter));
372	if (adapter->chip_params == NULL)
373		return -EINVAL;
374
375	return 0;
376}
377