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 /* I couldn't comeup with a better idea of not redefine
77 * another strcture and instead somehow reuse the earlier
78 * above structure and modify its members.
79 */
80 mac_callbacks_t t4_m_ring_callbacks = {
81 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES,
82 .mc_getstat = t4_mc_getstat,
83 .mc_start = t4_mc_start,
84 .mc_stop = t4_mc_stop,
85 .mc_setpromisc =t4_mc_setpromisc,
86 .mc_multicst = t4_mc_multicst,
87 .mc_unicst = NULL, /* t4_addmac */
88 .mc_tx = NULL, /* t4_eth_tx */
89 .mc_getcapab = t4_mc_getcapab,
90 .mc_setprop = t4_mc_setprop,
91 .mc_getprop = t4_mc_getprop,
92 .mc_propinfo = t4_mc_propinfo,
93 };
94
95 #define T4PROP_TMR_IDX "_holdoff_timer_idx"
96 #define T4PROP_PKTC_IDX "_holdoff_pktc_idx"
97 #define T4PROP_MTU "_mtu"
98 #define T4PROP_HW_CSUM "_hw_csum"
99 #define T4PROP_HW_LSO "_hw_lso"
100 #define T4PROP_TX_PAUSE "_tx_pause"
101 #define T4PROP_RX_PAUSE "_rx_pause"
102
103 char *t4_priv_props[] = {
104 T4PROP_TMR_IDX,
105 T4PROP_PKTC_IDX,
106 #if MAC_VERSION == 1
107 /* MAC_VERSION 1 doesn't seem to use MAC_PROP_MTU, hmmmm */
108 T4PROP_MTU,
109 #endif
110 T4PROP_HW_CSUM,
111 T4PROP_HW_LSO,
112 T4PROP_TX_PAUSE,
113 T4PROP_RX_PAUSE,
114 NULL
115 };
116
117 /*
118 * To determine the actual Ethernet mode that we're in we need to look at the
119 * port type. That will tell us whether we're using a BASE-T PHY, have an
120 * external SFP connection whose module type we also need to use to qualify
121 * this, and then the link speed itself. Combining that tuple we can then get
122 * the current media.
123 *
124 * Our tables below assume we have gotten it down so the last thing we need to
125 * consider is a single speed. If port types end up supporting the same class of
126 * transceiver at a given speed, then this will need to be changed to use
127 * additional information to disambiguate that (which will require additional
128 * logic from the firmware).
129 */
130 typedef struct {
131 fw_port_cap32_t tmm_speed;
132 mac_ether_media_t tmm_ether;
133 } t4nex_media_map_t;
134
135 static const t4nex_media_map_t t4nex_map_baset[] = {
136 /*
137 * We're assuming that the 100 Mb/s mode is 100BASE-TX. It's hard to say
138 * for certain what the phy would have done, but given the rest of the
139 * market, that seems the most likely one.
140 */
141 { FW_PORT_CAP32_SPEED_100M, ETHER_MEDIA_100BASE_TX },
142 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_T },
143 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_T }
144 };
145
146 static const t4nex_media_map_t t4nex_map_kx[] = {
147 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
148 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KX4 }
149 };
150
151 static const t4nex_media_map_t t4nex_map_cx[] = {
152 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CX4 }
153 };
154
155 static const t4nex_media_map_t t4nex_map_kr[] = {
156 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
157 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KR },
158 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_KR },
159 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_KR4 },
160 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_KR2 },
161 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_KR4 },
162 };
163
164 static const t4nex_media_map_t t4nex_map_lr[] = {
165 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_LX },
166 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LR },
167 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_LR },
168 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_LR4 },
169 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_LR2 },
170 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_LR4 },
171 };
172
173 static const t4nex_media_map_t t4nex_map_sr[] = {
174 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_SX },
175 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_SR },
176 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_SR },
177 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_SR4 },
178 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_SR2 },
179 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_SR4 },
180 };
181
182 static const t4nex_media_map_t t4nex_map_er[] = {
183 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ER },
184 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ER },
185 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ER4 },
186 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ER4 },
187 };
188
189 static const t4nex_media_map_t t4nex_map_cr[] = {
190 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
191 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CR },
192 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_CR },
193 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_CR4 },
194 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_CR2 },
195 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_CR4 },
196 };
197
198 static const t4nex_media_map_t t4nex_map_acc[] = {
199 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
200 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ACC },
201 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ACC },
202 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ACC4 },
203 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_ACC2 },
204 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ACC4 },
205 };
206
207 static const t4nex_media_map_t t4nex_map_lrm[] = {
208 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LRM },
209 };
210
211 static mac_ether_media_t
t4_port_to_media(struct port_info * pi)212 t4_port_to_media(struct port_info *pi)
213 {
214 fw_port_cap32_t speed;
215 struct link_config *lc = &pi->link_cfg;
216 const t4nex_media_map_t *map = NULL;
217 size_t count = 0;
218
219 if (lc->link_ok != 0) {
220 speed = t4_link_fwcap_to_fwspeed(lc->link_caps);
221 } else {
222 return (ETHER_MEDIA_UNKNOWN);
223 }
224
225 switch (pi->port_type) {
226 case FW_PORT_TYPE_FIBER_XFI:
227 case FW_PORT_TYPE_FIBER_XAUI:
228 case FW_PORT_TYPE_SFP:
229 case FW_PORT_TYPE_QSFP_10G:
230 case FW_PORT_TYPE_QSA:
231 case FW_PORT_TYPE_QSFP:
232 case FW_PORT_TYPE_CR4_QSFP:
233 case FW_PORT_TYPE_CR_QSFP:
234 case FW_PORT_TYPE_CR2_QSFP:
235 case FW_PORT_TYPE_SFP28:
236 switch (pi->mod_type) {
237 case FW_PORT_MOD_TYPE_LR:
238 map = t4nex_map_lr;
239 count = ARRAY_SIZE(t4nex_map_lr);
240 break;
241 case FW_PORT_MOD_TYPE_SR:
242 map = t4nex_map_sr;
243 count = ARRAY_SIZE(t4nex_map_sr);
244 break;
245 case FW_PORT_MOD_TYPE_ER:
246 map = t4nex_map_er;
247 count = ARRAY_SIZE(t4nex_map_er);
248 break;
249 case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
250 map = t4nex_map_cr;
251 count = ARRAY_SIZE(t4nex_map_cr);
252 break;
253 case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
254 map = t4nex_map_acc;
255 count = ARRAY_SIZE(t4nex_map_acc);
256 break;
257 case FW_PORT_MOD_TYPE_LRM:
258 map = t4nex_map_lrm;
259 count = ARRAY_SIZE(t4nex_map_lrm);
260 break;
261 case FW_PORT_MOD_TYPE_ERROR:
262 case FW_PORT_MOD_TYPE_UNKNOWN:
263 case FW_PORT_MOD_TYPE_NOTSUPPORTED:
264 case FW_PORT_MOD_TYPE_NONE:
265 case FW_PORT_MOD_TYPE_NA:
266 default:
267 break;
268 }
269 break;
270 case FW_PORT_TYPE_KX4:
271 case FW_PORT_TYPE_KX:
272 map = t4nex_map_kx;
273 count = ARRAY_SIZE(t4nex_map_kx);
274 break;
275 case FW_PORT_TYPE_CX4:
276 map = t4nex_map_cx;
277 count = ARRAY_SIZE(t4nex_map_cx);
278 break;
279 case FW_PORT_TYPE_KR:
280 case FW_PORT_TYPE_BP_AP:
281 case FW_PORT_TYPE_BP4_AP:
282 case FW_PORT_TYPE_BP40_BA:
283 case FW_PORT_TYPE_KR4_100G:
284 case FW_PORT_TYPE_KR_SFP28:
285 case FW_PORT_TYPE_KR_XLAUI:
286 map = t4nex_map_kr;
287 count = ARRAY_SIZE(t4nex_map_kr);
288 break;
289 case FW_PORT_TYPE_BT_SGMII:
290 case FW_PORT_TYPE_BT_XFI:
291 case FW_PORT_TYPE_BT_XAUI:
292 map = t4nex_map_baset;
293 count = ARRAY_SIZE(t4nex_map_baset);
294 break;
295 case FW_PORT_TYPE_NONE:
296 default:
297 break;
298 }
299
300 for (size_t i = 0; i < count; i++) {
301 if (map[i].tmm_speed == speed) {
302 return (map[i].tmm_ether);
303 }
304 }
305
306 /*
307 * At this point we return unknown as we already checked for a down link
308 * earlier.
309 */
310 return (ETHER_MEDIA_UNKNOWN);
311 }
312
313 static int
t4_mc_getstat(void * arg,uint_t stat,uint64_t * val)314 t4_mc_getstat(void *arg, uint_t stat, uint64_t *val)
315 {
316 struct port_info *pi = arg;
317 struct adapter *sc = pi->adapter;
318 struct link_config *lc = &pi->link_cfg;
319
320 #define GET_STAT(name) \
321 t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
322
323 switch (stat) {
324 case MAC_STAT_IFSPEED:
325 if (lc->link_ok != 0) {
326 *val = t4_link_fwcap_to_speed(lc->link_caps);
327 *val *= 1000000;
328 } else
329 *val = 0;
330 break;
331
332 case MAC_STAT_MULTIRCV:
333 *val = GET_STAT(RX_PORT_MCAST);
334 break;
335
336 case MAC_STAT_BRDCSTRCV:
337 *val = GET_STAT(RX_PORT_BCAST);
338 break;
339
340 case MAC_STAT_MULTIXMT:
341 *val = GET_STAT(TX_PORT_MCAST);
342 break;
343
344 case MAC_STAT_BRDCSTXMT:
345 *val = GET_STAT(TX_PORT_BCAST);
346 break;
347
348 case MAC_STAT_NORCVBUF:
349 *val = 0; /* TODO should come from rxq->nomem */
350 break;
351
352 case MAC_STAT_IERRORS:
353 *val = GET_STAT(RX_PORT_MTU_ERROR) +
354 GET_STAT(RX_PORT_MTU_CRC_ERROR) +
355 GET_STAT(RX_PORT_CRC_ERROR) +
356 GET_STAT(RX_PORT_LEN_ERROR) +
357 GET_STAT(RX_PORT_SYM_ERROR) +
358 GET_STAT(RX_PORT_LESS_64B);
359 break;
360
361 case MAC_STAT_UNKNOWNS:
362 return (ENOTSUP);
363
364 case MAC_STAT_NOXMTBUF:
365 *val = GET_STAT(TX_PORT_DROP);
366 break;
367
368 case MAC_STAT_OERRORS:
369 *val = GET_STAT(TX_PORT_ERROR);
370 break;
371
372 case MAC_STAT_COLLISIONS:
373 return (ENOTSUP);
374
375 case MAC_STAT_RBYTES:
376 *val = GET_STAT(RX_PORT_BYTES);
377 break;
378
379 case MAC_STAT_IPACKETS:
380 *val = GET_STAT(RX_PORT_FRAMES);
381 break;
382
383 case MAC_STAT_OBYTES:
384 *val = GET_STAT(TX_PORT_BYTES);
385 break;
386
387 case MAC_STAT_OPACKETS:
388 *val = GET_STAT(TX_PORT_FRAMES);
389 break;
390
391 case ETHER_STAT_ALIGN_ERRORS:
392 return (ENOTSUP);
393
394 case ETHER_STAT_FCS_ERRORS:
395 *val = GET_STAT(RX_PORT_CRC_ERROR);
396 break;
397
398 case ETHER_STAT_FIRST_COLLISIONS:
399 case ETHER_STAT_MULTI_COLLISIONS:
400 case ETHER_STAT_SQE_ERRORS:
401 case ETHER_STAT_DEFER_XMTS:
402 case ETHER_STAT_TX_LATE_COLLISIONS:
403 case ETHER_STAT_EX_COLLISIONS:
404 return (ENOTSUP);
405
406 case ETHER_STAT_MACXMT_ERRORS:
407 *val = GET_STAT(TX_PORT_ERROR);
408 break;
409
410 case ETHER_STAT_CARRIER_ERRORS:
411 return (ENOTSUP);
412
413 case ETHER_STAT_TOOLONG_ERRORS:
414 *val = GET_STAT(RX_PORT_MTU_ERROR);
415 break;
416
417 case ETHER_STAT_MACRCV_ERRORS:
418 *val = GET_STAT(RX_PORT_MTU_ERROR) +
419 GET_STAT(RX_PORT_MTU_CRC_ERROR) +
420 GET_STAT(RX_PORT_CRC_ERROR) +
421 GET_STAT(RX_PORT_LEN_ERROR) +
422 GET_STAT(RX_PORT_SYM_ERROR) +
423 GET_STAT(RX_PORT_LESS_64B);
424 break;
425
426 case ETHER_STAT_XCVR_ADDR:
427 case ETHER_STAT_XCVR_ID:
428 return (ENOTSUP);
429 case ETHER_STAT_XCVR_INUSE:
430 *val = t4_port_to_media(pi);
431 break;
432
433 case ETHER_STAT_CAP_100GFDX:
434 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G);
435 break;
436
437 case ETHER_STAT_CAP_50GFDX:
438 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_50G);
439 break;
440
441 case ETHER_STAT_CAP_40GFDX:
442 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
443 break;
444
445 case ETHER_STAT_CAP_25GFDX:
446 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
447 break;
448
449 case ETHER_STAT_CAP_10GFDX:
450 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
451 break;
452
453 case ETHER_STAT_CAP_1000FDX:
454 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
455 break;
456
457 case ETHER_STAT_CAP_100FDX:
458 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
459 break;
460
461 case ETHER_STAT_CAP_1000HDX:
462 case ETHER_STAT_CAP_100HDX:
463 case ETHER_STAT_CAP_10FDX:
464 case ETHER_STAT_CAP_10HDX:
465 return (ENOTSUP);
466
467 case ETHER_STAT_CAP_ASMPAUSE:
468 *val = !!(lc->pcaps & FW_PORT_CAP32_FC_RX);
469 break;
470
471 case ETHER_STAT_CAP_PAUSE:
472 *val = !!(lc->pcaps & FW_PORT_CAP32_FC_TX);
473 break;
474
475 case ETHER_STAT_CAP_AUTONEG:
476 *val = !!(lc->pcaps & FW_PORT_CAP32_ANEG);
477 break;
478
479 /*
480 * We have set flow control configuration based on tx_pause and rx_pause
481 * values supported through ndd. Now, we need to translate the settings
482 * we have in link_config structure to adv_cap_asmpause and
483 * adv_cap_pause.
484 *
485 * There are 4 combinations possible and the translation is as below:
486 * tx_pause = 0 => We don't send pause frames during Rx congestion
487 * tx_pause = 1 => We send pause frames during Rx congestion
488 * rx_pause = 0 => We ignore received pause frames
489 * rx_pause = 1 => We pause transmission when we receive pause frames
490 *
491 * +----------------------------+----------------------------------+
492 * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause |
493 * +-------------------------+-------------------------------------+
494 * | 0 | 0 | 0 | 0 |
495 * | 0 | 1 | 1 | 0 |
496 * | 1 | 0 | 1 | 1 |
497 * | 1 | 1 | 0 | 1 |
498 * +----------------------------+----------------------------------+
499 */
500
501 /* Advertised asymmetric pause capability */
502 case ETHER_STAT_ADV_CAP_ASMPAUSE:
503 if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
504 *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_ASM_DIR);
505 else
506 *val = (!!(lc->admin_caps & FW_PORT_CAP32_FC_TX)) ^
507 (!!(lc->admin_caps & FW_PORT_CAP32_FC_RX));
508 break;
509
510 /* Advertised pause capability */
511 case ETHER_STAT_ADV_CAP_PAUSE:
512 if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
513 *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_PAUSE);
514 else
515 *val = !!(lc->admin_caps & FW_PORT_CAP32_FC_TX);
516 break;
517
518 case ETHER_STAT_ADV_CAP_100GFDX:
519 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
520 break;
521
522 case ETHER_STAT_ADV_CAP_50GFDX:
523 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
524 break;
525
526 case ETHER_STAT_ADV_CAP_40GFDX:
527 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
528 break;
529
530 case ETHER_STAT_ADV_CAP_25GFDX:
531 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
532 break;
533
534 case ETHER_STAT_ADV_CAP_10GFDX:
535 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
536 break;
537
538 case ETHER_STAT_ADV_CAP_1000FDX:
539 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
540 break;
541
542 case ETHER_STAT_ADV_CAP_100FDX:
543 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
544 break;
545
546 case ETHER_STAT_ADV_CAP_AUTONEG:
547 *val = !!(lc->admin_caps & FW_PORT_CAP32_ANEG);
548 break;
549
550 case ETHER_STAT_ADV_CAP_1000HDX:
551 case ETHER_STAT_ADV_CAP_100HDX:
552 case ETHER_STAT_ADV_CAP_10FDX:
553 case ETHER_STAT_ADV_CAP_10HDX:
554 return (ENOTSUP); /* TODO */
555
556 case ETHER_STAT_LP_CAP_ASMPAUSE:
557 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
558 return (ENOTSUP);
559
560 if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
561 *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_ASM_DIR);
562 else
563 *val = (!!(lc->lpacaps & FW_PORT_CAP32_FC_TX)) ^
564 (!!(lc->lpacaps & FW_PORT_CAP32_FC_RX));
565 break;
566
567 case ETHER_STAT_LP_CAP_PAUSE:
568 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
569 return (ENOTSUP);
570
571 if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
572 *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_PAUSE);
573 else
574 *val = !!(lc->lpacaps & FW_PORT_CAP32_FC_TX);
575 break;
576
577 case ETHER_STAT_LP_CAP_100GFDX:
578 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
579 return (ENOTSUP);
580
581 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100G);
582 break;
583
584 case ETHER_STAT_LP_CAP_50GFDX:
585 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
586 return (ENOTSUP);
587
588 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_50G);
589 break;
590
591 case ETHER_STAT_LP_CAP_40GFDX:
592 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
593 return (ENOTSUP);
594
595 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_40G);
596 break;
597
598 case ETHER_STAT_LP_CAP_25GFDX:
599 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
600 return (ENOTSUP);
601
602 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_25G);
603 break;
604
605 case ETHER_STAT_LP_CAP_10GFDX:
606 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
607 return (ENOTSUP);
608
609 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_10G);
610 break;
611
612 case ETHER_STAT_LP_CAP_1000FDX:
613 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
614 return (ENOTSUP);
615
616 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_1G);
617 break;
618
619 case ETHER_STAT_LP_CAP_100FDX:
620 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
621 return (ENOTSUP);
622
623 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100M);
624 break;
625
626 case ETHER_STAT_LP_CAP_AUTONEG:
627 if (!(lc->acaps & FW_PORT_CAP32_ANEG))
628 return (ENOTSUP);
629
630 *val = !!(lc->lpacaps & FW_PORT_CAP32_ANEG);
631 break;
632
633 case ETHER_STAT_LP_CAP_1000HDX:
634 case ETHER_STAT_LP_CAP_100HDX:
635 case ETHER_STAT_LP_CAP_10FDX:
636 case ETHER_STAT_LP_CAP_10HDX:
637 return (ENOTSUP);
638
639 case ETHER_STAT_LINK_ASMPAUSE:
640 *val = (!!(lc->link_caps & FW_PORT_CAP32_FC_TX)) ^
641 (!!(lc->link_caps & FW_PORT_CAP32_FC_RX));
642 break;
643
644 case ETHER_STAT_LINK_PAUSE:
645 *val = !!(lc->link_caps & FW_PORT_CAP32_FC_TX);
646 break;
647
648 case ETHER_STAT_LINK_AUTONEG:
649 *val = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
650 break;
651
652 case ETHER_STAT_LINK_DUPLEX:
653 if (lc->link_ok != 0)
654 *val = LINK_DUPLEX_FULL;
655 else
656 *val = LINK_DUPLEX_UNKNOWN;
657 break;
658
659 default:
660 return (ENOTSUP);
661 }
662 #undef GET_STAT
663
664 return (0);
665 }
666
667 static int
t4_mc_start(void * arg)668 t4_mc_start(void *arg)
669 {
670 struct port_info *pi = arg;
671 int rc;
672
673 rc = begin_synchronized_op(pi, 0, 1);
674 if (rc != 0)
675 return (rc);
676 rc = t4_init_synchronized(pi);
677 end_synchronized_op(pi, 0);
678
679 return (rc);
680 }
681
682 static void
t4_mc_stop(void * arg)683 t4_mc_stop(void *arg)
684 {
685 struct port_info *pi = arg;
686
687 while (begin_synchronized_op(pi, 0, 1) != 0)
688 continue;
689 (void) t4_uninit_synchronized(pi);
690 end_synchronized_op(pi, 0);
691 }
692
693 static int
t4_mc_setpromisc(void * arg,boolean_t on)694 t4_mc_setpromisc(void *arg, boolean_t on)
695 {
696 struct port_info *pi = arg;
697 struct adapter *sc = pi->adapter;
698 int rc;
699
700 rc = begin_synchronized_op(pi, 1, 1);
701 if (rc != 0)
702 return (rc);
703 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
704 false);
705 end_synchronized_op(pi, 1);
706
707 return (rc);
708 }
709
710 /*
711 * TODO: Starts failing as soon as the 336 entry table fills up. Need to use
712 * hash in that case.
713 */
714 static int
t4_mc_multicst(void * arg,boolean_t add,const uint8_t * mcaddr)715 t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
716 {
717 struct port_info *pi = arg;
718 struct adapter *sc = pi->adapter;
719 struct fw_vi_mac_cmd c;
720 int len16, rc;
721
722 len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
723 sizeof (c.u.exact[0]), 16);
724 c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
725 F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
726 c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
727 c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
728 V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
729 FW_VI_MAC_MAC_BASED_FREE));
730 bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
731
732 rc = begin_synchronized_op(pi, 1, 1);
733 if (rc != 0)
734 return (rc);
735 rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
736 end_synchronized_op(pi, 1);
737 if (rc != 0)
738 return (rc);
739 #ifdef DEBUG
740 /*
741 * TODO: Firmware doesn't seem to return the correct index on removal
742 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
743 * code once it is fixed.
744 */
745 else {
746 uint16_t idx;
747
748 idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
749 cxgb_printf(pi->dip, CE_NOTE,
750 "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
751 mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
752 add ? "added at index" : "removed from index", idx);
753 }
754 #endif
755
756 return (0);
757 }
758
759 int
t4_mc_unicst(void * arg,const uint8_t * ucaddr)760 t4_mc_unicst(void *arg, const uint8_t *ucaddr)
761 {
762 struct port_info *pi = arg;
763 struct adapter *sc = pi->adapter;
764 int rc;
765
766 if (ucaddr == NULL)
767 return (EINVAL);
768
769 rc = begin_synchronized_op(pi, 1, 1);
770 if (rc != 0)
771 return (rc);
772
773 /* We will support adding only one mac address */
774 if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
775 end_synchronized_op(pi, 1);
776 return (ENOSPC);
777 }
778 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
779 true, &pi->smt_idx);
780 if (rc < 0)
781 rc = -rc;
782 else {
783 pi->macaddr_cnt++;
784 pi->xact_addr_filt = rc;
785 rc = 0;
786 }
787 end_synchronized_op(pi, 1);
788
789 return (rc);
790 }
791
792 int
t4_addmac(void * arg,const uint8_t * ucaddr)793 t4_addmac(void *arg, const uint8_t *ucaddr)
794 {
795 return (t4_mc_unicst(arg, ucaddr));
796 }
797
798 static int
t4_remmac(void * arg,const uint8_t * mac_addr)799 t4_remmac(void *arg, const uint8_t *mac_addr)
800 {
801 struct port_info *pi = arg;
802 int rc;
803
804 rc = begin_synchronized_op(pi, 1, 1);
805 if (rc != 0)
806 return (rc);
807
808 pi->macaddr_cnt--;
809 end_synchronized_op(pi, 1);
810
811 return (0);
812 }
813
814 /*
815 * Callback funtion for MAC layer to register all groups.
816 */
817 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)818 t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
819 mac_group_info_t *infop, mac_group_handle_t gh)
820 {
821 struct port_info *pi = arg;
822
823 switch (rtype) {
824 case MAC_RING_TYPE_RX: {
825 infop->mgi_driver = (mac_group_driver_t)arg;
826 infop->mgi_start = NULL;
827 infop->mgi_stop = NULL;
828 infop->mgi_addmac = t4_addmac;
829 infop->mgi_remmac = t4_remmac;
830 infop->mgi_count = pi->nrxq;
831 break;
832 }
833 case MAC_RING_TYPE_TX:
834 default:
835 ASSERT(0);
836 break;
837 }
838 }
839
840 static int
t4_ring_start(mac_ring_driver_t rh,uint64_t mr_gen_num)841 t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
842 {
843 struct sge_rxq *rxq = (struct sge_rxq *)rh;
844
845 RXQ_LOCK(rxq);
846 rxq->ring_gen_num = mr_gen_num;
847 RXQ_UNLOCK(rxq);
848 return (0);
849 }
850
851 /*
852 * Enable interrupt on the specificed rx ring.
853 */
854 int
t4_ring_intr_enable(mac_intr_handle_t intrh)855 t4_ring_intr_enable(mac_intr_handle_t intrh)
856 {
857 struct sge_rxq *rxq = (struct sge_rxq *)intrh;
858 struct adapter *sc = rxq->port->adapter;
859 struct sge_iq *iq;
860
861 iq = &rxq->iq;
862 RXQ_LOCK(rxq);
863 iq->polling = 0;
864 iq->state = IQS_IDLE;
865 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
866 V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id));
867 RXQ_UNLOCK(rxq);
868 return (0);
869 }
870
871 /*
872 * Disable interrupt on the specificed rx ring.
873 */
874 int
t4_ring_intr_disable(mac_intr_handle_t intrh)875 t4_ring_intr_disable(mac_intr_handle_t intrh)
876 {
877 struct sge_rxq *rxq = (struct sge_rxq *)intrh;
878 struct sge_iq *iq;
879
880 /* Nothing to be done here wrt interrupt, as it
881 * will not fire, until we write back to
882 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable.
883 */
884
885 iq = &rxq->iq;
886 RXQ_LOCK(rxq);
887 iq->polling = 1;
888 iq->state = IQS_BUSY;
889 RXQ_UNLOCK(rxq);
890 return (0);
891 }
892
893 mblk_t *
t4_poll_ring(void * arg,int n_bytes)894 t4_poll_ring(void *arg, int n_bytes)
895 {
896 struct sge_rxq *rxq = (struct sge_rxq *)arg;
897 mblk_t *mp = NULL;
898
899 ASSERT(n_bytes >= 0);
900 if (n_bytes == 0)
901 return (NULL);
902
903 RXQ_LOCK(rxq);
904 mp = t4_ring_rx(rxq, n_bytes);
905 RXQ_UNLOCK(rxq);
906
907 return (mp);
908 }
909
910 /*
911 * Retrieve a value for one of the statistics for a particular rx ring
912 */
913 int
t4_rx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)914 t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
915 {
916 struct sge_rxq *rxq = (struct sge_rxq *)rh;
917
918 switch (stat) {
919 case MAC_STAT_RBYTES:
920 *val = rxq->rxbytes;
921 break;
922
923 case MAC_STAT_IPACKETS:
924 *val = rxq->rxpkts;
925 break;
926
927 default:
928 *val = 0;
929 return (ENOTSUP);
930 }
931
932 return (0);
933 }
934
935 /*
936 * Retrieve a value for one of the statistics for a particular tx ring
937 */
938 int
t4_tx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)939 t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
940 {
941 struct sge_txq *txq = (struct sge_txq *)rh;
942
943 switch (stat) {
944 case MAC_STAT_RBYTES:
945 *val = txq->txbytes;
946 break;
947
948 case MAC_STAT_IPACKETS:
949 *val = txq->txpkts;
950 break;
951
952 default:
953 *val = 0;
954 return (ENOTSUP);
955 }
956
957 return (0);
958 }
959
960 /*
961 * Callback funtion for MAC layer to register all rings
962 * for given ring_group, noted by group_index.
963 * Since we have only one group, ring index becomes
964 * absolute index.
965 */
966 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)967 t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
968 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
969 {
970 struct port_info *pi = arg;
971 mac_intr_t *mintr;
972
973 switch (rtype) {
974 case MAC_RING_TYPE_RX: {
975 struct sge_rxq *rxq;
976
977 rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
978 rxq->ring_handle = rh;
979
980 infop->mri_driver = (mac_ring_driver_t)rxq;
981 infop->mri_start = t4_ring_start;
982 infop->mri_stop = NULL;
983 infop->mri_poll = t4_poll_ring;
984 infop->mri_stat = t4_rx_stat;
985
986 mintr = &infop->mri_intr;
987 mintr->mi_handle = (mac_intr_handle_t)rxq;
988 mintr->mi_enable = t4_ring_intr_enable;
989 mintr->mi_disable = t4_ring_intr_disable;
990
991 break;
992 }
993 case MAC_RING_TYPE_TX: {
994 struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index];
995 txq->ring_handle = rh;
996 infop->mri_driver = (mac_ring_driver_t)txq;
997 infop->mri_start = NULL;
998 infop->mri_stop = NULL;
999 infop->mri_tx = t4_eth_tx;
1000 infop->mri_stat = t4_tx_stat;
1001 break;
1002 }
1003 default:
1004 ASSERT(0);
1005 break;
1006 }
1007 }
1008
1009 mblk_t *
t4_mc_tx(void * arg,mblk_t * m)1010 t4_mc_tx(void *arg, mblk_t *m)
1011 {
1012 struct port_info *pi = arg;
1013 struct adapter *sc = pi->adapter;
1014 struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
1015
1016 return (t4_eth_tx(txq, m));
1017 }
1018
1019 static int
t4_mc_transceiver_info(void * arg,uint_t id,mac_transceiver_info_t * infop)1020 t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
1021 {
1022 struct port_info *pi = arg;
1023
1024 if (id != 0 || infop == NULL)
1025 return (EINVAL);
1026
1027 switch (pi->mod_type) {
1028 case FW_PORT_MOD_TYPE_NONE:
1029 mac_transceiver_info_set_present(infop, B_FALSE);
1030 break;
1031 case FW_PORT_MOD_TYPE_NOTSUPPORTED:
1032 mac_transceiver_info_set_present(infop, B_TRUE);
1033 mac_transceiver_info_set_usable(infop, B_FALSE);
1034 break;
1035 default:
1036 mac_transceiver_info_set_present(infop, B_TRUE);
1037 mac_transceiver_info_set_usable(infop, B_TRUE);
1038 break;
1039 }
1040
1041 return (0);
1042 }
1043
1044 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)1045 t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
1046 size_t nbytes, off_t offset, size_t *nread)
1047 {
1048 struct port_info *pi = arg;
1049 struct adapter *sc = pi->adapter;
1050 int rc;
1051 size_t i, maxread;
1052 /* LINTED: E_FUNC_VAR_UNUSED */
1053 struct fw_ldst_cmd ldst __unused;
1054
1055 if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
1056 (page != 0xa0 && page != 0xa2) || offset < 0)
1057 return (EINVAL);
1058
1059 if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
1060 return (EINVAL);
1061
1062 rc = begin_synchronized_op(pi, 0, 1);
1063 if (rc != 0)
1064 return (rc);
1065
1066 /*
1067 * Firmware has a maximum size that we can read. Don't read more than it
1068 * allows.
1069 */
1070 maxread = sizeof (ldst.u.i2c.data);
1071 for (i = 0; i < nbytes; i += maxread) {
1072 size_t toread = MIN(maxread, nbytes - i);
1073 rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
1074 bp);
1075 if (rc != 0)
1076 break;
1077 offset += toread;
1078 bp = (void *)((uintptr_t)bp + toread);
1079 }
1080 end_synchronized_op(pi, 0);
1081 if (rc == 0)
1082 *nread = nbytes;
1083 return (rc);
1084 }
1085
1086 static int
t4_port_led_set(void * arg,mac_led_mode_t mode,uint_t flags)1087 t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
1088 {
1089 struct port_info *pi = arg;
1090 struct adapter *sc = pi->adapter;
1091 int val, rc;
1092
1093 if (flags != 0)
1094 return (EINVAL);
1095
1096 switch (mode) {
1097 case MAC_LED_DEFAULT:
1098 val = 0;
1099 break;
1100 case MAC_LED_IDENT:
1101 val = 0xffff;
1102 break;
1103
1104 default:
1105 return (ENOTSUP);
1106 }
1107
1108 rc = begin_synchronized_op(pi, 1, 1);
1109 if (rc != 0)
1110 return (rc);
1111 rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
1112 end_synchronized_op(pi, 1);
1113
1114 return (rc);
1115 }
1116
1117 static boolean_t
t4_mc_getcapab(void * arg,mac_capab_t cap,void * data)1118 t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
1119 {
1120 struct port_info *pi = arg;
1121 boolean_t status = B_TRUE;
1122 mac_capab_transceiver_t *mct;
1123 mac_capab_led_t *mcl;
1124
1125 switch (cap) {
1126 case MAC_CAPAB_HCKSUM:
1127 if (pi->features & CXGBE_HW_CSUM) {
1128 uint32_t *d = data;
1129 *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM |
1130 HCKSUM_INET_FULL_V6;
1131 } else
1132 status = B_FALSE;
1133 break;
1134
1135 case MAC_CAPAB_LSO:
1136 /* Enabling LSO requires Checksum offloading */
1137 if (pi->features & CXGBE_HW_LSO &&
1138 pi->features & CXGBE_HW_CSUM) {
1139 mac_capab_lso_t *d = data;
1140
1141 d->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
1142 LSO_TX_BASIC_TCP_IPV6;
1143 d->lso_basic_tcp_ipv4.lso_max = 65535;
1144 d->lso_basic_tcp_ipv6.lso_max = 65535;
1145 } else
1146 status = B_FALSE;
1147 break;
1148
1149 case MAC_CAPAB_RINGS: {
1150 mac_capab_rings_t *cap_rings = data;
1151
1152 if (!pi->adapter->props.multi_rings) {
1153 status = B_FALSE;
1154 break;
1155 }
1156 switch (cap_rings->mr_type) {
1157 case MAC_RING_TYPE_RX:
1158 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
1159 cap_rings->mr_rnum = pi->nrxq;
1160 cap_rings->mr_gnum = 1;
1161 cap_rings->mr_rget = t4_fill_ring;
1162 cap_rings->mr_gget = t4_fill_group;
1163 cap_rings->mr_gaddring = NULL;
1164 cap_rings->mr_gremring = NULL;
1165 break;
1166 case MAC_RING_TYPE_TX:
1167 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
1168 cap_rings->mr_rnum = pi->ntxq;
1169 cap_rings->mr_gnum = 0;
1170 cap_rings->mr_rget = t4_fill_ring;
1171 cap_rings->mr_gget = NULL;
1172 break;
1173 }
1174 break;
1175 }
1176
1177 case MAC_CAPAB_TRANSCEIVER:
1178 mct = data;
1179
1180 mct->mct_flags = 0;
1181 mct->mct_ntransceivers = 1;
1182 mct->mct_info = t4_mc_transceiver_info;
1183 mct->mct_read = t4_mc_transceiver_read;
1184 break;
1185 case MAC_CAPAB_LED:
1186 mcl = data;
1187 mcl->mcl_flags = 0;
1188 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
1189 mcl->mcl_set = t4_port_led_set;
1190 break;
1191
1192 default:
1193 status = B_FALSE; /* cap not supported */
1194 }
1195
1196 return (status);
1197 }
1198
t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,link_flowctrl_t * fc)1199 static void t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,
1200 link_flowctrl_t *fc)
1201 {
1202 u8 pause_tx = 0, pause_rx = 0;
1203
1204 if (caps & FW_PORT_CAP32_FC_TX)
1205 pause_tx = 1;
1206
1207 if (caps & FW_PORT_CAP32_FC_RX)
1208 pause_rx = 1;
1209
1210 if (pause_rx & pause_tx)
1211 *fc = LINK_FLOWCTRL_BI;
1212 else if (pause_tx)
1213 *fc = LINK_FLOWCTRL_TX;
1214 else if (pause_rx)
1215 *fc = LINK_FLOWCTRL_RX;
1216 else
1217 *fc = LINK_FLOWCTRL_NONE;
1218 }
1219
t4_mac_flowctrl_to_link_caps(struct port_info * pi,link_flowctrl_t fc,fw_port_cap32_t * new_caps)1220 static int t4_mac_flowctrl_to_link_caps(struct port_info *pi,
1221 link_flowctrl_t fc,
1222 fw_port_cap32_t *new_caps)
1223 {
1224 cc_pause_t pause = 0;
1225
1226 switch (fc) {
1227 case LINK_FLOWCTRL_BI:
1228 pause |= PAUSE_TX | PAUSE_RX;
1229 break;
1230 case LINK_FLOWCTRL_TX:
1231 pause |= PAUSE_TX;
1232 break;
1233 case LINK_FLOWCTRL_RX:
1234 pause |= PAUSE_RX;
1235 break;
1236 default:
1237 break;
1238 }
1239
1240 if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG)
1241 pause |= PAUSE_AUTONEG;
1242
1243 return t4_link_set_pause(pi, pause, new_caps);
1244 }
1245
t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)1246 static link_fec_t t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)
1247 {
1248 link_fec_t link_fec = 0;
1249
1250 if (caps & FW_PORT_CAP32_FEC_RS)
1251 link_fec |= LINK_FEC_RS;
1252
1253 if (caps & FW_PORT_CAP32_FEC_BASER_RS)
1254 link_fec |= LINK_FEC_BASE_R;
1255
1256 if (caps & FW_PORT_CAP32_FEC_NO_FEC)
1257 link_fec |= LINK_FEC_NONE;
1258
1259 if ((link_fec & (link_fec - 1)) &&
1260 !(caps & FW_PORT_CAP32_FORCE_FEC))
1261 return LINK_FEC_AUTO;
1262
1263 return link_fec;
1264 }
1265
t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)1266 static void t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,
1267 link_fec_t *fec)
1268 {
1269 *fec = t4_mac_port_caps_to_fec_cap(caps);
1270 }
1271
t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)1272 static void t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,
1273 link_fec_t *fec)
1274 {
1275 link_fec_t link_fec;
1276
1277 caps &= ~FW_PORT_CAP32_FEC_NO_FEC;
1278 link_fec = t4_mac_port_caps_to_fec_cap(caps);
1279 *fec = link_fec ? link_fec : LINK_FEC_NONE;
1280 }
1281
t4_mac_fec_cap_to_link_caps(struct port_info * pi,link_fec_t v,fw_port_cap32_t * new_caps)1282 static int 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",
1427 __func__, rc);
1428 return (rc);
1429 }
1430 }
1431
1432 if (rx_mode != 0) {
1433 rc = begin_synchronized_op(pi, 1, 1);
1434 if (rc != 0)
1435 return (rc);
1436 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
1437 -1, -1, -1, false);
1438 end_synchronized_op(pi, 1);
1439 if (rc != 0) {
1440 cxgb_printf(pi->dip, CE_WARN,
1441 "set_rxmode failed: %d", rc);
1442 return (rc);
1443 }
1444 }
1445 }
1446
1447 if (relink != 0)
1448 lc->admin_caps = new_caps;
1449
1450 return (0);
1451 }
1452
1453 static int
t4_mc_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,void * val)1454 t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
1455 void *val)
1456 {
1457 struct port_info *pi = arg;
1458 struct link_config *lc = &pi->link_cfg;
1459 uint8_t *u = val;
1460 int rc = 0;
1461
1462 switch (id) {
1463 case MAC_PROP_DUPLEX:
1464 *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
1465 LINK_DUPLEX_UNKNOWN;
1466 break;
1467
1468 case MAC_PROP_SPEED:
1469 if (lc->link_ok != 0) {
1470 *(uint64_t *)val = 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