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