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