1 /*
2 * Copyright (c) 2008-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31 /*
32 * All efx_mac_*() must be after efx_port_init()
33 * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED
34 * to serialise against sfxge_restart()
35 */
36
37 #include <sys/types.h>
38 #include <sys/sysmacros.h>
39 #include <sys/ddi.h>
40 #include <sys/sunddi.h>
41
42 #include "sfxge.h"
43 #include "efx.h"
44
45 #define SFXGE_MAC_POLL_PERIOD_MS 1000
46
47 static void sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode);
48
49
50 /* MAC DMA attributes */
51 static ddi_device_acc_attr_t sfxge_mac_devacc = {
52
53 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */
54 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */
55 DDI_STRICTORDER_ACC /* devacc_attr_dataorder */
56 };
57
58 static ddi_dma_attr_t sfxge_mac_dma_attr = {
59 DMA_ATTR_V0, /* dma_attr_version */
60 0, /* dma_attr_addr_lo */
61 0xffffffffffffffffull, /* dma_attr_addr_hi */
62 0xffffffffffffffffull, /* dma_attr_count_max */
63 0x1000, /* dma_attr_align */
64 0xffffffff, /* dma_attr_burstsizes */
65 1, /* dma_attr_minxfer */
66 0xffffffffffffffffull, /* dma_attr_maxxfer */
67 0xffffffffffffffffull, /* dma_attr_seg */
68 1, /* dma_attr_sgllen */
69 1, /* dma_attr_granular */
70 0 /* dma_attr_flags */
71 };
72
73
74 static void
75 _sfxge_mac_stat_update(sfxge_mac_t *smp, int tries, int delay_usec)
76 {
77 sfxge_t *sp = smp->sm_sp;
78 efsys_mem_t *esmp = &(smp->sm_mem);
79 int i;
80
81 ASSERT(mutex_owned(&(smp->sm_lock)));
82 ASSERT3U(smp->sm_state, !=, SFXGE_MAC_UNINITIALIZED);
83
84 /* if no stats pending then they are already freshly updated */
85 if (smp->sm_mac_stats_timer_reqd && !smp->sm_mac_stats_pend)
86 return;
87
88 for (i = 0; i < tries; i++) {
89 /* Try to update the cached counters */
90 if (efx_mac_stats_update(sp->s_enp, esmp, smp->sm_stat,
91 NULL) != EAGAIN)
92 goto done;
93
94 drv_usecwait(delay_usec);
95 }
96
97 DTRACE_PROBE(mac_stat_timeout);
98 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "MAC stats timeout");
99 return;
100
101 done:
102 smp->sm_mac_stats_pend = B_FALSE;
103 smp->sm_lbolt = ddi_get_lbolt();
104 }
105
106 static void
107 sfxge_mac_stat_update_quick(sfxge_mac_t *smp)
108 {
109 /*
110 * Update the statistics from the most recent DMA. This might race
111 * with an inflight dma, so retry once. Otherwise get mac stat
112 * values from the last mac_poll() or MC periodic stats.
113 */
114 _sfxge_mac_stat_update(smp, 2, 50);
115 }
116
117 static void
118 sfxge_mac_stat_update_wait(sfxge_mac_t *smp)
119 {
120 /* Wait a max of 20 * 500us = 10ms */
121 _sfxge_mac_stat_update(smp, 20, 500);
122 }
123
124 static int
125 sfxge_mac_kstat_update(kstat_t *ksp, int rw)
126 {
127 sfxge_mac_t *smp = ksp->ks_private;
128 kstat_named_t *knp;
129 int rc;
130 unsigned int val;
131 sfxge_rx_coalesce_mode_t rxmode;
132
133 if (rw != KSTAT_READ) {
134 rc = EACCES;
135 goto fail1;
136 }
137
138 ASSERT(mutex_owned(&(smp->sm_lock)));
139
140 if (smp->sm_state != SFXGE_MAC_STARTED)
141 goto done;
142
143 sfxge_mac_stat_update_quick(smp);
144
145 knp = smp->sm_stat;
146 knp += EFX_MAC_NSTATS;
147
148 knp->value.ui64 = (smp->sm_link_up) ? 1 : 0;
149 knp++;
150
151 knp->value.ui64 = smp->sm_link_speed;
152 knp++;
153
154 knp->value.ui64 = smp->sm_link_duplex;
155 knp++;
156
157 knp->value.ui64 = (smp->sm_fcntl & EFX_FCNTL_GENERATE) ? 1 : 0;
158 knp++;
159
160 knp->value.ui64 = (smp->sm_fcntl & EFX_FCNTL_RESPOND) ? 1 : 0;
161 knp++;
162
163 sfxge_ev_moderation_get(smp->sm_sp, &val);
164 knp->value.ui64 = val;
165 knp++;
166
167 sfxge_rx_coalesce_mode_get(smp->sm_sp, &rxmode);
168 knp->value.ui64 = (uint64_t)rxmode;
169 knp++;
170
171 if (sfxge_rx_scale_count_get(smp->sm_sp, &val) != 0)
172 val = 0;
173 knp->value.ui64 = val;
174 knp++;
175
176 done:
177 return (0);
178
179 fail1:
180 DTRACE_PROBE1(fail1, int, rc);
181
182 return (rc);
183 }
184
185 static int
186 sfxge_mac_kstat_init(sfxge_t *sp)
187 {
188 sfxge_mac_t *smp = &(sp->s_mac);
189 dev_info_t *dip = sp->s_dip;
190 char name[MAXNAMELEN];
191 kstat_t *ksp;
192 kstat_named_t *knp;
193 unsigned int id;
194 int rc;
195
196 /* Create the set */
197 (void) snprintf(name, MAXNAMELEN - 1, "%s_mac", ddi_driver_name(dip));
198
199 if ((ksp = kstat_create((char *)ddi_driver_name(dip),
200 ddi_get_instance(dip), name, "mac", KSTAT_TYPE_NAMED,
201 EFX_MAC_NSTATS + 8, 0)) == NULL) {
202 rc = ENOMEM;
203 goto fail1;
204 }
205
206 smp->sm_ksp = ksp;
207
208 ksp->ks_update = sfxge_mac_kstat_update;
209 ksp->ks_private = smp;
210 ksp->ks_lock = &(smp->sm_lock);
211
212 /* Initialise the named stats */
213 smp->sm_stat = knp = ksp->ks_data;
214 for (id = 0; id < EFX_MAC_NSTATS; id++) {
215 kstat_named_init(knp, (char *)efx_mac_stat_name(sp->s_enp, id),
216 KSTAT_DATA_UINT64);
217 knp++;
218 }
219
220 kstat_named_init(knp++, "link_up", KSTAT_DATA_UINT64);
221 kstat_named_init(knp++, "link_speed", KSTAT_DATA_UINT64);
222 kstat_named_init(knp++, "link_duplex", KSTAT_DATA_UINT64);
223 kstat_named_init(knp++, "fcntl_generate", KSTAT_DATA_UINT64);
224 kstat_named_init(knp++, "fcntl_respond", KSTAT_DATA_UINT64);
225 kstat_named_init(knp++, "intr_moderation", KSTAT_DATA_UINT64);
226 kstat_named_init(knp++, "rx_coalesce_mode", KSTAT_DATA_UINT64);
227 kstat_named_init(knp++, "rx_scale_count", KSTAT_DATA_UINT64);
228
229 kstat_install(ksp);
230
231 return (0);
232
233 fail1:
234 DTRACE_PROBE1(fail1, int, rc);
235
236 return (rc);
237 }
238
239 static void
240 sfxge_mac_kstat_fini(sfxge_t *sp)
241 {
242 sfxge_mac_t *smp = &(sp->s_mac);
243
244 /* Destroy the set */
245 kstat_delete(smp->sm_ksp);
246 smp->sm_ksp = NULL;
247 smp->sm_stat = NULL;
248 }
249
250 void
251 sfxge_mac_stat_get(sfxge_t *sp, unsigned int id, uint64_t *valp)
252 {
253 sfxge_mac_t *smp = &(sp->s_mac);
254
255 /* Make sure the cached counter values are recent */
256 mutex_enter(&(smp->sm_lock));
257
258 if (smp->sm_state != SFXGE_MAC_STARTED)
259 goto done;
260
261 sfxge_mac_stat_update_quick(smp);
262
263 *valp = smp->sm_stat[id].value.ui64;
264
265 done:
266 mutex_exit(&(smp->sm_lock));
267 }
268
269 static void
270 sfxge_mac_poll(void *arg)
271 {
272 sfxge_t *sp = arg;
273 efx_nic_t *enp = sp->s_enp;
274 sfxge_mac_t *smp = &(sp->s_mac);
275 efsys_mem_t *esmp = &(smp->sm_mem);
276 efx_link_mode_t mode;
277 clock_t timeout;
278
279 mutex_enter(&(smp->sm_lock));
280 while (smp->sm_state == SFXGE_MAC_STARTED) {
281
282 /* clears smp->sm_mac_stats_pend if appropriate */
283 if (smp->sm_mac_stats_pend)
284 sfxge_mac_stat_update_wait(smp);
285
286 /* This may sleep waiting for MCDI completion */
287 mode = EFX_LINK_UNKNOWN;
288 if (efx_port_poll(enp, &mode) == 0)
289 sfxge_mac_link_update_locked(sp, mode);
290
291 if ((smp->sm_link_poll_reqd == B_FALSE) &&
292 (smp->sm_mac_stats_timer_reqd == B_FALSE))
293 goto done;
294
295 /* Zero the memory */
296 bzero(esmp->esm_base, EFX_MAC_STATS_SIZE);
297
298 /* Trigger upload the MAC statistics counters */
299 if (smp->sm_link_up &&
300 efx_mac_stats_upload(sp->s_enp, esmp) == 0)
301 smp->sm_mac_stats_pend = B_TRUE;
302
303 /* Wait for timeout or end of polling */
304 timeout = ddi_get_lbolt() + drv_usectohz(1000 *
305 SFXGE_MAC_POLL_PERIOD_MS);
306 while (smp->sm_state == SFXGE_MAC_STARTED) {
307 if (cv_timedwait(&(smp->sm_link_poll_kv),
308 &(smp->sm_lock), timeout) < 0) {
309 /* Timeout - poll if polling still enabled */
310 break;
311 }
312 }
313 }
314 done:
315 mutex_exit(&(smp->sm_lock));
316
317 }
318
319 static void
320 sfxge_mac_poll_start(sfxge_t *sp)
321 {
322 sfxge_mac_t *smp = &(sp->s_mac);
323
324 ASSERT(mutex_owned(&(smp->sm_lock)));
325 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
326
327 /* Schedule a poll */
328 (void) ddi_taskq_dispatch(smp->sm_tqp, sfxge_mac_poll, sp, DDI_SLEEP);
329 }
330
331 static void
332 sfxge_mac_poll_stop(sfxge_t *sp)
333 {
334 sfxge_mac_t *smp = &(sp->s_mac);
335
336 ASSERT(mutex_owned(&(smp->sm_lock)));
337 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
338
339 cv_broadcast(&(smp->sm_link_poll_kv));
340
341 /* Wait for link polling to cease */
342 mutex_exit(&(smp->sm_lock));
343 ddi_taskq_wait(smp->sm_tqp);
344 mutex_enter(&(smp->sm_lock));
345
346 /* Wait for any pending DMAed stats to complete */
347 sfxge_mac_stat_update_wait(smp);
348 }
349
350 int
351 sfxge_mac_init(sfxge_t *sp)
352 {
353 sfxge_mac_t *smp = &(sp->s_mac);
354 efsys_mem_t *esmp = &(smp->sm_mem);
355 dev_info_t *dip = sp->s_dip;
356 sfxge_dma_buffer_attr_t dma_attr;
357 const efx_nic_cfg_t *encp;
358 unsigned char *bytes;
359 unsigned int n;
360 int err, rc;
361
362 SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
363
364 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_UNINITIALIZED);
365
366 smp->sm_sp = sp;
367 encp = efx_nic_cfg_get(sp->s_enp);
368 smp->sm_link_poll_reqd = (~encp->enc_features &
369 EFX_FEATURE_LINK_EVENTS);
370 smp->sm_mac_stats_timer_reqd = (~encp->enc_features &
371 EFX_FEATURE_PERIODIC_MAC_STATS);
372
373 mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER,
374 DDI_INTR_PRI(sp->s_intr.si_intr_pri));
375 cv_init(&(smp->sm_link_poll_kv), NULL, CV_DRIVER, NULL);
376
377 /* Create link poll taskq */
378 smp->sm_tqp = ddi_taskq_create(dip, "mac_tq", 1, TASKQ_DEFAULTPRI, 0);
379 if (smp->sm_tqp == NULL) {
380 rc = ENOMEM;
381 goto fail1;
382 }
383
384 if ((rc = sfxge_phy_init(sp)) != 0)
385 goto fail2;
386
387 dma_attr.sdba_dip = dip;
388 dma_attr.sdba_dattrp = &sfxge_mac_dma_attr;
389 dma_attr.sdba_callback = DDI_DMA_SLEEP;
390 dma_attr.sdba_length = EFX_MAC_STATS_SIZE;
391 dma_attr.sdba_memflags = DDI_DMA_CONSISTENT;
392 dma_attr.sdba_devaccp = &sfxge_mac_devacc;
393 dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT;
394 dma_attr.sdba_maxcookies = 1;
395 dma_attr.sdba_zeroinit = B_TRUE;
396
397 if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
398 goto fail3;
399
400 /* Set the initial flow control values */
401 smp->sm_fcntl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
402
403 /*
404 * Determine the 'burnt-in' MAC address:
405 *
406 * A: if the "mac-address" property is set on our device node use that.
407 * B: otherwise, use the value from NVRAM.
408 */
409
410 /* A: property */
411 err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
412 "mac-address", &bytes, &n);
413 switch (err) {
414 case DDI_PROP_SUCCESS:
415 if (n == ETHERADDRL) {
416 bcopy(bytes, smp->sm_bia, ETHERADDRL);
417 goto done;
418 }
419
420 ddi_prop_free(bytes);
421 break;
422
423 default:
424 break;
425 }
426
427 /* B: NVRAM */
428 bcopy(encp->enc_mac_addr, smp->sm_bia, ETHERADDRL);
429
430 done:
431 /* Initialize the statistics */
432 if ((rc = sfxge_mac_kstat_init(sp)) != 0)
433 goto fail4;
434
435 if ((rc = sfxge_phy_kstat_init(sp)) != 0)
436 goto fail5;
437
438 smp->sm_state = SFXGE_MAC_INITIALIZED;
439
440 return (0);
441
442 fail5:
443 DTRACE_PROBE(fail5);
444
445 sfxge_mac_kstat_fini(sp);
446 fail4:
447 DTRACE_PROBE(fail4);
448
449 /* Tear down DMA setup */
450 sfxge_dma_buffer_destroy(esmp);
451 fail3:
452 DTRACE_PROBE(fail3);
453
454 sfxge_phy_fini(sp);
455 fail2:
456 DTRACE_PROBE(fail2);
457
458 /* Destroy the link poll taskq */
459 ddi_taskq_destroy(smp->sm_tqp);
460 smp->sm_tqp = NULL;
461
462 fail1:
463 DTRACE_PROBE1(fail1, int, rc);
464
465 cv_destroy(&(smp->sm_link_poll_kv));
466
467 mutex_destroy(&(smp->sm_lock));
468
469 smp->sm_sp = NULL;
470
471 SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
472
473 return (rc);
474 }
475
476 static int
477 sfxge_mac_filter_apply(sfxge_t *sp)
478 {
479 efx_nic_t *enp = sp->s_enp;
480 sfxge_mac_t *smp = &(sp->s_mac);
481 int rc;
482
483 ASSERT(mutex_owned(&(smp->sm_lock)));
484
485 if (smp->sm_state == SFXGE_MAC_STARTED) {
486 boolean_t all_unicst;
487 boolean_t mulcst;
488 boolean_t all_mulcst;
489 boolean_t brdcst;
490
491 all_unicst = (smp->sm_promisc == SFXGE_PROMISC_ALL_PHYS);
492 mulcst = (smp->sm_mcast_count > 0);
493 all_mulcst = (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI);
494 brdcst = B_TRUE;
495
496 if ((rc = efx_mac_filter_set(enp, all_unicst, mulcst,
497 all_mulcst, brdcst)) != 0) {
498 goto fail1;
499 }
500 if ((rc = efx_mac_multicast_list_set(enp,
501 smp->sm_mcast_addr, smp->sm_mcast_count)) != 0)
502 goto fail2;
503 }
504
505 return (0);
506
507 fail2:
508 DTRACE_PROBE(fail2);
509 fail1:
510 DTRACE_PROBE1(fail1, int, rc);
511
512 return (rc);
513 }
514
515 int
516 sfxge_mac_start(sfxge_t *sp, boolean_t restart)
517 {
518 sfxge_mac_t *smp = &(sp->s_mac);
519 efsys_mem_t *esmp = &(smp->sm_mem);
520 efx_nic_t *enp = sp->s_enp;
521 size_t pdu;
522 int rc;
523
524 mutex_enter(&(smp->sm_lock));
525
526 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
527
528 if ((rc = efx_port_init(enp)) != 0)
529 goto fail1;
530
531 /*
532 * Set up the advertised capabilities that may have been asked for
533 * before the call to efx_port_init().
534 */
535 if ((rc = sfxge_phy_cap_apply(sp, !restart)) != 0)
536 goto fail2;
537
538 /* Set the SDU */
539 pdu = EFX_MAC_PDU(sp->s_mtu);
540 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
541 goto fail3;
542
543 if ((rc = efx_mac_fcntl_set(enp, smp->sm_fcntl, B_TRUE)) != 0)
544 goto fail4;
545
546 /* Set the unicast address */
547 if ((rc = efx_mac_addr_set(enp, (smp->sm_laa_valid) ?
548 smp->sm_laa : smp->sm_bia)) != 0)
549 goto fail5;
550
551 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
552 goto fail6;
553
554 if (!smp->sm_mac_stats_timer_reqd) {
555 if ((rc = efx_mac_stats_periodic(enp, esmp,
556 SFXGE_MAC_POLL_PERIOD_MS, B_FALSE)) != 0)
557 goto fail7;
558 }
559
560 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
561 goto fail8;
562
563 smp->sm_state = SFXGE_MAC_STARTED;
564
565 /*
566 * Start link state polling. For hardware that reports link change
567 * events we still poll once to update the initial link state.
568 */
569 sfxge_mac_poll_start(sp);
570
571 mutex_exit(&(smp->sm_lock));
572 return (0);
573
574 fail8:
575 DTRACE_PROBE(fail8);
576 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
577 fail7:
578 DTRACE_PROBE(fail7);
579 fail6:
580 DTRACE_PROBE(fail6);
581 fail5:
582 DTRACE_PROBE(fail5);
583 fail4:
584 DTRACE_PROBE(fail4);
585 fail3:
586 DTRACE_PROBE(fail3);
587 fail2:
588 DTRACE_PROBE(fail2);
589 efx_port_fini(enp);
590 fail1:
591 DTRACE_PROBE1(fail1, int, rc);
592
593 mutex_exit(&(smp->sm_lock));
594
595 return (rc);
596 }
597
598
599 static void
600 sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode)
601 {
602 sfxge_mac_t *smp = &(sp->s_mac);
603 const char *change, *duplex;
604 char info[sizeof (": now 10000Mbps FULL duplex")];
605
606 ASSERT(mutex_owned(&(smp->sm_lock)));
607 if (smp->sm_state != SFXGE_MAC_STARTED)
608 return;
609
610 if (smp->sm_link_mode == mode)
611 return;
612
613 smp->sm_link_mode = mode;
614 smp->sm_link_up = B_TRUE;
615
616 switch (smp->sm_link_mode) {
617 case EFX_LINK_UNKNOWN:
618 case EFX_LINK_DOWN:
619 smp->sm_link_speed = 0;
620 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
621 smp->sm_link_up = B_FALSE;
622 break;
623
624 case EFX_LINK_10HDX:
625 case EFX_LINK_10FDX:
626 smp->sm_link_speed = 10;
627 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_10HDX) ?
628 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
629 break;
630
631 case EFX_LINK_100HDX:
632 case EFX_LINK_100FDX:
633 smp->sm_link_speed = 100;
634 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_100HDX) ?
635 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
636 break;
637
638 case EFX_LINK_1000HDX:
639 case EFX_LINK_1000FDX:
640 smp->sm_link_speed = 1000;
641 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_1000HDX) ?
642 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
643 break;
644
645 case EFX_LINK_10000FDX:
646 smp->sm_link_speed = 10000;
647 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
648 break;
649
650 case EFX_LINK_40000FDX:
651 smp->sm_link_speed = 40000;
652 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
653 break;
654
655 default:
656 ASSERT(B_FALSE);
657 break;
658 }
659
660 duplex = (smp->sm_link_duplex == SFXGE_LINK_DUPLEX_FULL) ?
661 "full" : "half";
662 change = (smp->sm_link_up) ? "UP" : "DOWN";
663 (void) snprintf(info, sizeof (info), ": now %dMbps %s duplex",
664 smp->sm_link_speed, duplex);
665
666 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "Link %s%s",
667 change, smp->sm_link_up ? info : "");
668
669 /* Push link state update to the OS */
670 sfxge_gld_link_update(sp);
671 }
672
673 void
674 sfxge_mac_link_update(sfxge_t *sp, efx_link_mode_t mode)
675 {
676 sfxge_mac_t *smp = &(sp->s_mac);
677
678 mutex_enter(&(smp->sm_lock));
679 sfxge_mac_link_update_locked(sp, mode);
680 mutex_exit(&(smp->sm_lock));
681 }
682
683 void
684 sfxge_mac_link_check(sfxge_t *sp, boolean_t *upp)
685 {
686 sfxge_mac_t *smp = &(sp->s_mac);
687
688 mutex_enter(&(smp->sm_lock));
689 *upp = smp->sm_link_up;
690 mutex_exit(&(smp->sm_lock));
691 }
692
693 void
694 sfxge_mac_link_speed_get(sfxge_t *sp, unsigned int *speedp)
695 {
696 sfxge_mac_t *smp = &(sp->s_mac);
697
698 mutex_enter(&(smp->sm_lock));
699 *speedp = smp->sm_link_speed;
700 mutex_exit(&(smp->sm_lock));
701 }
702
703 void
704 sfxge_mac_link_duplex_get(sfxge_t *sp, sfxge_link_duplex_t *duplexp)
705 {
706 sfxge_mac_t *smp = &(sp->s_mac);
707
708 mutex_enter(&(smp->sm_lock));
709 *duplexp = smp->sm_link_duplex;
710 mutex_exit(&(smp->sm_lock));
711 }
712
713 void
714 sfxge_mac_fcntl_get(sfxge_t *sp, unsigned int *fcntlp)
715 {
716 sfxge_mac_t *smp = &(sp->s_mac);
717
718 mutex_enter(&(smp->sm_lock));
719 *fcntlp = smp->sm_fcntl;
720 mutex_exit(&(smp->sm_lock));
721 }
722
723 int
724 sfxge_mac_fcntl_set(sfxge_t *sp, unsigned int fcntl)
725 {
726 sfxge_mac_t *smp = &(sp->s_mac);
727 int rc;
728
729 mutex_enter(&(smp->sm_lock));
730
731 if (smp->sm_fcntl == fcntl)
732 goto done;
733
734 smp->sm_fcntl = fcntl;
735
736 if (smp->sm_state != SFXGE_MAC_STARTED)
737 goto done;
738
739 if ((rc = efx_mac_fcntl_set(sp->s_enp, smp->sm_fcntl, B_TRUE)) != 0)
740 goto fail1;
741
742 done:
743 mutex_exit(&(smp->sm_lock));
744
745 return (0);
746
747 fail1:
748 DTRACE_PROBE1(fail1, int, rc);
749
750 mutex_exit(&(smp->sm_lock));
751
752 return (rc);
753 }
754
755 int
756 sfxge_mac_unicst_get(sfxge_t *sp, sfxge_unicst_type_t type, uint8_t *addr)
757 {
758 sfxge_mac_t *smp = &(sp->s_mac);
759 int rc;
760
761 if (type >= SFXGE_UNICST_NTYPES) {
762 rc = EINVAL;
763 goto fail1;
764 }
765
766 mutex_enter(&(smp->sm_lock));
767
768 if (smp->sm_state != SFXGE_MAC_INITIALIZED &&
769 smp->sm_state != SFXGE_MAC_STARTED) {
770 rc = EFAULT;
771 goto fail2;
772 }
773
774 switch (type) {
775 case SFXGE_UNICST_BIA:
776 bcopy(smp->sm_bia, addr, ETHERADDRL);
777 break;
778
779 case SFXGE_UNICST_LAA:
780 if (!(smp->sm_laa_valid)) {
781 rc = ENOENT;
782 goto fail3;
783 }
784
785 bcopy(smp->sm_laa, addr, ETHERADDRL);
786 break;
787
788 default:
789 ASSERT(B_FALSE);
790 break;
791 }
792
793 mutex_exit(&(smp->sm_lock));
794
795 return (0);
796
797
798 fail3:
799 DTRACE_PROBE(fail3);
800 fail2:
801 DTRACE_PROBE(fail2);
802
803 mutex_exit(&(smp->sm_lock));
804
805 fail1:
806 DTRACE_PROBE1(fail1, int, rc);
807
808 return (rc);
809 }
810
811 int
812 sfxge_mac_unicst_set(sfxge_t *sp, uint8_t *addr)
813 {
814 sfxge_mac_t *smp = &(sp->s_mac);
815 efx_nic_t *enp = sp->s_enp;
816 int rc;
817
818 mutex_enter(&(smp->sm_lock));
819
820 bcopy(addr, smp->sm_laa, ETHERADDRL);
821 smp->sm_laa_valid = B_TRUE;
822
823 if (smp->sm_state != SFXGE_MAC_STARTED)
824 goto done;
825
826 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0)
827 goto fail1;
828
829 done:
830 mutex_exit(&(smp->sm_lock));
831
832 return (0);
833
834 fail1:
835 DTRACE_PROBE1(fail1, int, rc);
836
837 mutex_exit(&(smp->sm_lock));
838
839 return (rc);
840 }
841
842 int
843 sfxge_mac_promisc_set(sfxge_t *sp, sfxge_promisc_type_t promisc)
844 {
845 sfxge_mac_t *smp = &(sp->s_mac);
846 int rc;
847
848 mutex_enter(&(smp->sm_lock));
849
850 if (smp->sm_promisc == promisc)
851 goto done;
852
853 smp->sm_promisc = promisc;
854
855 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
856 goto fail1;
857
858 done:
859 mutex_exit(&(smp->sm_lock));
860 return (0);
861
862 fail1:
863 DTRACE_PROBE1(fail1, int, rc);
864 mutex_exit(&(smp->sm_lock));
865
866 return (rc);
867 }
868
869 int
870 sfxge_mac_multicst_add(sfxge_t *sp, const uint8_t *addr)
871 {
872 sfxge_mac_t *smp = &(sp->s_mac);
873 int i;
874 int rc;
875
876 mutex_enter(&(smp->sm_lock));
877
878 /* Check if the address is already in the list */
879 i = 0;
880 while (i < smp->sm_mcast_count) {
881 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL),
882 addr, ETHERADDRL) == 0)
883 goto done;
884 else
885 i++;
886 }
887
888 /* Add to the list */
889 bcopy(addr, smp->sm_mcast_addr + (smp->sm_mcast_count++ * ETHERADDRL),
890 ETHERADDRL);
891
892 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
893 goto fail1;
894
895 done:
896 mutex_exit(&(smp->sm_lock));
897 return (0);
898
899 fail1:
900 DTRACE_PROBE1(fail1, int, rc);
901 mutex_exit(&(smp->sm_lock));
902
903 return (rc);
904 }
905
906 int
907 sfxge_mac_multicst_remove(sfxge_t *sp, const uint8_t *addr)
908 {
909 sfxge_mac_t *smp = &(sp->s_mac);
910 int i;
911 int rc;
912
913 mutex_enter(&(smp->sm_lock));
914
915 i = 0;
916 while (i < smp->sm_mcast_count) {
917 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL),
918 addr, ETHERADDRL) == 0) {
919 (void) memmove(smp->sm_mcast_addr + (i * ETHERADDRL),
920 smp->sm_mcast_addr + ((i + 1) * ETHERADDRL),
921 (smp->sm_mcast_count - (i + 1)) * ETHERADDRL);
922 smp->sm_mcast_count--;
923 } else
924 i++;
925 }
926
927 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
928 goto fail1;
929
930 mutex_exit(&(smp->sm_lock));
931 return (0);
932
933 fail1:
934 DTRACE_PROBE1(fail1, int, rc);
935 mutex_exit(&(smp->sm_lock));
936
937 return (rc);
938 }
939
940 void
941 sfxge_mac_stop(sfxge_t *sp)
942 {
943 sfxge_mac_t *smp = &(sp->s_mac);
944 efx_nic_t *enp = sp->s_enp;
945 efsys_mem_t *esmp = &(smp->sm_mem);
946
947 mutex_enter(&(smp->sm_lock));
948
949 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
950 ASSERT3P(smp->sm_sp, ==, sp);
951 smp->sm_state = SFXGE_MAC_INITIALIZED;
952
953 /* If stopping in response to an MC reboot this may fail */
954 if (!smp->sm_mac_stats_timer_reqd)
955 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
956
957 sfxge_mac_poll_stop(sp);
958
959 smp->sm_lbolt = 0;
960
961 smp->sm_link_up = B_FALSE;
962 smp->sm_link_speed = 0;
963 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
964
965 /* This may call MCDI */
966 (void) efx_mac_drain(enp, B_TRUE);
967
968 smp->sm_link_mode = EFX_LINK_UNKNOWN;
969
970 efx_port_fini(enp);
971
972 mutex_exit(&(smp->sm_lock));
973 }
974
975 void
976 sfxge_mac_fini(sfxge_t *sp)
977 {
978 sfxge_mac_t *smp = &(sp->s_mac);
979 efsys_mem_t *esmp = &(smp->sm_mem);
980
981 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
982 ASSERT3P(smp->sm_sp, ==, sp);
983
984 /* Tear down the statistics */
985 sfxge_phy_kstat_fini(sp);
986 sfxge_mac_kstat_fini(sp);
987
988 smp->sm_state = SFXGE_MAC_UNINITIALIZED;
989 smp->sm_link_mode = EFX_LINK_UNKNOWN;
990 smp->sm_promisc = SFXGE_PROMISC_OFF;
991
992 bzero(smp->sm_mcast_addr, SFXGE_MCAST_LIST_MAX * ETHERADDRL);
993 smp->sm_mcast_count = 0;
994
995 bzero(smp->sm_laa, ETHERADDRL);
996 smp->sm_laa_valid = B_FALSE;
997
998 bzero(smp->sm_bia, ETHERADDRL);
999
1000 smp->sm_fcntl = 0;
1001
1002 /* Finish with PHY DMA memory */
1003 sfxge_phy_fini(sp);
1004
1005 /* Teardown the DMA */
1006 sfxge_dma_buffer_destroy(esmp);
1007
1008 /* Destroy the link poll taskq */
1009 ddi_taskq_destroy(smp->sm_tqp);
1010 smp->sm_tqp = NULL;
1011
1012 mutex_destroy(&(smp->sm_lock));
1013
1014 smp->sm_sp = NULL;
1015
1016 SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
1017 }