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