1 /*
2 * Copyright (c) 2008-2016 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
_sfxge_mac_stat_update(sfxge_mac_t * smp,int tries,int delay_usec)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
sfxge_mac_stat_update_quick(sfxge_mac_t * smp)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
sfxge_mac_stat_update_wait(sfxge_mac_t * smp)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
sfxge_mac_kstat_update(kstat_t * ksp,int rw)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
sfxge_mac_kstat_init(sfxge_t * sp)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
sfxge_mac_kstat_fini(sfxge_t * sp)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
sfxge_mac_stat_get(sfxge_t * sp,unsigned int id,uint64_t * valp)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
sfxge_mac_poll(void * arg)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
sfxge_mac_poll_start(sfxge_t * sp)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
sfxge_mac_poll_stop(sfxge_t * sp)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 /* Collect the final statistics. */
347 sfxge_mac_stat_update_wait(smp);
348 }
349
350 int
sfxge_mac_init(sfxge_t * sp)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 return (rc);
472 }
473
474 static int
sfxge_mac_filter_apply(sfxge_t * sp)475 sfxge_mac_filter_apply(sfxge_t *sp)
476 {
477 efx_nic_t *enp = sp->s_enp;
478 sfxge_mac_t *smp = &(sp->s_mac);
479 int rc;
480
481 ASSERT(mutex_owned(&(smp->sm_lock)));
482
483 if (smp->sm_state == SFXGE_MAC_STARTED) {
484 boolean_t all_unicst;
485 boolean_t mulcst;
486 boolean_t all_mulcst;
487 boolean_t brdcst;
488
489 all_unicst = (smp->sm_promisc == SFXGE_PROMISC_ALL_PHYS);
490 mulcst = (smp->sm_mcast_count > 0);
491 all_mulcst = (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI);
492 brdcst = B_TRUE;
493
494 if ((rc = efx_mac_filter_set(enp, all_unicst, mulcst,
495 all_mulcst, brdcst)) != 0) {
496 goto fail1;
497 }
498 if ((rc = efx_mac_multicast_list_set(enp,
499 smp->sm_mcast_addr, smp->sm_mcast_count)) != 0)
500 goto fail2;
501 }
502
503 return (0);
504
505 fail2:
506 DTRACE_PROBE(fail2);
507 fail1:
508 DTRACE_PROBE1(fail1, int, rc);
509
510 return (rc);
511 }
512
513 int
sfxge_mac_start(sfxge_t * sp,boolean_t restart)514 sfxge_mac_start(sfxge_t *sp, boolean_t restart)
515 {
516 sfxge_mac_t *smp = &(sp->s_mac);
517 efsys_mem_t *esmp = &(smp->sm_mem);
518 efx_nic_t *enp = sp->s_enp;
519 size_t pdu;
520 int rc;
521
522 mutex_enter(&(smp->sm_lock));
523
524 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
525
526 if ((rc = efx_port_init(enp)) != 0)
527 goto fail1;
528
529 /*
530 * Set up the advertised capabilities that may have been asked for
531 * before the call to efx_port_init().
532 */
533 if ((rc = sfxge_phy_cap_apply(sp, !restart)) != 0)
534 goto fail2;
535
536 /* Set the SDU */
537 pdu = EFX_MAC_PDU(sp->s_mtu);
538 if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
539 goto fail3;
540
541 if ((rc = efx_mac_fcntl_set(enp, smp->sm_fcntl, B_TRUE)) != 0)
542 goto fail4;
543
544 /* Set the unicast address */
545 if ((rc = efx_mac_addr_set(enp, (smp->sm_laa_valid) ?
546 smp->sm_laa : smp->sm_bia)) != 0)
547 goto fail5;
548
549 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
550 goto fail6;
551
552 if (!smp->sm_mac_stats_timer_reqd) {
553 if ((rc = efx_mac_stats_periodic(enp, esmp,
554 SFXGE_MAC_POLL_PERIOD_MS, B_FALSE)) != 0)
555 goto fail7;
556 }
557
558 if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
559 goto fail8;
560
561 smp->sm_state = SFXGE_MAC_STARTED;
562
563 /*
564 * Start link state polling. For hardware that reports link change
565 * events we still poll once to update the initial link state.
566 */
567 sfxge_mac_poll_start(sp);
568
569 mutex_exit(&(smp->sm_lock));
570 return (0);
571
572 fail8:
573 DTRACE_PROBE(fail8);
574 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
575 fail7:
576 DTRACE_PROBE(fail7);
577 fail6:
578 DTRACE_PROBE(fail6);
579 fail5:
580 DTRACE_PROBE(fail5);
581 fail4:
582 DTRACE_PROBE(fail4);
583 fail3:
584 DTRACE_PROBE(fail3);
585 fail2:
586 DTRACE_PROBE(fail2);
587 efx_port_fini(enp);
588 fail1:
589 DTRACE_PROBE1(fail1, int, rc);
590
591 mutex_exit(&(smp->sm_lock));
592
593 return (rc);
594 }
595
596
597 static void
sfxge_mac_link_update_locked(sfxge_t * sp,efx_link_mode_t mode)598 sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode)
599 {
600 sfxge_mac_t *smp = &(sp->s_mac);
601 const char *change, *duplex;
602 char info[sizeof (": now 10000Mbps FULL duplex")];
603
604 ASSERT(mutex_owned(&(smp->sm_lock)));
605 if (smp->sm_state != SFXGE_MAC_STARTED)
606 return;
607
608 if (smp->sm_link_mode == mode)
609 return;
610
611 smp->sm_link_mode = mode;
612 smp->sm_link_up = B_TRUE;
613
614 switch (smp->sm_link_mode) {
615 case EFX_LINK_UNKNOWN:
616 case EFX_LINK_DOWN:
617 smp->sm_link_speed = 0;
618 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
619 smp->sm_link_up = B_FALSE;
620 break;
621
622 case EFX_LINK_10HDX:
623 case EFX_LINK_10FDX:
624 smp->sm_link_speed = 10;
625 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_10HDX) ?
626 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
627 break;
628
629 case EFX_LINK_100HDX:
630 case EFX_LINK_100FDX:
631 smp->sm_link_speed = 100;
632 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_100HDX) ?
633 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
634 break;
635
636 case EFX_LINK_1000HDX:
637 case EFX_LINK_1000FDX:
638 smp->sm_link_speed = 1000;
639 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_1000HDX) ?
640 SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
641 break;
642
643 case EFX_LINK_10000FDX:
644 smp->sm_link_speed = 10000;
645 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
646 break;
647
648 case EFX_LINK_40000FDX:
649 smp->sm_link_speed = 40000;
650 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
651 break;
652
653 default:
654 ASSERT(B_FALSE);
655 break;
656 }
657
658 duplex = (smp->sm_link_duplex == SFXGE_LINK_DUPLEX_FULL) ?
659 "full" : "half";
660 change = (smp->sm_link_up) ? "UP" : "DOWN";
661 (void) snprintf(info, sizeof (info), ": now %dMbps %s duplex",
662 smp->sm_link_speed, duplex);
663
664 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "Link %s%s",
665 change, smp->sm_link_up ? info : "");
666
667 /* Push link state update to the OS */
668 sfxge_gld_link_update(sp);
669 }
670
671 void
sfxge_mac_link_update(sfxge_t * sp,efx_link_mode_t mode)672 sfxge_mac_link_update(sfxge_t *sp, efx_link_mode_t mode)
673 {
674 sfxge_mac_t *smp = &(sp->s_mac);
675
676 mutex_enter(&(smp->sm_lock));
677 sfxge_mac_link_update_locked(sp, mode);
678 mutex_exit(&(smp->sm_lock));
679 }
680
681 void
sfxge_mac_link_check(sfxge_t * sp,boolean_t * upp)682 sfxge_mac_link_check(sfxge_t *sp, boolean_t *upp)
683 {
684 sfxge_mac_t *smp = &(sp->s_mac);
685
686 mutex_enter(&(smp->sm_lock));
687 *upp = smp->sm_link_up;
688 mutex_exit(&(smp->sm_lock));
689 }
690
691 void
sfxge_mac_link_speed_get(sfxge_t * sp,unsigned int * speedp)692 sfxge_mac_link_speed_get(sfxge_t *sp, unsigned int *speedp)
693 {
694 sfxge_mac_t *smp = &(sp->s_mac);
695
696 mutex_enter(&(smp->sm_lock));
697 *speedp = smp->sm_link_speed;
698 mutex_exit(&(smp->sm_lock));
699 }
700
701 void
sfxge_mac_link_duplex_get(sfxge_t * sp,sfxge_link_duplex_t * duplexp)702 sfxge_mac_link_duplex_get(sfxge_t *sp, sfxge_link_duplex_t *duplexp)
703 {
704 sfxge_mac_t *smp = &(sp->s_mac);
705
706 mutex_enter(&(smp->sm_lock));
707 *duplexp = smp->sm_link_duplex;
708 mutex_exit(&(smp->sm_lock));
709 }
710
711 void
sfxge_mac_fcntl_get(sfxge_t * sp,unsigned int * fcntlp)712 sfxge_mac_fcntl_get(sfxge_t *sp, unsigned int *fcntlp)
713 {
714 sfxge_mac_t *smp = &(sp->s_mac);
715
716 mutex_enter(&(smp->sm_lock));
717 *fcntlp = smp->sm_fcntl;
718 mutex_exit(&(smp->sm_lock));
719 }
720
721 int
sfxge_mac_fcntl_set(sfxge_t * sp,unsigned int fcntl)722 sfxge_mac_fcntl_set(sfxge_t *sp, unsigned int fcntl)
723 {
724 sfxge_mac_t *smp = &(sp->s_mac);
725 int rc;
726
727 mutex_enter(&(smp->sm_lock));
728
729 if (smp->sm_fcntl == fcntl)
730 goto done;
731
732 smp->sm_fcntl = fcntl;
733
734 if (smp->sm_state != SFXGE_MAC_STARTED)
735 goto done;
736
737 if ((rc = efx_mac_fcntl_set(sp->s_enp, smp->sm_fcntl, B_TRUE)) != 0)
738 goto fail1;
739
740 done:
741 mutex_exit(&(smp->sm_lock));
742
743 return (0);
744
745 fail1:
746 DTRACE_PROBE1(fail1, int, rc);
747
748 mutex_exit(&(smp->sm_lock));
749
750 return (rc);
751 }
752
753 int
sfxge_mac_unicst_get(sfxge_t * sp,sfxge_unicst_type_t type,uint8_t * addr)754 sfxge_mac_unicst_get(sfxge_t *sp, sfxge_unicst_type_t type, uint8_t *addr)
755 {
756 sfxge_mac_t *smp = &(sp->s_mac);
757 int rc;
758
759 if (type >= SFXGE_UNICST_NTYPES) {
760 rc = EINVAL;
761 goto fail1;
762 }
763
764 mutex_enter(&(smp->sm_lock));
765
766 if (smp->sm_state != SFXGE_MAC_INITIALIZED &&
767 smp->sm_state != SFXGE_MAC_STARTED) {
768 rc = EFAULT;
769 goto fail2;
770 }
771
772 switch (type) {
773 case SFXGE_UNICST_BIA:
774 bcopy(smp->sm_bia, addr, ETHERADDRL);
775 break;
776
777 case SFXGE_UNICST_LAA:
778 if (!(smp->sm_laa_valid)) {
779 rc = ENOENT;
780 goto fail3;
781 }
782
783 bcopy(smp->sm_laa, addr, ETHERADDRL);
784 break;
785
786 default:
787 ASSERT(B_FALSE);
788 break;
789 }
790
791 mutex_exit(&(smp->sm_lock));
792
793 return (0);
794
795
796 fail3:
797 DTRACE_PROBE(fail3);
798 fail2:
799 DTRACE_PROBE(fail2);
800
801 mutex_exit(&(smp->sm_lock));
802
803 fail1:
804 DTRACE_PROBE1(fail1, int, rc);
805
806 return (rc);
807 }
808
809 int
sfxge_mac_unicst_set(sfxge_t * sp,uint8_t * addr)810 sfxge_mac_unicst_set(sfxge_t *sp, uint8_t *addr)
811 {
812 sfxge_mac_t *smp = &(sp->s_mac);
813 efx_nic_t *enp = sp->s_enp;
814 boolean_t old_mac_valid;
815 uint8_t old_mac[ETHERADDRL];
816 int rc;
817
818 mutex_enter(&(smp->sm_lock));
819
820 old_mac_valid = smp->sm_laa_valid;
821 if (old_mac_valid)
822 bcopy(smp->sm_laa, old_mac, ETHERADDRL);
823
824 bcopy(addr, smp->sm_laa, ETHERADDRL);
825 smp->sm_laa_valid = B_TRUE;
826
827 if (smp->sm_state != SFXGE_MAC_STARTED)
828 goto done;
829
830 if (efx_nic_cfg_get(enp)->enc_allow_set_mac_with_installed_filters) {
831 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0) {
832 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR
833 "unable to set unicast MAC filter");
834 goto fail1;
835 }
836 } else {
837 /* Older EF10 firmware requires a device start */
838 mutex_exit(&smp->sm_lock);
839 sfxge_stop(sp);
840 if ((rc = sfxge_start(sp, B_TRUE)) != 0) {
841 dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR
842 "unable to restart with a new MAC");
843 mutex_enter(&(smp->sm_lock));
844 goto fail1;
845 }
846 mutex_enter(&smp->sm_lock);
847 }
848
849 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0)
850 goto fail1;
851
852 done:
853 mutex_exit(&(smp->sm_lock));
854
855 return (0);
856
857 fail1:
858 if (old_mac_valid)
859 bcopy(old_mac, smp->sm_laa, ETHERADDRL);
860 else
861 smp->sm_laa_valid = B_FALSE;
862
863 DTRACE_PROBE1(fail1, int, rc);
864
865 mutex_exit(&(smp->sm_lock));
866
867 return (rc);
868 }
869
870 int
sfxge_mac_promisc_set(sfxge_t * sp,sfxge_promisc_type_t promisc)871 sfxge_mac_promisc_set(sfxge_t *sp, sfxge_promisc_type_t promisc)
872 {
873 sfxge_mac_t *smp = &(sp->s_mac);
874 int rc;
875
876 mutex_enter(&(smp->sm_lock));
877
878 if (smp->sm_promisc == promisc)
879 goto done;
880
881 smp->sm_promisc = promisc;
882
883 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
884 goto fail1;
885
886 done:
887 mutex_exit(&(smp->sm_lock));
888 return (0);
889
890 fail1:
891 DTRACE_PROBE1(fail1, int, rc);
892 mutex_exit(&(smp->sm_lock));
893
894 return (rc);
895 }
896
897 int
sfxge_mac_multicst_add(sfxge_t * sp,const uint8_t * addr)898 sfxge_mac_multicst_add(sfxge_t *sp, const uint8_t *addr)
899 {
900 sfxge_mac_t *smp = &(sp->s_mac);
901 int i;
902 int rc;
903
904 mutex_enter(&(smp->sm_lock));
905
906 if ((addr[0] & 0x1) == 0) {
907 rc = EINVAL;
908 goto fail1;
909 }
910
911 /* Check if the address is already in the list */
912 i = 0;
913 while (i < smp->sm_mcast_count) {
914 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL),
915 addr, ETHERADDRL) == 0)
916 goto done;
917 else
918 i++;
919 }
920
921 if (smp->sm_mcast_count >= EFX_MAC_MULTICAST_LIST_MAX) {
922 rc = ENOENT;
923 goto fail1;
924 }
925
926 /* Add to the list */
927 bcopy(addr, smp->sm_mcast_addr + (smp->sm_mcast_count++ * ETHERADDRL),
928 ETHERADDRL);
929
930 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
931 goto fail2;
932
933 done:
934 mutex_exit(&(smp->sm_lock));
935 return (0);
936
937 fail2:
938 DTRACE_PROBE(fail2);
939 smp->sm_mcast_count--;
940 fail1:
941 DTRACE_PROBE1(fail1, int, rc);
942 mutex_exit(&(smp->sm_lock));
943
944 return (rc);
945 }
946
947 int
sfxge_mac_multicst_remove(sfxge_t * sp,const uint8_t * addr)948 sfxge_mac_multicst_remove(sfxge_t *sp, const uint8_t *addr)
949 {
950 sfxge_mac_t *smp = &(sp->s_mac);
951 int i;
952 int rc;
953
954 mutex_enter(&(smp->sm_lock));
955
956 i = 0;
957 while (i < smp->sm_mcast_count) {
958 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL),
959 addr, ETHERADDRL) == 0) {
960 (void) memmove(smp->sm_mcast_addr + (i * ETHERADDRL),
961 smp->sm_mcast_addr + ((i + 1) * ETHERADDRL),
962 (smp->sm_mcast_count - (i + 1)) * ETHERADDRL);
963 smp->sm_mcast_count--;
964 } else
965 i++;
966 }
967
968 if ((rc = sfxge_mac_filter_apply(sp)) != 0)
969 goto fail1;
970
971 mutex_exit(&(smp->sm_lock));
972 return (0);
973
974 fail1:
975 DTRACE_PROBE1(fail1, int, rc);
976 mutex_exit(&(smp->sm_lock));
977
978 return (rc);
979 }
980
981 void
sfxge_mac_stop(sfxge_t * sp)982 sfxge_mac_stop(sfxge_t *sp)
983 {
984 sfxge_mac_t *smp = &(sp->s_mac);
985 efx_nic_t *enp = sp->s_enp;
986 efsys_mem_t *esmp = &(smp->sm_mem);
987
988 mutex_enter(&(smp->sm_lock));
989
990 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
991 ASSERT3P(smp->sm_sp, ==, sp);
992 smp->sm_state = SFXGE_MAC_INITIALIZED;
993
994 /* If stopping in response to an MC reboot this may fail */
995 if (!smp->sm_mac_stats_timer_reqd)
996 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
997
998 sfxge_mac_poll_stop(sp);
999
1000 smp->sm_lbolt = 0;
1001
1002 smp->sm_link_up = B_FALSE;
1003 smp->sm_link_speed = 0;
1004 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
1005
1006 /* This may call MCDI */
1007 (void) efx_mac_drain(enp, B_TRUE);
1008
1009 smp->sm_link_mode = EFX_LINK_UNKNOWN;
1010
1011 efx_port_fini(enp);
1012
1013 mutex_exit(&(smp->sm_lock));
1014 }
1015
1016 void
sfxge_mac_fini(sfxge_t * sp)1017 sfxge_mac_fini(sfxge_t *sp)
1018 {
1019 sfxge_mac_t *smp = &(sp->s_mac);
1020 efsys_mem_t *esmp = &(smp->sm_mem);
1021
1022 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
1023 ASSERT3P(smp->sm_sp, ==, sp);
1024
1025 /* Tear down the statistics */
1026 sfxge_phy_kstat_fini(sp);
1027 sfxge_mac_kstat_fini(sp);
1028
1029 smp->sm_state = SFXGE_MAC_UNINITIALIZED;
1030 smp->sm_link_mode = EFX_LINK_UNKNOWN;
1031 smp->sm_promisc = SFXGE_PROMISC_OFF;
1032
1033 bzero(smp->sm_mcast_addr, sizeof (smp->sm_mcast_addr));
1034 smp->sm_mcast_count = 0;
1035
1036 bzero(smp->sm_laa, ETHERADDRL);
1037 smp->sm_laa_valid = B_FALSE;
1038
1039 bzero(smp->sm_bia, ETHERADDRL);
1040
1041 smp->sm_fcntl = 0;
1042
1043 /* Finish with PHY DMA memory */
1044 sfxge_phy_fini(sp);
1045
1046 /* Teardown the DMA */
1047 sfxge_dma_buffer_destroy(esmp);
1048
1049 /* Destroy the link poll taskq */
1050 ddi_taskq_destroy(smp->sm_tqp);
1051 smp->sm_tqp = NULL;
1052
1053 mutex_destroy(&(smp->sm_lock));
1054
1055 smp->sm_sp = NULL;
1056 }
1057