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(®, ((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(®, &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