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