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 * This file is part of the Chelsio T4 support code.
14 *
15 * Copyright (C) 2010-2013 Chelsio Communications. All rights reserved.
16 *
17 * This program is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
20 * release for licensing terms and conditions.
21 */
22
23 /*
24 * Copyright 2020 RackTop Systems, Inc.
25 * Copyright 2025 Oxide Computer Company
26 */
27
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
30 #include <sys/dlpi.h>
31 #include <sys/mac_provider.h>
32 #include <sys/mac_ether.h>
33 #include <sys/strsubr.h>
34 #include <sys/queue.h>
35
36 #include "common/common.h"
37 #include "common/t4_regs.h"
38
39 static int t4_mc_getstat(void *arg, uint_t stat, uint64_t *val);
40 static int t4_mc_start(void *arg);
41 static void t4_mc_stop(void *arg);
42 static int t4_mc_setpromisc(void *arg, boolean_t on);
43 static int t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr);
44 static int t4_mc_unicst(void *arg, const uint8_t *ucaddr);
45 static boolean_t t4_mc_getcapab(void *arg, mac_capab_t cap, void *data);
46 static int t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id,
47 uint_t size, const void *val);
48 static int t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id,
49 uint_t size, void *val);
50 static void t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
51 mac_prop_info_handle_t ph);
52
53 static int t4_init_synchronized(struct port_info *pi);
54 static int t4_uninit_synchronized(struct port_info *pi);
55 static void t4_propinfo_priv(struct port_info *, const char *,
56 mac_prop_info_handle_t);
57 static int t4_getprop_priv(struct port_info *, const char *, uint_t, void *);
58 static int t4_setprop_priv(struct port_info *, const char *, const void *);
59
60 mac_callbacks_t t4_m_callbacks = {
61 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES,
62 .mc_getstat = t4_mc_getstat,
63 .mc_start = t4_mc_start,
64 .mc_stop = t4_mc_stop,
65 .mc_setpromisc = t4_mc_setpromisc,
66 .mc_multicst = t4_mc_multicst,
67 .mc_unicst = t4_mc_unicst,
68 .mc_tx = t4_mc_tx,
69 .mc_getcapab = t4_mc_getcapab,
70 .mc_setprop = t4_mc_setprop,
71 .mc_getprop = t4_mc_getprop,
72 .mc_propinfo = t4_mc_propinfo,
73 };
74
75 mac_callbacks_t t4_m_ring_callbacks = {
76 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES,
77 .mc_getstat = t4_mc_getstat,
78 .mc_start = t4_mc_start,
79 .mc_stop = t4_mc_stop,
80 .mc_setpromisc = t4_mc_setpromisc,
81 .mc_multicst = t4_mc_multicst,
82 .mc_unicst = NULL, /* t4_addmac */
83 .mc_tx = NULL, /* t4_eth_tx */
84 .mc_getcapab = t4_mc_getcapab,
85 .mc_setprop = t4_mc_setprop,
86 .mc_getprop = t4_mc_getprop,
87 .mc_propinfo = t4_mc_propinfo,
88 };
89
90 typedef enum t4_prop_id {
91 T4PROP_FW_TMR,
92 T4PROP_FW_PKTC,
93 T4PROP_RX_TMR,
94 T4PROP_RX_PKTC,
95 T4PROP_TX_TMR,
96 T4PROP_HW_CSUM,
97 T4PROP_HW_LSO,
98 T4PROP_RX_PAUSE,
99 T4PROP_TX_PAUSE,
100 } t4_prop_id_t;
101
102 typedef struct t4_priv_prop {
103 const char *tpp_name;
104 t4_prop_id_t tpp_id;
105 bool tpp_is_bool;
106 } t4_priv_prop_t;
107
108 static const t4_priv_prop_t t4_priv_props[] = {
109 /*
110 * Because there is a single FWQ for the entire NIC, all ports will be
111 * impacted by changes to these properties.
112 */
113 { "_fw_coalesce_timer_us", T4PROP_FW_TMR },
114 { "_fw_coalesce_count", T4PROP_FW_PKTC },
115
116 { "_rx_coalesce_timer_us", T4PROP_RX_TMR },
117 { "_rx_coalesce_count", T4PROP_RX_PKTC },
118 { "_tx_reclaim_timer_us", T4PROP_TX_TMR },
119 { "_hw_csum", T4PROP_HW_CSUM, true },
120 { "_hw_lso", T4PROP_HW_LSO, true },
121 { "_rx_pause", T4PROP_RX_PAUSE, true },
122 { "_tx_pause", T4PROP_TX_PAUSE, true },
123 };
124
125 static const t4_priv_prop_t *
t4_priv_prop_match(const char * name)126 t4_priv_prop_match(const char *name)
127 {
128 for (uint_t i = 0; i < ARRAY_SIZE(t4_priv_props); i++) {
129 const t4_priv_prop_t *prop = &t4_priv_props[i];
130 if (strcmp(prop->tpp_name, name) == 0) {
131 return (prop);
132 }
133 }
134 return (NULL);
135 }
136
137 static bool
t4_priv_prop_supported(struct port_info * pi,const t4_priv_prop_t * prop)138 t4_priv_prop_supported(struct port_info *pi, const t4_priv_prop_t *prop)
139 {
140 struct adapter *sc = pi->adapter;
141
142 switch (prop->tpp_id) {
143 case T4PROP_TX_TMR:
144 return ((sc->flags & TAF_DBQ_TIMER) != 0);
145
146 default:
147 return (true);
148 }
149 }
150
151 const char **
t4_get_priv_props(struct port_info * pi,size_t * alloc_sz)152 t4_get_priv_props(struct port_info *pi, size_t *alloc_sz)
153 {
154 /*
155 * Just alloc for all possible options, skipping those which are not
156 * supported (and appending extra NULLs).
157 */
158 const size_t sz = (ARRAY_SIZE(t4_priv_props) + 1) * sizeof (char *);
159 const char **out = kmem_zalloc(sz, KM_SLEEP);
160
161 uint_t filled = 0;
162 for (uint_t i = 0; i < ARRAY_SIZE(t4_priv_props); i++) {
163 if (t4_priv_prop_supported(pi, &t4_priv_props[i])) {
164 out[filled++] = t4_priv_props[i].tpp_name;
165 }
166 }
167
168 *alloc_sz = sz;
169 return (out);
170 }
171
172 /*
173 * To determine the actual Ethernet mode that we're in we need to look at the
174 * port type. That will tell us whether we're using a BASE-T PHY, have an
175 * external SFP connection whose module type we also need to use to qualify
176 * this, and then the link speed itself. Combining that tuple we can then get
177 * the current media.
178 *
179 * Our tables below assume we have gotten it down so the last thing we need to
180 * consider is a single speed. If port types end up supporting the same class of
181 * transceiver at a given speed, then this will need to be changed to use
182 * additional information to disambiguate that (which will require additional
183 * logic from the firmware).
184 */
185 typedef struct {
186 fw_port_cap32_t tmm_speed;
187 mac_ether_media_t tmm_ether;
188 } t4nex_media_map_t;
189
190 static const t4nex_media_map_t t4nex_map_baset[] = {
191 /*
192 * We're assuming that the 100 Mb/s mode is 100BASE-TX. It's hard to say
193 * for certain what the phy would have done, but given the rest of the
194 * market, that seems the most likely one.
195 */
196 { FW_PORT_CAP32_SPEED_100M, ETHER_MEDIA_100BASE_TX },
197 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_T },
198 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_T }
199 };
200
201 static const t4nex_media_map_t t4nex_map_kx[] = {
202 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
203 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KX4 }
204 };
205
206 static const t4nex_media_map_t t4nex_map_cx[] = {
207 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CX4 }
208 };
209
210 static const t4nex_media_map_t t4nex_map_kr[] = {
211 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
212 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KR },
213 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_KR },
214 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_KR4 },
215 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_KR2 },
216 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_KR4 },
217 };
218
219 static const t4nex_media_map_t t4nex_map_lr[] = {
220 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_LX },
221 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LR },
222 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_LR },
223 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_LR4 },
224 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_LR2 },
225 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_LR4 },
226 };
227
228 static const t4nex_media_map_t t4nex_map_sr[] = {
229 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_SX },
230 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_SR },
231 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_SR },
232 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_SR4 },
233 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_SR2 },
234 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_SR4 },
235 };
236
237 static const t4nex_media_map_t t4nex_map_er[] = {
238 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ER },
239 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ER },
240 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ER4 },
241 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ER4 },
242 };
243
244 static const t4nex_media_map_t t4nex_map_cr[] = {
245 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
246 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CR },
247 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_CR },
248 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_CR4 },
249 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_CR2 },
250 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_CR4 },
251 };
252
253 static const t4nex_media_map_t t4nex_map_acc[] = {
254 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
255 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ACC },
256 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ACC },
257 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ACC4 },
258 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_ACC2 },
259 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ACC4 },
260 };
261
262 static const t4nex_media_map_t t4nex_map_lrm[] = {
263 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LRM },
264 };
265
266 static mac_ether_media_t
t4_port_to_media(struct port_info * pi)267 t4_port_to_media(struct port_info *pi)
268 {
269 fw_port_cap32_t speed;
270 struct link_config *lc = &pi->link_cfg;
271 const t4nex_media_map_t *map = NULL;
272 size_t count = 0;
273
274 if (lc->link_ok != 0) {
275 speed = t4_link_fwcap_to_fwspeed(lc->link_caps);
276 } else {
277 return (ETHER_MEDIA_UNKNOWN);
278 }
279
280 switch (pi->port_type) {
281 case FW_PORT_TYPE_FIBER_XFI:
282 case FW_PORT_TYPE_FIBER_XAUI:
283 case FW_PORT_TYPE_SFP:
284 case FW_PORT_TYPE_QSFP_10G:
285 case FW_PORT_TYPE_QSA:
286 case FW_PORT_TYPE_QSFP:
287 case FW_PORT_TYPE_CR4_QSFP:
288 case FW_PORT_TYPE_CR_QSFP:
289 case FW_PORT_TYPE_CR2_QSFP:
290 case FW_PORT_TYPE_SFP28:
291 switch (pi->mod_type) {
292 case FW_PORT_MOD_TYPE_LR:
293 map = t4nex_map_lr;
294 count = ARRAY_SIZE(t4nex_map_lr);
295 break;
296 case FW_PORT_MOD_TYPE_SR:
297 map = t4nex_map_sr;
298 count = ARRAY_SIZE(t4nex_map_sr);
299 break;
300 case FW_PORT_MOD_TYPE_ER:
301 map = t4nex_map_er;
302 count = ARRAY_SIZE(t4nex_map_er);
303 break;
304 case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
305 map = t4nex_map_cr;
306 count = ARRAY_SIZE(t4nex_map_cr);
307 break;
308 case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
309 map = t4nex_map_acc;
310 count = ARRAY_SIZE(t4nex_map_acc);
311 break;
312 case FW_PORT_MOD_TYPE_LRM:
313 map = t4nex_map_lrm;
314 count = ARRAY_SIZE(t4nex_map_lrm);
315 break;
316 case FW_PORT_MOD_TYPE_ERROR:
317 case FW_PORT_MOD_TYPE_UNKNOWN:
318 case FW_PORT_MOD_TYPE_NOTSUPPORTED:
319 case FW_PORT_MOD_TYPE_NONE:
320 case FW_PORT_MOD_TYPE_NA:
321 default:
322 break;
323 }
324 break;
325 case FW_PORT_TYPE_KX4:
326 case FW_PORT_TYPE_KX:
327 map = t4nex_map_kx;
328 count = ARRAY_SIZE(t4nex_map_kx);
329 break;
330 case FW_PORT_TYPE_CX4:
331 map = t4nex_map_cx;
332 count = ARRAY_SIZE(t4nex_map_cx);
333 break;
334 case FW_PORT_TYPE_KR:
335 case FW_PORT_TYPE_BP_AP:
336 case FW_PORT_TYPE_BP4_AP:
337 case FW_PORT_TYPE_BP40_BA:
338 case FW_PORT_TYPE_KR4_100G:
339 case FW_PORT_TYPE_KR_SFP28:
340 case FW_PORT_TYPE_KR_XLAUI:
341 map = t4nex_map_kr;
342 count = ARRAY_SIZE(t4nex_map_kr);
343 break;
344 case FW_PORT_TYPE_BT_SGMII:
345 case FW_PORT_TYPE_BT_XFI:
346 case FW_PORT_TYPE_BT_XAUI:
347 map = t4nex_map_baset;
348 count = ARRAY_SIZE(t4nex_map_baset);
349 break;
350 case FW_PORT_TYPE_NONE:
351 default:
352 break;
353 }
354
355 for (size_t i = 0; i < count; i++) {
356 if (map[i].tmm_speed == speed) {
357 return (map[i].tmm_ether);
358 }
359 }
360
361 /*
362 * At this point we return unknown as we already checked for a down link
363 * earlier.
364 */
365 return (ETHER_MEDIA_UNKNOWN);
366 }
367
368 static int
t4_mc_getstat(void * arg,uint_t stat,uint64_t * val)369 t4_mc_getstat(void *arg, uint_t stat, uint64_t *val)
370 {
371 struct port_info *pi = arg;
372 struct adapter *sc = pi->adapter;
373 struct link_config *lc = &pi->link_cfg;
374
375 #define GET_STAT(name) \
376 t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
377
378 switch (stat) {
379 case MAC_STAT_IFSPEED:
380 if (lc->link_ok != 0) {
381 *val = t4_link_fwcap_to_speed(lc->link_caps);
382 *val *= 1000000;
383 } else
384 *val = 0;
385 break;
386
387 case MAC_STAT_MULTIRCV:
388 *val = GET_STAT(RX_PORT_MCAST);
389 break;
390
391 case MAC_STAT_BRDCSTRCV:
392 *val = GET_STAT(RX_PORT_BCAST);
393 break;
394
395 case MAC_STAT_MULTIXMT:
396 *val = GET_STAT(TX_PORT_MCAST);
397 break;
398
399 case MAC_STAT_BRDCSTXMT:
400 *val = GET_STAT(TX_PORT_BCAST);
401 break;
402
403 case MAC_STAT_NORCVBUF:
404 *val = 0; /* TODO should come from rxq->nomem */
405 break;
406
407 case MAC_STAT_IERRORS:
408 *val = GET_STAT(RX_PORT_MTU_ERROR) +
409 GET_STAT(RX_PORT_MTU_CRC_ERROR) +
410 GET_STAT(RX_PORT_CRC_ERROR) +
411 GET_STAT(RX_PORT_LEN_ERROR) +
412 GET_STAT(RX_PORT_SYM_ERROR) +
413 GET_STAT(RX_PORT_LESS_64B);
414 break;
415
416 case MAC_STAT_UNKNOWNS:
417 return (ENOTSUP);
418
419 case MAC_STAT_NOXMTBUF:
420 *val = GET_STAT(TX_PORT_DROP);
421 break;
422
423 case MAC_STAT_OERRORS:
424 *val = GET_STAT(TX_PORT_ERROR);
425 break;
426
427 case MAC_STAT_COLLISIONS:
428 return (ENOTSUP);
429
430 case MAC_STAT_RBYTES:
431 *val = GET_STAT(RX_PORT_BYTES);
432 break;
433
434 case MAC_STAT_IPACKETS:
435 *val = GET_STAT(RX_PORT_FRAMES);
436 break;
437
438 case MAC_STAT_OBYTES:
439 *val = GET_STAT(TX_PORT_BYTES);
440 break;
441
442 case MAC_STAT_OPACKETS:
443 *val = GET_STAT(TX_PORT_FRAMES);
444 break;
445
446 case ETHER_STAT_ALIGN_ERRORS:
447 return (ENOTSUP);
448
449 case ETHER_STAT_FCS_ERRORS:
450 *val = GET_STAT(RX_PORT_CRC_ERROR);
451 break;
452
453 case ETHER_STAT_FIRST_COLLISIONS:
454 case ETHER_STAT_MULTI_COLLISIONS:
455 case ETHER_STAT_SQE_ERRORS:
456 case ETHER_STAT_DEFER_XMTS:
457 case ETHER_STAT_TX_LATE_COLLISIONS:
458 case ETHER_STAT_EX_COLLISIONS:
459 return (ENOTSUP);
460
461 case ETHER_STAT_MACXMT_ERRORS:
462 *val = GET_STAT(TX_PORT_ERROR);
463 break;
464
465 case ETHER_STAT_CARRIER_ERRORS:
466 return (ENOTSUP);
467
468 case ETHER_STAT_TOOLONG_ERRORS:
469 *val = GET_STAT(RX_PORT_MTU_ERROR);
470 break;
471
472 case ETHER_STAT_MACRCV_ERRORS:
473 *val = GET_STAT(RX_PORT_MTU_ERROR) +
474 GET_STAT(RX_PORT_MTU_CRC_ERROR) +
475 GET_STAT(RX_PORT_CRC_ERROR) +
476 GET_STAT(RX_PORT_LEN_ERROR) +
477 GET_STAT(RX_PORT_SYM_ERROR) +
478 GET_STAT(RX_PORT_LESS_64B);
479 break;
480
481 case ETHER_STAT_XCVR_ADDR:
482 case ETHER_STAT_XCVR_ID:
483 return (ENOTSUP);
484 case ETHER_STAT_XCVR_INUSE:
485 *val = t4_port_to_media(pi);
486 break;
487
488 case ETHER_STAT_CAP_100GFDX:
489 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G);
490 break;
491
492 case ETHER_STAT_CAP_50GFDX:
493 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_50G);
494 break;
495
496 case ETHER_STAT_CAP_40GFDX:
497 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
498 break;
499
500 case ETHER_STAT_CAP_25GFDX:
501 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
502 break;
503
504 case ETHER_STAT_CAP_10GFDX:
505 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
506 break;
507
508 case ETHER_STAT_CAP_1000FDX:
509 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
510 break;
511
512 case ETHER_STAT_CAP_100FDX:
513 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
514 break;
515
516 case ETHER_STAT_CAP_1000HDX:
517 case ETHER_STAT_CAP_100HDX:
518 case ETHER_STAT_CAP_10FDX:
519 case ETHER_STAT_CAP_10HDX:
520 return (ENOTSUP);
521
522 case ETHER_STAT_CAP_ASMPAUSE:
523 *val = !!(lc->pcaps & FW_PORT_CAP32_FC_RX);
524 break;
525
526 case ETHER_STAT_CAP_PAUSE:
527 *val = !!(lc->pcaps & FW_PORT_CAP32_FC_TX);
528 break;
529
530 case ETHER_STAT_CAP_AUTONEG:
531 *val = !!(lc->pcaps & FW_PORT_CAP32_ANEG);
532 break;
533
534 /*
535 * We have set flow control configuration based on tx_pause and rx_pause
536 * values supported through ndd. Now, we need to translate the settings
537 * we have in link_config structure to adv_cap_asmpause and
538 * adv_cap_pause.
539 *
540 * There are 4 combinations possible and the translation is as below:
541 * tx_pause = 0 => We don't send pause frames during Rx congestion
542 * tx_pause = 1 => We send pause frames during Rx congestion
543 * rx_pause = 0 => We ignore received pause frames
544 * rx_pause = 1 => We pause transmission when we receive pause frames
545 *
546 * +----------------------------+----------------------------------+
547 * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause |
548 * +-------------------------+-------------------------------------+
549 * | 0 | 0 | 0 | 0 |
550 * | 0 | 1 | 1 | 0 |
551 * | 1 | 0 | 1 | 1 |
552 * | 1 | 1 | 0 | 1 |
553 * +----------------------------+----------------------------------+
554 */
555
556 /* Advertised asymmetric pause capability */
557 case ETHER_STAT_ADV_CAP_ASMPAUSE:
558 if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
559 *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_ASM_DIR);
560 else
561 *val = (!!(lc->admin_caps & FW_PORT_CAP32_FC_TX)) ^
562 (!!(lc->admin_caps & FW_PORT_CAP32_FC_RX));
563 break;
564
565 /* Advertised pause capability */
566 case ETHER_STAT_ADV_CAP_PAUSE:
567 if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
568 *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_PAUSE);
569 else
570 *val = !!(lc->admin_caps & FW_PORT_CAP32_FC_TX);
571 break;
572
573 case ETHER_STAT_ADV_CAP_100GFDX:
574 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
575 break;
576
577 case ETHER_STAT_ADV_CAP_50GFDX:
578 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
579 break;
580
581 case ETHER_STAT_ADV_CAP_40GFDX:
582 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
583 break;
584
585 case ETHER_STAT_ADV_CAP_25GFDX:
586 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
587 break;
588
589 case ETHER_STAT_ADV_CAP_10GFDX:
590 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
591 break;
592
593 case ETHER_STAT_ADV_CAP_1000FDX:
594 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
595 break;
596
597 case ETHER_STAT_ADV_CAP_100FDX:
598 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
599 break;
600
601 case ETHER_STAT_ADV_CAP_AUTONEG:
602 *val = !!(lc->admin_caps & FW_PORT_CAP32_ANEG);
603 break;
604
605 case ETHER_STAT_ADV_CAP_1000HDX:
606 case ETHER_STAT_ADV_CAP_100HDX:
607 case ETHER_STAT_ADV_CAP_10FDX:
608 case ETHER_STAT_ADV_CAP_10HDX:
609 return (ENOTSUP); /* TODO */
610
611 case ETHER_STAT_LP_CAP_ASMPAUSE:
612 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
613 return (ENOTSUP);
614
615 if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
616 *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_ASM_DIR);
617 else
618 *val = (!!(lc->lpacaps & FW_PORT_CAP32_FC_TX)) ^
619 (!!(lc->lpacaps & FW_PORT_CAP32_FC_RX));
620 break;
621
622 case ETHER_STAT_LP_CAP_PAUSE:
623 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
624 return (ENOTSUP);
625
626 if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
627 *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_PAUSE);
628 else
629 *val = !!(lc->lpacaps & FW_PORT_CAP32_FC_TX);
630 break;
631
632 case ETHER_STAT_LP_CAP_100GFDX:
633 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
634 return (ENOTSUP);
635
636 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100G);
637 break;
638
639 case ETHER_STAT_LP_CAP_50GFDX:
640 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
641 return (ENOTSUP);
642
643 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_50G);
644 break;
645
646 case ETHER_STAT_LP_CAP_40GFDX:
647 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
648 return (ENOTSUP);
649
650 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_40G);
651 break;
652
653 case ETHER_STAT_LP_CAP_25GFDX:
654 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
655 return (ENOTSUP);
656
657 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_25G);
658 break;
659
660 case ETHER_STAT_LP_CAP_10GFDX:
661 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
662 return (ENOTSUP);
663
664 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_10G);
665 break;
666
667 case ETHER_STAT_LP_CAP_1000FDX:
668 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
669 return (ENOTSUP);
670
671 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_1G);
672 break;
673
674 case ETHER_STAT_LP_CAP_100FDX:
675 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
676 return (ENOTSUP);
677
678 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100M);
679 break;
680
681 case ETHER_STAT_LP_CAP_AUTONEG:
682 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
683 return (ENOTSUP);
684
685 *val = !!(lc->lpacaps & FW_PORT_CAP32_ANEG);
686 break;
687
688 case ETHER_STAT_LP_CAP_1000HDX:
689 case ETHER_STAT_LP_CAP_100HDX:
690 case ETHER_STAT_LP_CAP_10FDX:
691 case ETHER_STAT_LP_CAP_10HDX:
692 return (ENOTSUP);
693
694 case ETHER_STAT_LINK_ASMPAUSE:
695 *val = (!!(lc->link_caps & FW_PORT_CAP32_FC_TX)) ^
696 (!!(lc->link_caps & FW_PORT_CAP32_FC_RX));
697 break;
698
699 case ETHER_STAT_LINK_PAUSE:
700 *val = !!(lc->link_caps & FW_PORT_CAP32_FC_TX);
701 break;
702
703 case ETHER_STAT_LINK_AUTONEG:
704 *val = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
705 break;
706
707 case ETHER_STAT_LINK_DUPLEX:
708 if (lc->link_ok != 0)
709 *val = LINK_DUPLEX_FULL;
710 else
711 *val = LINK_DUPLEX_UNKNOWN;
712 break;
713
714 default:
715 return (ENOTSUP);
716 }
717 #undef GET_STAT
718
719 return (0);
720 }
721
722 static int
t4_mc_start(void * arg)723 t4_mc_start(void *arg)
724 {
725 struct port_info *pi = arg;
726
727 ADAPTER_LOCK(pi->adapter);
728 const int rc = t4_init_synchronized(pi);
729 ADAPTER_UNLOCK(pi->adapter);
730
731 return (rc);
732 }
733
734 static void
t4_mc_stop(void * arg)735 t4_mc_stop(void *arg)
736 {
737 struct port_info *pi = arg;
738
739 ADAPTER_LOCK(pi->adapter);
740 (void) t4_uninit_synchronized(pi);
741 ADAPTER_UNLOCK(pi->adapter);
742 }
743
744 static int
t4_mc_setpromisc(void * arg,boolean_t on)745 t4_mc_setpromisc(void *arg, boolean_t on)
746 {
747 struct port_info *pi = arg;
748 struct adapter *sc = pi->adapter;
749 int rc;
750
751 ADAPTER_LOCK(sc);
752 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
753 false);
754 ADAPTER_UNLOCK(sc);
755
756 return (rc);
757 }
758
759 /*
760 * TODO: Starts failing as soon as the 336 entry table fills up. Need to use
761 * hash in that case.
762 */
763 static int
t4_mc_multicst(void * arg,boolean_t add,const uint8_t * mcaddr)764 t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
765 {
766 struct port_info *pi = arg;
767 struct adapter *sc = pi->adapter;
768 struct fw_vi_mac_cmd c;
769 int len16, rc;
770
771 len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
772 sizeof (c.u.exact[0]), 16);
773 c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
774 F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
775 c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
776 c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
777 V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
778 FW_VI_MAC_MAC_BASED_FREE));
779 bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
780
781 ADAPTER_LOCK(sc);
782 rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
783 ADAPTER_UNLOCK(sc);
784 if (rc != 0)
785 return (rc);
786 #ifdef DEBUG
787 /*
788 * TODO: Firmware doesn't seem to return the correct index on removal
789 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
790 * code once it is fixed.
791 */
792 else {
793 uint16_t idx;
794
795 idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
796 cxgb_printf(pi->dip, CE_NOTE,
797 "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
798 mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
799 add ? "added at index" : "removed from index", idx);
800 }
801 #endif
802
803 return (0);
804 }
805
806 int
t4_mc_unicst(void * arg,const uint8_t * ucaddr)807 t4_mc_unicst(void *arg, const uint8_t *ucaddr)
808 {
809 struct port_info *pi = arg;
810 struct adapter *sc = pi->adapter;
811 int rc;
812
813 if (ucaddr == NULL)
814 return (EINVAL);
815
816 ADAPTER_LOCK(sc);
817
818 /* We will support adding only one mac address */
819 if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
820 ADAPTER_UNLOCK(sc);
821 return (ENOSPC);
822 }
823 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
824 true, &pi->smt_idx);
825 if (rc < 0) {
826 rc = -rc;
827 } else {
828 pi->macaddr_cnt++;
829 pi->xact_addr_filt = rc;
830 rc = 0;
831 }
832 ADAPTER_UNLOCK(sc);
833
834 return (rc);
835 }
836
837 int
t4_addmac(void * arg,const uint8_t * ucaddr)838 t4_addmac(void *arg, const uint8_t *ucaddr)
839 {
840 return (t4_mc_unicst(arg, ucaddr));
841 }
842
843 static int
t4_remmac(void * arg,const uint8_t * mac_addr)844 t4_remmac(void *arg, const uint8_t *mac_addr)
845 {
846 struct port_info *pi = arg;
847
848 ADAPTER_LOCK(pi->adapter);
849 pi->macaddr_cnt--;
850 ADAPTER_UNLOCK(pi->adapter);
851
852 return (0);
853 }
854
855 /*
856 * Callback funtion for MAC layer to register all groups.
857 */
858 void
t4_fill_group(void * arg,mac_ring_type_t rtype,const int rg_index,mac_group_info_t * infop,mac_group_handle_t gh)859 t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
860 mac_group_info_t *infop, mac_group_handle_t gh)
861 {
862 struct port_info *pi = arg;
863
864 switch (rtype) {
865 case MAC_RING_TYPE_RX: {
866 infop->mgi_driver = (mac_group_driver_t)arg;
867 infop->mgi_start = NULL;
868 infop->mgi_stop = NULL;
869 infop->mgi_addmac = t4_addmac;
870 infop->mgi_remmac = t4_remmac;
871 infop->mgi_count = pi->nrxq;
872 break;
873 }
874 case MAC_RING_TYPE_TX:
875 default:
876 ASSERT(0);
877 break;
878 }
879 }
880
881 static int
t4_ring_start(mac_ring_driver_t rh,uint64_t mr_gen_num)882 t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
883 {
884 struct sge_rxq *rxq = (struct sge_rxq *)rh;
885
886 RXQ_LOCK(rxq);
887 rxq->ring_gen_num = mr_gen_num;
888 RXQ_UNLOCK(rxq);
889 return (0);
890 }
891
892 /*
893 * Enable interrupt on the specificed rx ring.
894 */
895 int
t4_ring_intr_enable(mac_intr_handle_t intrh)896 t4_ring_intr_enable(mac_intr_handle_t intrh)
897 {
898 struct sge_rxq *rxq = (struct sge_rxq *)intrh;
899 struct sge_iq *iq = &rxq->iq;
900
901 RXQ_LOCK(rxq);
902 iq->polling = 0;
903 iq->state = IQS_IDLE;
904 t4_iq_gts_update(iq, iq->intr_params, 0);
905 RXQ_UNLOCK(rxq);
906 return (0);
907 }
908
909 /*
910 * Disable interrupt on the specificed rx ring.
911 */
912 int
t4_ring_intr_disable(mac_intr_handle_t intrh)913 t4_ring_intr_disable(mac_intr_handle_t intrh)
914 {
915 struct sge_rxq *rxq = (struct sge_rxq *)intrh;
916 struct sge_iq *iq;
917
918 /*
919 * Nothing to be done here WRT the interrupt, as it will not fire until
920 * re-enabled through the t4_iq_gts_update() in t4_ring_intr_enable().
921 */
922
923 iq = &rxq->iq;
924 RXQ_LOCK(rxq);
925 iq->polling = 1;
926 iq->state = IQS_BUSY;
927 RXQ_UNLOCK(rxq);
928
929 return (0);
930 }
931
932 mblk_t *
t4_poll_ring(void * arg,int n_bytes)933 t4_poll_ring(void *arg, int n_bytes)
934 {
935 struct sge_rxq *rxq = (struct sge_rxq *)arg;
936 mblk_t *mp = NULL;
937
938 ASSERT(n_bytes >= 0);
939 if (n_bytes == 0)
940 return (NULL);
941
942 RXQ_LOCK(rxq);
943 mp = t4_ring_rx(rxq, n_bytes);
944 RXQ_UNLOCK(rxq);
945
946 return (mp);
947 }
948
949 /*
950 * Retrieve a value for one of the statistics for a particular rx ring
951 */
952 int
t4_rx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)953 t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
954 {
955 struct sge_rxq *rxq = (struct sge_rxq *)rh;
956
957 switch (stat) {
958 case MAC_STAT_RBYTES:
959 *val = rxq->rxbytes;
960 break;
961
962 case MAC_STAT_IPACKETS:
963 *val = rxq->rxpkts;
964 break;
965
966 default:
967 *val = 0;
968 return (ENOTSUP);
969 }
970
971 return (0);
972 }
973
974 /*
975 * Retrieve a value for one of the statistics for a particular tx ring
976 */
977 int
t4_tx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)978 t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
979 {
980 struct sge_txq *txq = (struct sge_txq *)rh;
981
982 switch (stat) {
983 case MAC_STAT_RBYTES:
984 *val = txq->txbytes;
985 break;
986
987 case MAC_STAT_IPACKETS:
988 *val = txq->txpkts;
989 break;
990
991 default:
992 *val = 0;
993 return (ENOTSUP);
994 }
995
996 return (0);
997 }
998
999 /*
1000 * Callback funtion for MAC layer to register all rings
1001 * for given ring_group, noted by group_index.
1002 * Since we have only one group, ring index becomes
1003 * absolute index.
1004 */
1005 void
t4_fill_ring(void * arg,mac_ring_type_t rtype,const int group_index,const int ring_index,mac_ring_info_t * infop,mac_ring_handle_t rh)1006 t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
1007 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
1008 {
1009 struct port_info *pi = arg;
1010 mac_intr_t *mintr;
1011
1012 switch (rtype) {
1013 case MAC_RING_TYPE_RX: {
1014 struct sge_rxq *rxq;
1015
1016 rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
1017 rxq->ring_handle = rh;
1018
1019 infop->mri_driver = (mac_ring_driver_t)rxq;
1020 infop->mri_start = t4_ring_start;
1021 infop->mri_stop = NULL;
1022 infop->mri_poll = t4_poll_ring;
1023 infop->mri_stat = t4_rx_stat;
1024
1025 mintr = &infop->mri_intr;
1026 mintr->mi_handle = (mac_intr_handle_t)rxq;
1027 mintr->mi_enable = t4_ring_intr_enable;
1028 mintr->mi_disable = t4_ring_intr_disable;
1029
1030 break;
1031 }
1032 case MAC_RING_TYPE_TX: {
1033 struct sge_txq *txq =
1034 &pi->adapter->sge.txq[pi->first_txq + ring_index];
1035 txq->ring_handle = rh;
1036 infop->mri_driver = (mac_ring_driver_t)txq;
1037 infop->mri_start = NULL;
1038 infop->mri_stop = NULL;
1039 infop->mri_tx = t4_eth_tx;
1040 infop->mri_stat = t4_tx_stat;
1041 break;
1042 }
1043 default:
1044 ASSERT(0);
1045 break;
1046 }
1047 }
1048
1049 mblk_t *
t4_mc_tx(void * arg,mblk_t * m)1050 t4_mc_tx(void *arg, mblk_t *m)
1051 {
1052 struct port_info *pi = arg;
1053 struct adapter *sc = pi->adapter;
1054 struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
1055
1056 return (t4_eth_tx(txq, m));
1057 }
1058
1059 static int
t4_mc_transceiver_info(void * arg,uint_t id,mac_transceiver_info_t * infop)1060 t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
1061 {
1062 struct port_info *pi = arg;
1063
1064 if (id != 0 || infop == NULL)
1065 return (EINVAL);
1066
1067 switch (pi->mod_type) {
1068 case FW_PORT_MOD_TYPE_NONE:
1069 mac_transceiver_info_set_present(infop, B_FALSE);
1070 break;
1071 case FW_PORT_MOD_TYPE_NOTSUPPORTED:
1072 mac_transceiver_info_set_present(infop, B_TRUE);
1073 mac_transceiver_info_set_usable(infop, B_FALSE);
1074 break;
1075 default:
1076 mac_transceiver_info_set_present(infop, B_TRUE);
1077 mac_transceiver_info_set_usable(infop, B_TRUE);
1078 break;
1079 }
1080
1081 return (0);
1082 }
1083
1084 static int
t4_mc_transceiver_read(void * arg,uint_t id,uint_t page,void * bp,size_t nbytes,off_t offset,size_t * nread)1085 t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
1086 size_t nbytes, off_t offset, size_t *nread)
1087 {
1088 struct port_info *pi = arg;
1089 struct adapter *sc = pi->adapter;
1090 int rc;
1091
1092 if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
1093 (page != 0xa0 && page != 0xa2) || offset < 0)
1094 return (EINVAL);
1095
1096 if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
1097 return (EINVAL);
1098
1099 ADAPTER_LOCK(sc);
1100 /*
1101 * Firmware has a maximum size that we can read. Don't read more than it
1102 * allows.
1103 */
1104 const size_t maxread = sizeof (((struct fw_ldst_cmd *)0)->u.i2c.data);
1105 for (size_t i = 0; i < nbytes; i += maxread) {
1106 size_t toread = MIN(maxread, nbytes - i);
1107 rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
1108 bp);
1109 if (rc != 0)
1110 break;
1111 offset += toread;
1112 bp = (void *)((uintptr_t)bp + toread);
1113 }
1114 ADAPTER_UNLOCK(sc);
1115
1116 if (rc == 0)
1117 *nread = nbytes;
1118 return (rc);
1119 }
1120
1121 static int
t4_port_led_set(void * arg,mac_led_mode_t mode,uint_t flags)1122 t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
1123 {
1124 struct port_info *pi = arg;
1125 struct adapter *sc = pi->adapter;
1126 int val, rc;
1127
1128 if (flags != 0)
1129 return (EINVAL);
1130
1131 switch (mode) {
1132 case MAC_LED_DEFAULT:
1133 val = 0;
1134 break;
1135 case MAC_LED_IDENT:
1136 val = 0xffff;
1137 break;
1138
1139 default:
1140 return (ENOTSUP);
1141 }
1142
1143 ADAPTER_LOCK(sc);
1144 rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
1145 ADAPTER_UNLOCK(sc);
1146
1147 return (rc);
1148 }
1149
1150 static boolean_t
t4_mc_getcapab(void * arg,mac_capab_t cap,void * data)1151 t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
1152 {
1153 struct port_info *pi = arg;
1154 boolean_t status = B_TRUE;
1155 mac_capab_transceiver_t *mct;
1156 mac_capab_led_t *mcl;
1157
1158 switch (cap) {
1159 case MAC_CAPAB_HCKSUM:
1160 if (pi->features & CXGBE_HW_CSUM) {
1161 uint32_t *d = data;
1162 *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM |
1163 HCKSUM_INET_FULL_V6;
1164 } else
1165 status = B_FALSE;
1166 break;
1167
1168 case MAC_CAPAB_LSO:
1169 /* Enabling LSO requires Checksum offloading */
1170 if (pi->features & CXGBE_HW_LSO &&
1171 pi->features & CXGBE_HW_CSUM) {
1172 mac_capab_lso_t *d = data;
1173
1174 d->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
1175 LSO_TX_BASIC_TCP_IPV6;
1176 d->lso_basic_tcp_ipv4.lso_max = 65535;
1177 d->lso_basic_tcp_ipv6.lso_max = 65535;
1178 } else
1179 status = B_FALSE;
1180 break;
1181
1182 case MAC_CAPAB_RINGS: {
1183 mac_capab_rings_t *cap_rings = data;
1184
1185 if (!pi->adapter->props.multi_rings) {
1186 status = B_FALSE;
1187 break;
1188 }
1189 switch (cap_rings->mr_type) {
1190 case MAC_RING_TYPE_RX:
1191 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
1192 cap_rings->mr_rnum = pi->nrxq;
1193 cap_rings->mr_gnum = 1;
1194 cap_rings->mr_rget = t4_fill_ring;
1195 cap_rings->mr_gget = t4_fill_group;
1196 cap_rings->mr_gaddring = NULL;
1197 cap_rings->mr_gremring = NULL;
1198 break;
1199 case MAC_RING_TYPE_TX:
1200 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
1201 cap_rings->mr_rnum = pi->ntxq;
1202 cap_rings->mr_gnum = 0;
1203 cap_rings->mr_rget = t4_fill_ring;
1204 cap_rings->mr_gget = NULL;
1205 break;
1206 }
1207 break;
1208 }
1209
1210 case MAC_CAPAB_TRANSCEIVER:
1211 mct = data;
1212
1213 mct->mct_flags = 0;
1214 mct->mct_ntransceivers = 1;
1215 mct->mct_info = t4_mc_transceiver_info;
1216 mct->mct_read = t4_mc_transceiver_read;
1217 break;
1218 case MAC_CAPAB_LED:
1219 mcl = data;
1220 mcl->mcl_flags = 0;
1221 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
1222 mcl->mcl_set = t4_port_led_set;
1223 break;
1224
1225 default:
1226 status = B_FALSE; /* cap not supported */
1227 }
1228
1229 return (status);
1230 }
1231
1232 static void
t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,link_flowctrl_t * fc)1233 t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps, link_flowctrl_t *fc)
1234 {
1235 u8 pause_tx = 0, pause_rx = 0;
1236
1237 if (caps & FW_PORT_CAP32_FC_TX)
1238 pause_tx = 1;
1239
1240 if (caps & FW_PORT_CAP32_FC_RX)
1241 pause_rx = 1;
1242
1243 if (pause_rx & pause_tx)
1244 *fc = LINK_FLOWCTRL_BI;
1245 else if (pause_tx)
1246 *fc = LINK_FLOWCTRL_TX;
1247 else if (pause_rx)
1248 *fc = LINK_FLOWCTRL_RX;
1249 else
1250 *fc = LINK_FLOWCTRL_NONE;
1251 }
1252
1253 static int
t4_mac_flowctrl_to_link_caps(struct port_info * pi,link_flowctrl_t fc,fw_port_cap32_t * new_caps)1254 t4_mac_flowctrl_to_link_caps(struct port_info *pi, link_flowctrl_t fc,
1255 fw_port_cap32_t *new_caps)
1256 {
1257 cc_pause_t pause = 0;
1258
1259 switch (fc) {
1260 case LINK_FLOWCTRL_BI:
1261 pause |= PAUSE_TX | PAUSE_RX;
1262 break;
1263 case LINK_FLOWCTRL_TX:
1264 pause |= PAUSE_TX;
1265 break;
1266 case LINK_FLOWCTRL_RX:
1267 pause |= PAUSE_RX;
1268 break;
1269 default:
1270 break;
1271 }
1272
1273 if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG)
1274 pause |= PAUSE_AUTONEG;
1275
1276 return (t4_link_set_pause(pi, pause, new_caps));
1277 }
1278
1279 static link_fec_t
t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)1280 t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)
1281 {
1282 link_fec_t link_fec = 0;
1283
1284 if (caps & FW_PORT_CAP32_FEC_RS)
1285 link_fec |= LINK_FEC_RS;
1286
1287 if (caps & FW_PORT_CAP32_FEC_BASER_RS)
1288 link_fec |= LINK_FEC_BASE_R;
1289
1290 if (caps & FW_PORT_CAP32_FEC_NO_FEC)
1291 link_fec |= LINK_FEC_NONE;
1292
1293 if ((link_fec & (link_fec - 1)) &&
1294 !(caps & FW_PORT_CAP32_FORCE_FEC))
1295 return (LINK_FEC_AUTO);
1296
1297 return (link_fec);
1298 }
1299
1300 static void
t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)1301 t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps, link_fec_t *fec)
1302 {
1303 *fec = t4_mac_port_caps_to_fec_cap(caps);
1304 }
1305
1306 static void
t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)1307 t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps, link_fec_t *fec)
1308 {
1309 link_fec_t link_fec;
1310
1311 caps &= ~FW_PORT_CAP32_FEC_NO_FEC;
1312 link_fec = t4_mac_port_caps_to_fec_cap(caps);
1313 *fec = link_fec ? link_fec : LINK_FEC_NONE;
1314 }
1315
1316 static int
t4_mac_fec_cap_to_link_caps(struct port_info * pi,link_fec_t v,fw_port_cap32_t * new_caps)1317 t4_mac_fec_cap_to_link_caps(struct port_info *pi, link_fec_t v,
1318 fw_port_cap32_t *new_caps)
1319 {
1320 cc_fec_t fec = 0;
1321
1322 if (v == LINK_FEC_AUTO) {
1323 fec = FEC_AUTO;
1324 goto out;
1325 }
1326
1327 if (v & LINK_FEC_NONE) {
1328 v &= ~LINK_FEC_NONE;
1329 fec |= FEC_NONE;
1330 }
1331
1332 if (v & LINK_FEC_RS) {
1333 v &= ~LINK_FEC_RS;
1334 fec |= FEC_RS;
1335 }
1336
1337 if (v & LINK_FEC_BASE_R) {
1338 v &= ~LINK_FEC_BASE_R;
1339 fec |= FEC_BASER_RS;
1340 }
1341
1342 if (v != 0)
1343 return (-1);
1344
1345 ASSERT3S(fec, !=, 0);
1346
1347 fec |= FEC_FORCE;
1348
1349 out:
1350 return (t4_link_set_fec(pi, fec, new_caps));
1351 }
1352
1353 /* ARGSUSED */
1354 static int
t4_mc_setprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,const void * val)1355 t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
1356 const void *val)
1357 {
1358 struct port_info *pi = arg;
1359 struct adapter *sc = pi->adapter;
1360 struct link_config *lc = &pi->link_cfg;
1361 fw_port_cap32_t new_caps = lc->admin_caps;
1362 int relink = 0, rx_mode = 0, rc = 0;
1363 uint32_t v32 = *(uint32_t *)val;
1364 uint8_t v8 = *(uint8_t *)val;
1365
1366 switch (id) {
1367 case MAC_PROP_AUTONEG:
1368 rc = t4_link_set_autoneg(pi, v8, &new_caps);
1369 relink = 1;
1370 break;
1371
1372 case MAC_PROP_MTU:
1373 if (v32 < 46 || v32 > MAX_MTU) {
1374 rc = EINVAL;
1375 } else if (v32 != pi->mtu) {
1376 pi->mtu = v32;
1377 (void) mac_maxsdu_update(pi->mh, v32);
1378 rx_mode = 1;
1379 }
1380 break;
1381
1382 case MAC_PROP_FLOWCTRL:
1383 rc = t4_mac_flowctrl_to_link_caps(pi,
1384 *(const link_flowctrl_t *)val, &new_caps);
1385 relink = 1;
1386 break;
1387
1388 case MAC_PROP_EN_FEC_CAP:
1389 rc = t4_mac_fec_cap_to_link_caps(pi,
1390 *(const link_fec_t *)val, &new_caps);
1391 relink = 1;
1392 break;
1393
1394 case MAC_PROP_EN_100GFDX_CAP:
1395 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100G, v8,
1396 &new_caps);
1397 relink = 1;
1398 break;
1399
1400 case MAC_PROP_EN_50GFDX_CAP:
1401 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_50G, v8,
1402 &new_caps);
1403 relink = 1;
1404 break;
1405
1406 case MAC_PROP_EN_40GFDX_CAP:
1407 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_40G, v8,
1408 &new_caps);
1409 relink = 1;
1410 break;
1411
1412 case MAC_PROP_EN_25GFDX_CAP:
1413 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_25G, v8,
1414 &new_caps);
1415 relink = 1;
1416 break;
1417
1418 case MAC_PROP_EN_10GFDX_CAP:
1419 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_10G, v8,
1420 &new_caps);
1421 relink = 1;
1422 break;
1423
1424 case MAC_PROP_EN_1000FDX_CAP:
1425 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_1G, v8,
1426 &new_caps);
1427 relink = 1;
1428 break;
1429
1430 case MAC_PROP_EN_100FDX_CAP:
1431 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100M, v8,
1432 &new_caps);
1433 relink = 1;
1434 break;
1435
1436 case MAC_PROP_PRIVATE:
1437 return (t4_setprop_priv(pi, name, val));
1438
1439 default:
1440 rc = ENOTSUP;
1441 break;
1442 }
1443
1444 if (rc != 0)
1445 return (rc);
1446
1447 if ((pi->flags & TPF_OPEN) != 0) {
1448 if (relink != 0) {
1449 ADAPTER_LOCK(sc);
1450 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
1451 new_caps);
1452 ADAPTER_UNLOCK(sc);
1453 if (rc != 0) {
1454 cxgb_printf(pi->dip, CE_WARN,
1455 "%s link config failed: %d", __func__, rc);
1456 return (rc);
1457 }
1458 }
1459
1460 if (rx_mode != 0) {
1461 ADAPTER_LOCK(sc);
1462 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
1463 -1, -1, -1, false);
1464 ADAPTER_UNLOCK(sc);
1465 if (rc != 0) {
1466 cxgb_printf(pi->dip, CE_WARN,
1467 "set_rxmode failed: %d", rc);
1468 return (rc);
1469 }
1470 }
1471 }
1472
1473 if (relink != 0)
1474 lc->admin_caps = new_caps;
1475
1476 return (0);
1477 }
1478
1479 static int
t4_mc_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,void * val)1480 t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
1481 void *val)
1482 {
1483 struct port_info *pi = arg;
1484 struct link_config *lc = &pi->link_cfg;
1485 uint8_t *u = val;
1486 int rc = 0;
1487
1488 switch (id) {
1489 case MAC_PROP_DUPLEX:
1490 *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
1491 LINK_DUPLEX_UNKNOWN;
1492 break;
1493
1494 case MAC_PROP_SPEED:
1495 if (lc->link_ok != 0) {
1496 *(uint64_t *)val =
1497 t4_link_fwcap_to_speed(lc->link_caps);
1498 *(uint64_t *)val *= 1000000;
1499 } else {
1500 *(uint64_t *)val = 0;
1501 }
1502 break;
1503
1504 case MAC_PROP_STATUS:
1505 *(link_state_t *)val = lc->link_ok ? LINK_STATE_UP :
1506 LINK_STATE_DOWN;
1507 break;
1508
1509 case MAC_PROP_MEDIA:
1510 *(mac_ether_media_t *)val = t4_port_to_media(pi);
1511 break;
1512
1513 case MAC_PROP_AUTONEG:
1514 *u = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
1515 break;
1516
1517 case MAC_PROP_MTU:
1518 *(uint32_t *)val = pi->mtu;
1519 break;
1520
1521 case MAC_PROP_FLOWCTRL:
1522 t4_mac_link_caps_to_flowctrl(lc->link_caps, val);
1523 break;
1524
1525 case MAC_PROP_ADV_FEC_CAP:
1526 t4_mac_link_caps_to_fec_cap(lc->link_caps, val);
1527 break;
1528
1529 case MAC_PROP_EN_FEC_CAP:
1530 t4_mac_admin_caps_to_fec_cap(lc->admin_caps, val);
1531 break;
1532
1533 case MAC_PROP_ADV_100GFDX_CAP:
1534 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100G);
1535 break;
1536
1537 case MAC_PROP_EN_100GFDX_CAP:
1538 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
1539 break;
1540
1541 case MAC_PROP_ADV_50GFDX_CAP:
1542 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_50G);
1543 break;
1544
1545 case MAC_PROP_EN_50GFDX_CAP:
1546 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
1547 break;
1548
1549 case MAC_PROP_ADV_40GFDX_CAP:
1550 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_40G);
1551 break;
1552
1553 case MAC_PROP_EN_40GFDX_CAP:
1554 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
1555 break;
1556
1557 case MAC_PROP_ADV_25GFDX_CAP:
1558 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_25G);
1559 break;
1560
1561 case MAC_PROP_EN_25GFDX_CAP:
1562 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
1563 break;
1564
1565 case MAC_PROP_ADV_10GFDX_CAP:
1566 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_10G);
1567 break;
1568
1569 case MAC_PROP_EN_10GFDX_CAP:
1570 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
1571 break;
1572
1573 case MAC_PROP_ADV_1000FDX_CAP:
1574 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_1G);
1575 break;
1576
1577 case MAC_PROP_EN_1000FDX_CAP:
1578 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
1579 break;
1580
1581 case MAC_PROP_ADV_100FDX_CAP:
1582 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100M);
1583 break;
1584
1585 case MAC_PROP_EN_100FDX_CAP:
1586 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
1587 break;
1588
1589 case MAC_PROP_PRIVATE:
1590 return (t4_getprop_priv(pi, name, size, val));
1591
1592 default:
1593 return (ENOTSUP);
1594 }
1595
1596 return (rc);
1597 }
1598
1599 static void
t4_mc_propinfo(void * arg,const char * name,mac_prop_id_t id,mac_prop_info_handle_t ph)1600 t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
1601 mac_prop_info_handle_t ph)
1602 {
1603 struct port_info *pi = arg;
1604 struct link_config *lc = &pi->link_cfg;
1605
1606 switch (id) {
1607 case MAC_PROP_DUPLEX:
1608 case MAC_PROP_SPEED:
1609 case MAC_PROP_STATUS:
1610 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1611 break;
1612
1613 case MAC_PROP_AUTONEG:
1614 if (lc->pcaps & FW_PORT_CAP32_ANEG)
1615 mac_prop_info_set_default_uint8(ph, 1);
1616 else
1617 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1618 break;
1619
1620 case MAC_PROP_MTU:
1621 mac_prop_info_set_range_uint32(ph, 46, MAX_MTU);
1622 break;
1623
1624 case MAC_PROP_FLOWCTRL:
1625 mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI);
1626 break;
1627
1628 case MAC_PROP_EN_FEC_CAP:
1629 mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1630 break;
1631
1632 case MAC_PROP_ADV_FEC_CAP:
1633 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1634 mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1635 break;
1636
1637 case MAC_PROP_EN_100GFDX_CAP:
1638 if (lc->pcaps & FW_PORT_CAP32_SPEED_100G)
1639 mac_prop_info_set_default_uint8(ph, 1);
1640 else
1641 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1642 break;
1643
1644 case MAC_PROP_EN_50GFDX_CAP:
1645 if (lc->pcaps & FW_PORT_CAP32_SPEED_50G)
1646 mac_prop_info_set_default_uint8(ph, 1);
1647 else
1648 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1649 break;
1650
1651 case MAC_PROP_EN_40GFDX_CAP:
1652 if (lc->pcaps & FW_PORT_CAP32_SPEED_40G)
1653 mac_prop_info_set_default_uint8(ph, 1);
1654 else
1655 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1656 break;
1657
1658 case MAC_PROP_EN_25GFDX_CAP:
1659 if (lc->pcaps & FW_PORT_CAP32_SPEED_25G)
1660 mac_prop_info_set_default_uint8(ph, 1);
1661 else
1662 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1663 break;
1664
1665 case MAC_PROP_EN_10GFDX_CAP:
1666 if (lc->pcaps & FW_PORT_CAP32_SPEED_10G)
1667 mac_prop_info_set_default_uint8(ph, 1);
1668 else
1669 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1670 break;
1671
1672 case MAC_PROP_EN_1000FDX_CAP:
1673 if (lc->pcaps & FW_PORT_CAP32_SPEED_1G)
1674 mac_prop_info_set_default_uint8(ph, 1);
1675 else
1676 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1677 break;
1678
1679 case MAC_PROP_EN_100FDX_CAP:
1680 if (lc->pcaps & FW_PORT_CAP32_SPEED_100M)
1681 mac_prop_info_set_default_uint8(ph, 1);
1682 else
1683 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1684 break;
1685
1686 case MAC_PROP_ADV_100GFDX_CAP:
1687 case MAC_PROP_ADV_50GFDX_CAP:
1688 case MAC_PROP_ADV_40GFDX_CAP:
1689 case MAC_PROP_ADV_25GFDX_CAP:
1690 case MAC_PROP_ADV_10GFDX_CAP:
1691 case MAC_PROP_ADV_1000FDX_CAP:
1692 case MAC_PROP_ADV_100FDX_CAP:
1693 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1694 break;
1695
1696 case MAC_PROP_PRIVATE:
1697 t4_propinfo_priv(pi, name, ph);
1698 break;
1699
1700 default:
1701 break;
1702 }
1703 }
1704
1705 static int
t4_init_synchronized(struct port_info * pi)1706 t4_init_synchronized(struct port_info *pi)
1707 {
1708 struct adapter *sc = pi->adapter;
1709 int rc = 0;
1710
1711 ADAPTER_LOCK_ASSERT_OWNED(pi->adapter);
1712 ASSERT(sc->flags & TAF_INIT_DONE);
1713
1714 PORT_LOCK(pi);
1715
1716 if ((pi->flags & TPF_OPEN) != 0) {
1717 PORT_UNLOCK(pi);
1718 return (0); /* already running */
1719 }
1720
1721 if (!(pi->flags & TPF_INIT_DONE)) {
1722 rc = t4_port_full_init(pi);
1723 if (rc != 0) {
1724 PORT_UNLOCK(pi);
1725 return (rc); /* error message displayed already */
1726 }
1727 } else {
1728 t4_port_queues_enable(pi);
1729 }
1730
1731 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false);
1732 if (rc != 0) {
1733 cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc);
1734 goto done;
1735 }
1736 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt,
1737 pi->hw_addr, true, &pi->smt_idx);
1738 if (rc < 0) {
1739 cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc);
1740 rc = -rc;
1741 goto done;
1742 } else {
1743 pi->xact_addr_filt = rc;
1744 }
1745
1746 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg,
1747 pi->link_cfg.admin_caps);
1748 if (rc != 0) {
1749 cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc);
1750 goto done;
1751 }
1752
1753 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true);
1754 if (rc != 0) {
1755 cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc);
1756 goto done;
1757 }
1758
1759 /* all ok */
1760 pi->flags |= TPF_OPEN;
1761 done:
1762 PORT_UNLOCK(pi);
1763 if (rc != 0)
1764 (void) t4_uninit_synchronized(pi);
1765
1766 return (rc);
1767 }
1768
1769 /*
1770 * Idempotent.
1771 */
1772 static int
t4_uninit_synchronized(struct port_info * pi)1773 t4_uninit_synchronized(struct port_info *pi)
1774 {
1775 struct adapter *sc = pi->adapter;
1776 int rc;
1777
1778 ADAPTER_LOCK_ASSERT_OWNED(pi->adapter);
1779
1780 PORT_LOCK(pi);
1781 /*
1782 * Disable the VI so that all its data in either direction is discarded
1783 * by the MPS. Leave everything else (the queues, interrupts, and 1Hz
1784 * tick) intact as the TP can deliver negative advice or data that it's
1785 * holding in its RAM (for an offloaded connection) even after the VI is
1786 * disabled.
1787 */
1788 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false);
1789 if (rc != 0) {
1790 cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc);
1791 PORT_UNLOCK(pi);
1792 return (rc);
1793 }
1794
1795 t4_port_queues_disable(pi);
1796
1797 pi->flags &= ~TPF_OPEN;
1798 pi->link_cfg.link_ok = 0;
1799 PORT_UNLOCK(pi);
1800
1801 mac_link_update(pi->mh, LINK_STATE_UNKNOWN);
1802
1803 return (0);
1804 }
1805
1806 static uint_t
t4_convert_holdoff_timer(struct adapter * sc,uint_t idx)1807 t4_convert_holdoff_timer(struct adapter *sc, uint_t idx)
1808 {
1809 ASSERT(idx < SGE_NTIMERS);
1810 return (sc->props.holdoff_timer_us[idx]);
1811 }
1812
1813 static int
t4_convert_holdoff_pktcnt(struct adapter * sc,int idx)1814 t4_convert_holdoff_pktcnt(struct adapter *sc, int idx)
1815 {
1816 if (idx < 0) {
1817 return (-1);
1818 } else {
1819 ASSERT(idx < SGE_NCOUNTERS);
1820 return (sc->props.holdoff_pktcnt[idx]);
1821 }
1822 }
1823
1824 static uint_t
t4_convert_dbq_timer(struct adapter * sc,uint_t idx)1825 t4_convert_dbq_timer(struct adapter *sc, uint_t idx)
1826 {
1827 ASSERT(idx < SGE_NDBQTIMERS);
1828 return (sc->sge.dbq_timers[idx]);
1829 }
1830
1831 static void
t4_propinfo_priv(struct port_info * pi,const char * name,mac_prop_info_handle_t ph)1832 t4_propinfo_priv(struct port_info *pi, const char *name,
1833 mac_prop_info_handle_t ph)
1834 {
1835 struct adapter *sc = pi->adapter;
1836 struct driver_properties *dp = &sc->props;
1837 struct link_config *lc = &pi->link_cfg;
1838
1839 const t4_priv_prop_t *prop = t4_priv_prop_match(name);
1840 if (prop == NULL || !t4_priv_prop_supported(pi, prop)) {
1841 return;
1842 }
1843
1844 int v = 0;
1845 switch (prop->tpp_id) {
1846 case T4PROP_FW_TMR:
1847 v = t4_convert_holdoff_timer(sc, sc->props.fwq_tmr_idx);
1848 break;
1849 case T4PROP_FW_PKTC:
1850 v = t4_convert_holdoff_pktcnt(sc, sc->props.fwq_pktc_idx);
1851 break;
1852 case T4PROP_RX_TMR:
1853 v = t4_convert_holdoff_timer(sc, t4_port_is_10xg(pi) ?
1854 dp->tmr_idx_10g : dp->tmr_idx_1g);
1855 break;
1856 case T4PROP_RX_PKTC:
1857 v = t4_convert_holdoff_pktcnt(sc, t4_port_is_10xg(pi) ?
1858 dp->pktc_idx_10g : dp->pktc_idx_1g);
1859 break;
1860 case T4PROP_TX_TMR:
1861 v = t4_convert_dbq_timer(sc, dp->dbq_timer_idx);
1862 break;
1863 case T4PROP_HW_CSUM:
1864 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
1865 break;
1866 case T4PROP_HW_LSO:
1867 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
1868 break;
1869 case T4PROP_TX_PAUSE:
1870 v = (lc->pcaps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
1871 break;
1872 case T4PROP_RX_PAUSE:
1873 v = (lc->pcaps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
1874 break;
1875 default:
1876 return;
1877 }
1878
1879 char str[16];
1880 (void) snprintf(str, sizeof (str), "%d", v);
1881 mac_prop_info_set_default_str(ph, str);
1882 }
1883
1884 static int
t4_getprop_priv(struct port_info * pi,const char * name,uint_t size,void * val)1885 t4_getprop_priv(struct port_info *pi, const char *name, uint_t size, void *val)
1886 {
1887 struct adapter *sc = pi->adapter;
1888 struct link_config *lc = &pi->link_cfg;
1889
1890 const t4_priv_prop_t *prop = t4_priv_prop_match(name);
1891 if (prop == NULL || !t4_priv_prop_supported(pi, prop)) {
1892 return (ENOTSUP);
1893 }
1894
1895 PORT_LOCK(pi);
1896 int v = 0;
1897 switch (prop->tpp_id) {
1898 case T4PROP_FW_TMR:
1899 v = t4_convert_holdoff_timer(sc, sc->sge.fwq_tmr_idx);
1900 break;
1901 case T4PROP_FW_PKTC:
1902 v = t4_convert_holdoff_pktcnt(sc, sc->sge.fwq_pktc_idx);
1903 break;
1904 case T4PROP_RX_TMR:
1905 v = t4_convert_holdoff_timer(sc, pi->tmr_idx);
1906 break;
1907 case T4PROP_RX_PKTC:
1908 v = t4_convert_holdoff_pktcnt(sc, pi->pktc_idx);
1909 break;
1910 case T4PROP_TX_TMR:
1911 v = t4_convert_dbq_timer(sc, pi->dbq_timer_idx);
1912 break;
1913 case T4PROP_HW_CSUM:
1914 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
1915 break;
1916 case T4PROP_HW_LSO:
1917 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
1918 break;
1919 case T4PROP_TX_PAUSE:
1920 v = (lc->link_caps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
1921 break;
1922 case T4PROP_RX_PAUSE:
1923 v = (lc->link_caps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
1924 break;
1925 default:
1926 PORT_UNLOCK(pi);
1927 return (ENOTSUP);
1928 }
1929 PORT_UNLOCK(pi);
1930
1931 (void) snprintf(val, size, "%d", v);
1932 return (0);
1933 }
1934
1935 #define ABS_DELTA(left, right) \
1936 (((left) > (right)) ? (left) - (right) : (right) - (left))
1937
1938 uint8_t
t4_choose_holdoff_timer(struct adapter * sc,uint_t target_us)1939 t4_choose_holdoff_timer(struct adapter *sc, uint_t target_us)
1940 {
1941 const uint_t *timer_us = sc->props.holdoff_timer_us;
1942
1943 uint_t delta = UINT_MAX;
1944 uint_t chosen_idx = 0;
1945 for (uint_t i = 0; i < SGE_NTIMERS; i++) {
1946 const uint_t next_delta = ABS_DELTA(target_us, timer_us[i]);
1947
1948 if (next_delta < delta) {
1949 chosen_idx = i;
1950 delta = next_delta;
1951 }
1952 }
1953
1954 ASSERT3U(chosen_idx, <, SGE_NTIMERS);
1955 return (chosen_idx);
1956 }
1957
1958 int8_t
t4_choose_holdoff_pktcnt(struct adapter * sc,int target_cnt)1959 t4_choose_holdoff_pktcnt(struct adapter *sc, int target_cnt)
1960 {
1961 const uint_t *pkt_cnt = sc->props.holdoff_pktcnt;
1962
1963 if (target_cnt <= 0) {
1964 /* -1 is sentinel value for do-not-use */
1965 return (-1);
1966 }
1967
1968 uint_t delta = UINT_MAX;
1969 uint_t chosen_idx = 0;
1970 for (uint_t i = 0; i < SGE_NCOUNTERS; i++) {
1971 const uint_t next_delta = ABS_DELTA(target_cnt, pkt_cnt[i]);
1972
1973 if (next_delta < delta) {
1974 chosen_idx = i;
1975 delta = next_delta;
1976 }
1977 }
1978
1979 ASSERT3U(chosen_idx, <, SGE_NCOUNTERS);
1980 return (chosen_idx);
1981 }
1982
1983 uint_t
t4_choose_dbq_timer(struct adapter * sc,uint_t target_us)1984 t4_choose_dbq_timer(struct adapter *sc, uint_t target_us)
1985 {
1986 const uint16_t *dbq_us = sc->sge.dbq_timers;
1987
1988 uint_t delta = UINT_MAX;
1989 uint_t chosen_idx = 0;
1990 for (uint_t i = 0; i < SGE_NDBQTIMERS; i++) {
1991 const uint_t next_delta = ABS_DELTA(target_us, dbq_us[i]);
1992
1993 if (next_delta < delta) {
1994 chosen_idx = i;
1995 delta = next_delta;
1996 }
1997 }
1998
1999 ASSERT3U(chosen_idx, <, SGE_NDBQTIMERS);
2000 return (chosen_idx);
2001 }
2002
2003
2004 static int
t4_setprop_priv(struct port_info * pi,const char * name,const void * val)2005 t4_setprop_priv(struct port_info *pi, const char *name, const void *val)
2006 {
2007 struct adapter *sc = pi->adapter;
2008 long v;
2009
2010 const t4_priv_prop_t *prop = t4_priv_prop_match(name);
2011 if (prop == NULL || !t4_priv_prop_supported(pi, prop)) {
2012 return (ENOTSUP);
2013 }
2014
2015 (void) ddi_strtol(val, NULL, 0, &v);
2016 if (prop->tpp_is_bool && v != 0 && v != 1) {
2017 return (EINVAL);
2018 }
2019 const bool vbool = (v != 0);
2020
2021 /* XXX: this needs better locking to deal with adapter init */
2022
2023 bool update_rx_intr_cfg = false;
2024 bool update_link_cfg = false;
2025 struct link_config *lc = &pi->link_cfg;
2026 fw_port_cap32_t new_caps = lc->admin_caps;
2027 cc_pause_t fc = 0;
2028
2029 switch (prop->tpp_id) {
2030 case T4PROP_FW_TMR: {
2031 struct sge_iq *fwq = &sc->sge.fwq;
2032 const uint8_t idx = t4_choose_holdoff_timer(sc, MAX(0, v));
2033
2034 IQ_LOCK(fwq);
2035 sc->sge.fwq_tmr_idx = idx;
2036 t4_iq_update_intr_cfg(fwq, sc->sge.fwq_tmr_idx,
2037 sc->sge.fwq_pktc_idx);
2038 IQ_UNLOCK(fwq);
2039 break;
2040 }
2041 case T4PROP_FW_PKTC: {
2042 struct sge_iq *fwq = &sc->sge.fwq;
2043 const int8_t idx = t4_choose_holdoff_pktcnt(sc, (int)v);
2044
2045 IQ_LOCK(fwq);
2046 sc->sge.fwq_pktc_idx = idx;
2047 t4_iq_update_intr_cfg(fwq, sc->sge.fwq_tmr_idx,
2048 sc->sge.fwq_pktc_idx);
2049 IQ_UNLOCK(fwq);
2050 break;
2051 }
2052 case T4PROP_RX_TMR: {
2053 const uint8_t idx = t4_choose_holdoff_timer(sc, MAX(0, v));
2054 if (idx != pi->tmr_idx) {
2055 pi->tmr_idx = idx;
2056 update_rx_intr_cfg = true;
2057 }
2058 break;
2059 }
2060 case T4PROP_RX_PKTC: {
2061 const int8_t idx = t4_choose_holdoff_pktcnt(sc, (int)v);
2062 if (idx != pi->pktc_idx) {
2063 pi->pktc_idx = idx;
2064 update_rx_intr_cfg = true;
2065 }
2066 break;
2067 }
2068 case T4PROP_TX_TMR: {
2069 ASSERT(sc->flags & TAF_DBQ_TIMER);
2070 if (v <= 0) {
2071 return (EINVAL);
2072 }
2073 const uint_t idx = t4_choose_dbq_timer(sc, (uint_t)v);
2074 PORT_LOCK(pi);
2075 if ((pi->flags & TPF_OPEN) != 0 &&
2076 idx != pi->dbq_timer_idx) {
2077 pi->dbq_timer_idx = idx;
2078
2079 int i;
2080 struct sge_txq *txq;
2081 for_each_txq(pi, i, txq) {
2082 struct sge_eq *eq = &txq->eq;
2083
2084 EQ_LOCK(eq);
2085 t4_eq_update_dbq_timer(eq, pi);
2086 EQ_UNLOCK(eq);
2087 }
2088 }
2089 PORT_UNLOCK(pi);
2090 return (0);
2091 }
2092 case T4PROP_HW_CSUM:
2093 if (vbool)
2094 pi->features |= CXGBE_HW_CSUM;
2095 else
2096 pi->features &= ~CXGBE_HW_CSUM;
2097 break;
2098 case T4PROP_HW_LSO:
2099 if (vbool)
2100 pi->features |= CXGBE_HW_LSO;
2101 else
2102 pi->features &= ~CXGBE_HW_LSO;
2103 break;
2104 case T4PROP_TX_PAUSE:
2105 case T4PROP_RX_PAUSE:
2106 if (new_caps & FW_PORT_CAP32_FC_TX) {
2107 if (prop->tpp_id == T4PROP_TX_PAUSE) {
2108 fc |= vbool ? PAUSE_TX : 0;
2109 } else {
2110 fc |= PAUSE_TX;
2111 }
2112 }
2113 if (new_caps & FW_PORT_CAP32_FC_RX) {
2114 if (prop->tpp_id == T4PROP_RX_PAUSE) {
2115 fc |= vbool ? PAUSE_RX : 0;
2116 } else {
2117 fc |= PAUSE_RX;
2118 }
2119 }
2120 if (new_caps & FW_PORT_CAP32_ANEG) {
2121 fc |= PAUSE_AUTONEG;
2122 }
2123 update_link_cfg = true;
2124 break;
2125 default:
2126 return (ENOTSUP);
2127 }
2128
2129 if (update_rx_intr_cfg) {
2130 struct sge_rxq *rxq;
2131 int i;
2132
2133 PORT_LOCK(pi);
2134 if ((pi->flags & TPF_OPEN) != 0) {
2135 for_each_rxq(pi, i, rxq) {
2136 struct sge_iq *iq = &rxq->iq;
2137
2138 IQ_LOCK(iq);
2139 t4_iq_update_intr_cfg(iq, pi->tmr_idx,
2140 pi->pktc_idx);
2141 IQ_UNLOCK(iq);
2142 }
2143 }
2144 PORT_UNLOCK(pi);
2145 }
2146 if (update_link_cfg) {
2147 int rc = 0;
2148
2149 ADAPTER_LOCK(pi->adapter);
2150 PORT_LOCK(pi);
2151 t4_link_set_pause(pi, fc, &new_caps);
2152 if ((pi->flags & TPF_OPEN) != 0) {
2153 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
2154 new_caps);
2155 if (rc != 0) {
2156 cxgb_printf(pi->dip, CE_WARN,
2157 "%s link config failed: %d",
2158 __func__, rc);
2159 }
2160 }
2161
2162 if (rc == 0) {
2163 lc->admin_caps = new_caps;
2164 }
2165 PORT_UNLOCK(pi);
2166 ADAPTER_UNLOCK(pi->adapter);
2167 return (rc);
2168 }
2169
2170 return (0);
2171 }
2172
2173 void
t4_mc_cb_init(struct port_info * pi)2174 t4_mc_cb_init(struct port_info *pi)
2175 {
2176 if (pi->adapter->props.multi_rings)
2177 pi->mc = &t4_m_ring_callbacks;
2178 else
2179 pi->mc = &t4_m_callbacks;
2180 }
2181
2182 void
t4_os_link_changed(struct adapter * sc,int idx,int link_stat)2183 t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
2184 {
2185 struct port_info *pi = sc->port[idx];
2186
2187 mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN);
2188 }
2189
2190 /* ARGSUSED */
2191 void
t4_mac_rx(struct port_info * pi,struct sge_rxq * rxq,mblk_t * m)2192 t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m)
2193 {
2194 mac_rx(pi->mh, NULL, m);
2195 }
2196
2197 void
t4_mac_tx_update(struct port_info * pi,struct sge_txq * txq)2198 t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq)
2199 {
2200 if (pi->adapter->props.multi_rings)
2201 mac_tx_ring_update(pi->mh, txq->ring_handle);
2202 else
2203 mac_tx_update(pi->mh);
2204 }
2205