156b2bdd1SGireesh Nagabhushana /*
256b2bdd1SGireesh Nagabhushana  * This file and its contents are supplied under the terms of the
356b2bdd1SGireesh Nagabhushana  * Common Development and Distribution License ("CDDL"), version 1.0.
456b2bdd1SGireesh Nagabhushana  * You may only use this file in accordance with the terms of version
556b2bdd1SGireesh Nagabhushana  * 1.0 of the CDDL.
656b2bdd1SGireesh Nagabhushana  *
756b2bdd1SGireesh Nagabhushana  * A full copy of the text of the CDDL should have accompanied this
856b2bdd1SGireesh Nagabhushana  * source. A copy of the CDDL is also available via the Internet at
956b2bdd1SGireesh Nagabhushana  * http://www.illumos.org/license/CDDL.
1056b2bdd1SGireesh Nagabhushana  */
1156b2bdd1SGireesh Nagabhushana 
1256b2bdd1SGireesh Nagabhushana /*
1356b2bdd1SGireesh Nagabhushana  * This file is part of the Chelsio T4 support code.
1456b2bdd1SGireesh Nagabhushana  *
1556b2bdd1SGireesh Nagabhushana  * Copyright (C) 2010-2013 Chelsio Communications.  All rights reserved.
1656b2bdd1SGireesh Nagabhushana  *
1756b2bdd1SGireesh Nagabhushana  * This program is distributed in the hope that it will be useful, but WITHOUT
1856b2bdd1SGireesh Nagabhushana  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1956b2bdd1SGireesh Nagabhushana  * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
2056b2bdd1SGireesh Nagabhushana  * release for licensing terms and conditions.
2156b2bdd1SGireesh Nagabhushana  */
2256b2bdd1SGireesh Nagabhushana 
23d77e6e0fSPaul Winder /*
24d77e6e0fSPaul Winder  * Copyright 2020 RackTop Systems, Inc.
25*ece8d794SRobert Mustacchi  * Copyright 2023 Oxide Computer Company
26d77e6e0fSPaul Winder  */
27d77e6e0fSPaul Winder 
2856b2bdd1SGireesh Nagabhushana #include <sys/ddi.h>
2956b2bdd1SGireesh Nagabhushana #include <sys/sunddi.h>
3056b2bdd1SGireesh Nagabhushana #include <sys/dlpi.h>
3156b2bdd1SGireesh Nagabhushana #include <sys/mac_provider.h>
3256b2bdd1SGireesh Nagabhushana #include <sys/mac_ether.h>
3356b2bdd1SGireesh Nagabhushana #include <sys/strsubr.h>
3456b2bdd1SGireesh Nagabhushana #include <sys/queue.h>
3556b2bdd1SGireesh Nagabhushana 
3656b2bdd1SGireesh Nagabhushana #include "common/common.h"
3756b2bdd1SGireesh Nagabhushana #include "common/t4_regs.h"
3856b2bdd1SGireesh Nagabhushana 
3956b2bdd1SGireesh Nagabhushana static int t4_mc_getstat(void *arg, uint_t stat, uint64_t *val);
4056b2bdd1SGireesh Nagabhushana static int t4_mc_start(void *arg);
4156b2bdd1SGireesh Nagabhushana static void t4_mc_stop(void *arg);
4256b2bdd1SGireesh Nagabhushana static int t4_mc_setpromisc(void *arg, boolean_t on);
4356b2bdd1SGireesh Nagabhushana static int t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr);
4456b2bdd1SGireesh Nagabhushana static int t4_mc_unicst(void *arg, const uint8_t *ucaddr);
4556b2bdd1SGireesh Nagabhushana static boolean_t t4_mc_getcapab(void *arg, mac_capab_t cap, void *data);
4656b2bdd1SGireesh Nagabhushana static int t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id,
4756b2bdd1SGireesh Nagabhushana     uint_t size, const void *val);
4856b2bdd1SGireesh Nagabhushana static int t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id,
4956b2bdd1SGireesh Nagabhushana     uint_t size, void *val);
5056b2bdd1SGireesh Nagabhushana static void t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
5156b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph);
5256b2bdd1SGireesh Nagabhushana 
5356b2bdd1SGireesh Nagabhushana static int t4_init_synchronized(struct port_info *pi);
5456b2bdd1SGireesh Nagabhushana static int t4_uninit_synchronized(struct port_info *pi);
5556b2bdd1SGireesh Nagabhushana static void propinfo(struct port_info *pi, const char *name,
5656b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph);
5756b2bdd1SGireesh Nagabhushana static int getprop(struct port_info *pi, const char *name, uint_t size,
5856b2bdd1SGireesh Nagabhushana     void *val);
5956b2bdd1SGireesh Nagabhushana static int setprop(struct port_info *pi, const char *name, const void *val);
6056b2bdd1SGireesh Nagabhushana 
6156b2bdd1SGireesh Nagabhushana mac_callbacks_t t4_m_callbacks = {
6256b2bdd1SGireesh Nagabhushana 	.mc_callbacks	= MC_GETCAPAB | MC_PROPERTIES,
6356b2bdd1SGireesh Nagabhushana 	.mc_getstat	= t4_mc_getstat,
6456b2bdd1SGireesh Nagabhushana 	.mc_start	= t4_mc_start,
6556b2bdd1SGireesh Nagabhushana 	.mc_stop	= t4_mc_stop,
6656b2bdd1SGireesh Nagabhushana 	.mc_setpromisc	= t4_mc_setpromisc,
6756b2bdd1SGireesh Nagabhushana 	.mc_multicst	= t4_mc_multicst,
683dde7c95SVishal Kulkarni 	.mc_unicst =    t4_mc_unicst,
693dde7c95SVishal Kulkarni 	.mc_tx =        t4_mc_tx,
703dde7c95SVishal Kulkarni 	.mc_getcapab =	t4_mc_getcapab,
713dde7c95SVishal Kulkarni 	.mc_setprop =	t4_mc_setprop,
723dde7c95SVishal Kulkarni 	.mc_getprop =	t4_mc_getprop,
733dde7c95SVishal Kulkarni 	.mc_propinfo =	t4_mc_propinfo,
743dde7c95SVishal Kulkarni };
753dde7c95SVishal Kulkarni 
763dde7c95SVishal Kulkarni /* I couldn't comeup with a better idea of not redefine
773dde7c95SVishal Kulkarni  * another strcture and instead somehow reuse the earlier
783dde7c95SVishal Kulkarni  * above structure and modify its members.
793dde7c95SVishal Kulkarni  */
803dde7c95SVishal Kulkarni mac_callbacks_t t4_m_ring_callbacks = {
813dde7c95SVishal Kulkarni 	.mc_callbacks =	MC_GETCAPAB | MC_PROPERTIES,
823dde7c95SVishal Kulkarni 	.mc_getstat =	t4_mc_getstat,
833dde7c95SVishal Kulkarni 	.mc_start =	t4_mc_start,
843dde7c95SVishal Kulkarni 	.mc_stop =	t4_mc_stop,
853dde7c95SVishal Kulkarni 	.mc_setpromisc =t4_mc_setpromisc,
863dde7c95SVishal Kulkarni 	.mc_multicst =	t4_mc_multicst,
873dde7c95SVishal Kulkarni 	.mc_unicst =    NULL, /* t4_addmac */
883dde7c95SVishal Kulkarni 	.mc_tx =        NULL, /* t4_eth_tx */
8956b2bdd1SGireesh Nagabhushana 	.mc_getcapab	= t4_mc_getcapab,
9056b2bdd1SGireesh Nagabhushana 	.mc_setprop	= t4_mc_setprop,
9156b2bdd1SGireesh Nagabhushana 	.mc_getprop	= t4_mc_getprop,
9256b2bdd1SGireesh Nagabhushana 	.mc_propinfo	= t4_mc_propinfo,
9356b2bdd1SGireesh Nagabhushana };
9456b2bdd1SGireesh Nagabhushana 
9556b2bdd1SGireesh Nagabhushana #define	T4PROP_TMR_IDX "_holdoff_timer_idx"
9656b2bdd1SGireesh Nagabhushana #define	T4PROP_PKTC_IDX "_holdoff_pktc_idx"
9756b2bdd1SGireesh Nagabhushana #define	T4PROP_MTU "_mtu"
9856b2bdd1SGireesh Nagabhushana #define	T4PROP_HW_CSUM	"_hw_csum"
9956b2bdd1SGireesh Nagabhushana #define	T4PROP_HW_LSO	"_hw_lso"
10056b2bdd1SGireesh Nagabhushana #define	T4PROP_TX_PAUSE	"_tx_pause"
10156b2bdd1SGireesh Nagabhushana #define	T4PROP_RX_PAUSE	"_rx_pause"
10256b2bdd1SGireesh Nagabhushana 
10356b2bdd1SGireesh Nagabhushana char *t4_priv_props[] = {
10456b2bdd1SGireesh Nagabhushana 	T4PROP_TMR_IDX,
10556b2bdd1SGireesh Nagabhushana 	T4PROP_PKTC_IDX,
10656b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
10756b2bdd1SGireesh Nagabhushana 	/* MAC_VERSION 1 doesn't seem to use MAC_PROP_MTU, hmmmm */
10856b2bdd1SGireesh Nagabhushana 	T4PROP_MTU,
10956b2bdd1SGireesh Nagabhushana #endif
11056b2bdd1SGireesh Nagabhushana 	T4PROP_HW_CSUM,
11156b2bdd1SGireesh Nagabhushana 	T4PROP_HW_LSO,
11256b2bdd1SGireesh Nagabhushana 	T4PROP_TX_PAUSE,
11356b2bdd1SGireesh Nagabhushana 	T4PROP_RX_PAUSE,
11456b2bdd1SGireesh Nagabhushana 	NULL
11556b2bdd1SGireesh Nagabhushana };
11656b2bdd1SGireesh Nagabhushana 
117*ece8d794SRobert Mustacchi /*
118*ece8d794SRobert Mustacchi  * To determine the actual Ethernet mode that we're in we need to look at the
119*ece8d794SRobert Mustacchi  * port type. That will tell us whether we're using a BASE-T PHY, have an
120*ece8d794SRobert Mustacchi  * external SFP connection whose module type we also need to use to qualify
121*ece8d794SRobert Mustacchi  * this, and then the link speed itself. Combining that tuple we can then get
122*ece8d794SRobert Mustacchi  * the current media.
123*ece8d794SRobert Mustacchi  *
124*ece8d794SRobert Mustacchi  * Our tables below assume we have gotten it down so the last thing we need to
125*ece8d794SRobert Mustacchi  * consider is a single speed. If port types end up supporting the same class of
126*ece8d794SRobert Mustacchi  * transceiver at a given speed, then this will need to be changed to use
127*ece8d794SRobert Mustacchi  * additional information to disambiguate that (which will require additional
128*ece8d794SRobert Mustacchi  * logic from the firmware).
129*ece8d794SRobert Mustacchi  */
130*ece8d794SRobert Mustacchi typedef struct {
131*ece8d794SRobert Mustacchi 	fw_port_cap32_t tmm_speed;
132*ece8d794SRobert Mustacchi 	mac_ether_media_t tmm_ether;
133*ece8d794SRobert Mustacchi } t4nex_media_map_t;
134*ece8d794SRobert Mustacchi 
135*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_baset[] = {
136*ece8d794SRobert Mustacchi 	/*
137*ece8d794SRobert Mustacchi 	 * We're assuming that the 100 Mb/s mode is 100BASE-TX. It's hard to say
138*ece8d794SRobert Mustacchi 	 * for certain what the phy would have done, but given the rest of the
139*ece8d794SRobert Mustacchi 	 * market, that seems the most likely one.
140*ece8d794SRobert Mustacchi 	 */
141*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100M, ETHER_MEDIA_100BASE_TX },
142*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_T },
143*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_T }
144*ece8d794SRobert Mustacchi };
145*ece8d794SRobert Mustacchi 
146*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_kx[] = {
147*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
148*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KX4 }
149*ece8d794SRobert Mustacchi };
150*ece8d794SRobert Mustacchi 
151*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_cx[] = {
152*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CX4 }
153*ece8d794SRobert Mustacchi };
154*ece8d794SRobert Mustacchi 
155*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_kr[] = {
156*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
157*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KR },
158*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_KR },
159*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_KR4 },
160*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_KR2 },
161*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_KR4 },
162*ece8d794SRobert Mustacchi };
163*ece8d794SRobert Mustacchi 
164*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_lr[] = {
165*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_LX },
166*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LR },
167*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_LR },
168*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_LR4 },
169*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_LR2 },
170*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_LR4 },
171*ece8d794SRobert Mustacchi };
172*ece8d794SRobert Mustacchi 
173*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_sr[] = {
174*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_SX },
175*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_SR },
176*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_SR },
177*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_SR4 },
178*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_SR2 },
179*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_SR4 },
180*ece8d794SRobert Mustacchi };
181*ece8d794SRobert Mustacchi 
182*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_er[] = {
183*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ER },
184*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ER },
185*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ER4 },
186*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ER4 },
187*ece8d794SRobert Mustacchi };
188*ece8d794SRobert Mustacchi 
189*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_cr[] = {
190*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
191*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CR },
192*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_CR },
193*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_CR4 },
194*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_CR2 },
195*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_CR4 },
196*ece8d794SRobert Mustacchi };
197*ece8d794SRobert Mustacchi 
198*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_acc[] = {
199*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
200*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ACC },
201*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ACC },
202*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ACC4 },
203*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_ACC2 },
204*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ACC4 },
205*ece8d794SRobert Mustacchi };
206*ece8d794SRobert Mustacchi 
207*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_lrm[] = {
208*ece8d794SRobert Mustacchi 	{ FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LRM },
209*ece8d794SRobert Mustacchi };
210*ece8d794SRobert Mustacchi 
211*ece8d794SRobert Mustacchi static mac_ether_media_t
t4_port_to_media(struct port_info * pi)212*ece8d794SRobert Mustacchi t4_port_to_media(struct port_info *pi)
213*ece8d794SRobert Mustacchi {
214*ece8d794SRobert Mustacchi 	fw_port_cap32_t speed;
215*ece8d794SRobert Mustacchi 	struct link_config *lc = &pi->link_cfg;
216*ece8d794SRobert Mustacchi 	const t4nex_media_map_t *map = NULL;
217*ece8d794SRobert Mustacchi 	size_t count = 0;
218*ece8d794SRobert Mustacchi 
219*ece8d794SRobert Mustacchi 	if (lc->link_ok != 0) {
220*ece8d794SRobert Mustacchi 		speed = t4_link_fwcap_to_fwspeed(lc->link_caps);
221*ece8d794SRobert Mustacchi 	} else {
222*ece8d794SRobert Mustacchi 		return (ETHER_MEDIA_UNKNOWN);
223*ece8d794SRobert Mustacchi 	}
224*ece8d794SRobert Mustacchi 
225*ece8d794SRobert Mustacchi 	switch (pi->port_type) {
226*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_FIBER_XFI:
227*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_FIBER_XAUI:
228*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_SFP:
229*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_QSFP_10G:
230*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_QSA:
231*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_QSFP:
232*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_CR4_QSFP:
233*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_CR_QSFP:
234*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_CR2_QSFP:
235*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_SFP28:
236*ece8d794SRobert Mustacchi 		switch (pi->mod_type) {
237*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_LR:
238*ece8d794SRobert Mustacchi 			map = t4nex_map_lr;
239*ece8d794SRobert Mustacchi 			count = ARRAY_SIZE(t4nex_map_lr);
240*ece8d794SRobert Mustacchi 			break;
241*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_SR:
242*ece8d794SRobert Mustacchi 			map = t4nex_map_sr;
243*ece8d794SRobert Mustacchi 			count = ARRAY_SIZE(t4nex_map_sr);
244*ece8d794SRobert Mustacchi 			break;
245*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_ER:
246*ece8d794SRobert Mustacchi 			map = t4nex_map_er;
247*ece8d794SRobert Mustacchi 			count = ARRAY_SIZE(t4nex_map_er);
248*ece8d794SRobert Mustacchi 			break;
249*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
250*ece8d794SRobert Mustacchi 			map = t4nex_map_cr;
251*ece8d794SRobert Mustacchi 			count = ARRAY_SIZE(t4nex_map_cr);
252*ece8d794SRobert Mustacchi 			break;
253*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
254*ece8d794SRobert Mustacchi 			map = t4nex_map_acc;
255*ece8d794SRobert Mustacchi 			count = ARRAY_SIZE(t4nex_map_acc);
256*ece8d794SRobert Mustacchi 			break;
257*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_LRM:
258*ece8d794SRobert Mustacchi 			map = t4nex_map_lrm;
259*ece8d794SRobert Mustacchi 			count = ARRAY_SIZE(t4nex_map_lrm);
260*ece8d794SRobert Mustacchi 			break;
261*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_ERROR:
262*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_UNKNOWN:
263*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_NOTSUPPORTED:
264*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_NONE:
265*ece8d794SRobert Mustacchi 		case FW_PORT_MOD_TYPE_NA:
266*ece8d794SRobert Mustacchi 		default:
267*ece8d794SRobert Mustacchi 			break;
268*ece8d794SRobert Mustacchi 		}
269*ece8d794SRobert Mustacchi 		break;
270*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_KX4:
271*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_KX:
272*ece8d794SRobert Mustacchi 		map = t4nex_map_kx;
273*ece8d794SRobert Mustacchi 		count = ARRAY_SIZE(t4nex_map_kx);
274*ece8d794SRobert Mustacchi 		break;
275*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_CX4:
276*ece8d794SRobert Mustacchi 		map = t4nex_map_cx;
277*ece8d794SRobert Mustacchi 		count = ARRAY_SIZE(t4nex_map_cx);
278*ece8d794SRobert Mustacchi 		break;
279*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_KR:
280*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_BP_AP:
281*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_BP4_AP:
282*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_BP40_BA:
283*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_KR4_100G:
284*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_KR_SFP28:
285*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_KR_XLAUI:
286*ece8d794SRobert Mustacchi 		map = t4nex_map_kr;
287*ece8d794SRobert Mustacchi 		count = ARRAY_SIZE(t4nex_map_kr);
288*ece8d794SRobert Mustacchi 		break;
289*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_BT_SGMII:
290*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_BT_XFI:
291*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_BT_XAUI:
292*ece8d794SRobert Mustacchi 		map = t4nex_map_baset;
293*ece8d794SRobert Mustacchi 		count = ARRAY_SIZE(t4nex_map_baset);
294*ece8d794SRobert Mustacchi 		break;
295*ece8d794SRobert Mustacchi 	case FW_PORT_TYPE_NONE:
296*ece8d794SRobert Mustacchi 	default:
297*ece8d794SRobert Mustacchi 		break;
298*ece8d794SRobert Mustacchi 	}
299*ece8d794SRobert Mustacchi 
300*ece8d794SRobert Mustacchi 	for (size_t i = 0; i < count; i++) {
301*ece8d794SRobert Mustacchi 		if (map[i].tmm_speed == speed) {
302*ece8d794SRobert Mustacchi 			return (map[i].tmm_ether);
303*ece8d794SRobert Mustacchi 		}
304*ece8d794SRobert Mustacchi 	}
305*ece8d794SRobert Mustacchi 
306*ece8d794SRobert Mustacchi 	/*
307*ece8d794SRobert Mustacchi 	 * At this point we return unknown as we already checked for a down link
308*ece8d794SRobert Mustacchi 	 * earlier.
309*ece8d794SRobert Mustacchi 	 */
310*ece8d794SRobert Mustacchi 	return (ETHER_MEDIA_UNKNOWN);
311*ece8d794SRobert Mustacchi }
312*ece8d794SRobert Mustacchi 
31356b2bdd1SGireesh Nagabhushana static int
t4_mc_getstat(void * arg,uint_t stat,uint64_t * val)31456b2bdd1SGireesh Nagabhushana t4_mc_getstat(void *arg, uint_t stat, uint64_t *val)
31556b2bdd1SGireesh Nagabhushana {
31656b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
31756b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
31856b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
31956b2bdd1SGireesh Nagabhushana 
32056b2bdd1SGireesh Nagabhushana #define	GET_STAT(name) \
32156b2bdd1SGireesh Nagabhushana 	t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
32256b2bdd1SGireesh Nagabhushana 
32356b2bdd1SGireesh Nagabhushana 	switch (stat) {
32456b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IFSPEED:
32556b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
3266feac2e3SRahul Lakkireddy 			*val = t4_link_fwcap_to_speed(lc->link_caps);
32756b2bdd1SGireesh Nagabhushana 			*val *= 1000000;
32856b2bdd1SGireesh Nagabhushana 		} else
32956b2bdd1SGireesh Nagabhushana 			*val = 0;
33056b2bdd1SGireesh Nagabhushana 		break;
33156b2bdd1SGireesh Nagabhushana 
33256b2bdd1SGireesh Nagabhushana 	case MAC_STAT_MULTIRCV:
33356b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MCAST);
33456b2bdd1SGireesh Nagabhushana 		break;
33556b2bdd1SGireesh Nagabhushana 
33656b2bdd1SGireesh Nagabhushana 	case MAC_STAT_BRDCSTRCV:
33756b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_BCAST);
33856b2bdd1SGireesh Nagabhushana 		break;
33956b2bdd1SGireesh Nagabhushana 
34056b2bdd1SGireesh Nagabhushana 	case MAC_STAT_MULTIXMT:
34156b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_MCAST);
34256b2bdd1SGireesh Nagabhushana 		break;
34356b2bdd1SGireesh Nagabhushana 
34456b2bdd1SGireesh Nagabhushana 	case MAC_STAT_BRDCSTXMT:
34556b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_BCAST);
34656b2bdd1SGireesh Nagabhushana 		break;
34756b2bdd1SGireesh Nagabhushana 
34856b2bdd1SGireesh Nagabhushana 	case MAC_STAT_NORCVBUF:
34956b2bdd1SGireesh Nagabhushana 		*val = 0;	/* TODO should come from rxq->nomem */
35056b2bdd1SGireesh Nagabhushana 		break;
35156b2bdd1SGireesh Nagabhushana 
35256b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IERRORS:
35356b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR) +
35456b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_MTU_CRC_ERROR) +
35556b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_CRC_ERROR) +
35656b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LEN_ERROR) +
35756b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_SYM_ERROR) +
35856b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LESS_64B);
35956b2bdd1SGireesh Nagabhushana 		break;
36056b2bdd1SGireesh Nagabhushana 
36156b2bdd1SGireesh Nagabhushana 	case MAC_STAT_UNKNOWNS:
36256b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
36356b2bdd1SGireesh Nagabhushana 
36456b2bdd1SGireesh Nagabhushana 	case MAC_STAT_NOXMTBUF:
36556b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_DROP);
36656b2bdd1SGireesh Nagabhushana 		break;
36756b2bdd1SGireesh Nagabhushana 
36856b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OERRORS:
36956b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_ERROR);
37056b2bdd1SGireesh Nagabhushana 		break;
37156b2bdd1SGireesh Nagabhushana 
37256b2bdd1SGireesh Nagabhushana 	case MAC_STAT_COLLISIONS:
37356b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
37456b2bdd1SGireesh Nagabhushana 
37556b2bdd1SGireesh Nagabhushana 	case MAC_STAT_RBYTES:
37656b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_BYTES);
37756b2bdd1SGireesh Nagabhushana 		break;
37856b2bdd1SGireesh Nagabhushana 
37956b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IPACKETS:
38056b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_FRAMES);
38156b2bdd1SGireesh Nagabhushana 		break;
38256b2bdd1SGireesh Nagabhushana 
38356b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OBYTES:
38456b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_BYTES);
38556b2bdd1SGireesh Nagabhushana 		break;
38656b2bdd1SGireesh Nagabhushana 
38756b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OPACKETS:
38856b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_FRAMES);
38956b2bdd1SGireesh Nagabhushana 		break;
39056b2bdd1SGireesh Nagabhushana 
39156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ALIGN_ERRORS:
39256b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
39356b2bdd1SGireesh Nagabhushana 
39456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_FCS_ERRORS:
39556b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_CRC_ERROR);
39656b2bdd1SGireesh Nagabhushana 		break;
39756b2bdd1SGireesh Nagabhushana 
39856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_FIRST_COLLISIONS:
39956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MULTI_COLLISIONS:
40056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_SQE_ERRORS:
40156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_DEFER_XMTS:
40256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_TX_LATE_COLLISIONS:
40356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_EX_COLLISIONS:
40456b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
40556b2bdd1SGireesh Nagabhushana 
40656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MACXMT_ERRORS:
40756b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_ERROR);
40856b2bdd1SGireesh Nagabhushana 		break;
40956b2bdd1SGireesh Nagabhushana 
41056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CARRIER_ERRORS:
41156b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
41256b2bdd1SGireesh Nagabhushana 
41356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_TOOLONG_ERRORS:
41456b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR);
41556b2bdd1SGireesh Nagabhushana 		break;
41656b2bdd1SGireesh Nagabhushana 
41756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MACRCV_ERRORS:
41856b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR) +
41956b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_MTU_CRC_ERROR) +
42056b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_CRC_ERROR) +
42156b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LEN_ERROR) +
42256b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_SYM_ERROR) +
42356b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LESS_64B);
42456b2bdd1SGireesh Nagabhushana 		break;
42556b2bdd1SGireesh Nagabhushana 
42656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_ADDR:
42756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_ID:
42856b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
429*ece8d794SRobert Mustacchi 	case ETHER_STAT_XCVR_INUSE:
430*ece8d794SRobert Mustacchi 		*val = t4_port_to_media(pi);
431*ece8d794SRobert Mustacchi 		break;
43256b2bdd1SGireesh Nagabhushana 
4333dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_100GFDX:
4347e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G);
4353dde7c95SVishal Kulkarni 		break;
4363dde7c95SVishal Kulkarni 
4376feac2e3SRahul Lakkireddy 	case ETHER_STAT_CAP_50GFDX:
4386feac2e3SRahul Lakkireddy 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_50G);
4396feac2e3SRahul Lakkireddy 		break;
4406feac2e3SRahul Lakkireddy 
4413dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_40GFDX:
4427e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
4433dde7c95SVishal Kulkarni 		break;
4443dde7c95SVishal Kulkarni 
4453dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_25GFDX:
4467e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
4473dde7c95SVishal Kulkarni 		break;
4483dde7c95SVishal Kulkarni 
4493dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_10GFDX:
4507e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
4513dde7c95SVishal Kulkarni 		break;
4523dde7c95SVishal Kulkarni 
45356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_1000FDX:
4547e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
45556b2bdd1SGireesh Nagabhushana 		break;
45656b2bdd1SGireesh Nagabhushana 
45756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100FDX:
4587e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
45956b2bdd1SGireesh Nagabhushana 		break;
46056b2bdd1SGireesh Nagabhushana 
4616feac2e3SRahul Lakkireddy 	case ETHER_STAT_CAP_1000HDX:
46256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100HDX:
46356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_10FDX:
46456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_10HDX:
46556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
46656b2bdd1SGireesh Nagabhushana 
46756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_ASMPAUSE:
4686feac2e3SRahul Lakkireddy 		*val = !!(lc->pcaps & FW_PORT_CAP32_FC_RX);
46956b2bdd1SGireesh Nagabhushana 		break;
47056b2bdd1SGireesh Nagabhushana 
47156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_PAUSE:
4726feac2e3SRahul Lakkireddy 		*val = !!(lc->pcaps & FW_PORT_CAP32_FC_TX);
47356b2bdd1SGireesh Nagabhushana 		break;
47456b2bdd1SGireesh Nagabhushana 
47556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_AUTONEG:
4767e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_ANEG);
47756b2bdd1SGireesh Nagabhushana 		break;
47856b2bdd1SGireesh Nagabhushana 
47956b2bdd1SGireesh Nagabhushana 	/*
48056b2bdd1SGireesh Nagabhushana 	 * We have set flow control configuration based on tx_pause and rx_pause
48156b2bdd1SGireesh Nagabhushana 	 * values supported through ndd. Now, we need to translate the settings
48256b2bdd1SGireesh Nagabhushana 	 * we have in link_config structure to adv_cap_asmpause and
48356b2bdd1SGireesh Nagabhushana 	 * adv_cap_pause.
48456b2bdd1SGireesh Nagabhushana 	 *
48556b2bdd1SGireesh Nagabhushana 	 * There are 4 combinations possible and the translation is as below:
48656b2bdd1SGireesh Nagabhushana 	 * tx_pause = 0 => We don't send pause frames during Rx congestion
48756b2bdd1SGireesh Nagabhushana 	 * tx_pause = 1 => We send pause frames during Rx congestion
48856b2bdd1SGireesh Nagabhushana 	 * rx_pause = 0 => We ignore received pause frames
48956b2bdd1SGireesh Nagabhushana 	 * rx_pause = 1 => We pause transmission when we receive pause frames
49056b2bdd1SGireesh Nagabhushana 	 *
49156b2bdd1SGireesh Nagabhushana 	 * +----------------------------+----------------------------------+
49256b2bdd1SGireesh Nagabhushana 	 * |  tx_pause	|    rx_pause	| adv_cap_asmpause | adv_cap_pause |
49356b2bdd1SGireesh Nagabhushana 	 * +-------------------------+-------------------------------------+
49456b2bdd1SGireesh Nagabhushana 	 * |	0	|	0	|	0	   |	0	   |
49556b2bdd1SGireesh Nagabhushana 	 * |	0	|	1	|	1	   |	0	   |
49656b2bdd1SGireesh Nagabhushana 	 * |	1	|	0	|	1	   |	1	   |
49756b2bdd1SGireesh Nagabhushana 	 * |	1	|	1	|	0	   |	1	   |
49856b2bdd1SGireesh Nagabhushana 	 * +----------------------------+----------------------------------+
49956b2bdd1SGireesh Nagabhushana 	 */
50056b2bdd1SGireesh Nagabhushana 
50156b2bdd1SGireesh Nagabhushana 	/* Advertised asymmetric pause capability */
50256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
5036feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
5046feac2e3SRahul Lakkireddy 			*val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_ASM_DIR);
5056feac2e3SRahul Lakkireddy 		else
5066feac2e3SRahul Lakkireddy 			*val = (!!(lc->admin_caps & FW_PORT_CAP32_FC_TX)) ^
5076feac2e3SRahul Lakkireddy 			       (!!(lc->admin_caps & FW_PORT_CAP32_FC_RX));
50856b2bdd1SGireesh Nagabhushana 		break;
50956b2bdd1SGireesh Nagabhushana 
51056b2bdd1SGireesh Nagabhushana 	/* Advertised pause capability */
51156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_PAUSE:
5126feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
5136feac2e3SRahul Lakkireddy 			*val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_PAUSE);
5146feac2e3SRahul Lakkireddy 		else
5156feac2e3SRahul Lakkireddy 			*val = !!(lc->admin_caps & FW_PORT_CAP32_FC_TX);
51656b2bdd1SGireesh Nagabhushana 		break;
51756b2bdd1SGireesh Nagabhushana 
5183dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_100GFDX:
5196feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
5206feac2e3SRahul Lakkireddy 		break;
5216feac2e3SRahul Lakkireddy 
5226feac2e3SRahul Lakkireddy 	case ETHER_STAT_ADV_CAP_50GFDX:
5236feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
5243dde7c95SVishal Kulkarni 		break;
5253dde7c95SVishal Kulkarni 
5263dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_40GFDX:
5276feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
5283dde7c95SVishal Kulkarni 		break;
5293dde7c95SVishal Kulkarni 
5303dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_25GFDX:
5316feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
5323dde7c95SVishal Kulkarni 		break;
5333dde7c95SVishal Kulkarni 
5343dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_10GFDX:
5356feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
5363dde7c95SVishal Kulkarni 		break;
5373dde7c95SVishal Kulkarni 
53856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000FDX:
5396feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
5406feac2e3SRahul Lakkireddy 		break;
5416feac2e3SRahul Lakkireddy 
5426feac2e3SRahul Lakkireddy 	case ETHER_STAT_ADV_CAP_100FDX:
5436feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
5443dde7c95SVishal Kulkarni 		break;
5453dde7c95SVishal Kulkarni 
5463dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_AUTONEG:
5476feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_ANEG);
5483dde7c95SVishal Kulkarni 		break;
5493dde7c95SVishal Kulkarni 
55056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000HDX:
55156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_100HDX:
55256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10FDX:
55356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10HDX:
55456b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);	/* TODO */
55556b2bdd1SGireesh Nagabhushana 
5566feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_ASMPAUSE:
5576feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5586feac2e3SRahul Lakkireddy 			return (ENOTSUP);
5596feac2e3SRahul Lakkireddy 
5606feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
5616feac2e3SRahul Lakkireddy 			*val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_ASM_DIR);
5626feac2e3SRahul Lakkireddy 		else
5636feac2e3SRahul Lakkireddy 			*val = (!!(lc->lpacaps & FW_PORT_CAP32_FC_TX)) ^
5646feac2e3SRahul Lakkireddy 			       (!!(lc->lpacaps & FW_PORT_CAP32_FC_RX));
5656feac2e3SRahul Lakkireddy 		break;
5666feac2e3SRahul Lakkireddy 
5676feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_PAUSE:
5686feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5696feac2e3SRahul Lakkireddy 			return (ENOTSUP);
5706feac2e3SRahul Lakkireddy 
5716feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
5726feac2e3SRahul Lakkireddy 			*val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_PAUSE);
5736feac2e3SRahul Lakkireddy 		else
5746feac2e3SRahul Lakkireddy 			*val = !!(lc->lpacaps & FW_PORT_CAP32_FC_TX);
5756feac2e3SRahul Lakkireddy 		break;
5763dde7c95SVishal Kulkarni 
5773dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_100GFDX:
5786feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5796feac2e3SRahul Lakkireddy 			return (ENOTSUP);
5806feac2e3SRahul Lakkireddy 
5816feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100G);
5826feac2e3SRahul Lakkireddy 		break;
5836feac2e3SRahul Lakkireddy 
5846feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_50GFDX:
5856feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5866feac2e3SRahul Lakkireddy 			return (ENOTSUP);
5876feac2e3SRahul Lakkireddy 
5886feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_50G);
5893dde7c95SVishal Kulkarni 		break;
5903dde7c95SVishal Kulkarni 
5913dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_40GFDX:
5926feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5936feac2e3SRahul Lakkireddy 			return (ENOTSUP);
5946feac2e3SRahul Lakkireddy 
5956feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_40G);
5963dde7c95SVishal Kulkarni 		break;
5973dde7c95SVishal Kulkarni 
5983dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_25GFDX:
5996feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6006feac2e3SRahul Lakkireddy 			return (ENOTSUP);
6016feac2e3SRahul Lakkireddy 
6026feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_25G);
6033dde7c95SVishal Kulkarni 		break;
6043dde7c95SVishal Kulkarni 
6053dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_10GFDX:
6066feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6076feac2e3SRahul Lakkireddy 			return (ENOTSUP);
6086feac2e3SRahul Lakkireddy 
6096feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_10G);
6103dde7c95SVishal Kulkarni 		break;
6113dde7c95SVishal Kulkarni 
61256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000FDX:
6136feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6146feac2e3SRahul Lakkireddy 			return (ENOTSUP);
6156feac2e3SRahul Lakkireddy 
6166feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_1G);
6176feac2e3SRahul Lakkireddy 		break;
6186feac2e3SRahul Lakkireddy 
6196feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_100FDX:
6206feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6216feac2e3SRahul Lakkireddy 			return (ENOTSUP);
6226feac2e3SRahul Lakkireddy 
6236feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100M);
6243dde7c95SVishal Kulkarni 		break;
6253dde7c95SVishal Kulkarni 
6263dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_AUTONEG:
6276feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6286feac2e3SRahul Lakkireddy 			return (ENOTSUP);
6296feac2e3SRahul Lakkireddy 
6306feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_ANEG);
6313dde7c95SVishal Kulkarni 		break;
6323dde7c95SVishal Kulkarni 
63356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000HDX:
63456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_100HDX:
63556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10FDX:
63656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10HDX:
63756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
63856b2bdd1SGireesh Nagabhushana 
63956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_ASMPAUSE:
6406feac2e3SRahul Lakkireddy 		*val = (!!(lc->link_caps & FW_PORT_CAP32_FC_TX)) ^
6416feac2e3SRahul Lakkireddy 		       (!!(lc->link_caps & FW_PORT_CAP32_FC_RX));
64256b2bdd1SGireesh Nagabhushana 		break;
64356b2bdd1SGireesh Nagabhushana 
64456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_PAUSE:
6456feac2e3SRahul Lakkireddy 		*val = !!(lc->link_caps & FW_PORT_CAP32_FC_TX);
64656b2bdd1SGireesh Nagabhushana 		break;
64756b2bdd1SGireesh Nagabhushana 
64856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_AUTONEG:
6496feac2e3SRahul Lakkireddy 		*val = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
65056b2bdd1SGireesh Nagabhushana 		break;
65156b2bdd1SGireesh Nagabhushana 
65256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_DUPLEX:
65356b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0)
65456b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_FULL;
65556b2bdd1SGireesh Nagabhushana 		else
65656b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_UNKNOWN;
65756b2bdd1SGireesh Nagabhushana 		break;
65856b2bdd1SGireesh Nagabhushana 
65956b2bdd1SGireesh Nagabhushana 	default:
66056b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
66156b2bdd1SGireesh Nagabhushana 	}
66256b2bdd1SGireesh Nagabhushana #undef GET_STAT
66356b2bdd1SGireesh Nagabhushana 
66456b2bdd1SGireesh Nagabhushana 	return (0);
66556b2bdd1SGireesh Nagabhushana }
66656b2bdd1SGireesh Nagabhushana 
66756b2bdd1SGireesh Nagabhushana static int
t4_mc_start(void * arg)66856b2bdd1SGireesh Nagabhushana t4_mc_start(void *arg)
66956b2bdd1SGireesh Nagabhushana {
67056b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
67156b2bdd1SGireesh Nagabhushana 	int rc;
67256b2bdd1SGireesh Nagabhushana 
67356b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 0, 1);
67456b2bdd1SGireesh Nagabhushana 	if (rc != 0)
67556b2bdd1SGireesh Nagabhushana 		return (rc);
67656b2bdd1SGireesh Nagabhushana 	rc = t4_init_synchronized(pi);
67756b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
67856b2bdd1SGireesh Nagabhushana 
67956b2bdd1SGireesh Nagabhushana 	return (rc);
68056b2bdd1SGireesh Nagabhushana }
68156b2bdd1SGireesh Nagabhushana 
68256b2bdd1SGireesh Nagabhushana static void
t4_mc_stop(void * arg)68356b2bdd1SGireesh Nagabhushana t4_mc_stop(void *arg)
68456b2bdd1SGireesh Nagabhushana {
68556b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
68656b2bdd1SGireesh Nagabhushana 
68756b2bdd1SGireesh Nagabhushana 	while (begin_synchronized_op(pi, 0, 1) != 0)
68856b2bdd1SGireesh Nagabhushana 		continue;
68956b2bdd1SGireesh Nagabhushana 	(void) t4_uninit_synchronized(pi);
69056b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
69156b2bdd1SGireesh Nagabhushana }
69256b2bdd1SGireesh Nagabhushana 
69356b2bdd1SGireesh Nagabhushana static int
t4_mc_setpromisc(void * arg,boolean_t on)69456b2bdd1SGireesh Nagabhushana t4_mc_setpromisc(void *arg, boolean_t on)
69556b2bdd1SGireesh Nagabhushana {
69656b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
69756b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
69856b2bdd1SGireesh Nagabhushana 	int rc;
69956b2bdd1SGireesh Nagabhushana 
70056b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
70156b2bdd1SGireesh Nagabhushana 	if (rc != 0)
70256b2bdd1SGireesh Nagabhushana 		return (rc);
70356b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
70456b2bdd1SGireesh Nagabhushana 	    false);
70556b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
70656b2bdd1SGireesh Nagabhushana 
70756b2bdd1SGireesh Nagabhushana 	return (rc);
70856b2bdd1SGireesh Nagabhushana }
70956b2bdd1SGireesh Nagabhushana 
71056b2bdd1SGireesh Nagabhushana /*
71156b2bdd1SGireesh Nagabhushana  * TODO: Starts failing as soon as the 336 entry table fills up.  Need to use
71256b2bdd1SGireesh Nagabhushana  * hash in that case.
71356b2bdd1SGireesh Nagabhushana  */
71456b2bdd1SGireesh Nagabhushana static int
t4_mc_multicst(void * arg,boolean_t add,const uint8_t * mcaddr)71556b2bdd1SGireesh Nagabhushana t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
71656b2bdd1SGireesh Nagabhushana {
71756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
71856b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
71956b2bdd1SGireesh Nagabhushana 	struct fw_vi_mac_cmd c;
72056b2bdd1SGireesh Nagabhushana 	int len16, rc;
72156b2bdd1SGireesh Nagabhushana 
72256b2bdd1SGireesh Nagabhushana 	len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
72356b2bdd1SGireesh Nagabhushana 	    sizeof (c.u.exact[0]), 16);
72456b2bdd1SGireesh Nagabhushana 	c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
72556b2bdd1SGireesh Nagabhushana 	    F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
72656b2bdd1SGireesh Nagabhushana 	c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
72756b2bdd1SGireesh Nagabhushana 	c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
72856b2bdd1SGireesh Nagabhushana 	    V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
72956b2bdd1SGireesh Nagabhushana 	    FW_VI_MAC_MAC_BASED_FREE));
73056b2bdd1SGireesh Nagabhushana 	bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
73156b2bdd1SGireesh Nagabhushana 
73256b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
73356b2bdd1SGireesh Nagabhushana 	if (rc != 0)
73456b2bdd1SGireesh Nagabhushana 		return (rc);
73556b2bdd1SGireesh Nagabhushana 	rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
73656b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
73756b2bdd1SGireesh Nagabhushana 	if (rc != 0)
73856b2bdd1SGireesh Nagabhushana 		return (rc);
73956b2bdd1SGireesh Nagabhushana #ifdef DEBUG
74056b2bdd1SGireesh Nagabhushana 	/*
74156b2bdd1SGireesh Nagabhushana 	 * TODO: Firmware doesn't seem to return the correct index on removal
74256b2bdd1SGireesh Nagabhushana 	 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
74356b2bdd1SGireesh Nagabhushana 	 * code once it is fixed.
74456b2bdd1SGireesh Nagabhushana 	 */
74556b2bdd1SGireesh Nagabhushana 	else {
74656b2bdd1SGireesh Nagabhushana 		uint16_t idx;
74756b2bdd1SGireesh Nagabhushana 
74856b2bdd1SGireesh Nagabhushana 		idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
74956b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE,
75056b2bdd1SGireesh Nagabhushana 		    "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
75156b2bdd1SGireesh Nagabhushana 		    mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
75256b2bdd1SGireesh Nagabhushana 		    add ? "added at index" : "removed from index", idx);
75356b2bdd1SGireesh Nagabhushana 	}
75456b2bdd1SGireesh Nagabhushana #endif
75556b2bdd1SGireesh Nagabhushana 
75656b2bdd1SGireesh Nagabhushana 	return (0);
75756b2bdd1SGireesh Nagabhushana }
75856b2bdd1SGireesh Nagabhushana 
7593dde7c95SVishal Kulkarni int
t4_mc_unicst(void * arg,const uint8_t * ucaddr)76056b2bdd1SGireesh Nagabhushana t4_mc_unicst(void *arg, const uint8_t *ucaddr)
76156b2bdd1SGireesh Nagabhushana {
76256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
76356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
76456b2bdd1SGireesh Nagabhushana 	int rc;
76556b2bdd1SGireesh Nagabhushana 
7663dde7c95SVishal Kulkarni 	if (ucaddr == NULL)
7673dde7c95SVishal Kulkarni 		return (EINVAL);
7683dde7c95SVishal Kulkarni 
76956b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
77056b2bdd1SGireesh Nagabhushana 	if (rc != 0)
77156b2bdd1SGireesh Nagabhushana 		return (rc);
7723dde7c95SVishal Kulkarni 
7733dde7c95SVishal Kulkarni 	/* We will support adding only one mac address */
7743dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
7753dde7c95SVishal Kulkarni 		end_synchronized_op(pi, 1);
7763dde7c95SVishal Kulkarni 		return (ENOSPC);
7773dde7c95SVishal Kulkarni 	}
77856b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
7797e6ad469SVishal Kulkarni 			   true, &pi->smt_idx);
78056b2bdd1SGireesh Nagabhushana 	if (rc < 0)
78156b2bdd1SGireesh Nagabhushana 		rc = -rc;
78256b2bdd1SGireesh Nagabhushana 	else {
7833dde7c95SVishal Kulkarni 		pi->macaddr_cnt++;
78456b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
78556b2bdd1SGireesh Nagabhushana 		rc = 0;
78656b2bdd1SGireesh Nagabhushana 	}
78756b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
78856b2bdd1SGireesh Nagabhushana 
78956b2bdd1SGireesh Nagabhushana 	return (rc);
79056b2bdd1SGireesh Nagabhushana }
79156b2bdd1SGireesh Nagabhushana 
7923dde7c95SVishal Kulkarni int
t4_addmac(void * arg,const uint8_t * ucaddr)7933dde7c95SVishal Kulkarni t4_addmac(void *arg, const uint8_t *ucaddr)
7943dde7c95SVishal Kulkarni {
7953dde7c95SVishal Kulkarni 	return (t4_mc_unicst(arg, ucaddr));
7963dde7c95SVishal Kulkarni }
7973dde7c95SVishal Kulkarni 
7983dde7c95SVishal Kulkarni static int
t4_remmac(void * arg,const uint8_t * mac_addr)7993dde7c95SVishal Kulkarni t4_remmac(void *arg, const uint8_t *mac_addr)
8003dde7c95SVishal Kulkarni {
8013dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
8023dde7c95SVishal Kulkarni 	int rc;
8033dde7c95SVishal Kulkarni 
8043dde7c95SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
8053dde7c95SVishal Kulkarni 	if (rc != 0)
8063dde7c95SVishal Kulkarni 		return (rc);
8073dde7c95SVishal Kulkarni 
8083dde7c95SVishal Kulkarni 	pi->macaddr_cnt--;
8093dde7c95SVishal Kulkarni 	end_synchronized_op(pi, 1);
8103dde7c95SVishal Kulkarni 
8113dde7c95SVishal Kulkarni 	return (0);
8123dde7c95SVishal Kulkarni }
8133dde7c95SVishal Kulkarni 
8143dde7c95SVishal Kulkarni /*
8153dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all groups.
8163dde7c95SVishal Kulkarni  */
8173dde7c95SVishal Kulkarni 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)8183dde7c95SVishal Kulkarni t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
8193dde7c95SVishal Kulkarni 	      mac_group_info_t *infop, mac_group_handle_t gh)
8203dde7c95SVishal Kulkarni {
8213dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
8223dde7c95SVishal Kulkarni 
8233dde7c95SVishal Kulkarni 	switch (rtype) {
8243dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
8253dde7c95SVishal Kulkarni 		infop->mgi_driver = (mac_group_driver_t)arg;
8263dde7c95SVishal Kulkarni 		infop->mgi_start = NULL;
8273dde7c95SVishal Kulkarni 		infop->mgi_stop = NULL;
8283dde7c95SVishal Kulkarni 		infop->mgi_addmac = t4_addmac;
8293dde7c95SVishal Kulkarni 		infop->mgi_remmac = t4_remmac;
8303dde7c95SVishal Kulkarni 		infop->mgi_count = pi->nrxq;
8313dde7c95SVishal Kulkarni 		break;
8323dde7c95SVishal Kulkarni 	}
8333dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX:
8343dde7c95SVishal Kulkarni 	default:
8353dde7c95SVishal Kulkarni 		ASSERT(0);
8363dde7c95SVishal Kulkarni 		break;
8373dde7c95SVishal Kulkarni 	}
8383dde7c95SVishal Kulkarni }
8393dde7c95SVishal Kulkarni 
8403dde7c95SVishal Kulkarni static int
t4_ring_start(mac_ring_driver_t rh,uint64_t mr_gen_num)8413dde7c95SVishal Kulkarni t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
8423dde7c95SVishal Kulkarni {
8433dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
8443dde7c95SVishal Kulkarni 
8453dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
8463dde7c95SVishal Kulkarni 	rxq->ring_gen_num = mr_gen_num;
8473dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
8483dde7c95SVishal Kulkarni 	return (0);
8493dde7c95SVishal Kulkarni }
8503dde7c95SVishal Kulkarni 
8513dde7c95SVishal Kulkarni /*
8523dde7c95SVishal Kulkarni  * Enable interrupt on the specificed rx ring.
8533dde7c95SVishal Kulkarni  */
8543dde7c95SVishal Kulkarni int
t4_ring_intr_enable(mac_intr_handle_t intrh)8553dde7c95SVishal Kulkarni t4_ring_intr_enable(mac_intr_handle_t intrh)
8563dde7c95SVishal Kulkarni {
8573dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
8583dde7c95SVishal Kulkarni 	struct adapter *sc = rxq->port->adapter;
8593dde7c95SVishal Kulkarni 	struct sge_iq *iq;
8603dde7c95SVishal Kulkarni 
8613dde7c95SVishal Kulkarni 	iq = &rxq->iq;
8623dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
8633dde7c95SVishal Kulkarni 	iq->polling = 0;
8643dde7c95SVishal Kulkarni 	iq->state = IQS_IDLE;
8653dde7c95SVishal Kulkarni 	t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
8663dde7c95SVishal Kulkarni 		     V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id));
8673dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
8683dde7c95SVishal Kulkarni 	return (0);
8693dde7c95SVishal Kulkarni }
8703dde7c95SVishal Kulkarni 
8713dde7c95SVishal Kulkarni /*
8723dde7c95SVishal Kulkarni  * Disable interrupt on the specificed rx ring.
8733dde7c95SVishal Kulkarni  */
8743dde7c95SVishal Kulkarni int
t4_ring_intr_disable(mac_intr_handle_t intrh)8753dde7c95SVishal Kulkarni t4_ring_intr_disable(mac_intr_handle_t intrh)
8763dde7c95SVishal Kulkarni {
8773dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
8783dde7c95SVishal Kulkarni 	struct sge_iq *iq;
8793dde7c95SVishal Kulkarni 
8803dde7c95SVishal Kulkarni 	/* Nothing to be done here wrt interrupt, as it
8813dde7c95SVishal Kulkarni 	 * will not fire, until we write back to
8823dde7c95SVishal Kulkarni 	 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable.
8833dde7c95SVishal Kulkarni 	 */
8843dde7c95SVishal Kulkarni 
8853dde7c95SVishal Kulkarni 	iq = &rxq->iq;
8863dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
8873dde7c95SVishal Kulkarni 	iq->polling = 1;
8883dde7c95SVishal Kulkarni 	iq->state = IQS_BUSY;
8893dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
8903dde7c95SVishal Kulkarni 	return (0);
8913dde7c95SVishal Kulkarni }
8923dde7c95SVishal Kulkarni 
8933dde7c95SVishal Kulkarni mblk_t *
t4_poll_ring(void * arg,int n_bytes)8943dde7c95SVishal Kulkarni t4_poll_ring(void *arg, int n_bytes)
8953dde7c95SVishal Kulkarni {
8963dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)arg;
8973dde7c95SVishal Kulkarni 	mblk_t *mp = NULL;
8983dde7c95SVishal Kulkarni 
8993dde7c95SVishal Kulkarni 	ASSERT(n_bytes >= 0);
9003dde7c95SVishal Kulkarni 	if (n_bytes == 0)
9013dde7c95SVishal Kulkarni 		return (NULL);
9023dde7c95SVishal Kulkarni 
9033dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
9043dde7c95SVishal Kulkarni 	mp = t4_ring_rx(rxq, n_bytes);
9053dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
9063dde7c95SVishal Kulkarni 
9073dde7c95SVishal Kulkarni 	return (mp);
9083dde7c95SVishal Kulkarni }
9093dde7c95SVishal Kulkarni 
9103dde7c95SVishal Kulkarni /*
9113dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular rx ring
9123dde7c95SVishal Kulkarni  */
9133dde7c95SVishal Kulkarni int
t4_rx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)9143dde7c95SVishal Kulkarni t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
9153dde7c95SVishal Kulkarni {
9163dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
9173dde7c95SVishal Kulkarni 
9183dde7c95SVishal Kulkarni 	switch (stat) {
9193dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
9203dde7c95SVishal Kulkarni 		*val = rxq->rxbytes;
9213dde7c95SVishal Kulkarni 		break;
9223dde7c95SVishal Kulkarni 
9233dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
9243dde7c95SVishal Kulkarni 		*val = rxq->rxpkts;
9253dde7c95SVishal Kulkarni 		break;
9263dde7c95SVishal Kulkarni 
9273dde7c95SVishal Kulkarni 	default:
9283dde7c95SVishal Kulkarni 		*val = 0;
9293dde7c95SVishal Kulkarni 		return (ENOTSUP);
9303dde7c95SVishal Kulkarni 	}
9313dde7c95SVishal Kulkarni 
9323dde7c95SVishal Kulkarni 	return (0);
9333dde7c95SVishal Kulkarni }
9343dde7c95SVishal Kulkarni 
9353dde7c95SVishal Kulkarni /*
9363dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular tx ring
9373dde7c95SVishal Kulkarni  */
9383dde7c95SVishal Kulkarni int
t4_tx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)9393dde7c95SVishal Kulkarni t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
9403dde7c95SVishal Kulkarni {
9413dde7c95SVishal Kulkarni 	struct sge_txq *txq = (struct sge_txq *)rh;
9423dde7c95SVishal Kulkarni 
9433dde7c95SVishal Kulkarni 	switch (stat) {
9443dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
9453dde7c95SVishal Kulkarni 		*val = txq->txbytes;
9463dde7c95SVishal Kulkarni 		break;
9473dde7c95SVishal Kulkarni 
9483dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
9493dde7c95SVishal Kulkarni 		*val = txq->txpkts;
9503dde7c95SVishal Kulkarni 		break;
9513dde7c95SVishal Kulkarni 
9523dde7c95SVishal Kulkarni 	default:
9533dde7c95SVishal Kulkarni 		*val = 0;
9543dde7c95SVishal Kulkarni 		return (ENOTSUP);
9553dde7c95SVishal Kulkarni 	}
9563dde7c95SVishal Kulkarni 
9573dde7c95SVishal Kulkarni 	return (0);
9583dde7c95SVishal Kulkarni }
9593dde7c95SVishal Kulkarni 
9603dde7c95SVishal Kulkarni /*
9613dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all rings
9623dde7c95SVishal Kulkarni  * for given ring_group, noted by group_index.
9633dde7c95SVishal Kulkarni  * Since we have only one group, ring index becomes
9643dde7c95SVishal Kulkarni  * absolute index.
9653dde7c95SVishal Kulkarni  */
9663dde7c95SVishal Kulkarni 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)9673dde7c95SVishal Kulkarni t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
9683dde7c95SVishal Kulkarni 	     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
9693dde7c95SVishal Kulkarni {
9703dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
9713dde7c95SVishal Kulkarni 	mac_intr_t *mintr;
9723dde7c95SVishal Kulkarni 
9733dde7c95SVishal Kulkarni 	switch (rtype) {
9743dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
9753dde7c95SVishal Kulkarni 		struct sge_rxq *rxq;
9763dde7c95SVishal Kulkarni 
9773dde7c95SVishal Kulkarni 		rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
9783dde7c95SVishal Kulkarni 		rxq->ring_handle = rh;
9793dde7c95SVishal Kulkarni 
9803dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)rxq;
9813dde7c95SVishal Kulkarni 		infop->mri_start = t4_ring_start;
9823dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
9833dde7c95SVishal Kulkarni 		infop->mri_poll = t4_poll_ring;
9843dde7c95SVishal Kulkarni 		infop->mri_stat = t4_rx_stat;
9853dde7c95SVishal Kulkarni 
9863dde7c95SVishal Kulkarni 		mintr = &infop->mri_intr;
9873dde7c95SVishal Kulkarni 		mintr->mi_handle = (mac_intr_handle_t)rxq;
9883dde7c95SVishal Kulkarni 		mintr->mi_enable = t4_ring_intr_enable;
9893dde7c95SVishal Kulkarni 		mintr->mi_disable = t4_ring_intr_disable;
9903dde7c95SVishal Kulkarni 
9913dde7c95SVishal Kulkarni 		break;
9923dde7c95SVishal Kulkarni 	}
9933dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX: {
9943dde7c95SVishal Kulkarni 		struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index];
9953dde7c95SVishal Kulkarni 		txq->ring_handle = rh;
9963dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)txq;
9973dde7c95SVishal Kulkarni 		infop->mri_start = NULL;
9983dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
9993dde7c95SVishal Kulkarni 		infop->mri_tx = t4_eth_tx;
10003dde7c95SVishal Kulkarni 		infop->mri_stat = t4_tx_stat;
10013dde7c95SVishal Kulkarni 		break;
10023dde7c95SVishal Kulkarni 	}
10033dde7c95SVishal Kulkarni 	default:
10043dde7c95SVishal Kulkarni 		ASSERT(0);
10053dde7c95SVishal Kulkarni 		break;
10063dde7c95SVishal Kulkarni 	}
10073dde7c95SVishal Kulkarni }
10083dde7c95SVishal Kulkarni 
10093dde7c95SVishal Kulkarni mblk_t *
t4_mc_tx(void * arg,mblk_t * m)101056b2bdd1SGireesh Nagabhushana t4_mc_tx(void *arg, mblk_t *m)
101156b2bdd1SGireesh Nagabhushana {
101256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
101356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
101456b2bdd1SGireesh Nagabhushana 	struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
101556b2bdd1SGireesh Nagabhushana 
10163dde7c95SVishal Kulkarni 	return (t4_eth_tx(txq, m));
101756b2bdd1SGireesh Nagabhushana }
101856b2bdd1SGireesh Nagabhushana 
1019017c366dSRobert Mustacchi static int
t4_mc_transceiver_info(void * arg,uint_t id,mac_transceiver_info_t * infop)1020017c366dSRobert Mustacchi t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
1021017c366dSRobert Mustacchi {
1022017c366dSRobert Mustacchi 	struct port_info *pi = arg;
1023017c366dSRobert Mustacchi 
1024017c366dSRobert Mustacchi 	if (id != 0 || infop == NULL)
1025017c366dSRobert Mustacchi 		return (EINVAL);
1026017c366dSRobert Mustacchi 
1027017c366dSRobert Mustacchi 	switch (pi->mod_type) {
1028017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NONE:
1029017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_FALSE);
1030017c366dSRobert Mustacchi 		break;
1031017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NOTSUPPORTED:
1032017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
1033017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_FALSE);
1034017c366dSRobert Mustacchi 		break;
1035017c366dSRobert Mustacchi 	default:
1036017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
1037017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_TRUE);
1038017c366dSRobert Mustacchi 		break;
1039017c366dSRobert Mustacchi 	}
1040017c366dSRobert Mustacchi 
1041017c366dSRobert Mustacchi 	return (0);
1042017c366dSRobert Mustacchi }
1043017c366dSRobert Mustacchi 
1044017c366dSRobert Mustacchi 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)1045017c366dSRobert Mustacchi t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
1046017c366dSRobert Mustacchi     size_t nbytes, off_t offset, size_t *nread)
1047017c366dSRobert Mustacchi {
1048017c366dSRobert Mustacchi 	struct port_info *pi = arg;
1049017c366dSRobert Mustacchi 	struct adapter *sc = pi->adapter;
1050017c366dSRobert Mustacchi 	int rc;
1051017c366dSRobert Mustacchi 	size_t i, maxread;
1052017c366dSRobert Mustacchi 	/* LINTED: E_FUNC_VAR_UNUSED */
1053017c366dSRobert Mustacchi 	struct fw_ldst_cmd ldst __unused;
1054017c366dSRobert Mustacchi 
1055017c366dSRobert Mustacchi 	if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
1056017c366dSRobert Mustacchi 	    (page != 0xa0 && page != 0xa2) || offset < 0)
1057017c366dSRobert Mustacchi 		return (EINVAL);
1058017c366dSRobert Mustacchi 
1059017c366dSRobert Mustacchi 	if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
1060017c366dSRobert Mustacchi 		return (EINVAL);
1061017c366dSRobert Mustacchi 
1062017c366dSRobert Mustacchi 	rc = begin_synchronized_op(pi, 0, 1);
1063017c366dSRobert Mustacchi 	if (rc != 0)
1064017c366dSRobert Mustacchi 		return (rc);
1065017c366dSRobert Mustacchi 
1066017c366dSRobert Mustacchi 	/*
1067017c366dSRobert Mustacchi 	 * Firmware has a maximum size that we can read. Don't read more than it
1068017c366dSRobert Mustacchi 	 * allows.
1069017c366dSRobert Mustacchi 	 */
1070017c366dSRobert Mustacchi 	maxread = sizeof (ldst.u.i2c.data);
1071017c366dSRobert Mustacchi 	for (i = 0; i < nbytes; i += maxread) {
1072017c366dSRobert Mustacchi 		size_t toread = MIN(maxread, nbytes - i);
1073017c366dSRobert Mustacchi 		rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
1074017c366dSRobert Mustacchi 		    bp);
1075017c366dSRobert Mustacchi 		if (rc != 0)
1076017c366dSRobert Mustacchi 			break;
1077017c366dSRobert Mustacchi 		offset += toread;
1078017c366dSRobert Mustacchi 		bp = (void *)((uintptr_t)bp + toread);
1079017c366dSRobert Mustacchi 	}
1080017c366dSRobert Mustacchi 	end_synchronized_op(pi, 0);
1081017c366dSRobert Mustacchi 	if (rc == 0)
1082017c366dSRobert Mustacchi 		*nread = nbytes;
1083017c366dSRobert Mustacchi 	return (rc);
1084017c366dSRobert Mustacchi }
1085017c366dSRobert Mustacchi 
1086d87e4548SVishal Kulkarni static int
t4_port_led_set(void * arg,mac_led_mode_t mode,uint_t flags)1087d87e4548SVishal Kulkarni t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
1088d87e4548SVishal Kulkarni {
1089d87e4548SVishal Kulkarni 	struct port_info *pi = arg;
1090d87e4548SVishal Kulkarni 	struct adapter *sc = pi->adapter;
1091d87e4548SVishal Kulkarni 	int val, rc;
1092d87e4548SVishal Kulkarni 
1093d87e4548SVishal Kulkarni 	if (flags != 0)
1094d87e4548SVishal Kulkarni 		return (EINVAL);
1095d87e4548SVishal Kulkarni 
1096d87e4548SVishal Kulkarni 	switch (mode) {
1097d87e4548SVishal Kulkarni 	case MAC_LED_DEFAULT:
1098d87e4548SVishal Kulkarni 		val = 0;
1099d87e4548SVishal Kulkarni 		break;
1100d87e4548SVishal Kulkarni 	case MAC_LED_IDENT:
1101d87e4548SVishal Kulkarni 		val = 0xffff;
1102d87e4548SVishal Kulkarni 		break;
1103d87e4548SVishal Kulkarni 
1104d87e4548SVishal Kulkarni 	default:
1105d87e4548SVishal Kulkarni 		return (ENOTSUP);
1106d87e4548SVishal Kulkarni 	}
1107d87e4548SVishal Kulkarni 
1108d87e4548SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
1109d87e4548SVishal Kulkarni 	if (rc != 0)
1110d87e4548SVishal Kulkarni 		return (rc);
1111d87e4548SVishal Kulkarni 	rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
1112d87e4548SVishal Kulkarni 	end_synchronized_op(pi, 1);
1113d87e4548SVishal Kulkarni 
1114d87e4548SVishal Kulkarni 	return (rc);
1115d87e4548SVishal Kulkarni }
1116d87e4548SVishal Kulkarni 
111756b2bdd1SGireesh Nagabhushana static boolean_t
t4_mc_getcapab(void * arg,mac_capab_t cap,void * data)111856b2bdd1SGireesh Nagabhushana t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
111956b2bdd1SGireesh Nagabhushana {
112056b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
112156b2bdd1SGireesh Nagabhushana 	boolean_t status = B_TRUE;
1122017c366dSRobert Mustacchi 	mac_capab_transceiver_t *mct;
1123d87e4548SVishal Kulkarni 	mac_capab_led_t *mcl;
112456b2bdd1SGireesh Nagabhushana 
112556b2bdd1SGireesh Nagabhushana 	switch (cap) {
112656b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_HCKSUM:
112756b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_CSUM) {
112856b2bdd1SGireesh Nagabhushana 			uint32_t *d = data;
1129d75c6062SRobert Mustacchi 			*d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM |
1130d75c6062SRobert Mustacchi 			    HCKSUM_INET_FULL_V6;
113156b2bdd1SGireesh Nagabhushana 		} else
113256b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
113356b2bdd1SGireesh Nagabhushana 		break;
113456b2bdd1SGireesh Nagabhushana 
113556b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_LSO:
113656b2bdd1SGireesh Nagabhushana 		/* Enabling LSO requires Checksum offloading */
113756b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_LSO &&
113856b2bdd1SGireesh Nagabhushana 		    pi->features & CXGBE_HW_CSUM) {
113956b2bdd1SGireesh Nagabhushana 			mac_capab_lso_t *d = data;
114056b2bdd1SGireesh Nagabhushana 
1141d75c6062SRobert Mustacchi 			d->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
1142d75c6062SRobert Mustacchi 			    LSO_TX_BASIC_TCP_IPV6;
114356b2bdd1SGireesh Nagabhushana 			d->lso_basic_tcp_ipv4.lso_max = 65535;
1144d75c6062SRobert Mustacchi 			d->lso_basic_tcp_ipv6.lso_max = 65535;
114556b2bdd1SGireesh Nagabhushana 		} else
114656b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
114756b2bdd1SGireesh Nagabhushana 		break;
114856b2bdd1SGireesh Nagabhushana 
11493dde7c95SVishal Kulkarni 	case MAC_CAPAB_RINGS: {
11503dde7c95SVishal Kulkarni 		mac_capab_rings_t *cap_rings = data;
11513dde7c95SVishal Kulkarni 
11523dde7c95SVishal Kulkarni 		if (!pi->adapter->props.multi_rings) {
11533dde7c95SVishal Kulkarni 			status = B_FALSE;
11543dde7c95SVishal Kulkarni 			break;
11553dde7c95SVishal Kulkarni 		}
11563dde7c95SVishal Kulkarni 		switch (cap_rings->mr_type) {
11573dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_RX:
11583dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
11593dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->nrxq;
11603dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 1;
11613dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
11623dde7c95SVishal Kulkarni 			cap_rings->mr_gget = t4_fill_group;
11633dde7c95SVishal Kulkarni 			cap_rings->mr_gaddring = NULL;
11643dde7c95SVishal Kulkarni 			cap_rings->mr_gremring = NULL;
11653dde7c95SVishal Kulkarni 			break;
11663dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_TX:
11673dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
11683dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->ntxq;
11693dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 0;
11703dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
11713dde7c95SVishal Kulkarni 			cap_rings->mr_gget = NULL;
11723dde7c95SVishal Kulkarni 			break;
11733dde7c95SVishal Kulkarni 		}
11743dde7c95SVishal Kulkarni 		break;
11753dde7c95SVishal Kulkarni 	}
1176017c366dSRobert Mustacchi 
1177017c366dSRobert Mustacchi 	case MAC_CAPAB_TRANSCEIVER:
1178017c366dSRobert Mustacchi 		mct = data;
1179017c366dSRobert Mustacchi 
1180017c366dSRobert Mustacchi 		mct->mct_flags = 0;
1181017c366dSRobert Mustacchi 		mct->mct_ntransceivers = 1;
1182017c366dSRobert Mustacchi 		mct->mct_info = t4_mc_transceiver_info;
1183017c366dSRobert Mustacchi 		mct->mct_read = t4_mc_transceiver_read;
1184017c366dSRobert Mustacchi 		break;
1185d87e4548SVishal Kulkarni 	case MAC_CAPAB_LED:
1186d87e4548SVishal Kulkarni 		mcl = data;
1187d87e4548SVishal Kulkarni 		mcl->mcl_flags = 0;
1188d87e4548SVishal Kulkarni 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
1189d87e4548SVishal Kulkarni 		mcl->mcl_set = t4_port_led_set;
1190d87e4548SVishal Kulkarni 		break;
1191017c366dSRobert Mustacchi 
119256b2bdd1SGireesh Nagabhushana 	default:
119356b2bdd1SGireesh Nagabhushana 		status = B_FALSE; /* cap not supported */
119456b2bdd1SGireesh Nagabhushana 	}
119556b2bdd1SGireesh Nagabhushana 
119656b2bdd1SGireesh Nagabhushana 	return (status);
119756b2bdd1SGireesh Nagabhushana }
119856b2bdd1SGireesh Nagabhushana 
t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,link_flowctrl_t * fc)11996feac2e3SRahul Lakkireddy static void t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,
12006feac2e3SRahul Lakkireddy 					 link_flowctrl_t *fc)
1201d77e6e0fSPaul Winder {
12026feac2e3SRahul Lakkireddy 	u8 pause_tx = 0, pause_rx = 0;
1203d77e6e0fSPaul Winder 
12046feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FC_TX)
12056feac2e3SRahul Lakkireddy 		pause_tx = 1;
1206d77e6e0fSPaul Winder 
12076feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FC_RX)
12086feac2e3SRahul Lakkireddy 		pause_rx = 1;
12096feac2e3SRahul Lakkireddy 
12106feac2e3SRahul Lakkireddy 	if (pause_rx & pause_tx)
12116feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_BI;
12126feac2e3SRahul Lakkireddy 	else if (pause_tx)
12136feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_TX;
12146feac2e3SRahul Lakkireddy 	else if (pause_rx)
12156feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_RX;
12166feac2e3SRahul Lakkireddy 	else
12176feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_NONE;
12186feac2e3SRahul Lakkireddy }
12196feac2e3SRahul Lakkireddy 
t4_mac_flowctrl_to_link_caps(struct port_info * pi,link_flowctrl_t fc,fw_port_cap32_t * new_caps)12206feac2e3SRahul Lakkireddy static int t4_mac_flowctrl_to_link_caps(struct port_info *pi,
12216feac2e3SRahul Lakkireddy 					link_flowctrl_t fc,
12226feac2e3SRahul Lakkireddy 					fw_port_cap32_t *new_caps)
12236feac2e3SRahul Lakkireddy {
12246feac2e3SRahul Lakkireddy 	cc_pause_t pause = 0;
12256feac2e3SRahul Lakkireddy 
12266feac2e3SRahul Lakkireddy 	switch (fc) {
12276feac2e3SRahul Lakkireddy 	case LINK_FLOWCTRL_BI:
12286feac2e3SRahul Lakkireddy 		pause |= PAUSE_TX | PAUSE_RX;
12296feac2e3SRahul Lakkireddy 		break;
12306feac2e3SRahul Lakkireddy 	case LINK_FLOWCTRL_TX:
12316feac2e3SRahul Lakkireddy 		pause |= PAUSE_TX;
12326feac2e3SRahul Lakkireddy 		break;
12336feac2e3SRahul Lakkireddy 	case LINK_FLOWCTRL_RX:
12346feac2e3SRahul Lakkireddy 		pause |= PAUSE_RX;
12356feac2e3SRahul Lakkireddy 		break;
12366feac2e3SRahul Lakkireddy 	default:
12376feac2e3SRahul Lakkireddy 		break;
12386feac2e3SRahul Lakkireddy 	}
12396feac2e3SRahul Lakkireddy 
12406feac2e3SRahul Lakkireddy 	if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG)
12416feac2e3SRahul Lakkireddy 		pause |= PAUSE_AUTONEG;
1242d77e6e0fSPaul Winder 
12436feac2e3SRahul Lakkireddy 	return t4_link_set_pause(pi, pause, new_caps);
12446feac2e3SRahul Lakkireddy }
1245d77e6e0fSPaul Winder 
t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)12466feac2e3SRahul Lakkireddy static link_fec_t t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)
12476feac2e3SRahul Lakkireddy {
12486feac2e3SRahul Lakkireddy 	link_fec_t link_fec = 0;
12496feac2e3SRahul Lakkireddy 
12506feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FEC_RS)
1251d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_RS;
1252d77e6e0fSPaul Winder 
12536feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FEC_BASER_RS)
1254d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_BASE_R;
1255d77e6e0fSPaul Winder 
12566feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FEC_NO_FEC)
12576feac2e3SRahul Lakkireddy 		link_fec |= LINK_FEC_NONE;
12586feac2e3SRahul Lakkireddy 
12596feac2e3SRahul Lakkireddy 	if ((link_fec & (link_fec - 1)) &&
12606feac2e3SRahul Lakkireddy 	    !(caps & FW_PORT_CAP32_FORCE_FEC))
12616feac2e3SRahul Lakkireddy 		return LINK_FEC_AUTO;
12626feac2e3SRahul Lakkireddy 
12636feac2e3SRahul Lakkireddy 	return link_fec;
1264d77e6e0fSPaul Winder }
1265d77e6e0fSPaul Winder 
t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)12666feac2e3SRahul Lakkireddy static void t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,
12676feac2e3SRahul Lakkireddy 					 link_fec_t *fec)
12686feac2e3SRahul Lakkireddy {
12696feac2e3SRahul Lakkireddy 	*fec = t4_mac_port_caps_to_fec_cap(caps);
12706feac2e3SRahul Lakkireddy }
12716feac2e3SRahul Lakkireddy 
t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)12726feac2e3SRahul Lakkireddy static void t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,
12736feac2e3SRahul Lakkireddy 					link_fec_t *fec)
1274d77e6e0fSPaul Winder {
12756feac2e3SRahul Lakkireddy 	link_fec_t link_fec;
1276d77e6e0fSPaul Winder 
12776feac2e3SRahul Lakkireddy 	caps &= ~FW_PORT_CAP32_FEC_NO_FEC;
12786feac2e3SRahul Lakkireddy 	link_fec = t4_mac_port_caps_to_fec_cap(caps);
12796feac2e3SRahul Lakkireddy 	*fec = link_fec ? link_fec : LINK_FEC_NONE;
12806feac2e3SRahul Lakkireddy }
12816feac2e3SRahul Lakkireddy 
t4_mac_fec_cap_to_link_caps(struct port_info * pi,link_fec_t v,fw_port_cap32_t * new_caps)12826feac2e3SRahul Lakkireddy static int t4_mac_fec_cap_to_link_caps(struct port_info *pi, link_fec_t v,
12836feac2e3SRahul Lakkireddy 				       fw_port_cap32_t *new_caps)
12846feac2e3SRahul Lakkireddy {
12856feac2e3SRahul Lakkireddy 	cc_fec_t fec = 0;
12866feac2e3SRahul Lakkireddy 
12876feac2e3SRahul Lakkireddy 	if (v == LINK_FEC_AUTO) {
1288d77e6e0fSPaul Winder 		fec = FEC_AUTO;
12896feac2e3SRahul Lakkireddy 		goto out;
12906feac2e3SRahul Lakkireddy 	}
1291d77e6e0fSPaul Winder 
12926feac2e3SRahul Lakkireddy 	if (v & LINK_FEC_NONE) {
12936feac2e3SRahul Lakkireddy 		v &= ~LINK_FEC_NONE;
12946feac2e3SRahul Lakkireddy 		fec |= FEC_NONE;
12956feac2e3SRahul Lakkireddy 	}
1296d77e6e0fSPaul Winder 
12976feac2e3SRahul Lakkireddy 	if (v & LINK_FEC_RS) {
12986feac2e3SRahul Lakkireddy 		v &= ~LINK_FEC_RS;
12996feac2e3SRahul Lakkireddy 		fec |= FEC_RS;
13006feac2e3SRahul Lakkireddy 	}
13016feac2e3SRahul Lakkireddy 
13026feac2e3SRahul Lakkireddy 	if (v & LINK_FEC_BASE_R) {
13036feac2e3SRahul Lakkireddy 		v &= ~LINK_FEC_BASE_R;
13046feac2e3SRahul Lakkireddy 		fec |= FEC_BASER_RS;
1305d77e6e0fSPaul Winder 	}
1306d77e6e0fSPaul Winder 
1307d77e6e0fSPaul Winder 	if (v != 0)
1308d77e6e0fSPaul Winder 		return (-1);
1309d77e6e0fSPaul Winder 
1310d77e6e0fSPaul Winder 	ASSERT3S(fec, !=, 0);
1311d77e6e0fSPaul Winder 
13126feac2e3SRahul Lakkireddy 	fec |= FEC_FORCE;
13136feac2e3SRahul Lakkireddy 
13146feac2e3SRahul Lakkireddy out:
13156feac2e3SRahul Lakkireddy 	return t4_link_set_fec(pi, fec, new_caps);
1316d77e6e0fSPaul Winder }
1317d77e6e0fSPaul Winder 
131856b2bdd1SGireesh Nagabhushana /* ARGSUSED */
131956b2bdd1SGireesh Nagabhushana static int
t4_mc_setprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,const void * val)132056b2bdd1SGireesh Nagabhushana t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
132156b2bdd1SGireesh Nagabhushana     const void *val)
132256b2bdd1SGireesh Nagabhushana {
132356b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
132456b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
13256feac2e3SRahul Lakkireddy 	struct link_config *lc = &pi->link_cfg;
13266feac2e3SRahul Lakkireddy 	fw_port_cap32_t new_caps = lc->admin_caps;
13276feac2e3SRahul Lakkireddy 	int relink = 0, rx_mode = 0, rc = 0;
132856b2bdd1SGireesh Nagabhushana 	uint32_t v32 = *(uint32_t *)val;
13296feac2e3SRahul Lakkireddy 	uint8_t v8 = *(uint8_t *)val;
133056b2bdd1SGireesh Nagabhushana 	link_flowctrl_t fc;
1331d77e6e0fSPaul Winder 	link_fec_t fec;
133256b2bdd1SGireesh Nagabhushana 
133356b2bdd1SGireesh Nagabhushana 	switch (id) {
133456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
13356feac2e3SRahul Lakkireddy 		rc = t4_link_set_autoneg(pi, v8, &new_caps);
13366feac2e3SRahul Lakkireddy 		relink = 1;
133756b2bdd1SGireesh Nagabhushana 		break;
133856b2bdd1SGireesh Nagabhushana 
133956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
134056b2bdd1SGireesh Nagabhushana 		if (v32 < 46 || v32 > MAX_MTU) {
134156b2bdd1SGireesh Nagabhushana 			rc = EINVAL;
134256b2bdd1SGireesh Nagabhushana 		} else if (v32 != pi->mtu) {
134356b2bdd1SGireesh Nagabhushana 			pi->mtu = v32;
134456b2bdd1SGireesh Nagabhushana 			(void) mac_maxsdu_update(pi->mh, v32);
134556b2bdd1SGireesh Nagabhushana 			rx_mode = 1;
134656b2bdd1SGireesh Nagabhushana 		}
134756b2bdd1SGireesh Nagabhushana 
134856b2bdd1SGireesh Nagabhushana 		break;
134956b2bdd1SGireesh Nagabhushana 
135056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
135156b2bdd1SGireesh Nagabhushana 		fc = *(link_flowctrl_t *)val;
13526feac2e3SRahul Lakkireddy 		rc = t4_mac_flowctrl_to_link_caps(pi, fc, &new_caps);
13536feac2e3SRahul Lakkireddy 		relink = 1;
135456b2bdd1SGireesh Nagabhushana 		break;
135556b2bdd1SGireesh Nagabhushana 
1356d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1357d77e6e0fSPaul Winder 		fec = *(link_fec_t *)val;
13586feac2e3SRahul Lakkireddy 		rc = t4_mac_fec_cap_to_link_caps(pi, fec, &new_caps);
13596feac2e3SRahul Lakkireddy 		relink = 1;
1360d77e6e0fSPaul Winder 		break;
1361d77e6e0fSPaul Winder 
13626feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_100GFDX_CAP:
13636feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100G, v8,
13646feac2e3SRahul Lakkireddy 				       &new_caps);
13656feac2e3SRahul Lakkireddy 		relink = 1;
13666feac2e3SRahul Lakkireddy 		break;
136756b2bdd1SGireesh Nagabhushana 
13686feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_50GFDX_CAP:
13696feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_50G, v8,
13706feac2e3SRahul Lakkireddy 				       &new_caps);
13716feac2e3SRahul Lakkireddy 		relink = 1;
13726feac2e3SRahul Lakkireddy 		break;
13736feac2e3SRahul Lakkireddy 
13746feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_40GFDX_CAP:
13756feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_40G, v8,
13766feac2e3SRahul Lakkireddy 				       &new_caps);
13776feac2e3SRahul Lakkireddy 		relink = 1;
13786feac2e3SRahul Lakkireddy 		break;
13796feac2e3SRahul Lakkireddy 
13806feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_25GFDX_CAP:
13816feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_25G, v8,
13826feac2e3SRahul Lakkireddy 				       &new_caps);
13836feac2e3SRahul Lakkireddy 		relink = 1;
13846feac2e3SRahul Lakkireddy 		break;
13856feac2e3SRahul Lakkireddy 
13866feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_10GFDX_CAP:
13876feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_10G, v8,
13886feac2e3SRahul Lakkireddy 				       &new_caps);
13896feac2e3SRahul Lakkireddy 		relink = 1;
139056b2bdd1SGireesh Nagabhushana 		break;
139156b2bdd1SGireesh Nagabhushana 
139256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
13936feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_1G, v8,
13946feac2e3SRahul Lakkireddy 				       &new_caps);
13956feac2e3SRahul Lakkireddy 		relink = 1;
139656b2bdd1SGireesh Nagabhushana 		break;
139756b2bdd1SGireesh Nagabhushana 
139856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
13996feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100M, v8,
14006feac2e3SRahul Lakkireddy 				       &new_caps);
14016feac2e3SRahul Lakkireddy 		relink = 1;
140256b2bdd1SGireesh Nagabhushana 		break;
140356b2bdd1SGireesh Nagabhushana 
140456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
140556b2bdd1SGireesh Nagabhushana 		rc = setprop(pi, name, val);
140656b2bdd1SGireesh Nagabhushana 		break;
140756b2bdd1SGireesh Nagabhushana 
140856b2bdd1SGireesh Nagabhushana 	default:
140956b2bdd1SGireesh Nagabhushana 		rc = ENOTSUP;
14106feac2e3SRahul Lakkireddy 		break;
141156b2bdd1SGireesh Nagabhushana 	}
141256b2bdd1SGireesh Nagabhushana 
14136feac2e3SRahul Lakkireddy 	if (rc != 0)
14146feac2e3SRahul Lakkireddy 		return (rc);
14156feac2e3SRahul Lakkireddy 
141656b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
141756b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
141856b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
141956b2bdd1SGireesh Nagabhushana 			if (rc != 0)
142056b2bdd1SGireesh Nagabhushana 				return (rc);
14216feac2e3SRahul Lakkireddy 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
14226feac2e3SRahul Lakkireddy 					    new_caps);
142356b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
142456b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
142556b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
14266feac2e3SRahul Lakkireddy 					    "%s link config failed: %d",
14276feac2e3SRahul Lakkireddy 					    __func__, rc);
14286feac2e3SRahul Lakkireddy 				return (rc);
142956b2bdd1SGireesh Nagabhushana 			}
143056b2bdd1SGireesh Nagabhushana 		}
143156b2bdd1SGireesh Nagabhushana 
143256b2bdd1SGireesh Nagabhushana 		if (rx_mode != 0) {
143356b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
143456b2bdd1SGireesh Nagabhushana 			if (rc != 0)
143556b2bdd1SGireesh Nagabhushana 				return (rc);
143656b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
143756b2bdd1SGireesh Nagabhushana 			    -1, -1, -1, false);
143856b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
143956b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
144056b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
144156b2bdd1SGireesh Nagabhushana 				    "set_rxmode failed: %d", rc);
14426feac2e3SRahul Lakkireddy 				return (rc);
144356b2bdd1SGireesh Nagabhushana 			}
144456b2bdd1SGireesh Nagabhushana 		}
144556b2bdd1SGireesh Nagabhushana 	}
144656b2bdd1SGireesh Nagabhushana 
14476feac2e3SRahul Lakkireddy 	if (relink != 0)
14486feac2e3SRahul Lakkireddy 		lc->admin_caps = new_caps;
14496feac2e3SRahul Lakkireddy 
14506feac2e3SRahul Lakkireddy 	return (0);
145156b2bdd1SGireesh Nagabhushana }
145256b2bdd1SGireesh Nagabhushana 
145356b2bdd1SGireesh Nagabhushana static int
t4_mc_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,void * val)145456b2bdd1SGireesh Nagabhushana t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
145556b2bdd1SGireesh Nagabhushana     void *val)
145656b2bdd1SGireesh Nagabhushana {
145756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
145856b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
145956b2bdd1SGireesh Nagabhushana 	uint8_t *u = val;
14606feac2e3SRahul Lakkireddy 	int rc = 0;
146156b2bdd1SGireesh Nagabhushana 
146256b2bdd1SGireesh Nagabhushana 	switch (id) {
146356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
146456b2bdd1SGireesh Nagabhushana 		*(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
146556b2bdd1SGireesh Nagabhushana 		    LINK_DUPLEX_UNKNOWN;
146656b2bdd1SGireesh Nagabhushana 		break;
146756b2bdd1SGireesh Nagabhushana 
146856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
146956b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
14706feac2e3SRahul Lakkireddy 			*(uint64_t *)val = t4_link_fwcap_to_speed(lc->link_caps);
147156b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val *= 1000000;
14726feac2e3SRahul Lakkireddy 		} else {
147356b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val = 0;
14746feac2e3SRahul Lakkireddy 		}
147556b2bdd1SGireesh Nagabhushana 		break;
147656b2bdd1SGireesh Nagabhushana 
147756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
147856b2bdd1SGireesh Nagabhushana 		*(link_state_t *)val = lc->link_ok ? LINK_STATE_UP :
147956b2bdd1SGireesh Nagabhushana 		    LINK_STATE_DOWN;
148056b2bdd1SGireesh Nagabhushana 		break;
148156b2bdd1SGireesh Nagabhushana 
1482*ece8d794SRobert Mustacchi 	case MAC_PROP_MEDIA:
1483*ece8d794SRobert Mustacchi 		*(mac_ether_media_t *)val = t4_port_to_media(pi);
1484*ece8d794SRobert Mustacchi 		break;
1485*ece8d794SRobert Mustacchi 
148656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
14876feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
148856b2bdd1SGireesh Nagabhushana 		break;
148956b2bdd1SGireesh Nagabhushana 
149056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
149156b2bdd1SGireesh Nagabhushana 		*(uint32_t *)val = pi->mtu;
149256b2bdd1SGireesh Nagabhushana 		break;
149356b2bdd1SGireesh Nagabhushana 
149456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
14956feac2e3SRahul Lakkireddy 		t4_mac_link_caps_to_flowctrl(lc->link_caps, val);
149656b2bdd1SGireesh Nagabhushana 		break;
149756b2bdd1SGireesh Nagabhushana 
1498d77e6e0fSPaul Winder 	case MAC_PROP_ADV_FEC_CAP:
14996feac2e3SRahul Lakkireddy 		t4_mac_link_caps_to_fec_cap(lc->link_caps, val);
1500d77e6e0fSPaul Winder 		break;
1501d77e6e0fSPaul Winder 
1502d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
15036feac2e3SRahul Lakkireddy 		t4_mac_admin_caps_to_fec_cap(lc->admin_caps, val);
1504d77e6e0fSPaul Winder 		break;
1505d77e6e0fSPaul Winder 
15063dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_100GFDX_CAP:
15076feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100G);
15086feac2e3SRahul Lakkireddy 		break;
15096feac2e3SRahul Lakkireddy 
15103dde7c95SVishal Kulkarni 	case MAC_PROP_EN_100GFDX_CAP:
15116feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
15126feac2e3SRahul Lakkireddy 		break;
15136feac2e3SRahul Lakkireddy 
15146feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_50GFDX_CAP:
15156feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_50G);
15166feac2e3SRahul Lakkireddy 		break;
15176feac2e3SRahul Lakkireddy 
15186feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_50GFDX_CAP:
15196feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
15203dde7c95SVishal Kulkarni 		break;
15213dde7c95SVishal Kulkarni 
15223dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_40GFDX_CAP:
15236feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_40G);
15246feac2e3SRahul Lakkireddy 		break;
15256feac2e3SRahul Lakkireddy 
15263dde7c95SVishal Kulkarni 	case MAC_PROP_EN_40GFDX_CAP:
15276feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
15283dde7c95SVishal Kulkarni 		break;
15293dde7c95SVishal Kulkarni 
15303dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_25GFDX_CAP:
15316feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_25G);
15326feac2e3SRahul Lakkireddy 		break;
15336feac2e3SRahul Lakkireddy 
15343dde7c95SVishal Kulkarni 	case MAC_PROP_EN_25GFDX_CAP:
15356feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
15363dde7c95SVishal Kulkarni 		break;
15373dde7c95SVishal Kulkarni 
153856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
15396feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_10G);
15406feac2e3SRahul Lakkireddy 		break;
15416feac2e3SRahul Lakkireddy 
154256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
15436feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
154456b2bdd1SGireesh Nagabhushana 		break;
154556b2bdd1SGireesh Nagabhushana 
154656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
15476feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_1G);
15486feac2e3SRahul Lakkireddy 		break;
15496feac2e3SRahul Lakkireddy 
155056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
15516feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
155256b2bdd1SGireesh Nagabhushana 		break;
155356b2bdd1SGireesh Nagabhushana 
155456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
15556feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100M);
15566feac2e3SRahul Lakkireddy 		break;
15576feac2e3SRahul Lakkireddy 
155856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
15596feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
156056b2bdd1SGireesh Nagabhushana 		break;
156156b2bdd1SGireesh Nagabhushana 
156256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
156356b2bdd1SGireesh Nagabhushana 		return (getprop(pi, name, size, val));
156456b2bdd1SGireesh Nagabhushana 
156556b2bdd1SGireesh Nagabhushana 	default:
156656b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
156756b2bdd1SGireesh Nagabhushana 	}
156856b2bdd1SGireesh Nagabhushana 
15696feac2e3SRahul Lakkireddy 	return (rc);
157056b2bdd1SGireesh Nagabhushana }
157156b2bdd1SGireesh Nagabhushana 
157256b2bdd1SGireesh Nagabhushana static void
t4_mc_propinfo(void * arg,const char * name,mac_prop_id_t id,mac_prop_info_handle_t ph)157356b2bdd1SGireesh Nagabhushana t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
157456b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph)
157556b2bdd1SGireesh Nagabhushana {
157656b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
157756b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
157856b2bdd1SGireesh Nagabhushana 
157956b2bdd1SGireesh Nagabhushana 	switch (id) {
158056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
158156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
158256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
158356b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
158456b2bdd1SGireesh Nagabhushana 		break;
158556b2bdd1SGireesh Nagabhushana 
158656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
15877e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG)
158856b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
158956b2bdd1SGireesh Nagabhushana 		else
159056b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
159156b2bdd1SGireesh Nagabhushana 		break;
159256b2bdd1SGireesh Nagabhushana 
159356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
159456b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_range_uint32(ph, 46, MAX_MTU);
159556b2bdd1SGireesh Nagabhushana 		break;
159656b2bdd1SGireesh Nagabhushana 
159756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
159856b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI);
159956b2bdd1SGireesh Nagabhushana 		break;
160056b2bdd1SGireesh Nagabhushana 
1601d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1602d77e6e0fSPaul Winder 		mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1603d77e6e0fSPaul Winder 		break;
1604d77e6e0fSPaul Winder 
1605d77e6e0fSPaul Winder 	case MAC_PROP_ADV_FEC_CAP:
1606d77e6e0fSPaul Winder 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1607d77e6e0fSPaul Winder 		mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1608d77e6e0fSPaul Winder 		break;
1609d77e6e0fSPaul Winder 
16106feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_100GFDX_CAP:
16116feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_100G)
16126feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
16136feac2e3SRahul Lakkireddy 		else
16146feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16156feac2e3SRahul Lakkireddy 		break;
16166feac2e3SRahul Lakkireddy 
16176feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_50GFDX_CAP:
16186feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_50G)
16196feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
16206feac2e3SRahul Lakkireddy 		else
16216feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16226feac2e3SRahul Lakkireddy 		break;
16236feac2e3SRahul Lakkireddy 
16246feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_40GFDX_CAP:
16256feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_40G)
16266feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
16276feac2e3SRahul Lakkireddy 		else
16286feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16296feac2e3SRahul Lakkireddy 		break;
16306feac2e3SRahul Lakkireddy 
16316feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_25GFDX_CAP:
16326feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_25G)
16336feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
16346feac2e3SRahul Lakkireddy 		else
16356feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16366feac2e3SRahul Lakkireddy 		break;
16376feac2e3SRahul Lakkireddy 
163856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
16396feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_10G)
164056b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
164156b2bdd1SGireesh Nagabhushana 		else
164256b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
164356b2bdd1SGireesh Nagabhushana 		break;
164456b2bdd1SGireesh Nagabhushana 
164556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
16466feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_1G)
164756b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
164856b2bdd1SGireesh Nagabhushana 		else
164956b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
165056b2bdd1SGireesh Nagabhushana 		break;
165156b2bdd1SGireesh Nagabhushana 
165256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
16536feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_100M)
165456b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
165556b2bdd1SGireesh Nagabhushana 		else
165656b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
165756b2bdd1SGireesh Nagabhushana 		break;
165856b2bdd1SGireesh Nagabhushana 
16596feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_100GFDX_CAP:
16606feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_50GFDX_CAP:
16616feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_40GFDX_CAP:
16626feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_25GFDX_CAP:
166356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
166456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
166556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
166656b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
166756b2bdd1SGireesh Nagabhushana 		break;
166856b2bdd1SGireesh Nagabhushana 
166956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
167056b2bdd1SGireesh Nagabhushana 		propinfo(pi, name, ph);
167156b2bdd1SGireesh Nagabhushana 		break;
167256b2bdd1SGireesh Nagabhushana 
167356b2bdd1SGireesh Nagabhushana 	default:
167456b2bdd1SGireesh Nagabhushana 		break;
167556b2bdd1SGireesh Nagabhushana 	}
167656b2bdd1SGireesh Nagabhushana }
167756b2bdd1SGireesh Nagabhushana 
16787e6ad469SVishal Kulkarni int
begin_synchronized_op(struct port_info * pi,int hold,int waitok)167956b2bdd1SGireesh Nagabhushana begin_synchronized_op(struct port_info *pi, int hold, int waitok)
168056b2bdd1SGireesh Nagabhushana {
168156b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
168256b2bdd1SGireesh Nagabhushana 	int rc = 0;
168356b2bdd1SGireesh Nagabhushana 
168456b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK(sc);
168556b2bdd1SGireesh Nagabhushana 	while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
168656b2bdd1SGireesh Nagabhushana 		if (!waitok) {
168756b2bdd1SGireesh Nagabhushana 			rc = EBUSY;
168856b2bdd1SGireesh Nagabhushana 			goto failed;
168956b2bdd1SGireesh Nagabhushana 		} else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) {
169056b2bdd1SGireesh Nagabhushana 			rc = EINTR;
169156b2bdd1SGireesh Nagabhushana 			goto failed;
169256b2bdd1SGireesh Nagabhushana 		}
169356b2bdd1SGireesh Nagabhushana 	}
169456b2bdd1SGireesh Nagabhushana 	if (IS_DOOMED(pi) != 0) {	/* shouldn't happen on Solaris */
169556b2bdd1SGireesh Nagabhushana 		rc = ENXIO;
169656b2bdd1SGireesh Nagabhushana 		goto failed;
169756b2bdd1SGireesh Nagabhushana 	}
169856b2bdd1SGireesh Nagabhushana 	ASSERT(!IS_BUSY(sc));
169956b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
170056b2bdd1SGireesh Nagabhushana 	SET_BUSY(sc);
170156b2bdd1SGireesh Nagabhushana 
170256b2bdd1SGireesh Nagabhushana 	if (!hold)
170356b2bdd1SGireesh Nagabhushana 		ADAPTER_UNLOCK(sc);
170456b2bdd1SGireesh Nagabhushana 
170556b2bdd1SGireesh Nagabhushana 	return (0);
170656b2bdd1SGireesh Nagabhushana failed:
170756b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
170856b2bdd1SGireesh Nagabhushana 	return (rc);
170956b2bdd1SGireesh Nagabhushana }
171056b2bdd1SGireesh Nagabhushana 
17117e6ad469SVishal Kulkarni void
end_synchronized_op(struct port_info * pi,int held)171256b2bdd1SGireesh Nagabhushana end_synchronized_op(struct port_info *pi, int held)
171356b2bdd1SGireesh Nagabhushana {
171456b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
171556b2bdd1SGireesh Nagabhushana 
171656b2bdd1SGireesh Nagabhushana 	if (!held)
171756b2bdd1SGireesh Nagabhushana 		ADAPTER_LOCK(sc);
171856b2bdd1SGireesh Nagabhushana 
171956b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_OWNED(sc);
172056b2bdd1SGireesh Nagabhushana 	ASSERT(IS_BUSY(sc));
172156b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
172256b2bdd1SGireesh Nagabhushana 	CLR_BUSY(sc);
172356b2bdd1SGireesh Nagabhushana 	cv_signal(&sc->cv);
172456b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
172556b2bdd1SGireesh Nagabhushana }
172656b2bdd1SGireesh Nagabhushana 
172756b2bdd1SGireesh Nagabhushana static int
t4_init_synchronized(struct port_info * pi)172856b2bdd1SGireesh Nagabhushana t4_init_synchronized(struct port_info *pi)
172956b2bdd1SGireesh Nagabhushana {
173056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
173156b2bdd1SGireesh Nagabhushana 	int rc = 0;
173256b2bdd1SGireesh Nagabhushana 
173356b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
173456b2bdd1SGireesh Nagabhushana 
173556b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0)
173656b2bdd1SGireesh Nagabhushana 		return (0);	/* already running */
173756b2bdd1SGireesh Nagabhushana 
173856b2bdd1SGireesh Nagabhushana 	if (!(sc->flags & FULL_INIT_DONE) &&
173956b2bdd1SGireesh Nagabhushana 	    ((rc = adapter_full_init(sc)) != 0))
174056b2bdd1SGireesh Nagabhushana 		return (rc);	/* error message displayed already */
174156b2bdd1SGireesh Nagabhushana 
174256b2bdd1SGireesh Nagabhushana 	if (!(pi->flags & PORT_INIT_DONE)) {
174356b2bdd1SGireesh Nagabhushana 		rc = port_full_init(pi);
174456b2bdd1SGireesh Nagabhushana 		if (rc != 0)
174556b2bdd1SGireesh Nagabhushana 			return (rc); /* error message displayed already */
174656b2bdd1SGireesh Nagabhushana 	} else
174756b2bdd1SGireesh Nagabhushana 		enable_port_queues(pi);
174856b2bdd1SGireesh Nagabhushana 
174956b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false);
175056b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
175156b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc);
175256b2bdd1SGireesh Nagabhushana 		goto done;
175356b2bdd1SGireesh Nagabhushana 	}
175456b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt,
17557e6ad469SVishal Kulkarni 	    pi->hw_addr, true, &pi->smt_idx);
175656b2bdd1SGireesh Nagabhushana 	if (rc < 0) {
175756b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc);
175856b2bdd1SGireesh Nagabhushana 		rc = -rc;
175956b2bdd1SGireesh Nagabhushana 		goto done;
176056b2bdd1SGireesh Nagabhushana 	} else
176156b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
176256b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
176356b2bdd1SGireesh Nagabhushana 
17646feac2e3SRahul Lakkireddy 	rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg,
17656feac2e3SRahul Lakkireddy 			    pi->link_cfg.admin_caps);
176656b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
176756b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc);
176856b2bdd1SGireesh Nagabhushana 		goto done;
176956b2bdd1SGireesh Nagabhushana 	}
177056b2bdd1SGireesh Nagabhushana 
177156b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true);
177256b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
177356b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc);
177456b2bdd1SGireesh Nagabhushana 		goto done;
177556b2bdd1SGireesh Nagabhushana 	}
177656b2bdd1SGireesh Nagabhushana 
177756b2bdd1SGireesh Nagabhushana 	/* all ok */
177856b2bdd1SGireesh Nagabhushana 	setbit(&sc->open_device_map, pi->port_id);
177956b2bdd1SGireesh Nagabhushana done:
178056b2bdd1SGireesh Nagabhushana 	if (rc != 0)
178156b2bdd1SGireesh Nagabhushana 		(void) t4_uninit_synchronized(pi);
178256b2bdd1SGireesh Nagabhushana 
178356b2bdd1SGireesh Nagabhushana 	return (rc);
178456b2bdd1SGireesh Nagabhushana }
178556b2bdd1SGireesh Nagabhushana 
178656b2bdd1SGireesh Nagabhushana /*
178756b2bdd1SGireesh Nagabhushana  * Idempotent.
178856b2bdd1SGireesh Nagabhushana  */
178956b2bdd1SGireesh Nagabhushana static int
t4_uninit_synchronized(struct port_info * pi)179056b2bdd1SGireesh Nagabhushana t4_uninit_synchronized(struct port_info *pi)
179156b2bdd1SGireesh Nagabhushana {
179256b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
179356b2bdd1SGireesh Nagabhushana 	int rc;
179456b2bdd1SGireesh Nagabhushana 
179556b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
179656b2bdd1SGireesh Nagabhushana 
179756b2bdd1SGireesh Nagabhushana 	/*
179856b2bdd1SGireesh Nagabhushana 	 * Disable the VI so that all its data in either direction is discarded
179956b2bdd1SGireesh Nagabhushana 	 * by the MPS.  Leave everything else (the queues, interrupts, and 1Hz
180056b2bdd1SGireesh Nagabhushana 	 * tick) intact as the TP can deliver negative advice or data that it's
180156b2bdd1SGireesh Nagabhushana 	 * holding in its RAM (for an offloaded connection) even after the VI is
180256b2bdd1SGireesh Nagabhushana 	 * disabled.
180356b2bdd1SGireesh Nagabhushana 	 */
180456b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false);
180556b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
180656b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc);
180756b2bdd1SGireesh Nagabhushana 		return (rc);
180856b2bdd1SGireesh Nagabhushana 	}
180956b2bdd1SGireesh Nagabhushana 
181056b2bdd1SGireesh Nagabhushana 	disable_port_queues(pi);
181156b2bdd1SGireesh Nagabhushana 
181256b2bdd1SGireesh Nagabhushana 	clrbit(&sc->open_device_map, pi->port_id);
181356b2bdd1SGireesh Nagabhushana 
181456b2bdd1SGireesh Nagabhushana 	pi->link_cfg.link_ok = 0;
181556b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, LINK_STATE_UNKNOWN);
181656b2bdd1SGireesh Nagabhushana 
181756b2bdd1SGireesh Nagabhushana 	return (0);
181856b2bdd1SGireesh Nagabhushana }
181956b2bdd1SGireesh Nagabhushana 
182056b2bdd1SGireesh Nagabhushana static void
propinfo(struct port_info * pi,const char * name,mac_prop_info_handle_t ph)182156b2bdd1SGireesh Nagabhushana propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph)
182256b2bdd1SGireesh Nagabhushana {
182356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
182456b2bdd1SGireesh Nagabhushana 	struct driver_properties *p = &sc->props;
182556b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
182656b2bdd1SGireesh Nagabhushana 	int v;
182756b2bdd1SGireesh Nagabhushana 	char str[16];
182856b2bdd1SGireesh Nagabhushana 
182956b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
183056b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g;
183156b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
183256b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g;
183356b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
183456b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
183556b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
183656b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
183756b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
18386feac2e3SRahul Lakkireddy 		v = (lc->pcaps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
183956b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
18406feac2e3SRahul Lakkireddy 		v = (lc->pcaps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
184156b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
184256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
184356b2bdd1SGireesh Nagabhushana 		v = ETHERMTU;
184456b2bdd1SGireesh Nagabhushana #endif
184556b2bdd1SGireesh Nagabhushana 	else
184656b2bdd1SGireesh Nagabhushana 		return;
184756b2bdd1SGireesh Nagabhushana 
184856b2bdd1SGireesh Nagabhushana 	(void) snprintf(str, sizeof (str), "%d", v);
184956b2bdd1SGireesh Nagabhushana 	mac_prop_info_set_default_str(ph, str);
185056b2bdd1SGireesh Nagabhushana }
185156b2bdd1SGireesh Nagabhushana 
185256b2bdd1SGireesh Nagabhushana static int
getprop(struct port_info * pi,const char * name,uint_t size,void * val)185356b2bdd1SGireesh Nagabhushana getprop(struct port_info *pi, const char *name, uint_t size, void *val)
185456b2bdd1SGireesh Nagabhushana {
185556b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
185656b2bdd1SGireesh Nagabhushana 	int v;
185756b2bdd1SGireesh Nagabhushana 
185856b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
185956b2bdd1SGireesh Nagabhushana 		v = pi->tmr_idx;
186056b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
186156b2bdd1SGireesh Nagabhushana 		v = pi->pktc_idx;
186256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
186356b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
186456b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
186556b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
186656b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
18676feac2e3SRahul Lakkireddy 		v = (lc->link_caps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
186856b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
18696feac2e3SRahul Lakkireddy 		v = (lc->link_caps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
187056b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
187156b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
187256b2bdd1SGireesh Nagabhushana 		v = pi->mtu;
187356b2bdd1SGireesh Nagabhushana #endif
187456b2bdd1SGireesh Nagabhushana 	else
187556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
187656b2bdd1SGireesh Nagabhushana 
187756b2bdd1SGireesh Nagabhushana 	(void) snprintf(val, size, "%d", v);
187856b2bdd1SGireesh Nagabhushana 	return (0);
187956b2bdd1SGireesh Nagabhushana }
188056b2bdd1SGireesh Nagabhushana 
188156b2bdd1SGireesh Nagabhushana static int
setprop(struct port_info * pi,const char * name,const void * val)188256b2bdd1SGireesh Nagabhushana setprop(struct port_info *pi, const char *name, const void *val)
188356b2bdd1SGireesh Nagabhushana {
18846feac2e3SRahul Lakkireddy 	struct link_config *lc = &pi->link_cfg;
18856feac2e3SRahul Lakkireddy 	fw_port_cap32_t new_caps = lc->admin_caps;
188656b2bdd1SGireesh Nagabhushana 	int i, rc = 0, relink = 0, rx_mode = 0;
18876feac2e3SRahul Lakkireddy 	struct adapter *sc = pi->adapter;
188856b2bdd1SGireesh Nagabhushana 	struct sge_rxq *rxq;
18896feac2e3SRahul Lakkireddy 	cc_pause_t fc = 0;
18906feac2e3SRahul Lakkireddy 	long v;
189156b2bdd1SGireesh Nagabhushana 
189256b2bdd1SGireesh Nagabhushana 	(void) ddi_strtol(val, NULL, 0, &v);
189356b2bdd1SGireesh Nagabhushana 
189456b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0) {
189556b2bdd1SGireesh Nagabhushana 		if (v < 0 || v >= SGE_NTIMERS)
189656b2bdd1SGireesh Nagabhushana 			return (EINVAL);
189756b2bdd1SGireesh Nagabhushana 		if (v == pi->tmr_idx)
189856b2bdd1SGireesh Nagabhushana 			return (0);
189956b2bdd1SGireesh Nagabhushana 
190056b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
190156b2bdd1SGireesh Nagabhushana 		pi->tmr_idx = v;
190256b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
190356b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) |
190456b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(pi->pktc_idx >= 0);
190556b2bdd1SGireesh Nagabhushana 		}
190656b2bdd1SGireesh Nagabhushana 
190756b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_PKTC_IDX) == 0) {
190856b2bdd1SGireesh Nagabhushana 		if (v >= SGE_NCOUNTERS)
190956b2bdd1SGireesh Nagabhushana 			return (EINVAL);
191056b2bdd1SGireesh Nagabhushana 		if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1))
191156b2bdd1SGireesh Nagabhushana 			return (0);
191256b2bdd1SGireesh Nagabhushana 
191356b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
191456b2bdd1SGireesh Nagabhushana 		pi->pktc_idx = v < 0 ? -1 : v;
191556b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
191656b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) |
191756b2bdd1SGireesh Nagabhushana 			    /* takes effect right away */
191856b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(v >= 0);
191956b2bdd1SGireesh Nagabhushana 			/* LINTED: E_ASSIGN_NARROW_CONV */
192056b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */
192156b2bdd1SGireesh Nagabhushana 		}
192256b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_CSUM) == 0) {
192356b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
192456b2bdd1SGireesh Nagabhushana 			return (EINVAL);
192556b2bdd1SGireesh Nagabhushana 		if (v == 1)
192656b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_CSUM;
192756b2bdd1SGireesh Nagabhushana 		else
192856b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_CSUM;
192956b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_LSO) == 0) {
193056b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
193156b2bdd1SGireesh Nagabhushana 			return (EINVAL);
193256b2bdd1SGireesh Nagabhushana 		if (v == 1)
193356b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_LSO;
193456b2bdd1SGireesh Nagabhushana 		else
193556b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_LSO;
193656b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_TX_PAUSE) == 0) {
193756b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
193856b2bdd1SGireesh Nagabhushana 			return (EINVAL);
193956b2bdd1SGireesh Nagabhushana 
19406feac2e3SRahul Lakkireddy 		if ((new_caps & FW_PORT_CAP32_FC_TX) && (v == 1))
19416feac2e3SRahul Lakkireddy 			fc |= PAUSE_TX;
19426feac2e3SRahul Lakkireddy 		if (new_caps & FW_PORT_CAP32_FC_RX)
19436feac2e3SRahul Lakkireddy 			fc |= PAUSE_RX;
19446feac2e3SRahul Lakkireddy 		if (lc->admin_caps & FW_PORT_CAP32_ANEG)
19456feac2e3SRahul Lakkireddy 			fc |= PAUSE_AUTONEG;
194656b2bdd1SGireesh Nagabhushana 
19476feac2e3SRahul Lakkireddy 		t4_link_set_pause(pi, fc, &new_caps);
194856b2bdd1SGireesh Nagabhushana 		relink = 1;
194956b2bdd1SGireesh Nagabhushana 
195056b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_RX_PAUSE) == 0) {
195156b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
195256b2bdd1SGireesh Nagabhushana 			return (EINVAL);
195356b2bdd1SGireesh Nagabhushana 
19546feac2e3SRahul Lakkireddy 		if (new_caps & FW_PORT_CAP32_FC_TX)
19556feac2e3SRahul Lakkireddy 			fc |= PAUSE_TX;
19566feac2e3SRahul Lakkireddy 		if ((new_caps & FW_PORT_CAP32_FC_RX) && (v == 1))
19576feac2e3SRahul Lakkireddy 			fc |= PAUSE_RX;
19586feac2e3SRahul Lakkireddy 		if (lc->admin_caps & FW_PORT_CAP32_ANEG)
19596feac2e3SRahul Lakkireddy 			fc |= PAUSE_AUTONEG;
196056b2bdd1SGireesh Nagabhushana 
19616feac2e3SRahul Lakkireddy 		t4_link_set_pause(pi, fc, &new_caps);
196256b2bdd1SGireesh Nagabhushana 		relink = 1;
196356b2bdd1SGireesh Nagabhushana 	}
196456b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
196556b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0) {
196656b2bdd1SGireesh Nagabhushana 		if (v < 46 || v > MAX_MTU)
196756b2bdd1SGireesh Nagabhushana 			return (EINVAL);
196856b2bdd1SGireesh Nagabhushana 		if (v == pi->mtu)
196956b2bdd1SGireesh Nagabhushana 			return (0);
197056b2bdd1SGireesh Nagabhushana 
197156b2bdd1SGireesh Nagabhushana 		pi->mtu = (int)v;
197256b2bdd1SGireesh Nagabhushana 		(void) mac_maxsdu_update(pi->mh, v);
197356b2bdd1SGireesh Nagabhushana 		rx_mode = 1;
197456b2bdd1SGireesh Nagabhushana 	}
197556b2bdd1SGireesh Nagabhushana #endif
197656b2bdd1SGireesh Nagabhushana 	else
197756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
197856b2bdd1SGireesh Nagabhushana 
197956b2bdd1SGireesh Nagabhushana 	if (!(relink || rx_mode))
198056b2bdd1SGireesh Nagabhushana 		return (0);
198156b2bdd1SGireesh Nagabhushana 
198256b2bdd1SGireesh Nagabhushana 	/* If we are here, either relink or rx_mode is 1 */
198356b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
198456b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
198556b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
198656b2bdd1SGireesh Nagabhushana 			if (rc != 0)
198756b2bdd1SGireesh Nagabhushana 				return (rc);
19886feac2e3SRahul Lakkireddy 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
19896feac2e3SRahul Lakkireddy 					    new_caps);
199056b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
199156b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
199256b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
19936feac2e3SRahul Lakkireddy 					    "%s link config failed: %d",
19946feac2e3SRahul Lakkireddy 					    __func__, rc);
19956feac2e3SRahul Lakkireddy 				return (rc);
199656b2bdd1SGireesh Nagabhushana 			}
199756b2bdd1SGireesh Nagabhushana 		} else if (rx_mode != 0) {
199856b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
199956b2bdd1SGireesh Nagabhushana 			if (rc != 0)
200056b2bdd1SGireesh Nagabhushana 				return (rc);
200156b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1,
200256b2bdd1SGireesh Nagabhushana 			    -1, -1, false);
200356b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
200456b2bdd1SGireesh Nagabhushana 			if (rc != 0)  {
200556b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
20066feac2e3SRahul Lakkireddy 					    "set_rxmode failed: %d", rc);
20076feac2e3SRahul Lakkireddy 				return (rc);
200856b2bdd1SGireesh Nagabhushana 			}
200956b2bdd1SGireesh Nagabhushana 		}
201056b2bdd1SGireesh Nagabhushana 	}
201156b2bdd1SGireesh Nagabhushana 
20126feac2e3SRahul Lakkireddy 	if (relink != 0)
20136feac2e3SRahul Lakkireddy 		lc->admin_caps = new_caps;
20146feac2e3SRahul Lakkireddy 
201556b2bdd1SGireesh Nagabhushana 	return (0);
201656b2bdd1SGireesh Nagabhushana }
201756b2bdd1SGireesh Nagabhushana 
201856b2bdd1SGireesh Nagabhushana void
t4_mc_init(struct port_info * pi)201956b2bdd1SGireesh Nagabhushana t4_mc_init(struct port_info *pi)
202056b2bdd1SGireesh Nagabhushana {
202156b2bdd1SGireesh Nagabhushana 	pi->props = t4_priv_props;
202256b2bdd1SGireesh Nagabhushana }
202356b2bdd1SGireesh Nagabhushana 
20243dde7c95SVishal Kulkarni void
t4_mc_cb_init(struct port_info * pi)20253dde7c95SVishal Kulkarni t4_mc_cb_init(struct port_info *pi)
20263dde7c95SVishal Kulkarni {
20273dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
20283dde7c95SVishal Kulkarni 		pi->mc = &t4_m_ring_callbacks;
20293dde7c95SVishal Kulkarni 	else
20303dde7c95SVishal Kulkarni 		pi->mc = &t4_m_callbacks;
20313dde7c95SVishal Kulkarni }
20323dde7c95SVishal Kulkarni 
203356b2bdd1SGireesh Nagabhushana void
t4_os_link_changed(struct adapter * sc,int idx,int link_stat)203456b2bdd1SGireesh Nagabhushana t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
203556b2bdd1SGireesh Nagabhushana {
203656b2bdd1SGireesh Nagabhushana 	struct port_info *pi = sc->port[idx];
203756b2bdd1SGireesh Nagabhushana 
203856b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN);
203956b2bdd1SGireesh Nagabhushana }
204056b2bdd1SGireesh Nagabhushana 
204156b2bdd1SGireesh Nagabhushana /* ARGSUSED */
204256b2bdd1SGireesh Nagabhushana void
t4_mac_rx(struct port_info * pi,struct sge_rxq * rxq,mblk_t * m)204356b2bdd1SGireesh Nagabhushana t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m)
204456b2bdd1SGireesh Nagabhushana {
204556b2bdd1SGireesh Nagabhushana 	mac_rx(pi->mh, NULL, m);
204656b2bdd1SGireesh Nagabhushana }
20473dde7c95SVishal Kulkarni 
20483dde7c95SVishal Kulkarni void
t4_mac_tx_update(struct port_info * pi,struct sge_txq * txq)20493dde7c95SVishal Kulkarni t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq)
20503dde7c95SVishal Kulkarni {
20513dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
20523dde7c95SVishal Kulkarni 		mac_tx_ring_update(pi->mh, txq->ring_handle);
20533dde7c95SVishal Kulkarni 	else
20543dde7c95SVishal Kulkarni 		mac_tx_update(pi->mh);
20553dde7c95SVishal Kulkarni }
2056