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.
25d75c6062SRobert Mustacchi  * Copyright 2021 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 
11756b2bdd1SGireesh Nagabhushana static int
11856b2bdd1SGireesh Nagabhushana t4_mc_getstat(void *arg, uint_t stat, uint64_t *val)
11956b2bdd1SGireesh Nagabhushana {
12056b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
12156b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
12256b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
12356b2bdd1SGireesh Nagabhushana 
12456b2bdd1SGireesh Nagabhushana #define	GET_STAT(name) \
12556b2bdd1SGireesh Nagabhushana 	t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
12656b2bdd1SGireesh Nagabhushana 
12756b2bdd1SGireesh Nagabhushana 	switch (stat) {
12856b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IFSPEED:
12956b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
130*6feac2e3SRahul Lakkireddy 			*val = t4_link_fwcap_to_speed(lc->link_caps);
13156b2bdd1SGireesh Nagabhushana 			*val *= 1000000;
13256b2bdd1SGireesh Nagabhushana 		} else
13356b2bdd1SGireesh Nagabhushana 			*val = 0;
13456b2bdd1SGireesh Nagabhushana 		break;
13556b2bdd1SGireesh Nagabhushana 
13656b2bdd1SGireesh Nagabhushana 	case MAC_STAT_MULTIRCV:
13756b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MCAST);
13856b2bdd1SGireesh Nagabhushana 		break;
13956b2bdd1SGireesh Nagabhushana 
14056b2bdd1SGireesh Nagabhushana 	case MAC_STAT_BRDCSTRCV:
14156b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_BCAST);
14256b2bdd1SGireesh Nagabhushana 		break;
14356b2bdd1SGireesh Nagabhushana 
14456b2bdd1SGireesh Nagabhushana 	case MAC_STAT_MULTIXMT:
14556b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_MCAST);
14656b2bdd1SGireesh Nagabhushana 		break;
14756b2bdd1SGireesh Nagabhushana 
14856b2bdd1SGireesh Nagabhushana 	case MAC_STAT_BRDCSTXMT:
14956b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_BCAST);
15056b2bdd1SGireesh Nagabhushana 		break;
15156b2bdd1SGireesh Nagabhushana 
15256b2bdd1SGireesh Nagabhushana 	case MAC_STAT_NORCVBUF:
15356b2bdd1SGireesh Nagabhushana 		*val = 0;	/* TODO should come from rxq->nomem */
15456b2bdd1SGireesh Nagabhushana 		break;
15556b2bdd1SGireesh Nagabhushana 
15656b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IERRORS:
15756b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR) +
15856b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_MTU_CRC_ERROR) +
15956b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_CRC_ERROR) +
16056b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LEN_ERROR) +
16156b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_SYM_ERROR) +
16256b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LESS_64B);
16356b2bdd1SGireesh Nagabhushana 		break;
16456b2bdd1SGireesh Nagabhushana 
16556b2bdd1SGireesh Nagabhushana 	case MAC_STAT_UNKNOWNS:
16656b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
16756b2bdd1SGireesh Nagabhushana 
16856b2bdd1SGireesh Nagabhushana 	case MAC_STAT_NOXMTBUF:
16956b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_DROP);
17056b2bdd1SGireesh Nagabhushana 		break;
17156b2bdd1SGireesh Nagabhushana 
17256b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OERRORS:
17356b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_ERROR);
17456b2bdd1SGireesh Nagabhushana 		break;
17556b2bdd1SGireesh Nagabhushana 
17656b2bdd1SGireesh Nagabhushana 	case MAC_STAT_COLLISIONS:
17756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
17856b2bdd1SGireesh Nagabhushana 
17956b2bdd1SGireesh Nagabhushana 	case MAC_STAT_RBYTES:
18056b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_BYTES);
18156b2bdd1SGireesh Nagabhushana 		break;
18256b2bdd1SGireesh Nagabhushana 
18356b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IPACKETS:
18456b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_FRAMES);
18556b2bdd1SGireesh Nagabhushana 		break;
18656b2bdd1SGireesh Nagabhushana 
18756b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OBYTES:
18856b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_BYTES);
18956b2bdd1SGireesh Nagabhushana 		break;
19056b2bdd1SGireesh Nagabhushana 
19156b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OPACKETS:
19256b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_FRAMES);
19356b2bdd1SGireesh Nagabhushana 		break;
19456b2bdd1SGireesh Nagabhushana 
19556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ALIGN_ERRORS:
19656b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
19756b2bdd1SGireesh Nagabhushana 
19856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_FCS_ERRORS:
19956b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_CRC_ERROR);
20056b2bdd1SGireesh Nagabhushana 		break;
20156b2bdd1SGireesh Nagabhushana 
20256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_FIRST_COLLISIONS:
20356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MULTI_COLLISIONS:
20456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_SQE_ERRORS:
20556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_DEFER_XMTS:
20656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_TX_LATE_COLLISIONS:
20756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_EX_COLLISIONS:
20856b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
20956b2bdd1SGireesh Nagabhushana 
21056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MACXMT_ERRORS:
21156b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_ERROR);
21256b2bdd1SGireesh Nagabhushana 		break;
21356b2bdd1SGireesh Nagabhushana 
21456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CARRIER_ERRORS:
21556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
21656b2bdd1SGireesh Nagabhushana 
21756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_TOOLONG_ERRORS:
21856b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR);
21956b2bdd1SGireesh Nagabhushana 		break;
22056b2bdd1SGireesh Nagabhushana 
22156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MACRCV_ERRORS:
22256b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR) +
22356b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_MTU_CRC_ERROR) +
22456b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_CRC_ERROR) +
22556b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LEN_ERROR) +
22656b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_SYM_ERROR) +
22756b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LESS_64B);
22856b2bdd1SGireesh Nagabhushana 		break;
22956b2bdd1SGireesh Nagabhushana 
23056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_ADDR:
23156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_ID:
23256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_INUSE:
23356b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
23456b2bdd1SGireesh Nagabhushana 
2353dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_100GFDX:
2367e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G);
2373dde7c95SVishal Kulkarni 		break;
2383dde7c95SVishal Kulkarni 
239*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_CAP_50GFDX:
240*6feac2e3SRahul Lakkireddy 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_50G);
241*6feac2e3SRahul Lakkireddy 		break;
242*6feac2e3SRahul Lakkireddy 
2433dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_40GFDX:
2447e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
2453dde7c95SVishal Kulkarni 		break;
2463dde7c95SVishal Kulkarni 
2473dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_25GFDX:
2487e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
2493dde7c95SVishal Kulkarni 		break;
2503dde7c95SVishal Kulkarni 
2513dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_10GFDX:
2527e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
2533dde7c95SVishal Kulkarni 		break;
2543dde7c95SVishal Kulkarni 
25556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_1000FDX:
2567e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
25756b2bdd1SGireesh Nagabhushana 		break;
25856b2bdd1SGireesh Nagabhushana 
25956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100FDX:
2607e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
26156b2bdd1SGireesh Nagabhushana 		break;
26256b2bdd1SGireesh Nagabhushana 
263*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_CAP_1000HDX:
26456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100HDX:
26556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_10FDX:
26656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_10HDX:
26756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
26856b2bdd1SGireesh Nagabhushana 
26956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_ASMPAUSE:
270*6feac2e3SRahul Lakkireddy 		*val = !!(lc->pcaps & FW_PORT_CAP32_FC_RX);
27156b2bdd1SGireesh Nagabhushana 		break;
27256b2bdd1SGireesh Nagabhushana 
27356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_PAUSE:
274*6feac2e3SRahul Lakkireddy 		*val = !!(lc->pcaps & FW_PORT_CAP32_FC_TX);
27556b2bdd1SGireesh Nagabhushana 		break;
27656b2bdd1SGireesh Nagabhushana 
27756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_AUTONEG:
2787e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_ANEG);
27956b2bdd1SGireesh Nagabhushana 		break;
28056b2bdd1SGireesh Nagabhushana 
28156b2bdd1SGireesh Nagabhushana 	/*
28256b2bdd1SGireesh Nagabhushana 	 * We have set flow control configuration based on tx_pause and rx_pause
28356b2bdd1SGireesh Nagabhushana 	 * values supported through ndd. Now, we need to translate the settings
28456b2bdd1SGireesh Nagabhushana 	 * we have in link_config structure to adv_cap_asmpause and
28556b2bdd1SGireesh Nagabhushana 	 * adv_cap_pause.
28656b2bdd1SGireesh Nagabhushana 	 *
28756b2bdd1SGireesh Nagabhushana 	 * There are 4 combinations possible and the translation is as below:
28856b2bdd1SGireesh Nagabhushana 	 * tx_pause = 0 => We don't send pause frames during Rx congestion
28956b2bdd1SGireesh Nagabhushana 	 * tx_pause = 1 => We send pause frames during Rx congestion
29056b2bdd1SGireesh Nagabhushana 	 * rx_pause = 0 => We ignore received pause frames
29156b2bdd1SGireesh Nagabhushana 	 * rx_pause = 1 => We pause transmission when we receive pause frames
29256b2bdd1SGireesh Nagabhushana 	 *
29356b2bdd1SGireesh Nagabhushana 	 * +----------------------------+----------------------------------+
29456b2bdd1SGireesh Nagabhushana 	 * |  tx_pause	|    rx_pause	| adv_cap_asmpause | adv_cap_pause |
29556b2bdd1SGireesh Nagabhushana 	 * +-------------------------+-------------------------------------+
29656b2bdd1SGireesh Nagabhushana 	 * |	0	|	0	|	0	   |	0	   |
29756b2bdd1SGireesh Nagabhushana 	 * |	0	|	1	|	1	   |	0	   |
29856b2bdd1SGireesh Nagabhushana 	 * |	1	|	0	|	1	   |	1	   |
29956b2bdd1SGireesh Nagabhushana 	 * |	1	|	1	|	0	   |	1	   |
30056b2bdd1SGireesh Nagabhushana 	 * +----------------------------+----------------------------------+
30156b2bdd1SGireesh Nagabhushana 	 */
30256b2bdd1SGireesh Nagabhushana 
30356b2bdd1SGireesh Nagabhushana 	/* Advertised asymmetric pause capability */
30456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
305*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
306*6feac2e3SRahul Lakkireddy 			*val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_ASM_DIR);
307*6feac2e3SRahul Lakkireddy 		else
308*6feac2e3SRahul Lakkireddy 			*val = (!!(lc->admin_caps & FW_PORT_CAP32_FC_TX)) ^
309*6feac2e3SRahul Lakkireddy 			       (!!(lc->admin_caps & FW_PORT_CAP32_FC_RX));
31056b2bdd1SGireesh Nagabhushana 		break;
31156b2bdd1SGireesh Nagabhushana 
31256b2bdd1SGireesh Nagabhushana 	/* Advertised pause capability */
31356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_PAUSE:
314*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
315*6feac2e3SRahul Lakkireddy 			*val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_PAUSE);
316*6feac2e3SRahul Lakkireddy 		else
317*6feac2e3SRahul Lakkireddy 			*val = !!(lc->admin_caps & FW_PORT_CAP32_FC_TX);
31856b2bdd1SGireesh Nagabhushana 		break;
31956b2bdd1SGireesh Nagabhushana 
3203dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_100GFDX:
321*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
322*6feac2e3SRahul Lakkireddy 		break;
323*6feac2e3SRahul Lakkireddy 
324*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_ADV_CAP_50GFDX:
325*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
3263dde7c95SVishal Kulkarni 		break;
3273dde7c95SVishal Kulkarni 
3283dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_40GFDX:
329*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
3303dde7c95SVishal Kulkarni 		break;
3313dde7c95SVishal Kulkarni 
3323dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_25GFDX:
333*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
3343dde7c95SVishal Kulkarni 		break;
3353dde7c95SVishal Kulkarni 
3363dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_10GFDX:
337*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
3383dde7c95SVishal Kulkarni 		break;
3393dde7c95SVishal Kulkarni 
34056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000FDX:
341*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
342*6feac2e3SRahul Lakkireddy 		break;
343*6feac2e3SRahul Lakkireddy 
344*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_ADV_CAP_100FDX:
345*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
3463dde7c95SVishal Kulkarni 		break;
3473dde7c95SVishal Kulkarni 
3483dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_AUTONEG:
349*6feac2e3SRahul Lakkireddy 		*val = !!(lc->admin_caps & FW_PORT_CAP32_ANEG);
3503dde7c95SVishal Kulkarni 		break;
3513dde7c95SVishal Kulkarni 
35256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000HDX:
35356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_100HDX:
35456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10FDX:
35556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10HDX:
35656b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);	/* TODO */
35756b2bdd1SGireesh Nagabhushana 
358*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_ASMPAUSE:
359*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
360*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
361*6feac2e3SRahul Lakkireddy 
362*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
363*6feac2e3SRahul Lakkireddy 			*val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_ASM_DIR);
364*6feac2e3SRahul Lakkireddy 		else
365*6feac2e3SRahul Lakkireddy 			*val = (!!(lc->lpacaps & FW_PORT_CAP32_FC_TX)) ^
366*6feac2e3SRahul Lakkireddy 			       (!!(lc->lpacaps & FW_PORT_CAP32_FC_RX));
367*6feac2e3SRahul Lakkireddy 		break;
368*6feac2e3SRahul Lakkireddy 
369*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_PAUSE:
370*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
371*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
372*6feac2e3SRahul Lakkireddy 
373*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
374*6feac2e3SRahul Lakkireddy 			*val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_PAUSE);
375*6feac2e3SRahul Lakkireddy 		else
376*6feac2e3SRahul Lakkireddy 			*val = !!(lc->lpacaps & FW_PORT_CAP32_FC_TX);
377*6feac2e3SRahul Lakkireddy 		break;
3783dde7c95SVishal Kulkarni 
3793dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_100GFDX:
380*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
381*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
382*6feac2e3SRahul Lakkireddy 
383*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100G);
384*6feac2e3SRahul Lakkireddy 		break;
385*6feac2e3SRahul Lakkireddy 
386*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_50GFDX:
387*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
388*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
389*6feac2e3SRahul Lakkireddy 
390*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_50G);
3913dde7c95SVishal Kulkarni 		break;
3923dde7c95SVishal Kulkarni 
3933dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_40GFDX:
394*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
395*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
396*6feac2e3SRahul Lakkireddy 
397*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_40G);
3983dde7c95SVishal Kulkarni 		break;
3993dde7c95SVishal Kulkarni 
4003dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_25GFDX:
401*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
402*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
403*6feac2e3SRahul Lakkireddy 
404*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_25G);
4053dde7c95SVishal Kulkarni 		break;
4063dde7c95SVishal Kulkarni 
4073dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_10GFDX:
408*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
409*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
410*6feac2e3SRahul Lakkireddy 
411*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_10G);
4123dde7c95SVishal Kulkarni 		break;
4133dde7c95SVishal Kulkarni 
41456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000FDX:
415*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
416*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
417*6feac2e3SRahul Lakkireddy 
418*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_1G);
419*6feac2e3SRahul Lakkireddy 		break;
420*6feac2e3SRahul Lakkireddy 
421*6feac2e3SRahul Lakkireddy 	case ETHER_STAT_LP_CAP_100FDX:
422*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
423*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
424*6feac2e3SRahul Lakkireddy 
425*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100M);
4263dde7c95SVishal Kulkarni 		break;
4273dde7c95SVishal Kulkarni 
4283dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_AUTONEG:
429*6feac2e3SRahul Lakkireddy 		if (!(lc->acaps & FW_PORT_CAP32_ANEG))
430*6feac2e3SRahul Lakkireddy 			return (ENOTSUP);
431*6feac2e3SRahul Lakkireddy 
432*6feac2e3SRahul Lakkireddy 		*val = !!(lc->lpacaps & FW_PORT_CAP32_ANEG);
4333dde7c95SVishal Kulkarni 		break;
4343dde7c95SVishal Kulkarni 
43556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000HDX:
43656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_100HDX:
43756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10FDX:
43856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10HDX:
43956b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
44056b2bdd1SGireesh Nagabhushana 
44156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_ASMPAUSE:
442*6feac2e3SRahul Lakkireddy 		*val = (!!(lc->link_caps & FW_PORT_CAP32_FC_TX)) ^
443*6feac2e3SRahul Lakkireddy 		       (!!(lc->link_caps & FW_PORT_CAP32_FC_RX));
44456b2bdd1SGireesh Nagabhushana 		break;
44556b2bdd1SGireesh Nagabhushana 
44656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_PAUSE:
447*6feac2e3SRahul Lakkireddy 		*val = !!(lc->link_caps & FW_PORT_CAP32_FC_TX);
44856b2bdd1SGireesh Nagabhushana 		break;
44956b2bdd1SGireesh Nagabhushana 
45056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_AUTONEG:
451*6feac2e3SRahul Lakkireddy 		*val = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
45256b2bdd1SGireesh Nagabhushana 		break;
45356b2bdd1SGireesh Nagabhushana 
45456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_DUPLEX:
45556b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0)
45656b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_FULL;
45756b2bdd1SGireesh Nagabhushana 		else
45856b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_UNKNOWN;
45956b2bdd1SGireesh Nagabhushana 		break;
46056b2bdd1SGireesh Nagabhushana 
46156b2bdd1SGireesh Nagabhushana 	default:
46256b2bdd1SGireesh Nagabhushana #ifdef DEBUG
46356b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE, "stat %d not implemented.", stat);
46456b2bdd1SGireesh Nagabhushana #endif
46556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
46656b2bdd1SGireesh Nagabhushana 	}
46756b2bdd1SGireesh Nagabhushana #undef GET_STAT
46856b2bdd1SGireesh Nagabhushana 
46956b2bdd1SGireesh Nagabhushana 	return (0);
47056b2bdd1SGireesh Nagabhushana }
47156b2bdd1SGireesh Nagabhushana 
47256b2bdd1SGireesh Nagabhushana static int
47356b2bdd1SGireesh Nagabhushana t4_mc_start(void *arg)
47456b2bdd1SGireesh Nagabhushana {
47556b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
47656b2bdd1SGireesh Nagabhushana 	int rc;
47756b2bdd1SGireesh Nagabhushana 
47856b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 0, 1);
47956b2bdd1SGireesh Nagabhushana 	if (rc != 0)
48056b2bdd1SGireesh Nagabhushana 		return (rc);
48156b2bdd1SGireesh Nagabhushana 	rc = t4_init_synchronized(pi);
48256b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
48356b2bdd1SGireesh Nagabhushana 
48456b2bdd1SGireesh Nagabhushana 	return (rc);
48556b2bdd1SGireesh Nagabhushana }
48656b2bdd1SGireesh Nagabhushana 
48756b2bdd1SGireesh Nagabhushana static void
48856b2bdd1SGireesh Nagabhushana t4_mc_stop(void *arg)
48956b2bdd1SGireesh Nagabhushana {
49056b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
49156b2bdd1SGireesh Nagabhushana 
49256b2bdd1SGireesh Nagabhushana 	while (begin_synchronized_op(pi, 0, 1) != 0)
49356b2bdd1SGireesh Nagabhushana 		continue;
49456b2bdd1SGireesh Nagabhushana 	(void) t4_uninit_synchronized(pi);
49556b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
49656b2bdd1SGireesh Nagabhushana }
49756b2bdd1SGireesh Nagabhushana 
49856b2bdd1SGireesh Nagabhushana static int
49956b2bdd1SGireesh Nagabhushana t4_mc_setpromisc(void *arg, boolean_t on)
50056b2bdd1SGireesh Nagabhushana {
50156b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
50256b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
50356b2bdd1SGireesh Nagabhushana 	int rc;
50456b2bdd1SGireesh Nagabhushana 
50556b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
50656b2bdd1SGireesh Nagabhushana 	if (rc != 0)
50756b2bdd1SGireesh Nagabhushana 		return (rc);
50856b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
50956b2bdd1SGireesh Nagabhushana 	    false);
51056b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
51156b2bdd1SGireesh Nagabhushana 
51256b2bdd1SGireesh Nagabhushana 	return (rc);
51356b2bdd1SGireesh Nagabhushana }
51456b2bdd1SGireesh Nagabhushana 
51556b2bdd1SGireesh Nagabhushana /*
51656b2bdd1SGireesh Nagabhushana  * TODO: Starts failing as soon as the 336 entry table fills up.  Need to use
51756b2bdd1SGireesh Nagabhushana  * hash in that case.
51856b2bdd1SGireesh Nagabhushana  */
51956b2bdd1SGireesh Nagabhushana static int
52056b2bdd1SGireesh Nagabhushana t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
52156b2bdd1SGireesh Nagabhushana {
52256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
52356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
52456b2bdd1SGireesh Nagabhushana 	struct fw_vi_mac_cmd c;
52556b2bdd1SGireesh Nagabhushana 	int len16, rc;
52656b2bdd1SGireesh Nagabhushana 
52756b2bdd1SGireesh Nagabhushana 	len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
52856b2bdd1SGireesh Nagabhushana 	    sizeof (c.u.exact[0]), 16);
52956b2bdd1SGireesh Nagabhushana 	c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
53056b2bdd1SGireesh Nagabhushana 	    F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
53156b2bdd1SGireesh Nagabhushana 	c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
53256b2bdd1SGireesh Nagabhushana 	c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
53356b2bdd1SGireesh Nagabhushana 	    V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
53456b2bdd1SGireesh Nagabhushana 	    FW_VI_MAC_MAC_BASED_FREE));
53556b2bdd1SGireesh Nagabhushana 	bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
53656b2bdd1SGireesh Nagabhushana 
53756b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
53856b2bdd1SGireesh Nagabhushana 	if (rc != 0)
53956b2bdd1SGireesh Nagabhushana 		return (rc);
54056b2bdd1SGireesh Nagabhushana 	rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
54156b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
54256b2bdd1SGireesh Nagabhushana 	if (rc != 0)
54356b2bdd1SGireesh Nagabhushana 		return (rc);
54456b2bdd1SGireesh Nagabhushana #ifdef DEBUG
54556b2bdd1SGireesh Nagabhushana 	/*
54656b2bdd1SGireesh Nagabhushana 	 * TODO: Firmware doesn't seem to return the correct index on removal
54756b2bdd1SGireesh Nagabhushana 	 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
54856b2bdd1SGireesh Nagabhushana 	 * code once it is fixed.
54956b2bdd1SGireesh Nagabhushana 	 */
55056b2bdd1SGireesh Nagabhushana 	else {
55156b2bdd1SGireesh Nagabhushana 		uint16_t idx;
55256b2bdd1SGireesh Nagabhushana 
55356b2bdd1SGireesh Nagabhushana 		idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
55456b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE,
55556b2bdd1SGireesh Nagabhushana 		    "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
55656b2bdd1SGireesh Nagabhushana 		    mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
55756b2bdd1SGireesh Nagabhushana 		    add ? "added at index" : "removed from index", idx);
55856b2bdd1SGireesh Nagabhushana 	}
55956b2bdd1SGireesh Nagabhushana #endif
56056b2bdd1SGireesh Nagabhushana 
56156b2bdd1SGireesh Nagabhushana 	return (0);
56256b2bdd1SGireesh Nagabhushana }
56356b2bdd1SGireesh Nagabhushana 
5643dde7c95SVishal Kulkarni int
56556b2bdd1SGireesh Nagabhushana t4_mc_unicst(void *arg, const uint8_t *ucaddr)
56656b2bdd1SGireesh Nagabhushana {
56756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
56856b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
56956b2bdd1SGireesh Nagabhushana 	int rc;
57056b2bdd1SGireesh Nagabhushana 
5713dde7c95SVishal Kulkarni 	if (ucaddr == NULL)
5723dde7c95SVishal Kulkarni 		return (EINVAL);
5733dde7c95SVishal Kulkarni 
57456b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
57556b2bdd1SGireesh Nagabhushana 	if (rc != 0)
57656b2bdd1SGireesh Nagabhushana 		return (rc);
5773dde7c95SVishal Kulkarni 
5783dde7c95SVishal Kulkarni 	/* We will support adding only one mac address */
5793dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
5803dde7c95SVishal Kulkarni 		end_synchronized_op(pi, 1);
5813dde7c95SVishal Kulkarni 		return (ENOSPC);
5823dde7c95SVishal Kulkarni 	}
58356b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
5847e6ad469SVishal Kulkarni 			   true, &pi->smt_idx);
58556b2bdd1SGireesh Nagabhushana 	if (rc < 0)
58656b2bdd1SGireesh Nagabhushana 		rc = -rc;
58756b2bdd1SGireesh Nagabhushana 	else {
5883dde7c95SVishal Kulkarni 		pi->macaddr_cnt++;
58956b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
59056b2bdd1SGireesh Nagabhushana 		rc = 0;
59156b2bdd1SGireesh Nagabhushana 	}
59256b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
59356b2bdd1SGireesh Nagabhushana 
59456b2bdd1SGireesh Nagabhushana 	return (rc);
59556b2bdd1SGireesh Nagabhushana }
59656b2bdd1SGireesh Nagabhushana 
5973dde7c95SVishal Kulkarni int
5983dde7c95SVishal Kulkarni t4_addmac(void *arg, const uint8_t *ucaddr)
5993dde7c95SVishal Kulkarni {
6003dde7c95SVishal Kulkarni 	return (t4_mc_unicst(arg, ucaddr));
6013dde7c95SVishal Kulkarni }
6023dde7c95SVishal Kulkarni 
6033dde7c95SVishal Kulkarni static int
6043dde7c95SVishal Kulkarni t4_remmac(void *arg, const uint8_t *mac_addr)
6053dde7c95SVishal Kulkarni {
6063dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
6073dde7c95SVishal Kulkarni 	int rc;
6083dde7c95SVishal Kulkarni 
6093dde7c95SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
6103dde7c95SVishal Kulkarni 	if (rc != 0)
6113dde7c95SVishal Kulkarni 		return (rc);
6123dde7c95SVishal Kulkarni 
6133dde7c95SVishal Kulkarni 	pi->macaddr_cnt--;
6143dde7c95SVishal Kulkarni 	end_synchronized_op(pi, 1);
6153dde7c95SVishal Kulkarni 
6163dde7c95SVishal Kulkarni 	return (0);
6173dde7c95SVishal Kulkarni }
6183dde7c95SVishal Kulkarni 
6193dde7c95SVishal Kulkarni /*
6203dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all groups.
6213dde7c95SVishal Kulkarni  */
6223dde7c95SVishal Kulkarni void
6233dde7c95SVishal Kulkarni t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
6243dde7c95SVishal Kulkarni 	      mac_group_info_t *infop, mac_group_handle_t gh)
6253dde7c95SVishal Kulkarni {
6263dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
6273dde7c95SVishal Kulkarni 
6283dde7c95SVishal Kulkarni 	switch (rtype) {
6293dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
6303dde7c95SVishal Kulkarni 		infop->mgi_driver = (mac_group_driver_t)arg;
6313dde7c95SVishal Kulkarni 		infop->mgi_start = NULL;
6323dde7c95SVishal Kulkarni 		infop->mgi_stop = NULL;
6333dde7c95SVishal Kulkarni 		infop->mgi_addmac = t4_addmac;
6343dde7c95SVishal Kulkarni 		infop->mgi_remmac = t4_remmac;
6353dde7c95SVishal Kulkarni 		infop->mgi_count = pi->nrxq;
6363dde7c95SVishal Kulkarni 		break;
6373dde7c95SVishal Kulkarni 	}
6383dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX:
6393dde7c95SVishal Kulkarni 	default:
6403dde7c95SVishal Kulkarni 		ASSERT(0);
6413dde7c95SVishal Kulkarni 		break;
6423dde7c95SVishal Kulkarni 	}
6433dde7c95SVishal Kulkarni }
6443dde7c95SVishal Kulkarni 
6453dde7c95SVishal Kulkarni static int
6463dde7c95SVishal Kulkarni t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
6473dde7c95SVishal Kulkarni {
6483dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
6493dde7c95SVishal Kulkarni 
6503dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6513dde7c95SVishal Kulkarni 	rxq->ring_gen_num = mr_gen_num;
6523dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6533dde7c95SVishal Kulkarni 	return (0);
6543dde7c95SVishal Kulkarni }
6553dde7c95SVishal Kulkarni 
6563dde7c95SVishal Kulkarni /*
6573dde7c95SVishal Kulkarni  * Enable interrupt on the specificed rx ring.
6583dde7c95SVishal Kulkarni  */
6593dde7c95SVishal Kulkarni int
6603dde7c95SVishal Kulkarni t4_ring_intr_enable(mac_intr_handle_t intrh)
6613dde7c95SVishal Kulkarni {
6623dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
6633dde7c95SVishal Kulkarni 	struct adapter *sc = rxq->port->adapter;
6643dde7c95SVishal Kulkarni 	struct sge_iq *iq;
6653dde7c95SVishal Kulkarni 
6663dde7c95SVishal Kulkarni 	iq = &rxq->iq;
6673dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6683dde7c95SVishal Kulkarni 	iq->polling = 0;
6693dde7c95SVishal Kulkarni 	iq->state = IQS_IDLE;
6703dde7c95SVishal Kulkarni 	t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
6713dde7c95SVishal Kulkarni 		     V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id));
6723dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6733dde7c95SVishal Kulkarni 	return (0);
6743dde7c95SVishal Kulkarni }
6753dde7c95SVishal Kulkarni 
6763dde7c95SVishal Kulkarni /*
6773dde7c95SVishal Kulkarni  * Disable interrupt on the specificed rx ring.
6783dde7c95SVishal Kulkarni  */
6793dde7c95SVishal Kulkarni int
6803dde7c95SVishal Kulkarni t4_ring_intr_disable(mac_intr_handle_t intrh)
6813dde7c95SVishal Kulkarni {
6823dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
6833dde7c95SVishal Kulkarni 	struct sge_iq *iq;
6843dde7c95SVishal Kulkarni 
6853dde7c95SVishal Kulkarni 	/* Nothing to be done here wrt interrupt, as it
6863dde7c95SVishal Kulkarni 	 * will not fire, until we write back to
6873dde7c95SVishal Kulkarni 	 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable.
6883dde7c95SVishal Kulkarni 	 */
6893dde7c95SVishal Kulkarni 
6903dde7c95SVishal Kulkarni 	iq = &rxq->iq;
6913dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6923dde7c95SVishal Kulkarni 	iq->polling = 1;
6933dde7c95SVishal Kulkarni 	iq->state = IQS_BUSY;
6943dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6953dde7c95SVishal Kulkarni 	return (0);
6963dde7c95SVishal Kulkarni }
6973dde7c95SVishal Kulkarni 
6983dde7c95SVishal Kulkarni mblk_t *
6993dde7c95SVishal Kulkarni t4_poll_ring(void *arg, int n_bytes)
7003dde7c95SVishal Kulkarni {
7013dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)arg;
7023dde7c95SVishal Kulkarni 	mblk_t *mp = NULL;
7033dde7c95SVishal Kulkarni 
7043dde7c95SVishal Kulkarni 	ASSERT(n_bytes >= 0);
7053dde7c95SVishal Kulkarni 	if (n_bytes == 0)
7063dde7c95SVishal Kulkarni 		return (NULL);
7073dde7c95SVishal Kulkarni 
7083dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
7093dde7c95SVishal Kulkarni 	mp = t4_ring_rx(rxq, n_bytes);
7103dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
7113dde7c95SVishal Kulkarni 
7123dde7c95SVishal Kulkarni 	return (mp);
7133dde7c95SVishal Kulkarni }
7143dde7c95SVishal Kulkarni 
7153dde7c95SVishal Kulkarni /*
7163dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular rx ring
7173dde7c95SVishal Kulkarni  */
7183dde7c95SVishal Kulkarni int
7193dde7c95SVishal Kulkarni t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
7203dde7c95SVishal Kulkarni {
7213dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
7223dde7c95SVishal Kulkarni 
7233dde7c95SVishal Kulkarni 	switch (stat) {
7243dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
7253dde7c95SVishal Kulkarni 		*val = rxq->rxbytes;
7263dde7c95SVishal Kulkarni 		break;
7273dde7c95SVishal Kulkarni 
7283dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
7293dde7c95SVishal Kulkarni 		*val = rxq->rxpkts;
7303dde7c95SVishal Kulkarni 		break;
7313dde7c95SVishal Kulkarni 
7323dde7c95SVishal Kulkarni 	default:
7333dde7c95SVishal Kulkarni 		*val = 0;
7343dde7c95SVishal Kulkarni 		return (ENOTSUP);
7353dde7c95SVishal Kulkarni 	}
7363dde7c95SVishal Kulkarni 
7373dde7c95SVishal Kulkarni 	return (0);
7383dde7c95SVishal Kulkarni }
7393dde7c95SVishal Kulkarni 
7403dde7c95SVishal Kulkarni /*
7413dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular tx ring
7423dde7c95SVishal Kulkarni  */
7433dde7c95SVishal Kulkarni int
7443dde7c95SVishal Kulkarni t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
7453dde7c95SVishal Kulkarni {
7463dde7c95SVishal Kulkarni 	struct sge_txq *txq = (struct sge_txq *)rh;
7473dde7c95SVishal Kulkarni 
7483dde7c95SVishal Kulkarni 	switch (stat) {
7493dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
7503dde7c95SVishal Kulkarni 		*val = txq->txbytes;
7513dde7c95SVishal Kulkarni 		break;
7523dde7c95SVishal Kulkarni 
7533dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
7543dde7c95SVishal Kulkarni 		*val = txq->txpkts;
7553dde7c95SVishal Kulkarni 		break;
7563dde7c95SVishal Kulkarni 
7573dde7c95SVishal Kulkarni 	default:
7583dde7c95SVishal Kulkarni 		*val = 0;
7593dde7c95SVishal Kulkarni 		return (ENOTSUP);
7603dde7c95SVishal Kulkarni 	}
7613dde7c95SVishal Kulkarni 
7623dde7c95SVishal Kulkarni 	return (0);
7633dde7c95SVishal Kulkarni }
7643dde7c95SVishal Kulkarni 
7653dde7c95SVishal Kulkarni /*
7663dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all rings
7673dde7c95SVishal Kulkarni  * for given ring_group, noted by group_index.
7683dde7c95SVishal Kulkarni  * Since we have only one group, ring index becomes
7693dde7c95SVishal Kulkarni  * absolute index.
7703dde7c95SVishal Kulkarni  */
7713dde7c95SVishal Kulkarni void
7723dde7c95SVishal Kulkarni t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
7733dde7c95SVishal Kulkarni 	     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
7743dde7c95SVishal Kulkarni {
7753dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
7763dde7c95SVishal Kulkarni 	mac_intr_t *mintr;
7773dde7c95SVishal Kulkarni 
7783dde7c95SVishal Kulkarni 	switch (rtype) {
7793dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
7803dde7c95SVishal Kulkarni 		struct sge_rxq *rxq;
7813dde7c95SVishal Kulkarni 
7823dde7c95SVishal Kulkarni 		rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
7833dde7c95SVishal Kulkarni 		rxq->ring_handle = rh;
7843dde7c95SVishal Kulkarni 
7853dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)rxq;
7863dde7c95SVishal Kulkarni 		infop->mri_start = t4_ring_start;
7873dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
7883dde7c95SVishal Kulkarni 		infop->mri_poll = t4_poll_ring;
7893dde7c95SVishal Kulkarni 		infop->mri_stat = t4_rx_stat;
7903dde7c95SVishal Kulkarni 
7913dde7c95SVishal Kulkarni 		mintr = &infop->mri_intr;
7923dde7c95SVishal Kulkarni 		mintr->mi_handle = (mac_intr_handle_t)rxq;
7933dde7c95SVishal Kulkarni 		mintr->mi_enable = t4_ring_intr_enable;
7943dde7c95SVishal Kulkarni 		mintr->mi_disable = t4_ring_intr_disable;
7953dde7c95SVishal Kulkarni 
7963dde7c95SVishal Kulkarni 		break;
7973dde7c95SVishal Kulkarni 	}
7983dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX: {
7993dde7c95SVishal Kulkarni 		struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index];
8003dde7c95SVishal Kulkarni 		txq->ring_handle = rh;
8013dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)txq;
8023dde7c95SVishal Kulkarni 		infop->mri_start = NULL;
8033dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
8043dde7c95SVishal Kulkarni 		infop->mri_tx = t4_eth_tx;
8053dde7c95SVishal Kulkarni 		infop->mri_stat = t4_tx_stat;
8063dde7c95SVishal Kulkarni 		break;
8073dde7c95SVishal Kulkarni 	}
8083dde7c95SVishal Kulkarni 	default:
8093dde7c95SVishal Kulkarni 		ASSERT(0);
8103dde7c95SVishal Kulkarni 		break;
8113dde7c95SVishal Kulkarni 	}
8123dde7c95SVishal Kulkarni }
8133dde7c95SVishal Kulkarni 
8143dde7c95SVishal Kulkarni mblk_t *
81556b2bdd1SGireesh Nagabhushana t4_mc_tx(void *arg, mblk_t *m)
81656b2bdd1SGireesh Nagabhushana {
81756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
81856b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
81956b2bdd1SGireesh Nagabhushana 	struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
82056b2bdd1SGireesh Nagabhushana 
8213dde7c95SVishal Kulkarni 	return (t4_eth_tx(txq, m));
82256b2bdd1SGireesh Nagabhushana }
82356b2bdd1SGireesh Nagabhushana 
824017c366dSRobert Mustacchi static int
825017c366dSRobert Mustacchi t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
826017c366dSRobert Mustacchi {
827017c366dSRobert Mustacchi 	struct port_info *pi = arg;
828017c366dSRobert Mustacchi 
829017c366dSRobert Mustacchi 	if (id != 0 || infop == NULL)
830017c366dSRobert Mustacchi 		return (EINVAL);
831017c366dSRobert Mustacchi 
832017c366dSRobert Mustacchi 	switch (pi->mod_type) {
833017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NONE:
834017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_FALSE);
835017c366dSRobert Mustacchi 		break;
836017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NOTSUPPORTED:
837017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
838017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_FALSE);
839017c366dSRobert Mustacchi 		break;
840017c366dSRobert Mustacchi 	default:
841017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
842017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_TRUE);
843017c366dSRobert Mustacchi 		break;
844017c366dSRobert Mustacchi 	}
845017c366dSRobert Mustacchi 
846017c366dSRobert Mustacchi 	return (0);
847017c366dSRobert Mustacchi }
848017c366dSRobert Mustacchi 
849017c366dSRobert Mustacchi static int
850017c366dSRobert Mustacchi t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
851017c366dSRobert Mustacchi     size_t nbytes, off_t offset, size_t *nread)
852017c366dSRobert Mustacchi {
853017c366dSRobert Mustacchi 	struct port_info *pi = arg;
854017c366dSRobert Mustacchi 	struct adapter *sc = pi->adapter;
855017c366dSRobert Mustacchi 	int rc;
856017c366dSRobert Mustacchi 	size_t i, maxread;
857017c366dSRobert Mustacchi 	/* LINTED: E_FUNC_VAR_UNUSED */
858017c366dSRobert Mustacchi 	struct fw_ldst_cmd ldst __unused;
859017c366dSRobert Mustacchi 
860017c366dSRobert Mustacchi 	if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
861017c366dSRobert Mustacchi 	    (page != 0xa0 && page != 0xa2) || offset < 0)
862017c366dSRobert Mustacchi 		return (EINVAL);
863017c366dSRobert Mustacchi 
864017c366dSRobert Mustacchi 	if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
865017c366dSRobert Mustacchi 		return (EINVAL);
866017c366dSRobert Mustacchi 
867017c366dSRobert Mustacchi 	rc = begin_synchronized_op(pi, 0, 1);
868017c366dSRobert Mustacchi 	if (rc != 0)
869017c366dSRobert Mustacchi 		return (rc);
870017c366dSRobert Mustacchi 
871017c366dSRobert Mustacchi 	/*
872017c366dSRobert Mustacchi 	 * Firmware has a maximum size that we can read. Don't read more than it
873017c366dSRobert Mustacchi 	 * allows.
874017c366dSRobert Mustacchi 	 */
875017c366dSRobert Mustacchi 	maxread = sizeof (ldst.u.i2c.data);
876017c366dSRobert Mustacchi 	for (i = 0; i < nbytes; i += maxread) {
877017c366dSRobert Mustacchi 		size_t toread = MIN(maxread, nbytes - i);
878017c366dSRobert Mustacchi 		rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
879017c366dSRobert Mustacchi 		    bp);
880017c366dSRobert Mustacchi 		if (rc != 0)
881017c366dSRobert Mustacchi 			break;
882017c366dSRobert Mustacchi 		offset += toread;
883017c366dSRobert Mustacchi 		bp = (void *)((uintptr_t)bp + toread);
884017c366dSRobert Mustacchi 	}
885017c366dSRobert Mustacchi 	end_synchronized_op(pi, 0);
886017c366dSRobert Mustacchi 	if (rc == 0)
887017c366dSRobert Mustacchi 		*nread = nbytes;
888017c366dSRobert Mustacchi 	return (rc);
889017c366dSRobert Mustacchi }
890017c366dSRobert Mustacchi 
891d87e4548SVishal Kulkarni static int
892d87e4548SVishal Kulkarni t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
893d87e4548SVishal Kulkarni {
894d87e4548SVishal Kulkarni 	struct port_info *pi = arg;
895d87e4548SVishal Kulkarni 	struct adapter *sc = pi->adapter;
896d87e4548SVishal Kulkarni 	int val, rc;
897d87e4548SVishal Kulkarni 
898d87e4548SVishal Kulkarni 	if (flags != 0)
899d87e4548SVishal Kulkarni 		return (EINVAL);
900d87e4548SVishal Kulkarni 
901d87e4548SVishal Kulkarni 	switch (mode) {
902d87e4548SVishal Kulkarni 	case MAC_LED_DEFAULT:
903d87e4548SVishal Kulkarni 		val = 0;
904d87e4548SVishal Kulkarni 		break;
905d87e4548SVishal Kulkarni 	case MAC_LED_IDENT:
906d87e4548SVishal Kulkarni 		val = 0xffff;
907d87e4548SVishal Kulkarni 		break;
908d87e4548SVishal Kulkarni 
909d87e4548SVishal Kulkarni 	default:
910d87e4548SVishal Kulkarni 		return (ENOTSUP);
911d87e4548SVishal Kulkarni 	}
912d87e4548SVishal Kulkarni 
913d87e4548SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
914d87e4548SVishal Kulkarni 	if (rc != 0)
915d87e4548SVishal Kulkarni 		return (rc);
916d87e4548SVishal Kulkarni 	rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
917d87e4548SVishal Kulkarni 	end_synchronized_op(pi, 1);
918d87e4548SVishal Kulkarni 
919d87e4548SVishal Kulkarni 	return (rc);
920d87e4548SVishal Kulkarni }
921d87e4548SVishal Kulkarni 
92256b2bdd1SGireesh Nagabhushana static boolean_t
92356b2bdd1SGireesh Nagabhushana t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
92456b2bdd1SGireesh Nagabhushana {
92556b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
92656b2bdd1SGireesh Nagabhushana 	boolean_t status = B_TRUE;
927017c366dSRobert Mustacchi 	mac_capab_transceiver_t *mct;
928d87e4548SVishal Kulkarni 	mac_capab_led_t *mcl;
92956b2bdd1SGireesh Nagabhushana 
93056b2bdd1SGireesh Nagabhushana 	switch (cap) {
93156b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_HCKSUM:
93256b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_CSUM) {
93356b2bdd1SGireesh Nagabhushana 			uint32_t *d = data;
934d75c6062SRobert Mustacchi 			*d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM |
935d75c6062SRobert Mustacchi 			    HCKSUM_INET_FULL_V6;
93656b2bdd1SGireesh Nagabhushana 		} else
93756b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
93856b2bdd1SGireesh Nagabhushana 		break;
93956b2bdd1SGireesh Nagabhushana 
94056b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_LSO:
94156b2bdd1SGireesh Nagabhushana 		/* Enabling LSO requires Checksum offloading */
94256b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_LSO &&
94356b2bdd1SGireesh Nagabhushana 		    pi->features & CXGBE_HW_CSUM) {
94456b2bdd1SGireesh Nagabhushana 			mac_capab_lso_t *d = data;
94556b2bdd1SGireesh Nagabhushana 
946d75c6062SRobert Mustacchi 			d->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
947d75c6062SRobert Mustacchi 			    LSO_TX_BASIC_TCP_IPV6;
94856b2bdd1SGireesh Nagabhushana 			d->lso_basic_tcp_ipv4.lso_max = 65535;
949d75c6062SRobert Mustacchi 			d->lso_basic_tcp_ipv6.lso_max = 65535;
95056b2bdd1SGireesh Nagabhushana 		} else
95156b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
95256b2bdd1SGireesh Nagabhushana 		break;
95356b2bdd1SGireesh Nagabhushana 
9543dde7c95SVishal Kulkarni 	case MAC_CAPAB_RINGS: {
9553dde7c95SVishal Kulkarni 		mac_capab_rings_t *cap_rings = data;
9563dde7c95SVishal Kulkarni 
9573dde7c95SVishal Kulkarni 		if (!pi->adapter->props.multi_rings) {
9583dde7c95SVishal Kulkarni 			status = B_FALSE;
9593dde7c95SVishal Kulkarni 			break;
9603dde7c95SVishal Kulkarni 		}
9613dde7c95SVishal Kulkarni 		switch (cap_rings->mr_type) {
9623dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_RX:
9633dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
9643dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->nrxq;
9653dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 1;
9663dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
9673dde7c95SVishal Kulkarni 			cap_rings->mr_gget = t4_fill_group;
9683dde7c95SVishal Kulkarni 			cap_rings->mr_gaddring = NULL;
9693dde7c95SVishal Kulkarni 			cap_rings->mr_gremring = NULL;
9703dde7c95SVishal Kulkarni 			break;
9713dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_TX:
9723dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
9733dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->ntxq;
9743dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 0;
9753dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
9763dde7c95SVishal Kulkarni 			cap_rings->mr_gget = NULL;
9773dde7c95SVishal Kulkarni 			break;
9783dde7c95SVishal Kulkarni 		}
9793dde7c95SVishal Kulkarni 		break;
9803dde7c95SVishal Kulkarni 	}
981017c366dSRobert Mustacchi 
982017c366dSRobert Mustacchi 	case MAC_CAPAB_TRANSCEIVER:
983017c366dSRobert Mustacchi 		mct = data;
984017c366dSRobert Mustacchi 
985017c366dSRobert Mustacchi 		mct->mct_flags = 0;
986017c366dSRobert Mustacchi 		mct->mct_ntransceivers = 1;
987017c366dSRobert Mustacchi 		mct->mct_info = t4_mc_transceiver_info;
988017c366dSRobert Mustacchi 		mct->mct_read = t4_mc_transceiver_read;
989017c366dSRobert Mustacchi 		break;
990d87e4548SVishal Kulkarni 	case MAC_CAPAB_LED:
991d87e4548SVishal Kulkarni 		mcl = data;
992d87e4548SVishal Kulkarni 		mcl->mcl_flags = 0;
993d87e4548SVishal Kulkarni 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
994d87e4548SVishal Kulkarni 		mcl->mcl_set = t4_port_led_set;
995d87e4548SVishal Kulkarni 		break;
996017c366dSRobert Mustacchi 
99756b2bdd1SGireesh Nagabhushana 	default:
99856b2bdd1SGireesh Nagabhushana 		status = B_FALSE; /* cap not supported */
99956b2bdd1SGireesh Nagabhushana 	}
100056b2bdd1SGireesh Nagabhushana 
100156b2bdd1SGireesh Nagabhushana 	return (status);
100256b2bdd1SGireesh Nagabhushana }
100356b2bdd1SGireesh Nagabhushana 
1004*6feac2e3SRahul Lakkireddy static void t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,
1005*6feac2e3SRahul Lakkireddy 					 link_flowctrl_t *fc)
1006d77e6e0fSPaul Winder {
1007*6feac2e3SRahul Lakkireddy 	u8 pause_tx = 0, pause_rx = 0;
1008d77e6e0fSPaul Winder 
1009*6feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FC_TX)
1010*6feac2e3SRahul Lakkireddy 		pause_tx = 1;
1011d77e6e0fSPaul Winder 
1012*6feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FC_RX)
1013*6feac2e3SRahul Lakkireddy 		pause_rx = 1;
1014*6feac2e3SRahul Lakkireddy 
1015*6feac2e3SRahul Lakkireddy 	if (pause_rx & pause_tx)
1016*6feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_BI;
1017*6feac2e3SRahul Lakkireddy 	else if (pause_tx)
1018*6feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_TX;
1019*6feac2e3SRahul Lakkireddy 	else if (pause_rx)
1020*6feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_RX;
1021*6feac2e3SRahul Lakkireddy 	else
1022*6feac2e3SRahul Lakkireddy 		*fc = LINK_FLOWCTRL_NONE;
1023*6feac2e3SRahul Lakkireddy }
1024*6feac2e3SRahul Lakkireddy 
1025*6feac2e3SRahul Lakkireddy static int t4_mac_flowctrl_to_link_caps(struct port_info *pi,
1026*6feac2e3SRahul Lakkireddy 					link_flowctrl_t fc,
1027*6feac2e3SRahul Lakkireddy 					fw_port_cap32_t *new_caps)
1028*6feac2e3SRahul Lakkireddy {
1029*6feac2e3SRahul Lakkireddy 	cc_pause_t pause = 0;
1030*6feac2e3SRahul Lakkireddy 
1031*6feac2e3SRahul Lakkireddy 	switch (fc) {
1032*6feac2e3SRahul Lakkireddy 	case LINK_FLOWCTRL_BI:
1033*6feac2e3SRahul Lakkireddy 		pause |= PAUSE_TX | PAUSE_RX;
1034*6feac2e3SRahul Lakkireddy 		break;
1035*6feac2e3SRahul Lakkireddy 	case LINK_FLOWCTRL_TX:
1036*6feac2e3SRahul Lakkireddy 		pause |= PAUSE_TX;
1037*6feac2e3SRahul Lakkireddy 		break;
1038*6feac2e3SRahul Lakkireddy 	case LINK_FLOWCTRL_RX:
1039*6feac2e3SRahul Lakkireddy 		pause |= PAUSE_RX;
1040*6feac2e3SRahul Lakkireddy 		break;
1041*6feac2e3SRahul Lakkireddy 	default:
1042*6feac2e3SRahul Lakkireddy 		break;
1043*6feac2e3SRahul Lakkireddy 	}
1044*6feac2e3SRahul Lakkireddy 
1045*6feac2e3SRahul Lakkireddy 	if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG)
1046*6feac2e3SRahul Lakkireddy 		pause |= PAUSE_AUTONEG;
1047d77e6e0fSPaul Winder 
1048*6feac2e3SRahul Lakkireddy 	return t4_link_set_pause(pi, pause, new_caps);
1049*6feac2e3SRahul Lakkireddy }
1050d77e6e0fSPaul Winder 
1051*6feac2e3SRahul Lakkireddy static link_fec_t t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)
1052*6feac2e3SRahul Lakkireddy {
1053*6feac2e3SRahul Lakkireddy 	link_fec_t link_fec = 0;
1054*6feac2e3SRahul Lakkireddy 
1055*6feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FEC_RS)
1056d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_RS;
1057d77e6e0fSPaul Winder 
1058*6feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FEC_BASER_RS)
1059d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_BASE_R;
1060d77e6e0fSPaul Winder 
1061*6feac2e3SRahul Lakkireddy 	if (caps & FW_PORT_CAP32_FEC_NO_FEC)
1062*6feac2e3SRahul Lakkireddy 		link_fec |= LINK_FEC_NONE;
1063*6feac2e3SRahul Lakkireddy 
1064*6feac2e3SRahul Lakkireddy 	if ((link_fec & (link_fec - 1)) &&
1065*6feac2e3SRahul Lakkireddy 	    !(caps & FW_PORT_CAP32_FORCE_FEC))
1066*6feac2e3SRahul Lakkireddy 		return LINK_FEC_AUTO;
1067*6feac2e3SRahul Lakkireddy 
1068*6feac2e3SRahul Lakkireddy 	return link_fec;
1069d77e6e0fSPaul Winder }
1070d77e6e0fSPaul Winder 
1071*6feac2e3SRahul Lakkireddy static void t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,
1072*6feac2e3SRahul Lakkireddy 					 link_fec_t *fec)
1073*6feac2e3SRahul Lakkireddy {
1074*6feac2e3SRahul Lakkireddy 	*fec = t4_mac_port_caps_to_fec_cap(caps);
1075*6feac2e3SRahul Lakkireddy }
1076*6feac2e3SRahul Lakkireddy 
1077*6feac2e3SRahul Lakkireddy static void t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,
1078*6feac2e3SRahul Lakkireddy 					link_fec_t *fec)
1079d77e6e0fSPaul Winder {
1080*6feac2e3SRahul Lakkireddy 	link_fec_t link_fec;
1081d77e6e0fSPaul Winder 
1082*6feac2e3SRahul Lakkireddy 	caps &= ~FW_PORT_CAP32_FEC_NO_FEC;
1083*6feac2e3SRahul Lakkireddy 	link_fec = t4_mac_port_caps_to_fec_cap(caps);
1084*6feac2e3SRahul Lakkireddy 	*fec = link_fec ? link_fec : LINK_FEC_NONE;
1085*6feac2e3SRahul Lakkireddy }
1086*6feac2e3SRahul Lakkireddy 
1087*6feac2e3SRahul Lakkireddy static int t4_mac_fec_cap_to_link_caps(struct port_info *pi, link_fec_t v,
1088*6feac2e3SRahul Lakkireddy 				       fw_port_cap32_t *new_caps)
1089*6feac2e3SRahul Lakkireddy {
1090*6feac2e3SRahul Lakkireddy 	cc_fec_t fec = 0;
1091*6feac2e3SRahul Lakkireddy 
1092*6feac2e3SRahul Lakkireddy 	if (v == LINK_FEC_AUTO) {
1093d77e6e0fSPaul Winder 		fec = FEC_AUTO;
1094*6feac2e3SRahul Lakkireddy 		goto out;
1095*6feac2e3SRahul Lakkireddy 	}
1096d77e6e0fSPaul Winder 
1097*6feac2e3SRahul Lakkireddy 	if (v & LINK_FEC_NONE) {
1098*6feac2e3SRahul Lakkireddy 		v &= ~LINK_FEC_NONE;
1099*6feac2e3SRahul Lakkireddy 		fec |= FEC_NONE;
1100*6feac2e3SRahul Lakkireddy 	}
1101d77e6e0fSPaul Winder 
1102*6feac2e3SRahul Lakkireddy 	if (v & LINK_FEC_RS) {
1103*6feac2e3SRahul Lakkireddy 		v &= ~LINK_FEC_RS;
1104*6feac2e3SRahul Lakkireddy 		fec |= FEC_RS;
1105*6feac2e3SRahul Lakkireddy 	}
1106*6feac2e3SRahul Lakkireddy 
1107*6feac2e3SRahul Lakkireddy 	if (v & LINK_FEC_BASE_R) {
1108*6feac2e3SRahul Lakkireddy 		v &= ~LINK_FEC_BASE_R;
1109*6feac2e3SRahul Lakkireddy 		fec |= FEC_BASER_RS;
1110d77e6e0fSPaul Winder 	}
1111d77e6e0fSPaul Winder 
1112d77e6e0fSPaul Winder 	if (v != 0)
1113d77e6e0fSPaul Winder 		return (-1);
1114d77e6e0fSPaul Winder 
1115d77e6e0fSPaul Winder 	ASSERT3S(fec, !=, 0);
1116d77e6e0fSPaul Winder 
1117*6feac2e3SRahul Lakkireddy 	fec |= FEC_FORCE;
1118*6feac2e3SRahul Lakkireddy 
1119*6feac2e3SRahul Lakkireddy out:
1120*6feac2e3SRahul Lakkireddy 	return t4_link_set_fec(pi, fec, new_caps);
1121d77e6e0fSPaul Winder }
1122d77e6e0fSPaul Winder 
112356b2bdd1SGireesh Nagabhushana /* ARGSUSED */
112456b2bdd1SGireesh Nagabhushana static int
112556b2bdd1SGireesh Nagabhushana t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
112656b2bdd1SGireesh Nagabhushana     const void *val)
112756b2bdd1SGireesh Nagabhushana {
112856b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
112956b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
1130*6feac2e3SRahul Lakkireddy 	struct link_config *lc = &pi->link_cfg;
1131*6feac2e3SRahul Lakkireddy 	fw_port_cap32_t new_caps = lc->admin_caps;
1132*6feac2e3SRahul Lakkireddy 	int relink = 0, rx_mode = 0, rc = 0;
113356b2bdd1SGireesh Nagabhushana 	uint32_t v32 = *(uint32_t *)val;
1134*6feac2e3SRahul Lakkireddy 	uint8_t v8 = *(uint8_t *)val;
113556b2bdd1SGireesh Nagabhushana 	link_flowctrl_t fc;
1136d77e6e0fSPaul Winder 	link_fec_t fec;
113756b2bdd1SGireesh Nagabhushana 
113856b2bdd1SGireesh Nagabhushana 	switch (id) {
113956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
1140*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_autoneg(pi, v8, &new_caps);
1141*6feac2e3SRahul Lakkireddy 		relink = 1;
114256b2bdd1SGireesh Nagabhushana 		break;
114356b2bdd1SGireesh Nagabhushana 
114456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
114556b2bdd1SGireesh Nagabhushana 		if (v32 < 46 || v32 > MAX_MTU) {
114656b2bdd1SGireesh Nagabhushana 			rc = EINVAL;
114756b2bdd1SGireesh Nagabhushana 		} else if (v32 != pi->mtu) {
114856b2bdd1SGireesh Nagabhushana 			pi->mtu = v32;
114956b2bdd1SGireesh Nagabhushana 			(void) mac_maxsdu_update(pi->mh, v32);
115056b2bdd1SGireesh Nagabhushana 			rx_mode = 1;
115156b2bdd1SGireesh Nagabhushana 		}
115256b2bdd1SGireesh Nagabhushana 
115356b2bdd1SGireesh Nagabhushana 		break;
115456b2bdd1SGireesh Nagabhushana 
115556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
115656b2bdd1SGireesh Nagabhushana 		fc = *(link_flowctrl_t *)val;
1157*6feac2e3SRahul Lakkireddy 		rc = t4_mac_flowctrl_to_link_caps(pi, fc, &new_caps);
1158*6feac2e3SRahul Lakkireddy 		relink = 1;
115956b2bdd1SGireesh Nagabhushana 		break;
116056b2bdd1SGireesh Nagabhushana 
1161d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1162d77e6e0fSPaul Winder 		fec = *(link_fec_t *)val;
1163*6feac2e3SRahul Lakkireddy 		rc = t4_mac_fec_cap_to_link_caps(pi, fec, &new_caps);
1164*6feac2e3SRahul Lakkireddy 		relink = 1;
1165d77e6e0fSPaul Winder 		break;
1166d77e6e0fSPaul Winder 
1167*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_100GFDX_CAP:
1168*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100G, v8,
1169*6feac2e3SRahul Lakkireddy 				       &new_caps);
1170*6feac2e3SRahul Lakkireddy 		relink = 1;
1171*6feac2e3SRahul Lakkireddy 		break;
117256b2bdd1SGireesh Nagabhushana 
1173*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_50GFDX_CAP:
1174*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_50G, v8,
1175*6feac2e3SRahul Lakkireddy 				       &new_caps);
1176*6feac2e3SRahul Lakkireddy 		relink = 1;
1177*6feac2e3SRahul Lakkireddy 		break;
1178*6feac2e3SRahul Lakkireddy 
1179*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_40GFDX_CAP:
1180*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_40G, v8,
1181*6feac2e3SRahul Lakkireddy 				       &new_caps);
1182*6feac2e3SRahul Lakkireddy 		relink = 1;
1183*6feac2e3SRahul Lakkireddy 		break;
1184*6feac2e3SRahul Lakkireddy 
1185*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_25GFDX_CAP:
1186*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_25G, v8,
1187*6feac2e3SRahul Lakkireddy 				       &new_caps);
1188*6feac2e3SRahul Lakkireddy 		relink = 1;
1189*6feac2e3SRahul Lakkireddy 		break;
1190*6feac2e3SRahul Lakkireddy 
1191*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_10GFDX_CAP:
1192*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_10G, v8,
1193*6feac2e3SRahul Lakkireddy 				       &new_caps);
1194*6feac2e3SRahul Lakkireddy 		relink = 1;
119556b2bdd1SGireesh Nagabhushana 		break;
119656b2bdd1SGireesh Nagabhushana 
119756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
1198*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_1G, v8,
1199*6feac2e3SRahul Lakkireddy 				       &new_caps);
1200*6feac2e3SRahul Lakkireddy 		relink = 1;
120156b2bdd1SGireesh Nagabhushana 		break;
120256b2bdd1SGireesh Nagabhushana 
120356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
1204*6feac2e3SRahul Lakkireddy 		rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100M, v8,
1205*6feac2e3SRahul Lakkireddy 				       &new_caps);
1206*6feac2e3SRahul Lakkireddy 		relink = 1;
120756b2bdd1SGireesh Nagabhushana 		break;
120856b2bdd1SGireesh Nagabhushana 
120956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
121056b2bdd1SGireesh Nagabhushana 		rc = setprop(pi, name, val);
121156b2bdd1SGireesh Nagabhushana 		break;
121256b2bdd1SGireesh Nagabhushana 
121356b2bdd1SGireesh Nagabhushana 	default:
121456b2bdd1SGireesh Nagabhushana 		rc = ENOTSUP;
1215*6feac2e3SRahul Lakkireddy 		break;
121656b2bdd1SGireesh Nagabhushana 	}
121756b2bdd1SGireesh Nagabhushana 
1218*6feac2e3SRahul Lakkireddy 	if (rc != 0)
1219*6feac2e3SRahul Lakkireddy 		return (rc);
1220*6feac2e3SRahul Lakkireddy 
122156b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
122256b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
122356b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
122456b2bdd1SGireesh Nagabhushana 			if (rc != 0)
122556b2bdd1SGireesh Nagabhushana 				return (rc);
1226*6feac2e3SRahul Lakkireddy 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
1227*6feac2e3SRahul Lakkireddy 					    new_caps);
122856b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
122956b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
123056b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
1231*6feac2e3SRahul Lakkireddy 					    "%s link config failed: %d",
1232*6feac2e3SRahul Lakkireddy 					    __func__, rc);
1233*6feac2e3SRahul Lakkireddy 				return (rc);
123456b2bdd1SGireesh Nagabhushana 			}
123556b2bdd1SGireesh Nagabhushana 		}
123656b2bdd1SGireesh Nagabhushana 
123756b2bdd1SGireesh Nagabhushana 		if (rx_mode != 0) {
123856b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
123956b2bdd1SGireesh Nagabhushana 			if (rc != 0)
124056b2bdd1SGireesh Nagabhushana 				return (rc);
124156b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
124256b2bdd1SGireesh Nagabhushana 			    -1, -1, -1, false);
124356b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
124456b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
124556b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
124656b2bdd1SGireesh Nagabhushana 				    "set_rxmode failed: %d", rc);
1247*6feac2e3SRahul Lakkireddy 				return (rc);
124856b2bdd1SGireesh Nagabhushana 			}
124956b2bdd1SGireesh Nagabhushana 		}
125056b2bdd1SGireesh Nagabhushana 	}
125156b2bdd1SGireesh Nagabhushana 
1252*6feac2e3SRahul Lakkireddy 	if (relink != 0)
1253*6feac2e3SRahul Lakkireddy 		lc->admin_caps = new_caps;
1254*6feac2e3SRahul Lakkireddy 
1255*6feac2e3SRahul Lakkireddy 	return (0);
125656b2bdd1SGireesh Nagabhushana }
125756b2bdd1SGireesh Nagabhushana 
125856b2bdd1SGireesh Nagabhushana static int
125956b2bdd1SGireesh Nagabhushana t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
126056b2bdd1SGireesh Nagabhushana     void *val)
126156b2bdd1SGireesh Nagabhushana {
126256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
126356b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
126456b2bdd1SGireesh Nagabhushana 	uint8_t *u = val;
1265*6feac2e3SRahul Lakkireddy 	int rc = 0;
126656b2bdd1SGireesh Nagabhushana 
126756b2bdd1SGireesh Nagabhushana 	switch (id) {
126856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
126956b2bdd1SGireesh Nagabhushana 		*(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
127056b2bdd1SGireesh Nagabhushana 		    LINK_DUPLEX_UNKNOWN;
127156b2bdd1SGireesh Nagabhushana 		break;
127256b2bdd1SGireesh Nagabhushana 
127356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
127456b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
1275*6feac2e3SRahul Lakkireddy 			*(uint64_t *)val = t4_link_fwcap_to_speed(lc->link_caps);
127656b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val *= 1000000;
1277*6feac2e3SRahul Lakkireddy 		} else {
127856b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val = 0;
1279*6feac2e3SRahul Lakkireddy 		}
128056b2bdd1SGireesh Nagabhushana 		break;
128156b2bdd1SGireesh Nagabhushana 
128256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
128356b2bdd1SGireesh Nagabhushana 		*(link_state_t *)val = lc->link_ok ? LINK_STATE_UP :
128456b2bdd1SGireesh Nagabhushana 		    LINK_STATE_DOWN;
128556b2bdd1SGireesh Nagabhushana 		break;
128656b2bdd1SGireesh Nagabhushana 
128756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
1288*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
128956b2bdd1SGireesh Nagabhushana 		break;
129056b2bdd1SGireesh Nagabhushana 
129156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
129256b2bdd1SGireesh Nagabhushana 		*(uint32_t *)val = pi->mtu;
129356b2bdd1SGireesh Nagabhushana 		break;
129456b2bdd1SGireesh Nagabhushana 
129556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
1296*6feac2e3SRahul Lakkireddy 		t4_mac_link_caps_to_flowctrl(lc->link_caps, val);
129756b2bdd1SGireesh Nagabhushana 		break;
129856b2bdd1SGireesh Nagabhushana 
1299d77e6e0fSPaul Winder 	case MAC_PROP_ADV_FEC_CAP:
1300*6feac2e3SRahul Lakkireddy 		t4_mac_link_caps_to_fec_cap(lc->link_caps, val);
1301d77e6e0fSPaul Winder 		break;
1302d77e6e0fSPaul Winder 
1303d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1304*6feac2e3SRahul Lakkireddy 		t4_mac_admin_caps_to_fec_cap(lc->admin_caps, val);
1305d77e6e0fSPaul Winder 		break;
1306d77e6e0fSPaul Winder 
13073dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_100GFDX_CAP:
1308*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100G);
1309*6feac2e3SRahul Lakkireddy 		break;
1310*6feac2e3SRahul Lakkireddy 
13113dde7c95SVishal Kulkarni 	case MAC_PROP_EN_100GFDX_CAP:
1312*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
1313*6feac2e3SRahul Lakkireddy 		break;
1314*6feac2e3SRahul Lakkireddy 
1315*6feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_50GFDX_CAP:
1316*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_50G);
1317*6feac2e3SRahul Lakkireddy 		break;
1318*6feac2e3SRahul Lakkireddy 
1319*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_50GFDX_CAP:
1320*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
13213dde7c95SVishal Kulkarni 		break;
13223dde7c95SVishal Kulkarni 
13233dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_40GFDX_CAP:
1324*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_40G);
1325*6feac2e3SRahul Lakkireddy 		break;
1326*6feac2e3SRahul Lakkireddy 
13273dde7c95SVishal Kulkarni 	case MAC_PROP_EN_40GFDX_CAP:
1328*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
13293dde7c95SVishal Kulkarni 		break;
13303dde7c95SVishal Kulkarni 
13313dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_25GFDX_CAP:
1332*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_25G);
1333*6feac2e3SRahul Lakkireddy 		break;
1334*6feac2e3SRahul Lakkireddy 
13353dde7c95SVishal Kulkarni 	case MAC_PROP_EN_25GFDX_CAP:
1336*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
13373dde7c95SVishal Kulkarni 		break;
13383dde7c95SVishal Kulkarni 
133956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
1340*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_10G);
1341*6feac2e3SRahul Lakkireddy 		break;
1342*6feac2e3SRahul Lakkireddy 
134356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
1344*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
134556b2bdd1SGireesh Nagabhushana 		break;
134656b2bdd1SGireesh Nagabhushana 
134756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
1348*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_1G);
1349*6feac2e3SRahul Lakkireddy 		break;
1350*6feac2e3SRahul Lakkireddy 
135156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
1352*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
135356b2bdd1SGireesh Nagabhushana 		break;
135456b2bdd1SGireesh Nagabhushana 
135556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
1356*6feac2e3SRahul Lakkireddy 		*u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100M);
1357*6feac2e3SRahul Lakkireddy 		break;
1358*6feac2e3SRahul Lakkireddy 
135956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
1360*6feac2e3SRahul Lakkireddy 		*u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
136156b2bdd1SGireesh Nagabhushana 		break;
136256b2bdd1SGireesh Nagabhushana 
136356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
136456b2bdd1SGireesh Nagabhushana 		return (getprop(pi, name, size, val));
136556b2bdd1SGireesh Nagabhushana 
136656b2bdd1SGireesh Nagabhushana 	default:
136756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
136856b2bdd1SGireesh Nagabhushana 	}
136956b2bdd1SGireesh Nagabhushana 
1370*6feac2e3SRahul Lakkireddy 	return (rc);
137156b2bdd1SGireesh Nagabhushana }
137256b2bdd1SGireesh Nagabhushana 
137356b2bdd1SGireesh Nagabhushana static void
137456b2bdd1SGireesh Nagabhushana t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
137556b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph)
137656b2bdd1SGireesh Nagabhushana {
137756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
137856b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
137956b2bdd1SGireesh Nagabhushana 
138056b2bdd1SGireesh Nagabhushana 	switch (id) {
138156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
138256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
138356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
138456b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
138556b2bdd1SGireesh Nagabhushana 		break;
138656b2bdd1SGireesh Nagabhushana 
138756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
13887e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG)
138956b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
139056b2bdd1SGireesh Nagabhushana 		else
139156b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
139256b2bdd1SGireesh Nagabhushana 		break;
139356b2bdd1SGireesh Nagabhushana 
139456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
139556b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_range_uint32(ph, 46, MAX_MTU);
139656b2bdd1SGireesh Nagabhushana 		break;
139756b2bdd1SGireesh Nagabhushana 
139856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
139956b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI);
140056b2bdd1SGireesh Nagabhushana 		break;
140156b2bdd1SGireesh Nagabhushana 
1402d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1403d77e6e0fSPaul Winder 		mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1404d77e6e0fSPaul Winder 		break;
1405d77e6e0fSPaul Winder 
1406d77e6e0fSPaul Winder 	case MAC_PROP_ADV_FEC_CAP:
1407d77e6e0fSPaul Winder 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1408d77e6e0fSPaul Winder 		mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1409d77e6e0fSPaul Winder 		break;
1410d77e6e0fSPaul Winder 
1411*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_100GFDX_CAP:
1412*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_100G)
1413*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
1414*6feac2e3SRahul Lakkireddy 		else
1415*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1416*6feac2e3SRahul Lakkireddy 		break;
1417*6feac2e3SRahul Lakkireddy 
1418*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_50GFDX_CAP:
1419*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_50G)
1420*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
1421*6feac2e3SRahul Lakkireddy 		else
1422*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1423*6feac2e3SRahul Lakkireddy 		break;
1424*6feac2e3SRahul Lakkireddy 
1425*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_40GFDX_CAP:
1426*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_40G)
1427*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
1428*6feac2e3SRahul Lakkireddy 		else
1429*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1430*6feac2e3SRahul Lakkireddy 		break;
1431*6feac2e3SRahul Lakkireddy 
1432*6feac2e3SRahul Lakkireddy 	case MAC_PROP_EN_25GFDX_CAP:
1433*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_25G)
1434*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_default_uint8(ph, 1);
1435*6feac2e3SRahul Lakkireddy 		else
1436*6feac2e3SRahul Lakkireddy 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1437*6feac2e3SRahul Lakkireddy 		break;
1438*6feac2e3SRahul Lakkireddy 
143956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
1440*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_10G)
144156b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
144256b2bdd1SGireesh Nagabhushana 		else
144356b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
144456b2bdd1SGireesh Nagabhushana 		break;
144556b2bdd1SGireesh Nagabhushana 
144656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
1447*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_1G)
144856b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
144956b2bdd1SGireesh Nagabhushana 		else
145056b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
145156b2bdd1SGireesh Nagabhushana 		break;
145256b2bdd1SGireesh Nagabhushana 
145356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
1454*6feac2e3SRahul Lakkireddy 		if (lc->pcaps & FW_PORT_CAP32_SPEED_100M)
145556b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
145656b2bdd1SGireesh Nagabhushana 		else
145756b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
145856b2bdd1SGireesh Nagabhushana 		break;
145956b2bdd1SGireesh Nagabhushana 
1460*6feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_100GFDX_CAP:
1461*6feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_50GFDX_CAP:
1462*6feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_40GFDX_CAP:
1463*6feac2e3SRahul Lakkireddy 	case MAC_PROP_ADV_25GFDX_CAP:
146456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
146556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
146656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
146756b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
146856b2bdd1SGireesh Nagabhushana 		break;
146956b2bdd1SGireesh Nagabhushana 
147056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
147156b2bdd1SGireesh Nagabhushana 		propinfo(pi, name, ph);
147256b2bdd1SGireesh Nagabhushana 		break;
147356b2bdd1SGireesh Nagabhushana 
147456b2bdd1SGireesh Nagabhushana 	default:
147556b2bdd1SGireesh Nagabhushana 		break;
147656b2bdd1SGireesh Nagabhushana 	}
147756b2bdd1SGireesh Nagabhushana }
147856b2bdd1SGireesh Nagabhushana 
14797e6ad469SVishal Kulkarni int
148056b2bdd1SGireesh Nagabhushana begin_synchronized_op(struct port_info *pi, int hold, int waitok)
148156b2bdd1SGireesh Nagabhushana {
148256b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
148356b2bdd1SGireesh Nagabhushana 	int rc = 0;
148456b2bdd1SGireesh Nagabhushana 
148556b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK(sc);
148656b2bdd1SGireesh Nagabhushana 	while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
148756b2bdd1SGireesh Nagabhushana 		if (!waitok) {
148856b2bdd1SGireesh Nagabhushana 			rc = EBUSY;
148956b2bdd1SGireesh Nagabhushana 			goto failed;
149056b2bdd1SGireesh Nagabhushana 		} else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) {
149156b2bdd1SGireesh Nagabhushana 			rc = EINTR;
149256b2bdd1SGireesh Nagabhushana 			goto failed;
149356b2bdd1SGireesh Nagabhushana 		}
149456b2bdd1SGireesh Nagabhushana 	}
149556b2bdd1SGireesh Nagabhushana 	if (IS_DOOMED(pi) != 0) {	/* shouldn't happen on Solaris */
149656b2bdd1SGireesh Nagabhushana 		rc = ENXIO;
149756b2bdd1SGireesh Nagabhushana 		goto failed;
149856b2bdd1SGireesh Nagabhushana 	}
149956b2bdd1SGireesh Nagabhushana 	ASSERT(!IS_BUSY(sc));
150056b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
150156b2bdd1SGireesh Nagabhushana 	SET_BUSY(sc);
150256b2bdd1SGireesh Nagabhushana 
150356b2bdd1SGireesh Nagabhushana 	if (!hold)
150456b2bdd1SGireesh Nagabhushana 		ADAPTER_UNLOCK(sc);
150556b2bdd1SGireesh Nagabhushana 
150656b2bdd1SGireesh Nagabhushana 	return (0);
150756b2bdd1SGireesh Nagabhushana failed:
150856b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
150956b2bdd1SGireesh Nagabhushana 	return (rc);
151056b2bdd1SGireesh Nagabhushana }
151156b2bdd1SGireesh Nagabhushana 
15127e6ad469SVishal Kulkarni void
151356b2bdd1SGireesh Nagabhushana end_synchronized_op(struct port_info *pi, int held)
151456b2bdd1SGireesh Nagabhushana {
151556b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
151656b2bdd1SGireesh Nagabhushana 
151756b2bdd1SGireesh Nagabhushana 	if (!held)
151856b2bdd1SGireesh Nagabhushana 		ADAPTER_LOCK(sc);
151956b2bdd1SGireesh Nagabhushana 
152056b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_OWNED(sc);
152156b2bdd1SGireesh Nagabhushana 	ASSERT(IS_BUSY(sc));
152256b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
152356b2bdd1SGireesh Nagabhushana 	CLR_BUSY(sc);
152456b2bdd1SGireesh Nagabhushana 	cv_signal(&sc->cv);
152556b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
152656b2bdd1SGireesh Nagabhushana }
152756b2bdd1SGireesh Nagabhushana 
152856b2bdd1SGireesh Nagabhushana static int
152956b2bdd1SGireesh Nagabhushana t4_init_synchronized(struct port_info *pi)
153056b2bdd1SGireesh Nagabhushana {
153156b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
153256b2bdd1SGireesh Nagabhushana 	int rc = 0;
153356b2bdd1SGireesh Nagabhushana 
153456b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
153556b2bdd1SGireesh Nagabhushana 
153656b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0)
153756b2bdd1SGireesh Nagabhushana 		return (0);	/* already running */
153856b2bdd1SGireesh Nagabhushana 
153956b2bdd1SGireesh Nagabhushana 	if (!(sc->flags & FULL_INIT_DONE) &&
154056b2bdd1SGireesh Nagabhushana 	    ((rc = adapter_full_init(sc)) != 0))
154156b2bdd1SGireesh Nagabhushana 		return (rc);	/* error message displayed already */
154256b2bdd1SGireesh Nagabhushana 
154356b2bdd1SGireesh Nagabhushana 	if (!(pi->flags & PORT_INIT_DONE)) {
154456b2bdd1SGireesh Nagabhushana 		rc = port_full_init(pi);
154556b2bdd1SGireesh Nagabhushana 		if (rc != 0)
154656b2bdd1SGireesh Nagabhushana 			return (rc); /* error message displayed already */
154756b2bdd1SGireesh Nagabhushana 	} else
154856b2bdd1SGireesh Nagabhushana 		enable_port_queues(pi);
154956b2bdd1SGireesh Nagabhushana 
155056b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false);
155156b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
155256b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc);
155356b2bdd1SGireesh Nagabhushana 		goto done;
155456b2bdd1SGireesh Nagabhushana 	}
155556b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt,
15567e6ad469SVishal Kulkarni 	    pi->hw_addr, true, &pi->smt_idx);
155756b2bdd1SGireesh Nagabhushana 	if (rc < 0) {
155856b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc);
155956b2bdd1SGireesh Nagabhushana 		rc = -rc;
156056b2bdd1SGireesh Nagabhushana 		goto done;
156156b2bdd1SGireesh Nagabhushana 	} else
156256b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
156356b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
156456b2bdd1SGireesh Nagabhushana 
1565*6feac2e3SRahul Lakkireddy 	rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg,
1566*6feac2e3SRahul Lakkireddy 			    pi->link_cfg.admin_caps);
156756b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
156856b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc);
156956b2bdd1SGireesh Nagabhushana 		goto done;
157056b2bdd1SGireesh Nagabhushana 	}
157156b2bdd1SGireesh Nagabhushana 
157256b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true);
157356b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
157456b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc);
157556b2bdd1SGireesh Nagabhushana 		goto done;
157656b2bdd1SGireesh Nagabhushana 	}
157756b2bdd1SGireesh Nagabhushana 
157856b2bdd1SGireesh Nagabhushana 	/* all ok */
157956b2bdd1SGireesh Nagabhushana 	setbit(&sc->open_device_map, pi->port_id);
158056b2bdd1SGireesh Nagabhushana done:
158156b2bdd1SGireesh Nagabhushana 	if (rc != 0)
158256b2bdd1SGireesh Nagabhushana 		(void) t4_uninit_synchronized(pi);
158356b2bdd1SGireesh Nagabhushana 
158456b2bdd1SGireesh Nagabhushana 	return (rc);
158556b2bdd1SGireesh Nagabhushana }
158656b2bdd1SGireesh Nagabhushana 
158756b2bdd1SGireesh Nagabhushana /*
158856b2bdd1SGireesh Nagabhushana  * Idempotent.
158956b2bdd1SGireesh Nagabhushana  */
159056b2bdd1SGireesh Nagabhushana static int
159156b2bdd1SGireesh Nagabhushana t4_uninit_synchronized(struct port_info *pi)
159256b2bdd1SGireesh Nagabhushana {
159356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
159456b2bdd1SGireesh Nagabhushana 	int rc;
159556b2bdd1SGireesh Nagabhushana 
159656b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
159756b2bdd1SGireesh Nagabhushana 
159856b2bdd1SGireesh Nagabhushana 	/*
159956b2bdd1SGireesh Nagabhushana 	 * Disable the VI so that all its data in either direction is discarded
160056b2bdd1SGireesh Nagabhushana 	 * by the MPS.  Leave everything else (the queues, interrupts, and 1Hz
160156b2bdd1SGireesh Nagabhushana 	 * tick) intact as the TP can deliver negative advice or data that it's
160256b2bdd1SGireesh Nagabhushana 	 * holding in its RAM (for an offloaded connection) even after the VI is
160356b2bdd1SGireesh Nagabhushana 	 * disabled.
160456b2bdd1SGireesh Nagabhushana 	 */
160556b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false);
160656b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
160756b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc);
160856b2bdd1SGireesh Nagabhushana 		return (rc);
160956b2bdd1SGireesh Nagabhushana 	}
161056b2bdd1SGireesh Nagabhushana 
161156b2bdd1SGireesh Nagabhushana 	disable_port_queues(pi);
161256b2bdd1SGireesh Nagabhushana 
161356b2bdd1SGireesh Nagabhushana 	clrbit(&sc->open_device_map, pi->port_id);
161456b2bdd1SGireesh Nagabhushana 
161556b2bdd1SGireesh Nagabhushana 	pi->link_cfg.link_ok = 0;
161656b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, LINK_STATE_UNKNOWN);
161756b2bdd1SGireesh Nagabhushana 
161856b2bdd1SGireesh Nagabhushana 	return (0);
161956b2bdd1SGireesh Nagabhushana }
162056b2bdd1SGireesh Nagabhushana 
162156b2bdd1SGireesh Nagabhushana static void
162256b2bdd1SGireesh Nagabhushana propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph)
162356b2bdd1SGireesh Nagabhushana {
162456b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
162556b2bdd1SGireesh Nagabhushana 	struct driver_properties *p = &sc->props;
162656b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
162756b2bdd1SGireesh Nagabhushana 	int v;
162856b2bdd1SGireesh Nagabhushana 	char str[16];
162956b2bdd1SGireesh Nagabhushana 
163056b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
163156b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g;
163256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
163356b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g;
163456b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
163556b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
163656b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
163756b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
163856b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
1639*6feac2e3SRahul Lakkireddy 		v = (lc->pcaps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
164056b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
1641*6feac2e3SRahul Lakkireddy 		v = (lc->pcaps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
164256b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
164356b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
164456b2bdd1SGireesh Nagabhushana 		v = ETHERMTU;
164556b2bdd1SGireesh Nagabhushana #endif
164656b2bdd1SGireesh Nagabhushana 	else
164756b2bdd1SGireesh Nagabhushana 		return;
164856b2bdd1SGireesh Nagabhushana 
164956b2bdd1SGireesh Nagabhushana 	(void) snprintf(str, sizeof (str), "%d", v);
165056b2bdd1SGireesh Nagabhushana 	mac_prop_info_set_default_str(ph, str);
165156b2bdd1SGireesh Nagabhushana }
165256b2bdd1SGireesh Nagabhushana 
165356b2bdd1SGireesh Nagabhushana static int
165456b2bdd1SGireesh Nagabhushana getprop(struct port_info *pi, const char *name, uint_t size, void *val)
165556b2bdd1SGireesh Nagabhushana {
165656b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
165756b2bdd1SGireesh Nagabhushana 	int v;
165856b2bdd1SGireesh Nagabhushana 
165956b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
166056b2bdd1SGireesh Nagabhushana 		v = pi->tmr_idx;
166156b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
166256b2bdd1SGireesh Nagabhushana 		v = pi->pktc_idx;
166356b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
166456b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
166556b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
166656b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
166756b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
1668*6feac2e3SRahul Lakkireddy 		v = (lc->link_caps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
166956b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
1670*6feac2e3SRahul Lakkireddy 		v = (lc->link_caps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
167156b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
167256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
167356b2bdd1SGireesh Nagabhushana 		v = pi->mtu;
167456b2bdd1SGireesh Nagabhushana #endif
167556b2bdd1SGireesh Nagabhushana 	else
167656b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
167756b2bdd1SGireesh Nagabhushana 
167856b2bdd1SGireesh Nagabhushana 	(void) snprintf(val, size, "%d", v);
167956b2bdd1SGireesh Nagabhushana 	return (0);
168056b2bdd1SGireesh Nagabhushana }
168156b2bdd1SGireesh Nagabhushana 
168256b2bdd1SGireesh Nagabhushana static int
168356b2bdd1SGireesh Nagabhushana setprop(struct port_info *pi, const char *name, const void *val)
168456b2bdd1SGireesh Nagabhushana {
1685*6feac2e3SRahul Lakkireddy 	struct link_config *lc = &pi->link_cfg;
1686*6feac2e3SRahul Lakkireddy 	fw_port_cap32_t new_caps = lc->admin_caps;
168756b2bdd1SGireesh Nagabhushana 	int i, rc = 0, relink = 0, rx_mode = 0;
1688*6feac2e3SRahul Lakkireddy 	struct adapter *sc = pi->adapter;
168956b2bdd1SGireesh Nagabhushana 	struct sge_rxq *rxq;
1690*6feac2e3SRahul Lakkireddy 	cc_pause_t fc = 0;
1691*6feac2e3SRahul Lakkireddy 	long v;
169256b2bdd1SGireesh Nagabhushana 
169356b2bdd1SGireesh Nagabhushana 	(void) ddi_strtol(val, NULL, 0, &v);
169456b2bdd1SGireesh Nagabhushana 
169556b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0) {
169656b2bdd1SGireesh Nagabhushana 		if (v < 0 || v >= SGE_NTIMERS)
169756b2bdd1SGireesh Nagabhushana 			return (EINVAL);
169856b2bdd1SGireesh Nagabhushana 		if (v == pi->tmr_idx)
169956b2bdd1SGireesh Nagabhushana 			return (0);
170056b2bdd1SGireesh Nagabhushana 
170156b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
170256b2bdd1SGireesh Nagabhushana 		pi->tmr_idx = v;
170356b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
170456b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) |
170556b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(pi->pktc_idx >= 0);
170656b2bdd1SGireesh Nagabhushana 		}
170756b2bdd1SGireesh Nagabhushana 
170856b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_PKTC_IDX) == 0) {
170956b2bdd1SGireesh Nagabhushana 		if (v >= SGE_NCOUNTERS)
171056b2bdd1SGireesh Nagabhushana 			return (EINVAL);
171156b2bdd1SGireesh Nagabhushana 		if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1))
171256b2bdd1SGireesh Nagabhushana 			return (0);
171356b2bdd1SGireesh Nagabhushana 
171456b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
171556b2bdd1SGireesh Nagabhushana 		pi->pktc_idx = v < 0 ? -1 : v;
171656b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
171756b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) |
171856b2bdd1SGireesh Nagabhushana 			    /* takes effect right away */
171956b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(v >= 0);
172056b2bdd1SGireesh Nagabhushana 			/* LINTED: E_ASSIGN_NARROW_CONV */
172156b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */
172256b2bdd1SGireesh Nagabhushana 		}
172356b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_CSUM) == 0) {
172456b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
172556b2bdd1SGireesh Nagabhushana 			return (EINVAL);
172656b2bdd1SGireesh Nagabhushana 		if (v == 1)
172756b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_CSUM;
172856b2bdd1SGireesh Nagabhushana 		else
172956b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_CSUM;
173056b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_LSO) == 0) {
173156b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
173256b2bdd1SGireesh Nagabhushana 			return (EINVAL);
173356b2bdd1SGireesh Nagabhushana 		if (v == 1)
173456b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_LSO;
173556b2bdd1SGireesh Nagabhushana 		else
173656b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_LSO;
173756b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_TX_PAUSE) == 0) {
173856b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
173956b2bdd1SGireesh Nagabhushana 			return (EINVAL);
174056b2bdd1SGireesh Nagabhushana 
1741*6feac2e3SRahul Lakkireddy 		if ((new_caps & FW_PORT_CAP32_FC_TX) && (v == 1))
1742*6feac2e3SRahul Lakkireddy 			fc |= PAUSE_TX;
1743*6feac2e3SRahul Lakkireddy 		if (new_caps & FW_PORT_CAP32_FC_RX)
1744*6feac2e3SRahul Lakkireddy 			fc |= PAUSE_RX;
1745*6feac2e3SRahul Lakkireddy 		if (lc->admin_caps & FW_PORT_CAP32_ANEG)
1746*6feac2e3SRahul Lakkireddy 			fc |= PAUSE_AUTONEG;
174756b2bdd1SGireesh Nagabhushana 
1748*6feac2e3SRahul Lakkireddy 		t4_link_set_pause(pi, fc, &new_caps);
174956b2bdd1SGireesh Nagabhushana 		relink = 1;
175056b2bdd1SGireesh Nagabhushana 
175156b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_RX_PAUSE) == 0) {
175256b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
175356b2bdd1SGireesh Nagabhushana 			return (EINVAL);
175456b2bdd1SGireesh Nagabhushana 
1755*6feac2e3SRahul Lakkireddy 		if (new_caps & FW_PORT_CAP32_FC_TX)
1756*6feac2e3SRahul Lakkireddy 			fc |= PAUSE_TX;
1757*6feac2e3SRahul Lakkireddy 		if ((new_caps & FW_PORT_CAP32_FC_RX) && (v == 1))
1758*6feac2e3SRahul Lakkireddy 			fc |= PAUSE_RX;
1759*6feac2e3SRahul Lakkireddy 		if (lc->admin_caps & FW_PORT_CAP32_ANEG)
1760*6feac2e3SRahul Lakkireddy 			fc |= PAUSE_AUTONEG;
176156b2bdd1SGireesh Nagabhushana 
1762*6feac2e3SRahul Lakkireddy 		t4_link_set_pause(pi, fc, &new_caps);
176356b2bdd1SGireesh Nagabhushana 		relink = 1;
176456b2bdd1SGireesh Nagabhushana 	}
176556b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
176656b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0) {
176756b2bdd1SGireesh Nagabhushana 		if (v < 46 || v > MAX_MTU)
176856b2bdd1SGireesh Nagabhushana 			return (EINVAL);
176956b2bdd1SGireesh Nagabhushana 		if (v == pi->mtu)
177056b2bdd1SGireesh Nagabhushana 			return (0);
177156b2bdd1SGireesh Nagabhushana 
177256b2bdd1SGireesh Nagabhushana 		pi->mtu = (int)v;
177356b2bdd1SGireesh Nagabhushana 		(void) mac_maxsdu_update(pi->mh, v);
177456b2bdd1SGireesh Nagabhushana 		rx_mode = 1;
177556b2bdd1SGireesh Nagabhushana 	}
177656b2bdd1SGireesh Nagabhushana #endif
177756b2bdd1SGireesh Nagabhushana 	else
177856b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
177956b2bdd1SGireesh Nagabhushana 
178056b2bdd1SGireesh Nagabhushana 	if (!(relink || rx_mode))
178156b2bdd1SGireesh Nagabhushana 		return (0);
178256b2bdd1SGireesh Nagabhushana 
178356b2bdd1SGireesh Nagabhushana 	/* If we are here, either relink or rx_mode is 1 */
178456b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
178556b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
178656b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
178756b2bdd1SGireesh Nagabhushana 			if (rc != 0)
178856b2bdd1SGireesh Nagabhushana 				return (rc);
1789*6feac2e3SRahul Lakkireddy 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
1790*6feac2e3SRahul Lakkireddy 					    new_caps);
179156b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
179256b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
179356b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
1794*6feac2e3SRahul Lakkireddy 					    "%s link config failed: %d",
1795*6feac2e3SRahul Lakkireddy 					    __func__, rc);
1796*6feac2e3SRahul Lakkireddy 				return (rc);
179756b2bdd1SGireesh Nagabhushana 			}
179856b2bdd1SGireesh Nagabhushana 		} else if (rx_mode != 0) {
179956b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
180056b2bdd1SGireesh Nagabhushana 			if (rc != 0)
180156b2bdd1SGireesh Nagabhushana 				return (rc);
180256b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1,
180356b2bdd1SGireesh Nagabhushana 			    -1, -1, false);
180456b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
180556b2bdd1SGireesh Nagabhushana 			if (rc != 0)  {
180656b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
1807*6feac2e3SRahul Lakkireddy 					    "set_rxmode failed: %d", rc);
1808*6feac2e3SRahul Lakkireddy 				return (rc);
180956b2bdd1SGireesh Nagabhushana 			}
181056b2bdd1SGireesh Nagabhushana 		}
181156b2bdd1SGireesh Nagabhushana 	}
181256b2bdd1SGireesh Nagabhushana 
1813*6feac2e3SRahul Lakkireddy 	if (relink != 0)
1814*6feac2e3SRahul Lakkireddy 		lc->admin_caps = new_caps;
1815*6feac2e3SRahul Lakkireddy 
181656b2bdd1SGireesh Nagabhushana 	return (0);
181756b2bdd1SGireesh Nagabhushana }
181856b2bdd1SGireesh Nagabhushana 
181956b2bdd1SGireesh Nagabhushana void
182056b2bdd1SGireesh Nagabhushana t4_mc_init(struct port_info *pi)
182156b2bdd1SGireesh Nagabhushana {
182256b2bdd1SGireesh Nagabhushana 	pi->props = t4_priv_props;
182356b2bdd1SGireesh Nagabhushana }
182456b2bdd1SGireesh Nagabhushana 
18253dde7c95SVishal Kulkarni void
18263dde7c95SVishal Kulkarni t4_mc_cb_init(struct port_info *pi)
18273dde7c95SVishal Kulkarni {
18283dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
18293dde7c95SVishal Kulkarni 		pi->mc = &t4_m_ring_callbacks;
18303dde7c95SVishal Kulkarni 	else
18313dde7c95SVishal Kulkarni 		pi->mc = &t4_m_callbacks;
18323dde7c95SVishal Kulkarni }
18333dde7c95SVishal Kulkarni 
183456b2bdd1SGireesh Nagabhushana void
183556b2bdd1SGireesh Nagabhushana t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
183656b2bdd1SGireesh Nagabhushana {
183756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = sc->port[idx];
183856b2bdd1SGireesh Nagabhushana 
183956b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN);
184056b2bdd1SGireesh Nagabhushana }
184156b2bdd1SGireesh Nagabhushana 
184256b2bdd1SGireesh Nagabhushana /* ARGSUSED */
184356b2bdd1SGireesh Nagabhushana void
184456b2bdd1SGireesh Nagabhushana t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m)
184556b2bdd1SGireesh Nagabhushana {
184656b2bdd1SGireesh Nagabhushana 	mac_rx(pi->mh, NULL, m);
184756b2bdd1SGireesh Nagabhushana }
18483dde7c95SVishal Kulkarni 
18493dde7c95SVishal Kulkarni void
18503dde7c95SVishal Kulkarni t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq)
18513dde7c95SVishal Kulkarni {
18523dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
18533dde7c95SVishal Kulkarni 		mac_tx_ring_update(pi->mh, txq->ring_handle);
18543dde7c95SVishal Kulkarni 	else
18553dde7c95SVishal Kulkarni 		mac_tx_update(pi->mh);
18563dde7c95SVishal Kulkarni }
1857