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