1 /******************************************************************************
2 
3   Copyright (c) 2013-2018, Intel Corporation
4   All rights reserved.
5 
6   Redistribution and use in source and binary forms, with or without
7   modification, are permitted provided that the following conditions are met:
8 
9    1. Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11 
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15 
16    3. Neither the name of the Intel Corporation nor the names of its
17       contributors may be used to endorse or promote products derived from
18       this software without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   POSSIBILITY OF SUCH DAMAGE.
31 
32 ******************************************************************************/
33 /*$FreeBSD: stable/12/sys/dev/ixl/ixl_pf_main.c 372651 2022-10-19 23:25:25Z erj $*/
34 
35 
36 #include "ixl_pf.h"
37 
38 #ifdef PCI_IOV
39 #include "ixl_pf_iov.h"
40 #endif
41 
42 #ifdef IXL_IW
43 #include "ixl_iw.h"
44 #include "ixl_iw_int.h"
45 #endif
46 
47 static u8	ixl_convert_sysctl_aq_link_speed(u8, bool);
48 static void	ixl_sbuf_print_bytes(struct sbuf *, u8 *, int, int, bool);
49 static const char * ixl_link_speed_string(enum i40e_aq_link_speed);
50 static char *	ixl_switch_element_string(struct sbuf *, u8, u16);
51 static enum ixl_fw_mode ixl_get_fw_mode(struct ixl_pf *);
52 
53 /* Sysctls */
54 static int	ixl_sysctl_set_advertise(SYSCTL_HANDLER_ARGS);
55 static int	ixl_sysctl_supported_speeds(SYSCTL_HANDLER_ARGS);
56 static int	ixl_sysctl_current_speed(SYSCTL_HANDLER_ARGS);
57 static int	ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS);
58 static int	ixl_sysctl_unallocated_queues(SYSCTL_HANDLER_ARGS);
59 static int	ixl_sysctl_pf_tx_itr(SYSCTL_HANDLER_ARGS);
60 static int	ixl_sysctl_pf_rx_itr(SYSCTL_HANDLER_ARGS);
61 
62 static int	ixl_sysctl_eee_enable(SYSCTL_HANDLER_ARGS);
63 static int	ixl_sysctl_set_link_active(SYSCTL_HANDLER_ARGS);
64 
65 /* Debug Sysctls */
66 static int 	ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
67 static int	ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS);
68 static int	ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS);
69 static int	ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS);
70 static int	ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
71 static int	ixl_sysctl_switch_vlans(SYSCTL_HANDLER_ARGS);
72 static int	ixl_sysctl_hkey(SYSCTL_HANDLER_ARGS);
73 static int	ixl_sysctl_hena(SYSCTL_HANDLER_ARGS);
74 static int	ixl_sysctl_hlut(SYSCTL_HANDLER_ARGS);
75 static int	ixl_sysctl_fw_link_management(SYSCTL_HANDLER_ARGS);
76 static int	ixl_sysctl_read_i2c_byte(SYSCTL_HANDLER_ARGS);
77 static int	ixl_sysctl_write_i2c_byte(SYSCTL_HANDLER_ARGS);
78 static int	ixl_sysctl_fec_fc_ability(SYSCTL_HANDLER_ARGS);
79 static int	ixl_sysctl_fec_rs_ability(SYSCTL_HANDLER_ARGS);
80 static int	ixl_sysctl_fec_fc_request(SYSCTL_HANDLER_ARGS);
81 static int	ixl_sysctl_fec_rs_request(SYSCTL_HANDLER_ARGS);
82 static int	ixl_sysctl_fec_auto_enable(SYSCTL_HANDLER_ARGS);
83 static int	ixl_sysctl_dump_debug_data(SYSCTL_HANDLER_ARGS);
84 static int	ixl_sysctl_fw_lldp(SYSCTL_HANDLER_ARGS);
85 static int	ixl_sysctl_read_i2c_diag_data(SYSCTL_HANDLER_ARGS);
86 
87 /* Debug Sysctls */
88 static int	ixl_sysctl_do_pf_reset(SYSCTL_HANDLER_ARGS);
89 static int	ixl_sysctl_do_core_reset(SYSCTL_HANDLER_ARGS);
90 static int	ixl_sysctl_do_global_reset(SYSCTL_HANDLER_ARGS);
91 static int	ixl_sysctl_queue_interrupt_table(SYSCTL_HANDLER_ARGS);
92 #ifdef IXL_DEBUG
93 static int	ixl_sysctl_qtx_tail_handler(SYSCTL_HANDLER_ARGS);
94 static int	ixl_sysctl_qrx_tail_handler(SYSCTL_HANDLER_ARGS);
95 #endif
96 
97 #ifdef IXL_IW
98 extern int ixl_enable_iwarp;
99 extern int ixl_limit_iwarp_msix;
100 #endif
101 
102 static const char * const ixl_fc_string[6] = {
103 	"None",
104 	"Rx",
105 	"Tx",
106 	"Full",
107 	"Priority",
108 	"Default"
109 };
110 
111 static char *ixl_fec_string[3] = {
112        "CL108 RS-FEC",
113        "CL74 FC-FEC/BASE-R",
114        "None"
115 };
116 
117 MALLOC_DEFINE(M_IXL, "ixl", "ixl driver allocations");
118 
119 /*
120 ** Put the FW, API, NVM, EEtrackID, and OEM version information into a string
121 */
122 void
ixl_nvm_version_str(struct i40e_hw * hw,struct sbuf * buf)123 ixl_nvm_version_str(struct i40e_hw *hw, struct sbuf *buf)
124 {
125 	u8 oem_ver = (u8)(hw->nvm.oem_ver >> 24);
126 	u16 oem_build = (u16)((hw->nvm.oem_ver >> 16) & 0xFFFF);
127 	u8 oem_patch = (u8)(hw->nvm.oem_ver & 0xFF);
128 
129 	sbuf_printf(buf,
130 	    "fw %d.%d.%05d api %d.%d nvm %x.%02x etid %08x oem %d.%d.%d",
131 	    hw->aq.fw_maj_ver, hw->aq.fw_min_ver, hw->aq.fw_build,
132 	    hw->aq.api_maj_ver, hw->aq.api_min_ver,
133 	    (hw->nvm.version & IXL_NVM_VERSION_HI_MASK) >>
134 	    IXL_NVM_VERSION_HI_SHIFT,
135 	    (hw->nvm.version & IXL_NVM_VERSION_LO_MASK) >>
136 	    IXL_NVM_VERSION_LO_SHIFT,
137 	    hw->nvm.eetrack,
138 	    oem_ver, oem_build, oem_patch);
139 }
140 
141 void
ixl_print_nvm_version(struct ixl_pf * pf)142 ixl_print_nvm_version(struct ixl_pf *pf)
143 {
144 	struct i40e_hw *hw = &pf->hw;
145 	device_t dev = pf->dev;
146 	struct sbuf *sbuf;
147 
148 	sbuf = sbuf_new_auto();
149 	ixl_nvm_version_str(hw, sbuf);
150 	sbuf_finish(sbuf);
151 	device_printf(dev, "%s\n", sbuf_data(sbuf));
152 	sbuf_delete(sbuf);
153 }
154 
155 /**
156  * ixl_get_fw_mode - Check the state of FW
157  * @hw: device hardware structure
158  *
159  * Identify state of FW. It might be in a recovery mode
160  * which limits functionality and requires special handling
161  * from the driver.
162  *
163  * @returns FW mode (normal, recovery, unexpected EMP reset)
164  */
165 static enum ixl_fw_mode
ixl_get_fw_mode(struct ixl_pf * pf)166 ixl_get_fw_mode(struct ixl_pf *pf)
167 {
168 	struct i40e_hw *hw = &pf->hw;
169 	enum ixl_fw_mode fw_mode = IXL_FW_MODE_NORMAL;
170 	u32 fwsts;
171 
172 #ifdef IXL_DEBUG
173 	if (pf->recovery_mode)
174 		return IXL_FW_MODE_RECOVERY;
175 #endif
176 	fwsts = rd32(hw, I40E_GL_FWSTS) & I40E_GL_FWSTS_FWS1B_MASK;
177 
178 	/* Is set and has one of expected values */
179 	if ((fwsts >= I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK &&
180 	    fwsts <= I40E_XL710_GL_FWSTS_FWS1B_REC_MOD_NVM_MASK) ||
181 	    fwsts == I40E_X722_GL_FWSTS_FWS1B_REC_MOD_GLOBR_MASK ||
182 	    fwsts == I40E_X722_GL_FWSTS_FWS1B_REC_MOD_CORER_MASK)
183 		fw_mode = IXL_FW_MODE_RECOVERY;
184 	else {
185 		if (fwsts > I40E_GL_FWSTS_FWS1B_EMPR_0 &&
186 		    fwsts <= I40E_GL_FWSTS_FWS1B_EMPR_10)
187 			fw_mode = IXL_FW_MODE_UEMPR;
188 	}
189 	return (fw_mode);
190 }
191 
192 /**
193  * ixl_pf_reset - Reset the PF
194  * @pf: PF structure
195  *
196  * Ensure that FW is in the right state and do the reset
197  * if needed.
198  *
199  * @returns zero on success, or an error code on failure.
200  */
201 int
ixl_pf_reset(struct ixl_pf * pf)202 ixl_pf_reset(struct ixl_pf *pf)
203 {
204 	struct i40e_hw *hw = &pf->hw;
205 	enum i40e_status_code status;
206 	enum ixl_fw_mode fw_mode;
207 
208 	fw_mode = ixl_get_fw_mode(pf);
209 	ixl_dbg_info(pf, "%s: before PF reset FW mode: 0x%08x\n", __func__, fw_mode);
210 	if (fw_mode == IXL_FW_MODE_RECOVERY) {
211 		atomic_set_32(&pf->state, IXL_PF_STATE_RECOVERY_MODE);
212 		/* Don't try to reset device if it's in recovery mode */
213 		return (0);
214 	}
215 
216 	status = i40e_pf_reset(hw);
217 	if (status == I40E_SUCCESS)
218 		return (0);
219 
220 	/* Check FW mode again in case it has changed while
221 	 * waiting for reset to complete */
222 	fw_mode = ixl_get_fw_mode(pf);
223 	ixl_dbg_info(pf, "%s: after PF reset FW mode: 0x%08x\n", __func__, fw_mode);
224 	if (fw_mode == IXL_FW_MODE_RECOVERY) {
225 		atomic_set_32(&pf->state, IXL_PF_STATE_RECOVERY_MODE);
226 		return (0);
227 	}
228 
229 	if (fw_mode == IXL_FW_MODE_UEMPR)
230 		device_printf(pf->dev,
231 		    "Entering recovery mode due to repeated FW resets. This may take several minutes. Refer to the Intel(R) Ethernet Adapters and Devices User Guide.\n");
232 	else
233 		device_printf(pf->dev, "PF reset failure %s\n",
234 		    i40e_stat_str(hw, status));
235 	return (EIO);
236 }
237 
238 /**
239  * ixl_setup_hmc - Setup LAN Host Memory Cache
240  * @pf: PF structure
241  *
242  * Init and configure LAN Host Memory Cache
243  *
244  * @returns 0 on success, EIO on error
245  */
246 int
ixl_setup_hmc(struct ixl_pf * pf)247 ixl_setup_hmc(struct ixl_pf *pf)
248 {
249 	struct i40e_hw *hw = &pf->hw;
250 	enum i40e_status_code status;
251 
252 	status = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
253 	    hw->func_caps.num_rx_qp, 0, 0);
254 	if (status) {
255 		device_printf(pf->dev, "init_lan_hmc failed: %s\n",
256 		    i40e_stat_str(hw, status));
257 		return (EIO);
258 	}
259 
260 	status = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY);
261 	if (status) {
262 		device_printf(pf->dev, "configure_lan_hmc failed: %s\n",
263 		    i40e_stat_str(hw, status));
264 		return (EIO);
265 	}
266 
267 	return (0);
268 }
269 
270 /**
271  * ixl_shutdown_hmc - Shutdown LAN Host Memory Cache
272  * @pf: PF structure
273  *
274  * Shutdown Host Memory Cache if configured.
275  *
276  */
277 void
ixl_shutdown_hmc(struct ixl_pf * pf)278 ixl_shutdown_hmc(struct ixl_pf *pf)
279 {
280 	struct i40e_hw *hw = &pf->hw;
281 	enum i40e_status_code status;
282 
283 	/* HMC not configured, no need to shutdown */
284 	if (hw->hmc.hmc_obj == NULL)
285 		return;
286 
287 	status = i40e_shutdown_lan_hmc(hw);
288 	if (status)
289 		device_printf(pf->dev,
290 		    "Shutdown LAN HMC failed with code %s\n",
291 		    i40e_stat_str(hw, status));
292 }
293 /*
294  * Write PF ITR values to queue ITR registers.
295  */
296 void
ixl_configure_itr(struct ixl_pf * pf)297 ixl_configure_itr(struct ixl_pf *pf)
298 {
299 	ixl_configure_tx_itr(pf);
300 	ixl_configure_rx_itr(pf);
301 }
302 
303 /*********************************************************************
304  *
305  *  Get the hardware capabilities
306  *
307  **********************************************************************/
308 
309 int
ixl_get_hw_capabilities(struct ixl_pf * pf)310 ixl_get_hw_capabilities(struct ixl_pf *pf)
311 {
312 	struct i40e_aqc_list_capabilities_element_resp *buf;
313 	struct i40e_hw	*hw = &pf->hw;
314 	device_t 	dev = pf->dev;
315 	enum i40e_status_code status;
316 	int len, i2c_intfc_num;
317 	bool again = TRUE;
318 	u16 needed;
319 
320 	if (IXL_PF_IN_RECOVERY_MODE(pf)) {
321 		hw->func_caps.iwarp = 0;
322 		return (0);
323 	}
324 
325 	len = 40 * sizeof(struct i40e_aqc_list_capabilities_element_resp);
326 retry:
327 	if (!(buf = (struct i40e_aqc_list_capabilities_element_resp *)
328 	    malloc(len, M_IXL, M_NOWAIT | M_ZERO))) {
329 		device_printf(dev, "Unable to allocate cap memory\n");
330                 return (ENOMEM);
331 	}
332 
333 	/* This populates the hw struct */
334         status = i40e_aq_discover_capabilities(hw, buf, len,
335 	    &needed, i40e_aqc_opc_list_func_capabilities, NULL);
336 	free(buf, M_IXL);
337 	if ((pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) &&
338 	    (again == TRUE)) {
339 		/* retry once with a larger buffer */
340 		again = FALSE;
341 		len = needed;
342 		goto retry;
343 	} else if (status != I40E_SUCCESS) {
344 		device_printf(dev, "capability discovery failed; status %s, error %s\n",
345 		    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
346 		return (ENODEV);
347 	}
348 
349 	/*
350 	 * Some devices have both MDIO and I2C; since this isn't reported
351 	 * by the FW, check registers to see if an I2C interface exists.
352 	 */
353 	i2c_intfc_num = ixl_find_i2c_interface(pf);
354 	if (i2c_intfc_num != -1)
355 		pf->has_i2c = true;
356 
357 	/* Determine functions to use for driver I2C accesses */
358 	switch (pf->i2c_access_method) {
359 	case IXL_I2C_ACCESS_METHOD_BEST_AVAILABLE: {
360 		if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE) {
361 			pf->read_i2c_byte = ixl_read_i2c_byte_aq;
362 			pf->write_i2c_byte = ixl_write_i2c_byte_aq;
363 		} else {
364 			pf->read_i2c_byte = ixl_read_i2c_byte_reg;
365 			pf->write_i2c_byte = ixl_write_i2c_byte_reg;
366 		}
367 		break;
368 	}
369 	case IXL_I2C_ACCESS_METHOD_AQ:
370 		pf->read_i2c_byte = ixl_read_i2c_byte_aq;
371 		pf->write_i2c_byte = ixl_write_i2c_byte_aq;
372 		break;
373 	case IXL_I2C_ACCESS_METHOD_REGISTER_I2CCMD:
374 		pf->read_i2c_byte = ixl_read_i2c_byte_reg;
375 		pf->write_i2c_byte = ixl_write_i2c_byte_reg;
376 		break;
377 	case IXL_I2C_ACCESS_METHOD_BIT_BANG_I2CPARAMS:
378 		pf->read_i2c_byte = ixl_read_i2c_byte_bb;
379 		pf->write_i2c_byte = ixl_write_i2c_byte_bb;
380 		break;
381 	default:
382 		/* Should not happen */
383 		device_printf(dev, "Error setting I2C access functions\n");
384 		break;
385 	}
386 
387 	/* Keep link active by default */
388 	atomic_set_32(&pf->state, IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
389 
390 	/* Print a subset of the capability information. */
391 	device_printf(dev,
392 	    "PF-ID[%d]: VFs %d, MSI-X %d, VF MSI-X %d, QPs %d, %s\n",
393 	    hw->pf_id, hw->func_caps.num_vfs, hw->func_caps.num_msix_vectors,
394 	    hw->func_caps.num_msix_vectors_vf, hw->func_caps.num_tx_qp,
395 	    (hw->func_caps.mdio_port_mode == 2) ? "I2C" :
396 	    (hw->func_caps.mdio_port_mode == 1 && pf->has_i2c) ? "MDIO & I2C" :
397 	    (hw->func_caps.mdio_port_mode == 1) ? "MDIO dedicated" :
398 	    "MDIO shared");
399 
400 	return (0);
401 }
402 
403 /* For the set_advertise sysctl */
404 void
ixl_set_initial_advertised_speeds(struct ixl_pf * pf)405 ixl_set_initial_advertised_speeds(struct ixl_pf *pf)
406 {
407 	device_t dev = pf->dev;
408 	int err;
409 
410 	/* Make sure to initialize the device to the complete list of
411 	 * supported speeds on driver load, to ensure unloading and
412 	 * reloading the driver will restore this value.
413 	 */
414 	err = ixl_set_advertised_speeds(pf, pf->supported_speeds, true);
415 	if (err) {
416 		/* Non-fatal error */
417 		device_printf(dev, "%s: ixl_set_advertised_speeds() error %d\n",
418 			      __func__, err);
419 		return;
420 	}
421 
422 	pf->advertised_speed =
423 	    ixl_convert_sysctl_aq_link_speed(pf->supported_speeds, false);
424 }
425 
426 int
ixl_teardown_hw_structs(struct ixl_pf * pf)427 ixl_teardown_hw_structs(struct ixl_pf *pf)
428 {
429 	enum i40e_status_code status = 0;
430 	struct i40e_hw *hw = &pf->hw;
431 	device_t dev = pf->dev;
432 
433 	/* Shutdown LAN HMC */
434 	if (hw->hmc.hmc_obj) {
435 		status = i40e_shutdown_lan_hmc(hw);
436 		if (status) {
437 			device_printf(dev,
438 			    "init: LAN HMC shutdown failure; status %s\n",
439 			    i40e_stat_str(hw, status));
440 			goto err_out;
441 		}
442 	}
443 
444 	/* Shutdown admin queue */
445 	ixl_disable_intr0(hw);
446 	status = i40e_shutdown_adminq(hw);
447 	if (status)
448 		device_printf(dev,
449 		    "init: Admin Queue shutdown failure; status %s\n",
450 		    i40e_stat_str(hw, status));
451 
452 	ixl_pf_qmgr_release(&pf->qmgr, &pf->qtag);
453 err_out:
454 	return (status);
455 }
456 
457 /*
458 ** Creates new filter with given MAC address and VLAN ID
459 */
460 static struct ixl_mac_filter *
ixl_new_filter(struct ixl_ftl_head * headp,const u8 * macaddr,s16 vlan)461 ixl_new_filter(struct ixl_ftl_head *headp, const u8 *macaddr, s16 vlan)
462 {
463 	struct ixl_mac_filter  *f;
464 
465 	/* create a new empty filter */
466 	f = malloc(sizeof(struct ixl_mac_filter),
467 	    M_IXL, M_NOWAIT | M_ZERO);
468 	if (f) {
469 		LIST_INSERT_HEAD(headp, f, ftle);
470 		bcopy(macaddr, f->macaddr, ETHER_ADDR_LEN);
471 		f->vlan = vlan;
472 	}
473 
474 	return (f);
475 }
476 
477 /**
478  * ixl_free_filters - Free all filters in given list
479  * headp - pointer to list head
480  *
481  * Frees memory used by each entry in the list.
482  * Does not remove filters from HW.
483  */
484 void
ixl_free_filters(struct ixl_ftl_head * headp)485 ixl_free_filters(struct ixl_ftl_head *headp)
486 {
487 	struct ixl_mac_filter *f, *nf;
488 
489 	f = LIST_FIRST(headp);
490 	while (f != NULL) {
491 		nf = LIST_NEXT(f, ftle);
492 		free(f, M_IXL);
493 		f = nf;
494 	}
495 
496 	LIST_INIT(headp);
497 }
498 
499 static u_int
ixl_add_maddr(void * arg,struct sockaddr_dl * sdl,u_int cnt)500 ixl_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
501 {
502 	struct ixl_add_maddr_arg *ama = arg;
503 	struct ixl_vsi *vsi = ama->vsi;
504 	const u8 *macaddr = (u8*)LLADDR(sdl);
505 	struct ixl_mac_filter *f;
506 
507 	/* Does one already exist */
508 	f = ixl_find_filter(&vsi->ftl, macaddr, IXL_VLAN_ANY);
509 	if (f != NULL)
510 		return (0);
511 
512 	f = ixl_new_filter(&ama->to_add, macaddr, IXL_VLAN_ANY);
513 	if (f == NULL) {
514 		device_printf(vsi->dev, "WARNING: no filter available!!\n");
515 		return (0);
516 	}
517 	f->flags |= IXL_FILTER_MC;
518 
519 	return (1);
520 }
521 
522 /*********************************************************************
523  * 	Filter Routines
524  *
525  *	Routines for multicast and vlan filter management.
526  *
527  *********************************************************************/
528 void
ixl_add_multi(struct ixl_vsi * vsi)529 ixl_add_multi(struct ixl_vsi *vsi)
530 {
531 	struct	ifmultiaddr	*ifma;
532 	struct ifnet		*ifp = vsi->ifp;
533 	struct i40e_hw		*hw = vsi->hw;
534 	int			mcnt = 0;
535 	struct ixl_add_maddr_arg cb_arg;
536 
537 	IOCTL_DEBUGOUT("ixl_add_multi: begin");
538 
539 	if_maddr_rlock(ifp);
540 	/*
541 	** First just get a count, to decide if we
542 	** we simply use multicast promiscuous.
543 	*/
544 	CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
545 		if (ifma->ifma_addr->sa_family != AF_LINK)
546 			continue;
547 		mcnt++;
548 	}
549 	if_maddr_runlock(ifp);
550 
551 	if (__predict_false(mcnt >= MAX_MULTICAST_ADDR)) {
552 		i40e_aq_set_vsi_multicast_promiscuous(hw,
553 		    vsi->seid, TRUE, NULL);
554 		/* delete all existing MC filters */
555 		ixl_del_multi(vsi, true);
556 		return;
557 	}
558 
559 	cb_arg.vsi = vsi;
560 	LIST_INIT(&cb_arg.to_add);
561 
562 	mcnt = if_foreach_llmaddr(ifp, ixl_add_maddr, &cb_arg);
563 	if (mcnt > 0)
564 		ixl_add_hw_filters(vsi, &cb_arg.to_add, mcnt);
565 
566 	IOCTL_DEBUGOUT("ixl_add_multi: end");
567 }
568 
569 static u_int
ixl_match_maddr(void * arg,struct sockaddr_dl * sdl,u_int cnt)570 ixl_match_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt)
571 {
572 	struct ixl_mac_filter *f = arg;
573 
574 	if (ixl_ether_is_equal(f->macaddr, (u8 *)LLADDR(sdl)))
575 		return (1);
576 	else
577 		return (0);
578 }
579 
580 void
ixl_del_multi(struct ixl_vsi * vsi,bool all)581 ixl_del_multi(struct ixl_vsi *vsi, bool all)
582 {
583 	struct ixl_ftl_head	to_del;
584 	struct ifnet		*ifp = vsi->ifp;
585 	struct ixl_mac_filter	*f, *fn;
586 	int			mcnt = 0;
587 
588 	IOCTL_DEBUGOUT("ixl_del_multi: begin");
589 
590 	LIST_INIT(&to_del);
591 	/* Search for removed multicast addresses */
592 	LIST_FOREACH_SAFE(f, &vsi->ftl, ftle, fn) {
593 		if ((f->flags & IXL_FILTER_MC) == 0 ||
594 		    (!all && (if_foreach_llmaddr(ifp, ixl_match_maddr, f) == 0)))
595 			continue;
596 
597 		LIST_REMOVE(f, ftle);
598 		LIST_INSERT_HEAD(&to_del, f, ftle);
599 		mcnt++;
600 	}
601 
602 	if (mcnt > 0)
603 		ixl_del_hw_filters(vsi, &to_del, mcnt);
604 }
605 
606 void
ixl_link_up_msg(struct ixl_pf * pf)607 ixl_link_up_msg(struct ixl_pf *pf)
608 {
609 	struct i40e_hw *hw = &pf->hw;
610 	struct ifnet *ifp = pf->vsi.ifp;
611 	char *req_fec_string, *neg_fec_string;
612 	u8 fec_abilities;
613 
614 	fec_abilities = hw->phy.link_info.req_fec_info;
615 	/* If both RS and KR are requested, only show RS */
616 	if (fec_abilities & I40E_AQ_REQUEST_FEC_RS)
617 		req_fec_string = ixl_fec_string[0];
618 	else if (fec_abilities & I40E_AQ_REQUEST_FEC_KR)
619 		req_fec_string = ixl_fec_string[1];
620 	else
621 		req_fec_string = ixl_fec_string[2];
622 
623 	if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_RS_ENA)
624 		neg_fec_string = ixl_fec_string[0];
625 	else if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_KR_ENA)
626 		neg_fec_string = ixl_fec_string[1];
627 	else
628 		neg_fec_string = ixl_fec_string[2];
629 
630 	log(LOG_NOTICE, "%s: Link is up, %s Full Duplex, Requested FEC: %s, Negotiated FEC: %s, Autoneg: %s, Flow Control: %s\n",
631 	    ifp->if_xname,
632 	    ixl_link_speed_string(hw->phy.link_info.link_speed),
633 	    req_fec_string, neg_fec_string,
634 	    (hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED) ? "True" : "False",
635 	    (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX &&
636 	        hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) ?
637 		ixl_fc_string[3] : (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_TX) ?
638 		ixl_fc_string[2] : (hw->phy.link_info.an_info & I40E_AQ_LINK_PAUSE_RX) ?
639 		ixl_fc_string[1] : ixl_fc_string[0]);
640 }
641 
642 /*
643  * Configure admin queue/misc interrupt cause registers in hardware.
644  */
645 void
ixl_configure_intr0_msix(struct ixl_pf * pf)646 ixl_configure_intr0_msix(struct ixl_pf *pf)
647 {
648 	struct i40e_hw *hw = &pf->hw;
649 	u32 reg;
650 
651 	/* First set up the adminq - vector 0 */
652 	wr32(hw, I40E_PFINT_ICR0_ENA, 0);  /* disable all */
653 	rd32(hw, I40E_PFINT_ICR0);         /* read to clear */
654 
655 	reg = I40E_PFINT_ICR0_ENA_ECC_ERR_MASK |
656 	    I40E_PFINT_ICR0_ENA_GRST_MASK |
657 	    I40E_PFINT_ICR0_ENA_HMC_ERR_MASK |
658 	    I40E_PFINT_ICR0_ENA_ADMINQ_MASK |
659 	    I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK |
660 	    I40E_PFINT_ICR0_ENA_VFLR_MASK |
661 	    I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK |
662 	    I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK;
663 	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
664 
665 	/*
666 	 * 0x7FF is the end of the queue list.
667 	 * This means we won't use MSI-X vector 0 for a queue interrupt
668 	 * in MSI-X mode.
669 	 */
670 	wr32(hw, I40E_PFINT_LNKLST0, 0x7FF);
671 	/* Value is in 2 usec units, so 0x3E is 62*2 = 124 usecs. */
672 	wr32(hw, I40E_PFINT_ITR0(IXL_RX_ITR), 0x3E);
673 
674 	wr32(hw, I40E_PFINT_DYN_CTL0,
675 	    I40E_PFINT_DYN_CTL0_SW_ITR_INDX_MASK |
676 	    I40E_PFINT_DYN_CTL0_INTENA_MSK_MASK);
677 
678 	wr32(hw, I40E_PFINT_STAT_CTL0, 0);
679 }
680 
681 void
ixl_add_ifmedia(struct ifmedia * media,u64 phy_types)682 ixl_add_ifmedia(struct ifmedia *media, u64 phy_types)
683 {
684 	/* Display supported media types */
685 	if (phy_types & (I40E_CAP_PHY_TYPE_100BASE_TX))
686 		ifmedia_add(media, IFM_ETHER | IFM_100_TX, 0, NULL);
687 
688 	if (phy_types & (I40E_CAP_PHY_TYPE_1000BASE_T))
689 		ifmedia_add(media, IFM_ETHER | IFM_1000_T, 0, NULL);
690 	if (phy_types & (I40E_CAP_PHY_TYPE_1000BASE_SX))
691 		ifmedia_add(media, IFM_ETHER | IFM_1000_SX, 0, NULL);
692 	if (phy_types & (I40E_CAP_PHY_TYPE_1000BASE_LX))
693 		ifmedia_add(media, IFM_ETHER | IFM_1000_LX, 0, NULL);
694 
695 	if (phy_types & (I40E_CAP_PHY_TYPE_2_5GBASE_T))
696 		ifmedia_add(media, IFM_ETHER | IFM_2500_T, 0, NULL);
697 
698 	if (phy_types & (I40E_CAP_PHY_TYPE_5GBASE_T))
699 		ifmedia_add(media, IFM_ETHER | IFM_5000_T, 0, NULL);
700 
701 	if (phy_types & (I40E_CAP_PHY_TYPE_XAUI) ||
702 	    phy_types & (I40E_CAP_PHY_TYPE_XFI) ||
703 	    phy_types & (I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU))
704 		ifmedia_add(media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
705 
706 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_SR))
707 		ifmedia_add(media, IFM_ETHER | IFM_10G_SR, 0, NULL);
708 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_LR))
709 		ifmedia_add(media, IFM_ETHER | IFM_10G_LR, 0, NULL);
710 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_T))
711 		ifmedia_add(media, IFM_ETHER | IFM_10G_T, 0, NULL);
712 
713 	if (phy_types & (I40E_CAP_PHY_TYPE_40GBASE_CR4) ||
714 	    phy_types & (I40E_CAP_PHY_TYPE_40GBASE_CR4_CU) ||
715 	    phy_types & (I40E_CAP_PHY_TYPE_40GBASE_AOC) ||
716 	    phy_types & (I40E_CAP_PHY_TYPE_XLAUI) ||
717 	    phy_types & (I40E_CAP_PHY_TYPE_40GBASE_KR4))
718 		ifmedia_add(media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
719 	if (phy_types & (I40E_CAP_PHY_TYPE_40GBASE_SR4))
720 		ifmedia_add(media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
721 	if (phy_types & (I40E_CAP_PHY_TYPE_40GBASE_LR4))
722 		ifmedia_add(media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
723 
724 	if (phy_types & (I40E_CAP_PHY_TYPE_1000BASE_KX))
725 		ifmedia_add(media, IFM_ETHER | IFM_1000_KX, 0, NULL);
726 
727 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_CR1_CU)
728 	    || phy_types & (I40E_CAP_PHY_TYPE_10GBASE_CR1))
729 		ifmedia_add(media, IFM_ETHER | IFM_10G_CR1, 0, NULL);
730 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_AOC))
731 		ifmedia_add(media, IFM_ETHER | IFM_10G_AOC, 0, NULL);
732 	if (phy_types & (I40E_CAP_PHY_TYPE_SFI))
733 		ifmedia_add(media, IFM_ETHER | IFM_10G_SFI, 0, NULL);
734 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_KX4))
735 		ifmedia_add(media, IFM_ETHER | IFM_10G_KX4, 0, NULL);
736 	if (phy_types & (I40E_CAP_PHY_TYPE_10GBASE_KR))
737 		ifmedia_add(media, IFM_ETHER | IFM_10G_KR, 0, NULL);
738 
739 	if (phy_types & (I40E_CAP_PHY_TYPE_20GBASE_KR2))
740 		ifmedia_add(media, IFM_ETHER | IFM_20G_KR2, 0, NULL);
741 
742 	if (phy_types & (I40E_CAP_PHY_TYPE_40GBASE_KR4))
743 		ifmedia_add(media, IFM_ETHER | IFM_40G_KR4, 0, NULL);
744 	if (phy_types & (I40E_CAP_PHY_TYPE_XLPPI))
745 		ifmedia_add(media, IFM_ETHER | IFM_40G_XLPPI, 0, NULL);
746 
747 	if (phy_types & (I40E_CAP_PHY_TYPE_25GBASE_KR))
748 		ifmedia_add(media, IFM_ETHER | IFM_25G_KR, 0, NULL);
749 	if (phy_types & (I40E_CAP_PHY_TYPE_25GBASE_CR))
750 		ifmedia_add(media, IFM_ETHER | IFM_25G_CR, 0, NULL);
751 	if (phy_types & (I40E_CAP_PHY_TYPE_25GBASE_SR))
752 		ifmedia_add(media, IFM_ETHER | IFM_25G_SR, 0, NULL);
753 	if (phy_types & (I40E_CAP_PHY_TYPE_25GBASE_LR))
754 		ifmedia_add(media, IFM_ETHER | IFM_25G_LR, 0, NULL);
755 	if (phy_types & (I40E_CAP_PHY_TYPE_25GBASE_AOC))
756 		ifmedia_add(media, IFM_ETHER | IFM_25G_AOC, 0, NULL);
757 	if (phy_types & (I40E_CAP_PHY_TYPE_25GBASE_ACC))
758 		ifmedia_add(media, IFM_ETHER | IFM_25G_ACC, 0, NULL);
759 }
760 
761 /*********************************************************************
762  *
763  *  Get Firmware Switch configuration
764  *	- this will need to be more robust when more complex
765  *	  switch configurations are enabled.
766  *
767  **********************************************************************/
768 int
ixl_switch_config(struct ixl_pf * pf)769 ixl_switch_config(struct ixl_pf *pf)
770 {
771 	struct i40e_hw	*hw = &pf->hw;
772 	struct ixl_vsi	*vsi = &pf->vsi;
773 	device_t 	dev = iflib_get_dev(vsi->ctx);
774 	struct i40e_aqc_get_switch_config_resp *sw_config;
775 	u8	aq_buf[I40E_AQ_LARGE_BUF];
776 	int	ret;
777 	u16	next = 0;
778 
779 	memset(&aq_buf, 0, sizeof(aq_buf));
780 	sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
781 	ret = i40e_aq_get_switch_config(hw, sw_config,
782 	    sizeof(aq_buf), &next, NULL);
783 	if (ret) {
784 		device_printf(dev, "aq_get_switch_config() failed, error %d,"
785 		    " aq_error %d\n", ret, pf->hw.aq.asq_last_status);
786 		return (ret);
787 	}
788 	if (pf->dbg_mask & IXL_DBG_SWITCH_INFO) {
789 		device_printf(dev,
790 		    "Switch config: header reported: %d in structure, %d total\n",
791 		    LE16_TO_CPU(sw_config->header.num_reported),
792 		    LE16_TO_CPU(sw_config->header.num_total));
793 		for (int i = 0;
794 		    i < LE16_TO_CPU(sw_config->header.num_reported); i++) {
795 			device_printf(dev,
796 			    "-> %d: type=%d seid=%d uplink=%d downlink=%d\n", i,
797 			    sw_config->element[i].element_type,
798 			    LE16_TO_CPU(sw_config->element[i].seid),
799 			    LE16_TO_CPU(sw_config->element[i].uplink_seid),
800 			    LE16_TO_CPU(sw_config->element[i].downlink_seid));
801 		}
802 	}
803 	/* Simplified due to a single VSI */
804 	vsi->uplink_seid = LE16_TO_CPU(sw_config->element[0].uplink_seid);
805 	vsi->downlink_seid = LE16_TO_CPU(sw_config->element[0].downlink_seid);
806 	vsi->seid = LE16_TO_CPU(sw_config->element[0].seid);
807 	return (ret);
808 }
809 
810 void
ixl_vsi_add_sysctls(struct ixl_vsi * vsi,const char * sysctl_name,bool queues_sysctls)811 ixl_vsi_add_sysctls(struct ixl_vsi * vsi, const char * sysctl_name, bool queues_sysctls)
812 {
813 	struct sysctl_oid *tree;
814 	struct sysctl_oid_list *child;
815 	struct sysctl_oid_list *vsi_list;
816 
817 	tree = device_get_sysctl_tree(vsi->dev);
818 	child = SYSCTL_CHILDREN(tree);
819 	vsi->vsi_node = SYSCTL_ADD_NODE(&vsi->sysctl_ctx, child, OID_AUTO, sysctl_name,
820 			CTLFLAG_RD, NULL, "VSI Number");
821 
822 	vsi_list = SYSCTL_CHILDREN(vsi->vsi_node);
823 	ixl_add_sysctls_eth_stats(&vsi->sysctl_ctx, vsi_list, &vsi->eth_stats);
824 
825 	/* Copy of netstat RX errors counter for validation purposes */
826 	SYSCTL_ADD_UQUAD(&vsi->sysctl_ctx, vsi_list, OID_AUTO, "rx_errors",
827 			CTLFLAG_RD, &vsi->ierrors,
828 			"RX packet errors");
829 
830 	if (queues_sysctls)
831 		ixl_vsi_add_queues_stats(vsi, &vsi->sysctl_ctx);
832 }
833 
834 /*
835  * Used to set the Tx ITR value for all of the PF LAN VSI's queues.
836  * Writes to the ITR registers immediately.
837  */
838 static int
ixl_sysctl_pf_tx_itr(SYSCTL_HANDLER_ARGS)839 ixl_sysctl_pf_tx_itr(SYSCTL_HANDLER_ARGS)
840 {
841 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
842 	device_t dev = pf->dev;
843 	int error = 0;
844 	int requested_tx_itr;
845 
846 	requested_tx_itr = pf->tx_itr;
847 	error = sysctl_handle_int(oidp, &requested_tx_itr, 0, req);
848 	if ((error) || (req->newptr == NULL))
849 		return (error);
850 	if (pf->dynamic_tx_itr) {
851 		device_printf(dev,
852 		    "Cannot set TX itr value while dynamic TX itr is enabled\n");
853 		    return (EINVAL);
854 	}
855 	if (requested_tx_itr < 0 || requested_tx_itr > IXL_MAX_ITR) {
856 		device_printf(dev,
857 		    "Invalid TX itr value; value must be between 0 and %d\n",
858 		        IXL_MAX_ITR);
859 		return (EINVAL);
860 	}
861 
862 	pf->tx_itr = requested_tx_itr;
863 	ixl_configure_tx_itr(pf);
864 
865 	return (error);
866 }
867 
868 /*
869  * Used to set the Rx ITR value for all of the PF LAN VSI's queues.
870  * Writes to the ITR registers immediately.
871  */
872 static int
ixl_sysctl_pf_rx_itr(SYSCTL_HANDLER_ARGS)873 ixl_sysctl_pf_rx_itr(SYSCTL_HANDLER_ARGS)
874 {
875 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
876 	device_t dev = pf->dev;
877 	int error = 0;
878 	int requested_rx_itr;
879 
880 	requested_rx_itr = pf->rx_itr;
881 	error = sysctl_handle_int(oidp, &requested_rx_itr, 0, req);
882 	if ((error) || (req->newptr == NULL))
883 		return (error);
884 	if (pf->dynamic_rx_itr) {
885 		device_printf(dev,
886 		    "Cannot set RX itr value while dynamic RX itr is enabled\n");
887 		    return (EINVAL);
888 	}
889 	if (requested_rx_itr < 0 || requested_rx_itr > IXL_MAX_ITR) {
890 		device_printf(dev,
891 		    "Invalid RX itr value; value must be between 0 and %d\n",
892 		        IXL_MAX_ITR);
893 		return (EINVAL);
894 	}
895 
896 	pf->rx_itr = requested_rx_itr;
897 	ixl_configure_rx_itr(pf);
898 
899 	return (error);
900 }
901 
902 void
ixl_add_sysctls_mac_stats(struct sysctl_ctx_list * ctx,struct sysctl_oid_list * child,struct i40e_hw_port_stats * stats)903 ixl_add_sysctls_mac_stats(struct sysctl_ctx_list *ctx,
904 	struct sysctl_oid_list *child,
905 	struct i40e_hw_port_stats *stats)
906 {
907 	struct sysctl_oid *stat_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "mac",
908 				    CTLFLAG_RD, NULL, "Mac Statistics");
909 	struct sysctl_oid_list *stat_list = SYSCTL_CHILDREN(stat_node);
910 
911 	struct i40e_eth_stats *eth_stats = &stats->eth;
912 	ixl_add_sysctls_eth_stats(ctx, stat_list, eth_stats);
913 
914 	struct ixl_sysctl_info ctls[] =
915 	{
916 		{&stats->crc_errors, "crc_errors", "CRC Errors"},
917 		{&stats->illegal_bytes, "illegal_bytes", "Illegal Byte Errors"},
918 		{&stats->mac_local_faults, "local_faults", "MAC Local Faults"},
919 		{&stats->mac_remote_faults, "remote_faults", "MAC Remote Faults"},
920 		{&stats->rx_length_errors, "rx_length_errors", "Receive Length Errors"},
921 		/* Packet Reception Stats */
922 		{&stats->rx_size_64, "rx_frames_64", "64 byte frames received"},
923 		{&stats->rx_size_127, "rx_frames_65_127", "65-127 byte frames received"},
924 		{&stats->rx_size_255, "rx_frames_128_255", "128-255 byte frames received"},
925 		{&stats->rx_size_511, "rx_frames_256_511", "256-511 byte frames received"},
926 		{&stats->rx_size_1023, "rx_frames_512_1023", "512-1023 byte frames received"},
927 		{&stats->rx_size_1522, "rx_frames_1024_1522", "1024-1522 byte frames received"},
928 		{&stats->rx_size_big, "rx_frames_big", "1523-9522 byte frames received"},
929 		{&stats->rx_undersize, "rx_undersize", "Undersized packets received"},
930 		{&stats->rx_fragments, "rx_fragmented", "Fragmented packets received"},
931 		{&stats->rx_oversize, "rx_oversized", "Oversized packets received"},
932 		{&stats->rx_jabber, "rx_jabber", "Received Jabber"},
933 		{&stats->checksum_error, "checksum_errors", "Checksum Errors"},
934 		/* Packet Transmission Stats */
935 		{&stats->tx_size_64, "tx_frames_64", "64 byte frames transmitted"},
936 		{&stats->tx_size_127, "tx_frames_65_127", "65-127 byte frames transmitted"},
937 		{&stats->tx_size_255, "tx_frames_128_255", "128-255 byte frames transmitted"},
938 		{&stats->tx_size_511, "tx_frames_256_511", "256-511 byte frames transmitted"},
939 		{&stats->tx_size_1023, "tx_frames_512_1023", "512-1023 byte frames transmitted"},
940 		{&stats->tx_size_1522, "tx_frames_1024_1522", "1024-1522 byte frames transmitted"},
941 		{&stats->tx_size_big, "tx_frames_big", "1523-9522 byte frames transmitted"},
942 		/* Flow control */
943 		{&stats->link_xon_tx, "xon_txd", "Link XON transmitted"},
944 		{&stats->link_xon_rx, "xon_recvd", "Link XON received"},
945 		{&stats->link_xoff_tx, "xoff_txd", "Link XOFF transmitted"},
946 		{&stats->link_xoff_rx, "xoff_recvd", "Link XOFF received"},
947 		/* End */
948 		{0,0,0}
949 	};
950 
951 	struct ixl_sysctl_info *entry = ctls;
952 	while (entry->stat != 0)
953 	{
954 		SYSCTL_ADD_UQUAD(ctx, stat_list, OID_AUTO, entry->name,
955 				CTLFLAG_RD, entry->stat,
956 				entry->description);
957 		entry++;
958 	}
959 }
960 
961 void
ixl_set_rss_key(struct ixl_pf * pf)962 ixl_set_rss_key(struct ixl_pf *pf)
963 {
964 	struct i40e_hw *hw = &pf->hw;
965 	struct ixl_vsi *vsi = &pf->vsi;
966 	device_t	dev = pf->dev;
967 	u32 rss_seed[IXL_RSS_KEY_SIZE_REG];
968 	enum i40e_status_code status;
969 
970 #ifdef RSS
971         /* Fetch the configured RSS key */
972         rss_getkey((uint8_t *) &rss_seed);
973 #else
974 	ixl_get_default_rss_key(rss_seed);
975 #endif
976 	/* Fill out hash function seed */
977 	if (hw->mac.type == I40E_MAC_X722) {
978 		struct i40e_aqc_get_set_rss_key_data key_data;
979 		bcopy(rss_seed, &key_data, 52);
980 		status = i40e_aq_set_rss_key(hw, vsi->vsi_num, &key_data);
981 		if (status)
982 			device_printf(dev,
983 			    "i40e_aq_set_rss_key status %s, error %s\n",
984 			    i40e_stat_str(hw, status),
985 			    i40e_aq_str(hw, hw->aq.asq_last_status));
986 	} else {
987 		for (int i = 0; i < IXL_RSS_KEY_SIZE_REG; i++)
988 			i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i), rss_seed[i]);
989 	}
990 }
991 
992 /*
993  * Configure enabled PCTYPES for RSS.
994  */
995 void
ixl_set_rss_pctypes(struct ixl_pf * pf)996 ixl_set_rss_pctypes(struct ixl_pf *pf)
997 {
998 	struct i40e_hw *hw = &pf->hw;
999 	u64		set_hena = 0, hena;
1000 
1001 #ifdef RSS
1002 	u32		rss_hash_config;
1003 
1004 	rss_hash_config = rss_gethashconfig();
1005 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4)
1006                 set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER);
1007 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4)
1008                 set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
1009 	if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4)
1010                 set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP);
1011 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6)
1012                 set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER);
1013 	if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6_EX)
1014 		set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6);
1015 	if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6)
1016                 set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
1017         if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6)
1018                 set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP);
1019 #else
1020 	if (hw->mac.type == I40E_MAC_X722)
1021 		set_hena = IXL_DEFAULT_RSS_HENA_X722;
1022 	else
1023 		set_hena = IXL_DEFAULT_RSS_HENA_XL710;
1024 #endif
1025 	hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) |
1026 	    ((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32);
1027 	hena |= set_hena;
1028 	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena);
1029 	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (u32)(hena >> 32));
1030 
1031 }
1032 
1033 /*
1034 ** Setup the PF's RSS parameters.
1035 */
1036 void
ixl_config_rss(struct ixl_pf * pf)1037 ixl_config_rss(struct ixl_pf *pf)
1038 {
1039 	ixl_set_rss_key(pf);
1040 	ixl_set_rss_pctypes(pf);
1041 	ixl_set_rss_hlut(pf);
1042 }
1043 
1044 /*
1045  * In some firmware versions there is default MAC/VLAN filter
1046  * configured which interferes with filters managed by driver.
1047  * Make sure it's removed.
1048  */
1049 void
ixl_del_default_hw_filters(struct ixl_vsi * vsi)1050 ixl_del_default_hw_filters(struct ixl_vsi *vsi)
1051 {
1052 	struct i40e_aqc_remove_macvlan_element_data e;
1053 
1054 	bzero(&e, sizeof(e));
1055 	bcopy(vsi->hw->mac.perm_addr, e.mac_addr, ETHER_ADDR_LEN);
1056 	e.vlan_tag = 0;
1057 	e.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
1058 	i40e_aq_remove_macvlan(vsi->hw, vsi->seid, &e, 1, NULL);
1059 
1060 	bzero(&e, sizeof(e));
1061 	bcopy(vsi->hw->mac.perm_addr, e.mac_addr, ETHER_ADDR_LEN);
1062 	e.vlan_tag = 0;
1063 	e.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
1064 		I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
1065 	i40e_aq_remove_macvlan(vsi->hw, vsi->seid, &e, 1, NULL);
1066 }
1067 
1068 /*
1069 ** Initialize filter list and add filters that the hardware
1070 ** needs to know about.
1071 **
1072 ** Requires VSI's seid to be set before calling.
1073 */
1074 void
ixl_init_filters(struct ixl_vsi * vsi)1075 ixl_init_filters(struct ixl_vsi *vsi)
1076 {
1077 	struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
1078 
1079 	ixl_dbg_filter(pf, "%s: start\n", __func__);
1080 
1081 	/* Initialize mac filter list for VSI */
1082 	LIST_INIT(&vsi->ftl);
1083 	vsi->num_hw_filters = 0;
1084 
1085 	/* Receive broadcast Ethernet frames */
1086 	i40e_aq_set_vsi_broadcast(&pf->hw, vsi->seid, TRUE, NULL);
1087 
1088 	if (IXL_VSI_IS_VF(vsi))
1089 		return;
1090 
1091 	ixl_del_default_hw_filters(vsi);
1092 
1093 	ixl_add_filter(vsi, vsi->hw->mac.addr, IXL_VLAN_ANY);
1094 
1095 	/*
1096 	 * Prevent Tx flow control frames from being sent out by
1097 	 * non-firmware transmitters.
1098 	 * This affects every VSI in the PF.
1099 	 */
1100 #ifndef IXL_DEBUG_FC
1101 	i40e_add_filter_to_drop_tx_flow_control_frames(vsi->hw, vsi->seid);
1102 #else
1103 	if (pf->enable_tx_fc_filter)
1104 		i40e_add_filter_to_drop_tx_flow_control_frames(vsi->hw, vsi->seid);
1105 #endif
1106 }
1107 
1108 void
ixl_reconfigure_filters(struct ixl_vsi * vsi)1109 ixl_reconfigure_filters(struct ixl_vsi *vsi)
1110 {
1111 	struct i40e_hw *hw = vsi->hw;
1112 	struct ixl_ftl_head tmp;
1113 	int cnt;
1114 
1115 	/*
1116 	 * The ixl_add_hw_filters function adds filters configured
1117 	 * in HW to a list in VSI. Move all filters to a temporary
1118 	 * list to avoid corrupting it by concatenating to itself.
1119 	 */
1120 	LIST_INIT(&tmp);
1121 	LIST_CONCAT(&tmp, &vsi->ftl, ixl_mac_filter, ftle);
1122 	cnt = vsi->num_hw_filters;
1123 	vsi->num_hw_filters = 0;
1124 
1125 	ixl_add_hw_filters(vsi, &tmp, cnt);
1126 
1127 	/*
1128 	 * When the vsi is allocated for the VFs, both vsi->hw and vsi->ifp
1129 	 * will be NULL. Furthermore, the ftl of such vsi already contains
1130 	 * IXL_VLAN_ANY filter so we can skip that as well.
1131 	 */
1132 	if (hw == NULL)
1133 		return;
1134 
1135 	/* Filter could be removed if MAC address was changed */
1136 	ixl_add_filter(vsi, hw->mac.addr, IXL_VLAN_ANY);
1137 
1138 	if ((if_getcapenable(vsi->ifp) & IFCAP_VLAN_HWFILTER) == 0)
1139 		return;
1140 	/*
1141 	 * VLAN HW filtering is enabled, make sure that filters
1142 	 * for all registered VLAN tags are configured
1143 	 */
1144 	ixl_add_vlan_filters(vsi, hw->mac.addr);
1145 }
1146 
1147 /*
1148  * This routine adds a MAC/VLAN filter to the software filter
1149  * list, then adds that new filter to the HW if it doesn't already
1150  * exist in the SW filter list.
1151  */
1152 void
ixl_add_filter(struct ixl_vsi * vsi,const u8 * macaddr,s16 vlan)1153 ixl_add_filter(struct ixl_vsi *vsi, const u8 *macaddr, s16 vlan)
1154 {
1155 	struct ixl_mac_filter	*f, *tmp;
1156 	struct ixl_pf		*pf;
1157 	device_t		dev;
1158 	struct ixl_ftl_head	to_add;
1159 	int			to_add_cnt;
1160 
1161 	pf = vsi->back;
1162 	dev = pf->dev;
1163 	to_add_cnt = 1;
1164 
1165 	ixl_dbg_filter(pf, "ixl_add_filter: " MAC_FORMAT ", vlan %4d\n",
1166 	    MAC_FORMAT_ARGS(macaddr), vlan);
1167 
1168 	/* Does one already exist */
1169 	f = ixl_find_filter(&vsi->ftl, macaddr, vlan);
1170 	if (f != NULL)
1171 		return;
1172 
1173 	LIST_INIT(&to_add);
1174 	f = ixl_new_filter(&to_add, macaddr, vlan);
1175 	if (f == NULL) {
1176 		device_printf(dev, "WARNING: no filter available!!\n");
1177 		return;
1178 	}
1179 	if (f->vlan != IXL_VLAN_ANY)
1180 		f->flags |= IXL_FILTER_VLAN;
1181 	else
1182 		vsi->num_macs++;
1183 
1184 	/*
1185 	** Is this the first vlan being registered, if so we
1186 	** need to remove the ANY filter that indicates we are
1187 	** not in a vlan, and replace that with a 0 filter.
1188 	*/
1189 	if ((vlan != IXL_VLAN_ANY) && (vsi->num_vlans == 1)) {
1190 		tmp = ixl_find_filter(&vsi->ftl, macaddr, IXL_VLAN_ANY);
1191 		if (tmp != NULL) {
1192 			struct ixl_ftl_head to_del;
1193 
1194 			/* Prepare new filter first to avoid removing
1195 			 * VLAN_ANY filter if allocation fails */
1196 			f = ixl_new_filter(&to_add, macaddr, 0);
1197 			if (f == NULL) {
1198 				device_printf(dev, "WARNING: no filter available!!\n");
1199 				free(LIST_FIRST(&to_add), M_IXL);
1200 				return;
1201 			}
1202 			to_add_cnt++;
1203 
1204 			LIST_REMOVE(tmp, ftle);
1205 			LIST_INIT(&to_del);
1206 			LIST_INSERT_HEAD(&to_del, tmp, ftle);
1207 			ixl_del_hw_filters(vsi, &to_del, 1);
1208 		}
1209 	}
1210 
1211 	ixl_add_hw_filters(vsi, &to_add, to_add_cnt);
1212 }
1213 
1214 /**
1215  * ixl_add_vlan_filters - Add MAC/VLAN filters for all registered VLANs
1216  * @vsi: pointer to VSI
1217  * @macaddr: MAC address
1218  *
1219  * Adds MAC/VLAN filter for each VLAN configured on the interface
1220  * if there is enough HW filters. Otherwise adds a single filter
1221  * for all tagged and untagged frames to allow all configured VLANs
1222  * to recieve traffic.
1223  */
1224 void
ixl_add_vlan_filters(struct ixl_vsi * vsi,const u8 * macaddr)1225 ixl_add_vlan_filters(struct ixl_vsi *vsi, const u8 *macaddr)
1226 {
1227 	struct ixl_ftl_head to_add;
1228 	struct ixl_mac_filter *f;
1229 	int to_add_cnt = 0;
1230 	int i, vlan = 0;
1231 
1232 	if (vsi->num_vlans == 0 || vsi->num_vlans > IXL_MAX_VLAN_FILTERS) {
1233 		ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY);
1234 		return;
1235 	}
1236 	LIST_INIT(&to_add);
1237 
1238 	/* Add filter for untagged frames if it does not exist yet */
1239 	f = ixl_find_filter(&vsi->ftl, macaddr, 0);
1240 	if (f == NULL) {
1241 		f = ixl_new_filter(&to_add, macaddr, 0);
1242 		if (f == NULL) {
1243 			device_printf(vsi->dev, "WARNING: no filter available!!\n");
1244 			return;
1245 		}
1246 		to_add_cnt++;
1247 	}
1248 
1249 	for (i = 1; i < EVL_VLID_MASK; i = vlan + 1) {
1250 		bit_ffs_at(vsi->vlans_map, i, IXL_VLANS_MAP_LEN, &vlan);
1251 		if (vlan == -1)
1252 			break;
1253 
1254 		/* Does one already exist */
1255 		f = ixl_find_filter(&vsi->ftl, macaddr, vlan);
1256 		if (f != NULL)
1257 			continue;
1258 
1259 		f = ixl_new_filter(&to_add, macaddr, vlan);
1260 		if (f == NULL) {
1261 			device_printf(vsi->dev, "WARNING: no filter available!!\n");
1262 			ixl_free_filters(&to_add);
1263 			return;
1264 		}
1265 		to_add_cnt++;
1266 	}
1267 
1268 	ixl_add_hw_filters(vsi, &to_add, to_add_cnt);
1269 }
1270 
1271 void
ixl_del_filter(struct ixl_vsi * vsi,const u8 * macaddr,s16 vlan)1272 ixl_del_filter(struct ixl_vsi *vsi, const u8 *macaddr, s16 vlan)
1273 {
1274 	struct ixl_mac_filter *f, *tmp;
1275 	struct ixl_ftl_head ftl_head;
1276 	int to_del_cnt = 1;
1277 
1278 	ixl_dbg_filter((struct ixl_pf *)vsi->back,
1279 	    "ixl_del_filter: " MAC_FORMAT ", vlan %4d\n",
1280 	    MAC_FORMAT_ARGS(macaddr), vlan);
1281 
1282 	f = ixl_find_filter(&vsi->ftl, macaddr, vlan);
1283 	if (f == NULL)
1284 		return;
1285 
1286 	LIST_REMOVE(f, ftle);
1287 	LIST_INIT(&ftl_head);
1288 	LIST_INSERT_HEAD(&ftl_head, f, ftle);
1289 	if (f->vlan == IXL_VLAN_ANY && (f->flags & IXL_FILTER_VLAN) != 0)
1290 		vsi->num_macs--;
1291 
1292 	/* If this is not the last vlan just remove the filter */
1293 	if (vlan == IXL_VLAN_ANY || vsi->num_vlans > 0) {
1294 		ixl_del_hw_filters(vsi, &ftl_head, to_del_cnt);
1295 		return;
1296 	}
1297 
1298 	/* It's the last vlan, we need to switch back to a non-vlan filter */
1299 	tmp = ixl_find_filter(&vsi->ftl, macaddr, 0);
1300 	if (tmp != NULL) {
1301 		LIST_REMOVE(tmp, ftle);
1302 		LIST_INSERT_AFTER(f, tmp, ftle);
1303 		to_del_cnt++;
1304 	}
1305 	ixl_del_hw_filters(vsi, &ftl_head, to_del_cnt);
1306 
1307 	ixl_add_filter(vsi, macaddr, IXL_VLAN_ANY);
1308 }
1309 
1310 /**
1311  * ixl_del_all_vlan_filters - Delete all VLAN filters with given MAC
1312  * @vsi: VSI which filters need to be removed
1313  * @macaddr: MAC address
1314  *
1315  * Remove all MAC/VLAN filters with a given MAC address. For multicast
1316  * addresses there is always single filter for all VLANs used (IXL_VLAN_ANY)
1317  * so skip them to speed up processing. Those filters should be removed
1318  * using ixl_del_filter function.
1319  */
1320 void
ixl_del_all_vlan_filters(struct ixl_vsi * vsi,const u8 * macaddr)1321 ixl_del_all_vlan_filters(struct ixl_vsi *vsi, const u8 *macaddr)
1322 {
1323 	struct ixl_mac_filter *f, *tmp;
1324 	struct ixl_ftl_head to_del;
1325 	int to_del_cnt = 0;
1326 
1327 	LIST_INIT(&to_del);
1328 
1329 	LIST_FOREACH_SAFE(f, &vsi->ftl, ftle, tmp) {
1330 		if ((f->flags & IXL_FILTER_MC) != 0 ||
1331 		    !ixl_ether_is_equal(f->macaddr, macaddr))
1332 			continue;
1333 
1334 		LIST_REMOVE(f, ftle);
1335 		LIST_INSERT_HEAD(&to_del, f, ftle);
1336 		to_del_cnt++;
1337 	}
1338 
1339 	ixl_dbg_filter((struct ixl_pf *)vsi->back,
1340 	    "%s: " MAC_FORMAT ", to_del_cnt: %d\n",
1341 	    __func__, MAC_FORMAT_ARGS(macaddr), to_del_cnt);
1342 	if (to_del_cnt > 0)
1343 		ixl_del_hw_filters(vsi, &to_del, to_del_cnt);
1344 }
1345 
1346 /*
1347 ** Find the filter with both matching mac addr and vlan id
1348 */
1349 struct ixl_mac_filter *
ixl_find_filter(struct ixl_ftl_head * headp,const u8 * macaddr,s16 vlan)1350 ixl_find_filter(struct ixl_ftl_head *headp, const u8 *macaddr, s16 vlan)
1351 {
1352 	struct ixl_mac_filter	*f;
1353 
1354 	LIST_FOREACH(f, headp, ftle) {
1355 		if (ixl_ether_is_equal(f->macaddr, macaddr) &&
1356 		    (f->vlan == vlan)) {
1357 			return (f);
1358 		}
1359 	}
1360 
1361 	return (NULL);
1362 }
1363 
1364 /*
1365 ** This routine takes additions to the vsi filter
1366 ** table and creates an Admin Queue call to create
1367 ** the filters in the hardware.
1368 */
1369 void
ixl_add_hw_filters(struct ixl_vsi * vsi,struct ixl_ftl_head * to_add,int cnt)1370 ixl_add_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_add, int cnt)
1371 {
1372 	struct i40e_aqc_add_macvlan_element_data *a, *b;
1373 	struct ixl_mac_filter	*f, *fn;
1374 	struct ixl_pf		*pf;
1375 	struct i40e_hw		*hw;
1376 	device_t		dev;
1377 	enum i40e_status_code	status;
1378 	int			j = 0;
1379 
1380 	pf = vsi->back;
1381 	dev = vsi->dev;
1382 	hw = &pf->hw;
1383 
1384 	ixl_dbg_filter(pf, "ixl_add_hw_filters: cnt: %d\n", cnt);
1385 
1386 	if (cnt < 1) {
1387 		ixl_dbg_info(pf, "ixl_add_hw_filters: cnt == 0\n");
1388 		return;
1389 	}
1390 
1391 	a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt,
1392 	    M_IXL, M_NOWAIT | M_ZERO);
1393 	if (a == NULL) {
1394 		device_printf(dev, "add_hw_filters failed to get memory\n");
1395 		return;
1396 	}
1397 
1398 	LIST_FOREACH(f, to_add, ftle) {
1399 		b = &a[j]; // a pox on fvl long names :)
1400 		bcopy(f->macaddr, b->mac_addr, ETHER_ADDR_LEN);
1401 		if (f->vlan == IXL_VLAN_ANY) {
1402 			b->vlan_tag = 0;
1403 			b->flags = I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
1404 		} else {
1405 			b->vlan_tag = f->vlan;
1406 			b->flags = 0;
1407 		}
1408 		b->flags |= I40E_AQC_MACVLAN_ADD_PERFECT_MATCH;
1409 		ixl_dbg_filter(pf, "ADD: " MAC_FORMAT "\n",
1410 		    MAC_FORMAT_ARGS(f->macaddr));
1411 
1412 		if (++j == cnt)
1413 			break;
1414 	}
1415 	if (j != cnt) {
1416 		/* Something went wrong */
1417 		device_printf(dev,
1418 		    "%s ERROR: list of filters to short expected: %d, found: %d\n",
1419 		    __func__, cnt, j);
1420 		ixl_free_filters(to_add);
1421 		goto out_free;
1422 	}
1423 
1424 	status = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL);
1425 	if (status == I40E_SUCCESS) {
1426 		LIST_CONCAT(&vsi->ftl, to_add, ixl_mac_filter, ftle);
1427 		vsi->num_hw_filters += j;
1428 		goto out_free;
1429 	}
1430 
1431 	device_printf(dev,
1432 	    "i40e_aq_add_macvlan status %s, error %s\n",
1433 	    i40e_stat_str(hw, status),
1434 	    i40e_aq_str(hw, hw->aq.asq_last_status));
1435 	j = 0;
1436 
1437 	/* Verify which filters were actually configured in HW
1438 	 * and add them to the list */
1439 	LIST_FOREACH_SAFE(f, to_add, ftle, fn) {
1440 		LIST_REMOVE(f, ftle);
1441 		if (a[j].match_method == I40E_AQC_MM_ERR_NO_RES) {
1442 			ixl_dbg_filter(pf,
1443 			    "%s filter " MAC_FORMAT " VTAG: %d not added\n",
1444 			    __func__,
1445 			    MAC_FORMAT_ARGS(f->macaddr),
1446 			    f->vlan);
1447 			free(f, M_IXL);
1448 		} else {
1449 			LIST_INSERT_HEAD(&vsi->ftl, f, ftle);
1450 			vsi->num_hw_filters++;
1451 		}
1452 		j++;
1453 	}
1454 
1455 out_free:
1456 	free(a, M_IXL);
1457 }
1458 
1459 /*
1460 ** This routine takes removals in the vsi filter
1461 ** table and creates an Admin Queue call to delete
1462 ** the filters in the hardware.
1463 */
1464 void
ixl_del_hw_filters(struct ixl_vsi * vsi,struct ixl_ftl_head * to_del,int cnt)1465 ixl_del_hw_filters(struct ixl_vsi *vsi, struct ixl_ftl_head *to_del, int cnt)
1466 {
1467 	struct i40e_aqc_remove_macvlan_element_data *d, *e;
1468 	struct ixl_pf		*pf;
1469 	struct i40e_hw		*hw;
1470 	device_t		dev;
1471 	struct ixl_mac_filter	*f, *f_temp;
1472 	enum i40e_status_code	status;
1473 	int			j = 0;
1474 
1475 	pf = vsi->back;
1476 	hw = &pf->hw;
1477 	dev = vsi->dev;
1478 
1479 	ixl_dbg_filter(pf, "%s: start, cnt: %d\n", __func__, cnt);
1480 
1481 	d = malloc(sizeof(struct i40e_aqc_remove_macvlan_element_data) * cnt,
1482 	    M_IXL, M_NOWAIT | M_ZERO);
1483 	if (d == NULL) {
1484 		device_printf(dev, "%s: failed to get memory\n", __func__);
1485 		return;
1486 	}
1487 
1488 	LIST_FOREACH_SAFE(f, to_del, ftle, f_temp) {
1489 		e = &d[j]; // a pox on fvl long names :)
1490 		bcopy(f->macaddr, e->mac_addr, ETHER_ADDR_LEN);
1491 		e->flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH;
1492 		if (f->vlan == IXL_VLAN_ANY) {
1493 			e->vlan_tag = 0;
1494 			e->flags |= I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
1495 		} else {
1496 			e->vlan_tag = f->vlan;
1497 		}
1498 
1499 		ixl_dbg_filter(pf, "DEL: " MAC_FORMAT "\n",
1500 		    MAC_FORMAT_ARGS(f->macaddr));
1501 
1502 		/* delete entry from the list */
1503 		LIST_REMOVE(f, ftle);
1504 		free(f, M_IXL);
1505 		if (++j == cnt)
1506 			break;
1507 	}
1508 	if (j != cnt || !LIST_EMPTY(to_del)) {
1509 		/* Something went wrong */
1510 		device_printf(dev,
1511 		    "%s ERROR: wrong size of list of filters, expected: %d, found: %d\n",
1512 		    __func__, cnt, j);
1513 		ixl_free_filters(to_del);
1514 		goto out_free;
1515 	}
1516 	status = i40e_aq_remove_macvlan(hw, vsi->seid, d, j, NULL);
1517 	if (status) {
1518 		device_printf(dev,
1519 		    "%s: i40e_aq_remove_macvlan status %s, error %s\n",
1520 		    __func__, i40e_stat_str(hw, status),
1521 		    i40e_aq_str(hw, hw->aq.asq_last_status));
1522 		for (int i = 0; i < j; i++) {
1523 			if (d[i].error_code == 0)
1524 				continue;
1525 			device_printf(dev,
1526 			    "%s Filter does not exist " MAC_FORMAT " VTAG: %d\n",
1527 			    __func__, MAC_FORMAT_ARGS(d[i].mac_addr),
1528 			    d[i].vlan_tag);
1529 		}
1530 	}
1531 
1532 	vsi->num_hw_filters -= j;
1533 
1534 out_free:
1535 	free(d, M_IXL);
1536 
1537 	ixl_dbg_filter(pf, "%s: end\n", __func__);
1538 }
1539 
1540 int
ixl_enable_tx_ring(struct ixl_pf * pf,struct ixl_pf_qtag * qtag,u16 vsi_qidx)1541 ixl_enable_tx_ring(struct ixl_pf *pf, struct ixl_pf_qtag *qtag, u16 vsi_qidx)
1542 {
1543 	struct i40e_hw	*hw = &pf->hw;
1544 	int		error = 0;
1545 	u32		reg;
1546 	u16		pf_qidx;
1547 
1548 	pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
1549 
1550 	ixl_dbg(pf, IXL_DBG_EN_DIS,
1551 	    "Enabling PF TX ring %4d / VSI TX ring %4d...\n",
1552 	    pf_qidx, vsi_qidx);
1553 
1554 	i40e_pre_tx_queue_cfg(hw, pf_qidx, TRUE);
1555 
1556 	reg = rd32(hw, I40E_QTX_ENA(pf_qidx));
1557 	reg |= I40E_QTX_ENA_QENA_REQ_MASK |
1558 	    I40E_QTX_ENA_QENA_STAT_MASK;
1559 	wr32(hw, I40E_QTX_ENA(pf_qidx), reg);
1560 	/* Verify the enable took */
1561 	for (int j = 0; j < 10; j++) {
1562 		reg = rd32(hw, I40E_QTX_ENA(pf_qidx));
1563 		if (reg & I40E_QTX_ENA_QENA_STAT_MASK)
1564 			break;
1565 		i40e_usec_delay(10);
1566 	}
1567 	if ((reg & I40E_QTX_ENA_QENA_STAT_MASK) == 0) {
1568 		device_printf(pf->dev, "TX queue %d still disabled!\n",
1569 		    pf_qidx);
1570 		error = ETIMEDOUT;
1571 	}
1572 
1573 	return (error);
1574 }
1575 
1576 int
ixl_enable_rx_ring(struct ixl_pf * pf,struct ixl_pf_qtag * qtag,u16 vsi_qidx)1577 ixl_enable_rx_ring(struct ixl_pf *pf, struct ixl_pf_qtag *qtag, u16 vsi_qidx)
1578 {
1579 	struct i40e_hw	*hw = &pf->hw;
1580 	int		error = 0;
1581 	u32		reg;
1582 	u16		pf_qidx;
1583 
1584 	pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
1585 
1586 	ixl_dbg(pf, IXL_DBG_EN_DIS,
1587 	    "Enabling PF RX ring %4d / VSI RX ring %4d...\n",
1588 	    pf_qidx, vsi_qidx);
1589 
1590 	reg = rd32(hw, I40E_QRX_ENA(pf_qidx));
1591 	reg |= I40E_QRX_ENA_QENA_REQ_MASK |
1592 	    I40E_QRX_ENA_QENA_STAT_MASK;
1593 	wr32(hw, I40E_QRX_ENA(pf_qidx), reg);
1594 	/* Verify the enable took */
1595 	for (int j = 0; j < 10; j++) {
1596 		reg = rd32(hw, I40E_QRX_ENA(pf_qidx));
1597 		if (reg & I40E_QRX_ENA_QENA_STAT_MASK)
1598 			break;
1599 		i40e_usec_delay(10);
1600 	}
1601 	if ((reg & I40E_QRX_ENA_QENA_STAT_MASK) == 0) {
1602 		device_printf(pf->dev, "RX queue %d still disabled!\n",
1603 		    pf_qidx);
1604 		error = ETIMEDOUT;
1605 	}
1606 
1607 	return (error);
1608 }
1609 
1610 int
ixl_enable_ring(struct ixl_pf * pf,struct ixl_pf_qtag * qtag,u16 vsi_qidx)1611 ixl_enable_ring(struct ixl_pf *pf, struct ixl_pf_qtag *qtag, u16 vsi_qidx)
1612 {
1613 	int error = 0;
1614 
1615 	error = ixl_enable_tx_ring(pf, qtag, vsi_qidx);
1616 	/* Called function already prints error message */
1617 	if (error)
1618 		return (error);
1619 	error = ixl_enable_rx_ring(pf, qtag, vsi_qidx);
1620 	return (error);
1621 }
1622 
1623 /*
1624  * Returns error on first ring that is detected hung.
1625  */
1626 int
ixl_disable_tx_ring(struct ixl_pf * pf,struct ixl_pf_qtag * qtag,u16 vsi_qidx)1627 ixl_disable_tx_ring(struct ixl_pf *pf, struct ixl_pf_qtag *qtag, u16 vsi_qidx)
1628 {
1629 	struct i40e_hw	*hw = &pf->hw;
1630 	int		error = 0;
1631 	u32		reg;
1632 	u16		pf_qidx;
1633 
1634 	pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
1635 
1636 	ixl_dbg(pf, IXL_DBG_EN_DIS,
1637 	    "Disabling PF TX ring %4d / VSI TX ring %4d...\n",
1638 	    pf_qidx, vsi_qidx);
1639 
1640 	i40e_pre_tx_queue_cfg(hw, pf_qidx, FALSE);
1641 	i40e_usec_delay(500);
1642 
1643 	reg = rd32(hw, I40E_QTX_ENA(pf_qidx));
1644 	reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
1645 	wr32(hw, I40E_QTX_ENA(pf_qidx), reg);
1646 	/* Verify the disable took */
1647 	for (int j = 0; j < 10; j++) {
1648 		reg = rd32(hw, I40E_QTX_ENA(pf_qidx));
1649 		if (!(reg & I40E_QTX_ENA_QENA_STAT_MASK))
1650 			break;
1651 		i40e_msec_delay(10);
1652 	}
1653 	if (reg & I40E_QTX_ENA_QENA_STAT_MASK) {
1654 		device_printf(pf->dev, "TX queue %d still enabled!\n",
1655 		    pf_qidx);
1656 		error = ETIMEDOUT;
1657 	}
1658 
1659 	return (error);
1660 }
1661 
1662 /*
1663  * Returns error on first ring that is detected hung.
1664  */
1665 int
ixl_disable_rx_ring(struct ixl_pf * pf,struct ixl_pf_qtag * qtag,u16 vsi_qidx)1666 ixl_disable_rx_ring(struct ixl_pf *pf, struct ixl_pf_qtag *qtag, u16 vsi_qidx)
1667 {
1668 	struct i40e_hw	*hw = &pf->hw;
1669 	int		error = 0;
1670 	u32		reg;
1671 	u16		pf_qidx;
1672 
1673 	pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
1674 
1675 	ixl_dbg(pf, IXL_DBG_EN_DIS,
1676 	    "Disabling PF RX ring %4d / VSI RX ring %4d...\n",
1677 	    pf_qidx, vsi_qidx);
1678 
1679 	reg = rd32(hw, I40E_QRX_ENA(pf_qidx));
1680 	reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
1681 	wr32(hw, I40E_QRX_ENA(pf_qidx), reg);
1682 	/* Verify the disable took */
1683 	for (int j = 0; j < 10; j++) {
1684 		reg = rd32(hw, I40E_QRX_ENA(pf_qidx));
1685 		if (!(reg & I40E_QRX_ENA_QENA_STAT_MASK))
1686 			break;
1687 		i40e_msec_delay(10);
1688 	}
1689 	if (reg & I40E_QRX_ENA_QENA_STAT_MASK) {
1690 		device_printf(pf->dev, "RX queue %d still enabled!\n",
1691 		    pf_qidx);
1692 		error = ETIMEDOUT;
1693 	}
1694 
1695 	return (error);
1696 }
1697 
1698 int
ixl_disable_ring(struct ixl_pf * pf,struct ixl_pf_qtag * qtag,u16 vsi_qidx)1699 ixl_disable_ring(struct ixl_pf *pf, struct ixl_pf_qtag *qtag, u16 vsi_qidx)
1700 {
1701 	int error = 0;
1702 
1703 	error = ixl_disable_tx_ring(pf, qtag, vsi_qidx);
1704 	/* Called function already prints error message */
1705 	if (error)
1706 		return (error);
1707 	error = ixl_disable_rx_ring(pf, qtag, vsi_qidx);
1708 	return (error);
1709 }
1710 
1711 static void
ixl_handle_tx_mdd_event(struct ixl_pf * pf)1712 ixl_handle_tx_mdd_event(struct ixl_pf *pf)
1713 {
1714 	struct i40e_hw *hw = &pf->hw;
1715 	device_t dev = pf->dev;
1716 	struct ixl_vf *vf;
1717 	bool mdd_detected = false;
1718 	bool pf_mdd_detected = false;
1719 	bool vf_mdd_detected = false;
1720 	u16 vf_num, queue;
1721 	u8 pf_num, event;
1722 	u8 pf_mdet_num, vp_mdet_num;
1723 	u32 reg;
1724 
1725 	/* find what triggered the MDD event */
1726 	reg = rd32(hw, I40E_GL_MDET_TX);
1727 	if (reg & I40E_GL_MDET_TX_VALID_MASK) {
1728 		pf_num = (reg & I40E_GL_MDET_TX_PF_NUM_MASK) >>
1729 		    I40E_GL_MDET_TX_PF_NUM_SHIFT;
1730 		vf_num = (reg & I40E_GL_MDET_TX_VF_NUM_MASK) >>
1731 		    I40E_GL_MDET_TX_VF_NUM_SHIFT;
1732 		event = (reg & I40E_GL_MDET_TX_EVENT_MASK) >>
1733 		    I40E_GL_MDET_TX_EVENT_SHIFT;
1734 		queue = (reg & I40E_GL_MDET_TX_QUEUE_MASK) >>
1735 		    I40E_GL_MDET_TX_QUEUE_SHIFT;
1736 		wr32(hw, I40E_GL_MDET_TX, 0xffffffff);
1737 		mdd_detected = true;
1738 	}
1739 
1740 	if (!mdd_detected)
1741 		return;
1742 
1743 	reg = rd32(hw, I40E_PF_MDET_TX);
1744 	if (reg & I40E_PF_MDET_TX_VALID_MASK) {
1745 		wr32(hw, I40E_PF_MDET_TX, 0xFFFF);
1746 		pf_mdet_num = hw->pf_id;
1747 		pf_mdd_detected = true;
1748 	}
1749 
1750 	/* Check if MDD was caused by a VF */
1751 	for (int i = 0; i < pf->num_vfs; i++) {
1752 		vf = &(pf->vfs[i]);
1753 		reg = rd32(hw, I40E_VP_MDET_TX(i));
1754 		if (reg & I40E_VP_MDET_TX_VALID_MASK) {
1755 			wr32(hw, I40E_VP_MDET_TX(i), 0xFFFF);
1756 			vp_mdet_num = i;
1757 			vf->num_mdd_events++;
1758 			vf_mdd_detected = true;
1759 		}
1760 	}
1761 
1762 	/* Print out an error message */
1763 	if (vf_mdd_detected && pf_mdd_detected)
1764 		device_printf(dev,
1765 		    "Malicious Driver Detection event %d"
1766 		    " on TX queue %d, pf number %d (PF-%d), vf number %d (VF-%d)\n",
1767 		    event, queue, pf_num, pf_mdet_num, vf_num, vp_mdet_num);
1768 	else if (vf_mdd_detected && !pf_mdd_detected)
1769 		device_printf(dev,
1770 		    "Malicious Driver Detection event %d"
1771 		    " on TX queue %d, pf number %d, vf number %d (VF-%d)\n",
1772 		    event, queue, pf_num, vf_num, vp_mdet_num);
1773 	else if (!vf_mdd_detected && pf_mdd_detected)
1774 		device_printf(dev,
1775 		    "Malicious Driver Detection event %d"
1776 		    " on TX queue %d, pf number %d (PF-%d)\n",
1777 		    event, queue, pf_num, pf_mdet_num);
1778 	/* Theoretically shouldn't happen */
1779 	else
1780 		device_printf(dev,
1781 		    "TX Malicious Driver Detection event (unknown)\n");
1782 }
1783 
1784 static void
ixl_handle_rx_mdd_event(struct ixl_pf * pf)1785 ixl_handle_rx_mdd_event(struct ixl_pf *pf)
1786 {
1787 	struct i40e_hw *hw = &pf->hw;
1788 	device_t dev = pf->dev;
1789 	struct ixl_vf *vf;
1790 	bool mdd_detected = false;
1791 	bool pf_mdd_detected = false;
1792 	bool vf_mdd_detected = false;
1793 	u16 queue;
1794 	u8 pf_num, event;
1795 	u8 pf_mdet_num, vp_mdet_num;
1796 	u32 reg;
1797 
1798 	/*
1799 	 * GL_MDET_RX doesn't contain VF number information, unlike
1800 	 * GL_MDET_TX.
1801 	 */
1802 	reg = rd32(hw, I40E_GL_MDET_RX);
1803 	if (reg & I40E_GL_MDET_RX_VALID_MASK) {
1804 		pf_num = (reg & I40E_GL_MDET_RX_FUNCTION_MASK) >>
1805 		    I40E_GL_MDET_RX_FUNCTION_SHIFT;
1806 		event = (reg & I40E_GL_MDET_RX_EVENT_MASK) >>
1807 		    I40E_GL_MDET_RX_EVENT_SHIFT;
1808 		queue = (reg & I40E_GL_MDET_RX_QUEUE_MASK) >>
1809 		    I40E_GL_MDET_RX_QUEUE_SHIFT;
1810 		wr32(hw, I40E_GL_MDET_RX, 0xffffffff);
1811 		mdd_detected = true;
1812 	}
1813 
1814 	if (!mdd_detected)
1815 		return;
1816 
1817 	reg = rd32(hw, I40E_PF_MDET_RX);
1818 	if (reg & I40E_PF_MDET_RX_VALID_MASK) {
1819 		wr32(hw, I40E_PF_MDET_RX, 0xFFFF);
1820 		pf_mdet_num = hw->pf_id;
1821 		pf_mdd_detected = true;
1822 	}
1823 
1824 	/* Check if MDD was caused by a VF */
1825 	for (int i = 0; i < pf->num_vfs; i++) {
1826 		vf = &(pf->vfs[i]);
1827 		reg = rd32(hw, I40E_VP_MDET_RX(i));
1828 		if (reg & I40E_VP_MDET_RX_VALID_MASK) {
1829 			wr32(hw, I40E_VP_MDET_RX(i), 0xFFFF);
1830 			vp_mdet_num = i;
1831 			vf->num_mdd_events++;
1832 			vf_mdd_detected = true;
1833 		}
1834 	}
1835 
1836 	/* Print out an error message */
1837 	if (vf_mdd_detected && pf_mdd_detected)
1838 		device_printf(dev,
1839 		    "Malicious Driver Detection event %d"
1840 		    " on RX queue %d, pf number %d (PF-%d), (VF-%d)\n",
1841 		    event, queue, pf_num, pf_mdet_num, vp_mdet_num);
1842 	else if (vf_mdd_detected && !pf_mdd_detected)
1843 		device_printf(dev,
1844 		    "Malicious Driver Detection event %d"
1845 		    " on RX queue %d, pf number %d, (VF-%d)\n",
1846 		    event, queue, pf_num, vp_mdet_num);
1847 	else if (!vf_mdd_detected && pf_mdd_detected)
1848 		device_printf(dev,
1849 		    "Malicious Driver Detection event %d"
1850 		    " on RX queue %d, pf number %d (PF-%d)\n",
1851 		    event, queue, pf_num, pf_mdet_num);
1852 	/* Theoretically shouldn't happen */
1853 	else
1854 		device_printf(dev,
1855 		    "RX Malicious Driver Detection event (unknown)\n");
1856 }
1857 
1858 /**
1859  * ixl_handle_mdd_event
1860  *
1861  * Called from interrupt handler to identify possibly malicious vfs
1862  * (But also detects events from the PF, as well)
1863  **/
1864 void
ixl_handle_mdd_event(struct ixl_pf * pf)1865 ixl_handle_mdd_event(struct ixl_pf *pf)
1866 {
1867 	struct i40e_hw *hw = &pf->hw;
1868 	u32 reg;
1869 
1870 	/*
1871 	 * Handle both TX/RX because it's possible they could
1872 	 * both trigger in the same interrupt.
1873 	 */
1874 	ixl_handle_tx_mdd_event(pf);
1875 	ixl_handle_rx_mdd_event(pf);
1876 
1877 	atomic_clear_32(&pf->state, IXL_PF_STATE_MDD_PENDING);
1878 
1879 	/* re-enable mdd interrupt cause */
1880 	reg = rd32(hw, I40E_PFINT_ICR0_ENA);
1881 	reg |= I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
1882 	wr32(hw, I40E_PFINT_ICR0_ENA, reg);
1883 	ixl_flush(hw);
1884 }
1885 
1886 void
ixl_enable_intr0(struct i40e_hw * hw)1887 ixl_enable_intr0(struct i40e_hw *hw)
1888 {
1889 	u32		reg;
1890 
1891 	/* Use IXL_ITR_NONE so ITR isn't updated here */
1892 	reg = I40E_PFINT_DYN_CTL0_INTENA_MASK |
1893 	    I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
1894 	    (IXL_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT);
1895 	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
1896 }
1897 
1898 void
ixl_disable_intr0(struct i40e_hw * hw)1899 ixl_disable_intr0(struct i40e_hw *hw)
1900 {
1901 	u32		reg;
1902 
1903 	reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT;
1904 	wr32(hw, I40E_PFINT_DYN_CTL0, reg);
1905 	ixl_flush(hw);
1906 }
1907 
1908 void
ixl_enable_queue(struct i40e_hw * hw,int id)1909 ixl_enable_queue(struct i40e_hw *hw, int id)
1910 {
1911 	u32		reg;
1912 
1913 	reg = I40E_PFINT_DYN_CTLN_INTENA_MASK |
1914 	    I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
1915 	    (IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
1916 	wr32(hw, I40E_PFINT_DYN_CTLN(id), reg);
1917 }
1918 
1919 void
ixl_disable_queue(struct i40e_hw * hw,int id)1920 ixl_disable_queue(struct i40e_hw *hw, int id)
1921 {
1922 	u32		reg;
1923 
1924 	reg = IXL_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT;
1925 	wr32(hw, I40E_PFINT_DYN_CTLN(id), reg);
1926 }
1927 
1928 void
ixl_handle_empr_reset(struct ixl_pf * pf)1929 ixl_handle_empr_reset(struct ixl_pf *pf)
1930 {
1931 	struct ixl_vsi	*vsi = &pf->vsi;
1932 	bool is_up = !!(vsi->ifp->if_drv_flags & IFF_DRV_RUNNING);
1933 
1934 	ixl_prepare_for_reset(pf, is_up);
1935 	/*
1936 	 * i40e_pf_reset checks the type of reset and acts
1937 	 * accordingly. If EMP or Core reset was performed
1938 	 * doing PF reset is not necessary and it sometimes
1939 	 * fails.
1940 	 */
1941 	ixl_pf_reset(pf);
1942 
1943 	if (!IXL_PF_IN_RECOVERY_MODE(pf) &&
1944 	    ixl_get_fw_mode(pf) == IXL_FW_MODE_RECOVERY) {
1945 		atomic_set_32(&pf->state, IXL_PF_STATE_RECOVERY_MODE);
1946 		device_printf(pf->dev,
1947 		    "Firmware recovery mode detected. Limiting functionality. Refer to Intel(R) Ethernet Adapters and Devices User Guide for details on firmware recovery mode.\n");
1948 		pf->link_up = FALSE;
1949 		ixl_update_link_status(pf);
1950 	}
1951 
1952 	ixl_rebuild_hw_structs_after_reset(pf, is_up);
1953 
1954 	atomic_clear_32(&pf->state, IXL_PF_STATE_RESETTING);
1955 }
1956 
1957 void
ixl_update_stats_counters(struct ixl_pf * pf)1958 ixl_update_stats_counters(struct ixl_pf *pf)
1959 {
1960 	struct i40e_hw	*hw = &pf->hw;
1961 	struct ixl_vsi	*vsi = &pf->vsi;
1962 	struct ixl_vf	*vf;
1963 	u64 prev_link_xoff_rx = pf->stats.link_xoff_rx;
1964 
1965 	struct i40e_hw_port_stats *nsd = &pf->stats;
1966 	struct i40e_hw_port_stats *osd = &pf->stats_offsets;
1967 
1968 	/* Update hw stats */
1969 	ixl_stat_update32(hw, I40E_GLPRT_CRCERRS(hw->port),
1970 			   pf->stat_offsets_loaded,
1971 			   &osd->crc_errors, &nsd->crc_errors);
1972 	ixl_stat_update32(hw, I40E_GLPRT_ILLERRC(hw->port),
1973 			   pf->stat_offsets_loaded,
1974 			   &osd->illegal_bytes, &nsd->illegal_bytes);
1975 	ixl_stat_update48(hw, I40E_GLPRT_GORCH(hw->port),
1976 			   I40E_GLPRT_GORCL(hw->port),
1977 			   pf->stat_offsets_loaded,
1978 			   &osd->eth.rx_bytes, &nsd->eth.rx_bytes);
1979 	ixl_stat_update48(hw, I40E_GLPRT_GOTCH(hw->port),
1980 			   I40E_GLPRT_GOTCL(hw->port),
1981 			   pf->stat_offsets_loaded,
1982 			   &osd->eth.tx_bytes, &nsd->eth.tx_bytes);
1983 	ixl_stat_update32(hw, I40E_GLPRT_RDPC(hw->port),
1984 			   pf->stat_offsets_loaded,
1985 			   &osd->eth.rx_discards,
1986 			   &nsd->eth.rx_discards);
1987 	ixl_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port),
1988 			   I40E_GLPRT_UPRCL(hw->port),
1989 			   pf->stat_offsets_loaded,
1990 			   &osd->eth.rx_unicast,
1991 			   &nsd->eth.rx_unicast);
1992 	ixl_stat_update48(hw, I40E_GLPRT_UPTCH(hw->port),
1993 			   I40E_GLPRT_UPTCL(hw->port),
1994 			   pf->stat_offsets_loaded,
1995 			   &osd->eth.tx_unicast,
1996 			   &nsd->eth.tx_unicast);
1997 	ixl_stat_update48(hw, I40E_GLPRT_MPRCH(hw->port),
1998 			   I40E_GLPRT_MPRCL(hw->port),
1999 			   pf->stat_offsets_loaded,
2000 			   &osd->eth.rx_multicast,
2001 			   &nsd->eth.rx_multicast);
2002 	ixl_stat_update48(hw, I40E_GLPRT_MPTCH(hw->port),
2003 			   I40E_GLPRT_MPTCL(hw->port),
2004 			   pf->stat_offsets_loaded,
2005 			   &osd->eth.tx_multicast,
2006 			   &nsd->eth.tx_multicast);
2007 	ixl_stat_update48(hw, I40E_GLPRT_BPRCH(hw->port),
2008 			   I40E_GLPRT_BPRCL(hw->port),
2009 			   pf->stat_offsets_loaded,
2010 			   &osd->eth.rx_broadcast,
2011 			   &nsd->eth.rx_broadcast);
2012 	ixl_stat_update48(hw, I40E_GLPRT_BPTCH(hw->port),
2013 			   I40E_GLPRT_BPTCL(hw->port),
2014 			   pf->stat_offsets_loaded,
2015 			   &osd->eth.tx_broadcast,
2016 			   &nsd->eth.tx_broadcast);
2017 
2018 	ixl_stat_update32(hw, I40E_GLPRT_TDOLD(hw->port),
2019 			   pf->stat_offsets_loaded,
2020 			   &osd->tx_dropped_link_down,
2021 			   &nsd->tx_dropped_link_down);
2022 	ixl_stat_update32(hw, I40E_GLPRT_MLFC(hw->port),
2023 			   pf->stat_offsets_loaded,
2024 			   &osd->mac_local_faults,
2025 			   &nsd->mac_local_faults);
2026 	ixl_stat_update32(hw, I40E_GLPRT_MRFC(hw->port),
2027 			   pf->stat_offsets_loaded,
2028 			   &osd->mac_remote_faults,
2029 			   &nsd->mac_remote_faults);
2030 	ixl_stat_update32(hw, I40E_GLPRT_RLEC(hw->port),
2031 			   pf->stat_offsets_loaded,
2032 			   &osd->rx_length_errors,
2033 			   &nsd->rx_length_errors);
2034 
2035 	/* Flow control (LFC) stats */
2036 	ixl_stat_update32(hw, I40E_GLPRT_LXONRXC(hw->port),
2037 			   pf->stat_offsets_loaded,
2038 			   &osd->link_xon_rx, &nsd->link_xon_rx);
2039 	ixl_stat_update32(hw, I40E_GLPRT_LXONTXC(hw->port),
2040 			   pf->stat_offsets_loaded,
2041 			   &osd->link_xon_tx, &nsd->link_xon_tx);
2042 	ixl_stat_update32(hw, I40E_GLPRT_LXOFFRXC(hw->port),
2043 			   pf->stat_offsets_loaded,
2044 			   &osd->link_xoff_rx, &nsd->link_xoff_rx);
2045 	ixl_stat_update32(hw, I40E_GLPRT_LXOFFTXC(hw->port),
2046 			   pf->stat_offsets_loaded,
2047 			   &osd->link_xoff_tx, &nsd->link_xoff_tx);
2048 
2049 	/*
2050 	 * For watchdog management we need to know if we have been paused
2051 	 * during the last interval, so capture that here.
2052 	 */
2053 	if (pf->stats.link_xoff_rx != prev_link_xoff_rx)
2054 		vsi->shared->isc_pause_frames = 1;
2055 
2056 	/* Packet size stats rx */
2057 	ixl_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port),
2058 			   I40E_GLPRT_PRC64L(hw->port),
2059 			   pf->stat_offsets_loaded,
2060 			   &osd->rx_size_64, &nsd->rx_size_64);
2061 	ixl_stat_update48(hw, I40E_GLPRT_PRC127H(hw->port),
2062 			   I40E_GLPRT_PRC127L(hw->port),
2063 			   pf->stat_offsets_loaded,
2064 			   &osd->rx_size_127, &nsd->rx_size_127);
2065 	ixl_stat_update48(hw, I40E_GLPRT_PRC255H(hw->port),
2066 			   I40E_GLPRT_PRC255L(hw->port),
2067 			   pf->stat_offsets_loaded,
2068 			   &osd->rx_size_255, &nsd->rx_size_255);
2069 	ixl_stat_update48(hw, I40E_GLPRT_PRC511H(hw->port),
2070 			   I40E_GLPRT_PRC511L(hw->port),
2071 			   pf->stat_offsets_loaded,
2072 			   &osd->rx_size_511, &nsd->rx_size_511);
2073 	ixl_stat_update48(hw, I40E_GLPRT_PRC1023H(hw->port),
2074 			   I40E_GLPRT_PRC1023L(hw->port),
2075 			   pf->stat_offsets_loaded,
2076 			   &osd->rx_size_1023, &nsd->rx_size_1023);
2077 	ixl_stat_update48(hw, I40E_GLPRT_PRC1522H(hw->port),
2078 			   I40E_GLPRT_PRC1522L(hw->port),
2079 			   pf->stat_offsets_loaded,
2080 			   &osd->rx_size_1522, &nsd->rx_size_1522);
2081 	ixl_stat_update48(hw, I40E_GLPRT_PRC9522H(hw->port),
2082 			   I40E_GLPRT_PRC9522L(hw->port),
2083 			   pf->stat_offsets_loaded,
2084 			   &osd->rx_size_big, &nsd->rx_size_big);
2085 
2086 	/* Packet size stats tx */
2087 	ixl_stat_update48(hw, I40E_GLPRT_PTC64H(hw->port),
2088 			   I40E_GLPRT_PTC64L(hw->port),
2089 			   pf->stat_offsets_loaded,
2090 			   &osd->tx_size_64, &nsd->tx_size_64);
2091 	ixl_stat_update48(hw, I40E_GLPRT_PTC127H(hw->port),
2092 			   I40E_GLPRT_PTC127L(hw->port),
2093 			   pf->stat_offsets_loaded,
2094 			   &osd->tx_size_127, &nsd->tx_size_127);
2095 	ixl_stat_update48(hw, I40E_GLPRT_PTC255H(hw->port),
2096 			   I40E_GLPRT_PTC255L(hw->port),
2097 			   pf->stat_offsets_loaded,
2098 			   &osd->tx_size_255, &nsd->tx_size_255);
2099 	ixl_stat_update48(hw, I40E_GLPRT_PTC511H(hw->port),
2100 			   I40E_GLPRT_PTC511L(hw->port),
2101 			   pf->stat_offsets_loaded,
2102 			   &osd->tx_size_511, &nsd->tx_size_511);
2103 	ixl_stat_update48(hw, I40E_GLPRT_PTC1023H(hw->port),
2104 			   I40E_GLPRT_PTC1023L(hw->port),
2105 			   pf->stat_offsets_loaded,
2106 			   &osd->tx_size_1023, &nsd->tx_size_1023);
2107 	ixl_stat_update48(hw, I40E_GLPRT_PTC1522H(hw->port),
2108 			   I40E_GLPRT_PTC1522L(hw->port),
2109 			   pf->stat_offsets_loaded,
2110 			   &osd->tx_size_1522, &nsd->tx_size_1522);
2111 	ixl_stat_update48(hw, I40E_GLPRT_PTC9522H(hw->port),
2112 			   I40E_GLPRT_PTC9522L(hw->port),
2113 			   pf->stat_offsets_loaded,
2114 			   &osd->tx_size_big, &nsd->tx_size_big);
2115 
2116 	ixl_stat_update32(hw, I40E_GLPRT_RUC(hw->port),
2117 			   pf->stat_offsets_loaded,
2118 			   &osd->rx_undersize, &nsd->rx_undersize);
2119 	ixl_stat_update32(hw, I40E_GLPRT_RFC(hw->port),
2120 			   pf->stat_offsets_loaded,
2121 			   &osd->rx_fragments, &nsd->rx_fragments);
2122 	ixl_stat_update32(hw, I40E_GLPRT_ROC(hw->port),
2123 			   pf->stat_offsets_loaded,
2124 			   &osd->rx_oversize, &nsd->rx_oversize);
2125 	ixl_stat_update32(hw, I40E_GLPRT_RJC(hw->port),
2126 			   pf->stat_offsets_loaded,
2127 			   &osd->rx_jabber, &nsd->rx_jabber);
2128 	/* EEE */
2129 	i40e_get_phy_lpi_status(hw, nsd);
2130 
2131 	i40e_lpi_stat_update(hw, pf->stat_offsets_loaded,
2132 			  &osd->tx_lpi_count, &nsd->tx_lpi_count,
2133 			  &osd->rx_lpi_count, &nsd->rx_lpi_count);
2134 
2135 	pf->stat_offsets_loaded = true;
2136 	/* End hw stats */
2137 
2138 	/* Update vsi stats */
2139 	ixl_update_vsi_stats(vsi);
2140 
2141 	for (int i = 0; i < pf->num_vfs; i++) {
2142 		vf = &pf->vfs[i];
2143 		if (vf->vf_flags & VF_FLAG_ENABLED)
2144 			ixl_update_eth_stats(&pf->vfs[i].vsi);
2145 	}
2146 }
2147 
2148 /**
2149  * Update VSI-specific ethernet statistics counters.
2150  **/
2151 void
ixl_update_eth_stats(struct ixl_vsi * vsi)2152 ixl_update_eth_stats(struct ixl_vsi *vsi)
2153 {
2154 	struct ixl_pf *pf = (struct ixl_pf *)vsi->back;
2155 	struct i40e_hw *hw = &pf->hw;
2156 	struct i40e_eth_stats *es;
2157 	struct i40e_eth_stats *oes;
2158 	u16 stat_idx = vsi->info.stat_counter_idx;
2159 
2160 	es = &vsi->eth_stats;
2161 	oes = &vsi->eth_stats_offsets;
2162 
2163 	/* Gather up the stats that the hw collects */
2164 	ixl_stat_update32(hw, I40E_GLV_TEPC(stat_idx),
2165 			   vsi->stat_offsets_loaded,
2166 			   &oes->tx_errors, &es->tx_errors);
2167 	ixl_stat_update32(hw, I40E_GLV_RDPC(stat_idx),
2168 			   vsi->stat_offsets_loaded,
2169 			   &oes->rx_discards, &es->rx_discards);
2170 
2171 	ixl_stat_update48(hw, I40E_GLV_GORCH(stat_idx),
2172 			   I40E_GLV_GORCL(stat_idx),
2173 			   vsi->stat_offsets_loaded,
2174 			   &oes->rx_bytes, &es->rx_bytes);
2175 	ixl_stat_update48(hw, I40E_GLV_UPRCH(stat_idx),
2176 			   I40E_GLV_UPRCL(stat_idx),
2177 			   vsi->stat_offsets_loaded,
2178 			   &oes->rx_unicast, &es->rx_unicast);
2179 	ixl_stat_update48(hw, I40E_GLV_MPRCH(stat_idx),
2180 			   I40E_GLV_MPRCL(stat_idx),
2181 			   vsi->stat_offsets_loaded,
2182 			   &oes->rx_multicast, &es->rx_multicast);
2183 	ixl_stat_update48(hw, I40E_GLV_BPRCH(stat_idx),
2184 			   I40E_GLV_BPRCL(stat_idx),
2185 			   vsi->stat_offsets_loaded,
2186 			   &oes->rx_broadcast, &es->rx_broadcast);
2187 
2188 	ixl_stat_update48(hw, I40E_GLV_GOTCH(stat_idx),
2189 			   I40E_GLV_GOTCL(stat_idx),
2190 			   vsi->stat_offsets_loaded,
2191 			   &oes->tx_bytes, &es->tx_bytes);
2192 	ixl_stat_update48(hw, I40E_GLV_UPTCH(stat_idx),
2193 			   I40E_GLV_UPTCL(stat_idx),
2194 			   vsi->stat_offsets_loaded,
2195 			   &oes->tx_unicast, &es->tx_unicast);
2196 	ixl_stat_update48(hw, I40E_GLV_MPTCH(stat_idx),
2197 			   I40E_GLV_MPTCL(stat_idx),
2198 			   vsi->stat_offsets_loaded,
2199 			   &oes->tx_multicast, &es->tx_multicast);
2200 	ixl_stat_update48(hw, I40E_GLV_BPTCH(stat_idx),
2201 			   I40E_GLV_BPTCL(stat_idx),
2202 			   vsi->stat_offsets_loaded,
2203 			   &oes->tx_broadcast, &es->tx_broadcast);
2204 	vsi->stat_offsets_loaded = true;
2205 }
2206 
2207 void
ixl_update_vsi_stats(struct ixl_vsi * vsi)2208 ixl_update_vsi_stats(struct ixl_vsi *vsi)
2209 {
2210 	struct ixl_pf		*pf;
2211 	struct ifnet		*ifp;
2212 	struct i40e_eth_stats	*es;
2213 	u64			tx_discards, csum_errs;
2214 
2215 	struct i40e_hw_port_stats *nsd;
2216 
2217 	pf = vsi->back;
2218 	ifp = vsi->ifp;
2219 	es = &vsi->eth_stats;
2220 	nsd = &pf->stats;
2221 
2222 	ixl_update_eth_stats(vsi);
2223 
2224 	tx_discards = es->tx_discards + nsd->tx_dropped_link_down;
2225 
2226 	csum_errs = 0;
2227 	for (int i = 0; i < vsi->num_rx_queues; i++)
2228 		csum_errs += vsi->rx_queues[i].rxr.csum_errs;
2229 	nsd->checksum_error = csum_errs;
2230 
2231 	/* Update ifnet stats */
2232 	IXL_SET_IPACKETS(vsi, es->rx_unicast +
2233 	                   es->rx_multicast +
2234 			   es->rx_broadcast);
2235 	IXL_SET_OPACKETS(vsi, es->tx_unicast +
2236 	                   es->tx_multicast +
2237 			   es->tx_broadcast);
2238 	IXL_SET_IBYTES(vsi, es->rx_bytes);
2239 	IXL_SET_OBYTES(vsi, es->tx_bytes);
2240 	IXL_SET_IMCASTS(vsi, es->rx_multicast);
2241 	IXL_SET_OMCASTS(vsi, es->tx_multicast);
2242 
2243 	IXL_SET_IERRORS(vsi, nsd->crc_errors + nsd->illegal_bytes +
2244 	    nsd->checksum_error + nsd->rx_length_errors +
2245 	    nsd->rx_undersize + nsd->rx_fragments + nsd->rx_oversize +
2246 	    nsd->rx_jabber);
2247 	IXL_SET_OERRORS(vsi, es->tx_errors);
2248 	IXL_SET_IQDROPS(vsi, es->rx_discards + nsd->eth.rx_discards);
2249 	IXL_SET_OQDROPS(vsi, tx_discards);
2250 	IXL_SET_NOPROTO(vsi, es->rx_unknown_protocol);
2251 	IXL_SET_COLLISIONS(vsi, 0);
2252 }
2253 
2254 /**
2255  * Reset all of the stats for the given pf
2256  **/
2257 void
ixl_pf_reset_stats(struct ixl_pf * pf)2258 ixl_pf_reset_stats(struct ixl_pf *pf)
2259 {
2260 	bzero(&pf->stats, sizeof(struct i40e_hw_port_stats));
2261 	bzero(&pf->stats_offsets, sizeof(struct i40e_hw_port_stats));
2262 	pf->stat_offsets_loaded = false;
2263 }
2264 
2265 /**
2266  * Resets all stats of the given vsi
2267  **/
2268 void
ixl_vsi_reset_stats(struct ixl_vsi * vsi)2269 ixl_vsi_reset_stats(struct ixl_vsi *vsi)
2270 {
2271 	bzero(&vsi->eth_stats, sizeof(struct i40e_eth_stats));
2272 	bzero(&vsi->eth_stats_offsets, sizeof(struct i40e_eth_stats));
2273 	vsi->stat_offsets_loaded = false;
2274 }
2275 
2276 /**
2277  * Read and update a 48 bit stat from the hw
2278  *
2279  * Since the device stats are not reset at PFReset, they likely will not
2280  * be zeroed when the driver starts.  We'll save the first values read
2281  * and use them as offsets to be subtracted from the raw values in order
2282  * to report stats that count from zero.
2283  **/
2284 void
ixl_stat_update48(struct i40e_hw * hw,u32 hireg,u32 loreg,bool offset_loaded,u64 * offset,u64 * stat)2285 ixl_stat_update48(struct i40e_hw *hw, u32 hireg, u32 loreg,
2286 	bool offset_loaded, u64 *offset, u64 *stat)
2287 {
2288 	u64 new_data;
2289 
2290 #if defined(__FreeBSD__) && (__FreeBSD_version >= 1000000) && defined(__amd64__)
2291 	new_data = rd64(hw, loreg);
2292 #else
2293 	/*
2294 	 * Use two rd32's instead of one rd64; FreeBSD versions before
2295 	 * 10 don't support 64-bit bus reads/writes.
2296 	 */
2297 	new_data = rd32(hw, loreg);
2298 	new_data |= ((u64)(rd32(hw, hireg) & 0xFFFF)) << 32;
2299 #endif
2300 
2301 	if (!offset_loaded)
2302 		*offset = new_data;
2303 	if (new_data >= *offset)
2304 		*stat = new_data - *offset;
2305 	else
2306 		*stat = (new_data + ((u64)1 << 48)) - *offset;
2307 	*stat &= 0xFFFFFFFFFFFFULL;
2308 }
2309 
2310 /**
2311  * Read and update a 32 bit stat from the hw
2312  **/
2313 void
ixl_stat_update32(struct i40e_hw * hw,u32 reg,bool offset_loaded,u64 * offset,u64 * stat)2314 ixl_stat_update32(struct i40e_hw *hw, u32 reg,
2315 	bool offset_loaded, u64 *offset, u64 *stat)
2316 {
2317 	u32 new_data;
2318 
2319 	new_data = rd32(hw, reg);
2320 	if (!offset_loaded)
2321 		*offset = new_data;
2322 	if (new_data >= *offset)
2323 		*stat = (u32)(new_data - *offset);
2324 	else
2325 		*stat = (u32)((new_data + ((u64)1 << 32)) - *offset);
2326 }
2327 
2328 /**
2329  * Add subset of device sysctls safe to use in recovery mode
2330  */
2331 void
ixl_add_sysctls_recovery_mode(struct ixl_pf * pf)2332 ixl_add_sysctls_recovery_mode(struct ixl_pf *pf)
2333 {
2334 	device_t dev = pf->dev;
2335 
2336 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
2337 	struct sysctl_oid_list *ctx_list =
2338 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
2339 
2340 	struct sysctl_oid *debug_node;
2341 	struct sysctl_oid_list *debug_list;
2342 
2343 	SYSCTL_ADD_PROC(ctx, ctx_list,
2344 	    OID_AUTO, "fw_version",
2345 	    CTLTYPE_STRING | CTLFLAG_RD, pf, 0,
2346 	    ixl_sysctl_show_fw, "A", "Firmware version");
2347 
2348 	/* Add sysctls meant to print debug information, but don't list them
2349 	 * in "sysctl -a" output. */
2350 	debug_node = SYSCTL_ADD_NODE(ctx, ctx_list,
2351 	    OID_AUTO, "debug", CTLFLAG_RD | CTLFLAG_SKIP, NULL,
2352 	    "Debug Sysctls");
2353 	debug_list = SYSCTL_CHILDREN(debug_node);
2354 
2355 	SYSCTL_ADD_UINT(ctx, debug_list,
2356 	    OID_AUTO, "shared_debug_mask", CTLFLAG_RW,
2357 	    &pf->hw.debug_mask, 0, "Shared code debug message level");
2358 
2359 	SYSCTL_ADD_UINT(ctx, debug_list,
2360 	    OID_AUTO, "core_debug_mask", CTLFLAG_RW,
2361 	    &pf->dbg_mask, 0, "Non-shared code debug message level");
2362 
2363 	SYSCTL_ADD_PROC(ctx, debug_list,
2364 	    OID_AUTO, "dump_debug_data",
2365 	    CTLTYPE_STRING | CTLFLAG_RD,
2366 	    pf, 0, ixl_sysctl_dump_debug_data, "A", "Dump Debug Data from FW");
2367 
2368 	SYSCTL_ADD_PROC(ctx, debug_list,
2369 	    OID_AUTO, "do_pf_reset",
2370 	    CTLTYPE_INT | CTLFLAG_WR,
2371 	    pf, 0, ixl_sysctl_do_pf_reset, "I", "Tell HW to initiate a PF reset");
2372 
2373 	SYSCTL_ADD_PROC(ctx, debug_list,
2374 	    OID_AUTO, "do_core_reset",
2375 	    CTLTYPE_INT | CTLFLAG_WR,
2376 	    pf, 0, ixl_sysctl_do_core_reset, "I", "Tell HW to initiate a CORE reset");
2377 
2378 	SYSCTL_ADD_PROC(ctx, debug_list,
2379 	    OID_AUTO, "do_global_reset",
2380 	    CTLTYPE_INT | CTLFLAG_WR,
2381 	    pf, 0, ixl_sysctl_do_global_reset, "I", "Tell HW to initiate a GLOBAL reset");
2382 
2383 	SYSCTL_ADD_PROC(ctx, debug_list,
2384 	    OID_AUTO, "queue_interrupt_table",
2385 	    CTLTYPE_STRING | CTLFLAG_RD,
2386 	    pf, 0, ixl_sysctl_queue_interrupt_table, "A", "View MSI-X indices for TX/RX queues");
2387 }
2388 
2389 void
ixl_add_device_sysctls(struct ixl_pf * pf)2390 ixl_add_device_sysctls(struct ixl_pf *pf)
2391 {
2392 	device_t dev = pf->dev;
2393 	struct i40e_hw *hw = &pf->hw;
2394 
2395 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(dev);
2396 	struct sysctl_oid_list *ctx_list =
2397 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
2398 
2399 	struct sysctl_oid *debug_node;
2400 	struct sysctl_oid_list *debug_list;
2401 
2402 	struct sysctl_oid *fec_node;
2403 	struct sysctl_oid_list *fec_list;
2404 	struct sysctl_oid *eee_node;
2405 	struct sysctl_oid_list *eee_list;
2406 
2407 	/* Set up sysctls */
2408 	SYSCTL_ADD_PROC(ctx, ctx_list,
2409 	    OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW,
2410 	    pf, 0, ixl_sysctl_set_flowcntl, "I", IXL_SYSCTL_HELP_FC);
2411 
2412 	SYSCTL_ADD_PROC(ctx, ctx_list,
2413 	    OID_AUTO, "advertise_speed", CTLTYPE_INT | CTLFLAG_RW,
2414 	    pf, 0, ixl_sysctl_set_advertise, "I", IXL_SYSCTL_HELP_SET_ADVERTISE);
2415 
2416 	SYSCTL_ADD_PROC(ctx, ctx_list,
2417 	    OID_AUTO, "supported_speeds", CTLTYPE_INT | CTLFLAG_RD,
2418 	    pf, 0, ixl_sysctl_supported_speeds, "I", IXL_SYSCTL_HELP_SUPPORTED_SPEED);
2419 
2420 	SYSCTL_ADD_PROC(ctx, ctx_list,
2421 	    OID_AUTO, "current_speed", CTLTYPE_STRING | CTLFLAG_RD,
2422 	    pf, 0, ixl_sysctl_current_speed, "A", "Current Port Speed");
2423 
2424 	SYSCTL_ADD_PROC(ctx, ctx_list,
2425 	    OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD,
2426 	    pf, 0, ixl_sysctl_show_fw, "A", "Firmware version");
2427 
2428 	SYSCTL_ADD_PROC(ctx, ctx_list,
2429 	    OID_AUTO, "unallocated_queues", CTLTYPE_INT | CTLFLAG_RD,
2430 	    pf, 0, ixl_sysctl_unallocated_queues, "I",
2431 	    "Queues not allocated to a PF or VF");
2432 
2433 	SYSCTL_ADD_PROC(ctx, ctx_list,
2434 	    OID_AUTO, "tx_itr", CTLTYPE_INT | CTLFLAG_RW,
2435 	    pf, 0, ixl_sysctl_pf_tx_itr, "I",
2436 	    "Immediately set TX ITR value for all queues");
2437 
2438 	SYSCTL_ADD_PROC(ctx, ctx_list,
2439 	    OID_AUTO, "rx_itr", CTLTYPE_INT | CTLFLAG_RW,
2440 	    pf, 0, ixl_sysctl_pf_rx_itr, "I",
2441 	    "Immediately set RX ITR value for all queues");
2442 
2443 	SYSCTL_ADD_INT(ctx, ctx_list,
2444 	    OID_AUTO, "dynamic_rx_itr", CTLFLAG_RW,
2445 	    &pf->dynamic_rx_itr, 0, "Enable dynamic RX ITR");
2446 
2447 	SYSCTL_ADD_INT(ctx, ctx_list,
2448 	    OID_AUTO, "dynamic_tx_itr", CTLFLAG_RW,
2449 	    &pf->dynamic_tx_itr, 0, "Enable dynamic TX ITR");
2450 
2451 	/* Add FEC sysctls for 25G adapters */
2452 	if (i40e_is_25G_device(hw->device_id)) {
2453 		fec_node = SYSCTL_ADD_NODE(ctx, ctx_list,
2454 		    OID_AUTO, "fec", CTLFLAG_RD, NULL, "FEC Sysctls");
2455 		fec_list = SYSCTL_CHILDREN(fec_node);
2456 
2457 		SYSCTL_ADD_PROC(ctx, fec_list,
2458 		    OID_AUTO, "fc_ability", CTLTYPE_INT | CTLFLAG_RW,
2459 		    pf, 0, ixl_sysctl_fec_fc_ability, "I", "FC FEC ability enabled");
2460 
2461 		SYSCTL_ADD_PROC(ctx, fec_list,
2462 		    OID_AUTO, "rs_ability", CTLTYPE_INT | CTLFLAG_RW,
2463 		    pf, 0, ixl_sysctl_fec_rs_ability, "I", "RS FEC ability enabled");
2464 
2465 		SYSCTL_ADD_PROC(ctx, fec_list,
2466 		    OID_AUTO, "fc_requested", CTLTYPE_INT | CTLFLAG_RW,
2467 		    pf, 0, ixl_sysctl_fec_fc_request, "I", "FC FEC mode requested on link");
2468 
2469 		SYSCTL_ADD_PROC(ctx, fec_list,
2470 		    OID_AUTO, "rs_requested", CTLTYPE_INT | CTLFLAG_RW,
2471 		    pf, 0, ixl_sysctl_fec_rs_request, "I", "RS FEC mode requested on link");
2472 
2473 		SYSCTL_ADD_PROC(ctx, fec_list,
2474 		    OID_AUTO, "auto_fec_enabled", CTLTYPE_INT | CTLFLAG_RW,
2475 		    pf, 0, ixl_sysctl_fec_auto_enable, "I", "Let FW decide FEC ability/request modes");
2476 	}
2477 
2478 	SYSCTL_ADD_PROC(ctx, ctx_list,
2479 	    OID_AUTO, "fw_lldp", CTLTYPE_INT | CTLFLAG_RW,
2480 	    pf, 0, ixl_sysctl_fw_lldp, "I", IXL_SYSCTL_HELP_FW_LLDP);
2481 
2482 	eee_node = SYSCTL_ADD_NODE(ctx, ctx_list,
2483 	    OID_AUTO, "eee", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL,
2484 	    "Energy Efficient Ethernet (EEE) Sysctls");
2485 	eee_list = SYSCTL_CHILDREN(eee_node);
2486 
2487 	SYSCTL_ADD_PROC(ctx, eee_list,
2488 	    OID_AUTO, "enable", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
2489 	    pf, 0, ixl_sysctl_eee_enable, "I",
2490 	    "Enable Energy Efficient Ethernet (EEE)");
2491 
2492 	SYSCTL_ADD_UINT(ctx, eee_list, OID_AUTO, "tx_lpi_status",
2493 	    CTLFLAG_RD | CTLFLAG_MPSAFE, &pf->stats.tx_lpi_status, 0,
2494 	    "TX LPI status");
2495 
2496 	SYSCTL_ADD_UINT(ctx, eee_list, OID_AUTO, "rx_lpi_status",
2497 	    CTLFLAG_RD | CTLFLAG_MPSAFE, &pf->stats.rx_lpi_status, 0,
2498 	    "RX LPI status");
2499 
2500 	SYSCTL_ADD_UQUAD(ctx, eee_list, OID_AUTO, "tx_lpi_count",
2501 	    CTLFLAG_RD | CTLFLAG_MPSAFE, &pf->stats.tx_lpi_count,
2502 	    "TX LPI count");
2503 
2504 	SYSCTL_ADD_UQUAD(ctx, eee_list, OID_AUTO, "rx_lpi_count",
2505 	    CTLFLAG_RD | CTLFLAG_MPSAFE, &pf->stats.rx_lpi_count,
2506 	    "RX LPI count");
2507 
2508 	SYSCTL_ADD_PROC(ctx, ctx_list, OID_AUTO,
2509 	    "link_active_on_if_down",
2510 	    CTLTYPE_INT | CTLFLAG_RWTUN,
2511 	    pf, 0, ixl_sysctl_set_link_active, "I",
2512 	    IXL_SYSCTL_HELP_SET_LINK_ACTIVE);
2513 
2514 	/* Add sysctls meant to print debug information, but don't list them
2515 	 * in "sysctl -a" output. */
2516 	debug_node = SYSCTL_ADD_NODE(ctx, ctx_list,
2517 	    OID_AUTO, "debug", CTLFLAG_RD | CTLFLAG_SKIP, NULL, "Debug Sysctls");
2518 	debug_list = SYSCTL_CHILDREN(debug_node);
2519 
2520 	SYSCTL_ADD_UINT(ctx, debug_list,
2521 	    OID_AUTO, "shared_debug_mask", CTLFLAG_RW,
2522 	    &pf->hw.debug_mask, 0, "Shared code debug message level");
2523 
2524 	SYSCTL_ADD_UINT(ctx, debug_list,
2525 	    OID_AUTO, "core_debug_mask", CTLFLAG_RW,
2526 	    &pf->dbg_mask, 0, "Non-shared code debug message level");
2527 
2528 	SYSCTL_ADD_PROC(ctx, debug_list,
2529 	    OID_AUTO, "link_status", CTLTYPE_STRING | CTLFLAG_RD,
2530 	    pf, 0, ixl_sysctl_link_status, "A", IXL_SYSCTL_HELP_LINK_STATUS);
2531 
2532 	SYSCTL_ADD_PROC(ctx, debug_list,
2533 	    OID_AUTO, "phy_abilities_init",
2534 	    CTLTYPE_STRING | CTLFLAG_RD,
2535 	    pf, 1, ixl_sysctl_phy_abilities, "A", "Initial PHY Abilities");
2536 
2537 	SYSCTL_ADD_PROC(ctx, debug_list,
2538 	    OID_AUTO, "phy_abilities",
2539 	    CTLTYPE_STRING | CTLFLAG_RD,
2540 	    pf, 0, ixl_sysctl_phy_abilities, "A", "PHY Abilities");
2541 
2542 	SYSCTL_ADD_PROC(ctx, debug_list,
2543 	    OID_AUTO, "filter_list", CTLTYPE_STRING | CTLFLAG_RD,
2544 	    pf, 0, ixl_sysctl_sw_filter_list, "A", "SW Filter List");
2545 
2546 	SYSCTL_ADD_PROC(ctx, debug_list,
2547 	    OID_AUTO, "hw_res_alloc", CTLTYPE_STRING | CTLFLAG_RD,
2548 	    pf, 0, ixl_sysctl_hw_res_alloc, "A", "HW Resource Allocation");
2549 
2550 	SYSCTL_ADD_PROC(ctx, debug_list,
2551 	    OID_AUTO, "switch_config", CTLTYPE_STRING | CTLFLAG_RD,
2552 	    pf, 0, ixl_sysctl_switch_config, "A", "HW Switch Configuration");
2553 
2554 	SYSCTL_ADD_PROC(ctx, debug_list,
2555 	    OID_AUTO, "switch_vlans", CTLTYPE_INT | CTLFLAG_WR,
2556 	    pf, 0, ixl_sysctl_switch_vlans, "I", "HW Switch VLAN Configuration");
2557 
2558 	SYSCTL_ADD_PROC(ctx, debug_list,
2559 	    OID_AUTO, "rss_key", CTLTYPE_STRING | CTLFLAG_RD,
2560 	    pf, 0, ixl_sysctl_hkey, "A", "View RSS key");
2561 
2562 	SYSCTL_ADD_PROC(ctx, debug_list,
2563 	    OID_AUTO, "rss_lut", CTLTYPE_STRING | CTLFLAG_RD,
2564 	    pf, 0, ixl_sysctl_hlut, "A", "View RSS lookup table");
2565 
2566 	SYSCTL_ADD_PROC(ctx, debug_list,
2567 	    OID_AUTO, "rss_hena", CTLTYPE_ULONG | CTLFLAG_RD,
2568 	    pf, 0, ixl_sysctl_hena, "LU", "View enabled packet types for RSS");
2569 
2570 	SYSCTL_ADD_PROC(ctx, debug_list,
2571 	    OID_AUTO, "disable_fw_link_management", CTLTYPE_INT | CTLFLAG_WR,
2572 	    pf, 0, ixl_sysctl_fw_link_management, "I", "Disable FW Link Management");
2573 
2574 	SYSCTL_ADD_PROC(ctx, debug_list,
2575 	    OID_AUTO, "dump_debug_data", CTLTYPE_STRING | CTLFLAG_RD,
2576 	    pf, 0, ixl_sysctl_dump_debug_data, "A", "Dump Debug Data from FW");
2577 
2578 	SYSCTL_ADD_PROC(ctx, debug_list,
2579 	    OID_AUTO, "do_pf_reset", CTLTYPE_INT | CTLFLAG_WR,
2580 	    pf, 0, ixl_sysctl_do_pf_reset, "I", "Tell HW to initiate a PF reset");
2581 
2582 	SYSCTL_ADD_PROC(ctx, debug_list,
2583 	    OID_AUTO, "do_core_reset", CTLTYPE_INT | CTLFLAG_WR,
2584 	    pf, 0, ixl_sysctl_do_core_reset, "I", "Tell HW to initiate a CORE reset");
2585 
2586 	SYSCTL_ADD_PROC(ctx, debug_list,
2587 	    OID_AUTO, "do_global_reset", CTLTYPE_INT | CTLFLAG_WR,
2588 	    pf, 0, ixl_sysctl_do_global_reset, "I", "Tell HW to initiate a GLOBAL reset");
2589 
2590 	SYSCTL_ADD_PROC(ctx, debug_list,
2591 	    OID_AUTO, "queue_interrupt_table", CTLTYPE_STRING | CTLFLAG_RD,
2592 	    pf, 0, ixl_sysctl_queue_interrupt_table, "A", "View MSI-X indices for TX/RX queues");
2593 
2594 	if (pf->has_i2c) {
2595 		SYSCTL_ADD_PROC(ctx, debug_list,
2596 		    OID_AUTO, "read_i2c_byte", CTLTYPE_INT | CTLFLAG_RW,
2597 		    pf, 0, ixl_sysctl_read_i2c_byte, "I", IXL_SYSCTL_HELP_READ_I2C);
2598 
2599 		SYSCTL_ADD_PROC(ctx, debug_list,
2600 		    OID_AUTO, "write_i2c_byte", CTLTYPE_INT | CTLFLAG_RW,
2601 		    pf, 0, ixl_sysctl_write_i2c_byte, "I", IXL_SYSCTL_HELP_WRITE_I2C);
2602 
2603 		SYSCTL_ADD_PROC(ctx, debug_list,
2604 		    OID_AUTO, "read_i2c_diag_data", CTLTYPE_STRING | CTLFLAG_RD,
2605 		    pf, 0, ixl_sysctl_read_i2c_diag_data, "A", "Dump selected diagnostic data from FW");
2606 	}
2607 }
2608 
2609 /*
2610  * Primarily for finding out how many queues can be assigned to VFs,
2611  * at runtime.
2612  */
2613 static int
ixl_sysctl_unallocated_queues(SYSCTL_HANDLER_ARGS)2614 ixl_sysctl_unallocated_queues(SYSCTL_HANDLER_ARGS)
2615 {
2616 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
2617 	int queues;
2618 
2619 	queues = (int)ixl_pf_qmgr_get_num_free(&pf->qmgr);
2620 
2621 	return sysctl_handle_int(oidp, NULL, queues, req);
2622 }
2623 
2624 static const char *
ixl_link_speed_string(enum i40e_aq_link_speed link_speed)2625 ixl_link_speed_string(enum i40e_aq_link_speed link_speed)
2626 {
2627 	const char * link_speed_str[] = {
2628 		"Unknown",
2629 		"100 Mbps",
2630 		"1 Gbps",
2631 		"10 Gbps",
2632 		"40 Gbps",
2633 		"20 Gbps",
2634 		"25 Gbps",
2635 		"2.5 Gbps",
2636 		"5 Gbps"
2637 	};
2638 	int index;
2639 
2640 	switch (link_speed) {
2641 	case I40E_LINK_SPEED_100MB:
2642 		index = 1;
2643 		break;
2644 	case I40E_LINK_SPEED_1GB:
2645 		index = 2;
2646 		break;
2647 	case I40E_LINK_SPEED_10GB:
2648 		index = 3;
2649 		break;
2650 	case I40E_LINK_SPEED_40GB:
2651 		index = 4;
2652 		break;
2653 	case I40E_LINK_SPEED_20GB:
2654 		index = 5;
2655 		break;
2656 	case I40E_LINK_SPEED_25GB:
2657 		index = 6;
2658 		break;
2659 	case I40E_LINK_SPEED_2_5GB:
2660 		index = 7;
2661 		break;
2662 	case I40E_LINK_SPEED_5GB:
2663 		index = 8;
2664 		break;
2665 	case I40E_LINK_SPEED_UNKNOWN:
2666 	default:
2667 		index = 0;
2668 		break;
2669 	}
2670 
2671 	return (link_speed_str[index]);
2672 }
2673 
2674 int
ixl_sysctl_current_speed(SYSCTL_HANDLER_ARGS)2675 ixl_sysctl_current_speed(SYSCTL_HANDLER_ARGS)
2676 {
2677 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
2678 	struct i40e_hw *hw = &pf->hw;
2679 	int error = 0;
2680 
2681 	ixl_update_link_status(pf);
2682 
2683 	error = sysctl_handle_string(oidp,
2684 	    __DECONST(void *,
2685 		ixl_link_speed_string(hw->phy.link_info.link_speed)),
2686 	    8, req);
2687 
2688 	return (error);
2689 }
2690 
2691 /*
2692  * Converts 8-bit speeds value to and from sysctl flags and
2693  * Admin Queue flags.
2694  */
2695 static u8
ixl_convert_sysctl_aq_link_speed(u8 speeds,bool to_aq)2696 ixl_convert_sysctl_aq_link_speed(u8 speeds, bool to_aq)
2697 {
2698 #define SPEED_MAP_SIZE 8
2699 	static u16 speedmap[SPEED_MAP_SIZE] = {
2700 		(I40E_LINK_SPEED_100MB | (0x1 << 8)),
2701 		(I40E_LINK_SPEED_1GB   | (0x2 << 8)),
2702 		(I40E_LINK_SPEED_10GB  | (0x4 << 8)),
2703 		(I40E_LINK_SPEED_20GB  | (0x8 << 8)),
2704 		(I40E_LINK_SPEED_25GB  | (0x10 << 8)),
2705 		(I40E_LINK_SPEED_40GB  | (0x20 << 8)),
2706 		(I40E_LINK_SPEED_2_5GB | (0x40 << 8)),
2707 		(I40E_LINK_SPEED_5GB   | (0x80 << 8)),
2708 	};
2709 	u8 retval = 0;
2710 
2711 	for (int i = 0; i < SPEED_MAP_SIZE; i++) {
2712 		if (to_aq)
2713 			retval |= (speeds & (speedmap[i] >> 8)) ? (speedmap[i] & 0xff) : 0;
2714 		else
2715 			retval |= (speeds & speedmap[i]) ? (speedmap[i] >> 8) : 0;
2716 	}
2717 
2718 	return (retval);
2719 }
2720 
2721 int
ixl_set_advertised_speeds(struct ixl_pf * pf,int speeds,bool from_aq)2722 ixl_set_advertised_speeds(struct ixl_pf *pf, int speeds, bool from_aq)
2723 {
2724 	struct i40e_hw *hw = &pf->hw;
2725 	device_t dev = pf->dev;
2726 	struct i40e_aq_get_phy_abilities_resp abilities;
2727 	struct i40e_aq_set_phy_config config;
2728 	enum i40e_status_code aq_error = 0;
2729 
2730 	/* Get current capability information */
2731 	aq_error = i40e_aq_get_phy_capabilities(hw,
2732 	    FALSE, FALSE, &abilities, NULL);
2733 	if (aq_error) {
2734 		device_printf(dev,
2735 		    "%s: Error getting phy capabilities %d,"
2736 		    " aq error: %d\n", __func__, aq_error,
2737 		    hw->aq.asq_last_status);
2738 		return (EIO);
2739 	}
2740 
2741 	/* Prepare new config */
2742 	bzero(&config, sizeof(config));
2743 	if (from_aq)
2744 		config.link_speed = speeds;
2745 	else
2746 		config.link_speed = ixl_convert_sysctl_aq_link_speed(speeds, true);
2747 	config.phy_type = abilities.phy_type;
2748 	config.phy_type_ext = abilities.phy_type_ext;
2749 	config.abilities = abilities.abilities
2750 	    | I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
2751 	config.eee_capability = abilities.eee_capability;
2752 	config.eeer = abilities.eeer_val;
2753 	config.low_power_ctrl = abilities.d3_lpan;
2754 	config.fec_config = abilities.fec_cfg_curr_mod_ext_info
2755 	    & I40E_AQ_PHY_FEC_CONFIG_MASK;
2756 
2757 	/* Do aq command & restart link */
2758 	aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
2759 	if (aq_error) {
2760 		device_printf(dev,
2761 		    "%s: Error setting new phy config %d,"
2762 		    " aq error: %d\n", __func__, aq_error,
2763 		    hw->aq.asq_last_status);
2764 		return (EIO);
2765 	}
2766 
2767 	return (0);
2768 }
2769 
2770 /*
2771 ** Supported link speeds
2772 **	Flags:
2773 **	 0x1 - 100 Mb
2774 **	 0x2 - 1G
2775 **	 0x4 - 10G
2776 **	 0x8 - 20G
2777 **	0x10 - 25G
2778 **	0x20 - 40G
2779 **	0x40 - 2.5G
2780 **	0x80 - 5G
2781 */
2782 static int
ixl_sysctl_supported_speeds(SYSCTL_HANDLER_ARGS)2783 ixl_sysctl_supported_speeds(SYSCTL_HANDLER_ARGS)
2784 {
2785 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
2786 	int supported = ixl_convert_sysctl_aq_link_speed(pf->supported_speeds, false);
2787 
2788 	return sysctl_handle_int(oidp, NULL, supported, req);
2789 }
2790 
2791 /*
2792 ** Control link advertise speed:
2793 **	Flags:
2794 **	 0x1 - advertise 100 Mb
2795 **	 0x2 - advertise 1G
2796 **	 0x4 - advertise 10G
2797 **	 0x8 - advertise 20G
2798 **	0x10 - advertise 25G
2799 **	0x20 - advertise 40G
2800 **	0x40 - advertise 2.5G
2801 **	0x80 - advertise 5G
2802 **
2803 **	Set to 0 to disable link
2804 */
2805 int
ixl_sysctl_set_advertise(SYSCTL_HANDLER_ARGS)2806 ixl_sysctl_set_advertise(SYSCTL_HANDLER_ARGS)
2807 {
2808 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
2809 	device_t dev = pf->dev;
2810 	u8 converted_speeds;
2811 	int requested_ls = 0;
2812 	int error = 0;
2813 
2814 	/* Read in new mode */
2815 	requested_ls = pf->advertised_speed;
2816 	error = sysctl_handle_int(oidp, &requested_ls, 0, req);
2817 	if ((error) || (req->newptr == NULL))
2818 		return (error);
2819 	if (IXL_PF_IN_RECOVERY_MODE(pf)) {
2820 		device_printf(dev, "Interface is currently in FW recovery mode. "
2821 				"Setting advertise speed not supported\n");
2822 		return (EINVAL);
2823 	}
2824 
2825 	/* Error out if bits outside of possible flag range are set */
2826 	if ((requested_ls & ~((u8)0xFF)) != 0) {
2827 		device_printf(dev, "Input advertised speed out of range; "
2828 		    "valid flags are: 0x%02x\n",
2829 		    ixl_convert_sysctl_aq_link_speed(pf->supported_speeds, false));
2830 		return (EINVAL);
2831 	}
2832 
2833 	/* Check if adapter supports input value */
2834 	converted_speeds = ixl_convert_sysctl_aq_link_speed((u8)requested_ls, true);
2835 	if ((converted_speeds | pf->supported_speeds) != pf->supported_speeds) {
2836 		device_printf(dev, "Invalid advertised speed; "
2837 		    "valid flags are: 0x%02x\n",
2838 		    ixl_convert_sysctl_aq_link_speed(pf->supported_speeds, false));
2839 		return (EINVAL);
2840 	}
2841 
2842 	error = ixl_set_advertised_speeds(pf, requested_ls, false);
2843 	if (error)
2844 		return (error);
2845 
2846 	pf->advertised_speed = requested_ls;
2847 	ixl_update_link_status(pf);
2848 	return (0);
2849 }
2850 
2851 /*
2852  * Input: bitmap of enum i40e_aq_link_speed
2853  */
2854 u64
ixl_max_aq_speed_to_value(u8 link_speeds)2855 ixl_max_aq_speed_to_value(u8 link_speeds)
2856 {
2857 	if (link_speeds & I40E_LINK_SPEED_40GB)
2858 		return IF_Gbps(40);
2859 	if (link_speeds & I40E_LINK_SPEED_25GB)
2860 		return IF_Gbps(25);
2861 	if (link_speeds & I40E_LINK_SPEED_20GB)
2862 		return IF_Gbps(20);
2863 	if (link_speeds & I40E_LINK_SPEED_10GB)
2864 		return IF_Gbps(10);
2865 	if (link_speeds & I40E_LINK_SPEED_5GB)
2866 		return IF_Gbps(5);
2867 	if (link_speeds & I40E_LINK_SPEED_2_5GB)
2868 		return IF_Mbps(2500);
2869 	if (link_speeds & I40E_LINK_SPEED_1GB)
2870 		return IF_Gbps(1);
2871 	if (link_speeds & I40E_LINK_SPEED_100MB)
2872 		return IF_Mbps(100);
2873 	else
2874 		/* Minimum supported link speed */
2875 		return IF_Mbps(100);
2876 }
2877 
2878 /*
2879 ** Get the width and transaction speed of
2880 ** the bus this adapter is plugged into.
2881 */
2882 void
ixl_get_bus_info(struct ixl_pf * pf)2883 ixl_get_bus_info(struct ixl_pf *pf)
2884 {
2885 	struct i40e_hw *hw = &pf->hw;
2886 	device_t dev = pf->dev;
2887         u16 link;
2888         u32 offset, num_ports;
2889 	u64 max_speed;
2890 
2891 	/* Some devices don't use PCIE */
2892 	if (hw->mac.type == I40E_MAC_X722)
2893 		return;
2894 
2895         /* Read PCI Express Capabilities Link Status Register */
2896         pci_find_cap(dev, PCIY_EXPRESS, &offset);
2897         link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
2898 
2899 	/* Fill out hw struct with PCIE info */
2900 	i40e_set_pci_config_data(hw, link);
2901 
2902 	/* Use info to print out bandwidth messages */
2903         device_printf(dev,"PCI Express Bus: Speed %s %s\n",
2904             ((hw->bus.speed == i40e_bus_speed_8000) ? "8.0GT/s":
2905             (hw->bus.speed == i40e_bus_speed_5000) ? "5.0GT/s":
2906             (hw->bus.speed == i40e_bus_speed_2500) ? "2.5GT/s":"Unknown"),
2907             (hw->bus.width == i40e_bus_width_pcie_x8) ? "Width x8" :
2908             (hw->bus.width == i40e_bus_width_pcie_x4) ? "Width x4" :
2909             (hw->bus.width == i40e_bus_width_pcie_x2) ? "Width x2" :
2910             (hw->bus.width == i40e_bus_width_pcie_x1) ? "Width x1" :
2911             ("Unknown"));
2912 
2913 	/*
2914 	 * If adapter is in slot with maximum supported speed,
2915 	 * no warning message needs to be printed out.
2916 	 */
2917 	if (hw->bus.speed >= i40e_bus_speed_8000
2918 	    && hw->bus.width >= i40e_bus_width_pcie_x8)
2919 		return;
2920 
2921 	num_ports = bitcount32(hw->func_caps.valid_functions);
2922 	max_speed = ixl_max_aq_speed_to_value(pf->supported_speeds) / 1000000;
2923 
2924 	if ((num_ports * max_speed) > hw->bus.speed * hw->bus.width) {
2925                 device_printf(dev, "PCI-Express bandwidth available"
2926                     " for this device may be insufficient for"
2927                     " optimal performance.\n");
2928                 device_printf(dev, "Please move the device to a different"
2929 		    " PCI-e link with more lanes and/or higher"
2930 		    " transfer rate.\n");
2931         }
2932 }
2933 
2934 static int
ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS)2935 ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS)
2936 {
2937 	struct ixl_pf	*pf = (struct ixl_pf *)arg1;
2938 	struct i40e_hw	*hw = &pf->hw;
2939 	struct sbuf	*sbuf;
2940 
2941 	sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
2942 	ixl_nvm_version_str(hw, sbuf);
2943 	sbuf_finish(sbuf);
2944 	sbuf_delete(sbuf);
2945 
2946 	return (0);
2947 }
2948 
2949 void
ixl_print_nvm_cmd(device_t dev,struct i40e_nvm_access * nvma)2950 ixl_print_nvm_cmd(device_t dev, struct i40e_nvm_access *nvma)
2951 {
2952 	u8 nvma_ptr = nvma->config & 0xFF;
2953 	u8 nvma_flags = (nvma->config & 0xF00) >> 8;
2954 	const char * cmd_str;
2955 
2956 	switch (nvma->command) {
2957 	case I40E_NVM_READ:
2958 		if (nvma_ptr == 0xF && nvma_flags == 0xF &&
2959 		    nvma->offset == 0 && nvma->data_size == 1) {
2960 			device_printf(dev, "NVMUPD: Get Driver Status Command\n");
2961 			return;
2962 		}
2963 		cmd_str = "READ ";
2964 		break;
2965 	case I40E_NVM_WRITE:
2966 		cmd_str = "WRITE";
2967 		break;
2968 	default:
2969 		device_printf(dev, "NVMUPD: unknown command: 0x%08x\n", nvma->command);
2970 		return;
2971 	}
2972 	device_printf(dev,
2973 	    "NVMUPD: cmd: %s ptr: 0x%02x flags: 0x%01x offset: 0x%08x data_s: 0x%08x\n",
2974 	    cmd_str, nvma_ptr, nvma_flags, nvma->offset, nvma->data_size);
2975 }
2976 
2977 int
ixl_handle_nvmupd_cmd(struct ixl_pf * pf,struct ifdrv * ifd)2978 ixl_handle_nvmupd_cmd(struct ixl_pf *pf, struct ifdrv *ifd)
2979 {
2980 	struct i40e_hw *hw = &pf->hw;
2981 	struct i40e_nvm_access *nvma;
2982 	device_t dev = pf->dev;
2983 	enum i40e_status_code status = 0;
2984 	size_t nvma_size, ifd_len, exp_len;
2985 	int err, perrno;
2986 
2987 	DEBUGFUNC("ixl_handle_nvmupd_cmd");
2988 
2989 	/* Sanity checks */
2990 	nvma_size = sizeof(struct i40e_nvm_access);
2991 	ifd_len = ifd->ifd_len;
2992 
2993 	if (ifd_len < nvma_size ||
2994 	    ifd->ifd_data == NULL) {
2995 		device_printf(dev, "%s: incorrect ifdrv length or data pointer\n",
2996 		    __func__);
2997 		device_printf(dev, "%s: ifdrv length: %zu, sizeof(struct i40e_nvm_access): %zu\n",
2998 		    __func__, ifd_len, nvma_size);
2999 		device_printf(dev, "%s: data pointer: %p\n", __func__,
3000 		    ifd->ifd_data);
3001 		return (EINVAL);
3002 	}
3003 
3004 	nvma = malloc(ifd_len, M_IXL, M_WAITOK);
3005 	err = copyin(ifd->ifd_data, nvma, ifd_len);
3006 	if (err) {
3007 		device_printf(dev, "%s: Cannot get request from user space\n",
3008 		    __func__);
3009 		free(nvma, M_IXL);
3010 		return (err);
3011 	}
3012 
3013 	if (pf->dbg_mask & IXL_DBG_NVMUPD)
3014 		ixl_print_nvm_cmd(dev, nvma);
3015 
3016 	if (IXL_PF_IS_RESETTING(pf)) {
3017 		int count = 0;
3018 		while (count++ < 100) {
3019 			i40e_msec_delay(100);
3020 			if (!(IXL_PF_IS_RESETTING(pf)))
3021 				break;
3022 		}
3023 	}
3024 
3025 	if (IXL_PF_IS_RESETTING(pf)) {
3026 		device_printf(dev,
3027 		    "%s: timeout waiting for EMP reset to finish\n",
3028 		    __func__);
3029 		free(nvma, M_IXL);
3030 		return (-EBUSY);
3031 	}
3032 
3033 	if (nvma->data_size < 1 || nvma->data_size > 4096) {
3034 		device_printf(dev,
3035 		    "%s: invalid request, data size not in supported range\n",
3036 		    __func__);
3037 		free(nvma, M_IXL);
3038 		return (EINVAL);
3039 	}
3040 
3041 	/*
3042 	 * Older versions of the NVM update tool don't set ifd_len to the size
3043 	 * of the entire buffer passed to the ioctl. Check the data_size field
3044 	 * in the contained i40e_nvm_access struct and ensure everything is
3045 	 * copied in from userspace.
3046 	 */
3047 	exp_len = nvma_size + nvma->data_size - 1; /* One byte is kept in struct */
3048 
3049 	if (ifd_len < exp_len) {
3050 		ifd_len = exp_len;
3051 		nvma = realloc(nvma, ifd_len, M_IXL, M_WAITOK);
3052 		err = copyin(ifd->ifd_data, nvma, ifd_len);
3053 		if (err) {
3054 			device_printf(dev, "%s: Cannot get request from user space\n",
3055 					__func__);
3056 			free(nvma, M_IXL);
3057 			return (err);
3058 		}
3059 	}
3060 
3061 	// TODO: Might need a different lock here
3062 	// IXL_PF_LOCK(pf);
3063 	status = i40e_nvmupd_command(hw, nvma, nvma->data, &perrno);
3064 	// IXL_PF_UNLOCK(pf);
3065 
3066 	err = copyout(nvma, ifd->ifd_data, ifd_len);
3067 	free(nvma, M_IXL);
3068 	if (err) {
3069 		device_printf(dev, "%s: Cannot return data to user space\n",
3070 				__func__);
3071 		return (err);
3072 	}
3073 
3074 	/* Let the nvmupdate report errors, show them only when debug is enabled */
3075 	if (status != 0 && (pf->dbg_mask & IXL_DBG_NVMUPD) != 0)
3076 		device_printf(dev, "i40e_nvmupd_command status %s, perrno %d\n",
3077 		    i40e_stat_str(hw, status), perrno);
3078 
3079 	/*
3080 	 * -EPERM is actually ERESTART, which the kernel interprets as it needing
3081 	 * to run this ioctl again. So use -EACCES for -EPERM instead.
3082 	 */
3083 	if (perrno == -EPERM)
3084 		return (-EACCES);
3085 	else
3086 		return (perrno);
3087 }
3088 
3089 int
ixl_find_i2c_interface(struct ixl_pf * pf)3090 ixl_find_i2c_interface(struct ixl_pf *pf)
3091 {
3092 	struct i40e_hw *hw = &pf->hw;
3093 	bool i2c_en, port_matched;
3094 	u32 reg;
3095 
3096 	for (int i = 0; i < 4; i++) {
3097 		reg = rd32(hw, I40E_GLGEN_MDIO_I2C_SEL(i));
3098 		i2c_en = (reg & I40E_GLGEN_MDIO_I2C_SEL_MDIO_I2C_SEL_MASK);
3099 		port_matched = ((reg & I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_MASK)
3100 		    >> I40E_GLGEN_MDIO_I2C_SEL_PHY_PORT_NUM_SHIFT)
3101 		    & BIT(hw->port);
3102 		if (i2c_en && port_matched)
3103 			return (i);
3104 	}
3105 
3106 	return (-1);
3107 }
3108 
3109 void
ixl_set_link(struct ixl_pf * pf,bool enable)3110 ixl_set_link(struct ixl_pf *pf, bool enable)
3111 {
3112 	struct i40e_hw *hw = &pf->hw;
3113 	device_t dev = pf->dev;
3114 	struct i40e_aq_get_phy_abilities_resp abilities;
3115 	struct i40e_aq_set_phy_config config;
3116 	enum i40e_status_code aq_error = 0;
3117 	u32 phy_type, phy_type_ext;
3118 
3119 	/* Get initial capability information */
3120 	aq_error = i40e_aq_get_phy_capabilities(hw,
3121 	    FALSE, TRUE, &abilities, NULL);
3122 	if (aq_error) {
3123 		device_printf(dev,
3124 		    "%s: Error getting phy capabilities %d,"
3125 		    " aq error: %d\n", __func__, aq_error,
3126 		    hw->aq.asq_last_status);
3127 		return;
3128 	}
3129 
3130 	phy_type = abilities.phy_type;
3131 	phy_type_ext = abilities.phy_type_ext;
3132 
3133 	/* Get current capability information */
3134 	aq_error = i40e_aq_get_phy_capabilities(hw,
3135 	    FALSE, FALSE, &abilities, NULL);
3136 	if (aq_error) {
3137 		device_printf(dev,
3138 		    "%s: Error getting phy capabilities %d,"
3139 		    " aq error: %d\n", __func__, aq_error,
3140 		    hw->aq.asq_last_status);
3141 		return;
3142 	}
3143 
3144 	/* Prepare new config */
3145 	memset(&config, 0, sizeof(config));
3146 	config.link_speed = abilities.link_speed;
3147 	config.abilities = abilities.abilities;
3148 	config.eee_capability = abilities.eee_capability;
3149 	config.eeer = abilities.eeer_val;
3150 	config.low_power_ctrl = abilities.d3_lpan;
3151 	config.fec_config = abilities.fec_cfg_curr_mod_ext_info
3152 	    & I40E_AQ_PHY_FEC_CONFIG_MASK;
3153 	config.phy_type = 0;
3154 	config.phy_type_ext = 0;
3155 
3156 	config.abilities &= ~(I40E_AQ_PHY_FLAG_PAUSE_TX |
3157 			I40E_AQ_PHY_FLAG_PAUSE_RX);
3158 
3159 	switch (pf->fc) {
3160 	case I40E_FC_FULL:
3161 		config.abilities |= I40E_AQ_PHY_FLAG_PAUSE_TX |
3162 			I40E_AQ_PHY_FLAG_PAUSE_RX;
3163 		break;
3164 	case I40E_FC_RX_PAUSE:
3165 		config.abilities |= I40E_AQ_PHY_FLAG_PAUSE_RX;
3166 		break;
3167 	case I40E_FC_TX_PAUSE:
3168 		config.abilities |= I40E_AQ_PHY_FLAG_PAUSE_TX;
3169 		break;
3170 	default:
3171 		break;
3172 	}
3173 
3174 	if (enable) {
3175 		config.phy_type = phy_type;
3176 		config.phy_type_ext = phy_type_ext;
3177 
3178 	}
3179 
3180 	aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
3181 	if (aq_error) {
3182 		device_printf(dev,
3183 		    "%s: Error setting new phy config %d,"
3184 		    " aq error: %d\n", __func__, aq_error,
3185 		    hw->aq.asq_last_status);
3186 		return;
3187 	}
3188 
3189 	aq_error = i40e_aq_set_link_restart_an(hw, enable, NULL);
3190 	if (aq_error) {
3191 		device_printf(dev,
3192 		    "%s: Error set link config %d,"
3193 		    " aq error: %d\n", __func__, aq_error,
3194 		    hw->aq.asq_last_status);
3195 		return;
3196 	}
3197 }
3198 
3199 static char *
ixl_phy_type_string(u32 bit_pos,bool ext)3200 ixl_phy_type_string(u32 bit_pos, bool ext)
3201 {
3202 	static char * phy_types_str[32] = {
3203 		"SGMII",
3204 		"1000BASE-KX",
3205 		"10GBASE-KX4",
3206 		"10GBASE-KR",
3207 		"40GBASE-KR4",
3208 		"XAUI",
3209 		"XFI",
3210 		"SFI",
3211 		"XLAUI",
3212 		"XLPPI",
3213 		"40GBASE-CR4",
3214 		"10GBASE-CR1",
3215 		"SFP+ Active DA",
3216 		"QSFP+ Active DA",
3217 		"Reserved (14)",
3218 		"Reserved (15)",
3219 		"Reserved (16)",
3220 		"100BASE-TX",
3221 		"1000BASE-T",
3222 		"10GBASE-T",
3223 		"10GBASE-SR",
3224 		"10GBASE-LR",
3225 		"10GBASE-SFP+Cu",
3226 		"10GBASE-CR1",
3227 		"40GBASE-CR4",
3228 		"40GBASE-SR4",
3229 		"40GBASE-LR4",
3230 		"1000BASE-SX",
3231 		"1000BASE-LX",
3232 		"1000BASE-T Optical",
3233 		"20GBASE-KR2",
3234 		"Reserved (31)"
3235 	};
3236 	static char * ext_phy_types_str[8] = {
3237 		"25GBASE-KR",
3238 		"25GBASE-CR",
3239 		"25GBASE-SR",
3240 		"25GBASE-LR",
3241 		"25GBASE-AOC",
3242 		"25GBASE-ACC",
3243 		"2.5GBASE-T",
3244 		"5GBASE-T"
3245 	};
3246 
3247 	if (ext && bit_pos > 7) return "Invalid_Ext";
3248 	if (bit_pos > 31) return "Invalid";
3249 
3250 	return (ext) ? ext_phy_types_str[bit_pos] : phy_types_str[bit_pos];
3251 }
3252 
3253 /* TODO: ERJ: I don't this is necessary anymore. */
3254 int
ixl_aq_get_link_status(struct ixl_pf * pf,struct i40e_aqc_get_link_status * link_status)3255 ixl_aq_get_link_status(struct ixl_pf *pf, struct i40e_aqc_get_link_status *link_status)
3256 {
3257 	device_t dev = pf->dev;
3258 	struct i40e_hw *hw = &pf->hw;
3259 	struct i40e_aq_desc desc;
3260 	enum i40e_status_code status;
3261 
3262 	struct i40e_aqc_get_link_status *aq_link_status =
3263 		(struct i40e_aqc_get_link_status *)&desc.params.raw;
3264 
3265 	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_get_link_status);
3266 	link_status->command_flags = CPU_TO_LE16(I40E_AQ_LSE_ENABLE);
3267 	status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL);
3268 	if (status) {
3269 		device_printf(dev,
3270 		    "%s: i40e_aqc_opc_get_link_status status %s, aq error %s\n",
3271 		    __func__, i40e_stat_str(hw, status),
3272 		    i40e_aq_str(hw, hw->aq.asq_last_status));
3273 		return (EIO);
3274 	}
3275 
3276 	bcopy(aq_link_status, link_status, sizeof(struct i40e_aqc_get_link_status));
3277 	return (0);
3278 }
3279 
3280 static char *
ixl_phy_type_string_ls(u8 val)3281 ixl_phy_type_string_ls(u8 val)
3282 {
3283 	if (val >= 0x1F)
3284 		return ixl_phy_type_string(val - 0x1F, true);
3285 	else
3286 		return ixl_phy_type_string(val, false);
3287 }
3288 
3289 static int
ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS)3290 ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS)
3291 {
3292 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3293 	device_t dev = pf->dev;
3294 	struct sbuf *buf;
3295 	int error = 0;
3296 
3297 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3298 	if (!buf) {
3299 		device_printf(dev, "Could not allocate sbuf for sysctl output.\n");
3300 		return (ENOMEM);
3301 	}
3302 
3303 	struct i40e_aqc_get_link_status link_status;
3304 	error = ixl_aq_get_link_status(pf, &link_status);
3305 	if (error) {
3306 		sbuf_delete(buf);
3307 		return (error);
3308 	}
3309 
3310 	sbuf_printf(buf, "\n"
3311 	    "PHY Type : 0x%02x<%s>\n"
3312 	    "Speed    : 0x%02x\n"
3313 	    "Link info: 0x%02x\n"
3314 	    "AN info  : 0x%02x\n"
3315 	    "Ext info : 0x%02x\n"
3316 	    "Loopback : 0x%02x\n"
3317 	    "Max Frame: %d\n"
3318 	    "Config   : 0x%02x\n"
3319 	    "Power    : 0x%02x",
3320 	    link_status.phy_type,
3321 	    ixl_phy_type_string_ls(link_status.phy_type),
3322 	    link_status.link_speed,
3323 	    link_status.link_info,
3324 	    link_status.an_info,
3325 	    link_status.ext_info,
3326 	    link_status.loopback,
3327 	    link_status.max_frame_size,
3328 	    link_status.config,
3329 	    link_status.power_desc);
3330 
3331 	error = sbuf_finish(buf);
3332 	if (error)
3333 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3334 
3335 	sbuf_delete(buf);
3336 	return (error);
3337 }
3338 
3339 static int
ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS)3340 ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS)
3341 {
3342 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3343 	struct i40e_hw *hw = &pf->hw;
3344 	device_t dev = pf->dev;
3345 	enum i40e_status_code status;
3346 	struct i40e_aq_get_phy_abilities_resp abilities;
3347 	struct sbuf *buf;
3348 	int error = 0;
3349 
3350 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3351 	if (!buf) {
3352 		device_printf(dev, "Could not allocate sbuf for sysctl output.\n");
3353 		return (ENOMEM);
3354 	}
3355 
3356 	status = i40e_aq_get_phy_capabilities(hw,
3357 	    FALSE, arg2 != 0, &abilities, NULL);
3358 	if (status) {
3359 		device_printf(dev,
3360 		    "%s: i40e_aq_get_phy_capabilities() status %s, aq error %s\n",
3361 		    __func__, i40e_stat_str(hw, status),
3362 		    i40e_aq_str(hw, hw->aq.asq_last_status));
3363 		sbuf_delete(buf);
3364 		return (EIO);
3365 	}
3366 
3367 	sbuf_printf(buf, "\n"
3368 	    "PHY Type : %08x",
3369 	    abilities.phy_type);
3370 
3371 	if (abilities.phy_type != 0) {
3372 		sbuf_printf(buf, "<");
3373 		for (int i = 0; i < 32; i++)
3374 			if ((1 << i) & abilities.phy_type)
3375 				sbuf_printf(buf, "%s,", ixl_phy_type_string(i, false));
3376 		sbuf_printf(buf, ">");
3377 	}
3378 
3379 	sbuf_printf(buf, "\nPHY Ext  : %02x",
3380 	    abilities.phy_type_ext);
3381 
3382 	if (abilities.phy_type_ext != 0) {
3383 		sbuf_printf(buf, "<");
3384 		for (int i = 0; i < 4; i++)
3385 			if ((1 << i) & abilities.phy_type_ext)
3386 				sbuf_printf(buf, "%s,",
3387 				    ixl_phy_type_string(i, true));
3388 		sbuf_printf(buf, ">");
3389 	}
3390 
3391 	sbuf_printf(buf, "\nSpeed    : %02x", abilities.link_speed);
3392 	if (abilities.link_speed != 0) {
3393 		u8 link_speed;
3394 		sbuf_printf(buf, " <");
3395 		for (int i = 0; i < 8; i++) {
3396 			link_speed = (1 << i) & abilities.link_speed;
3397 			if (link_speed)
3398 				sbuf_printf(buf, "%s, ",
3399 				    ixl_link_speed_string(link_speed));
3400 		}
3401 		sbuf_printf(buf, ">");
3402 	}
3403 
3404 	sbuf_printf(buf, "\n"
3405 	    "Abilities: %02x\n"
3406 	    "EEE cap  : %04x\n"
3407 	    "EEER reg : %08x\n"
3408 	    "D3 Lpan  : %02x\n"
3409 	    "ID       : %02x %02x %02x %02x\n"
3410 	    "ModType  : %02x %02x %02x\n"
3411 	    "ModType E: %01x\n"
3412 	    "FEC Cfg  : %02x\n"
3413 	    "Ext CC   : %02x",
3414 	    abilities.abilities, abilities.eee_capability,
3415 	    abilities.eeer_val, abilities.d3_lpan,
3416 	    abilities.phy_id[0], abilities.phy_id[1],
3417 	    abilities.phy_id[2], abilities.phy_id[3],
3418 	    abilities.module_type[0], abilities.module_type[1],
3419 	    abilities.module_type[2], (abilities.fec_cfg_curr_mod_ext_info & 0xe0) >> 5,
3420 	    abilities.fec_cfg_curr_mod_ext_info & 0x1F,
3421 	    abilities.ext_comp_code);
3422 
3423 	error = sbuf_finish(buf);
3424 	if (error)
3425 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3426 
3427 	sbuf_delete(buf);
3428 	return (error);
3429 }
3430 
3431 static int
ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS)3432 ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS)
3433 {
3434 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3435 	struct ixl_vsi *vsi = &pf->vsi;
3436 	struct ixl_mac_filter *f;
3437 	device_t dev = pf->dev;
3438 	int error = 0, ftl_len = 0, ftl_counter = 0;
3439 
3440 	struct sbuf *buf;
3441 
3442 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3443 	if (!buf) {
3444 		device_printf(dev, "Could not allocate sbuf for sysctl output.\n");
3445 		return (ENOMEM);
3446 	}
3447 
3448 	sbuf_printf(buf, "\n");
3449 
3450 	/* Print MAC filters */
3451 	sbuf_printf(buf, "PF Filters:\n");
3452 	LIST_FOREACH(f, &vsi->ftl, ftle)
3453 		ftl_len++;
3454 
3455 	if (ftl_len < 1)
3456 		sbuf_printf(buf, "(none)\n");
3457 	else {
3458 		LIST_FOREACH(f, &vsi->ftl, ftle) {
3459 			sbuf_printf(buf,
3460 			    MAC_FORMAT ", vlan %4d, flags %#06x",
3461 			    MAC_FORMAT_ARGS(f->macaddr), f->vlan, f->flags);
3462 			/* don't print '\n' for last entry */
3463 			if (++ftl_counter != ftl_len)
3464 				sbuf_printf(buf, "\n");
3465 		}
3466 	}
3467 
3468 #ifdef PCI_IOV
3469 	/* TODO: Give each VF its own filter list sysctl */
3470 	struct ixl_vf *vf;
3471 	if (pf->num_vfs > 0) {
3472 		sbuf_printf(buf, "\n\n");
3473 		for (int i = 0; i < pf->num_vfs; i++) {
3474 			vf = &pf->vfs[i];
3475 			if (!(vf->vf_flags & VF_FLAG_ENABLED))
3476 				continue;
3477 
3478 			vsi = &vf->vsi;
3479 			ftl_len = 0, ftl_counter = 0;
3480 			sbuf_printf(buf, "VF-%d Filters:\n", vf->vf_num);
3481 			LIST_FOREACH(f, &vsi->ftl, ftle)
3482 				ftl_len++;
3483 
3484 			if (ftl_len < 1)
3485 				sbuf_printf(buf, "(none)\n");
3486 			else {
3487 				LIST_FOREACH(f, &vsi->ftl, ftle) {
3488 					sbuf_printf(buf,
3489 					    MAC_FORMAT ", vlan %4d, flags %#06x\n",
3490 					    MAC_FORMAT_ARGS(f->macaddr), f->vlan, f->flags);
3491 				}
3492 			}
3493 		}
3494 	}
3495 #endif
3496 
3497 	error = sbuf_finish(buf);
3498 	if (error)
3499 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3500 	sbuf_delete(buf);
3501 
3502 	return (error);
3503 }
3504 
3505 #define IXL_SW_RES_SIZE 0x14
3506 int
ixl_res_alloc_cmp(const void * a,const void * b)3507 ixl_res_alloc_cmp(const void *a, const void *b)
3508 {
3509 	const struct i40e_aqc_switch_resource_alloc_element_resp *one, *two;
3510 	one = (const struct i40e_aqc_switch_resource_alloc_element_resp *)a;
3511 	two = (const struct i40e_aqc_switch_resource_alloc_element_resp *)b;
3512 
3513 	return ((int)one->resource_type - (int)two->resource_type);
3514 }
3515 
3516 /*
3517  * Longest string length: 25
3518  */
3519 const char *
ixl_switch_res_type_string(u8 type)3520 ixl_switch_res_type_string(u8 type)
3521 {
3522 	static const char * ixl_switch_res_type_strings[IXL_SW_RES_SIZE] = {
3523 		"VEB",
3524 		"VSI",
3525 		"Perfect Match MAC address",
3526 		"S-tag",
3527 		"(Reserved)",
3528 		"Multicast hash entry",
3529 		"Unicast hash entry",
3530 		"VLAN",
3531 		"VSI List entry",
3532 		"(Reserved)",
3533 		"VLAN Statistic Pool",
3534 		"Mirror Rule",
3535 		"Queue Set",
3536 		"Inner VLAN Forward filter",
3537 		"(Reserved)",
3538 		"Inner MAC",
3539 		"IP",
3540 		"GRE/VN1 Key",
3541 		"VN2 Key",
3542 		"Tunneling Port"
3543 	};
3544 
3545 	if (type < IXL_SW_RES_SIZE)
3546 		return ixl_switch_res_type_strings[type];
3547 	else
3548 		return "(Reserved)";
3549 }
3550 
3551 static int
ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)3552 ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)
3553 {
3554 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3555 	struct i40e_hw *hw = &pf->hw;
3556 	device_t dev = pf->dev;
3557 	struct sbuf *buf;
3558 	enum i40e_status_code status;
3559 	int error = 0;
3560 
3561 	u8 num_entries;
3562 	struct i40e_aqc_switch_resource_alloc_element_resp resp[IXL_SW_RES_SIZE];
3563 
3564 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3565 	if (!buf) {
3566 		device_printf(dev, "Could not allocate sbuf for output.\n");
3567 		return (ENOMEM);
3568 	}
3569 
3570 	bzero(resp, sizeof(resp));
3571 	status = i40e_aq_get_switch_resource_alloc(hw, &num_entries,
3572 				resp,
3573 				IXL_SW_RES_SIZE,
3574 				NULL);
3575 	if (status) {
3576 		device_printf(dev,
3577 		    "%s: get_switch_resource_alloc() error %s, aq error %s\n",
3578 		    __func__, i40e_stat_str(hw, status),
3579 		    i40e_aq_str(hw, hw->aq.asq_last_status));
3580 		sbuf_delete(buf);
3581 		return (error);
3582 	}
3583 
3584 	/* Sort entries by type for display */
3585 	qsort(resp, num_entries,
3586 	    sizeof(struct i40e_aqc_switch_resource_alloc_element_resp),
3587 	    &ixl_res_alloc_cmp);
3588 
3589 	sbuf_cat(buf, "\n");
3590 	sbuf_printf(buf, "# of entries: %d\n", num_entries);
3591 	sbuf_printf(buf,
3592 	    "                     Type | Guaranteed | Total | Used   | Un-allocated\n"
3593 	    "                          | (this)     | (all) | (this) | (all)       \n");
3594 	for (int i = 0; i < num_entries; i++) {
3595 		sbuf_printf(buf,
3596 		    "%25s | %10d   %5d   %6d   %12d",
3597 		    ixl_switch_res_type_string(resp[i].resource_type),
3598 		    resp[i].guaranteed,
3599 		    resp[i].total,
3600 		    resp[i].used,
3601 		    resp[i].total_unalloced);
3602 		if (i < num_entries - 1)
3603 			sbuf_cat(buf, "\n");
3604 	}
3605 
3606 	error = sbuf_finish(buf);
3607 	if (error)
3608 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3609 
3610 	sbuf_delete(buf);
3611 	return (error);
3612 }
3613 
3614 enum ixl_sw_seid_offset {
3615 	IXL_SW_SEID_EMP = 1,
3616 	IXL_SW_SEID_MAC_START = 2,
3617 	IXL_SW_SEID_MAC_END = 5,
3618 	IXL_SW_SEID_PF_START = 16,
3619 	IXL_SW_SEID_PF_END = 31,
3620 	IXL_SW_SEID_VF_START = 32,
3621 	IXL_SW_SEID_VF_END = 159,
3622 };
3623 
3624 /*
3625  * Caller must init and delete sbuf; this function will clear and
3626  * finish it for caller.
3627  *
3628  * Note: The SEID argument only applies for elements defined by FW at
3629  * power-on; these include the EMP, Ports, PFs and VFs.
3630  */
3631 static char *
ixl_switch_element_string(struct sbuf * s,u8 element_type,u16 seid)3632 ixl_switch_element_string(struct sbuf *s, u8 element_type, u16 seid)
3633 {
3634 	sbuf_clear(s);
3635 
3636 	/* If SEID is in certain ranges, then we can infer the
3637 	 * mapping of SEID to switch element.
3638 	 */
3639 	if (seid == IXL_SW_SEID_EMP) {
3640 		sbuf_cat(s, "EMP");
3641 		goto out;
3642 	} else if (seid >= IXL_SW_SEID_MAC_START &&
3643 	    seid <= IXL_SW_SEID_MAC_END) {
3644 		sbuf_printf(s, "MAC  %2d",
3645 		    seid - IXL_SW_SEID_MAC_START);
3646 		goto out;
3647 	} else if (seid >= IXL_SW_SEID_PF_START &&
3648 	    seid <= IXL_SW_SEID_PF_END) {
3649 		sbuf_printf(s, "PF  %3d",
3650 		    seid - IXL_SW_SEID_PF_START);
3651 		goto out;
3652 	} else if (seid >= IXL_SW_SEID_VF_START &&
3653 	    seid <= IXL_SW_SEID_VF_END) {
3654 		sbuf_printf(s, "VF  %3d",
3655 		    seid - IXL_SW_SEID_VF_START);
3656 		goto out;
3657 	}
3658 
3659 	switch (element_type) {
3660 	case I40E_AQ_SW_ELEM_TYPE_BMC:
3661 		sbuf_cat(s, "BMC");
3662 		break;
3663 	case I40E_AQ_SW_ELEM_TYPE_PV:
3664 		sbuf_cat(s, "PV");
3665 		break;
3666 	case I40E_AQ_SW_ELEM_TYPE_VEB:
3667 		sbuf_cat(s, "VEB");
3668 		break;
3669 	case I40E_AQ_SW_ELEM_TYPE_PA:
3670 		sbuf_cat(s, "PA");
3671 		break;
3672 	case I40E_AQ_SW_ELEM_TYPE_VSI:
3673 		sbuf_printf(s, "VSI");
3674 		break;
3675 	default:
3676 		sbuf_cat(s, "?");
3677 		break;
3678 	}
3679 
3680 out:
3681 	sbuf_finish(s);
3682 	return sbuf_data(s);
3683 }
3684 
3685 static int
ixl_sw_cfg_elem_seid_cmp(const void * a,const void * b)3686 ixl_sw_cfg_elem_seid_cmp(const void *a, const void *b)
3687 {
3688 	const struct i40e_aqc_switch_config_element_resp *one, *two;
3689 	one = (const struct i40e_aqc_switch_config_element_resp *)a;
3690 	two = (const struct i40e_aqc_switch_config_element_resp *)b;
3691 
3692 	return ((int)one->seid - (int)two->seid);
3693 }
3694 
3695 static int
ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)3696 ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
3697 {
3698 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3699 	struct i40e_hw *hw = &pf->hw;
3700 	device_t dev = pf->dev;
3701 	struct sbuf *buf;
3702 	struct sbuf *nmbuf;
3703 	enum i40e_status_code status;
3704 	int error = 0;
3705 	u16 next = 0;
3706 	u8 aq_buf[I40E_AQ_LARGE_BUF];
3707 
3708 	struct i40e_aqc_switch_config_element_resp *elem;
3709 	struct i40e_aqc_get_switch_config_resp *sw_config;
3710 	sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
3711 
3712 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3713 	if (!buf) {
3714 		device_printf(dev, "Could not allocate sbuf for sysctl output.\n");
3715 		return (ENOMEM);
3716 	}
3717 
3718 	status = i40e_aq_get_switch_config(hw, sw_config,
3719 	    sizeof(aq_buf), &next, NULL);
3720 	if (status) {
3721 		device_printf(dev,
3722 		    "%s: aq_get_switch_config() error %s, aq error %s\n",
3723 		    __func__, i40e_stat_str(hw, status),
3724 		    i40e_aq_str(hw, hw->aq.asq_last_status));
3725 		sbuf_delete(buf);
3726 		return error;
3727 	}
3728 	if (next)
3729 		device_printf(dev, "%s: TODO: get more config with SEID %d\n",
3730 		    __func__, next);
3731 
3732 	nmbuf = sbuf_new_auto();
3733 	if (!nmbuf) {
3734 		device_printf(dev, "Could not allocate sbuf for name output.\n");
3735 		sbuf_delete(buf);
3736 		return (ENOMEM);
3737 	}
3738 
3739 	/* Sort entries by SEID for display */
3740 	qsort(sw_config->element, sw_config->header.num_reported,
3741 	    sizeof(struct i40e_aqc_switch_config_element_resp),
3742 	    &ixl_sw_cfg_elem_seid_cmp);
3743 
3744 	sbuf_cat(buf, "\n");
3745 	/* Assuming <= 255 elements in switch */
3746 	sbuf_printf(buf, "# of reported elements: %d\n", sw_config->header.num_reported);
3747 	sbuf_printf(buf, "total # of elements: %d\n", sw_config->header.num_total);
3748 	/* Exclude:
3749 	 * Revision -- all elements are revision 1 for now
3750 	 */
3751 	sbuf_printf(buf,
3752 	    "SEID (  Name  ) |  Up  (  Name  ) | Down (  Name  ) | Conn Type\n"
3753 	    "                |                 |                 | (uplink)\n");
3754 	for (int i = 0; i < sw_config->header.num_reported; i++) {
3755 		elem = &sw_config->element[i];
3756 
3757 		// "%4d (%8s) | %8s   %8s   %#8x",
3758 		sbuf_printf(buf, "%4d", elem->seid);
3759 		sbuf_cat(buf, " ");
3760 		sbuf_printf(buf, "(%8s)", ixl_switch_element_string(nmbuf,
3761 		    elem->element_type, elem->seid));
3762 		sbuf_cat(buf, " | ");
3763 		sbuf_printf(buf, "%4d", elem->uplink_seid);
3764 		sbuf_cat(buf, " ");
3765 		sbuf_printf(buf, "(%8s)", ixl_switch_element_string(nmbuf,
3766 		    0, elem->uplink_seid));
3767 		sbuf_cat(buf, " | ");
3768 		sbuf_printf(buf, "%4d", elem->downlink_seid);
3769 		sbuf_cat(buf, " ");
3770 		sbuf_printf(buf, "(%8s)", ixl_switch_element_string(nmbuf,
3771 		    0, elem->downlink_seid));
3772 		sbuf_cat(buf, " | ");
3773 		sbuf_printf(buf, "%8d", elem->connection_type);
3774 		if (i < sw_config->header.num_reported - 1)
3775 			sbuf_cat(buf, "\n");
3776 	}
3777 	sbuf_delete(nmbuf);
3778 
3779 	error = sbuf_finish(buf);
3780 	if (error)
3781 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3782 
3783 	sbuf_delete(buf);
3784 
3785 	return (error);
3786 }
3787 
3788 static int
ixl_sysctl_switch_vlans(SYSCTL_HANDLER_ARGS)3789 ixl_sysctl_switch_vlans(SYSCTL_HANDLER_ARGS)
3790 {
3791 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3792 	struct i40e_hw *hw = &pf->hw;
3793 	device_t dev = pf->dev;
3794 	int requested_vlan = -1;
3795 	enum i40e_status_code status = 0;
3796 	int error = 0;
3797 
3798 	error = sysctl_handle_int(oidp, &requested_vlan, 0, req);
3799 	if ((error) || (req->newptr == NULL))
3800 	    return (error);
3801 
3802 	if ((hw->flags & I40E_HW_FLAG_802_1AD_CAPABLE) == 0) {
3803 		device_printf(dev, "Flags disallow setting of vlans\n");
3804 		return (ENODEV);
3805 	}
3806 
3807 	hw->switch_tag = requested_vlan;
3808 	device_printf(dev,
3809 	    "Setting switch config to switch_tag=%04x, first_tag=%04x, second_tag=%04x\n",
3810 	    hw->switch_tag, hw->first_tag, hw->second_tag);
3811 	status = i40e_aq_set_switch_config(hw, 0, 0, 0, NULL);
3812 	if (status) {
3813 		device_printf(dev,
3814 		    "%s: aq_set_switch_config() error %s, aq error %s\n",
3815 		    __func__, i40e_stat_str(hw, status),
3816 		    i40e_aq_str(hw, hw->aq.asq_last_status));
3817 		return (status);
3818 	}
3819 	return (0);
3820 }
3821 
3822 static int
ixl_sysctl_hkey(SYSCTL_HANDLER_ARGS)3823 ixl_sysctl_hkey(SYSCTL_HANDLER_ARGS)
3824 {
3825 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3826 	struct i40e_hw *hw = &pf->hw;
3827 	device_t dev = pf->dev;
3828 	struct sbuf *buf;
3829 	int error = 0;
3830 	enum i40e_status_code status;
3831 	u32 reg;
3832 
3833 	struct i40e_aqc_get_set_rss_key_data key_data;
3834 
3835 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3836 	if (!buf) {
3837 		device_printf(dev, "Could not allocate sbuf for output.\n");
3838 		return (ENOMEM);
3839 	}
3840 
3841 	bzero(&key_data, sizeof(key_data));
3842 
3843 	sbuf_cat(buf, "\n");
3844 	if (hw->mac.type == I40E_MAC_X722) {
3845 		status = i40e_aq_get_rss_key(hw, pf->vsi.vsi_num, &key_data);
3846 		if (status)
3847 			device_printf(dev, "i40e_aq_get_rss_key status %s, error %s\n",
3848 			    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
3849 	} else {
3850 		for (int i = 0; i < IXL_RSS_KEY_SIZE_REG; i++) {
3851 			reg = i40e_read_rx_ctl(hw, I40E_PFQF_HKEY(i));
3852 			bcopy(&reg, ((caddr_t)&key_data) + (i << 2), 4);
3853 		}
3854 	}
3855 
3856 	ixl_sbuf_print_bytes(buf, (u8 *)&key_data, sizeof(key_data), 0, true);
3857 
3858 	error = sbuf_finish(buf);
3859 	if (error)
3860 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3861 	sbuf_delete(buf);
3862 
3863 	return (error);
3864 }
3865 
3866 static void
ixl_sbuf_print_bytes(struct sbuf * sb,u8 * buf,int length,int label_offset,bool text)3867 ixl_sbuf_print_bytes(struct sbuf *sb, u8 *buf, int length, int label_offset, bool text)
3868 {
3869 	int i, j, k, width;
3870 	char c;
3871 
3872 	if (length < 1 || buf == NULL) return;
3873 
3874 	int byte_stride = 16;
3875 	int lines = length / byte_stride;
3876 	int rem = length % byte_stride;
3877 	if (rem > 0)
3878 		lines++;
3879 
3880 	for (i = 0; i < lines; i++) {
3881 		width = (rem > 0 && i == lines - 1)
3882 		    ? rem : byte_stride;
3883 
3884 		sbuf_printf(sb, "%4d | ", label_offset + i * byte_stride);
3885 
3886 		for (j = 0; j < width; j++)
3887 			sbuf_printf(sb, "%02x ", buf[i * byte_stride + j]);
3888 
3889 		if (width < byte_stride) {
3890 			for (k = 0; k < (byte_stride - width); k++)
3891 				sbuf_printf(sb, "   ");
3892 		}
3893 
3894 		if (!text) {
3895 			sbuf_printf(sb, "\n");
3896 			continue;
3897 		}
3898 
3899 		for (j = 0; j < width; j++) {
3900 			c = (char)buf[i * byte_stride + j];
3901 			if (c < 32 || c > 126)
3902 				sbuf_printf(sb, ".");
3903 			else
3904 				sbuf_printf(sb, "%c", c);
3905 
3906 			if (j == width - 1)
3907 				sbuf_printf(sb, "\n");
3908 		}
3909 	}
3910 }
3911 
3912 static int
ixl_sysctl_hlut(SYSCTL_HANDLER_ARGS)3913 ixl_sysctl_hlut(SYSCTL_HANDLER_ARGS)
3914 {
3915 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3916 	struct i40e_hw *hw = &pf->hw;
3917 	device_t dev = pf->dev;
3918 	struct sbuf *buf;
3919 	int error = 0;
3920 	enum i40e_status_code status;
3921 	u8 hlut[512];
3922 	u32 reg;
3923 
3924 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
3925 	if (!buf) {
3926 		device_printf(dev, "Could not allocate sbuf for output.\n");
3927 		return (ENOMEM);
3928 	}
3929 
3930 	bzero(hlut, sizeof(hlut));
3931 	sbuf_cat(buf, "\n");
3932 	if (hw->mac.type == I40E_MAC_X722) {
3933 		status = i40e_aq_get_rss_lut(hw, pf->vsi.vsi_num, TRUE, hlut, sizeof(hlut));
3934 		if (status)
3935 			device_printf(dev, "i40e_aq_get_rss_lut status %s, error %s\n",
3936 			    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
3937 	} else {
3938 		for (int i = 0; i < hw->func_caps.rss_table_size >> 2; i++) {
3939 			reg = rd32(hw, I40E_PFQF_HLUT(i));
3940 			bcopy(&reg, &hlut[i << 2], 4);
3941 		}
3942 	}
3943 	ixl_sbuf_print_bytes(buf, hlut, 512, 0, false);
3944 
3945 	error = sbuf_finish(buf);
3946 	if (error)
3947 		device_printf(dev, "Error finishing sbuf: %d\n", error);
3948 	sbuf_delete(buf);
3949 
3950 	return (error);
3951 }
3952 
3953 static int
ixl_sysctl_hena(SYSCTL_HANDLER_ARGS)3954 ixl_sysctl_hena(SYSCTL_HANDLER_ARGS)
3955 {
3956 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3957 	struct i40e_hw *hw = &pf->hw;
3958 	u64 hena;
3959 
3960 	hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) |
3961 	    ((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32);
3962 
3963 	return sysctl_handle_long(oidp, NULL, hena, req);
3964 }
3965 
3966 /*
3967  * Sysctl to disable firmware's link management
3968  *
3969  * 1 - Disable link management on this port
3970  * 0 - Re-enable link management
3971  *
3972  * On normal NVMs, firmware manages link by default.
3973  */
3974 static int
ixl_sysctl_fw_link_management(SYSCTL_HANDLER_ARGS)3975 ixl_sysctl_fw_link_management(SYSCTL_HANDLER_ARGS)
3976 {
3977 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
3978 	struct i40e_hw *hw = &pf->hw;
3979 	device_t dev = pf->dev;
3980 	int requested_mode = -1;
3981 	enum i40e_status_code status = 0;
3982 	int error = 0;
3983 
3984 	/* Read in new mode */
3985 	error = sysctl_handle_int(oidp, &requested_mode, 0, req);
3986 	if ((error) || (req->newptr == NULL))
3987 		return (error);
3988 	/* Check for sane value */
3989 	if (requested_mode < 0 || requested_mode > 1) {
3990 		device_printf(dev, "Valid modes are 0 or 1\n");
3991 		return (EINVAL);
3992 	}
3993 
3994 	/* Set new mode */
3995 	status = i40e_aq_set_phy_debug(hw, !!(requested_mode) << 4, NULL);
3996 	if (status) {
3997 		device_printf(dev,
3998 		    "%s: Error setting new phy debug mode %s,"
3999 		    " aq error: %s\n", __func__, i40e_stat_str(hw, status),
4000 		    i40e_aq_str(hw, hw->aq.asq_last_status));
4001 		return (EIO);
4002 	}
4003 
4004 	return (0);
4005 }
4006 
4007 /*
4008  * Read some diagnostic data from a (Q)SFP+ module
4009  *
4010  *             SFP A2   QSFP Lower Page
4011  * Temperature 96-97	22-23
4012  * Vcc         98-99    26-27
4013  * TX power    102-103  34-35..40-41
4014  * RX power    104-105  50-51..56-57
4015  */
4016 static int
ixl_sysctl_read_i2c_diag_data(SYSCTL_HANDLER_ARGS)4017 ixl_sysctl_read_i2c_diag_data(SYSCTL_HANDLER_ARGS)
4018 {
4019 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4020 	device_t dev = pf->dev;
4021 	struct sbuf *sbuf;
4022 	int error = 0;
4023 	u8 output;
4024 
4025 	if (req->oldptr == NULL) {
4026 		error = SYSCTL_OUT(req, 0, 128);
4027 		return (0);
4028 	}
4029 
4030 	error = pf->read_i2c_byte(pf, 0, 0xA0, &output);
4031 	if (error) {
4032 		device_printf(dev, "Error reading from i2c\n");
4033 		return (error);
4034 	}
4035 
4036 	/* 0x3 for SFP; 0xD/0x11 for QSFP+/QSFP28 */
4037 	if (output == 0x3) {
4038 		/*
4039 		 * Check for:
4040 		 * - Internally calibrated data
4041 		 * - Diagnostic monitoring is implemented
4042 		 */
4043 		pf->read_i2c_byte(pf, 92, 0xA0, &output);
4044 		if (!(output & 0x60)) {
4045 			device_printf(dev, "Module doesn't support diagnostics: %02X\n", output);
4046 			return (0);
4047 		}
4048 
4049 		sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
4050 
4051 		for (u8 offset = 96; offset < 100; offset++) {
4052 			pf->read_i2c_byte(pf, offset, 0xA2, &output);
4053 			sbuf_printf(sbuf, "%02X ", output);
4054 		}
4055 		for (u8 offset = 102; offset < 106; offset++) {
4056 			pf->read_i2c_byte(pf, offset, 0xA2, &output);
4057 			sbuf_printf(sbuf, "%02X ", output);
4058 		}
4059 	} else if (output == 0xD || output == 0x11) {
4060 		/*
4061 		 * QSFP+ modules are always internally calibrated, and must indicate
4062 		 * what types of diagnostic monitoring are implemented
4063 		 */
4064 		sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
4065 
4066 		for (u8 offset = 22; offset < 24; offset++) {
4067 			pf->read_i2c_byte(pf, offset, 0xA0, &output);
4068 			sbuf_printf(sbuf, "%02X ", output);
4069 		}
4070 		for (u8 offset = 26; offset < 28; offset++) {
4071 			pf->read_i2c_byte(pf, offset, 0xA0, &output);
4072 			sbuf_printf(sbuf, "%02X ", output);
4073 		}
4074 		/* Read the data from the first lane */
4075 		for (u8 offset = 34; offset < 36; offset++) {
4076 			pf->read_i2c_byte(pf, offset, 0xA0, &output);
4077 			sbuf_printf(sbuf, "%02X ", output);
4078 		}
4079 		for (u8 offset = 50; offset < 52; offset++) {
4080 			pf->read_i2c_byte(pf, offset, 0xA0, &output);
4081 			sbuf_printf(sbuf, "%02X ", output);
4082 		}
4083 	} else {
4084 		device_printf(dev, "Module is not SFP/SFP+/SFP28/QSFP+ (%02X)\n", output);
4085 		return (0);
4086 	}
4087 
4088 	sbuf_finish(sbuf);
4089 	sbuf_delete(sbuf);
4090 
4091 	return (0);
4092 }
4093 
4094 /*
4095  * Sysctl to read a byte from I2C bus.
4096  *
4097  * Input: 32-bit value:
4098  * 	bits 0-7:   device address (0xA0 or 0xA2)
4099  * 	bits 8-15:  offset (0-255)
4100  *	bits 16-31: unused
4101  * Output: 8-bit value read
4102  */
4103 static int
ixl_sysctl_read_i2c_byte(SYSCTL_HANDLER_ARGS)4104 ixl_sysctl_read_i2c_byte(SYSCTL_HANDLER_ARGS)
4105 {
4106 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4107 	device_t dev = pf->dev;
4108 	int input = -1, error = 0;
4109 	u8 dev_addr, offset, output;
4110 
4111 	/* Read in I2C read parameters */
4112 	error = sysctl_handle_int(oidp, &input, 0, req);
4113 	if ((error) || (req->newptr == NULL))
4114 		return (error);
4115 	/* Validate device address */
4116 	dev_addr = input & 0xFF;
4117 	if (dev_addr != 0xA0 && dev_addr != 0xA2) {
4118 		return (EINVAL);
4119 	}
4120 	offset = (input >> 8) & 0xFF;
4121 
4122 	error = pf->read_i2c_byte(pf, offset, dev_addr, &output);
4123 	if (error)
4124 		return (error);
4125 
4126 	device_printf(dev, "%02X\n", output);
4127 	return (0);
4128 }
4129 
4130 /*
4131  * Sysctl to write a byte to the I2C bus.
4132  *
4133  * Input: 32-bit value:
4134  * 	bits 0-7:   device address (0xA0 or 0xA2)
4135  * 	bits 8-15:  offset (0-255)
4136  *	bits 16-23: value to write
4137  *	bits 24-31: unused
4138  * Output: 8-bit value written
4139  */
4140 static int
ixl_sysctl_write_i2c_byte(SYSCTL_HANDLER_ARGS)4141 ixl_sysctl_write_i2c_byte(SYSCTL_HANDLER_ARGS)
4142 {
4143 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4144 	device_t dev = pf->dev;
4145 	int input = -1, error = 0;
4146 	u8 dev_addr, offset, value;
4147 
4148 	/* Read in I2C write parameters */
4149 	error = sysctl_handle_int(oidp, &input, 0, req);
4150 	if ((error) || (req->newptr == NULL))
4151 		return (error);
4152 	/* Validate device address */
4153 	dev_addr = input & 0xFF;
4154 	if (dev_addr != 0xA0 && dev_addr != 0xA2) {
4155 		return (EINVAL);
4156 	}
4157 	offset = (input >> 8) & 0xFF;
4158 	value = (input >> 16) & 0xFF;
4159 
4160 	error = pf->write_i2c_byte(pf, offset, dev_addr, value);
4161 	if (error)
4162 		return (error);
4163 
4164 	device_printf(dev, "%02X written\n", value);
4165 	return (0);
4166 }
4167 
4168 static int
ixl_get_fec_config(struct ixl_pf * pf,struct i40e_aq_get_phy_abilities_resp * abilities,u8 bit_pos,int * is_set)4169 ixl_get_fec_config(struct ixl_pf *pf, struct i40e_aq_get_phy_abilities_resp *abilities,
4170     u8 bit_pos, int *is_set)
4171 {
4172 	device_t dev = pf->dev;
4173 	struct i40e_hw *hw = &pf->hw;
4174 	enum i40e_status_code status;
4175 
4176 	if (IXL_PF_IN_RECOVERY_MODE(pf))
4177 		return (EIO);
4178 
4179 	status = i40e_aq_get_phy_capabilities(hw,
4180 	    FALSE, FALSE, abilities, NULL);
4181 	if (status) {
4182 		device_printf(dev,
4183 		    "%s: i40e_aq_get_phy_capabilities() status %s, aq error %s\n",
4184 		    __func__, i40e_stat_str(hw, status),
4185 		    i40e_aq_str(hw, hw->aq.asq_last_status));
4186 		return (EIO);
4187 	}
4188 
4189 	*is_set = !!(abilities->fec_cfg_curr_mod_ext_info & bit_pos);
4190 	return (0);
4191 }
4192 
4193 static int
ixl_set_fec_config(struct ixl_pf * pf,struct i40e_aq_get_phy_abilities_resp * abilities,u8 bit_pos,int set)4194 ixl_set_fec_config(struct ixl_pf *pf, struct i40e_aq_get_phy_abilities_resp *abilities,
4195     u8 bit_pos, int set)
4196 {
4197 	device_t dev = pf->dev;
4198 	struct i40e_hw *hw = &pf->hw;
4199 	struct i40e_aq_set_phy_config config;
4200 	enum i40e_status_code status;
4201 
4202 	/* Set new PHY config */
4203 	memset(&config, 0, sizeof(config));
4204 	config.fec_config = abilities->fec_cfg_curr_mod_ext_info & ~(bit_pos);
4205 	if (set)
4206 		config.fec_config |= bit_pos;
4207 	if (config.fec_config != abilities->fec_cfg_curr_mod_ext_info) {
4208 		config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
4209 		config.phy_type = abilities->phy_type;
4210 		config.phy_type_ext = abilities->phy_type_ext;
4211 		config.link_speed = abilities->link_speed;
4212 		config.eee_capability = abilities->eee_capability;
4213 		config.eeer = abilities->eeer_val;
4214 		config.low_power_ctrl = abilities->d3_lpan;
4215 		status = i40e_aq_set_phy_config(hw, &config, NULL);
4216 
4217 		if (status) {
4218 			device_printf(dev,
4219 			    "%s: i40e_aq_set_phy_config() status %s, aq error %s\n",
4220 			    __func__, i40e_stat_str(hw, status),
4221 			    i40e_aq_str(hw, hw->aq.asq_last_status));
4222 			return (EIO);
4223 		}
4224 	}
4225 
4226 	return (0);
4227 }
4228 
4229 static int
ixl_sysctl_fec_fc_ability(SYSCTL_HANDLER_ARGS)4230 ixl_sysctl_fec_fc_ability(SYSCTL_HANDLER_ARGS)
4231 {
4232 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4233 	int mode, error = 0;
4234 
4235 	struct i40e_aq_get_phy_abilities_resp abilities;
4236 	error = ixl_get_fec_config(pf, &abilities, I40E_AQ_ENABLE_FEC_KR, &mode);
4237 	if (error)
4238 		return (error);
4239 	/* Read in new mode */
4240 	error = sysctl_handle_int(oidp, &mode, 0, req);
4241 	if ((error) || (req->newptr == NULL))
4242 		return (error);
4243 
4244 	return ixl_set_fec_config(pf, &abilities, I40E_AQ_SET_FEC_ABILITY_KR, !!(mode));
4245 }
4246 
4247 static int
ixl_sysctl_fec_rs_ability(SYSCTL_HANDLER_ARGS)4248 ixl_sysctl_fec_rs_ability(SYSCTL_HANDLER_ARGS)
4249 {
4250 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4251 	int mode, error = 0;
4252 
4253 	struct i40e_aq_get_phy_abilities_resp abilities;
4254 	error = ixl_get_fec_config(pf, &abilities, I40E_AQ_ENABLE_FEC_RS, &mode);
4255 	if (error)
4256 		return (error);
4257 	/* Read in new mode */
4258 	error = sysctl_handle_int(oidp, &mode, 0, req);
4259 	if ((error) || (req->newptr == NULL))
4260 		return (error);
4261 
4262 	return ixl_set_fec_config(pf, &abilities, I40E_AQ_SET_FEC_ABILITY_RS, !!(mode));
4263 }
4264 
4265 static int
ixl_sysctl_fec_fc_request(SYSCTL_HANDLER_ARGS)4266 ixl_sysctl_fec_fc_request(SYSCTL_HANDLER_ARGS)
4267 {
4268 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4269 	int mode, error = 0;
4270 
4271 	struct i40e_aq_get_phy_abilities_resp abilities;
4272 	error = ixl_get_fec_config(pf, &abilities, I40E_AQ_REQUEST_FEC_KR, &mode);
4273 	if (error)
4274 		return (error);
4275 	/* Read in new mode */
4276 	error = sysctl_handle_int(oidp, &mode, 0, req);
4277 	if ((error) || (req->newptr == NULL))
4278 		return (error);
4279 
4280 	return ixl_set_fec_config(pf, &abilities, I40E_AQ_SET_FEC_REQUEST_KR, !!(mode));
4281 }
4282 
4283 static int
ixl_sysctl_fec_rs_request(SYSCTL_HANDLER_ARGS)4284 ixl_sysctl_fec_rs_request(SYSCTL_HANDLER_ARGS)
4285 {
4286 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4287 	int mode, error = 0;
4288 
4289 	struct i40e_aq_get_phy_abilities_resp abilities;
4290 	error = ixl_get_fec_config(pf, &abilities, I40E_AQ_REQUEST_FEC_RS, &mode);
4291 	if (error)
4292 		return (error);
4293 	/* Read in new mode */
4294 	error = sysctl_handle_int(oidp, &mode, 0, req);
4295 	if ((error) || (req->newptr == NULL))
4296 		return (error);
4297 
4298 	return ixl_set_fec_config(pf, &abilities, I40E_AQ_SET_FEC_REQUEST_RS, !!(mode));
4299 }
4300 
4301 static int
ixl_sysctl_fec_auto_enable(SYSCTL_HANDLER_ARGS)4302 ixl_sysctl_fec_auto_enable(SYSCTL_HANDLER_ARGS)
4303 {
4304 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4305 	int mode, error = 0;
4306 
4307 	struct i40e_aq_get_phy_abilities_resp abilities;
4308 	error = ixl_get_fec_config(pf, &abilities, I40E_AQ_ENABLE_FEC_AUTO, &mode);
4309 	if (error)
4310 		return (error);
4311 	/* Read in new mode */
4312 	error = sysctl_handle_int(oidp, &mode, 0, req);
4313 	if ((error) || (req->newptr == NULL))
4314 		return (error);
4315 
4316 	return ixl_set_fec_config(pf, &abilities, I40E_AQ_SET_FEC_AUTO, !!(mode));
4317 }
4318 
4319 static int
ixl_sysctl_dump_debug_data(SYSCTL_HANDLER_ARGS)4320 ixl_sysctl_dump_debug_data(SYSCTL_HANDLER_ARGS)
4321 {
4322 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4323 	struct i40e_hw *hw = &pf->hw;
4324 	device_t dev = pf->dev;
4325 	struct sbuf *buf;
4326 	int error = 0;
4327 	enum i40e_status_code status;
4328 
4329 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
4330 	if (!buf) {
4331 		device_printf(dev, "Could not allocate sbuf for output.\n");
4332 		return (ENOMEM);
4333 	}
4334 
4335 	u8 *final_buff;
4336 	/* This amount is only necessary if reading the entire cluster into memory */
4337 #define IXL_FINAL_BUFF_SIZE	(1280 * 1024)
4338 	final_buff = malloc(IXL_FINAL_BUFF_SIZE, M_IXL, M_NOWAIT);
4339 	if (final_buff == NULL) {
4340 		device_printf(dev, "Could not allocate memory for output.\n");
4341 		goto out;
4342 	}
4343 	int final_buff_len = 0;
4344 
4345 	u8 cluster_id = 1;
4346 	bool more = true;
4347 
4348 	u8 dump_buf[4096];
4349 	u16 curr_buff_size = 4096;
4350 	u8 curr_next_table = 0;
4351 	u32 curr_next_index = 0;
4352 
4353 	u16 ret_buff_size;
4354 	u8 ret_next_table;
4355 	u32 ret_next_index;
4356 
4357 	sbuf_cat(buf, "\n");
4358 
4359 	while (more) {
4360 		status = i40e_aq_debug_dump(hw, cluster_id, curr_next_table, curr_next_index, curr_buff_size,
4361 		    dump_buf, &ret_buff_size, &ret_next_table, &ret_next_index, NULL);
4362 		if (status) {
4363 			device_printf(dev, "i40e_aq_debug_dump status %s, error %s\n",
4364 			    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
4365 			goto free_out;
4366 		}
4367 
4368 		/* copy info out of temp buffer */
4369 		bcopy(dump_buf, (caddr_t)final_buff + final_buff_len, ret_buff_size);
4370 		final_buff_len += ret_buff_size;
4371 
4372 		if (ret_next_table != curr_next_table) {
4373 			/* We're done with the current table; we can dump out read data. */
4374 			sbuf_printf(buf, "%d:", curr_next_table);
4375 			int bytes_printed = 0;
4376 			while (bytes_printed <= final_buff_len) {
4377 				sbuf_printf(buf, "%16D", ((caddr_t)final_buff + bytes_printed), "");
4378 				bytes_printed += 16;
4379 			}
4380 				sbuf_cat(buf, "\n");
4381 
4382 			/* The entire cluster has been read; we're finished */
4383 			if (ret_next_table == 0xFF)
4384 				break;
4385 
4386 			/* Otherwise clear the output buffer and continue reading */
4387 			bzero(final_buff, IXL_FINAL_BUFF_SIZE);
4388 			final_buff_len = 0;
4389 		}
4390 
4391 		if (ret_next_index == 0xFFFFFFFF)
4392 			ret_next_index = 0;
4393 
4394 		bzero(dump_buf, sizeof(dump_buf));
4395 		curr_next_table = ret_next_table;
4396 		curr_next_index = ret_next_index;
4397 	}
4398 
4399 free_out:
4400 	free(final_buff, M_IXL);
4401 out:
4402 	error = sbuf_finish(buf);
4403 	if (error)
4404 		device_printf(dev, "Error finishing sbuf: %d\n", error);
4405 	sbuf_delete(buf);
4406 
4407 	return (error);
4408 }
4409 
4410 static int
ixl_start_fw_lldp(struct ixl_pf * pf)4411 ixl_start_fw_lldp(struct ixl_pf *pf)
4412 {
4413 	struct i40e_hw *hw = &pf->hw;
4414 	enum i40e_status_code status;
4415 
4416 	status = i40e_aq_start_lldp(hw, false, NULL);
4417 	if (status != I40E_SUCCESS) {
4418 		switch (hw->aq.asq_last_status) {
4419 		case I40E_AQ_RC_EEXIST:
4420 			device_printf(pf->dev,
4421 			    "FW LLDP agent is already running\n");
4422 			break;
4423 		case I40E_AQ_RC_EPERM:
4424 			device_printf(pf->dev,
4425 			    "Device configuration forbids SW from starting "
4426 			    "the LLDP agent. Set the \"LLDP Agent\" UEFI HII "
4427 			    "attribute to \"Enabled\" to use this sysctl\n");
4428 			return (EINVAL);
4429 		default:
4430 			device_printf(pf->dev,
4431 			    "Starting FW LLDP agent failed: error: %s, %s\n",
4432 			    i40e_stat_str(hw, status),
4433 			    i40e_aq_str(hw, hw->aq.asq_last_status));
4434 			return (EINVAL);
4435 		}
4436 	}
4437 
4438 	atomic_clear_32(&pf->state, IXL_PF_STATE_FW_LLDP_DISABLED);
4439 	return (0);
4440 }
4441 
4442 static int
ixl_stop_fw_lldp(struct ixl_pf * pf)4443 ixl_stop_fw_lldp(struct ixl_pf *pf)
4444 {
4445 	struct i40e_hw *hw = &pf->hw;
4446 	device_t dev = pf->dev;
4447 	enum i40e_status_code status;
4448 
4449 	if (hw->func_caps.npar_enable != 0) {
4450 		device_printf(dev,
4451 		    "Disabling FW LLDP agent is not supported on this device\n");
4452 		return (EINVAL);
4453 	}
4454 
4455 	if ((hw->flags & I40E_HW_FLAG_FW_LLDP_STOPPABLE) == 0) {
4456 		device_printf(dev,
4457 		    "Disabling FW LLDP agent is not supported in this FW version. Please update FW to enable this feature.\n");
4458 		return (EINVAL);
4459 	}
4460 
4461 	status = i40e_aq_stop_lldp(hw, true, false, NULL);
4462 	if (status != I40E_SUCCESS) {
4463 		if (hw->aq.asq_last_status != I40E_AQ_RC_EPERM) {
4464 			device_printf(dev,
4465 			    "Disabling FW LLDP agent failed: error: %s, %s\n",
4466 			    i40e_stat_str(hw, status),
4467 			    i40e_aq_str(hw, hw->aq.asq_last_status));
4468 			return (EINVAL);
4469 		}
4470 
4471 		device_printf(dev, "FW LLDP agent is already stopped\n");
4472 	}
4473 
4474 	i40e_aq_set_dcb_parameters(hw, true, NULL);
4475 	atomic_set_32(&pf->state, IXL_PF_STATE_FW_LLDP_DISABLED);
4476 	return (0);
4477 }
4478 
4479 static int
ixl_sysctl_fw_lldp(SYSCTL_HANDLER_ARGS)4480 ixl_sysctl_fw_lldp(SYSCTL_HANDLER_ARGS)
4481 {
4482 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4483 	int state, new_state, error = 0;
4484 
4485 	state = new_state = ((pf->state & IXL_PF_STATE_FW_LLDP_DISABLED) == 0);
4486 
4487 	/* Read in new mode */
4488 	error = sysctl_handle_int(oidp, &new_state, 0, req);
4489 	if ((error) || (req->newptr == NULL))
4490 		return (error);
4491 
4492 	/* Already in requested state */
4493 	if (new_state == state)
4494 		return (error);
4495 
4496 	if (new_state == 0)
4497 		return ixl_stop_fw_lldp(pf);
4498 
4499 	return ixl_start_fw_lldp(pf);
4500 }
4501 
4502 static int
ixl_sysctl_eee_enable(SYSCTL_HANDLER_ARGS)4503 ixl_sysctl_eee_enable(SYSCTL_HANDLER_ARGS)
4504 {
4505 	struct ixl_pf         *pf = (struct ixl_pf *)arg1;
4506 	int                   state, new_state;
4507 	int                   sysctl_handle_status = 0;
4508 	enum i40e_status_code cmd_status;
4509 
4510 	/* Init states' values */
4511 	state = new_state = (!!(pf->state & IXL_PF_STATE_EEE_ENABLED));
4512 
4513 	/* Get requested mode */
4514 	sysctl_handle_status = sysctl_handle_int(oidp, &new_state, 0, req);
4515 	if ((sysctl_handle_status) || (req->newptr == NULL))
4516 		return (sysctl_handle_status);
4517 
4518 	/* Check if state has changed */
4519 	if (new_state == state)
4520 		return (0);
4521 
4522 	/* Set new state */
4523 	cmd_status = i40e_enable_eee(&pf->hw, (bool)(!!new_state));
4524 
4525 	/* Save new state or report error */
4526 	if (!cmd_status) {
4527 		if (new_state == 0)
4528 			atomic_clear_32(&pf->state, IXL_PF_STATE_EEE_ENABLED);
4529 		else
4530 			atomic_set_32(&pf->state, IXL_PF_STATE_EEE_ENABLED);
4531 	} else if (cmd_status == I40E_ERR_CONFIG)
4532 		return (EPERM);
4533 	else
4534 		return (EIO);
4535 
4536 	return (0);
4537 }
4538 
4539 static int
ixl_sysctl_set_link_active(SYSCTL_HANDLER_ARGS)4540 ixl_sysctl_set_link_active(SYSCTL_HANDLER_ARGS)
4541 {
4542 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4543 	int error, state;
4544 
4545 	state = !!(atomic_load_acq_32(&pf->state) &
4546 	    IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
4547 
4548 	error = sysctl_handle_int(oidp, &state, 0, req);
4549 	if ((error) || (req->newptr == NULL))
4550 		return (error);
4551 
4552 	if (state == 0)
4553 		atomic_clear_32(&pf->state, IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
4554 	else
4555 		atomic_set_32(&pf->state, IXL_PF_STATE_LINK_ACTIVE_ON_DOWN);
4556 
4557 	return (0);
4558 }
4559 
4560 
4561 int
ixl_attach_get_link_status(struct ixl_pf * pf)4562 ixl_attach_get_link_status(struct ixl_pf *pf)
4563 {
4564 	struct i40e_hw *hw = &pf->hw;
4565 	device_t dev = pf->dev;
4566 	int error = 0;
4567 
4568 	if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
4569 	    (hw->aq.fw_maj_ver < 4)) {
4570 		i40e_msec_delay(75);
4571 		error = i40e_aq_set_link_restart_an(hw, TRUE, NULL);
4572 		if (error) {
4573 			device_printf(dev, "link restart failed, aq_err=%d\n",
4574 			    pf->hw.aq.asq_last_status);
4575 			return error;
4576 		}
4577 	}
4578 
4579 	/* Determine link state */
4580 	hw->phy.get_link_info = TRUE;
4581 	i40e_get_link_status(hw, &pf->link_up);
4582 
4583 	/* Flow Control mode not set by user, read current FW settings */
4584 	if (pf->fc == -1)
4585 		pf->fc = hw->fc.current_mode;
4586 
4587 	return (0);
4588 }
4589 
4590 static int
ixl_sysctl_do_pf_reset(SYSCTL_HANDLER_ARGS)4591 ixl_sysctl_do_pf_reset(SYSCTL_HANDLER_ARGS)
4592 {
4593 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4594 	int requested = 0, error = 0;
4595 
4596 	/* Read in new mode */
4597 	error = sysctl_handle_int(oidp, &requested, 0, req);
4598 	if ((error) || (req->newptr == NULL))
4599 		return (error);
4600 
4601 	/* Initiate the PF reset later in the admin task */
4602 	atomic_set_32(&pf->state, IXL_PF_STATE_PF_RESET_REQ);
4603 
4604 	return (error);
4605 }
4606 
4607 static int
ixl_sysctl_do_core_reset(SYSCTL_HANDLER_ARGS)4608 ixl_sysctl_do_core_reset(SYSCTL_HANDLER_ARGS)
4609 {
4610 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4611 	struct i40e_hw *hw = &pf->hw;
4612 	int requested = 0, error = 0;
4613 
4614 	/* Read in new mode */
4615 	error = sysctl_handle_int(oidp, &requested, 0, req);
4616 	if ((error) || (req->newptr == NULL))
4617 		return (error);
4618 
4619 	wr32(hw, I40E_GLGEN_RTRIG, I40E_GLGEN_RTRIG_CORER_MASK);
4620 
4621 	return (error);
4622 }
4623 
4624 static int
ixl_sysctl_do_global_reset(SYSCTL_HANDLER_ARGS)4625 ixl_sysctl_do_global_reset(SYSCTL_HANDLER_ARGS)
4626 {
4627 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4628 	struct i40e_hw *hw = &pf->hw;
4629 	int requested = 0, error = 0;
4630 
4631 	/* Read in new mode */
4632 	error = sysctl_handle_int(oidp, &requested, 0, req);
4633 	if ((error) || (req->newptr == NULL))
4634 		return (error);
4635 
4636 	wr32(hw, I40E_GLGEN_RTRIG, I40E_GLGEN_RTRIG_GLOBR_MASK);
4637 
4638 	return (error);
4639 }
4640 
4641 /*
4642  * Print out mapping of TX queue indexes and Rx queue indexes
4643  * to MSI-X vectors.
4644  */
4645 static int
ixl_sysctl_queue_interrupt_table(SYSCTL_HANDLER_ARGS)4646 ixl_sysctl_queue_interrupt_table(SYSCTL_HANDLER_ARGS)
4647 {
4648 	struct ixl_pf *pf = (struct ixl_pf *)arg1;
4649 	struct ixl_vsi *vsi = &pf->vsi;
4650 	device_t dev = pf->dev;
4651 	struct sbuf *buf;
4652 	int error = 0;
4653 
4654 	struct ixl_rx_queue *rx_que = vsi->rx_queues;
4655 	struct ixl_tx_queue *tx_que = vsi->tx_queues;
4656 
4657 	buf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
4658 	if (!buf) {
4659 		device_printf(dev, "Could not allocate sbuf for output.\n");
4660 		return (ENOMEM);
4661 	}
4662 
4663 	sbuf_cat(buf, "\n");
4664 	for (int i = 0; i < vsi->num_rx_queues; i++) {
4665 		rx_que = &vsi->rx_queues[i];
4666 		sbuf_printf(buf, "(rxq %3d): %d\n", i, rx_que->msix);
4667 	}
4668 	for (int i = 0; i < vsi->num_tx_queues; i++) {
4669 		tx_que = &vsi->tx_queues[i];
4670 		sbuf_printf(buf, "(txq %3d): %d\n", i, tx_que->msix);
4671 	}
4672 
4673 	error = sbuf_finish(buf);
4674 	if (error)
4675 		device_printf(dev, "Error finishing sbuf: %d\n", error);
4676 	sbuf_delete(buf);
4677 
4678 	return (error);
4679 }
4680