1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008-2013 Solarflare Communications Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
30 #include <sys/modctl.h>
31 #include <sys/conf.h>
32 #include <sys/ethernet.h>
33 #include <sys/pci.h>
34 #include <sys/stream.h>
35 #include <sys/strsun.h>
36 #include <sys/processor.h>
37 #include <sys/cpuvar.h>
38 #include <sys/pghw.h>
39
40 #include "version.h"
41
42 #include "sfxge.h"
43 #include "efsys.h"
44 #include "efx.h"
45
46 #ifdef DEBUG
47 boolean_t sfxge_aask = B_FALSE;
48 #endif
49
50 /* Receive queue TRIM default polling interval (in microseconds) */
51 #define SFXGE_RX_QPOLL_USEC (5000000)
52
53 /* Broadcast address */
54 uint8_t sfxge_brdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
55
56 /* Soft state head */
57 static void *sfxge_ss;
58
59 /*
60 * By default modinfo will display lines truncated to 80 characters and so just
61 * show 32 characters of our sfxge_ident string. At the moment CI_VERSION_STRING
62 * is 12 characters. To show the whole string use modinfo -w
63 */
64 #if defined(_USE_GLD_V3_SOL10) && !defined(_USE_GLD_V3_SOL11)
65 #ifdef DEBUG
66 /*
67 * The (DEBUG) part of this string will not be displayed in modinfo by
68 * default. See previous comment.
69 */
70 const char sfxge_ident[] =
71 CI_VERSION_STRING" for Sol10u8,u9,u10 (DEBUG)";
72 #else
73 const char sfxge_ident[] =
74 CI_VERSION_STRING" for Sol10u8,u9,u10";
75 #endif
76 #elif defined(_USE_GLD_V3_SOL11)
77 #ifdef DEBUG
78 const char sfxge_ident[] = CI_VERSION_STRING" for Sol11 (DEBUG)";
79 #else
80 const char sfxge_ident[] = CI_VERSION_STRING" for Sol11";
81 #endif
82 #elif defined(_USE_GLD_V3)
83 #ifdef DEBUG
84 const char sfxge_ident[] = CI_VERSION_STRING" GLDv3 (DEBUG)";
85 #else
86 const char sfxge_ident[] = CI_VERSION_STRING" GLDv3";
87 #endif
88 #elif defined(_USE_GLD_V2)
89 #ifdef DEBUG
90 const char sfxge_ident[] = CI_VERSION_STRING" GLDv2 (DEBUG)";
91 #else
92 const char sfxge_ident[] = CI_VERSION_STRING" GLDv2";
93 #endif
94 #else
95 #error "sfxge_ident undefined"
96 #endif
97 const char sfxge_version[] = CI_VERSION_STRING;
98
99 static void
100 sfxge_cfg_build(sfxge_t *sp)
101 {
102 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sp->s_enp);
103 (void) snprintf(sp->s_cfg_kstat.buf.sck_mac, 64,
104 "%02X:%02X:%02X:%02X:%02X:%02X",
105 encp->enc_mac_addr[0], encp->enc_mac_addr[1],
106 encp->enc_mac_addr[2], encp->enc_mac_addr[3],
107 encp->enc_mac_addr[4], encp->enc_mac_addr[5]);
108 }
109
110 static int
111 sfxge_create(dev_info_t *dip, sfxge_t **spp)
112 {
113 int instance = ddi_get_instance(dip);
114 sfxge_t *sp;
115 efx_nic_t *enp;
116 char name[MAXNAMELEN];
117 unsigned int rxq_size;
118 int rxq_poll_usec;
119 int rc;
120
121 /* Allocate the soft state object */
122 if (ddi_soft_state_zalloc(sfxge_ss, instance) != DDI_SUCCESS) {
123 rc = ENOMEM;
124 goto fail1;
125 }
126
127 sp = ddi_get_soft_state(sfxge_ss, instance);
128 ASSERT(sp != NULL);
129
130 SFXGE_OBJ_CHECK(sp, sfxge_t);
131
132 sp->s_dip = dip;
133
134 mutex_init(&(sp->s_state_lock), "", MUTEX_DRIVER, NULL);
135 sp->s_state = SFXGE_UNINITIALIZED;
136
137 /* Get property values */
138 sp->s_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
139 DDI_PROP_DONTPASS, "mtu", ETHERMTU);
140
141 sp->s_action_on_hw_err = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
142 DDI_PROP_DONTPASS, "action_on_hw_err", SFXGE_RECOVER);
143
144 rxq_size = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
145 DDI_PROP_DONTPASS, "rxq_size", SFXGE_DEFAULT_RXQ_SIZE);
146 if (!(IS_POW2(rxq_size)))
147 rxq_size = SFXGE_DEFAULT_RXQ_SIZE;
148 rxq_size = min(rxq_size, EFX_RXQ_MAXNDESCS);
149 sp->s_rxq_size = max(rxq_size, EFX_RXQ_MINNDESCS);
150
151 /* Configure polling interval for queue refill/trim */
152 rxq_poll_usec = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
153 DDI_PROP_DONTPASS, "rxq_poll_usec", SFXGE_RX_QPOLL_USEC);
154 if (rxq_poll_usec <= 0)
155 rxq_poll_usec = SFXGE_RX_QPOLL_USEC;
156 sp->s_rxq_poll_usec = rxq_poll_usec;
157
158 /* Create a taskq */
159 (void) snprintf(name, MAXNAMELEN - 1, "%s_tq", ddi_driver_name(dip));
160 sp->s_tqp = ddi_taskq_create(dip, name, 1, TASKQ_DEFAULTPRI, DDI_SLEEP);
161 if (sp->s_tqp == NULL) {
162 rc = ENOMEM;
163 goto fail2;
164 }
165
166 /* Check and initialize PCI configuration space */
167 if ((rc = sfxge_pci_init(sp)) != 0)
168 goto fail3;
169
170 /* Map the device registers */
171 if ((rc = sfxge_bar_init(sp)) != 0)
172 goto fail4;
173
174 /* Create the NIC object */
175 mutex_init(&(sp->s_nic_lock), NULL, MUTEX_DRIVER, NULL);
176
177 if ((rc = efx_nic_create(sp->s_family, (efsys_identifier_t *)sp,
178 &(sp->s_bar), &(sp->s_nic_lock), &enp)) != 0)
179 goto fail5;
180
181 sp->s_enp = enp;
182
183 /* Initialize MCDI to talk to the Microcontroller */
184 if ((rc = sfxge_mcdi_init(sp)) != 0)
185 goto fail6;
186
187 /* Probe the NIC and build the configuration data area */
188 if ((rc = efx_nic_probe(enp)) != 0)
189 goto fail7;
190
191 if (sp->s_family == EFX_FAMILY_SIENA) {
192 sfxge_pcie_check_link(sp, 8, 2); /* PCI 8x Gen2 */
193
194 } else if (sp->s_family == EFX_FAMILY_FALCON) {
195 sfxge_pcie_check_link(sp, 8, 1); /* PCI 8x Gen1 */
196
197 rc = efx_nic_pcie_tune(enp, sp->s_pcie_nlanes);
198 ASSERT(rc == 0);
199 }
200
201 if ((rc = efx_nvram_init(enp)) != 0)
202 goto fail8;
203
204 if ((rc = efx_vpd_init(enp)) != 0)
205 goto fail9;
206
207 if ((rc = efx_nic_reset(enp)) != 0)
208 goto fail10;
209
210 sfxge_sram_init(sp);
211
212 if ((rc = sfxge_intr_init(sp)) != 0)
213 goto fail11;
214
215 if ((rc = sfxge_ev_init(sp)) != 0)
216 goto fail12;
217
218 if ((rc = sfxge_rx_init(sp)) != 0)
219 goto fail13;
220
221 if ((rc = sfxge_tx_init(sp)) != 0)
222 goto fail14;
223
224 if ((rc = sfxge_mon_init(sp)) != 0)
225 goto fail15;
226
227 if ((rc = sfxge_mac_init(sp)) != 0)
228 goto fail16;
229
230 mutex_init(&(sp->s_tx_flush_lock), "", MUTEX_DRIVER,
231 DDI_INTR_PRI(sp->s_intr.si_intr_pri));
232 cv_init(&(sp->s_tx_flush_kv), "", CV_DRIVER, NULL);
233
234 sp->s_state = SFXGE_INITIALIZED;
235
236 *spp = sp;
237 return (0);
238
239 fail16:
240 DTRACE_PROBE(fail16);
241 sfxge_mon_fini(sp);
242
243 fail15:
244 DTRACE_PROBE(fail15);
245 sfxge_tx_fini(sp);
246
247 fail14:
248 DTRACE_PROBE(fail14);
249 sfxge_rx_fini(sp);
250
251 fail13:
252 DTRACE_PROBE(fail13);
253 sfxge_ev_fini(sp);
254
255 fail12:
256 DTRACE_PROBE(fail12);
257 sfxge_intr_fini(sp);
258
259 fail11:
260 DTRACE_PROBE(fail11);
261 sfxge_sram_fini(sp);
262 (void) efx_nic_reset(sp->s_enp);
263
264 fail10:
265 DTRACE_PROBE(fail10);
266 efx_vpd_fini(enp);
267
268 fail9:
269 DTRACE_PROBE(fail9);
270 efx_nvram_fini(enp);
271
272 fail8:
273 DTRACE_PROBE(fail8);
274 efx_nic_unprobe(enp);
275
276 fail7:
277 DTRACE_PROBE(fail7);
278 sfxge_mcdi_fini(sp);
279
280 fail6:
281 DTRACE_PROBE(fail6);
282 sp->s_enp = NULL;
283 efx_nic_destroy(enp);
284
285 fail5:
286 DTRACE_PROBE(fail5);
287 mutex_destroy(&(sp->s_nic_lock));
288 sfxge_bar_fini(sp);
289
290 fail4:
291 DTRACE_PROBE(fail4);
292 sfxge_pci_fini(sp);
293
294 fail3:
295 DTRACE_PROBE(fail3);
296 ddi_taskq_destroy(sp->s_tqp);
297 sp->s_tqp = NULL;
298
299 fail2:
300 DTRACE_PROBE(fail2);
301
302 /* Clear property values */
303 sp->s_mtu = 0;
304
305 mutex_destroy(&(sp->s_state_lock));
306
307 /* Free the soft state */
308 sp->s_dip = NULL;
309
310 SFXGE_OBJ_CHECK(sp, sfxge_t);
311 ddi_soft_state_free(sfxge_ss, instance);
312
313 fail1:
314 DTRACE_PROBE1(fail1, int, rc);
315
316 return (rc);
317 }
318
319
320 static int
321 sfxge_start_locked(sfxge_t *sp, boolean_t restart)
322 {
323 int rc;
324
325 ASSERT(mutex_owned(&(sp->s_state_lock)));
326
327 if (sp->s_state == SFXGE_STARTED)
328 goto done;
329
330 if (sp->s_state != SFXGE_REGISTERED) {
331 rc = EINVAL;
332 goto fail1;
333 }
334 sp->s_state = SFXGE_STARTING;
335
336 if ((rc = efx_nic_reset(sp->s_enp)) != 0)
337 goto fail2;
338
339 if ((rc = efx_nic_init(sp->s_enp)) != 0)
340 goto fail3;
341
342 if ((rc = sfxge_sram_start(sp)) != 0)
343 goto fail4;
344
345 if ((rc = sfxge_intr_start(sp)) != 0)
346 goto fail5;
347
348 if ((rc = sfxge_ev_start(sp)) != 0)
349 goto fail6;
350
351 if ((rc = sfxge_rx_start(sp)) != 0)
352 goto fail7;
353
354 if ((rc = sfxge_tx_start(sp)) != 0)
355 goto fail8;
356
357 if ((rc = sfxge_mon_start(sp)) != 0)
358 goto fail9;
359
360 if ((rc = sfxge_mac_start(sp, restart)) != 0)
361 goto fail10;
362
363 ASSERT3U(sp->s_state, ==, SFXGE_STARTING);
364 sp->s_state = SFXGE_STARTED;
365
366 /* Notify any change of MTU */
367 sfxge_gld_mtu_update(sp);
368
369 done:
370 return (0);
371
372 fail10:
373 DTRACE_PROBE(fail10);
374 sfxge_mon_stop(sp);
375
376 fail9:
377 DTRACE_PROBE(fail9);
378 sfxge_tx_stop(sp);
379
380 fail8:
381 DTRACE_PROBE(fail8);
382 sfxge_rx_stop(sp);
383
384 fail7:
385 DTRACE_PROBE(fail7);
386 sfxge_ev_stop(sp);
387
388 fail6:
389 DTRACE_PROBE(fail6);
390 sfxge_intr_stop(sp);
391
392 fail5:
393 DTRACE_PROBE(fail5);
394 sfxge_sram_stop(sp);
395
396 fail4:
397 DTRACE_PROBE(fail4);
398 efx_nic_fini(sp->s_enp);
399
400 fail3:
401 DTRACE_PROBE(fail3);
402 (void) efx_nic_reset(sp->s_enp);
403
404 fail2:
405 DTRACE_PROBE(fail2);
406
407 ASSERT3U(sp->s_state, ==, SFXGE_STARTING);
408 sp->s_state = SFXGE_REGISTERED;
409
410 fail1:
411 DTRACE_PROBE1(fail1, int, rc);
412
413 return (rc);
414 }
415
416
417 int
418 sfxge_start(sfxge_t *sp, boolean_t restart)
419 {
420 int rc;
421
422 mutex_enter(&(sp->s_state_lock));
423 rc = sfxge_start_locked(sp, restart);
424 mutex_exit(&(sp->s_state_lock));
425 return (rc);
426 }
427
428
429 static void
430 sfxge_stop_locked(sfxge_t *sp)
431 {
432 ASSERT(mutex_owned(&(sp->s_state_lock)));
433
434 if (sp->s_state != SFXGE_STARTED) {
435 return;
436 }
437 sp->s_state = SFXGE_STOPPING;
438
439 sfxge_mac_stop(sp);
440 sfxge_mon_stop(sp);
441 sfxge_tx_stop(sp);
442 sfxge_rx_stop(sp);
443
444 /* Stop event processing - must be after rx_stop see sfxge_rx_qpoll() */
445 sfxge_ev_stop(sp);
446 sfxge_intr_stop(sp); /* cope with late flush/soft events until here */
447 sfxge_sram_stop(sp);
448
449 efx_nic_fini(sp->s_enp);
450 efx_nic_reset(sp->s_enp);
451
452 ASSERT3U(sp->s_state, ==, SFXGE_STOPPING);
453 sp->s_state = SFXGE_REGISTERED;
454 }
455
456 void
457 sfxge_stop(sfxge_t *sp)
458 {
459 mutex_enter(&(sp->s_state_lock));
460 sfxge_stop_locked(sp);
461 mutex_exit(&(sp->s_state_lock));
462 }
463
464 static void
465 _sfxge_restart(void *arg)
466 {
467 sfxge_t *sp = arg;
468 int rc;
469
470 /* logging on entry is in sfxge_restart_dispatch */
471 mutex_enter(&(sp->s_state_lock));
472
473 DTRACE_PROBE(_sfxge_restart);
474 if (sp->s_state != SFXGE_STARTED)
475 goto done;
476
477 /* inform the OS that the link is down - may trigger IPMP failover */
478 if (sp->s_hw_err && sp->s_action_on_hw_err != SFXGE_INVISIBLE) {
479 sp->s_mac.sm_link_mode = EFX_LINK_DOWN;
480 sfxge_gld_link_update(sp);
481 }
482
483 /* Stop processing */
484 sfxge_stop_locked(sp);
485
486 if (sp->s_hw_err && sp->s_action_on_hw_err == SFXGE_LEAVE_DEAD) {
487 cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] NIC error - interface is"
488 " being left permanently DOWN per driver config",
489 ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
490 mutex_exit(&(sp->s_state_lock));
491 return;
492 } else
493 sp->s_hw_err = SFXGE_HW_OK;
494
495 /* Start processing */
496 if ((rc = sfxge_start_locked(sp, B_TRUE)) != 0)
497 goto fail1;
498
499 done:
500 mutex_exit(&(sp->s_state_lock));
501 cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] NIC restart complete",
502 ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip));
503 return;
504
505 fail1:
506 DTRACE_PROBE1(fail1, int, rc);
507 cmn_err(CE_WARN,
508 SFXGE_CMN_ERR "[%s%d] FATAL ERROR: NIC restart failed rc=%d",
509 ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip), rc);
510
511 mutex_exit(&(sp->s_state_lock));
512 }
513
514 int
515 sfxge_restart_dispatch(sfxge_t *sp, uint_t cflags, sfxge_hw_err_t hw_err,
516 const char *reason, uint32_t errval)
517 {
518 if (hw_err == SFXGE_HW_OK)
519 sp->s_num_restarts++;
520 else {
521 sp->s_hw_err = hw_err;
522 sp->s_num_restarts_hw_err++;
523 }
524
525 DTRACE_PROBE2(sfxge_restart_dispatch, sfxge_hw_err_t, hw_err, char *,
526 reason);
527
528 cmn_err(CE_WARN, SFXGE_CMN_ERR "[%s%d] NIC restart due to %s:%d",
529 ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip), reason,
530 errval);
531
532 /* If cflags == DDI_SLEEP then guaranteed to succeed */
533 return (ddi_taskq_dispatch(sp->s_tqp, _sfxge_restart, sp, cflags));
534 }
535
536
537 static int
538 sfxge_can_destroy(sfxge_t *sp)
539 {
540 sfxge_intr_t *sip = &(sp->s_intr);
541 int index;
542
543 /*
544 * In SFC bug 19834 it was noted that a mblk passed up to STREAMS
545 * could be reused for transmit and sit in the sfxge_tx_packet_cache.
546 * This call to empty the TX deferred packet list may result in
547 * rx_loaned reducing.
548 */
549 index = sip->si_nalloc;
550 while (--index >= 0) {
551 sfxge_txq_t *stp = sp->s_stp[index];
552 sfxge_tx_qdpl_flush(stp);
553 }
554
555 /* Need to wait for desballoc free_func callback */
556 return (sfxge_rx_loaned(sp));
557 }
558
559
560 static int
561 sfxge_destroy(sfxge_t *sp)
562 {
563 dev_info_t *dip = sp->s_dip;
564 int instance = ddi_get_instance(dip);
565 ddi_taskq_t *tqp;
566 efx_nic_t *enp;
567 int rc;
568
569 ASSERT3U(sp->s_state, ==, SFXGE_INITIALIZED);
570 enp = sp->s_enp;
571
572 if (sfxge_can_destroy(sp) != 0) {
573 rc = EBUSY;
574 goto fail1;
575 }
576
577 sp->s_state = SFXGE_UNINITIALIZED;
578
579 cv_destroy(&(sp->s_tx_flush_kv));
580 mutex_destroy(&(sp->s_tx_flush_lock));
581
582 sfxge_mac_fini(sp);
583 sfxge_mon_fini(sp);
584 sfxge_tx_fini(sp);
585 sfxge_rx_fini(sp);
586 sfxge_ev_fini(sp);
587 sfxge_intr_fini(sp);
588 sfxge_sram_fini(sp);
589 (void) efx_nic_reset(enp);
590
591 efx_vpd_fini(enp);
592 efx_nvram_fini(enp);
593 efx_nic_unprobe(enp);
594 sfxge_mcdi_fini(sp);
595
596 /* Destroy the NIC object */
597 sp->s_enp = NULL;
598 efx_nic_destroy(enp);
599
600 mutex_destroy(&(sp->s_nic_lock));
601
602 /* Unmap the device registers */
603 sfxge_bar_fini(sp);
604
605 /* Tear down PCI configuration space */
606 sfxge_pci_fini(sp);
607
608 /* Destroy the taskq */
609 tqp = sp->s_tqp;
610 sp->s_tqp = NULL;
611 ddi_taskq_destroy(tqp);
612
613 mutex_destroy(&(sp->s_state_lock));
614
615 /* Clear property values */
616 sp->s_mtu = 0;
617
618 /* Free the soft state */
619 sp->s_dip = NULL;
620
621 SFXGE_OBJ_CHECK(sp, sfxge_t);
622 ddi_soft_state_free(sfxge_ss, instance);
623
624 return (0);
625
626 fail1:
627 DTRACE_PROBE1(fail1, int, rc);
628
629 return (rc);
630 }
631
632 void
633 sfxge_ioctl(sfxge_t *sp, queue_t *wq, mblk_t *mp)
634 {
635 struct iocblk *iocp;
636 int rc, taskq_wait = 0;
637 size_t ioclen = 0;
638
639 /*
640 * single concurrent IOCTL
641 * serialized from sfxge_create, _destroy, _(re)start, _stop
642 */
643 mutex_enter(&(sp->s_state_lock));
644
645 /*LINTED*/
646 iocp = (struct iocblk *)mp->b_rptr;
647
648 switch (iocp->ioc_cmd) {
649 case SFXGE_TX_IOC:
650 ioclen = sizeof (sfxge_tx_ioc_t);
651 break;
652 case SFXGE_RX_IOC:
653 ioclen = sizeof (sfxge_rx_ioc_t);
654 break;
655 case SFXGE_BAR_IOC:
656 ioclen = sizeof (sfxge_bar_ioc_t);
657 break;
658 case SFXGE_PCI_IOC:
659 ioclen = sizeof (sfxge_pci_ioc_t);
660 break;
661 case SFXGE_MAC_IOC:
662 ioclen = sizeof (sfxge_mac_ioc_t);
663 break;
664 case SFXGE_PHY_IOC:
665 ioclen = sizeof (sfxge_phy_ioc_t);
666 break;
667 case SFXGE_PHY_BIST_IOC:
668 ioclen = sizeof (sfxge_phy_bist_ioc_t);
669 break;
670 case SFXGE_SRAM_IOC:
671 ioclen = sizeof (sfxge_sram_ioc_t);
672 break;
673 case SFXGE_NVRAM_IOC:
674 ioclen = sizeof (sfxge_nvram_ioc_t);
675 break;
676 case SFXGE_MCDI_IOC:
677 ioclen = sizeof (sfxge_mcdi_ioc_t);
678 break;
679 case SFXGE_VPD_IOC:
680 ioclen = sizeof (sfxge_vpd_ioc_t);
681 break;
682 case SFXGE_START_IOC:
683 case SFXGE_STOP_IOC:
684 case SFXGE_NIC_RESET_IOC:
685 break;
686 default:
687 rc = ENOTSUP;
688 goto fail1;
689 }
690
691 if (iocp->ioc_count != ioclen) {
692 rc = EINVAL;
693 goto fail2;
694 }
695
696 /* if in multiple fragments pull it up to one linear buffer */
697 if ((rc = miocpullup(mp, ioclen)) != 0) {
698 goto fail3;
699 }
700
701 switch (iocp->ioc_cmd) {
702 case SFXGE_START_IOC:
703 if ((rc = sfxge_start_locked(sp, B_TRUE)) != 0)
704 goto fail4;
705
706 break;
707
708 case SFXGE_STOP_IOC:
709 sfxge_stop_locked(sp);
710 break;
711
712 case SFXGE_TX_IOC: {
713 sfxge_tx_ioc_t *stip = (sfxge_tx_ioc_t *)mp->b_cont->b_rptr;
714
715 if ((rc = sfxge_tx_ioctl(sp, stip)) != 0)
716 goto fail4;
717
718 break;
719 }
720 case SFXGE_RX_IOC: {
721 sfxge_rx_ioc_t *srip = (sfxge_rx_ioc_t *)mp->b_cont->b_rptr;
722
723 if ((rc = sfxge_rx_ioctl(sp, srip)) != 0)
724 goto fail4;
725
726 break;
727 }
728 case SFXGE_BAR_IOC: {
729 sfxge_bar_ioc_t *sbip = (sfxge_bar_ioc_t *)mp->b_cont->b_rptr;
730
731 if ((rc = sfxge_bar_ioctl(sp, sbip)) != 0)
732 goto fail4;
733
734 break;
735 }
736 case SFXGE_PCI_IOC: {
737 sfxge_pci_ioc_t *spip = (sfxge_pci_ioc_t *)mp->b_cont->b_rptr;
738
739 if ((rc = sfxge_pci_ioctl(sp, spip)) != 0)
740 goto fail4;
741
742 break;
743 }
744 case SFXGE_MAC_IOC: {
745 sfxge_mac_ioc_t *smip = (sfxge_mac_ioc_t *)mp->b_cont->b_rptr;
746
747 if ((rc = sfxge_mac_ioctl(sp, smip)) != 0)
748 goto fail4;
749
750 break;
751 }
752 case SFXGE_PHY_IOC: {
753 sfxge_phy_ioc_t *spip = (sfxge_phy_ioc_t *)mp->b_cont->b_rptr;
754
755 if ((rc = sfxge_phy_ioctl(sp, spip)) != 0)
756 goto fail4;
757
758 break;
759 }
760 case SFXGE_PHY_BIST_IOC: {
761 sfxge_phy_bist_ioc_t *spbip;
762
763 spbip = (sfxge_phy_bist_ioc_t *)mp->b_cont->b_rptr;
764
765 if ((rc = sfxge_phy_bist_ioctl(sp, spbip)) != 0)
766 goto fail4;
767
768 break;
769 }
770 case SFXGE_SRAM_IOC: {
771 sfxge_sram_ioc_t *ssip = (sfxge_sram_ioc_t *)mp->b_cont->b_rptr;
772
773 if ((rc = sfxge_sram_ioctl(sp, ssip)) != 0)
774 goto fail4;
775
776 break;
777 }
778 case SFXGE_NVRAM_IOC: {
779 sfxge_nvram_ioc_t *snip =
780 (sfxge_nvram_ioc_t *)mp->b_cont->b_rptr;
781
782 if ((rc = sfxge_nvram_ioctl(sp, snip)) != 0)
783 goto fail4;
784
785 break;
786 }
787 case SFXGE_MCDI_IOC: {
788 sfxge_mcdi_ioc_t *smip = (sfxge_mcdi_ioc_t *)mp->b_cont->b_rptr;
789
790 if ((rc = sfxge_mcdi_ioctl(sp, smip)) != 0)
791 goto fail4;
792 taskq_wait = 1;
793
794 break;
795 }
796 case SFXGE_NIC_RESET_IOC: {
797 DTRACE_PROBE(nic_reset_ioc);
798
799 /* sp->s_state_lock held */
800 (void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK,
801 "NIC_RESET_IOC", 0);
802 taskq_wait = 1;
803
804 break;
805 }
806 case SFXGE_VPD_IOC: {
807 sfxge_vpd_ioc_t *svip = (sfxge_vpd_ioc_t *)mp->b_cont->b_rptr;
808
809 if ((rc = sfxge_vpd_ioctl(sp, svip)) != 0)
810 goto fail4;
811
812 break;
813 }
814 default:
815 ASSERT(0);
816 }
817
818 mutex_exit(&(sp->s_state_lock));
819
820 if (taskq_wait) {
821 /*
822 * Wait for any tasks that may be accessing GLD functions
823 * This may end up waiting for multiple nic_resets
824 * as it needs to be outside of s_state_lock for sfxge_restart()
825 */
826 ddi_taskq_wait(sp->s_tqp);
827 }
828
829 /* The entire structure is the acknowledgement */
830 miocack(wq, mp, iocp->ioc_count, 0);
831
832 return;
833
834 fail4:
835 DTRACE_PROBE(fail4);
836 fail3:
837 DTRACE_PROBE(fail3);
838 fail2:
839 DTRACE_PROBE(fail2);
840 fail1:
841 DTRACE_PROBE1(fail1, int, rc);
842
843 mutex_exit(&(sp->s_state_lock));
844
845 /* no data returned */
846 miocnak(wq, mp, 0, rc);
847 }
848
849 static int
850 sfxge_register(sfxge_t *sp)
851 {
852 int rc;
853
854 ASSERT3U(sp->s_state, ==, SFXGE_INITIALIZED);
855
856 if ((rc = sfxge_gld_register(sp)) != 0)
857 goto fail1;
858
859 sp->s_state = SFXGE_REGISTERED;
860
861 return (0);
862
863 fail1:
864 DTRACE_PROBE1(fail1, int, rc);
865
866 return (rc);
867 }
868
869 static int
870 sfxge_unregister(sfxge_t *sp)
871 {
872 int rc;
873
874 ASSERT3U(sp->s_state, ==, SFXGE_REGISTERED);
875
876 /* Wait for any tasks that may be accessing GLD functions */
877 ddi_taskq_wait(sp->s_tqp);
878
879 if ((rc = sfxge_gld_unregister(sp)) != 0)
880 goto fail1;
881
882 sp->s_state = SFXGE_INITIALIZED;
883
884 return (0);
885
886 fail1:
887 DTRACE_PROBE1(fail1, int, rc);
888
889 return (rc);
890 }
891
892 static void
893 _sfxge_vpd_kstat_init(sfxge_t *sp, caddr_t vpd, size_t size, efx_vpd_tag_t tag,
894 const char *keyword, sfxge_vpd_type_t type)
895 {
896 static const char unknown[] = "?";
897 efx_nic_t *enp = sp->s_enp;
898 sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
899 kstat_named_t *knp;
900 efx_vpd_value_t *evvp;
901
902 evvp = svkp->svk_vv + type;
903 evvp->evv_tag = tag;
904 evvp->evv_keyword = EFX_VPD_KEYWORD(keyword[0], keyword[1]);
905
906 if (efx_vpd_get(enp, vpd, size, evvp) != 0) {
907 evvp->evv_length = strlen(unknown) + 1;
908 memcpy(evvp->evv_value, unknown, evvp->evv_length);
909 }
910
911 knp = &(svkp->svk_stat[type]);
912
913 kstat_named_init(knp, (char *)keyword, KSTAT_DATA_STRING);
914 kstat_named_setstr(knp, (char *)evvp->evv_value);
915 svkp->svk_ksp->ks_data_size += sizeof (*evvp);
916 }
917
918 static int
919 sfxge_vpd_kstat_init(sfxge_t *sp)
920 {
921 efx_nic_t *enp = sp->s_enp;
922 sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
923 dev_info_t *dip = sp->s_dip;
924 char name[MAXNAMELEN];
925 kstat_t *ksp;
926 caddr_t vpd;
927 size_t size;
928 int rc;
929
930 SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
931 (void) snprintf(name, MAXNAMELEN - 1, "%s_vpd", ddi_driver_name(dip));
932
933 /* Get a copy of the VPD space */
934 if ((rc = efx_vpd_size(enp, &size)) != 0)
935 goto fail1;
936
937 if ((vpd = kmem_zalloc(size, KM_NOSLEEP)) == NULL) {
938 rc = ENOMEM;
939 goto fail2;
940 }
941
942 if ((svkp->svk_vv = kmem_zalloc(sizeof (efx_vpd_value_t) *
943 SFXGE_VPD_MAX, KM_NOSLEEP)) == NULL) {
944 rc = ENOMEM;
945 goto fail3;
946 }
947
948 if ((rc = efx_vpd_read(enp, vpd, size)) != 0)
949 goto fail4;
950
951 if ((ksp = kstat_create((char *)ddi_driver_name(dip),
952 ddi_get_instance(dip), name, "vpd", KSTAT_TYPE_NAMED, SFXGE_VPD_MAX,
953 KSTAT_FLAG_VIRTUAL)) == NULL) {
954 rc = ENOMEM;
955 goto fail5;
956 }
957 svkp->svk_ksp = ksp;
958 ksp->ks_data = &(svkp->svk_stat);
959
960 _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_ID, "ID", SFXGE_VPD_ID);
961 _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "PN", SFXGE_VPD_PN);
962 _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "SN", SFXGE_VPD_SN);
963 _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "EC", SFXGE_VPD_EC);
964 _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "VD", SFXGE_VPD_VD);
965
966 kstat_install(ksp);
967 kmem_free(vpd, size);
968
969 return (0);
970
971 fail5:
972 DTRACE_PROBE(fail5);
973 fail4:
974 DTRACE_PROBE(fail4);
975 kmem_free(svkp->svk_vv, sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
976 fail3:
977 DTRACE_PROBE(fail3);
978 kmem_free(vpd, size);
979 fail2:
980 DTRACE_PROBE(fail2);
981 fail1:
982 DTRACE_PROBE1(fail1, int, rc);
983 SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
984
985 return (rc);
986 }
987
988 static void
989 sfxge_vpd_kstat_fini(sfxge_t *sp)
990 {
991 sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
992
993 /* NOTE: VPD support is optional, so kstats might not be registered */
994 if (svkp->svk_ksp != NULL) {
995
996 kstat_delete(svkp->svk_ksp);
997
998 kmem_free(svkp->svk_vv,
999 sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
1000
1001 bzero(svkp->svk_stat,
1002 sizeof (kstat_named_t) * SFXGE_VPD_MAX);
1003
1004 svkp->svk_ksp = NULL;
1005 }
1006
1007 SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
1008 }
1009
1010 static int
1011 sfxge_cfg_kstat_init(sfxge_t *sp)
1012 {
1013 dev_info_t *dip = sp->s_dip;
1014 char name[MAXNAMELEN];
1015 kstat_t *ksp;
1016 sfxge_cfg_kstat_t *sckp;
1017 int rc;
1018
1019 sfxge_cfg_build(sp);
1020
1021 /* Create the set */
1022 (void) snprintf(name, MAXNAMELEN - 1, "%s_cfg", ddi_driver_name(dip));
1023
1024 if ((ksp = kstat_create((char *)ddi_driver_name(dip),
1025 ddi_get_instance(dip), name, "cfg", KSTAT_TYPE_NAMED,
1026 sizeof (sckp->kstat) / sizeof (kstat_named_t),
1027 KSTAT_FLAG_VIRTUAL)) == NULL) {
1028 rc = ENOMEM;
1029 goto fail1;
1030 }
1031
1032 sp->s_cfg_ksp = ksp;
1033
1034 ksp->ks_data = sckp = &(sp->s_cfg_kstat);
1035
1036 kstat_named_init(&(sckp->kstat.sck_mac), "mac", KSTAT_DATA_STRING);
1037 kstat_named_setstr(&(sckp->kstat.sck_mac), sckp->buf.sck_mac);
1038 ksp->ks_data_size += sizeof (sckp->buf.sck_mac);
1039
1040 kstat_named_init(&(sckp->kstat.sck_version), "version",
1041 KSTAT_DATA_STRING);
1042 kstat_named_setstr(&(sckp->kstat.sck_version), sfxge_version);
1043 ksp->ks_data_size += sizeof (sfxge_version);
1044
1045 kstat_install(ksp);
1046 return (0);
1047
1048 fail1:
1049 DTRACE_PROBE1(fail1, int, rc);
1050
1051 return (rc);
1052 }
1053
1054 static void
1055 sfxge_cfg_kstat_fini(sfxge_t *sp)
1056 {
1057 if (sp->s_cfg_ksp == NULL)
1058 return;
1059
1060 kstat_delete(sp->s_cfg_ksp);
1061 sp->s_cfg_ksp = NULL;
1062
1063 bzero(&(sp->s_cfg_kstat), sizeof (sfxge_cfg_kstat_t));
1064 }
1065
1066 static int
1067 sfxge_resume(dev_info_t *dip)
1068 {
1069 sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
1070 int rc;
1071
1072 /* Start processing */
1073 if ((rc = sfxge_start(sp, B_FALSE)) != 0)
1074 goto fail1;
1075
1076 return (DDI_SUCCESS);
1077
1078 fail1:
1079 DTRACE_PROBE1(fail1, int, rc);
1080
1081 return (DDI_FAILURE);
1082 }
1083
1084 static int
1085 sfxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1086 {
1087 sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
1088 int rc;
1089
1090 switch (cmd) {
1091 case DDI_ATTACH:
1092 if (sp != NULL) {
1093 cmn_err(CE_WARN, SFXGE_CMN_ERR
1094 "[%s%d] ATTACH for attached instance\n",
1095 ddi_driver_name(sp->s_dip),
1096 ddi_get_instance(sp->s_dip));
1097 return (DDI_FAILURE);
1098 }
1099 break;
1100
1101 case DDI_RESUME:
1102 if (sp == NULL) {
1103 cmn_err(CE_WARN, SFXGE_CMN_ERR
1104 "[%s%d] RESUME for missing instance\n",
1105 ddi_driver_name(sp->s_dip),
1106 ddi_get_instance(sp->s_dip));
1107 return (DDI_FAILURE);
1108 }
1109 return (sfxge_resume(dip));
1110
1111 default:
1112 return (DDI_FAILURE);
1113 }
1114
1115 /* Create the soft state */
1116 if ((rc = sfxge_create(dip, &sp)) != 0)
1117 goto fail1;
1118
1119 /* Create the configuration kstats */
1120 if ((rc = sfxge_cfg_kstat_init(sp)) != 0)
1121 goto fail2;
1122
1123 /* Create the VPD kstats */
1124 if ((rc = sfxge_vpd_kstat_init(sp)) != 0) {
1125 if (rc != ENOTSUP)
1126 goto fail3;
1127 }
1128
1129 /* Register the interface */
1130 if ((rc = sfxge_register(sp)) != 0)
1131 goto fail4;
1132
1133 /* Announce ourselves in the system log */
1134 ddi_report_dev(dip);
1135
1136 return (DDI_SUCCESS);
1137
1138 fail4:
1139 DTRACE_PROBE(fail4);
1140
1141 /* Destroy the VPD kstats */
1142 sfxge_vpd_kstat_fini(sp);
1143
1144 fail3:
1145 DTRACE_PROBE(fail3);
1146
1147 /* Destroy the configuration kstats */
1148 sfxge_cfg_kstat_fini(sp);
1149
1150 fail2:
1151 DTRACE_PROBE(fail2);
1152
1153 /* Destroy the soft state */
1154 (void) sfxge_destroy(sp);
1155
1156 fail1:
1157 DTRACE_PROBE1(fail1, int, rc);
1158
1159 return (DDI_FAILURE);
1160 }
1161
1162 static int
1163 sfxge_suspend(dev_info_t *dip)
1164 {
1165 sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
1166
1167 /* Stop processing */
1168 sfxge_stop(sp);
1169
1170 return (DDI_SUCCESS);
1171 }
1172
1173 static int
1174 sfxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1175 {
1176 sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
1177 int rc;
1178
1179 switch (cmd) {
1180 case DDI_DETACH:
1181 if (sp == NULL) {
1182 cmn_err(CE_WARN, SFXGE_CMN_ERR
1183 "[%s%d] DETACH for missing instance\n",
1184 ddi_driver_name(sp->s_dip),
1185 ddi_get_instance(sp->s_dip));
1186 return (DDI_FAILURE);
1187 }
1188 break;
1189
1190 case DDI_SUSPEND:
1191 if (sp == NULL) {
1192 cmn_err(CE_WARN, SFXGE_CMN_ERR
1193 "[%s%d] SUSPEND for missing instance\n",
1194 ddi_driver_name(sp->s_dip),
1195 ddi_get_instance(sp->s_dip));
1196 return (DDI_FAILURE);
1197 }
1198 return (sfxge_suspend(dip));
1199
1200 default:
1201 return (DDI_FAILURE);
1202 }
1203
1204 ASSERT(sp != NULL);
1205
1206 /* Wait for any pending restarts to complete */
1207 ddi_taskq_wait(sp->s_tqp);
1208
1209 /*
1210 * IOCTLs from utilites can cause GLD mc_start() (SFXGE_STARTED state)
1211 * And mc_stop() may not occur until detach time and race. SFC bug 19855
1212 * Holding the lock seems to be enough - the log message is not seen
1213 */
1214 mutex_enter(&(sp->s_state_lock));
1215 if (sp->s_state == SFXGE_STARTED) {
1216 cmn_err(CE_WARN, SFXGE_CMN_ERR
1217 "[%s%d] STREAMS detach when STARTED\n",
1218 ddi_driver_name(sp->s_dip),
1219 ddi_get_instance(sp->s_dip));
1220 sfxge_stop_locked(sp);
1221 ASSERT3U(sp->s_state, ==, SFXGE_REGISTERED);
1222 }
1223 mutex_exit(&(sp->s_state_lock));
1224
1225 ASSERT(sp->s_state == SFXGE_REGISTERED ||
1226 sp->s_state == SFXGE_INITIALIZED);
1227
1228 if (sp->s_state != SFXGE_REGISTERED)
1229 goto destroy;
1230
1231 /* Unregister the interface */
1232 if ((rc = sfxge_unregister(sp)) != 0)
1233 goto fail1;
1234
1235 destroy:
1236 /* Destroy the VPD kstats */
1237 sfxge_vpd_kstat_fini(sp);
1238
1239 /* Destroy the configuration kstats */
1240 sfxge_cfg_kstat_fini(sp);
1241
1242 /*
1243 * Destroy the soft state - this might fail until rx_loaned packets that
1244 * have been passed up the STREAMS stack are returned
1245 */
1246 if ((rc = sfxge_destroy(sp)) != 0)
1247 goto fail2;
1248
1249 return (DDI_SUCCESS);
1250
1251 fail2:
1252 DTRACE_PROBE(fail2);
1253 fail1:
1254 DTRACE_PROBE1(fail1, int, rc);
1255
1256 return (DDI_FAILURE);
1257 }
1258
1259 #ifdef _USE_GLD_V3
1260 #ifndef _USE_GLD_V3_SOL10
1261 static int
1262 sfxge_quiesce(dev_info_t *dip)
1263 {
1264 sfxge_t *sp = ddi_get_soft_state(sfxge_ss, ddi_get_instance(dip));
1265 int rc;
1266
1267 /* Reset the hardware */
1268 if ((rc = sfxge_reset(sp, B_FALSE)) != 0)
1269 goto fail1;
1270
1271 return (DDI_SUCCESS);
1272
1273 fail1:
1274 DTRACE_PROBE1(fail1, int, rc);
1275
1276 return (DDI_FAILURE);
1277 }
1278 #endif
1279 #endif
1280
1281 /*
1282 * modlinkage
1283 */
1284 DDI_DEFINE_STREAM_OPS(sfxge_dev_ops, nulldev, nulldev, sfxge_attach,
1285 sfxge_detach, nulldev, NULL, D_MP, NULL, NULL);
1286
1287 #ifdef _USE_GLD_V2
1288
1289 static struct module_info sfxge_module_info = {
1290 0,
1291 SFXGE_DRIVER_NAME,
1292 0,
1293 INFPSZ,
1294 1,
1295 0
1296 };
1297
1298 static struct qinit sfxge_rqinit = {
1299 NULL,
1300 gld_rsrv,
1301 gld_open,
1302 gld_close,
1303 NULL,
1304 &sfxge_module_info,
1305 NULL
1306 };
1307
1308 static struct qinit sfxge_wqinit = {
1309 gld_wput,
1310 gld_wsrv,
1311 NULL,
1312 NULL,
1313 NULL,
1314 &sfxge_module_info,
1315 NULL
1316 };
1317
1318 static struct streamtab sfxge_streamtab = {
1319 &sfxge_rqinit,
1320 &sfxge_wqinit,
1321 NULL,
1322 NULL
1323 };
1324
1325 static struct cb_ops sfxge_cb_ops = {
1326 nulldev, /* cb_open */
1327 nulldev, /* cb_close */
1328 nodev, /* cb_strategy */
1329 nodev, /* cb_print */
1330 nodev, /* cb_dump */
1331 nodev, /* cb_read */
1332 nodev, /* cb_write */
1333 nodev, /* cb_ioctl */
1334 nodev, /* cb_devmap */
1335 nodev, /* cb_mmap */
1336 nodev, /* cb_segmap */
1337 nochpoll, /* cb_chpoll */
1338 ddi_prop_op, /* cb_prop_op */
1339 &sfxge_streamtab, /* cb_stream */
1340 D_MP, /* cb_flag */
1341 CB_REV, /* cb_rev */
1342 nodev, /* cb_aread */
1343 nodev, /* cb_awrite */
1344 };
1345
1346 static struct dev_ops sfxge_dev_ops = {
1347 DEVO_REV, /* devo_rev */
1348 0, /* devo_refcnt */
1349 NULL, /* devo_getinfo */
1350 nulldev, /* devo_identify */
1351 nulldev, /* devo_probe */
1352 sfxge_attach, /* devo_attach */
1353 sfxge_detach, /* devo_detach */
1354 nulldev, /* devo_reset */
1355 &sfxge_cb_ops, /* devo_cb_ops */
1356 (struct bus_ops *)NULL, /* devo_bus_ops */
1357 NULL /* devo_power */
1358 };
1359
1360 #endif
1361
1362 static struct modldrv sfxge_modldrv = {
1363 &mod_driverops,
1364 (char *)sfxge_ident,
1365 &sfxge_dev_ops,
1366 };
1367
1368 static struct modlinkage sfxge_modlinkage = {
1369 MODREV_1,
1370 { &sfxge_modldrv, NULL }
1371 };
1372
1373 kmutex_t sfxge_global_lock;
1374 unsigned int *sfxge_cpu;
1375 #ifdef _USE_CPU_PHYSID
1376 unsigned int *sfxge_core;
1377 unsigned int *sfxge_cache;
1378 unsigned int *sfxge_chip;
1379 #endif
1380
1381 int
1382 _init(void)
1383 {
1384 int rc;
1385
1386 mutex_init(&sfxge_global_lock, NULL, MUTEX_DRIVER, NULL);
1387
1388 /* Create tables for CPU, core, cache and chip counts */
1389 sfxge_cpu = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
1390 #ifdef _USE_CPU_PHYSID
1391 sfxge_core = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
1392 sfxge_cache = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
1393 sfxge_chip = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
1394 #endif
1395
1396 if ((rc = ddi_soft_state_init(&sfxge_ss, sizeof (sfxge_t), 0)) != 0)
1397 goto fail1;
1398
1399 #ifdef _USE_GLD_V3
1400 mac_init_ops(&sfxge_dev_ops, SFXGE_DRIVER_NAME);
1401 #endif
1402
1403 if ((rc = mod_install(&sfxge_modlinkage)) != 0)
1404 goto fail2;
1405
1406 cmn_err(CE_NOTE, SFXGE_CMN_ERR
1407 "LOAD: Solarflare Ethernet Driver (%s) %s",
1408 SFXGE_DRIVER_NAME, sfxge_ident);
1409
1410 return (0);
1411
1412 fail2:
1413 DTRACE_PROBE(fail2);
1414
1415 #ifdef _USE_GLD_V3
1416 // mac_fini_ops(&sfxge_dev_ops);
1417 #endif
1418
1419 ddi_soft_state_fini(&sfxge_ss);
1420
1421 fail1:
1422 DTRACE_PROBE1(fail1, int, rc);
1423
1424 return (rc);
1425 }
1426
1427 int
1428 _fini(void)
1429 {
1430 int rc;
1431
1432 if ((rc = mod_remove(&sfxge_modlinkage)) != 0)
1433 return (rc);
1434
1435 cmn_err(CE_NOTE, SFXGE_CMN_ERR
1436 "UNLOAD: Solarflare Ethernet Driver (%s) %s",
1437 SFXGE_DRIVER_NAME, sfxge_ident);
1438
1439 #ifdef _USE_GLD_V3
1440 mac_fini_ops(&sfxge_dev_ops);
1441 #endif
1442
1443 ddi_soft_state_fini(&sfxge_ss);
1444
1445 /* Destroy tables */
1446 #ifdef _USE_CPU_PHYSID
1447 kmem_free(sfxge_chip, sizeof (unsigned int) * NCPU);
1448 kmem_free(sfxge_cache, sizeof (unsigned int) * NCPU);
1449 kmem_free(sfxge_core, sizeof (unsigned int) * NCPU);
1450 #endif
1451 kmem_free(sfxge_cpu, sizeof (unsigned int) * NCPU);
1452
1453 mutex_destroy(&sfxge_global_lock);
1454
1455 return (0);
1456 }
1457
1458 int
1459 _info(struct modinfo *mip)
1460 {
1461 return (mod_info(&sfxge_modlinkage, mip));
1462 }