1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
14 */
15
16 /*
17 * Initialization entry points and setup for the Intel XL710 (i40e) family
18 * of Ethernet NICs.
19 */
20
21 #include "i40e_sw.h"
22
23 static char i40e_ident[] = "Intel 40Gb Ethernet";
24 static uint8_t i40e_ether_broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
25
26 /*
27 * Local function prototypes.
28 */
29
30 static int i40e_attach(dev_info_t *, ddi_attach_cmd_t);
31 static int i40e_detach(dev_info_t *, ddi_detach_cmd_t);
32 static int i40e_quiesce(dev_info_t *);
33 static void i40e_unconfigure(dev_info_t *, i40e_t *);
34 static void i40e_fm_init(i40e_t *);
35 static void i40e_fm_fini(i40e_t *);
36 static boolean_t i40e_identify_hardware(i40e_t *);
37 static boolean_t i40e_regs_map(i40e_t *);
38 static void i40e_init_properties(i40e_t *);
39 static boolean_t i40e_alloc_intrs(i40e_t *, dev_info_t *);
40 static boolean_t i40e_alloc_trqpairs_locks(i40e_t *);
41 static boolean_t i40e_map_intrs_to_vectors(i40e_t *);
42 static void i40e_free_trqpairs_locks(i40e_t *);
43 static int i40e_intr_callback(dev_info_t *, ddi_cb_action_t, void *, void *,
44 void *);
45 static boolean_t i40e_add_intr_handlers(i40e_t *);
46 static void i40e_timer(void *);
47 static boolean_t i40e_enable_interrupts(i40e_t *);
48 static boolean_t i40e_disable_interrupts(i40e_t *);
49 static int i40e_get_vsi_id(i40e_t *);
50
51 static struct cb_ops i40e_cb_ops = {
52 nulldev, /* cb_open */
53 nulldev, /* cb_close */
54 nodev, /* cb_strategy */
55 nodev, /* cb_print */
56 nodev, /* cb_dump */
57 nodev, /* cb_read */
58 nodev, /* cb_write */
59 nodev, /* cb_ioctl */
60 nodev, /* cb_devmap */
61 nodev, /* cb_mmap */
62 nodev, /* cb_segmap */
63 nochpoll, /* cb_chpoll */
64 ddi_prop_op, /* cb_prop_op */
65 NULL, /* cb_stream */
66 D_MP | D_HOTPLUG, /* cb_flag */
67 CB_REV, /* cb_rev */
68 nodev, /* cb_aread */
69 nodev /* cb_awrite */
70 };
71
72 static struct dev_ops i40e_dev_ops = {
73 DEVO_REV, /* devo_rev */
74 0, /* devo_refcnt */
75 NULL, /* devo_getinfo */
76 nulldev, /* devo_identify */
77 nulldev, /* devo_probe */
78 i40e_attach, /* devo_attach */
79 i40e_detach, /* devo_detach */
80 nodev, /* devo_reset */
81 &i40e_cb_ops, /* devo_cb_ops */
82 NULL, /* devo_bus_ops */
83 ddi_power, /* devo_power */
84 i40e_quiesce, /* devo_quiesce */
85 };
86
87 static struct modldrv i40e_modldrv = {
88 &mod_driverops, /* Type of module. This one is a driver */
89 i40e_ident, /* Description string */
90 &i40e_dev_ops /* driver ops */
91 };
92
93 static struct modlinkage i40e_modlinkage = {
94 MODREV_1, &i40e_modldrv, NULL
95 };
96
97 /*
98 * Access attributes for register mapping
99 * XXX KEBE ASKS --> Change these? Currently they're stolen from ixgbe...
100 */
101 ddi_device_acc_attr_t i40e_regs_acc_attr = {
102 DDI_DEVICE_ATTR_V1,
103 DDI_STRUCTURE_LE_ACC,
104 DDI_STRICTORDER_ACC,
105 DDI_FLAGERR_ACC
106 };
107
108 /*
109 * XXX KEBE SAYS NOTE: I'm currently using the ixgbe approach to things.
110 * It's VERY possible the Fortville/i40e world changes the game enough where
111 * we need to restructure the device capability structure.
112 * See i40e_common_code_init() for examples of why I NOTE this.
113 *
114 * Values pulled will have section number references from:
115 *
116 * BEGIN CSTYLED
117 * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xl710-10-40-controller-datasheet.pdf
118 * END CSTYLED
119 */
120 static adapter_info_t i40e_XL710_cap = {
121 1536, /* maximum number of rx queues */ /* 1.1.2 - LQP */
122 1, /* minimum number of rx queues */
123 256, /* default number of rx queues */
124 384, /* maximum number of rx groups */ /* 1.1.6 */
125 1, /* minimum number of rx groups */
126 1, /* default number of rx groups */
127 1536, /* maximum number of tx queues */ /* 1.1.2 - LQP */
128 1, /* minimum number of tx queues */
129 32, /* default number of tx queues */
130 9710, /* maximum MTU size */ /* 1.2, tbl 1-3 */
131 0xFF8, /* maximum interrupt throttle rate */
132 0, /* minimum interrupt throttle rate */
133 200, /* default interrupt throttle rate */
134 1024, /* maximum admin queue size. XXX KEBE SAYS REFERENCE */
135 256, /* minimum admin queue size. */
136 256, /* default admin queue size. */
137 4096, /* maximum admin queue buffer size. XXX REFERENCE */
138 4096, /* maximum admin queue buffer size. */
139 4096, /* maximum admin queue buffer size. */
140 129, /* maximum total msix vectors */ /* 1.2, tbl 1-2 */
141 48, /* maximum number of ring vectors */
142 2, /* maximum number of other vectors */
143 (0), /* "other" interrupt types handled */ /* KEBE SAYS FILL ME IN */
144
145 (0), /* "other" interrupt types enable mask */ /* KEBE SAYS FILL IN */
146
147 (I40E_FLAG_DCA_CAPABLE
148 | I40E_FLAG_RSS_CAPABLE
149 | I40E_FLAG_VMDQ_CAPABLE
150 | I40E_FLAG_RSC_CAPABLE) /* capability flags */
151 };
152
153 /*
154 * Loopback properties (see sys/netlb.h).
155 */
156 /* KEBE SAYS UNCOMMENT ME LATER...
157 static lb_property_t lb_normal = {
158 normal, "normal", I40E_LB_NONE
159 };
160
161 static lb_property_t lb_mac = {
162 internal, "MAC", I40E_LB_INTERNAL_MAC
163 };
164
165 static lb_property_t lb_external = {
166 external, "External", I40E_LB_EXTERNAL
167 };
168 ... XXX KEBE */
169
170 /*
171 * Generic Lan Driver (GLDv3)/MAC definitions and structures should mostly
172 * be in i40e_gld.c.
173 */
174
175 /*
176 * Logging function for this driver.
177 */
178 void
179 i40e_dev_err(i40e_t *i40e, int level, boolean_t console, const char *fmt,
180 va_list ap)
181 {
182 char buf[256]; /* Pardon the constant, seems enough for printing. */
183
184 (void) vsnprintf(buf, sizeof (buf), fmt, ap);
185
186 if (i40e == NULL) {
187 cmn_err(level, (console) ? "%s: %s" : "!%s: %s", MODULE_NAME,
188 buf);
189 } else {
190 dev_err(i40e->i40e_dip, level, (console) ? "%s" : "!%s",
191 buf);
192 }
193 }
194
195 /*
196 * Because there's the stupid trailing-comma problem with the C preprocessor
197 * and variable arguments, I need to instantiate these. Pardon the redundant
198 * code.
199 */
200 void
201 i40e_error(i40e_t *i40e, const char *fmt, ...)
202 {
203 va_list ap;
204
205 va_start(ap, fmt);
206 i40e_dev_err(i40e, CE_WARN, B_FALSE, fmt, ap);
207 va_end(ap);
208 }
209
210 void
211 i40e_log(i40e_t *i40e, const char *fmt, ...)
212 {
213 va_list ap;
214
215 va_start(ap, fmt);
216 i40e_dev_err(i40e, CE_NOTE, B_FALSE, fmt, ap);
217 va_end(ap);
218 }
219
220 void
221 i40e_notice(i40e_t *i40e, const char *fmt, ...)
222 {
223 va_list ap;
224
225 va_start(ap, fmt);
226 i40e_dev_err(i40e, CE_NOTE, B_TRUE, fmt, ap);
227 va_end(ap);
228 }
229
230 #define FIRST_TRY_COUNT 40 /* Arbitrary guess at how many elements needed. */
231 static boolean_t
232 i40e_get_hw_capabilities(i40e_t *i40e, i40e_hw_t *hw)
233 {
234 struct i40e_aqc_list_capabilities_element_resp *buf;
235 int nelems = FIRST_TRY_COUNT;
236 int rc, len;
237 uint16_t needed;
238
239 /*
240 * The common-code call needs a buffer. Allocate it, and try.
241 * if the common-code calls complains the buffer isn't large enough,
242 * use "needed" to try another allocation.
243 */
244 do {
245 len = nelems * sizeof (*buf);
246 buf = kmem_alloc(len, KM_SLEEP);
247 ASSERT(buf != NULL); /* Safe with KM_SLEEP. */
248 rc = i40e_aq_discover_capabilities(hw, buf, len,
249 &needed, i40e_aqc_opc_list_func_capabilities, NULL);
250 kmem_free(buf, len);
251 if (hw->aq.asq_last_status == I40E_AQ_RC_ENOMEM &&
252 nelems == FIRST_TRY_COUNT) {
253 if (nelems == needed) {
254 /* Measurable in WTFs... */
255 i40e_error(i40e, "Common code is insane.");
256 return (B_FALSE);
257 }
258 nelems = needed;
259 buf = NULL; /* i.e. Continue the loop. */
260 } else if (hw->aq.asq_last_status != I40E_AQ_RC_OK) {
261 i40e_error(i40e, "Capability discovery failed: %d", rc);
262 return (B_FALSE);
263 }
264 /* OKAY, we're good, with a freed buffer pointer to exit... */
265 ASSERT(buf != NULL);
266 } while (buf == NULL);
267
268 /*
269 * XXX KEBE SAYS NOTE: FreeBSD says capture this PF's starting queue
270 * pair.
271 */
272 /* i40e->i40e_qbase = hw->func_caps.base_queue; */ /* TODO? */
273 i40e_log(i40e, "The base queue pair is %d", hw->func_caps.base_queue);
274
275 return (B_TRUE);
276 }
277 #undef FIRST_TRY_COUNT
278
279 /*
280 * Unless a .conf file already overrode i40e_t structure values, they will
281 * be 0, and need to be set in conjuction with the now-available HW report.
282 */
283 static void
284 i40e_hw_to_instance(i40e_t *i40e, i40e_hw_t *hw)
285 {
286 if (i40e->i40e_num_trqpairs == 0) {
287 i40e->i40e_num_trqpairs =
288 min(hw->func_caps.num_tx_qp + hw->func_caps.num_rx_qp,
289 MAX_TX_RX_QUEUE_PAIRS);
290 }
291 /*
292 * XXX KEBE ASKS -> Is there an i40e/XL710 version of receive groups?
293 * For now, let's just set it to 1.
294 */
295 i40e->i40e_num_rx_groups = 1;
296
297 /*
298 * The combination of num_rx_rings and num_rx_groups may be not
299 * supported by h/w. We need to adjust them to appropriate values.
300 *
301 * NOTE: Right now we only work with XL710, if we get other i40es,
302 * we may need to adjust.
303 *
304 * NOTE2: With only one GLDv3 receive group, we can only do
305 * "RSS" at the moment. Also there are two types of VMDQ now in i40e,
306 * VMDQ and VMDQv2.
307 */
308 if (i40e->i40e_num_trqpairs == 1)
309 i40e->i40e_classify_mode = I40E_CLASSIFY_NONE;
310 else
311 i40e->i40e_classify_mode = I40E_CLASSIFY_RSS;
312 }
313
314 /*
315 * Initialize and call Intel common-code routines, includes some setup
316 * the common code expects from the driver. Also prints on failure, so
317 * the caller doesn't have to.
318 */
319 static boolean_t
320 i40e_common_code_init(i40e_t *i40e, i40e_hw_t *hw)
321 {
322 int rc;
323
324 /* Clear & reset hardware, using Intel's code. */
325 i40e_clear_hw(hw);
326 rc = i40e_pf_reset(hw);
327 if (rc != 0) {
328 i40e_error(i40e, "i40e_pf_reset() failed: %d\n", rc);
329 /* XXX KEBE ASKS FMA report? */
330 i40e_fm_ereport(i40e, DDI_FM_DEVICE_INVAL_STATE);
331 return (B_FALSE);
332 }
333
334 /* Initialize the shared code. */
335 rc = i40e_init_shared_code(hw);
336 if (rc != 0) {
337 i40e_error(i40e, "i40e_init_shared_code() failed: %d\n", rc);
338 return (B_FALSE);
339 }
340
341 /* Set admin queue parameters */
342 hw->aq.num_arq_entries = i40e->i40e_capab->def_adminq_len;
343 hw->aq.num_asq_entries = i40e->i40e_capab->def_adminq_len;
344 hw->aq.arq_buf_size = i40e->i40e_capab->def_adminq_bufsize;
345 hw->aq.asq_buf_size = i40e->i40e_capab->def_adminq_bufsize;
346 /* Initialize the admin queue */
347 rc = i40e_init_adminq(hw);
348 if (rc != 0) {
349 i40e_error(i40e, "i40e_init_adminq() failed: %d\n", rc);
350 i40e_error(i40e, "This may be due to a mismatch between "
351 "the firmware and the driver.\n");
352 /* XXX KEBE ASKS FMA report? */
353 i40e_fm_ereport(i40e, DDI_FM_DEVICE_INVAL_STATE);
354 return (B_FALSE);
355 }
356 /* Check for other firmware mismatches. */
357 if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
358 hw->aq.api_min_ver > I40E_FW_API_VERSION_MINOR) {
359 i40e_notice(i40e, "The driver for the device detected a newer "
360 "version of the NVM image (%d.%d) than expected (%d.%d).\n"
361 "Please install the most recent version of the network "
362 "driver.\n", hw->aq.api_maj_ver, hw->aq.api_min_ver,
363 I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR);
364 } else if (hw->aq.api_maj_ver < I40E_FW_API_VERSION_MAJOR ||
365 hw->aq.api_min_ver < (I40E_FW_API_VERSION_MINOR - 1)) {
366 i40e_notice(i40e, "The driver for the device detected an older"
367 " version of the NVM image (%d.%d) than expected (%d.%d)."
368 "\nPlease update the NVM image.\n",
369 hw->aq.api_maj_ver, hw->aq.api_min_ver,
370 I40E_FW_API_VERSION_MAJOR, I40E_FW_API_VERSION_MINOR - 1);
371 }
372
373 /* Clear PXE mode */
374 i40e_clear_pxe_mode(hw);
375
376 /*
377 * Have the common code discover things about the hardware.
378 */
379 if (!i40e_get_hw_capabilities(i40e, hw)) {
380 i40e_error(i40e, "Obtaining HW capabilities failed.");
381 /* XXX KEBE ASKS FMA report? */
382 i40e_fm_ereport(i40e, DDI_FM_DEVICE_INVAL_STATE);
383 return (B_FALSE);
384 }
385
386 /*
387 * Now that we know some of the HW capabilities, let's initialize
388 * them if they aren't already in our i40e.
389 */
390 i40e_hw_to_instance(i40e, hw);
391
392 /* Set up host memory cache */
393 rc = i40e_init_lan_hmc(hw, hw->func_caps.num_tx_qp,
394 hw->func_caps.num_rx_qp, 0, 0);
395 if (rc != 0) {
396 i40e_error(i40e, "init_lan_hmc failed: %d\n", rc);
397 return (B_FALSE);
398 }
399
400 rc = i40e_configure_lan_hmc(hw, I40E_HMC_MODEL_DIRECT_ONLY);
401 if (rc != 0) {
402 i40e_error(i40e, "configure_lan_hmc failed: %d\n", rc);
403 return (B_FALSE);
404 }
405
406 /* Disable LLDP from the firmware */
407 i40e_aq_stop_lldp(hw, TRUE, NULL);
408
409 i40e_get_mac_addr(hw, hw->mac.addr);
410 rc = i40e_validate_mac_addr(hw->mac.addr);
411 if (rc != 0) {
412 i40e_error(i40e, "validate_mac_addr failed: %d\n", rc);
413 return (B_FALSE);
414 }
415 bcopy(hw->mac.addr, hw->mac.perm_addr, ETHERADDRL);
416 i40e_get_port_mac_addr(hw, hw->mac.port_addr);
417
418 /*
419 * We need to obtain the Virtual Station ID (vsi) before we can
420 * anything else.
421 */
422 i40e->i40e_vsi_id = i40e_get_vsi_id(i40e);
423 if (i40e->i40e_vsi_id == -1) {
424 i40e_error(i40e, "Failed to get VSI ID");
425 return (B_FALSE);
426 }
427
428 return (B_TRUE);
429 }
430
431 /*
432 * Free any resources required by, or setup by, the Intel common code.
433 */
434 static void
435 i40e_common_code_fini(i40e_t *i40e)
436 {
437 i40e_hw_t *hw = &i40e->i40e_hw_space;
438 int rc;
439
440 rc = i40e_shutdown_adminq(hw);
441 if (rc != I40E_SUCCESS)
442 i40e_error(i40e, "i40e_shutdown_adminq() failed: %d", rc);
443
444 rc = i40e_shutdown_lan_hmc(hw);
445 if (rc != I40E_SUCCESS)
446 i40e_error(i40e, "i40e_shutdown_lan_hmc() failed: %d", rc);
447
448 /* XXX KEBE ASKS ---> more here?!? */
449 }
450
451 static boolean_t
452 i40e_final_init(i40e_t *i40e)
453 {
454 i40e_hw_t *hw = &i40e->i40e_hw_space;
455 struct i40e_osdep *osdep = OS_DEP(hw);
456 uint8_t pbanum[I40E_PBANUM_STRLEN];
457 enum i40e_status_code irc;
458
459 /* XXX KEBE ASKS enter/exit i40e->i40e_gen_lock here ? */
460
461 pbanum[0] = '\0';
462 irc = i40e_read_pba_string(hw, pbanum, sizeof (pbanum));
463 if (irc != I40E_SUCCESS) {
464 i40e_error(i40e, "i40e_read_pba_string() failed: %d", irc);
465 return (B_FALSE);
466 }
467 if (pbanum[0] != '\0') {
468 /* (void) this?!? */
469 (void) ddi_prop_update_string(DDI_DEV_T_NONE, i40e->i40e_dip,
470 "printed-board-assembly", (char *)pbanum);
471 }
472
473 if (!i40e_set_hw_bus_info(hw))
474 return (B_FALSE);
475
476 if (i40e_check_acc_handle(osdep->reg_handle) != DDI_FM_OK) {
477 ddi_fm_service_impact(i40e->i40e_dip, DDI_SERVICE_LOST);
478 return (B_FALSE);
479 }
480
481 return (B_TRUE);
482 }
483
484 /*
485 * i40e_attach - Driver attach.
486 *
487 * This function is the device specific initialization entry
488 * point. This entry point is required and must be written.
489 * The DDI_ATTACH command must be provided in the attach entry
490 * point. When attach() is called with cmd set to DDI_ATTACH,
491 * all normal kernel services (such as kmem_alloc(9F)) are
492 * available for use by the driver.
493 *
494 * The attach() function will be called once for each instance
495 * of the device on the system with cmd set to DDI_ATTACH.
496 * Until attach() succeeds, the only driver entry points which
497 * may be called are open(9E) and getinfo(9E).
498 */
499 static int
500 i40e_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
501 {
502 i40e_t *i40e;
503 struct i40e_osdep *osdep;
504 i40e_hw_t *hw;
505 int instance, rc;
506 char taskqname[32];
507
508 /* Vector off bad commands or RESUME. */
509 switch (cmd) {
510 default:
511 return (DDI_FAILURE);
512 case DDI_RESUME:
513 /* return (i40e_resume(devinfo)); */
514 goto attach_fail; /* XXX NUKE ME!!! */
515 case DDI_ATTACH:
516 break;
517 }
518
519 /* NOW we proceed with the actual attachment code. */
520
521 instance = ddi_get_instance(devinfo);
522 i40e = kmem_zalloc(sizeof (i40e_t), KM_SLEEP);
523 /* No NULL check needed for KM_SLEEP... */
524
525 i40e->i40e_instance = instance;
526 i40e->i40e_dip = devinfo;
527
528 hw = &i40e->i40e_hw_space;
529 osdep = &i40e->i40e_osdep_space;
530 hw->back = osdep;
531 osdep->i40e = i40e;
532
533 ddi_set_driver_private(devinfo, i40e);
534
535 /* Setup FMA support. */
536 i40e_fm_init(i40e);
537 i40e->i40e_attach_progress |= ATTACH_PROGRESS_FM_INIT;
538
539 /* Map PCI config space registers. */
540 if (pci_config_setup(devinfo, &osdep->cfg_handle) != DDI_SUCCESS) {
541 i40e_error(i40e, "Failed to map PCI configurations.");
542 goto attach_fail;
543 }
544 i40e->i40e_attach_progress |= ATTACH_PROGRESS_PCI_CONFIG;
545
546 /*
547 * Map the device registers. This involves identifying the
548 * hardware, followed by the actual mapping.
549 */
550 if (!i40e_identify_hardware(i40e)) {
551 i40e_error(i40e, "Cannot identify hardware.");
552 goto attach_fail;
553 }
554
555 /* Now the actual mapping. */
556 if (!i40e_regs_map(i40e)) {
557 i40e_error(i40e, "Failed to map device registers.");
558 goto attach_fail;
559 }
560 i40e->i40e_attach_progress |= ATTACH_PROGRESS_REGS_MAP;
561
562 i40e_init_properties(i40e);
563 i40e->i40e_attach_progress |= ATTACH_PROGRESS_PROPS;
564
565 if (!i40e_common_code_init(i40e, hw))
566 goto attach_fail;
567 i40e->i40e_attach_progress |= ATTACH_PROGRESS_COMMON_CODE;
568
569 /* Register the interrupt callback and allocate interrupts. */
570 rc = ddi_cb_register(devinfo, DDI_CB_FLAG_INTR, i40e_intr_callback,
571 i40e, NULL, &i40e->i40e_callback_handle);
572 if (rc != DDI_SUCCESS) {
573 i40e_error(i40e,
574 "Failed to register an interrupt callback: %d.", rc);
575 goto attach_fail;
576 }
577
578 if (!i40e_alloc_intrs(i40e, devinfo)) {
579 i40e_error(i40e, "Failed to allocate interrupts.");
580 goto attach_fail;
581 }
582 i40e->i40e_attach_progress |= ATTACH_PROGRESS_ALLOC_INTR;
583
584 /* Allocate tx/rx queue pairs and initialize locks. */
585 if (!i40e_alloc_trqpairs_locks(i40e)) {
586 i40e_error(i40e,
587 "Failed to allocate receive & transmit rings.");
588 goto attach_fail;
589 }
590 i40e->i40e_attach_progress |= ATTACH_PROGRESS_ALLOC_RINGSLOCKS;
591
592 /* Map trqpairs to interrupts vectors... */
593 if (!i40e_map_intrs_to_vectors(i40e)) {
594 i40e_error(i40e, "Failed to map interrupts to vectors.");
595 goto attach_fail;
596 }
597 /* ...then add interrupt handlers. */
598 if (!i40e_add_intr_handlers(i40e)) {
599 i40e_error(i40e, "Failed to add the interrupt handlers.");
600 goto attach_fail;
601 }
602 i40e->i40e_attach_progress |= ATTACH_PROGRESS_ADD_INTR;
603
604 /* Create taskqs for SFP-change & over-temp. */
605 (void) sprintf(taskqname, "i40e%d_sfp_taskq", instance);
606 i40e->i40e_sfp_taskq = ddi_taskq_create(devinfo, taskqname, 1,
607 TASKQ_DEFAULTPRI, 0);
608 if (i40e->i40e_sfp_taskq == NULL) {
609 i40e_error(i40e, "i40e_sfp_taskq creation failed");
610 goto attach_fail;
611 }
612 i40e->i40e_attach_progress |= ATTACH_PROGRESS_SFP_TASKQ;
613
614 (void) sprintf(taskqname, "i40e%d_overtemp_taskq", instance);
615 i40e->i40e_overtemp_taskq = ddi_taskq_create(devinfo, taskqname, 1,
616 TASKQ_DEFAULTPRI, 0);
617 if (i40e->i40e_overtemp_taskq == NULL) {
618 i40e_error(i40e, "i40e_overtemp_taskq creation failed");
619 goto attach_fail;
620 }
621 i40e->i40e_attach_progress |= ATTACH_PROGRESS_OVERTEMP_TASKQ;
622
623 /* Additional initialization of chipset hardware. */
624 if (!i40e_final_init(i40e)) {
625 i40e_error(i40e, "Final initialization failed.");
626 goto attach_fail;
627 }
628 i40e->i40e_attach_progress |= ATTACH_PROGRESS_INIT;
629
630 /* Check the FM acc handle. (No progress needed.) */
631 if (i40e_check_acc_handle(i40e->i40e_osdep_space.cfg_handle) !=
632 DDI_FM_OK) {
633 ddi_fm_service_impact(i40e->i40e_dip, DDI_SERVICE_LOST);
634 goto attach_fail;
635 }
636
637 /* XXX KEBE SAYS Initialize the statistics. */
638
639 if (!i40e_init_stats(i40e)) {
640 i40e_error(i40e, "Stats initialization failed.");
641 goto attach_fail;
642 }
643 i40e->i40e_attach_progress |= ATTACH_PROGRESS_STATS;
644
645 /* Register the driver to GLDv3/mac. */
646 if (!i40e_register_mac(i40e)) {
647 i40e_error(i40e, "Failed to register to MAC/GLDv3");
648 goto attach_fail;
649 }
650 i40e->i40e_attach_progress |= ATTACH_PROGRESS_MAC;
651
652 /* Add a DDI periodic timer. */
653 i40e->i40e_periodic_id = ddi_periodic_add(i40e_timer, i40e,
654 I40E_CYCLIC_PERIOD, DDI_IPL_0);
655 if (i40e->i40e_periodic_id == 0) {
656 i40e_error(i40e, "Failed to add the link-check timer");
657 goto attach_fail;
658 }
659 i40e->i40e_attach_progress |= ATTACH_PROGRESS_LINK_TIMER;
660
661 /* XXX KEBE SAYS Enable the interrupts! */
662 if (!i40e_enable_interrupts(i40e)) {
663 i40e_error(i40e, "Failed to enable DDI interrupts");
664 goto attach_fail;
665 }
666 i40e->i40e_attach_progress |= ATTACH_PROGRESS_ENABLE_INTR;
667
668 /* Atomic-or the I40E_INITIALIZED flag. */
669 atomic_or_32(&i40e->i40e_state, I40E_INITIALIZED);
670
671 return (DDI_SUCCESS);
672
673 attach_fail:
674 i40e_unconfigure(devinfo, i40e);
675 return (DDI_FAILURE);
676 }
677
678 /*
679 * i40e_detach - Driver detach.
680 *
681 * The detach() function is the complement of the attach routine.
682 * If cmd is set to DDI_DETACH, detach() is used to remove the
683 * state associated with a given instance of a device node
684 * prior to the removal of that instance from the system.
685 *
686 * The detach() function will be called once for each instance
687 * of the device for which there has been a successful attach()
688 * once there are no longer any opens on the device.
689 *
690 * Interrupts routine are disabled, All memory allocated by this
691 * driver are freed.
692 */
693 static int
694 i40e_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
695 {
696 i40e_t *i40e;
697
698 switch (cmd) {
699 default:
700 return (DDI_FAILURE);
701 case DDI_SUSPEND:
702 /* XXX KEBE SAYS FILL ME IN */
703 return (DDI_FAILURE);
704 case DDI_DETACH:
705 break;
706 }
707
708 i40e = (i40e_t *)ddi_get_driver_private(devinfo);
709 if (i40e == NULL) {
710 i40e_log(NULL, "i40e_detach() called with no i40e pointer!");
711 return (DDI_FAILURE);
712 }
713
714 /*
715 * XXX KEBE SAYS FILL IN still-running checks and drain the rx
716 * buffers that upper layers may have lying about.
717 */
718
719 /*
720 if (i40e->i40e_state & I40E_STARTED...)
721 */
722
723
724 /*
725 if (!i40e_rx_drain(i40e))
726 return (DDI_FAILURE);
727 */
728
729 i40e_unconfigure(devinfo, i40e);
730 return (DDI_SUCCESS);
731 }
732
733 static void
734 i40e_rem_intrs(i40e_t *i40e)
735 {
736 int i, rc;
737
738 for (i = 0; i < i40e->i40e_intr_count; i++) {
739 rc = ddi_intr_free(i40e->i40e_intr_handles[i]);
740 if (rc != DDI_SUCCESS) {
741 i40e_log(i40e, "Can't free i40e_intr_handle[%d]: %d",
742 i, rc);
743 }
744 }
745
746 kmem_free(i40e->i40e_intr_handles, i40e->i40e_intr_size);
747 i40e->i40e_intr_handles = NULL;
748 }
749
750 static void
751 i40e_rem_intr_handlers(i40e_t *i40e)
752 {
753 int i, rc;
754
755 for (i = 0; i < i40e->i40e_intr_count; i++) {
756 rc = ddi_intr_remove_handler(i40e->i40e_intr_handles[i]);
757 if (rc != DDI_SUCCESS) {
758 i40e_log(i40e, "Can't remove intr_handler[%d]: %d",
759 i, rc);
760 }
761 }
762 }
763
764 static void
765 i40e_unconfigure(dev_info_t *devinfo, i40e_t *i40e)
766 {
767 int rc;
768
769 /*
770 * Disable interrupts (and ignore the return code since we're
771 * detaching.
772 */
773 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_ENABLE_INTR)
774 (void) i40e_disable_interrupts(i40e);
775
776 /* Remove the link check timer. */
777 if ((i40e->i40e_attach_progress & ATTACH_PROGRESS_LINK_TIMER) &&
778 i40e->i40e_periodic_id != 0) {
779 ddi_periodic_delete(i40e->i40e_periodic_id);
780 i40e->i40e_periodic_id = 0;
781 }
782
783 /* Unregister from GLDv3/mac. */
784 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_MAC) {
785 rc = mac_unregister(i40e->i40e_mac_hdl);
786 if (rc != 0)
787 i40e_error(i40e, "mac_unregister() failed: %d", rc);
788 }
789
790 /* Free statistics... */
791 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_STATS)
792 kstat_delete((kstat_t *)i40e->i40e_kstats);
793
794 /* if (i40e->i40e_attach_progress & ATTACH_PROGRESS_INIT)
795 ; */
796
797 /* Remove the taskqs. */
798 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_OVERTEMP_TASKQ)
799 ddi_taskq_destroy(i40e->i40e_overtemp_taskq);
800 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_SFP_TASKQ)
801 ddi_taskq_destroy(i40e->i40e_sfp_taskq);
802
803 /* XXX KEBE SAYS Remove the interrupt handlers. */
804 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_ADD_INTR)
805 i40e_rem_intr_handlers(i40e);
806
807 /* Remove the tx/rx qpairs and decommission the locks. */
808 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_ALLOC_RINGSLOCKS)
809 i40e_free_trqpairs_locks(i40e);
810
811 /* Remove interrupts and un-register interrupt callback handler. */
812 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_ALLOC_INTR)
813 i40e_rem_intrs(i40e);
814
815 /* Check for unregistering by checking for a NULL callback handle. */
816 if (i40e->i40e_callback_handle != NULL)
817 (void) ddi_cb_unregister(i40e->i40e_callback_handle);
818
819 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_COMMON_CODE)
820 i40e_common_code_fini(i40e);
821
822 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_PROPS)
823 (void) ddi_prop_remove_all(devinfo);
824
825 /*
826 * Free the register handle.
827 */
828 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_REGS_MAP &&
829 i40e->i40e_osdep_space.reg_handle != NULL) {
830 ddi_regs_map_free(&i40e->i40e_osdep_space.reg_handle);
831 }
832
833 /*
834 * Free PCI config handle
835 */
836 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_PCI_CONFIG &&
837 i40e->i40e_osdep_space.cfg_handle != NULL) {
838 pci_config_teardown(&i40e->i40e_osdep_space.cfg_handle);
839 }
840
841 /*
842 * Unregister FMA capabilities
843 */
844 if (i40e->i40e_attach_progress & ATTACH_PROGRESS_FM_INIT)
845 i40e_fm_fini(i40e);
846
847 /*
848 * Free the driver data structure
849 */
850 kmem_free(i40e, sizeof (i40e_t));
851
852 ddi_set_driver_private(devinfo, NULL);
853 }
854
855 /*
856 * quiesce(9E) entry point.
857 *
858 * This function is called when the system is single-threaded at high
859 * PIL with preemption disabled. Therefore, this function must not be
860 * blocked.
861 *
862 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
863 * DDI_FAILURE indicates an error condition and should almost never happen.
864 */
865 static int
866 i40e_quiesce(dev_info_t *devinfo)
867 {
868 return (DDI_FAILURE); /* For now. */
869 }
870
871 /*
872 * illumos Fault Management Architecture (FMA) support.
873 */
874
875 int
876 i40e_check_acc_handle(ddi_acc_handle_t handle)
877 {
878 ddi_fm_error_t de;
879
880 ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
881 ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
882 return (de.fme_status);
883 }
884
885 int
886 i40e_check_dma_handle(ddi_dma_handle_t handle)
887 {
888 ddi_fm_error_t de;
889
890 ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
891 return (de.fme_status);
892 }
893
894 /*
895 * Fault service error handling callback function.
896 */
897 static int
898 i40e_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
899 {
900 _NOTE(ARGUNUSED(impl_data));
901 /*
902 * as the driver can always deal with an error in any dma or
903 * access handle, we can just return the fme_status value.
904 */
905 pci_ereport_post(dip, err, NULL);
906 return (err->fme_status);
907 }
908
909 static void
910 i40e_fm_init(i40e_t *i40e)
911 {
912 ddi_iblock_cookie_t iblk;
913
914 /*
915 * Gather up capabilities. In ixgbe (this driver's inspiration) this
916 * was done in the caller. For i40e it's being encapsulated here.
917 * NOTE: We have a looper for most i40e.conf entries, but we need to
918 * do "fm_capable" early.
919 */
920 i40e->i40e_fm_capabilities = ddi_prop_get_int(DDI_DEV_T_ANY,
921 i40e->i40e_dip, DDI_PROP_DONTPASS, "fm_capable",
922 DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
923 DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
924
925 if (i40e->i40e_fm_capabilities < 0) {
926 i40e->i40e_fm_capabilities = 0;
927 } else if (i40e->i40e_fm_capabilities > 0xf) {
928 i40e->i40e_fm_capabilities = DDI_FM_EREPORT_CAPABLE |
929 DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE |
930 DDI_FM_ERRCB_CAPABLE;
931 }
932
933 /*
934 * Only register with IO Fault Services if we have some capability
935 */
936 if (i40e->i40e_fm_capabilities & DDI_FM_ACCCHK_CAPABLE) {
937 i40e_regs_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
938 } else {
939 i40e_regs_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
940 }
941
942 i40e_set_fma_flags(
943 (i40e->i40e_fm_capabilities & DDI_FM_DMACHK_CAPABLE) != 0);
944
945 if (i40e->i40e_fm_capabilities) {
946 /*
947 * Register capabilities with IO Fault Services
948 */
949 ddi_fm_init(i40e->i40e_dip, &i40e->i40e_fm_capabilities, &iblk);
950
951 /*
952 * Initialize pci ereport capabilities if ereport capable
953 */
954 if (DDI_FM_EREPORT_CAP(i40e->i40e_fm_capabilities) ||
955 DDI_FM_ERRCB_CAP(i40e->i40e_fm_capabilities)) {
956 pci_ereport_setup(i40e->i40e_dip);
957 }
958
959 /*
960 * Register error callback if error callback capable
961 */
962 if (DDI_FM_ERRCB_CAP(i40e->i40e_fm_capabilities)) {
963 ddi_fm_handler_register(i40e->i40e_dip,
964 i40e_fm_error_cb, (void*)i40e);
965 }
966 }
967 }
968
969 static void
970 i40e_fm_fini(i40e_t *i40e)
971 {
972 /*
973 * Only unregister FMA capabilities if they are registered
974 */
975 if (i40e->i40e_fm_capabilities) {
976
977 /*
978 * Release any resources allocated by pci_ereport_setup()
979 */
980 if (DDI_FM_EREPORT_CAP(i40e->i40e_fm_capabilities) ||
981 DDI_FM_ERRCB_CAP(i40e->i40e_fm_capabilities))
982 pci_ereport_teardown(i40e->i40e_dip);
983
984 /*
985 * Un-register error callback if error callback capable
986 */
987 if (DDI_FM_ERRCB_CAP(i40e->i40e_fm_capabilities))
988 ddi_fm_handler_unregister(i40e->i40e_dip);
989
990 /*
991 * Unregister from IO Fault Service
992 */
993 ddi_fm_fini(i40e->i40e_dip);
994 }
995 }
996
997 void
998 i40e_fm_ereport(i40e_t *i40e, char *detail)
999 {
1000 uint64_t ena;
1001 char buf[FM_MAX_CLASS];
1002
1003 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
1004 ena = fm_ena_generate(0, FM_ENA_FMT1);
1005 if (DDI_FM_EREPORT_CAP(i40e->i40e_fm_capabilities)) {
1006 ddi_fm_ereport_post(i40e->i40e_dip, buf, ena, DDI_NOSLEEP,
1007 FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
1008 }
1009 }
1010
1011 /*
1012 * Identify the chipset to which we're attaching, and make necessary records.
1013 * B_TRUE == success.
1014 */
1015 static boolean_t
1016 i40e_identify_hardware(i40e_t *i40e)
1017 {
1018 i40e_hw_t *hw = &i40e->i40e_hw_space;
1019 struct i40e_osdep *osdep = &i40e->i40e_osdep_space;
1020
1021 hw->vendor_id = pci_config_get16(osdep->cfg_handle, PCI_CONF_VENID);
1022 hw->device_id = pci_config_get16(osdep->cfg_handle, PCI_CONF_DEVID);
1023 hw->revision_id = pci_config_get8(osdep->cfg_handle, PCI_CONF_REVID);
1024 hw->subsystem_device_id =
1025 pci_config_get16(osdep->cfg_handle, PCI_CONF_SUBSYSID);
1026 hw->subsystem_vendor_id =
1027 pci_config_get16(osdep->cfg_handle, PCI_CONF_SUBVENID);
1028 /*
1029 * XXX KEBE SAYS FreeBSD sets bus.device with the slot, and bus.func
1030 * with "pci_get_function()". Do we need this in illumos?
1031 */
1032
1033 /* Call common code to set the MAC type for this adapter. */
1034 if (i40e_set_mac_type(hw) != I40E_SUCCESS)
1035 return (B_FALSE);
1036
1037 /*
1038 * Now that we have the MAC type, use it to inform our view of the
1039 * capabilities.
1040 */
1041 switch (hw->mac.type) {
1042 case I40E_MAC_XL710:
1043 /* XXX KEBE SAYS FILL ME IN!!! */
1044 /* XXX KEBE ASKS - do we need to do this? */
1045 i40e->i40e_capab = &i40e_XL710_cap;
1046 break;
1047 #ifdef X722_SUPPORT
1048 case I40E_MAC_X722:
1049 break;
1050 case I40E_MAC_X722_VF:
1051 #endif /* X722_SUPPORT */
1052 case I40E_MAC_VF:
1053 /* illumos does not support the _VF types. */
1054 i40e_error(i40e,
1055 "i40e_attach() to _VF configuration not supported.");
1056 return (B_FALSE);
1057 case I40E_MAC_GENERIC:
1058 /*
1059 * Unsure what to do with devices the Intel common code
1060 * doesn't know what to do with. Bail, for now.
1061 */
1062 i40e_error(i40e, "i40e doesn't support I40E_MAC_GENERIC.");
1063 return (B_FALSE);
1064 default:
1065 /* Should never reach here, but inform and fail anyway. */
1066 i40e_error(i40e, "Unknown i40e MAC type.");
1067 return (B_FALSE);
1068 }
1069
1070 return (B_TRUE);
1071 }
1072
1073 static boolean_t
1074 i40e_regs_map(i40e_t *i40e)
1075 {
1076 dev_info_t *devinfo = i40e->i40e_dip;
1077 i40e_hw_t *hw = &i40e->i40e_hw_space;
1078 struct i40e_osdep *osdep = &i40e->i40e_osdep_space;
1079 off_t memsize;
1080
1081 if (ddi_dev_regsize(devinfo, I40E_ADAPTER_REGSET, &memsize) !=
1082 DDI_SUCCESS) {
1083 return (B_FALSE);
1084 }
1085
1086 if (ddi_regs_map_setup(devinfo, I40E_ADAPTER_REGSET,
1087 (caddr_t *)&hw->hw_addr, 0, memsize, &i40e_regs_acc_attr,
1088 &osdep->reg_handle) != DDI_SUCCESS) {
1089 return (B_FALSE);
1090 }
1091
1092 return (B_TRUE);
1093 }
1094
1095 /*
1096 * Two parts of i40e_init_properties().
1097 */
1098
1099 /* Part 1 - read i40e.conf. */
1100 static void
1101 i40e_get_conf(i40e_t *i40e)
1102 {
1103 struct adapter_info *capab = i40e->i40e_capab;
1104 struct i40e_proplist {
1105 char *name; /* Property name. */
1106 int min; /* Property minimum value. */
1107 int max; /* Property maximum value. */
1108 int def; /* Property default value. */
1109 int offset; /* Offset into i40e_t for the value. */
1110 } props[] = {
1111 /*
1112 * Just add entries to this table for any integer value.
1113 * XXX KEBE ASKS - should I enforce uint_t instead?
1114 */
1115
1116 /* Default MTU size. */
1117 { "default_mtu", ETHERMIN, capab->max_mtu, capab->max_mtu,
1118 offsetof(i40e_t, i40e_default_mtu) },
1119
1120 /* Flow control... */
1121 { "flow_control", I40E_FC_NONE, I40E_FC_DEFAULT, I40E_FC_NONE,
1122 offsetof(i40e_t, i40e_hw_space) +
1123 offsetof(struct i40e_hw, fc) +
1124 offsetof(struct i40e_fc_info, requested_mode) },
1125
1126 /* Interrupt forcing. */
1127 { "intr_force", I40E_INTR_NONE, I40E_INTR_LEGACY,
1128 I40E_INTR_NONE, offsetof(i40e_t, i40e_intr_force) },
1129
1130 /*
1131 * HW ring enable/disable.
1132 * (Assume sizeof (boolean_t) == sizeof (uint_t).)
1133 */
1134 { "mr_enable", B_FALSE, B_TRUE, B_TRUE,
1135 offsetof(i40e_t, i40e_mr_enable) },
1136
1137 /* Number of transmit/receive queue pairs */
1138 /* XXX KEBE SAYS SET TO 2 for BRINGUP... */
1139 { "tx_rx_queue_pairs", 0, MAX_TX_RX_QUEUE_PAIRS,
1140 1, offsetof(i40e_t, i40e_num_trqpairs) },
1141
1142 /*
1143 * Various enables/disables.
1144 * Assume sizeof (boolean_t) == sizeof (uint_t).
1145 * XXX KEBE SAYS - some of these may/should become dladm(1M)
1146 * link properties.
1147 */
1148 { "tx_hcksum_enable", B_FALSE, B_TRUE, B_TRUE,
1149 offsetof(i40e_t, i40e_tx_hcksum_enable) },
1150 { "rx_hcksum_enable", B_FALSE, B_TRUE, B_TRUE,
1151 offsetof(i40e_t, i40e_rx_hcksum_enable) },
1152 /* XXX KEBE ASKS - lso_enable set to true by default?!? */
1153 { "lso_enable", B_FALSE, B_TRUE, B_TRUE,
1154 offsetof(i40e_t, i40e_lso_enable) },
1155 { "lro_enable", B_FALSE, B_TRUE, B_FALSE,
1156 offsetof(i40e_t, i40e_lro_enable) },
1157
1158 /* Must end with a NULL string... */
1159 { NULL, 0, 0, 0, 0}
1160 };
1161 int i, propval;
1162
1163 #define PTROF(i40e, offset) ((int *)((uint8_t *)(i40e) + (offset)))
1164 for (i = 0; props[i].name != NULL; i++) {
1165 struct i40e_proplist *pvp = &(props[i]);
1166
1167 propval = ddi_prop_get_int(DDI_DEV_T_ANY, i40e->i40e_dip,
1168 DDI_PROP_DONTPASS, pvp->name, pvp->def);
1169
1170 if (propval > pvp->max)
1171 propval = pvp->max;
1172
1173 if (propval < pvp->min)
1174 propval = pvp->min;
1175
1176 ASSERT(IS_P2ALIGNED(PTROF(i40e, pvp->offset), 4));
1177 *PTROF(i40e, pvp->offset) = propval;
1178 }
1179 #undef PTROF
1180
1181 /* Make additional decisions based on properties initialized above. */
1182
1183 if (!i40e->i40e_mr_enable) {
1184 i40e->i40e_num_trqpairs = 1;
1185 i40e->i40e_classify_mode = I40E_CLASSIFY_NONE;
1186 }
1187 /*
1188 * Else we'll have to do this later, after we grab things from the
1189 * hardware.
1190 */
1191
1192 /* Some reality checks. */
1193
1194 /* Can't do LRO unless you have receive HW checksum enabled. */
1195 i40e->i40e_lro_enable &= i40e->i40e_rx_hcksum_enable;
1196
1197 /* XXX KEBE SAYS FILL ME IN! */
1198 }
1199
1200 /* Part 2 - Set up other parameters in the i40 instance. */
1201 static void
1202 i40e_init_params(i40e_t *i40e)
1203 {
1204 /* XXX KEBE SAYS FILL ME IN! */
1205 /*
1206 * Wow, lots to fill in here. ixgbe has 100, 1000, 10000fdx stuff,
1207 * both enable, advertised, and "lp". We'll have to add 20000 and
1208 * 40000 to that as well, I believe.
1209 */
1210 }
1211
1212 /* Initialize driver properties... */
1213 static void
1214 i40e_init_properties(i40e_t *i40e)
1215 {
1216 /* Split into two parts for easier reading & organization. See above. */
1217 i40e_get_conf(i40e);
1218 i40e_init_params(i40e);
1219 }
1220
1221 /*
1222 * i40e_alloc_intr_handles - Allocate interrupt handles. Called further down
1223 * by the higher-level interrupt allocator: i40e_alloc_intrs().
1224 *
1225 * For legacy and MSI, only 1 handle is needed. For MSI-X, if fewer than 2
1226 * handles are available, return failure. Upon success, this maps the vectors
1227 * to rx and tx rings for interrupts.
1228 */
1229 static boolean_t
1230 i40e_alloc_intr_handles(i40e_t *i40e, dev_info_t *devinfo, int intr_type)
1231 {
1232 int request, count, actual, rc;
1233 /*
1234 * XXX KEBE ASKS --> should this even be here?
1235 * ixgbe sets this, but it's ALWAYS 1. Instead of cargo-culting, should
1236 * we be smarter and always assume minimum == 1?
1237 */
1238 int minimum = 1;
1239
1240 switch (intr_type) {
1241 case DDI_INTR_TYPE_FIXED:
1242 case DDI_INTR_TYPE_MSI:
1243 request = 1;
1244 break;
1245 case DDI_INTR_TYPE_MSIX:
1246 /*
1247 * XXX KEBE SAYS FILL ME IN, and consider best number
1248 * of vectors the way ixgbe considered it (or better).
1249 */
1250
1251 /* XXX KEBE SAYS CONSULT "hw" now! */
1252
1253 /*
1254 * KEBE SAYS Cap as a function of how many CPU cores are
1255 * available. Is this a preferred use of ncpus_online?
1256 * KEBE ASKS what happens when more/less go? Is that an
1257 * interrupt change event?
1258 */
1259 #if 0
1260 /* XXX KEBE ASKS two interrupts for each pair? Or just one? */
1261 request = min(ncpus_online, 2 * i40e->i40e_num_trqpairs + 1);
1262 if (request > i40e->i40e_capab->max_ring_vect)
1263 request = i40e->i40e_capab->max_ring_vect;
1264 #else
1265 /*
1266 * XXX KEBE SAYS BRINGUP TEST - just do two (adminq and one
1267 * trqpair).
1268 */
1269 ASSERT(i40e->i40e_num_trqpairs == 1);
1270 request = 2;
1271 #endif
1272 break;
1273 default:
1274 i40e_log(i40e,
1275 "Who called i40e_alloc_intr_handles() w/%d?", intr_type);
1276 return (B_FALSE);
1277 }
1278
1279 /* Counting on left->right evaluation and short-circuiting... */
1280 rc = ddi_intr_get_nintrs(devinfo, intr_type, &count);
1281 if (rc != DDI_SUCCESS || count < minimum) {
1282 i40e_log(i40e, "Get interrupt number failed, "
1283 "returned %d, count %d\n", rc, count);
1284 return (B_FALSE);
1285 }
1286
1287 rc = ddi_intr_get_navail(devinfo, intr_type, &count);
1288 if (rc != DDI_SUCCESS || count < minimum) {
1289 i40e_log(i40e, "Get AVAILABLE interrupt number failed, "
1290 "returned %d, count %d\n", rc, count);
1291 return (B_FALSE);
1292 }
1293
1294 actual = 0;
1295 i40e->i40e_intr_count = 0;
1296 i40e->i40e_intr_count_max = 0;
1297 i40e->i40e_intr_count_min = 0;
1298
1299 /* Actually allocate the array of interrupt handles. */
1300 i40e->i40e_intr_size = request * sizeof (ddi_intr_handle_t);
1301 i40e->i40e_intr_handles = kmem_alloc(i40e->i40e_intr_size, KM_SLEEP);
1302 /*
1303 * KM_SLEEP allocation is okay during attach() and during a
1304 * reallocation.
1305 */
1306
1307 rc = ddi_intr_alloc(devinfo, i40e->i40e_intr_handles, intr_type, 0,
1308 min(request, count), &actual, DDI_INTR_ALLOC_NORMAL);
1309 if (rc != DDI_SUCCESS) {
1310 i40e_log(i40e, "Interrupt allocation failed with %d.", rc);
1311 goto alloc_handle_fail;
1312 }
1313
1314 i40e->i40e_intr_count = actual;
1315 i40e->i40e_intr_count_max = request;
1316 i40e->i40e_intr_count_min = minimum;
1317
1318 /*
1319 * (re)adjust rss number per group & the rss ring count, depending
1320 * on how interrupt allocation went.
1321 */
1322 if (actual < i40e->i40e_num_trqpairs + 1) {
1323 /* Remember, we need one for the adminq. */
1324 i40e->i40e_num_trqpairs = (actual - 1) / 2;
1325 if (i40e->i40e_num_trqpairs == 1)
1326 i40e->i40e_classify_mode = I40E_CLASSIFY_NONE;
1327 else
1328 i40e->i40e_classify_mode = I40E_CLASSIFY_RSS;
1329 }
1330
1331 /* Time to map the number of interrupt vectors we have. */
1332 if (actual < minimum) {
1333 /* XXX KEBE SAYS See cargo-culting comment re: minimum above */
1334 i40e_log(i40e, "actual (%d) is less than minimum (%d).",
1335 actual, minimum);
1336 goto alloc_handle_fail;
1337 }
1338
1339 /*
1340 * Get & record priority and capabilities for first vector. Once
1341 * we have it, that's our priority until detach time. Even if we
1342 * get IRM requests (see i40e_intr_callback()), our priority won't
1343 * change.
1344 */
1345 rc = ddi_intr_get_pri(i40e->i40e_intr_handles[0], &i40e->i40e_intr_pri);
1346 if (rc != DDI_SUCCESS) {
1347 i40e_log(i40e,
1348 "Getting interrupt priority failed with %d.", rc);
1349 goto alloc_handle_fail;
1350 }
1351
1352 rc = ddi_intr_get_cap(i40e->i40e_intr_handles[0], &i40e->i40e_intr_cap);
1353 if (rc != DDI_SUCCESS) {
1354 i40e_log(i40e,
1355 "Getting interrupt capabilities failed with %d.", rc);
1356 goto alloc_handle_fail;
1357 }
1358
1359 /* Okay, we made it! */
1360 i40e->i40e_intr_type = intr_type;
1361 return (B_TRUE);
1362
1363 alloc_handle_fail:
1364
1365 i40e_rem_intrs(i40e);
1366 return (B_FALSE);
1367 }
1368
1369 /* Allocate the driver's interrupts. */
1370 static boolean_t
1371 i40e_alloc_intrs(i40e_t *i40e, dev_info_t *devinfo)
1372 {
1373 int intr_types, rc;
1374
1375 rc = ddi_intr_get_supported_types(devinfo, &intr_types);
1376 if (rc != DDI_SUCCESS) {
1377 i40e_log(i40e, "Get supported interrupt types failed: %d", rc);
1378 return (B_FALSE);
1379 }
1380
1381 i40e->i40e_intr_type = 0;
1382
1383 /* Try installing MSI-X interrupts first. */
1384 if ((intr_types & DDI_INTR_TYPE_MSIX) &&
1385 (i40e->i40e_intr_force <= I40E_INTR_MSIX)) {
1386 if (i40e_alloc_intr_handles(i40e, devinfo, DDI_INTR_TYPE_MSIX))
1387 return (B_TRUE);
1388 i40e_log(i40e, "Failed MSI-X attempt, trying MSI...");
1389 }
1390
1391 /*
1392 * If I reach here, I failed to allocate MSI-X interrupts.
1393 * Instead, force all rings & groups to 1, and first try MSI.
1394 */
1395 i40e->i40e_num_trqpairs = 1;
1396 i40e->i40e_classify_mode = I40E_CLASSIFY_NONE;
1397
1398 /* Actually attempt an MSI interrupt allocation. */
1399 if ((intr_types & DDI_INTR_TYPE_MSI) &&
1400 (i40e->i40e_intr_force <= I40E_INTR_MSI)) {
1401 if (i40e_alloc_intr_handles(i40e, devinfo, DDI_INTR_TYPE_MSI))
1402 return (B_TRUE);
1403
1404 i40e_log(i40e, "Failed MSI attempt, trying legacy...");
1405 }
1406
1407 /* And if I reach here, try a legacy interrupt allocation. */
1408 if (intr_types & DDI_INTR_TYPE_FIXED) {
1409 if (i40e_alloc_intr_handles(i40e, devinfo, DDI_INTR_TYPE_FIXED))
1410 return (B_TRUE);
1411
1412 i40e_log(i40e, "Failed Legacy attempt. Giving up.");
1413 }
1414
1415 /* If I reach here, none of the interrupt allocations succeeded. */
1416 return (B_FALSE);
1417 }
1418
1419 /* ARGSUSED */
1420 static int
1421 i40e_intr_callback(dev_info_t *dip, ddi_cb_action_t cbaction, void *cbarg,
1422 void *arg, void *unused)
1423 {
1424 i40e_t *i40e = (i40e_t *)arg;
1425 /* int count = (int)(uintptr_t)cbarg; */
1426
1427 VERIFY(i40e->i40e_dip == dip); /* XXX KEBE SAYS change to ASSERT(). */
1428
1429 switch (cbaction) {
1430 case DDI_CB_INTR_ADD:
1431 case DDI_CB_INTR_REMOVE:
1432 /* Interrupt Resource Management (IRM) requests. */
1433 /* XXX KEBE SAYS FILL ME IN WITH ADJUSTMENT CODE! */
1434 /* XXX KEBE SAYS that'll use "count" above. */
1435 break;
1436 default:
1437 /* Don't know this cbaction. */
1438 return (DDI_ENOTSUP);
1439 }
1440
1441 /* If I make it here, I'm good! */
1442 return (DDI_SUCCESS);
1443 }
1444
1445 /*
1446 * Free receive & transmit rings.
1447 */
1448 static void
1449 i40e_free_trqpairs_locks(i40e_t *i40e)
1450 {
1451 int i;
1452 i40e_trqpair_t *itrq;
1453
1454 if (i40e->i40e_trqpairs != NULL) {
1455 itrq = &i40e->i40e_trqpairs[0];
1456 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
1457 mutex_destroy(&itrq->itrq_rx_lock);
1458 mutex_destroy(&itrq->itrq_tx_lock);
1459 /* XXX KEBE SAYS more mutexes and other frees... */
1460 itrq++;
1461 }
1462
1463 kmem_free(i40e->i40e_trqpairs,
1464 sizeof (i40e_trqpair_t) * i40e->i40e_num_trqpairs);
1465 i40e->i40e_trqpairs = NULL;
1466 }
1467
1468 mutex_destroy(&i40e->i40e_general_lock);
1469 /* mutex_destroy(&i40e->i40e_watchdog_lock); */
1470 }
1471
1472 /*
1473 * Allocate receive & transmit rings.
1474 */
1475 static boolean_t
1476 i40e_alloc_trqpairs_locks(i40e_t *i40e)
1477 {
1478 int i;
1479 void *mutexpri = DDI_INTR_PRI(i40e->i40e_intr_pri);
1480 i40e_trqpair_t *itrq;
1481
1482 /*
1483 * Now that we have the priority for the interrupts, initialize
1484 * all relevant locks.
1485 */
1486 mutex_init(&i40e->i40e_general_lock, NULL, MUTEX_DRIVER, mutexpri);
1487 /*
1488 * mutex_init(&i40e->i40e_watchdog_lock, NULL, MUTEX_DRIVER, mutexpri);
1489 */
1490
1491 /*
1492 * Can call with KM_SLEEP because we're attach()-ing.
1493 * If in some future we can't, call instead with NOSLEEP and return
1494 * B_FALSE after any allocations failures & cleanups.
1495 */
1496 i40e->i40e_trqpairs = kmem_zalloc(
1497 sizeof (i40e_trqpair_t) * i40e->i40e_num_trqpairs, KM_SLEEP);
1498 itrq = &(i40e->i40e_trqpairs[0]);
1499 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
1500 itrq->itrq_i40e = i40e;
1501 mutex_init(&itrq->itrq_rx_lock, NULL, MUTEX_DRIVER, mutexpri);
1502 mutex_init(&itrq->itrq_tx_lock, NULL, MUTEX_DRIVER, mutexpri);
1503 itrq->itrq_index = i;
1504 /* XXX KEBE SAYS more mutexes and other allocs... */
1505 itrq++;
1506 }
1507
1508 return (B_TRUE);
1509 }
1510
1511 /*
1512 * ixgbe_map_rxring_to_vector - Map given rx ring to given interrupt vector.
1513 */
1514 static inline void
1515 i40e_map_rx_to_vector(i40e_t *i40e, int qp_idx, int v_idx)
1516 {
1517 /*
1518 * Set bit in map
1519 */
1520 BT_SET(i40e->i40e_vector_map[v_idx].iv_rx_map, qp_idx);
1521
1522 /*
1523 * Count bits set
1524 */
1525 i40e->i40e_vector_map[v_idx].iv_rx_count++;
1526
1527 /*
1528 * Remember bit position
1529 */
1530 i40e->i40e_trqpairs[qp_idx].itrq_rx_intrvec = v_idx;
1531 i40e->i40e_trqpairs[qp_idx].itrq_rx_vectorbit = 1 << v_idx;
1532 }
1533
1534 static inline void
1535 i40e_map_tx_to_vector(i40e_t *i40e, int qp_idx, int v_idx)
1536 {
1537 /*
1538 * Set bit in map
1539 */
1540 BT_SET(i40e->i40e_vector_map[v_idx].iv_tx_map, qp_idx);
1541
1542 /*
1543 * Count bits set
1544 */
1545 i40e->i40e_vector_map[v_idx].iv_tx_count++;
1546
1547 /*
1548 * Remember bit position
1549 */
1550 i40e->i40e_trqpairs[qp_idx].itrq_tx_intrvec = v_idx;
1551 i40e->i40e_trqpairs[qp_idx].itrq_tx_vectorbit = 1 << v_idx;
1552 }
1553
1554 /*
1555 * Map different interrupts to MSI-X vectors.
1556 */
1557 static boolean_t
1558 i40e_map_intrs_to_vectors(i40e_t *i40e)
1559 {
1560 int i, vectornum;
1561
1562 bzero(&i40e->i40e_vector_map, sizeof (i40e->i40e_vector_map));
1563
1564 if (i40e->i40e_intr_type != DDI_INTR_TYPE_MSIX) {
1565 /*
1566 * We have adminq, plus rx & tx to concern ourselves with.
1567 * XXX KEBE SAYS FIGURE THAT OUT.
1568 */
1569 i40e_error(i40e, "Can't support MSI or LEGACY yet.");
1570 return (B_FALSE); /* For now, bail. */
1571 }
1572
1573 /*
1574 * We should have an odd number of MSI-X interrupts. 0 is for the
1575 * adminq, and...
1576 *
1577 * XXXX 1-N is for N/2 qpairs, where rx & tx get their own
1578 * interrupts. XXXX
1579 *
1580 * XXX KEBE ASKS (and maybe BRINGUP) - do rx & tx actually get
1581 * their own interrupts?!? RIght now, they share.
1582 */
1583
1584 /* The adminq. */
1585 BT_SET(i40e->i40e_vector_map[0].iv_other_map, 0);
1586 i40e->i40e_vector_map[0].iv_other_count++;
1587
1588 vectornum = 1;
1589 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
1590 /* Map tx & rx qpairs to the same interrupt vector for now. */
1591 i40e_map_tx_to_vector(i40e, i, vectornum);
1592 i40e_map_rx_to_vector(i40e, i, vectornum);
1593 vectornum = (vectornum + 1) % i40e->i40e_intr_count;
1594 if (vectornum == 0)
1595 vectornum++; /* Skip 0, that's for adminq only. */
1596 }
1597
1598 return (B_TRUE);
1599 }
1600
1601 /*
1602 * Add appropriate interrupt handlers based on the interrupt type.
1603 * Caller must have added rx/tx rings and interrupt vectors to "i40e" prior
1604 * to calling here.
1605 *
1606 * Interrupt handlers are in their own file: i40e_intr.c.
1607 */
1608 static boolean_t
1609 i40e_add_intr_handlers(i40e_t *i40e)
1610 {
1611 int rc, vector;
1612
1613 switch (i40e->i40e_intr_type) {
1614 case DDI_INTR_TYPE_MSIX:
1615 for (vector = 0; vector < i40e->i40e_intr_count; vector++) {
1616 rc = ddi_intr_add_handler(
1617 i40e->i40e_intr_handles[vector],
1618 (ddi_intr_handler_t *)i40e_intr_msix, i40e,
1619 (void *)(uintptr_t)vector);
1620 if (rc != DDI_SUCCESS) {
1621 i40e_log(i40e, "Add interrupt handler (MSI-X) "
1622 "failed: return %d, vector %d", rc, vector);
1623 for (vector--; vector >= 0; vector--) {
1624 (void) ddi_intr_remove_handler(
1625 i40e->i40e_intr_handles[vector]);
1626 }
1627 return (B_FALSE);
1628 }
1629 }
1630 break;
1631 case DDI_INTR_TYPE_MSI:
1632 rc = ddi_intr_add_handler(i40e->i40e_intr_handles[0],
1633 (ddi_intr_handler_t *)i40e_intr_msi, i40e, NULL);
1634 if (rc != DDI_SUCCESS) {
1635 i40e_log(i40e, "Add interrupt handler (MSI) failed: "
1636 "return %d", rc);
1637 return (B_FALSE);
1638 }
1639 break;
1640 case DDI_INTR_TYPE_FIXED:
1641 rc = ddi_intr_add_handler(i40e->i40e_intr_handles[0],
1642 (ddi_intr_handler_t *)i40e_intr_legacy, i40e, NULL);
1643 if (rc != DDI_SUCCESS) {
1644 i40e_log(i40e, "Add interrupt handler (legacy) failed:"
1645 " return %d", rc);
1646 return (B_FALSE);
1647 }
1648 break;
1649 default:
1650 i40e_error(i40e,
1651 "i40e_add_intr_handlers() called where intr_type is %d.",
1652 i40e->i40e_intr_type);
1653 return (B_FALSE);
1654 }
1655
1656 return (B_TRUE);
1657 }
1658
1659 static boolean_t
1660 i40e_enable_interrupts(i40e_t *i40e)
1661 {
1662 int i, rc;
1663
1664 if (i40e->i40e_intr_cap & DDI_INTR_FLAG_BLOCK) {
1665 /* MSI/MSI-X block-enable */
1666 rc = ddi_intr_block_enable(i40e->i40e_intr_handles,
1667 i40e->i40e_intr_count);
1668 if (rc != DDI_SUCCESS) {
1669 i40e_error(i40e, "interrupts block-enable failed: %d",
1670 rc);
1671 return (B_FALSE);
1672 }
1673 } else {
1674 for (i = 0; i < i40e->i40e_intr_count; i++) {
1675 rc = ddi_intr_enable(i40e->i40e_intr_handles[i]);
1676 if (rc != DDI_SUCCESS) {
1677 i40e_error(i40e,
1678 "Enable interrupt %d failed: %d", i, rc);
1679 /* Just Disable It (TM) for the earlier ones. */
1680 while (--i >= 0) {
1681 (void) ddi_intr_disable(
1682 i40e->i40e_intr_handles[i]);
1683 }
1684 return (B_FALSE);
1685 }
1686 }
1687 }
1688
1689 return (B_TRUE);
1690 }
1691
1692 static boolean_t
1693 i40e_disable_interrupts(i40e_t *i40e)
1694 {
1695 int i, rc;
1696
1697 if (i40e->i40e_intr_cap & DDI_INTR_FLAG_BLOCK) {
1698 rc = ddi_intr_block_disable(i40e->i40e_intr_handles,
1699 i40e->i40e_intr_count);
1700 if (rc != DDI_SUCCESS) {
1701 i40e_error(i40e,
1702 "interrupts block-disabled failed: %d", rc);
1703 return (B_FALSE);
1704
1705 }
1706 } else {
1707 for (i = 0; i < i40e->i40e_intr_count; i++) {
1708 rc = ddi_intr_disable(i40e->i40e_intr_handles[i]);
1709 if (rc != DDI_SUCCESS) {
1710 i40e_error(i40e,
1711 "Disable interrupts %d failed: %d", i, rc);
1712 return (B_FALSE);
1713 }
1714 }
1715 }
1716
1717 return (B_TRUE);
1718 }
1719
1720 /*
1721 * Timer functions.
1722 */
1723 static void
1724 i40e_timer(void *arg)
1725 {
1726 i40e_t *i40e = arg;
1727
1728 mutex_enter(&i40e->i40e_general_lock);
1729 /* XXX KEBE SAYS FILL ME IN XXX */
1730 /*
1731 * A generic link-check function (that can be called elsewhere) is in
1732 * order.
1733 */
1734 mutex_exit(&i40e->i40e_general_lock);
1735
1736 if ((i40e->i40e_state & I40E_WATCHDOG) == 0)
1737 return;
1738
1739 /* Perform watchdog bits while not holding i40e_general_lock. */
1740 /*
1741 * Check state for OVERTEMP or ERROR. Attempt reset on ERROR.
1742 * If reset succeeds, service-impact with DDI_SERVICE_RESTORED.
1743 */
1744 /* Perform a stall check, degrade if need be. */
1745 }
1746
1747 /*
1748 * Watchdog timer functions.
1749 */
1750 void
1751 i40e_disable_watchdog_timer(i40e_t *i40e)
1752 {
1753 /*
1754 * NOP for now -> disable a bit in i40e to inform the periodic timer
1755 * NOT to do watchdog things.
1756 */
1757 }
1758
1759 void
1760 i40e_enable_watchdog_timer(i40e_t *i40e)
1761 {
1762 /*
1763 * NOP for now -> enable a bit in i40e to let the periodic timer
1764 * do watchdog things.
1765 */
1766 }
1767
1768 /*
1769 * Get the hardware state, and scribble away anything that needs scribbling.
1770 */
1771 static void
1772 i40e_get_hw_state(i40e_t *i40e, i40e_hw_t *hw)
1773 {
1774 int rc;
1775 struct i40e_aq_get_phy_abilities_resp abilities;
1776
1777 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
1778
1779 i40e_aq_get_link_info(hw, TRUE, NULL, NULL);
1780 i40e_get_link_status(hw, (bool *)&i40e->i40e_link_state);
1781
1782 rc = i40e_aq_get_phy_capabilities(hw, B_FALSE, B_TRUE, &abilities,
1783 NULL);
1784 /* Intel or FreeBSD say we may need delay to detect fiber correctly */
1785 if (rc == I40E_ERR_UNKNOWN_PHY) {
1786 i40e_msec_delay(200);
1787 rc = i40e_aq_get_phy_capabilities(hw, B_FALSE, B_TRUE,
1788 &abilities, NULL);
1789 }
1790
1791 if (rc != I40E_SUCCESS) {
1792 i40e_error(i40e, "Get physical capabilities failed: %d", rc);
1793 /* XXX KEBE ASKS FM faulty? */
1794 }
1795
1796 rc = i40e_update_link_info(hw);
1797 if (rc != I40E_SUCCESS) {
1798 i40e_error(i40e, "Update link info failed: %d", rc);
1799 /* XXX KEBE ASKS FM faulty? */
1800 }
1801
1802 /* Limit phy interrupts to link and modules failure */
1803 rc = i40e_aq_set_phy_int_mask(hw,
1804 I40E_AQ_EVENT_LINK_UPDOWN | I40E_AQ_EVENT_MODULE_QUAL_FAIL, NULL);
1805 if (rc != I40E_SUCCESS) {
1806 /* XXX KEBE ASKS FMA? */
1807 i40e_error(i40e, "set phy mask failed: %d\n", rc);
1808 }
1809 }
1810
1811 /*
1812 * Used at re-init time, AND by the GLD addmac/remmac code.
1813 */
1814 boolean_t
1815 i40e_hwadd_mac(i40e_t *i40e, i40e_hw_t *hw, const uint8_t *mac_addr)
1816 {
1817 uint8_t buffer[I40E_AQ_LARGE_BUF];
1818 struct i40e_aqc_add_macvlan_element_data *mvlist =
1819 (struct i40e_aqc_add_macvlan_element_data *)buffer;
1820
1821 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
1822
1823 bcopy(mac_addr, mvlist->mac_addr, ETHERADDRL);
1824 mvlist->vlan_tag = 0; /* No VLAN... we do that some other way... */
1825 mvlist->flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH |
1826 I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
1827 /* Be conservative in what you send... */
1828 mvlist->queue_number = 0;
1829 return (i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, mvlist, 1, NULL) ==
1830 I40E_SUCCESS);
1831 }
1832
1833 /*
1834 * Initialize or reset the unicast addresses for our (currently just one) VSI.
1835 */
1836 static void
1837 i40e_init_macaddrs(i40e_t *i40e, i40e_hw_t *hw)
1838 {
1839 int i;
1840 i40e_ether_addr_t *i40eth, *lastone;
1841
1842 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
1843
1844 if (i40e->i40e_mac_total > 0) {
1845 /*
1846 * We are up and running already, and just need to kick things
1847 * in the pants again.
1848 */
1849 /* NOTE: Skip slot 1 as it's the board's MAC address... */
1850 for (i = 1; i < i40e->i40e_mac_used; i++) {
1851 i40eth = &(i40e->i40e_mac_addrs[i]);
1852 if (!i40e_hwadd_mac(i40e, hw, i40eth->i40eth_mac)) {
1853 /*
1854 * Oh shoot, we failed on reset. Warn loudly,
1855 * and drop ones we can't initialize.
1856 * Do a swap of the last one to this slot,
1857 * so we can continue. Or if we're the last
1858 * slot, do nothing.
1859 *
1860 * Either way, the last slot is emptied, and
1861 * the number of unicast MACs used drops by 1.
1862 */
1863 i40e_notice(i40e, "WARNING: <fill me in>");
1864 lastone = &(i40e->i40e_mac_addrs[
1865 i40e->i40e_mac_used - 1]);
1866 if (lastone != i40eth) {
1867 /* Do the swap if we have more... */
1868 *i40eth = *lastone;
1869 lastone->i40eth_used = 0;
1870 i--;
1871 } else {
1872 /*
1873 * ... or if we're the last one,
1874 * simply mark this as unused.
1875 */
1876 i40eth->i40eth_used = 0;
1877 }
1878 i40e->i40e_mac_used--;
1879 }
1880 }
1881 return;
1882 }
1883
1884 /*
1885 * Actually initialize things.
1886 */
1887 i40e->i40e_mac_total = I40E_MAX_MAC;
1888
1889 /*
1890 * XXX KEBE WARNS...
1891 *
1892 * If there's a way to query the HW for what's left, we'll need to
1893 * do that dynamically. For now, just cap at I40E_MAX_UNICAST.
1894 * See its definition for whole-board vs. per-port/PF problems.
1895 */
1896 #if 0
1897 /*
1898 * Put the board's ethernet address in for slot #0.
1899 */
1900 i40e->i40e_mac_used = 1;
1901 i40e->i40e_mac_addrs[0].i40eth_used = 1;
1902 /* I hope this is where the port's/board's/PF's MAC address is... */
1903 bcopy(hw->mac.addr, i40e->i40e_mac_addrs[0].i40eth_mac, ETHERADDRL);
1904 #endif
1905 }
1906
1907 /*
1908 * Configure the hardware for the Virtual Station Interface (VSI). Currently
1909 * we only support one, but in the future we could instantiate more than one
1910 * per attach-point.
1911 */
1912 static boolean_t
1913 i40e_config_vsi(i40e_t *i40e, i40e_hw_t *hw)
1914 {
1915 /* Let's hope C99's initializers do the right thing. */
1916 struct i40e_vsi_context context = {0};
1917 int err;
1918
1919 context.seid = i40e->i40e_vsi_id;
1920 context.pf_num = hw->pf_id;
1921 err = i40e_aq_get_vsi_params(hw, &context, NULL);
1922 if (err != I40E_SUCCESS) {
1923 i40e_error(i40e, "get VSI params failed with %d\n", err);
1924 return (B_FALSE);
1925 }
1926
1927 /*
1928 * Set the queue and traffic class bits. Keep it simple for now.
1929 */
1930 context.info.valid_sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
1931 context.info.mapping_flags |= I40E_AQ_VSI_QUE_MAP_CONTIG;
1932 context.info.queue_mapping[0] = 0;
1933 context.info.tc_mapping[0] = 0x0800;
1934
1935 #if 0 /* XXX KEBE IS Not sure about this... I thought mac did this. */
1936 /* Set VLAN receive stripping mode */
1937 context.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID;
1938 context.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL;
1939 if (<some-nemo-thing>)
1940 context.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_STR_BOTH;
1941 else
1942 context.info.port_vlan_flags |= I40E_AQ_VSI_PVLAN_EMOD_NOTHING;
1943 #else
1944 /* XXX KEBE SAYS he's more sure about these... */
1945 context.info.valid_sections |= I40E_AQ_VSI_PROP_VLAN_VALID;
1946 context.info.port_vlan_flags = I40E_AQ_VSI_PVLAN_MODE_ALL |
1947 I40E_AQ_VSI_PVLAN_EMOD_NOTHING;
1948 #endif
1949 context.flags = LE_16(I40E_AQ_VSI_TYPE_PF);
1950 err = i40e_aq_update_vsi_params(hw, &context, NULL);
1951 if (err != I40E_SUCCESS) {
1952 i40e_error(i40e, "Update VSI params failed with %d", err);
1953 return (B_FALSE);
1954 }
1955
1956 /*
1957 * XXX KEBE SAYS Iterate through the trqpairs, setting up pointers
1958 * to DMA memory.
1959 */
1960 /* XXX KEBE SAYS CHECKPOINT --> GET BACK TO ME */
1961
1962 return (B_TRUE);
1963 }
1964
1965 /*
1966 * Wrapper to kick the chipset on.
1967 */
1968 static boolean_t
1969 i40e_chip_start(i40e_t *i40e)
1970 {
1971 i40e_hw_t *hw = &i40e->i40e_hw_space;
1972 /* Let's hope C99-initializing does the right thing. */
1973 struct i40e_filter_control_settings filter = {0};
1974 int i, rc;
1975
1976 if (((hw->aq.fw_maj_ver == 4) && (hw->aq.fw_min_ver < 33)) ||
1977 (hw->aq.fw_maj_ver < 4)) {
1978 i40e_msec_delay(75);
1979 if (i40e_aq_set_link_restart_an(hw, TRUE, NULL) !=
1980 I40E_SUCCESS) {
1981 i40e_error(i40e, "link restart failed, aq_err=%d\n",
1982 hw->aq.asq_last_status);
1983 /* XXX KEBE ASKS FMA? */
1984 return (B_FALSE);
1985 }
1986 }
1987
1988 /* Determine hardware state */
1989 i40e_get_hw_state(i40e, hw);
1990
1991 /* Initialize mac addresses. */
1992 i40e_init_macaddrs(i40e, hw);
1993
1994 /*
1995 * Set up the filter control.
1996 */
1997 filter.enable_ethtype = TRUE;
1998 filter.enable_macvlan = TRUE;
1999
2000 rc = i40e_set_filter_control(hw, &filter);
2001 if (rc != I40E_SUCCESS) {
2002 i40e_error(i40e, "i40e_set_filter_control() returned %d", rc);
2003 return (B_FALSE);
2004 }
2005
2006 #if 0
2007 /*
2008 * XXX KEBE SAYS for BRINGUP, skip this, but configure the RSS
2009 * parameters. See FreeBSD's ixl_config_rss().
2010 */
2011 if (!i40e_config_rss(i40e, hw))
2012 return (B_FALSE);
2013 #endif
2014
2015 /*
2016 * XXX KEBE SAYS FILL IN vsi information, some of which can be pushed
2017 * down to the trqpairs below, except if/when we become multi-VSI
2018 * aware. See ixl_initialize_vsi().
2019 */
2020 if (!i40e_config_vsi(i40e, hw))
2021 return (B_FALSE);
2022
2023 /* Add the ethernet broadcast address to the HW filter list. */
2024 if (!i40e_hwadd_mac(i40e, hw, i40e_ether_broadcast))
2025 return (B_FALSE);
2026
2027 /*
2028 * Each interrupt vector needs to be explicitly enabled.
2029 * NOTE: Vector 0 is admin-queue/CTL0, rest are CTLN.
2030 */
2031
2032 /* First, the adminq. */
2033
2034 wr32(hw, I40E_PFINT_DYN_CTL0,
2035 I40E_PFINT_DYN_CTL0_INTENA_MASK |
2036 I40E_PFINT_DYN_CTL0_CLEARPBA_MASK |
2037 (I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT));
2038 i40e_flush(hw);
2039 /*
2040 * SO MUCH TO FILL IN!
2041 * - ICR0_ENA disable
2042 * - ICR0 read-to-clear
2043 * - ITR for adminq (set to I40E_ITR_8K)
2044 * - XXX KEBE ASKS more?
2045 */
2046
2047 /* Then the others. */
2048 /* XXX KEBE ASKS -- use vector number instead?!? */
2049 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
2050 /*
2051 * SO MUCH TO FILL IN!
2052 * - ITR state
2053 * - DYN_CTLN(i)
2054 * - LNKLSTN(i)
2055 * - QINT_[TR]QCTL(i)
2056 * - Various rx/tx bits relating to things we set here.
2057 */
2058
2059 wr32(hw, I40E_PFINT_DYN_CTLN(i),
2060 I40E_PFINT_DYN_CTLN_INTENA_MASK |
2061 I40E_PFINT_DYN_CTLN_CLEARPBA_MASK |
2062 (I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT));
2063 }
2064 i40e_flush(hw); /* XXX FreeBSD doesn't do this... */
2065
2066 return (B_TRUE);
2067 }
2068
2069 void
2070 i40e_chip_stop(i40e_t *i40e)
2071 {
2072 i40e_hw_t *hw = &i40e->i40e_hw_space;
2073 int i;
2074
2075 /* XXX KEBE SAYS FILL ME IN XXX */
2076 /*
2077 * Each interrupt vector needs to be explicitly disabled.
2078 * NOTE: Vector 0 is admin-queue/CTL0, rest are CTLN.
2079 */
2080
2081 /* First, the adminq. */
2082 wr32(hw, I40E_PFINT_DYN_CTL0,
2083 I40E_ITR_NONE << I40E_PFINT_DYN_CTL0_ITR_INDX_SHIFT);
2084 /* XXX KEBE ASKS - flush? */
2085
2086 /* Then the others. */
2087 /* XXX KEBE ASKS -- use vector number instead?!? */
2088 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
2089 wr32(hw, I40E_PFINT_DYN_CTLN(i),
2090 I40E_ITR_NONE << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT);
2091 }
2092 /* XXX KEBE ASKS - flush? */
2093 }
2094
2095 /*
2096 * Actually stop the chipset. This also includes various buffer frees.
2097 */
2098 void
2099 i40e_stop(i40e_t *i40e, boolean_t free_allocations)
2100 {
2101 int i;
2102
2103 /* XXX KEBE SAYS FILL ME IN! */
2104 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
2105
2106 /* XXX KEBE SAYS Disable all of the interrupts. */
2107
2108 /* XXX KEBE SAYS drain any pending tx packets. */
2109
2110 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
2111 mutex_enter(&i40e->i40e_trqpairs[i].itrq_rx_lock);
2112 mutex_enter(&i40e->i40e_trqpairs[i].itrq_tx_lock);
2113 }
2114
2115 i40e_chip_stop(i40e);
2116
2117 /* XXX KEBE SAYS Clean pending tx resources. */
2118
2119 for (i = i40e->i40e_num_trqpairs - 1; i >= 0; i--) {
2120 mutex_exit(&i40e->i40e_trqpairs[i].itrq_tx_lock);
2121 mutex_exit(&i40e->i40e_trqpairs[i].itrq_rx_lock);
2122 }
2123
2124 if (i40e->i40e_link_state == LINK_STATE_UP) {
2125 i40e->i40e_link_state = LINK_STATE_UNKNOWN;
2126 mac_link_update(i40e->i40e_mac_hdl, i40e->i40e_link_state);
2127 }
2128
2129 if (free_allocations) {
2130 i40e_free_dma(i40e);
2131 i40e_free_rx_data(i40e);
2132 }
2133 }
2134
2135 /*
2136 * Return -1 on failure, let caller deal with it.
2137 */
2138 static int
2139 i40e_get_vsi_id(i40e_t *i40e)
2140 {
2141 i40e_hw_t *hw = &i40e->i40e_hw_space;
2142 struct i40e_aqc_get_switch_config_resp *sw_config;
2143 uint8_t aq_buf[I40E_AQ_LARGE_BUF];
2144 uint16_t next; /* Needed for common-code call. */
2145 int rc;
2146
2147 sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
2148 rc = i40e_aq_get_switch_config(hw, sw_config, sizeof(aq_buf), &next,
2149 NULL);
2150 if (rc != I40E_SUCCESS) {
2151 i40e_error(i40e, "i40e_aq_get_switch_config() failed %d\n", rc);
2152 return (-1);
2153 }
2154
2155 /*
2156 * XXX KEBE SAYS - there may be other elements we need later,
2157 * but for now, we just want the basic seid.
2158 */
2159 return (sw_config->element[0].seid);
2160 }
2161
2162 /*
2163 * Actually start the chipset. This also includes various buffer allocations.
2164 */
2165 boolean_t
2166 i40e_start(i40e_t *i40e, boolean_t alloc)
2167 {
2168 boolean_t rc = B_TRUE;
2169 int i;
2170
2171 /* XXX KEBE SAYS FILL ME IN! */
2172 ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
2173
2174 if (alloc) {
2175 if (!i40e_alloc_rx_data(i40e)) {
2176 i40e_error(i40e,
2177 "Failed to allocate receive-ring data");
2178 return (B_FALSE);
2179 }
2180 if (!i40e_alloc_dma(i40e)) {
2181 i40e_error(i40e, "Failed to allocate DMA data");
2182 return (B_FALSE);
2183 }
2184 }
2185
2186 /* Big batch of mutex enters to block things... */
2187 for (i = 0; i < i40e->i40e_num_trqpairs; i++) {
2188 mutex_enter(&i40e->i40e_trqpairs[i].itrq_rx_lock);
2189 mutex_enter(&i40e->i40e_trqpairs[i].itrq_tx_lock);
2190 }
2191
2192
2193 /*
2194 * XXX KEBE SAYS ixgbe calls chip_start() here. Did we do that
2195 * already?
2196 */
2197 if (!i40e_chip_start(i40e)) {
2198 i40e_fm_ereport(i40e, DDI_FM_DEVICE_INVAL_STATE);
2199 rc = B_FALSE;
2200 goto done;
2201 }
2202
2203 if (i40e_check_acc_handle(i40e->i40e_osdep_space.reg_handle) !=
2204 DDI_FM_OK) {
2205 rc = B_FALSE;
2206 goto done;
2207 }
2208
2209 /* XXX KEBE SAYS set up the rx/tx rings (including rx/tx buffers?) */
2210
2211 /* Clear state bits prior to final interrupt enabling. */
2212 atomic_and_32(&i40e->i40e_state,
2213 ~(I40E_ERROR | I40E_STALL | I40E_OVERTEMP));
2214
2215 /* XXX KEBE SAYS enable the interrupts here (really?)! */
2216
2217 done:
2218 for (i = i40e->i40e_num_trqpairs - 1; i >= 0; i--) {
2219 mutex_exit(&i40e->i40e_trqpairs[i].itrq_tx_lock);
2220 mutex_exit(&i40e->i40e_trqpairs[i].itrq_rx_lock);
2221 }
2222 if (!rc)
2223 ddi_fm_service_impact(i40e->i40e_dip, DDI_SERVICE_LOST);
2224
2225 return (rc);
2226 }
2227
2228 /*
2229 * Module Initialization Functions.
2230 */
2231 int
2232 _init(void)
2233 {
2234 int status;
2235
2236 mac_init_ops(&i40e_dev_ops, MODULE_NAME);
2237
2238 status = mod_install(&i40e_modlinkage);
2239
2240 if (status != DDI_SUCCESS) {
2241 mac_fini_ops(&i40e_dev_ops);
2242 }
2243
2244 return (status);
2245 }
2246
2247 int
2248 _fini(void)
2249 {
2250 int status;
2251
2252 status = mod_remove(&i40e_modlinkage);
2253
2254 if (status == DDI_SUCCESS) {
2255 mac_fini_ops(&i40e_dev_ops);
2256 }
2257
2258 return (status);
2259 }
2260
2261 int
2262 _info(struct modinfo *modinfop)
2263 {
2264 int status;
2265
2266 status = mod_info(&i40e_modlinkage, modinfop);
2267
2268 return (status);
2269 }