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
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.
13 * This file is part of the Chelsio T4 support code.
15 * Copyright (C) 2010-2013 Chelsio Communications. All rights reserved.
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.
24 * Copyright 2020 RackTop Systems, Inc.
25 * Copyright 2023 Oxide Computer Company
29 #include <sys/sunddi.h>
31 #include <sys/mac_provider.h>
32 #include <sys/mac_ether.h>
33 #include <sys/strsubr.h>
34 #include <sys/queue.h>
36 #include "common/common.h"
37 #include "common/t4_regs.h"
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
);
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
,
59 static int setprop(struct port_info
*pi
, const char *name
, const void *val
);
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
,
70 .mc_getcapab
= t4_mc_getcapab
,
71 .mc_setprop
= t4_mc_setprop
,
72 .mc_getprop
= t4_mc_getprop
,
73 .mc_propinfo
= t4_mc_propinfo
,
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.
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
,
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"
103 char *t4_priv_props
[] = {
107 /* MAC_VERSION 1 doesn't seem to use MAC_PROP_MTU, hmmmm */
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
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).
131 fw_port_cap32_t tmm_speed
;
132 mac_ether_media_t tmm_ether
;
135 static const t4nex_media_map_t t4nex_map_baset
[] = {
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.
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
}
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
}
151 static const t4nex_media_map_t t4nex_map_cx
[] = {
152 { FW_PORT_CAP32_SPEED_10G
, ETHER_MEDIA_10GBASE_CX4
}
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
},
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
},
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
},
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
},
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
},
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
},
207 static const t4nex_media_map_t t4nex_map_lrm
[] = {
208 { FW_PORT_CAP32_SPEED_10G
, ETHER_MEDIA_10GBASE_LRM
},
211 static mac_ether_media_t
212 t4_port_to_media(struct port_info
*pi
)
214 fw_port_cap32_t speed
;
215 struct link_config
*lc
= &pi
->link_cfg
;
216 const t4nex_media_map_t
*map
= NULL
;
219 if (lc
->link_ok
!= 0) {
220 speed
= t4_link_fwcap_to_fwspeed(lc
->link_caps
);
222 return (ETHER_MEDIA_UNKNOWN
);
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
:
239 count
= ARRAY_SIZE(t4nex_map_lr
);
241 case FW_PORT_MOD_TYPE_SR
:
243 count
= ARRAY_SIZE(t4nex_map_sr
);
245 case FW_PORT_MOD_TYPE_ER
:
247 count
= ARRAY_SIZE(t4nex_map_er
);
249 case FW_PORT_MOD_TYPE_TWINAX_PASSIVE
:
251 count
= ARRAY_SIZE(t4nex_map_cr
);
253 case FW_PORT_MOD_TYPE_TWINAX_ACTIVE
:
255 count
= ARRAY_SIZE(t4nex_map_acc
);
257 case FW_PORT_MOD_TYPE_LRM
:
259 count
= ARRAY_SIZE(t4nex_map_lrm
);
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
:
270 case FW_PORT_TYPE_KX4
:
271 case FW_PORT_TYPE_KX
:
273 count
= ARRAY_SIZE(t4nex_map_kx
);
275 case FW_PORT_TYPE_CX4
:
277 count
= ARRAY_SIZE(t4nex_map_cx
);
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
:
287 count
= ARRAY_SIZE(t4nex_map_kr
);
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
);
295 case FW_PORT_TYPE_NONE
:
300 for (size_t i
= 0; i
< count
; i
++) {
301 if (map
[i
].tmm_speed
== speed
) {
302 return (map
[i
].tmm_ether
);
307 * At this point we return unknown as we already checked for a down link
310 return (ETHER_MEDIA_UNKNOWN
);
314 t4_mc_getstat(void *arg
, uint_t stat
, uint64_t *val
)
316 struct port_info
*pi
= arg
;
317 struct adapter
*sc
= pi
->adapter
;
318 struct link_config
*lc
= &pi
->link_cfg
;
320 #define GET_STAT(name) \
321 t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
324 case MAC_STAT_IFSPEED
:
325 if (lc
->link_ok
!= 0) {
326 *val
= t4_link_fwcap_to_speed(lc
->link_caps
);
332 case MAC_STAT_MULTIRCV
:
333 *val
= GET_STAT(RX_PORT_MCAST
);
336 case MAC_STAT_BRDCSTRCV
:
337 *val
= GET_STAT(RX_PORT_BCAST
);
340 case MAC_STAT_MULTIXMT
:
341 *val
= GET_STAT(TX_PORT_MCAST
);
344 case MAC_STAT_BRDCSTXMT
:
345 *val
= GET_STAT(TX_PORT_BCAST
);
348 case MAC_STAT_NORCVBUF
:
349 *val
= 0; /* TODO should come from rxq->nomem */
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
);
361 case MAC_STAT_UNKNOWNS
:
364 case MAC_STAT_NOXMTBUF
:
365 *val
= GET_STAT(TX_PORT_DROP
);
368 case MAC_STAT_OERRORS
:
369 *val
= GET_STAT(TX_PORT_ERROR
);
372 case MAC_STAT_COLLISIONS
:
375 case MAC_STAT_RBYTES
:
376 *val
= GET_STAT(RX_PORT_BYTES
);
379 case MAC_STAT_IPACKETS
:
380 *val
= GET_STAT(RX_PORT_FRAMES
);
383 case MAC_STAT_OBYTES
:
384 *val
= GET_STAT(TX_PORT_BYTES
);
387 case MAC_STAT_OPACKETS
:
388 *val
= GET_STAT(TX_PORT_FRAMES
);
391 case ETHER_STAT_ALIGN_ERRORS
:
394 case ETHER_STAT_FCS_ERRORS
:
395 *val
= GET_STAT(RX_PORT_CRC_ERROR
);
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
:
406 case ETHER_STAT_MACXMT_ERRORS
:
407 *val
= GET_STAT(TX_PORT_ERROR
);
410 case ETHER_STAT_CARRIER_ERRORS
:
413 case ETHER_STAT_TOOLONG_ERRORS
:
414 *val
= GET_STAT(RX_PORT_MTU_ERROR
);
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
);
426 case ETHER_STAT_XCVR_ADDR
:
427 case ETHER_STAT_XCVR_ID
:
429 case ETHER_STAT_XCVR_INUSE
:
430 *val
= t4_port_to_media(pi
);
433 case ETHER_STAT_CAP_100GFDX
:
434 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_100G
);
437 case ETHER_STAT_CAP_50GFDX
:
438 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_50G
);
441 case ETHER_STAT_CAP_40GFDX
:
442 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_40G
);
445 case ETHER_STAT_CAP_25GFDX
:
446 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_25G
);
449 case ETHER_STAT_CAP_10GFDX
:
450 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_10G
);
453 case ETHER_STAT_CAP_1000FDX
:
454 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_1G
);
457 case ETHER_STAT_CAP_100FDX
:
458 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_SPEED_100M
);
461 case ETHER_STAT_CAP_1000HDX
:
462 case ETHER_STAT_CAP_100HDX
:
463 case ETHER_STAT_CAP_10FDX
:
464 case ETHER_STAT_CAP_10HDX
:
467 case ETHER_STAT_CAP_ASMPAUSE
:
468 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_FC_RX
);
471 case ETHER_STAT_CAP_PAUSE
:
472 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_FC_TX
);
475 case ETHER_STAT_CAP_AUTONEG
:
476 *val
= !!(lc
->pcaps
& FW_PORT_CAP32_ANEG
);
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
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
491 * +----------------------------+----------------------------------+
492 * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause |
493 * +-------------------------+-------------------------------------+
498 * +----------------------------+----------------------------------+
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
);
506 *val
= (!!(lc
->admin_caps
& FW_PORT_CAP32_FC_TX
)) ^
507 (!!(lc
->admin_caps
& FW_PORT_CAP32_FC_RX
));
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
);
515 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_FC_TX
);
518 case ETHER_STAT_ADV_CAP_100GFDX
:
519 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_100G
);
522 case ETHER_STAT_ADV_CAP_50GFDX
:
523 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_50G
);
526 case ETHER_STAT_ADV_CAP_40GFDX
:
527 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_40G
);
530 case ETHER_STAT_ADV_CAP_25GFDX
:
531 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_25G
);
534 case ETHER_STAT_ADV_CAP_10GFDX
:
535 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_10G
);
538 case ETHER_STAT_ADV_CAP_1000FDX
:
539 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_1G
);
542 case ETHER_STAT_ADV_CAP_100FDX
:
543 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_100M
);
546 case ETHER_STAT_ADV_CAP_AUTONEG
:
547 *val
= !!(lc
->admin_caps
& FW_PORT_CAP32_ANEG
);
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 */
556 case ETHER_STAT_LP_CAP_ASMPAUSE
:
557 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
560 if (lc
->pcaps
& FW_PORT_CAP32_802_3_ASM_DIR
)
561 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_802_3_ASM_DIR
);
563 *val
= (!!(lc
->lpacaps
& FW_PORT_CAP32_FC_TX
)) ^
564 (!!(lc
->lpacaps
& FW_PORT_CAP32_FC_RX
));
567 case ETHER_STAT_LP_CAP_PAUSE
:
568 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
571 if (lc
->pcaps
& FW_PORT_CAP32_802_3_PAUSE
)
572 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_802_3_PAUSE
);
574 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_FC_TX
);
577 case ETHER_STAT_LP_CAP_100GFDX
:
578 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
581 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_100G
);
584 case ETHER_STAT_LP_CAP_50GFDX
:
585 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
588 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_50G
);
591 case ETHER_STAT_LP_CAP_40GFDX
:
592 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
595 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_40G
);
598 case ETHER_STAT_LP_CAP_25GFDX
:
599 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
602 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_25G
);
605 case ETHER_STAT_LP_CAP_10GFDX
:
606 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
609 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_10G
);
612 case ETHER_STAT_LP_CAP_1000FDX
:
613 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
616 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_1G
);
619 case ETHER_STAT_LP_CAP_100FDX
:
620 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
623 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_SPEED_100M
);
626 case ETHER_STAT_LP_CAP_AUTONEG
:
627 if (!(lc
->acaps
& FW_PORT_CAP32_ANEG
))
630 *val
= !!(lc
->lpacaps
& FW_PORT_CAP32_ANEG
);
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
:
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
));
644 case ETHER_STAT_LINK_PAUSE
:
645 *val
= !!(lc
->link_caps
& FW_PORT_CAP32_FC_TX
);
648 case ETHER_STAT_LINK_AUTONEG
:
649 *val
= !!(lc
->link_caps
& FW_PORT_CAP32_ANEG
);
652 case ETHER_STAT_LINK_DUPLEX
:
653 if (lc
->link_ok
!= 0)
654 *val
= LINK_DUPLEX_FULL
;
656 *val
= LINK_DUPLEX_UNKNOWN
;
668 t4_mc_start(void *arg
)
670 struct port_info
*pi
= arg
;
673 rc
= begin_synchronized_op(pi
, 0, 1);
676 rc
= t4_init_synchronized(pi
);
677 end_synchronized_op(pi
, 0);
683 t4_mc_stop(void *arg
)
685 struct port_info
*pi
= arg
;
687 while (begin_synchronized_op(pi
, 0, 1) != 0)
689 (void) t4_uninit_synchronized(pi
);
690 end_synchronized_op(pi
, 0);
694 t4_mc_setpromisc(void *arg
, boolean_t on
)
696 struct port_info
*pi
= arg
;
697 struct adapter
*sc
= pi
->adapter
;
700 rc
= begin_synchronized_op(pi
, 1, 1);
703 rc
= -t4_set_rxmode(sc
, sc
->mbox
, pi
->viid
, -1, on
? 1 : 0, -1, -1, -1,
705 end_synchronized_op(pi
, 1);
711 * TODO: Starts failing as soon as the 336 entry table fills up. Need to use
715 t4_mc_multicst(void *arg
, boolean_t add
, const uint8_t *mcaddr
)
717 struct port_info
*pi
= arg
;
718 struct adapter
*sc
= pi
->adapter
;
719 struct fw_vi_mac_cmd c
;
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
);
732 rc
= begin_synchronized_op(pi
, 1, 1);
735 rc
= -t4_wr_mbox_meat(sc
, sc
->mbox
, &c
, len16
* 16, &c
, true);
736 end_synchronized_op(pi
, 1);
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.
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
);
760 t4_mc_unicst(void *arg
, const uint8_t *ucaddr
)
762 struct port_info
*pi
= arg
;
763 struct adapter
*sc
= pi
->adapter
;
769 rc
= begin_synchronized_op(pi
, 1, 1);
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);
778 rc
= t4_change_mac(sc
, sc
->mbox
, pi
->viid
, pi
->xact_addr_filt
, ucaddr
,
784 pi
->xact_addr_filt
= rc
;
787 end_synchronized_op(pi
, 1);
793 t4_addmac(void *arg
, const uint8_t *ucaddr
)
795 return (t4_mc_unicst(arg
, ucaddr
));
799 t4_remmac(void *arg
, const uint8_t *mac_addr
)
801 struct port_info
*pi
= arg
;
804 rc
= begin_synchronized_op(pi
, 1, 1);
809 end_synchronized_op(pi
, 1);
815 * Callback funtion for MAC layer to register all groups.
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
)
821 struct port_info
*pi
= arg
;
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
;
833 case MAC_RING_TYPE_TX
:
841 t4_ring_start(mac_ring_driver_t rh
, uint64_t mr_gen_num
)
843 struct sge_rxq
*rxq
= (struct sge_rxq
*)rh
;
846 rxq
->ring_gen_num
= mr_gen_num
;
852 * Enable interrupt on the specificed rx ring.
855 t4_ring_intr_enable(mac_intr_handle_t intrh
)
857 struct sge_rxq
*rxq
= (struct sge_rxq
*)intrh
;
858 struct adapter
*sc
= rxq
->port
->adapter
;
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
));
872 * Disable interrupt on the specificed rx ring.
875 t4_ring_intr_disable(mac_intr_handle_t intrh
)
877 struct sge_rxq
*rxq
= (struct sge_rxq
*)intrh
;
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.
888 iq
->state
= IQS_BUSY
;
894 t4_poll_ring(void *arg
, int n_bytes
)
896 struct sge_rxq
*rxq
= (struct sge_rxq
*)arg
;
899 ASSERT(n_bytes
>= 0);
904 mp
= t4_ring_rx(rxq
, n_bytes
);
911 * Retrieve a value for one of the statistics for a particular rx ring
914 t4_rx_stat(mac_ring_driver_t rh
, uint_t stat
, uint64_t *val
)
916 struct sge_rxq
*rxq
= (struct sge_rxq
*)rh
;
919 case MAC_STAT_RBYTES
:
923 case MAC_STAT_IPACKETS
:
936 * Retrieve a value for one of the statistics for a particular tx ring
939 t4_tx_stat(mac_ring_driver_t rh
, uint_t stat
, uint64_t *val
)
941 struct sge_txq
*txq
= (struct sge_txq
*)rh
;
944 case MAC_STAT_RBYTES
:
948 case MAC_STAT_IPACKETS
:
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
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
)
970 struct port_info
*pi
= arg
;
974 case MAC_RING_TYPE_RX
: {
977 rxq
= &pi
->adapter
->sge
.rxq
[pi
->first_rxq
+ ring_index
];
978 rxq
->ring_handle
= rh
;
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
;
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
;
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
;
1010 t4_mc_tx(void *arg
, mblk_t
*m
)
1012 struct port_info
*pi
= arg
;
1013 struct adapter
*sc
= pi
->adapter
;
1014 struct sge_txq
*txq
= &sc
->sge
.txq
[pi
->first_txq
];
1016 return (t4_eth_tx(txq
, m
));
1020 t4_mc_transceiver_info(void *arg
, uint_t id
, mac_transceiver_info_t
*infop
)
1022 struct port_info
*pi
= arg
;
1024 if (id
!= 0 || infop
== NULL
)
1027 switch (pi
->mod_type
) {
1028 case FW_PORT_MOD_TYPE_NONE
:
1029 mac_transceiver_info_set_present(infop
, B_FALSE
);
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
);
1036 mac_transceiver_info_set_present(infop
, B_TRUE
);
1037 mac_transceiver_info_set_usable(infop
, B_TRUE
);
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
)
1048 struct port_info
*pi
= arg
;
1049 struct adapter
*sc
= pi
->adapter
;
1052 /* LINTED: E_FUNC_VAR_UNUSED */
1053 struct fw_ldst_cmd ldst __unused
;
1055 if (id
!= 0 || bp
== NULL
|| nbytes
== 0 || nread
== NULL
||
1056 (page
!= 0xa0 && page
!= 0xa2) || offset
< 0)
1059 if (nbytes
> 256 || offset
>= 256 || (offset
+ nbytes
> 256))
1062 rc
= begin_synchronized_op(pi
, 0, 1);
1067 * Firmware has a maximum size that we can read. Don't read more than it
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
,
1078 bp
= (void *)((uintptr_t)bp
+ toread
);
1080 end_synchronized_op(pi
, 0);
1087 t4_port_led_set(void *arg
, mac_led_mode_t mode
, uint_t flags
)
1089 struct port_info
*pi
= arg
;
1090 struct adapter
*sc
= pi
->adapter
;
1097 case MAC_LED_DEFAULT
:
1108 rc
= begin_synchronized_op(pi
, 1, 1);
1111 rc
= -t4_identify_port(sc
, sc
->mbox
, pi
->viid
, val
);
1112 end_synchronized_op(pi
, 1);
1118 t4_mc_getcapab(void *arg
, mac_capab_t cap
, void *data
)
1120 struct port_info
*pi
= arg
;
1121 boolean_t status
= B_TRUE
;
1122 mac_capab_transceiver_t
*mct
;
1123 mac_capab_led_t
*mcl
;
1126 case MAC_CAPAB_HCKSUM
:
1127 if (pi
->features
& CXGBE_HW_CSUM
) {
1129 *d
= HCKSUM_INET_FULL_V4
| HCKSUM_IPHDRCKSUM
|
1130 HCKSUM_INET_FULL_V6
;
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
;
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;
1149 case MAC_CAPAB_RINGS
: {
1150 mac_capab_rings_t
*cap_rings
= data
;
1152 if (!pi
->adapter
->props
.multi_rings
) {
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
;
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
;
1177 case MAC_CAPAB_TRANSCEIVER
:
1181 mct
->mct_ntransceivers
= 1;
1182 mct
->mct_info
= t4_mc_transceiver_info
;
1183 mct
->mct_read
= t4_mc_transceiver_read
;
1188 mcl
->mcl_modes
= MAC_LED_DEFAULT
| MAC_LED_IDENT
;
1189 mcl
->mcl_set
= t4_port_led_set
;
1193 status
= B_FALSE
; /* cap not supported */
1199 static void t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps
,
1200 link_flowctrl_t
*fc
)
1202 u8 pause_tx
= 0, pause_rx
= 0;
1204 if (caps
& FW_PORT_CAP32_FC_TX
)
1207 if (caps
& FW_PORT_CAP32_FC_RX
)
1210 if (pause_rx
& pause_tx
)
1211 *fc
= LINK_FLOWCTRL_BI
;
1213 *fc
= LINK_FLOWCTRL_TX
;
1215 *fc
= LINK_FLOWCTRL_RX
;
1217 *fc
= LINK_FLOWCTRL_NONE
;
1220 static int t4_mac_flowctrl_to_link_caps(struct port_info
*pi
,
1222 fw_port_cap32_t
*new_caps
)
1224 cc_pause_t pause
= 0;
1227 case LINK_FLOWCTRL_BI
:
1228 pause
|= PAUSE_TX
| PAUSE_RX
;
1230 case LINK_FLOWCTRL_TX
:
1233 case LINK_FLOWCTRL_RX
:
1240 if (pi
->link_cfg
.admin_caps
& FW_PORT_CAP32_ANEG
)
1241 pause
|= PAUSE_AUTONEG
;
1243 return t4_link_set_pause(pi
, pause
, new_caps
);
1246 static link_fec_t
t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps
)
1248 link_fec_t link_fec
= 0;
1250 if (caps
& FW_PORT_CAP32_FEC_RS
)
1251 link_fec
|= LINK_FEC_RS
;
1253 if (caps
& FW_PORT_CAP32_FEC_BASER_RS
)
1254 link_fec
|= LINK_FEC_BASE_R
;
1256 if (caps
& FW_PORT_CAP32_FEC_NO_FEC
)
1257 link_fec
|= LINK_FEC_NONE
;
1259 if ((link_fec
& (link_fec
- 1)) &&
1260 !(caps
& FW_PORT_CAP32_FORCE_FEC
))
1261 return LINK_FEC_AUTO
;
1266 static void t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps
,
1269 *fec
= t4_mac_port_caps_to_fec_cap(caps
);
1272 static void t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps
,
1275 link_fec_t link_fec
;
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
;
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
)
1287 if (v
== LINK_FEC_AUTO
) {
1292 if (v
& LINK_FEC_NONE
) {
1293 v
&= ~LINK_FEC_NONE
;
1297 if (v
& LINK_FEC_RS
) {
1302 if (v
& LINK_FEC_BASE_R
) {
1303 v
&= ~LINK_FEC_BASE_R
;
1304 fec
|= FEC_BASER_RS
;
1310 ASSERT3S(fec
, !=, 0);
1315 return t4_link_set_fec(pi
, fec
, new_caps
);
1320 t4_mc_setprop(void *arg
, const char *name
, mac_prop_id_t id
, uint_t size
,
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
;
1334 case MAC_PROP_AUTONEG
:
1335 rc
= t4_link_set_autoneg(pi
, v8
, &new_caps
);
1340 if (v32
< 46 || v32
> MAX_MTU
) {
1342 } else if (v32
!= pi
->mtu
) {
1344 (void) mac_maxsdu_update(pi
->mh
, v32
);
1350 case MAC_PROP_FLOWCTRL
:
1351 fc
= *(link_flowctrl_t
*)val
;
1352 rc
= t4_mac_flowctrl_to_link_caps(pi
, fc
, &new_caps
);
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
);
1362 case MAC_PROP_EN_100GFDX_CAP
:
1363 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_100G
, v8
,
1368 case MAC_PROP_EN_50GFDX_CAP
:
1369 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_50G
, v8
,
1374 case MAC_PROP_EN_40GFDX_CAP
:
1375 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_40G
, v8
,
1380 case MAC_PROP_EN_25GFDX_CAP
:
1381 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_25G
, v8
,
1386 case MAC_PROP_EN_10GFDX_CAP
:
1387 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_10G
, v8
,
1392 case MAC_PROP_EN_1000FDX_CAP
:
1393 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_1G
, v8
,
1398 case MAC_PROP_EN_100FDX_CAP
:
1399 rc
= t4_link_set_speed(pi
, FW_PORT_CAP32_SPEED_100M
, v8
,
1404 case MAC_PROP_PRIVATE
:
1405 rc
= setprop(pi
, name
, val
);
1416 if (isset(&sc
->open_device_map
, pi
->port_id
) != 0) {
1418 rc
= begin_synchronized_op(pi
, 1, 1);
1421 rc
= -t4_link_l1cfg(sc
, sc
->mbox
, pi
->tx_chan
, lc
,
1423 end_synchronized_op(pi
, 1);
1425 cxgb_printf(pi
->dip
, CE_WARN
,
1426 "%s link config failed: %d",
1433 rc
= begin_synchronized_op(pi
, 1, 1);
1436 rc
= -t4_set_rxmode(sc
, sc
->mbox
, pi
->viid
, v32
, -1,
1438 end_synchronized_op(pi
, 1);
1440 cxgb_printf(pi
->dip
, CE_WARN
,
1441 "set_rxmode failed: %d", rc
);
1448 lc
->admin_caps
= new_caps
;
1454 t4_mc_getprop(void *arg
, const char *name
, mac_prop_id_t id
, uint_t size
,
1457 struct port_info
*pi
= arg
;
1458 struct link_config
*lc
= &pi
->link_cfg
;
1463 case MAC_PROP_DUPLEX
:
1464 *(link_duplex_t
*)val
= lc
->link_ok
? LINK_DUPLEX_FULL
:
1465 LINK_DUPLEX_UNKNOWN
;
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;
1473 *(uint64_t *)val
= 0;
1477 case MAC_PROP_STATUS
:
1478 *(link_state_t
*)val
= lc
->link_ok
? LINK_STATE_UP
:
1482 case MAC_PROP_MEDIA
:
1483 *(mac_ether_media_t
*)val
= t4_port_to_media(pi
);
1486 case MAC_PROP_AUTONEG
:
1487 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_ANEG
);
1491 *(uint32_t *)val
= pi
->mtu
;
1494 case MAC_PROP_FLOWCTRL
:
1495 t4_mac_link_caps_to_flowctrl(lc
->link_caps
, val
);
1498 case MAC_PROP_ADV_FEC_CAP
:
1499 t4_mac_link_caps_to_fec_cap(lc
->link_caps
, val
);
1502 case MAC_PROP_EN_FEC_CAP
:
1503 t4_mac_admin_caps_to_fec_cap(lc
->admin_caps
, val
);
1506 case MAC_PROP_ADV_100GFDX_CAP
:
1507 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_100G
);
1510 case MAC_PROP_EN_100GFDX_CAP
:
1511 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_100G
);
1514 case MAC_PROP_ADV_50GFDX_CAP
:
1515 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_50G
);
1518 case MAC_PROP_EN_50GFDX_CAP
:
1519 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_50G
);
1522 case MAC_PROP_ADV_40GFDX_CAP
:
1523 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_40G
);
1526 case MAC_PROP_EN_40GFDX_CAP
:
1527 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_40G
);
1530 case MAC_PROP_ADV_25GFDX_CAP
:
1531 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_25G
);
1534 case MAC_PROP_EN_25GFDX_CAP
:
1535 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_25G
);
1538 case MAC_PROP_ADV_10GFDX_CAP
:
1539 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_10G
);
1542 case MAC_PROP_EN_10GFDX_CAP
:
1543 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_10G
);
1546 case MAC_PROP_ADV_1000FDX_CAP
:
1547 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_1G
);
1550 case MAC_PROP_EN_1000FDX_CAP
:
1551 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_1G
);
1554 case MAC_PROP_ADV_100FDX_CAP
:
1555 *u
= !!(lc
->link_caps
& FW_PORT_CAP32_SPEED_100M
);
1558 case MAC_PROP_EN_100FDX_CAP
:
1559 *u
= !!(lc
->admin_caps
& FW_PORT_CAP32_SPEED_100M
);
1562 case MAC_PROP_PRIVATE
:
1563 return (getprop(pi
, name
, size
, val
));
1573 t4_mc_propinfo(void *arg
, const char *name
, mac_prop_id_t id
,
1574 mac_prop_info_handle_t ph
)
1576 struct port_info
*pi
= arg
;
1577 struct link_config
*lc
= &pi
->link_cfg
;
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
);
1586 case MAC_PROP_AUTONEG
:
1587 if (lc
->pcaps
& FW_PORT_CAP32_ANEG
)
1588 mac_prop_info_set_default_uint8(ph
, 1);
1590 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
1594 mac_prop_info_set_range_uint32(ph
, 46, MAX_MTU
);
1597 case MAC_PROP_FLOWCTRL
:
1598 mac_prop_info_set_default_link_flowctrl(ph
, LINK_FLOWCTRL_BI
);
1601 case MAC_PROP_EN_FEC_CAP
:
1602 mac_prop_info_set_default_fec(ph
, LINK_FEC_AUTO
);
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
);
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);
1614 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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);
1621 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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);
1628 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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);
1635 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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);
1642 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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);
1649 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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);
1656 mac_prop_info_set_perm(ph
, MAC_PROP_PERM_READ
);
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
);
1669 case MAC_PROP_PRIVATE
:
1670 propinfo(pi
, name
, ph
);
1679 begin_synchronized_op(struct port_info
*pi
, int hold
, int waitok
)
1681 struct adapter
*sc
= pi
->adapter
;
1685 while (!IS_DOOMED(pi
) && IS_BUSY(sc
)) {
1689 } else if (cv_wait_sig(&sc
->cv
, &sc
->lock
) == 0) {
1694 if (IS_DOOMED(pi
) != 0) { /* shouldn't happen on Solaris */
1698 ASSERT(!IS_BUSY(sc
));
1699 /* LINTED: E_CONSTANT_CONDITION */
1712 end_synchronized_op(struct port_info
*pi
, int held
)
1714 struct adapter
*sc
= pi
->adapter
;
1719 ADAPTER_LOCK_ASSERT_OWNED(sc
);
1720 ASSERT(IS_BUSY(sc
));
1721 /* LINTED: E_CONSTANT_CONDITION */
1728 t4_init_synchronized(struct port_info
*pi
)
1730 struct adapter
*sc
= pi
->adapter
;
1733 ADAPTER_LOCK_ASSERT_NOTOWNED(sc
);
1735 if (isset(&sc
->open_device_map
, pi
->port_id
) != 0)
1736 return (0); /* already running */
1738 if (!(sc
->flags
& FULL_INIT_DONE
) &&
1739 ((rc
= adapter_full_init(sc
)) != 0))
1740 return (rc
); /* error message displayed already */
1742 if (!(pi
->flags
& PORT_INIT_DONE
)) {
1743 rc
= port_full_init(pi
);
1745 return (rc
); /* error message displayed already */
1747 enable_port_queues(pi
);
1749 rc
= -t4_set_rxmode(sc
, sc
->mbox
, pi
->viid
, pi
->mtu
, 0, 0, 1, 0, false);
1751 cxgb_printf(pi
->dip
, CE_WARN
, "set_rxmode failed: %d", rc
);
1754 rc
= t4_change_mac(sc
, sc
->mbox
, pi
->viid
, pi
->xact_addr_filt
,
1755 pi
->hw_addr
, true, &pi
->smt_idx
);
1757 cxgb_printf(pi
->dip
, CE_WARN
, "change_mac failed: %d", rc
);
1761 /* LINTED: E_ASSIGN_NARROW_CONV */
1762 pi
->xact_addr_filt
= rc
;
1764 rc
= -t4_link_l1cfg(sc
, sc
->mbox
, pi
->tx_chan
, &pi
->link_cfg
,
1765 pi
->link_cfg
.admin_caps
);
1767 cxgb_printf(pi
->dip
, CE_WARN
, "start_link failed: %d", rc
);
1771 rc
= -t4_enable_vi(sc
, sc
->mbox
, pi
->viid
, true, true);
1773 cxgb_printf(pi
->dip
, CE_WARN
, "enable_vi failed: %d", rc
);
1778 setbit(&sc
->open_device_map
, pi
->port_id
);
1781 (void) t4_uninit_synchronized(pi
);
1790 t4_uninit_synchronized(struct port_info
*pi
)
1792 struct adapter
*sc
= pi
->adapter
;
1795 ADAPTER_LOCK_ASSERT_NOTOWNED(sc
);
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
1804 rc
= -t4_enable_vi(sc
, sc
->mbox
, pi
->viid
, false, false);
1806 cxgb_printf(pi
->dip
, CE_WARN
, "disable_vi failed: %d", rc
);
1810 disable_port_queues(pi
);
1812 clrbit(&sc
->open_device_map
, pi
->port_id
);
1814 pi
->link_cfg
.link_ok
= 0;
1815 mac_link_update(pi
->mh
, LINK_STATE_UNKNOWN
);
1821 propinfo(struct port_info
*pi
, const char *name
, mac_prop_info_handle_t ph
)
1823 struct adapter
*sc
= pi
->adapter
;
1824 struct driver_properties
*p
= &sc
->props
;
1825 struct link_config
*lc
= &pi
->link_cfg
;
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)
1848 (void) snprintf(str
, sizeof (str
), "%d", v
);
1849 mac_prop_info_set_default_str(ph
, str
);
1853 getprop(struct port_info
*pi
, const char *name
, uint_t size
, void *val
)
1855 struct link_config
*lc
= &pi
->link_cfg
;
1858 if (strcmp(name
, T4PROP_TMR_IDX
) == 0)
1860 else if (strcmp(name
, T4PROP_PKTC_IDX
) == 0)
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)
1877 (void) snprintf(val
, size
, "%d", v
);
1882 setprop(struct port_info
*pi
, const char *name
, const void *val
)
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
;
1892 (void) ddi_strtol(val
, NULL
, 0, &v
);
1894 if (strcmp(name
, T4PROP_TMR_IDX
) == 0) {
1895 if (v
< 0 || v
>= SGE_NTIMERS
)
1897 if (v
== pi
->tmr_idx
)
1900 /* LINTED: E_ASSIGN_NARROW_CONV */
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);
1907 } else if (strcmp(name
, T4PROP_PKTC_IDX
) == 0) {
1908 if (v
>= SGE_NCOUNTERS
)
1910 if (v
== pi
->pktc_idx
|| (v
< 0 && pi
->pktc_idx
== -1))
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 */
1922 } else if (strcmp(name
, T4PROP_HW_CSUM
) == 0) {
1923 if (v
!= 0 && v
!= 1)
1926 pi
->features
|= CXGBE_HW_CSUM
;
1928 pi
->features
&= ~CXGBE_HW_CSUM
;
1929 } else if (strcmp(name
, T4PROP_HW_LSO
) == 0) {
1930 if (v
!= 0 && v
!= 1)
1933 pi
->features
|= CXGBE_HW_LSO
;
1935 pi
->features
&= ~CXGBE_HW_LSO
;
1936 } else if (strcmp(name
, T4PROP_TX_PAUSE
) == 0) {
1937 if (v
!= 0 && v
!= 1)
1940 if ((new_caps
& FW_PORT_CAP32_FC_TX
) && (v
== 1))
1942 if (new_caps
& FW_PORT_CAP32_FC_RX
)
1944 if (lc
->admin_caps
& FW_PORT_CAP32_ANEG
)
1945 fc
|= PAUSE_AUTONEG
;
1947 t4_link_set_pause(pi
, fc
, &new_caps
);
1950 } else if (strcmp(name
, T4PROP_RX_PAUSE
) == 0) {
1951 if (v
!= 0 && v
!= 1)
1954 if (new_caps
& FW_PORT_CAP32_FC_TX
)
1956 if ((new_caps
& FW_PORT_CAP32_FC_RX
) && (v
== 1))
1958 if (lc
->admin_caps
& FW_PORT_CAP32_ANEG
)
1959 fc
|= PAUSE_AUTONEG
;
1961 t4_link_set_pause(pi
, fc
, &new_caps
);
1964 #if MAC_VERSION == 1
1965 else if (strcmp(name
, T4PROP_MTU
) == 0) {
1966 if (v
< 46 || v
> MAX_MTU
)
1972 (void) mac_maxsdu_update(pi
->mh
, v
);
1979 if (!(relink
|| rx_mode
))
1982 /* If we are here, either relink or rx_mode is 1 */
1983 if (isset(&sc
->open_device_map
, pi
->port_id
) != 0) {
1985 rc
= begin_synchronized_op(pi
, 1, 1);
1988 rc
= -t4_link_l1cfg(sc
, sc
->mbox
, pi
->tx_chan
, lc
,
1990 end_synchronized_op(pi
, 1);
1992 cxgb_printf(pi
->dip
, CE_WARN
,
1993 "%s link config failed: %d",
1997 } else if (rx_mode
!= 0) {
1998 rc
= begin_synchronized_op(pi
, 1, 1);
2001 rc
= -t4_set_rxmode(sc
, sc
->mbox
, pi
->viid
, v
, -1, -1,
2003 end_synchronized_op(pi
, 1);
2005 cxgb_printf(pi
->dip
, CE_WARN
,
2006 "set_rxmode failed: %d", rc
);
2013 lc
->admin_caps
= new_caps
;
2019 t4_mc_init(struct port_info
*pi
)
2021 pi
->props
= t4_priv_props
;
2025 t4_mc_cb_init(struct port_info
*pi
)
2027 if (pi
->adapter
->props
.multi_rings
)
2028 pi
->mc
= &t4_m_ring_callbacks
;
2030 pi
->mc
= &t4_m_callbacks
;
2034 t4_os_link_changed(struct adapter
*sc
, int idx
, int link_stat
)
2036 struct port_info
*pi
= sc
->port
[idx
];
2038 mac_link_update(pi
->mh
, link_stat
? LINK_STATE_UP
: LINK_STATE_DOWN
);
2043 t4_mac_rx(struct port_info
*pi
, struct sge_rxq
*rxq
, mblk_t
*m
)
2045 mac_rx(pi
->mh
, NULL
, m
);
2049 t4_mac_tx_update(struct port_info
*pi
, struct sge_txq
*txq
)
2051 if (pi
->adapter
->props
.multi_rings
)
2052 mac_tx_ring_update(pi
->mh
, txq
->ring_handle
);
2054 mac_tx_update(pi
->mh
);