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