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