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 
2356b2bdd1SGireesh Nagabhushana #include <sys/ddi.h>
2456b2bdd1SGireesh Nagabhushana #include <sys/sunddi.h>
2556b2bdd1SGireesh Nagabhushana #include <sys/dlpi.h>
2656b2bdd1SGireesh Nagabhushana #include <sys/mac_provider.h>
2756b2bdd1SGireesh Nagabhushana #include <sys/mac_ether.h>
2856b2bdd1SGireesh Nagabhushana #include <sys/strsubr.h>
2956b2bdd1SGireesh Nagabhushana #include <sys/queue.h>
3056b2bdd1SGireesh Nagabhushana 
3156b2bdd1SGireesh Nagabhushana #include "common/common.h"
3256b2bdd1SGireesh Nagabhushana #include "common/t4_regs.h"
3356b2bdd1SGireesh Nagabhushana 
3456b2bdd1SGireesh Nagabhushana static int t4_mc_getstat(void *arg, uint_t stat, uint64_t *val);
3556b2bdd1SGireesh Nagabhushana static int t4_mc_start(void *arg);
3656b2bdd1SGireesh Nagabhushana static void t4_mc_stop(void *arg);
3756b2bdd1SGireesh Nagabhushana static int t4_mc_setpromisc(void *arg, boolean_t on);
3856b2bdd1SGireesh Nagabhushana static int t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr);
3956b2bdd1SGireesh Nagabhushana static int t4_mc_unicst(void *arg, const uint8_t *ucaddr);
4056b2bdd1SGireesh Nagabhushana static boolean_t t4_mc_getcapab(void *arg, mac_capab_t cap, void *data);
4156b2bdd1SGireesh Nagabhushana static int t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id,
4256b2bdd1SGireesh Nagabhushana     uint_t size, const void *val);
4356b2bdd1SGireesh Nagabhushana static int t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id,
4456b2bdd1SGireesh Nagabhushana     uint_t size, void *val);
4556b2bdd1SGireesh Nagabhushana static void t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
4656b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph);
4756b2bdd1SGireesh Nagabhushana 
4856b2bdd1SGireesh Nagabhushana static int t4_init_synchronized(struct port_info *pi);
4956b2bdd1SGireesh Nagabhushana static int t4_uninit_synchronized(struct port_info *pi);
5056b2bdd1SGireesh Nagabhushana static void propinfo(struct port_info *pi, const char *name,
5156b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph);
5256b2bdd1SGireesh Nagabhushana static int getprop(struct port_info *pi, const char *name, uint_t size,
5356b2bdd1SGireesh Nagabhushana     void *val);
5456b2bdd1SGireesh Nagabhushana static int setprop(struct port_info *pi, const char *name, const void *val);
5556b2bdd1SGireesh Nagabhushana 
5656b2bdd1SGireesh Nagabhushana mac_callbacks_t t4_m_callbacks = {
5756b2bdd1SGireesh Nagabhushana 	.mc_callbacks	= MC_GETCAPAB | MC_PROPERTIES,
5856b2bdd1SGireesh Nagabhushana 	.mc_getstat	= t4_mc_getstat,
5956b2bdd1SGireesh Nagabhushana 	.mc_start	= t4_mc_start,
6056b2bdd1SGireesh Nagabhushana 	.mc_stop	= t4_mc_stop,
6156b2bdd1SGireesh Nagabhushana 	.mc_setpromisc	= t4_mc_setpromisc,
6256b2bdd1SGireesh Nagabhushana 	.mc_multicst	= t4_mc_multicst,
633dde7c95SVishal Kulkarni 	.mc_unicst =    t4_mc_unicst,
643dde7c95SVishal Kulkarni 	.mc_tx =        t4_mc_tx,
653dde7c95SVishal Kulkarni 	.mc_getcapab =	t4_mc_getcapab,
663dde7c95SVishal Kulkarni 	.mc_setprop =	t4_mc_setprop,
673dde7c95SVishal Kulkarni 	.mc_getprop =	t4_mc_getprop,
683dde7c95SVishal Kulkarni 	.mc_propinfo =	t4_mc_propinfo,
693dde7c95SVishal Kulkarni };
703dde7c95SVishal Kulkarni 
713dde7c95SVishal Kulkarni /* I couldn't comeup with a better idea of not redefine
723dde7c95SVishal Kulkarni  * another strcture and instead somehow reuse the earlier
733dde7c95SVishal Kulkarni  * above structure and modify its members.
743dde7c95SVishal Kulkarni  */
753dde7c95SVishal Kulkarni mac_callbacks_t t4_m_ring_callbacks = {
763dde7c95SVishal Kulkarni 	.mc_callbacks =	MC_GETCAPAB | MC_PROPERTIES,
773dde7c95SVishal Kulkarni 	.mc_getstat =	t4_mc_getstat,
783dde7c95SVishal Kulkarni 	.mc_start =	t4_mc_start,
793dde7c95SVishal Kulkarni 	.mc_stop =	t4_mc_stop,
803dde7c95SVishal Kulkarni 	.mc_setpromisc =t4_mc_setpromisc,
813dde7c95SVishal Kulkarni 	.mc_multicst =	t4_mc_multicst,
823dde7c95SVishal Kulkarni 	.mc_unicst =    NULL, /* t4_addmac */
833dde7c95SVishal Kulkarni 	.mc_tx =        NULL, /* t4_eth_tx */
8456b2bdd1SGireesh Nagabhushana 	.mc_getcapab	= t4_mc_getcapab,
8556b2bdd1SGireesh Nagabhushana 	.mc_setprop	= t4_mc_setprop,
8656b2bdd1SGireesh Nagabhushana 	.mc_getprop	= t4_mc_getprop,
8756b2bdd1SGireesh Nagabhushana 	.mc_propinfo	= t4_mc_propinfo,
8856b2bdd1SGireesh Nagabhushana };
8956b2bdd1SGireesh Nagabhushana 
9056b2bdd1SGireesh Nagabhushana #define	T4PROP_TMR_IDX "_holdoff_timer_idx"
9156b2bdd1SGireesh Nagabhushana #define	T4PROP_PKTC_IDX "_holdoff_pktc_idx"
9256b2bdd1SGireesh Nagabhushana #define	T4PROP_MTU "_mtu"
9356b2bdd1SGireesh Nagabhushana #define	T4PROP_HW_CSUM	"_hw_csum"
9456b2bdd1SGireesh Nagabhushana #define	T4PROP_HW_LSO	"_hw_lso"
9556b2bdd1SGireesh Nagabhushana #define	T4PROP_TX_PAUSE	"_tx_pause"
9656b2bdd1SGireesh Nagabhushana #define	T4PROP_RX_PAUSE	"_rx_pause"
9756b2bdd1SGireesh Nagabhushana 
9856b2bdd1SGireesh Nagabhushana char *t4_priv_props[] = {
9956b2bdd1SGireesh Nagabhushana 	T4PROP_TMR_IDX,
10056b2bdd1SGireesh Nagabhushana 	T4PROP_PKTC_IDX,
10156b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
10256b2bdd1SGireesh Nagabhushana 	/* MAC_VERSION 1 doesn't seem to use MAC_PROP_MTU, hmmmm */
10356b2bdd1SGireesh Nagabhushana 	T4PROP_MTU,
10456b2bdd1SGireesh Nagabhushana #endif
10556b2bdd1SGireesh Nagabhushana 	T4PROP_HW_CSUM,
10656b2bdd1SGireesh Nagabhushana 	T4PROP_HW_LSO,
10756b2bdd1SGireesh Nagabhushana 	T4PROP_TX_PAUSE,
10856b2bdd1SGireesh Nagabhushana 	T4PROP_RX_PAUSE,
10956b2bdd1SGireesh Nagabhushana 	NULL
11056b2bdd1SGireesh Nagabhushana };
11156b2bdd1SGireesh Nagabhushana 
11256b2bdd1SGireesh Nagabhushana static int
11356b2bdd1SGireesh Nagabhushana t4_mc_getstat(void *arg, uint_t stat, uint64_t *val)
11456b2bdd1SGireesh Nagabhushana {
11556b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
11656b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
11756b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
11856b2bdd1SGireesh Nagabhushana 
11956b2bdd1SGireesh Nagabhushana #define	GET_STAT(name) \
12056b2bdd1SGireesh Nagabhushana 	t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
12156b2bdd1SGireesh Nagabhushana 
12256b2bdd1SGireesh Nagabhushana 	switch (stat) {
12356b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IFSPEED:
12456b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
12556b2bdd1SGireesh Nagabhushana 			*val = lc->speed;
12656b2bdd1SGireesh Nagabhushana 			*val *= 1000000;
12756b2bdd1SGireesh Nagabhushana 		} else
12856b2bdd1SGireesh Nagabhushana 			*val = 0;
12956b2bdd1SGireesh Nagabhushana 		break;
13056b2bdd1SGireesh Nagabhushana 
13156b2bdd1SGireesh Nagabhushana 	case MAC_STAT_MULTIRCV:
13256b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MCAST);
13356b2bdd1SGireesh Nagabhushana 		break;
13456b2bdd1SGireesh Nagabhushana 
13556b2bdd1SGireesh Nagabhushana 	case MAC_STAT_BRDCSTRCV:
13656b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_BCAST);
13756b2bdd1SGireesh Nagabhushana 		break;
13856b2bdd1SGireesh Nagabhushana 
13956b2bdd1SGireesh Nagabhushana 	case MAC_STAT_MULTIXMT:
14056b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_MCAST);
14156b2bdd1SGireesh Nagabhushana 		break;
14256b2bdd1SGireesh Nagabhushana 
14356b2bdd1SGireesh Nagabhushana 	case MAC_STAT_BRDCSTXMT:
14456b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_BCAST);
14556b2bdd1SGireesh Nagabhushana 		break;
14656b2bdd1SGireesh Nagabhushana 
14756b2bdd1SGireesh Nagabhushana 	case MAC_STAT_NORCVBUF:
14856b2bdd1SGireesh Nagabhushana 		*val = 0;	/* TODO should come from rxq->nomem */
14956b2bdd1SGireesh Nagabhushana 		break;
15056b2bdd1SGireesh Nagabhushana 
15156b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IERRORS:
15256b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR) +
15356b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_MTU_CRC_ERROR) +
15456b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_CRC_ERROR) +
15556b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LEN_ERROR) +
15656b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_SYM_ERROR) +
15756b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LESS_64B);
15856b2bdd1SGireesh Nagabhushana 		break;
15956b2bdd1SGireesh Nagabhushana 
16056b2bdd1SGireesh Nagabhushana 	case MAC_STAT_UNKNOWNS:
16156b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
16256b2bdd1SGireesh Nagabhushana 
16356b2bdd1SGireesh Nagabhushana 	case MAC_STAT_NOXMTBUF:
16456b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_DROP);
16556b2bdd1SGireesh Nagabhushana 		break;
16656b2bdd1SGireesh Nagabhushana 
16756b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OERRORS:
16856b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_ERROR);
16956b2bdd1SGireesh Nagabhushana 		break;
17056b2bdd1SGireesh Nagabhushana 
17156b2bdd1SGireesh Nagabhushana 	case MAC_STAT_COLLISIONS:
17256b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
17356b2bdd1SGireesh Nagabhushana 
17456b2bdd1SGireesh Nagabhushana 	case MAC_STAT_RBYTES:
17556b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_BYTES);
17656b2bdd1SGireesh Nagabhushana 		break;
17756b2bdd1SGireesh Nagabhushana 
17856b2bdd1SGireesh Nagabhushana 	case MAC_STAT_IPACKETS:
17956b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_FRAMES);
18056b2bdd1SGireesh Nagabhushana 		break;
18156b2bdd1SGireesh Nagabhushana 
18256b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OBYTES:
18356b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_BYTES);
18456b2bdd1SGireesh Nagabhushana 		break;
18556b2bdd1SGireesh Nagabhushana 
18656b2bdd1SGireesh Nagabhushana 	case MAC_STAT_OPACKETS:
18756b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_FRAMES);
18856b2bdd1SGireesh Nagabhushana 		break;
18956b2bdd1SGireesh Nagabhushana 
19056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ALIGN_ERRORS:
19156b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
19256b2bdd1SGireesh Nagabhushana 
19356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_FCS_ERRORS:
19456b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_CRC_ERROR);
19556b2bdd1SGireesh Nagabhushana 		break;
19656b2bdd1SGireesh Nagabhushana 
19756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_FIRST_COLLISIONS:
19856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MULTI_COLLISIONS:
19956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_SQE_ERRORS:
20056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_DEFER_XMTS:
20156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_TX_LATE_COLLISIONS:
20256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_EX_COLLISIONS:
20356b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
20456b2bdd1SGireesh Nagabhushana 
20556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MACXMT_ERRORS:
20656b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(TX_PORT_ERROR);
20756b2bdd1SGireesh Nagabhushana 		break;
20856b2bdd1SGireesh Nagabhushana 
20956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CARRIER_ERRORS:
21056b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
21156b2bdd1SGireesh Nagabhushana 
21256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_TOOLONG_ERRORS:
21356b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR);
21456b2bdd1SGireesh Nagabhushana 		break;
21556b2bdd1SGireesh Nagabhushana 
21656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_MACRCV_ERRORS:
21756b2bdd1SGireesh Nagabhushana 		*val = GET_STAT(RX_PORT_MTU_ERROR) +
21856b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_MTU_CRC_ERROR) +
21956b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_CRC_ERROR) +
22056b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LEN_ERROR) +
22156b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_SYM_ERROR) +
22256b2bdd1SGireesh Nagabhushana 		    GET_STAT(RX_PORT_LESS_64B);
22356b2bdd1SGireesh Nagabhushana 		break;
22456b2bdd1SGireesh Nagabhushana 
22556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_ADDR:
22656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_ID:
22756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_XCVR_INUSE:
22856b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
22956b2bdd1SGireesh Nagabhushana 
2303dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_100GFDX:
231*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G);
2323dde7c95SVishal Kulkarni 		break;
2333dde7c95SVishal Kulkarni 
2343dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_40GFDX:
235*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
2363dde7c95SVishal Kulkarni 		break;
2373dde7c95SVishal Kulkarni 
2383dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_25GFDX:
239*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
2403dde7c95SVishal Kulkarni 		break;
2413dde7c95SVishal Kulkarni 
2423dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_10GFDX:
243*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
2443dde7c95SVishal Kulkarni 		break;
2453dde7c95SVishal Kulkarni 
24656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_1000FDX:
247*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
24856b2bdd1SGireesh Nagabhushana 		break;
24956b2bdd1SGireesh Nagabhushana 
25056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_1000HDX:
25156b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
25256b2bdd1SGireesh Nagabhushana 
25356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100FDX:
254*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
25556b2bdd1SGireesh Nagabhushana 		break;
25656b2bdd1SGireesh Nagabhushana 
25756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100HDX:
25856b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
25956b2bdd1SGireesh Nagabhushana 
26056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_10FDX:
26156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_10HDX:
26256b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
26356b2bdd1SGireesh Nagabhushana 
26456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_ASMPAUSE:
26556b2bdd1SGireesh Nagabhushana 		*val = 0;
26656b2bdd1SGireesh Nagabhushana 		break;
26756b2bdd1SGireesh Nagabhushana 
26856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_PAUSE:
26956b2bdd1SGireesh Nagabhushana 		*val = 1;
27056b2bdd1SGireesh Nagabhushana 		break;
27156b2bdd1SGireesh Nagabhushana 
27256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_AUTONEG:
273*7e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_ANEG);
27456b2bdd1SGireesh Nagabhushana 		break;
27556b2bdd1SGireesh Nagabhushana 
27656b2bdd1SGireesh Nagabhushana 	/*
27756b2bdd1SGireesh Nagabhushana 	 * We have set flow control configuration based on tx_pause and rx_pause
27856b2bdd1SGireesh Nagabhushana 	 * values supported through ndd. Now, we need to translate the settings
27956b2bdd1SGireesh Nagabhushana 	 * we have in link_config structure to adv_cap_asmpause and
28056b2bdd1SGireesh Nagabhushana 	 * adv_cap_pause.
28156b2bdd1SGireesh Nagabhushana 	 *
28256b2bdd1SGireesh Nagabhushana 	 * There are 4 combinations possible and the translation is as below:
28356b2bdd1SGireesh Nagabhushana 	 * tx_pause = 0 => We don't send pause frames during Rx congestion
28456b2bdd1SGireesh Nagabhushana 	 * tx_pause = 1 => We send pause frames during Rx congestion
28556b2bdd1SGireesh Nagabhushana 	 * rx_pause = 0 => We ignore received pause frames
28656b2bdd1SGireesh Nagabhushana 	 * rx_pause = 1 => We pause transmission when we receive pause frames
28756b2bdd1SGireesh Nagabhushana 	 *
28856b2bdd1SGireesh Nagabhushana 	 * +----------------------------+----------------------------------+
28956b2bdd1SGireesh Nagabhushana 	 * |  tx_pause	|    rx_pause	| adv_cap_asmpause | adv_cap_pause |
29056b2bdd1SGireesh Nagabhushana 	 * +-------------------------+-------------------------------------+
29156b2bdd1SGireesh Nagabhushana 	 * |	0	|	0	|	0	   |	0	   |
29256b2bdd1SGireesh Nagabhushana 	 * |	0	|	1	|	1	   |	0	   |
29356b2bdd1SGireesh Nagabhushana 	 * |	1	|	0	|	1	   |	1	   |
29456b2bdd1SGireesh Nagabhushana 	 * |	1	|	1	|	0	   |	1	   |
29556b2bdd1SGireesh Nagabhushana 	 * +----------------------------+----------------------------------+
29656b2bdd1SGireesh Nagabhushana 	 */
29756b2bdd1SGireesh Nagabhushana 
29856b2bdd1SGireesh Nagabhushana 	/* Advertised asymmetric pause capability */
29956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_ASMPAUSE:
30056b2bdd1SGireesh Nagabhushana 		*val = (((lc->requested_fc & PAUSE_TX) ? 1 : 0) ^
30156b2bdd1SGireesh Nagabhushana 		    (lc->requested_fc & PAUSE_RX));
30256b2bdd1SGireesh Nagabhushana 		break;
30356b2bdd1SGireesh Nagabhushana 
30456b2bdd1SGireesh Nagabhushana 	/* Advertised pause capability */
30556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_PAUSE:
30656b2bdd1SGireesh Nagabhushana 		*val = (lc->requested_fc & PAUSE_TX) ? 1 : 0;
30756b2bdd1SGireesh Nagabhushana 		break;
30856b2bdd1SGireesh Nagabhushana 
3093dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_100GFDX:
310*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_100G);
3113dde7c95SVishal Kulkarni 		break;
3123dde7c95SVishal Kulkarni 
3133dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_40GFDX:
314*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_40G);
3153dde7c95SVishal Kulkarni 		break;
3163dde7c95SVishal Kulkarni 
3173dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_25GFDX:
318*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_25G);
3193dde7c95SVishal Kulkarni 		break;
3203dde7c95SVishal Kulkarni 
3213dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_10GFDX:
322*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_10G);
3233dde7c95SVishal Kulkarni 		break;
3243dde7c95SVishal Kulkarni 
32556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000FDX:
326*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_1G);
3273dde7c95SVishal Kulkarni 		break;
3283dde7c95SVishal Kulkarni 
3293dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_AUTONEG:
330*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_ANEG);
3313dde7c95SVishal Kulkarni 		break;
3323dde7c95SVishal Kulkarni 
33356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000HDX:
33456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_100FDX:
33556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_100HDX:
33656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10FDX:
33756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10HDX:
33856b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);	/* TODO */
33956b2bdd1SGireesh Nagabhushana 
3403dde7c95SVishal Kulkarni 
3413dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_100GFDX:
342*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_100G);
3433dde7c95SVishal Kulkarni 		break;
3443dde7c95SVishal Kulkarni 
3453dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_40GFDX:
346*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_40G);
3473dde7c95SVishal Kulkarni 		break;
3483dde7c95SVishal Kulkarni 
3493dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_25GFDX:
350*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_25G);
3513dde7c95SVishal Kulkarni 		break;
3523dde7c95SVishal Kulkarni 
3533dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_10GFDX:
354*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_10G);
3553dde7c95SVishal Kulkarni 		break;
3563dde7c95SVishal Kulkarni 
35756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000FDX:
358*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_1G);
3593dde7c95SVishal Kulkarni 		break;
3603dde7c95SVishal Kulkarni 
3613dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_AUTONEG:
362*7e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_ANEG);
3633dde7c95SVishal Kulkarni 		break;
3643dde7c95SVishal Kulkarni 
36556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000HDX:
36656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_100FDX:
36756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_100HDX:
36856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10FDX:
36956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10HDX:
37056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_ASMPAUSE:
37156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_PAUSE:
37256b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
37356b2bdd1SGireesh Nagabhushana 
37456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_ASMPAUSE:
37556b2bdd1SGireesh Nagabhushana 		*val = 0;
37656b2bdd1SGireesh Nagabhushana 		break;
37756b2bdd1SGireesh Nagabhushana 
37856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_PAUSE:
37956b2bdd1SGireesh Nagabhushana 		*val = 1;
38056b2bdd1SGireesh Nagabhushana 		break;
38156b2bdd1SGireesh Nagabhushana 
38256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_AUTONEG:
38356b2bdd1SGireesh Nagabhushana 		*val = lc->autoneg == AUTONEG_ENABLE;
38456b2bdd1SGireesh Nagabhushana 		break;
38556b2bdd1SGireesh Nagabhushana 
38656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_DUPLEX:
38756b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0)
38856b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_FULL;
38956b2bdd1SGireesh Nagabhushana 		else
39056b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_UNKNOWN;
39156b2bdd1SGireesh Nagabhushana 		break;
39256b2bdd1SGireesh Nagabhushana 
39356b2bdd1SGireesh Nagabhushana 	default:
39456b2bdd1SGireesh Nagabhushana #ifdef DEBUG
39556b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE, "stat %d not implemented.", stat);
39656b2bdd1SGireesh Nagabhushana #endif
39756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
39856b2bdd1SGireesh Nagabhushana 	}
39956b2bdd1SGireesh Nagabhushana #undef GET_STAT
40056b2bdd1SGireesh Nagabhushana 
40156b2bdd1SGireesh Nagabhushana 	return (0);
40256b2bdd1SGireesh Nagabhushana }
40356b2bdd1SGireesh Nagabhushana 
40456b2bdd1SGireesh Nagabhushana static int
40556b2bdd1SGireesh Nagabhushana t4_mc_start(void *arg)
40656b2bdd1SGireesh Nagabhushana {
40756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
40856b2bdd1SGireesh Nagabhushana 	int rc;
40956b2bdd1SGireesh Nagabhushana 
41056b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 0, 1);
41156b2bdd1SGireesh Nagabhushana 	if (rc != 0)
41256b2bdd1SGireesh Nagabhushana 		return (rc);
41356b2bdd1SGireesh Nagabhushana 	rc = t4_init_synchronized(pi);
41456b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
41556b2bdd1SGireesh Nagabhushana 
41656b2bdd1SGireesh Nagabhushana 	return (rc);
41756b2bdd1SGireesh Nagabhushana }
41856b2bdd1SGireesh Nagabhushana 
41956b2bdd1SGireesh Nagabhushana static void
42056b2bdd1SGireesh Nagabhushana t4_mc_stop(void *arg)
42156b2bdd1SGireesh Nagabhushana {
42256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
42356b2bdd1SGireesh Nagabhushana 
42456b2bdd1SGireesh Nagabhushana 	while (begin_synchronized_op(pi, 0, 1) != 0)
42556b2bdd1SGireesh Nagabhushana 		continue;
42656b2bdd1SGireesh Nagabhushana 	(void) t4_uninit_synchronized(pi);
42756b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
42856b2bdd1SGireesh Nagabhushana }
42956b2bdd1SGireesh Nagabhushana 
43056b2bdd1SGireesh Nagabhushana static int
43156b2bdd1SGireesh Nagabhushana t4_mc_setpromisc(void *arg, boolean_t on)
43256b2bdd1SGireesh Nagabhushana {
43356b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
43456b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
43556b2bdd1SGireesh Nagabhushana 	int rc;
43656b2bdd1SGireesh Nagabhushana 
43756b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
43856b2bdd1SGireesh Nagabhushana 	if (rc != 0)
43956b2bdd1SGireesh Nagabhushana 		return (rc);
44056b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
44156b2bdd1SGireesh Nagabhushana 	    false);
44256b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
44356b2bdd1SGireesh Nagabhushana 
44456b2bdd1SGireesh Nagabhushana 	return (rc);
44556b2bdd1SGireesh Nagabhushana }
44656b2bdd1SGireesh Nagabhushana 
44756b2bdd1SGireesh Nagabhushana /*
44856b2bdd1SGireesh Nagabhushana  * TODO: Starts failing as soon as the 336 entry table fills up.  Need to use
44956b2bdd1SGireesh Nagabhushana  * hash in that case.
45056b2bdd1SGireesh Nagabhushana  */
45156b2bdd1SGireesh Nagabhushana static int
45256b2bdd1SGireesh Nagabhushana t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
45356b2bdd1SGireesh Nagabhushana {
45456b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
45556b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
45656b2bdd1SGireesh Nagabhushana 	struct fw_vi_mac_cmd c;
45756b2bdd1SGireesh Nagabhushana 	int len16, rc;
45856b2bdd1SGireesh Nagabhushana 
45956b2bdd1SGireesh Nagabhushana 	len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
46056b2bdd1SGireesh Nagabhushana 	    sizeof (c.u.exact[0]), 16);
46156b2bdd1SGireesh Nagabhushana 	c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
46256b2bdd1SGireesh Nagabhushana 	    F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
46356b2bdd1SGireesh Nagabhushana 	c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
46456b2bdd1SGireesh Nagabhushana 	c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
46556b2bdd1SGireesh Nagabhushana 	    V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
46656b2bdd1SGireesh Nagabhushana 	    FW_VI_MAC_MAC_BASED_FREE));
46756b2bdd1SGireesh Nagabhushana 	bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
46856b2bdd1SGireesh Nagabhushana 
46956b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
47056b2bdd1SGireesh Nagabhushana 	if (rc != 0)
47156b2bdd1SGireesh Nagabhushana 		return (rc);
47256b2bdd1SGireesh Nagabhushana 	rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
47356b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
47456b2bdd1SGireesh Nagabhushana 	if (rc != 0)
47556b2bdd1SGireesh Nagabhushana 		return (rc);
47656b2bdd1SGireesh Nagabhushana #ifdef DEBUG
47756b2bdd1SGireesh Nagabhushana 	/*
47856b2bdd1SGireesh Nagabhushana 	 * TODO: Firmware doesn't seem to return the correct index on removal
47956b2bdd1SGireesh Nagabhushana 	 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
48056b2bdd1SGireesh Nagabhushana 	 * code once it is fixed.
48156b2bdd1SGireesh Nagabhushana 	 */
48256b2bdd1SGireesh Nagabhushana 	else {
48356b2bdd1SGireesh Nagabhushana 		uint16_t idx;
48456b2bdd1SGireesh Nagabhushana 
48556b2bdd1SGireesh Nagabhushana 		idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
48656b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE,
48756b2bdd1SGireesh Nagabhushana 		    "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
48856b2bdd1SGireesh Nagabhushana 		    mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
48956b2bdd1SGireesh Nagabhushana 		    add ? "added at index" : "removed from index", idx);
49056b2bdd1SGireesh Nagabhushana 	}
49156b2bdd1SGireesh Nagabhushana #endif
49256b2bdd1SGireesh Nagabhushana 
49356b2bdd1SGireesh Nagabhushana 	return (0);
49456b2bdd1SGireesh Nagabhushana }
49556b2bdd1SGireesh Nagabhushana 
4963dde7c95SVishal Kulkarni int
49756b2bdd1SGireesh Nagabhushana t4_mc_unicst(void *arg, const uint8_t *ucaddr)
49856b2bdd1SGireesh Nagabhushana {
49956b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
50056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
50156b2bdd1SGireesh Nagabhushana 	int rc;
50256b2bdd1SGireesh Nagabhushana 
5033dde7c95SVishal Kulkarni 	if (ucaddr == NULL)
5043dde7c95SVishal Kulkarni 		return (EINVAL);
5053dde7c95SVishal Kulkarni 
50656b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
50756b2bdd1SGireesh Nagabhushana 	if (rc != 0)
50856b2bdd1SGireesh Nagabhushana 		return (rc);
5093dde7c95SVishal Kulkarni 
5103dde7c95SVishal Kulkarni 	/* We will support adding only one mac address */
5113dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
5123dde7c95SVishal Kulkarni 		end_synchronized_op(pi, 1);
5133dde7c95SVishal Kulkarni 		return (ENOSPC);
5143dde7c95SVishal Kulkarni 	}
51556b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
516*7e6ad469SVishal Kulkarni 			   true, &pi->smt_idx);
51756b2bdd1SGireesh Nagabhushana 	if (rc < 0)
51856b2bdd1SGireesh Nagabhushana 		rc = -rc;
51956b2bdd1SGireesh Nagabhushana 	else {
5203dde7c95SVishal Kulkarni 		pi->macaddr_cnt++;
52156b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
52256b2bdd1SGireesh Nagabhushana 		rc = 0;
52356b2bdd1SGireesh Nagabhushana 	}
52456b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
52556b2bdd1SGireesh Nagabhushana 
52656b2bdd1SGireesh Nagabhushana 	return (rc);
52756b2bdd1SGireesh Nagabhushana }
52856b2bdd1SGireesh Nagabhushana 
5293dde7c95SVishal Kulkarni int
5303dde7c95SVishal Kulkarni t4_addmac(void *arg, const uint8_t *ucaddr)
5313dde7c95SVishal Kulkarni {
5323dde7c95SVishal Kulkarni 	return (t4_mc_unicst(arg, ucaddr));
5333dde7c95SVishal Kulkarni }
5343dde7c95SVishal Kulkarni 
5353dde7c95SVishal Kulkarni static int
5363dde7c95SVishal Kulkarni t4_remmac(void *arg, const uint8_t *mac_addr)
5373dde7c95SVishal Kulkarni {
5383dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
5393dde7c95SVishal Kulkarni 	int rc;
5403dde7c95SVishal Kulkarni 
5413dde7c95SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
5423dde7c95SVishal Kulkarni 	if (rc != 0)
5433dde7c95SVishal Kulkarni 		return (rc);
5443dde7c95SVishal Kulkarni 
5453dde7c95SVishal Kulkarni 	pi->macaddr_cnt--;
5463dde7c95SVishal Kulkarni 	end_synchronized_op(pi, 1);
5473dde7c95SVishal Kulkarni 
5483dde7c95SVishal Kulkarni 	return (0);
5493dde7c95SVishal Kulkarni }
5503dde7c95SVishal Kulkarni 
5513dde7c95SVishal Kulkarni /*
5523dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all groups.
5533dde7c95SVishal Kulkarni  */
5543dde7c95SVishal Kulkarni void
5553dde7c95SVishal Kulkarni t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
5563dde7c95SVishal Kulkarni 	      mac_group_info_t *infop, mac_group_handle_t gh)
5573dde7c95SVishal Kulkarni {
5583dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
5593dde7c95SVishal Kulkarni 
5603dde7c95SVishal Kulkarni 	switch (rtype) {
5613dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
5623dde7c95SVishal Kulkarni 		infop->mgi_driver = (mac_group_driver_t)arg;
5633dde7c95SVishal Kulkarni 		infop->mgi_start = NULL;
5643dde7c95SVishal Kulkarni 		infop->mgi_stop = NULL;
5653dde7c95SVishal Kulkarni 		infop->mgi_addmac = t4_addmac;
5663dde7c95SVishal Kulkarni 		infop->mgi_remmac = t4_remmac;
5673dde7c95SVishal Kulkarni 		infop->mgi_count = pi->nrxq;
5683dde7c95SVishal Kulkarni 		break;
5693dde7c95SVishal Kulkarni 	}
5703dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX:
5713dde7c95SVishal Kulkarni 	default:
5723dde7c95SVishal Kulkarni 		ASSERT(0);
5733dde7c95SVishal Kulkarni 		break;
5743dde7c95SVishal Kulkarni 	}
5753dde7c95SVishal Kulkarni }
5763dde7c95SVishal Kulkarni 
5773dde7c95SVishal Kulkarni static int
5783dde7c95SVishal Kulkarni t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
5793dde7c95SVishal Kulkarni {
5803dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
5813dde7c95SVishal Kulkarni 
5823dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
5833dde7c95SVishal Kulkarni 	rxq->ring_gen_num = mr_gen_num;
5843dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
5853dde7c95SVishal Kulkarni 	return (0);
5863dde7c95SVishal Kulkarni }
5873dde7c95SVishal Kulkarni 
5883dde7c95SVishal Kulkarni /*
5893dde7c95SVishal Kulkarni  * Enable interrupt on the specificed rx ring.
5903dde7c95SVishal Kulkarni  */
5913dde7c95SVishal Kulkarni int
5923dde7c95SVishal Kulkarni t4_ring_intr_enable(mac_intr_handle_t intrh)
5933dde7c95SVishal Kulkarni {
5943dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
5953dde7c95SVishal Kulkarni 	struct adapter *sc = rxq->port->adapter;
5963dde7c95SVishal Kulkarni 	struct sge_iq *iq;
5973dde7c95SVishal Kulkarni 
5983dde7c95SVishal Kulkarni 	iq = &rxq->iq;
5993dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6003dde7c95SVishal Kulkarni 	iq->polling = 0;
6013dde7c95SVishal Kulkarni 	iq->state = IQS_IDLE;
6023dde7c95SVishal Kulkarni 	t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
6033dde7c95SVishal Kulkarni 		     V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id));
6043dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6053dde7c95SVishal Kulkarni 	return (0);
6063dde7c95SVishal Kulkarni }
6073dde7c95SVishal Kulkarni 
6083dde7c95SVishal Kulkarni /*
6093dde7c95SVishal Kulkarni  * Disable interrupt on the specificed rx ring.
6103dde7c95SVishal Kulkarni  */
6113dde7c95SVishal Kulkarni int
6123dde7c95SVishal Kulkarni t4_ring_intr_disable(mac_intr_handle_t intrh)
6133dde7c95SVishal Kulkarni {
6143dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
6153dde7c95SVishal Kulkarni 	struct sge_iq *iq;
6163dde7c95SVishal Kulkarni 
6173dde7c95SVishal Kulkarni 	/* Nothing to be done here wrt interrupt, as it
6183dde7c95SVishal Kulkarni 	 * will not fire, until we write back to
6193dde7c95SVishal Kulkarni 	 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable.
6203dde7c95SVishal Kulkarni 	 */
6213dde7c95SVishal Kulkarni 
6223dde7c95SVishal Kulkarni 	iq = &rxq->iq;
6233dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6243dde7c95SVishal Kulkarni 	iq->polling = 1;
6253dde7c95SVishal Kulkarni 	iq->state = IQS_BUSY;
6263dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6273dde7c95SVishal Kulkarni 	return (0);
6283dde7c95SVishal Kulkarni }
6293dde7c95SVishal Kulkarni 
6303dde7c95SVishal Kulkarni mblk_t *
6313dde7c95SVishal Kulkarni t4_poll_ring(void *arg, int n_bytes)
6323dde7c95SVishal Kulkarni {
6333dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)arg;
6343dde7c95SVishal Kulkarni 	mblk_t *mp = NULL;
6353dde7c95SVishal Kulkarni 
6363dde7c95SVishal Kulkarni 	ASSERT(n_bytes >= 0);
6373dde7c95SVishal Kulkarni 	if (n_bytes == 0)
6383dde7c95SVishal Kulkarni 		return (NULL);
6393dde7c95SVishal Kulkarni 
6403dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6413dde7c95SVishal Kulkarni 	mp = t4_ring_rx(rxq, n_bytes);
6423dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6433dde7c95SVishal Kulkarni 
6443dde7c95SVishal Kulkarni 	return (mp);
6453dde7c95SVishal Kulkarni }
6463dde7c95SVishal Kulkarni 
6473dde7c95SVishal Kulkarni /*
6483dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular rx ring
6493dde7c95SVishal Kulkarni  */
6503dde7c95SVishal Kulkarni int
6513dde7c95SVishal Kulkarni t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
6523dde7c95SVishal Kulkarni {
6533dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
6543dde7c95SVishal Kulkarni 
6553dde7c95SVishal Kulkarni 	switch (stat) {
6563dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
6573dde7c95SVishal Kulkarni 		*val = rxq->rxbytes;
6583dde7c95SVishal Kulkarni 		break;
6593dde7c95SVishal Kulkarni 
6603dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
6613dde7c95SVishal Kulkarni 		*val = rxq->rxpkts;
6623dde7c95SVishal Kulkarni 		break;
6633dde7c95SVishal Kulkarni 
6643dde7c95SVishal Kulkarni 	default:
6653dde7c95SVishal Kulkarni 		*val = 0;
6663dde7c95SVishal Kulkarni 		return (ENOTSUP);
6673dde7c95SVishal Kulkarni 	}
6683dde7c95SVishal Kulkarni 
6693dde7c95SVishal Kulkarni 	return (0);
6703dde7c95SVishal Kulkarni }
6713dde7c95SVishal Kulkarni 
6723dde7c95SVishal Kulkarni /*
6733dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular tx ring
6743dde7c95SVishal Kulkarni  */
6753dde7c95SVishal Kulkarni int
6763dde7c95SVishal Kulkarni t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
6773dde7c95SVishal Kulkarni {
6783dde7c95SVishal Kulkarni 	struct sge_txq *txq = (struct sge_txq *)rh;
6793dde7c95SVishal Kulkarni 
6803dde7c95SVishal Kulkarni 	switch (stat) {
6813dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
6823dde7c95SVishal Kulkarni 		*val = txq->txbytes;
6833dde7c95SVishal Kulkarni 		break;
6843dde7c95SVishal Kulkarni 
6853dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
6863dde7c95SVishal Kulkarni 		*val = txq->txpkts;
6873dde7c95SVishal Kulkarni 		break;
6883dde7c95SVishal Kulkarni 
6893dde7c95SVishal Kulkarni 	default:
6903dde7c95SVishal Kulkarni 		*val = 0;
6913dde7c95SVishal Kulkarni 		return (ENOTSUP);
6923dde7c95SVishal Kulkarni 	}
6933dde7c95SVishal Kulkarni 
6943dde7c95SVishal Kulkarni 	return (0);
6953dde7c95SVishal Kulkarni }
6963dde7c95SVishal Kulkarni 
6973dde7c95SVishal Kulkarni /*
6983dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all rings
6993dde7c95SVishal Kulkarni  * for given ring_group, noted by group_index.
7003dde7c95SVishal Kulkarni  * Since we have only one group, ring index becomes
7013dde7c95SVishal Kulkarni  * absolute index.
7023dde7c95SVishal Kulkarni  */
7033dde7c95SVishal Kulkarni void
7043dde7c95SVishal Kulkarni t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
7053dde7c95SVishal Kulkarni 	     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
7063dde7c95SVishal Kulkarni {
7073dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
7083dde7c95SVishal Kulkarni 	mac_intr_t *mintr;
7093dde7c95SVishal Kulkarni 
7103dde7c95SVishal Kulkarni 	switch (rtype) {
7113dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
7123dde7c95SVishal Kulkarni 		struct sge_rxq *rxq;
7133dde7c95SVishal Kulkarni 
7143dde7c95SVishal Kulkarni 		rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
7153dde7c95SVishal Kulkarni 		rxq->ring_handle = rh;
7163dde7c95SVishal Kulkarni 
7173dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)rxq;
7183dde7c95SVishal Kulkarni 		infop->mri_start = t4_ring_start;
7193dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
7203dde7c95SVishal Kulkarni 		infop->mri_poll = t4_poll_ring;
7213dde7c95SVishal Kulkarni 		infop->mri_stat = t4_rx_stat;
7223dde7c95SVishal Kulkarni 
7233dde7c95SVishal Kulkarni 		mintr = &infop->mri_intr;
7243dde7c95SVishal Kulkarni 		mintr->mi_handle = (mac_intr_handle_t)rxq;
7253dde7c95SVishal Kulkarni 		mintr->mi_enable = t4_ring_intr_enable;
7263dde7c95SVishal Kulkarni 		mintr->mi_disable = t4_ring_intr_disable;
7273dde7c95SVishal Kulkarni 
7283dde7c95SVishal Kulkarni 		break;
7293dde7c95SVishal Kulkarni 	}
7303dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX: {
7313dde7c95SVishal Kulkarni 		struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index];
7323dde7c95SVishal Kulkarni 		txq->ring_handle = rh;
7333dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)txq;
7343dde7c95SVishal Kulkarni 		infop->mri_start = NULL;
7353dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
7363dde7c95SVishal Kulkarni 		infop->mri_tx = t4_eth_tx;
7373dde7c95SVishal Kulkarni 		infop->mri_stat = t4_tx_stat;
7383dde7c95SVishal Kulkarni 		break;
7393dde7c95SVishal Kulkarni 	}
7403dde7c95SVishal Kulkarni 	default:
7413dde7c95SVishal Kulkarni 		ASSERT(0);
7423dde7c95SVishal Kulkarni 		break;
7433dde7c95SVishal Kulkarni 	}
7443dde7c95SVishal Kulkarni }
7453dde7c95SVishal Kulkarni 
7463dde7c95SVishal Kulkarni mblk_t *
74756b2bdd1SGireesh Nagabhushana t4_mc_tx(void *arg, mblk_t *m)
74856b2bdd1SGireesh Nagabhushana {
74956b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
75056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
75156b2bdd1SGireesh Nagabhushana 	struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
75256b2bdd1SGireesh Nagabhushana 
7533dde7c95SVishal Kulkarni 	return (t4_eth_tx(txq, m));
75456b2bdd1SGireesh Nagabhushana }
75556b2bdd1SGireesh Nagabhushana 
756017c366dSRobert Mustacchi static int
757017c366dSRobert Mustacchi t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
758017c366dSRobert Mustacchi {
759017c366dSRobert Mustacchi 	struct port_info *pi = arg;
760017c366dSRobert Mustacchi 
761017c366dSRobert Mustacchi 	if (id != 0 || infop == NULL)
762017c366dSRobert Mustacchi 		return (EINVAL);
763017c366dSRobert Mustacchi 
764017c366dSRobert Mustacchi 	switch (pi->mod_type) {
765017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NONE:
766017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_FALSE);
767017c366dSRobert Mustacchi 		break;
768017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NOTSUPPORTED:
769017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
770017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_FALSE);
771017c366dSRobert Mustacchi 		break;
772017c366dSRobert Mustacchi 	default:
773017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
774017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_TRUE);
775017c366dSRobert Mustacchi 		break;
776017c366dSRobert Mustacchi 	}
777017c366dSRobert Mustacchi 
778017c366dSRobert Mustacchi 	return (0);
779017c366dSRobert Mustacchi }
780017c366dSRobert Mustacchi 
781017c366dSRobert Mustacchi static int
782017c366dSRobert Mustacchi t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
783017c366dSRobert Mustacchi     size_t nbytes, off_t offset, size_t *nread)
784017c366dSRobert Mustacchi {
785017c366dSRobert Mustacchi 	struct port_info *pi = arg;
786017c366dSRobert Mustacchi 	struct adapter *sc = pi->adapter;
787017c366dSRobert Mustacchi 	int rc;
788017c366dSRobert Mustacchi 	size_t i, maxread;
789017c366dSRobert Mustacchi 	/* LINTED: E_FUNC_VAR_UNUSED */
790017c366dSRobert Mustacchi 	struct fw_ldst_cmd ldst __unused;
791017c366dSRobert Mustacchi 
792017c366dSRobert Mustacchi 	if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
793017c366dSRobert Mustacchi 	    (page != 0xa0 && page != 0xa2) || offset < 0)
794017c366dSRobert Mustacchi 		return (EINVAL);
795017c366dSRobert Mustacchi 
796017c366dSRobert Mustacchi 	if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
797017c366dSRobert Mustacchi 		return (EINVAL);
798017c366dSRobert Mustacchi 
799017c366dSRobert Mustacchi 	rc = begin_synchronized_op(pi, 0, 1);
800017c366dSRobert Mustacchi 	if (rc != 0)
801017c366dSRobert Mustacchi 		return (rc);
802017c366dSRobert Mustacchi 
803017c366dSRobert Mustacchi 	/*
804017c366dSRobert Mustacchi 	 * Firmware has a maximum size that we can read. Don't read more than it
805017c366dSRobert Mustacchi 	 * allows.
806017c366dSRobert Mustacchi 	 */
807017c366dSRobert Mustacchi 	maxread = sizeof (ldst.u.i2c.data);
808017c366dSRobert Mustacchi 	for (i = 0; i < nbytes; i += maxread) {
809017c366dSRobert Mustacchi 		size_t toread = MIN(maxread, nbytes - i);
810017c366dSRobert Mustacchi 		rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
811017c366dSRobert Mustacchi 		    bp);
812017c366dSRobert Mustacchi 		if (rc != 0)
813017c366dSRobert Mustacchi 			break;
814017c366dSRobert Mustacchi 		offset += toread;
815017c366dSRobert Mustacchi 		bp = (void *)((uintptr_t)bp + toread);
816017c366dSRobert Mustacchi 	}
817017c366dSRobert Mustacchi 	end_synchronized_op(pi, 0);
818017c366dSRobert Mustacchi 	if (rc == 0)
819017c366dSRobert Mustacchi 		*nread = nbytes;
820017c366dSRobert Mustacchi 	return (rc);
821017c366dSRobert Mustacchi }
822017c366dSRobert Mustacchi 
823d87e4548SVishal Kulkarni static int
824d87e4548SVishal Kulkarni t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
825d87e4548SVishal Kulkarni {
826d87e4548SVishal Kulkarni 	struct port_info *pi = arg;
827d87e4548SVishal Kulkarni 	struct adapter *sc = pi->adapter;
828d87e4548SVishal Kulkarni 	int val, rc;
829d87e4548SVishal Kulkarni 
830d87e4548SVishal Kulkarni 	if (flags != 0)
831d87e4548SVishal Kulkarni 		return (EINVAL);
832d87e4548SVishal Kulkarni 
833d87e4548SVishal Kulkarni 	switch (mode) {
834d87e4548SVishal Kulkarni 	case MAC_LED_DEFAULT:
835d87e4548SVishal Kulkarni 		val = 0;
836d87e4548SVishal Kulkarni 		break;
837d87e4548SVishal Kulkarni 	case MAC_LED_IDENT:
838d87e4548SVishal Kulkarni 		val = 0xffff;
839d87e4548SVishal Kulkarni 		break;
840d87e4548SVishal Kulkarni 
841d87e4548SVishal Kulkarni 	default:
842d87e4548SVishal Kulkarni 		return (ENOTSUP);
843d87e4548SVishal Kulkarni 	}
844d87e4548SVishal Kulkarni 
845d87e4548SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
846d87e4548SVishal Kulkarni 	if (rc != 0)
847d87e4548SVishal Kulkarni 		return (rc);
848d87e4548SVishal Kulkarni 	rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
849d87e4548SVishal Kulkarni 	end_synchronized_op(pi, 1);
850d87e4548SVishal Kulkarni 
851d87e4548SVishal Kulkarni 	return (rc);
852d87e4548SVishal Kulkarni }
853d87e4548SVishal Kulkarni 
85456b2bdd1SGireesh Nagabhushana static boolean_t
85556b2bdd1SGireesh Nagabhushana t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
85656b2bdd1SGireesh Nagabhushana {
85756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
85856b2bdd1SGireesh Nagabhushana 	boolean_t status = B_TRUE;
859017c366dSRobert Mustacchi 	mac_capab_transceiver_t *mct;
860d87e4548SVishal Kulkarni 	mac_capab_led_t *mcl;
86156b2bdd1SGireesh Nagabhushana 
86256b2bdd1SGireesh Nagabhushana 	switch (cap) {
86356b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_HCKSUM:
86456b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_CSUM) {
86556b2bdd1SGireesh Nagabhushana 			uint32_t *d = data;
86656b2bdd1SGireesh Nagabhushana 			*d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
86756b2bdd1SGireesh Nagabhushana 		} else
86856b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
86956b2bdd1SGireesh Nagabhushana 		break;
87056b2bdd1SGireesh Nagabhushana 
87156b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_LSO:
87256b2bdd1SGireesh Nagabhushana 		/* Enabling LSO requires Checksum offloading */
87356b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_LSO &&
87456b2bdd1SGireesh Nagabhushana 		    pi->features & CXGBE_HW_CSUM) {
87556b2bdd1SGireesh Nagabhushana 			mac_capab_lso_t *d = data;
87656b2bdd1SGireesh Nagabhushana 
87756b2bdd1SGireesh Nagabhushana 			d->lso_flags = LSO_TX_BASIC_TCP_IPV4;
87856b2bdd1SGireesh Nagabhushana 			d->lso_basic_tcp_ipv4.lso_max = 65535;
87956b2bdd1SGireesh Nagabhushana 		} else
88056b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
88156b2bdd1SGireesh Nagabhushana 		break;
88256b2bdd1SGireesh Nagabhushana 
8833dde7c95SVishal Kulkarni 	case MAC_CAPAB_RINGS: {
8843dde7c95SVishal Kulkarni 		mac_capab_rings_t *cap_rings = data;
8853dde7c95SVishal Kulkarni 
8863dde7c95SVishal Kulkarni 		if (!pi->adapter->props.multi_rings) {
8873dde7c95SVishal Kulkarni 			status = B_FALSE;
8883dde7c95SVishal Kulkarni 			break;
8893dde7c95SVishal Kulkarni 		}
8903dde7c95SVishal Kulkarni 		switch (cap_rings->mr_type) {
8913dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_RX:
8923dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
8933dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->nrxq;
8943dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 1;
8953dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
8963dde7c95SVishal Kulkarni 			cap_rings->mr_gget = t4_fill_group;
8973dde7c95SVishal Kulkarni 			cap_rings->mr_gaddring = NULL;
8983dde7c95SVishal Kulkarni 			cap_rings->mr_gremring = NULL;
8993dde7c95SVishal Kulkarni 			break;
9003dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_TX:
9013dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
9023dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->ntxq;
9033dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 0;
9043dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
9053dde7c95SVishal Kulkarni 			cap_rings->mr_gget = NULL;
9063dde7c95SVishal Kulkarni 			break;
9073dde7c95SVishal Kulkarni 		}
9083dde7c95SVishal Kulkarni 		break;
9093dde7c95SVishal Kulkarni 	}
910017c366dSRobert Mustacchi 
911017c366dSRobert Mustacchi 	case MAC_CAPAB_TRANSCEIVER:
912017c366dSRobert Mustacchi 		mct = data;
913017c366dSRobert Mustacchi 
914017c366dSRobert Mustacchi 		mct->mct_flags = 0;
915017c366dSRobert Mustacchi 		mct->mct_ntransceivers = 1;
916017c366dSRobert Mustacchi 		mct->mct_info = t4_mc_transceiver_info;
917017c366dSRobert Mustacchi 		mct->mct_read = t4_mc_transceiver_read;
918017c366dSRobert Mustacchi 		break;
919d87e4548SVishal Kulkarni 	case MAC_CAPAB_LED:
920d87e4548SVishal Kulkarni 		mcl = data;
921d87e4548SVishal Kulkarni 		mcl->mcl_flags = 0;
922d87e4548SVishal Kulkarni 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
923d87e4548SVishal Kulkarni 		mcl->mcl_set = t4_port_led_set;
924d87e4548SVishal Kulkarni 		break;
925017c366dSRobert Mustacchi 
92656b2bdd1SGireesh Nagabhushana 	default:
92756b2bdd1SGireesh Nagabhushana 		status = B_FALSE; /* cap not supported */
92856b2bdd1SGireesh Nagabhushana 	}
92956b2bdd1SGireesh Nagabhushana 
93056b2bdd1SGireesh Nagabhushana 	return (status);
93156b2bdd1SGireesh Nagabhushana }
93256b2bdd1SGireesh Nagabhushana 
93356b2bdd1SGireesh Nagabhushana /* ARGSUSED */
93456b2bdd1SGireesh Nagabhushana static int
93556b2bdd1SGireesh Nagabhushana t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
93656b2bdd1SGireesh Nagabhushana     const void *val)
93756b2bdd1SGireesh Nagabhushana {
93856b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
93956b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
94056b2bdd1SGireesh Nagabhushana 	struct link_config lc_copy, *lc = &pi->link_cfg;
94156b2bdd1SGireesh Nagabhushana 	uint8_t v8 = *(uint8_t *)val;
94256b2bdd1SGireesh Nagabhushana 	uint32_t v32 = *(uint32_t *)val;
94356b2bdd1SGireesh Nagabhushana 	int old, new = 0, relink = 0, rx_mode = 0, rc = 0;
94456b2bdd1SGireesh Nagabhushana 	link_flowctrl_t fc;
94556b2bdd1SGireesh Nagabhushana 
94656b2bdd1SGireesh Nagabhushana 	/*
94756b2bdd1SGireesh Nagabhushana 	 * Save a copy of link_config. This can be used to restore link_config
9483dde7c95SVishal Kulkarni 	 * if t4_link_l1cfg() fails.
94956b2bdd1SGireesh Nagabhushana 	 */
95056b2bdd1SGireesh Nagabhushana 	bcopy(lc, &lc_copy, sizeof (struct link_config));
95156b2bdd1SGireesh Nagabhushana 
95256b2bdd1SGireesh Nagabhushana 	switch (id) {
95356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
954*7e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG) {
95556b2bdd1SGireesh Nagabhushana 			old = lc->autoneg;
95656b2bdd1SGireesh Nagabhushana 			new = v8 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
95756b2bdd1SGireesh Nagabhushana 			if (old != new) {
95856b2bdd1SGireesh Nagabhushana 				/* LINTED: E_CONSTANT_CONDITION */
95956b2bdd1SGireesh Nagabhushana 				lc->autoneg = new;
96056b2bdd1SGireesh Nagabhushana 				relink = 1;
96156b2bdd1SGireesh Nagabhushana 				if (new == AUTONEG_DISABLE) {
96256b2bdd1SGireesh Nagabhushana 					/* Only 100M is available */
963*7e6ad469SVishal Kulkarni 					lc->speed_caps =
964*7e6ad469SVishal Kulkarni 					    FW_PORT_CAP32_SPEED_100M;
965*7e6ad469SVishal Kulkarni 					lc->acaps =
966*7e6ad469SVishal Kulkarni 					    FW_PORT_CAP32_SPEED_100M;
96756b2bdd1SGireesh Nagabhushana 				} else {
96856b2bdd1SGireesh Nagabhushana 					/*
96956b2bdd1SGireesh Nagabhushana 					 * Advertise autonegotiation capability
97056b2bdd1SGireesh Nagabhushana 					 * along with supported speeds
97156b2bdd1SGireesh Nagabhushana 					 */
972*7e6ad469SVishal Kulkarni 					lc->acaps |= (FW_PORT_CAP32_ANEG |
973*7e6ad469SVishal Kulkarni 					    (lc->pcaps &
974*7e6ad469SVishal Kulkarni 					    (FW_PORT_CAP32_SPEED_100M |
975*7e6ad469SVishal Kulkarni 					    FW_PORT_CAP32_SPEED_1G)));
976*7e6ad469SVishal Kulkarni 					lc->speed_caps = 0;
97756b2bdd1SGireesh Nagabhushana 				}
97856b2bdd1SGireesh Nagabhushana 			}
97956b2bdd1SGireesh Nagabhushana 		} else
98056b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
98156b2bdd1SGireesh Nagabhushana 		break;
98256b2bdd1SGireesh Nagabhushana 
98356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
98456b2bdd1SGireesh Nagabhushana 		if (v32 < 46 || v32 > MAX_MTU) {
98556b2bdd1SGireesh Nagabhushana 			rc = EINVAL;
98656b2bdd1SGireesh Nagabhushana 		} else if (v32 != pi->mtu) {
98756b2bdd1SGireesh Nagabhushana 			pi->mtu = v32;
98856b2bdd1SGireesh Nagabhushana 			(void) mac_maxsdu_update(pi->mh, v32);
98956b2bdd1SGireesh Nagabhushana 			rx_mode = 1;
99056b2bdd1SGireesh Nagabhushana 		}
99156b2bdd1SGireesh Nagabhushana 
99256b2bdd1SGireesh Nagabhushana 		break;
99356b2bdd1SGireesh Nagabhushana 
99456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
99556b2bdd1SGireesh Nagabhushana 		fc = *(link_flowctrl_t *)val;
99656b2bdd1SGireesh Nagabhushana 		old = lc->requested_fc & (PAUSE_TX | PAUSE_RX);
99756b2bdd1SGireesh Nagabhushana 
99856b2bdd1SGireesh Nagabhushana 		if (fc == LINK_FLOWCTRL_BI)
99956b2bdd1SGireesh Nagabhushana 			new = (PAUSE_TX | PAUSE_RX);
100056b2bdd1SGireesh Nagabhushana 		else if (fc == LINK_FLOWCTRL_TX)
100156b2bdd1SGireesh Nagabhushana 			new = PAUSE_TX;
100256b2bdd1SGireesh Nagabhushana 		else if (fc == LINK_FLOWCTRL_RX)
100356b2bdd1SGireesh Nagabhushana 			new = PAUSE_RX;
100456b2bdd1SGireesh Nagabhushana 
100556b2bdd1SGireesh Nagabhushana 		if (new != old) {
100656b2bdd1SGireesh Nagabhushana 			lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX);
100756b2bdd1SGireesh Nagabhushana 			lc->requested_fc |= new;
100856b2bdd1SGireesh Nagabhushana 			relink = 1;
100956b2bdd1SGireesh Nagabhushana 		}
101056b2bdd1SGireesh Nagabhushana 		break;
101156b2bdd1SGireesh Nagabhushana 
101256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
1013*7e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG && is_10G_port(pi)) {
1014*7e6ad469SVishal Kulkarni 			old = lc->acaps & FW_PORT_CAP32_SPEED_10G;
1015*7e6ad469SVishal Kulkarni 			new = v8 ? FW_PORT_CAP32_SPEED_10G : 0;
101656b2bdd1SGireesh Nagabhushana 			if (new != old) {
1017*7e6ad469SVishal Kulkarni 				lc->acaps &= ~FW_PORT_CAP32_SPEED_10G;
1018*7e6ad469SVishal Kulkarni 				lc->acaps |= new;
101956b2bdd1SGireesh Nagabhushana 				relink = 1;
102056b2bdd1SGireesh Nagabhushana 			}
102156b2bdd1SGireesh Nagabhushana 		} else
102256b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
102356b2bdd1SGireesh Nagabhushana 
102456b2bdd1SGireesh Nagabhushana 		break;
102556b2bdd1SGireesh Nagabhushana 
102656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
102756b2bdd1SGireesh Nagabhushana 		/* Forced 1G */
102856b2bdd1SGireesh Nagabhushana 		if (lc->autoneg == AUTONEG_ENABLE) {
1029*7e6ad469SVishal Kulkarni 			old = lc->acaps & FW_PORT_CAP32_SPEED_1G;
1030*7e6ad469SVishal Kulkarni 			new = v8 ? FW_PORT_CAP32_SPEED_1G : 0;
103156b2bdd1SGireesh Nagabhushana 
103256b2bdd1SGireesh Nagabhushana 			if (old != new) {
1033*7e6ad469SVishal Kulkarni 				lc->acaps &= ~FW_PORT_CAP32_SPEED_1G;
1034*7e6ad469SVishal Kulkarni 				lc->acaps |= new;
103556b2bdd1SGireesh Nagabhushana 				relink = 1;
103656b2bdd1SGireesh Nagabhushana 			}
103756b2bdd1SGireesh Nagabhushana 		} else
103856b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
103956b2bdd1SGireesh Nagabhushana 		break;
104056b2bdd1SGireesh Nagabhushana 
104156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
104256b2bdd1SGireesh Nagabhushana 		/* Forced 100M */
104356b2bdd1SGireesh Nagabhushana 		if (lc->autoneg == AUTONEG_ENABLE) {
1044*7e6ad469SVishal Kulkarni 			old = lc->acaps & FW_PORT_CAP32_SPEED_100M;
1045*7e6ad469SVishal Kulkarni 			new = v8 ? FW_PORT_CAP32_SPEED_100M : 0;
104656b2bdd1SGireesh Nagabhushana 			if (old != new) {
1047*7e6ad469SVishal Kulkarni 				lc->acaps &= ~FW_PORT_CAP32_SPEED_100M;
1048*7e6ad469SVishal Kulkarni 				lc->acaps |= new;
104956b2bdd1SGireesh Nagabhushana 				relink = 1;
105056b2bdd1SGireesh Nagabhushana 			}
105156b2bdd1SGireesh Nagabhushana 		} else
105256b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
105356b2bdd1SGireesh Nagabhushana 		break;
105456b2bdd1SGireesh Nagabhushana 
105556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
105656b2bdd1SGireesh Nagabhushana 		rc = setprop(pi, name, val);
105756b2bdd1SGireesh Nagabhushana 		break;
105856b2bdd1SGireesh Nagabhushana 
105956b2bdd1SGireesh Nagabhushana 	default:
106056b2bdd1SGireesh Nagabhushana 		rc = ENOTSUP;
106156b2bdd1SGireesh Nagabhushana 	}
106256b2bdd1SGireesh Nagabhushana 
106356b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
106456b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
106556b2bdd1SGireesh Nagabhushana 			t4_os_link_changed(pi->adapter, pi->port_id, 0);
106656b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
106756b2bdd1SGireesh Nagabhushana 			if (rc != 0)
106856b2bdd1SGireesh Nagabhushana 				return (rc);
10693dde7c95SVishal Kulkarni 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan,
107056b2bdd1SGireesh Nagabhushana 			    &pi->link_cfg);
107156b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
107256b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
107356b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
107456b2bdd1SGireesh Nagabhushana 				    "start_link failed:%d", rc);
107556b2bdd1SGireesh Nagabhushana 
107656b2bdd1SGireesh Nagabhushana 				/* Restore link_config */
107756b2bdd1SGireesh Nagabhushana 				bcopy(&lc_copy, lc,
107856b2bdd1SGireesh Nagabhushana 				    sizeof (struct link_config));
107956b2bdd1SGireesh Nagabhushana 			}
108056b2bdd1SGireesh Nagabhushana 		}
108156b2bdd1SGireesh Nagabhushana 
108256b2bdd1SGireesh Nagabhushana 		if (rx_mode != 0) {
108356b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
108456b2bdd1SGireesh Nagabhushana 			if (rc != 0)
108556b2bdd1SGireesh Nagabhushana 				return (rc);
108656b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
108756b2bdd1SGireesh Nagabhushana 			    -1, -1, -1, false);
108856b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
108956b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
109056b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
109156b2bdd1SGireesh Nagabhushana 				    "set_rxmode failed: %d", rc);
109256b2bdd1SGireesh Nagabhushana 			}
109356b2bdd1SGireesh Nagabhushana 		}
109456b2bdd1SGireesh Nagabhushana 	}
109556b2bdd1SGireesh Nagabhushana 
109656b2bdd1SGireesh Nagabhushana 	return (rc);
109756b2bdd1SGireesh Nagabhushana }
109856b2bdd1SGireesh Nagabhushana 
109956b2bdd1SGireesh Nagabhushana static int
110056b2bdd1SGireesh Nagabhushana t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
110156b2bdd1SGireesh Nagabhushana     void *val)
110256b2bdd1SGireesh Nagabhushana {
110356b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
110456b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
110556b2bdd1SGireesh Nagabhushana 	uint8_t *u = val;
110656b2bdd1SGireesh Nagabhushana 
110756b2bdd1SGireesh Nagabhushana 	switch (id) {
110856b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
110956b2bdd1SGireesh Nagabhushana 		*(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
111056b2bdd1SGireesh Nagabhushana 		    LINK_DUPLEX_UNKNOWN;
111156b2bdd1SGireesh Nagabhushana 		break;
111256b2bdd1SGireesh Nagabhushana 
111356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
111456b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
111556b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val = lc->speed;
111656b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val *= 1000000;
111756b2bdd1SGireesh Nagabhushana 		} else
111856b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val = 0;
111956b2bdd1SGireesh Nagabhushana 		break;
112056b2bdd1SGireesh Nagabhushana 
112156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
112256b2bdd1SGireesh Nagabhushana 		*(link_state_t *)val = lc->link_ok ? LINK_STATE_UP :
112356b2bdd1SGireesh Nagabhushana 		    LINK_STATE_DOWN;
112456b2bdd1SGireesh Nagabhushana 		break;
112556b2bdd1SGireesh Nagabhushana 
112656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
112756b2bdd1SGireesh Nagabhushana 		*u = lc->autoneg == AUTONEG_ENABLE;
112856b2bdd1SGireesh Nagabhushana 		break;
112956b2bdd1SGireesh Nagabhushana 
113056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
113156b2bdd1SGireesh Nagabhushana 		*(uint32_t *)val = pi->mtu;
113256b2bdd1SGireesh Nagabhushana 		break;
113356b2bdd1SGireesh Nagabhushana 
113456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
113556b2bdd1SGireesh Nagabhushana 		if ((lc->requested_fc & (PAUSE_TX | PAUSE_RX)) ==
113656b2bdd1SGireesh Nagabhushana 		    (PAUSE_TX | PAUSE_RX))
113756b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_BI;
113856b2bdd1SGireesh Nagabhushana 		else if (lc->requested_fc & PAUSE_TX)
113956b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_TX;
114056b2bdd1SGireesh Nagabhushana 		else if (lc->requested_fc & PAUSE_RX)
114156b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_RX;
114256b2bdd1SGireesh Nagabhushana 		else
114356b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_NONE;
114456b2bdd1SGireesh Nagabhushana 		break;
114556b2bdd1SGireesh Nagabhushana 
11463dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_100GFDX_CAP:
11473dde7c95SVishal Kulkarni 	case MAC_PROP_EN_100GFDX_CAP:
1148*7e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_100G);
11493dde7c95SVishal Kulkarni 		break;
11503dde7c95SVishal Kulkarni 
11513dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_40GFDX_CAP:
11523dde7c95SVishal Kulkarni 	case MAC_PROP_EN_40GFDX_CAP:
1153*7e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_40G);
11543dde7c95SVishal Kulkarni 		break;
11553dde7c95SVishal Kulkarni 
11563dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_25GFDX_CAP:
11573dde7c95SVishal Kulkarni 	case MAC_PROP_EN_25GFDX_CAP:
1158*7e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_25G);
11593dde7c95SVishal Kulkarni 		break;
11603dde7c95SVishal Kulkarni 
116156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
116256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
1163*7e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_10G);
116456b2bdd1SGireesh Nagabhushana 		break;
116556b2bdd1SGireesh Nagabhushana 
116656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
116756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
1168*7e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_1G);
116956b2bdd1SGireesh Nagabhushana 		break;
117056b2bdd1SGireesh Nagabhushana 
117156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
117256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
1173*7e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_100M);
117456b2bdd1SGireesh Nagabhushana 		break;
117556b2bdd1SGireesh Nagabhushana 
117656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
117756b2bdd1SGireesh Nagabhushana 		return (getprop(pi, name, size, val));
117856b2bdd1SGireesh Nagabhushana 
117956b2bdd1SGireesh Nagabhushana 	default:
118056b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
118156b2bdd1SGireesh Nagabhushana 	}
118256b2bdd1SGireesh Nagabhushana 
118356b2bdd1SGireesh Nagabhushana 	return (0);
118456b2bdd1SGireesh Nagabhushana }
118556b2bdd1SGireesh Nagabhushana 
118656b2bdd1SGireesh Nagabhushana static void
118756b2bdd1SGireesh Nagabhushana t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
118856b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph)
118956b2bdd1SGireesh Nagabhushana {
119056b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
119156b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
119256b2bdd1SGireesh Nagabhushana 
119356b2bdd1SGireesh Nagabhushana 	switch (id) {
119456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
119556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
119656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
119756b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
119856b2bdd1SGireesh Nagabhushana 		break;
119956b2bdd1SGireesh Nagabhushana 
120056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
1201*7e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG)
120256b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
120356b2bdd1SGireesh Nagabhushana 		else
120456b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
120556b2bdd1SGireesh Nagabhushana 		break;
120656b2bdd1SGireesh Nagabhushana 
120756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
120856b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_range_uint32(ph, 46, MAX_MTU);
120956b2bdd1SGireesh Nagabhushana 		break;
121056b2bdd1SGireesh Nagabhushana 
121156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
121256b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI);
121356b2bdd1SGireesh Nagabhushana 		break;
121456b2bdd1SGireesh Nagabhushana 
121556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
1216*7e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG &&
1217*7e6ad469SVishal Kulkarni 		    lc->pcaps & FW_PORT_CAP32_SPEED_10G)
121856b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
121956b2bdd1SGireesh Nagabhushana 		else
122056b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
122156b2bdd1SGireesh Nagabhushana 		break;
122256b2bdd1SGireesh Nagabhushana 
122356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
1224*7e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG &&
1225*7e6ad469SVishal Kulkarni 		    lc->pcaps & FW_PORT_CAP32_SPEED_1G)
122656b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
122756b2bdd1SGireesh Nagabhushana 		else
122856b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
122956b2bdd1SGireesh Nagabhushana 		break;
123056b2bdd1SGireesh Nagabhushana 
123156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
1232*7e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG &&
1233*7e6ad469SVishal Kulkarni 		    lc->pcaps & FW_PORT_CAP32_SPEED_100M)
123456b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
123556b2bdd1SGireesh Nagabhushana 		else
123656b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
123756b2bdd1SGireesh Nagabhushana 		break;
123856b2bdd1SGireesh Nagabhushana 
123956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
124056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
124156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
124256b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
124356b2bdd1SGireesh Nagabhushana 		break;
124456b2bdd1SGireesh Nagabhushana 
124556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
124656b2bdd1SGireesh Nagabhushana 		propinfo(pi, name, ph);
124756b2bdd1SGireesh Nagabhushana 		break;
124856b2bdd1SGireesh Nagabhushana 
124956b2bdd1SGireesh Nagabhushana 	default:
125056b2bdd1SGireesh Nagabhushana 		break;
125156b2bdd1SGireesh Nagabhushana 	}
125256b2bdd1SGireesh Nagabhushana }
125356b2bdd1SGireesh Nagabhushana 
1254*7e6ad469SVishal Kulkarni int
125556b2bdd1SGireesh Nagabhushana begin_synchronized_op(struct port_info *pi, int hold, int waitok)
125656b2bdd1SGireesh Nagabhushana {
125756b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
125856b2bdd1SGireesh Nagabhushana 	int rc = 0;
125956b2bdd1SGireesh Nagabhushana 
126056b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK(sc);
126156b2bdd1SGireesh Nagabhushana 	while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
126256b2bdd1SGireesh Nagabhushana 		if (!waitok) {
126356b2bdd1SGireesh Nagabhushana 			rc = EBUSY;
126456b2bdd1SGireesh Nagabhushana 			goto failed;
126556b2bdd1SGireesh Nagabhushana 		} else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) {
126656b2bdd1SGireesh Nagabhushana 			rc = EINTR;
126756b2bdd1SGireesh Nagabhushana 			goto failed;
126856b2bdd1SGireesh Nagabhushana 		}
126956b2bdd1SGireesh Nagabhushana 	}
127056b2bdd1SGireesh Nagabhushana 	if (IS_DOOMED(pi) != 0) {	/* shouldn't happen on Solaris */
127156b2bdd1SGireesh Nagabhushana 		rc = ENXIO;
127256b2bdd1SGireesh Nagabhushana 		goto failed;
127356b2bdd1SGireesh Nagabhushana 	}
127456b2bdd1SGireesh Nagabhushana 	ASSERT(!IS_BUSY(sc));
127556b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
127656b2bdd1SGireesh Nagabhushana 	SET_BUSY(sc);
127756b2bdd1SGireesh Nagabhushana 
127856b2bdd1SGireesh Nagabhushana 	if (!hold)
127956b2bdd1SGireesh Nagabhushana 		ADAPTER_UNLOCK(sc);
128056b2bdd1SGireesh Nagabhushana 
128156b2bdd1SGireesh Nagabhushana 	return (0);
128256b2bdd1SGireesh Nagabhushana failed:
128356b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
128456b2bdd1SGireesh Nagabhushana 	return (rc);
128556b2bdd1SGireesh Nagabhushana }
128656b2bdd1SGireesh Nagabhushana 
1287*7e6ad469SVishal Kulkarni void
128856b2bdd1SGireesh Nagabhushana end_synchronized_op(struct port_info *pi, int held)
128956b2bdd1SGireesh Nagabhushana {
129056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
129156b2bdd1SGireesh Nagabhushana 
129256b2bdd1SGireesh Nagabhushana 	if (!held)
129356b2bdd1SGireesh Nagabhushana 		ADAPTER_LOCK(sc);
129456b2bdd1SGireesh Nagabhushana 
129556b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_OWNED(sc);
129656b2bdd1SGireesh Nagabhushana 	ASSERT(IS_BUSY(sc));
129756b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
129856b2bdd1SGireesh Nagabhushana 	CLR_BUSY(sc);
129956b2bdd1SGireesh Nagabhushana 	cv_signal(&sc->cv);
130056b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
130156b2bdd1SGireesh Nagabhushana }
130256b2bdd1SGireesh Nagabhushana 
130356b2bdd1SGireesh Nagabhushana static int
130456b2bdd1SGireesh Nagabhushana t4_init_synchronized(struct port_info *pi)
130556b2bdd1SGireesh Nagabhushana {
130656b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
130756b2bdd1SGireesh Nagabhushana 	int rc = 0;
130856b2bdd1SGireesh Nagabhushana 
130956b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
131056b2bdd1SGireesh Nagabhushana 
131156b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0)
131256b2bdd1SGireesh Nagabhushana 		return (0);	/* already running */
131356b2bdd1SGireesh Nagabhushana 
131456b2bdd1SGireesh Nagabhushana 	if (!(sc->flags & FULL_INIT_DONE) &&
131556b2bdd1SGireesh Nagabhushana 	    ((rc = adapter_full_init(sc)) != 0))
131656b2bdd1SGireesh Nagabhushana 		return (rc);	/* error message displayed already */
131756b2bdd1SGireesh Nagabhushana 
131856b2bdd1SGireesh Nagabhushana 	if (!(pi->flags & PORT_INIT_DONE)) {
131956b2bdd1SGireesh Nagabhushana 		rc = port_full_init(pi);
132056b2bdd1SGireesh Nagabhushana 		if (rc != 0)
132156b2bdd1SGireesh Nagabhushana 			return (rc); /* error message displayed already */
132256b2bdd1SGireesh Nagabhushana 	} else
132356b2bdd1SGireesh Nagabhushana 		enable_port_queues(pi);
132456b2bdd1SGireesh Nagabhushana 
132556b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false);
132656b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
132756b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc);
132856b2bdd1SGireesh Nagabhushana 		goto done;
132956b2bdd1SGireesh Nagabhushana 	}
133056b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt,
1331*7e6ad469SVishal Kulkarni 	    pi->hw_addr, true, &pi->smt_idx);
133256b2bdd1SGireesh Nagabhushana 	if (rc < 0) {
133356b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc);
133456b2bdd1SGireesh Nagabhushana 		rc = -rc;
133556b2bdd1SGireesh Nagabhushana 		goto done;
133656b2bdd1SGireesh Nagabhushana 	} else
133756b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
133856b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
133956b2bdd1SGireesh Nagabhushana 
13403dde7c95SVishal Kulkarni 	rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg);
134156b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
134256b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc);
134356b2bdd1SGireesh Nagabhushana 		goto done;
134456b2bdd1SGireesh Nagabhushana 	}
134556b2bdd1SGireesh Nagabhushana 
134656b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true);
134756b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
134856b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc);
134956b2bdd1SGireesh Nagabhushana 		goto done;
135056b2bdd1SGireesh Nagabhushana 	}
135156b2bdd1SGireesh Nagabhushana 
135256b2bdd1SGireesh Nagabhushana 	/* all ok */
135356b2bdd1SGireesh Nagabhushana 	setbit(&sc->open_device_map, pi->port_id);
135456b2bdd1SGireesh Nagabhushana done:
135556b2bdd1SGireesh Nagabhushana 	if (rc != 0)
135656b2bdd1SGireesh Nagabhushana 		(void) t4_uninit_synchronized(pi);
135756b2bdd1SGireesh Nagabhushana 
135856b2bdd1SGireesh Nagabhushana 	return (rc);
135956b2bdd1SGireesh Nagabhushana }
136056b2bdd1SGireesh Nagabhushana 
136156b2bdd1SGireesh Nagabhushana /*
136256b2bdd1SGireesh Nagabhushana  * Idempotent.
136356b2bdd1SGireesh Nagabhushana  */
136456b2bdd1SGireesh Nagabhushana static int
136556b2bdd1SGireesh Nagabhushana t4_uninit_synchronized(struct port_info *pi)
136656b2bdd1SGireesh Nagabhushana {
136756b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
136856b2bdd1SGireesh Nagabhushana 	int rc;
136956b2bdd1SGireesh Nagabhushana 
137056b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
137156b2bdd1SGireesh Nagabhushana 
137256b2bdd1SGireesh Nagabhushana 	/*
137356b2bdd1SGireesh Nagabhushana 	 * Disable the VI so that all its data in either direction is discarded
137456b2bdd1SGireesh Nagabhushana 	 * by the MPS.  Leave everything else (the queues, interrupts, and 1Hz
137556b2bdd1SGireesh Nagabhushana 	 * tick) intact as the TP can deliver negative advice or data that it's
137656b2bdd1SGireesh Nagabhushana 	 * holding in its RAM (for an offloaded connection) even after the VI is
137756b2bdd1SGireesh Nagabhushana 	 * disabled.
137856b2bdd1SGireesh Nagabhushana 	 */
137956b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false);
138056b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
138156b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc);
138256b2bdd1SGireesh Nagabhushana 		return (rc);
138356b2bdd1SGireesh Nagabhushana 	}
138456b2bdd1SGireesh Nagabhushana 
138556b2bdd1SGireesh Nagabhushana 	disable_port_queues(pi);
138656b2bdd1SGireesh Nagabhushana 
138756b2bdd1SGireesh Nagabhushana 	clrbit(&sc->open_device_map, pi->port_id);
138856b2bdd1SGireesh Nagabhushana 
138956b2bdd1SGireesh Nagabhushana 	pi->link_cfg.link_ok = 0;
139056b2bdd1SGireesh Nagabhushana 	pi->link_cfg.speed = 0;
139156b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, LINK_STATE_UNKNOWN);
139256b2bdd1SGireesh Nagabhushana 
139356b2bdd1SGireesh Nagabhushana 	return (0);
139456b2bdd1SGireesh Nagabhushana }
139556b2bdd1SGireesh Nagabhushana 
139656b2bdd1SGireesh Nagabhushana static void
139756b2bdd1SGireesh Nagabhushana propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph)
139856b2bdd1SGireesh Nagabhushana {
139956b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
140056b2bdd1SGireesh Nagabhushana 	struct driver_properties *p = &sc->props;
140156b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
140256b2bdd1SGireesh Nagabhushana 	int v;
140356b2bdd1SGireesh Nagabhushana 	char str[16];
140456b2bdd1SGireesh Nagabhushana 
140556b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
140656b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g;
140756b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
140856b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g;
140956b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
141056b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
141156b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
141256b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
141356b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
141456b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_TX) ? 1 : 0;
141556b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
141656b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_RX) ? 1 : 0;
141756b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
141856b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
141956b2bdd1SGireesh Nagabhushana 		v = ETHERMTU;
142056b2bdd1SGireesh Nagabhushana #endif
142156b2bdd1SGireesh Nagabhushana 	else
142256b2bdd1SGireesh Nagabhushana 		return;
142356b2bdd1SGireesh Nagabhushana 
142456b2bdd1SGireesh Nagabhushana 	(void) snprintf(str, sizeof (str), "%d", v);
142556b2bdd1SGireesh Nagabhushana 	mac_prop_info_set_default_str(ph, str);
142656b2bdd1SGireesh Nagabhushana }
142756b2bdd1SGireesh Nagabhushana 
142856b2bdd1SGireesh Nagabhushana static int
142956b2bdd1SGireesh Nagabhushana getprop(struct port_info *pi, const char *name, uint_t size, void *val)
143056b2bdd1SGireesh Nagabhushana {
143156b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
143256b2bdd1SGireesh Nagabhushana 	int v;
143356b2bdd1SGireesh Nagabhushana 
143456b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
143556b2bdd1SGireesh Nagabhushana 		v = pi->tmr_idx;
143656b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
143756b2bdd1SGireesh Nagabhushana 		v = pi->pktc_idx;
143856b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
143956b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
144056b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
144156b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
144256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
144356b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_TX) ? 1 : 0;
144456b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
144556b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_RX) ? 1 : 0;
144656b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
144756b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
144856b2bdd1SGireesh Nagabhushana 		v = pi->mtu;
144956b2bdd1SGireesh Nagabhushana #endif
145056b2bdd1SGireesh Nagabhushana 	else
145156b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
145256b2bdd1SGireesh Nagabhushana 
145356b2bdd1SGireesh Nagabhushana 	(void) snprintf(val, size, "%d", v);
145456b2bdd1SGireesh Nagabhushana 	return (0);
145556b2bdd1SGireesh Nagabhushana }
145656b2bdd1SGireesh Nagabhushana 
145756b2bdd1SGireesh Nagabhushana static int
145856b2bdd1SGireesh Nagabhushana setprop(struct port_info *pi, const char *name, const void *val)
145956b2bdd1SGireesh Nagabhushana {
146056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
146156b2bdd1SGireesh Nagabhushana 	long v;
146256b2bdd1SGireesh Nagabhushana 	int i, rc = 0, relink = 0, rx_mode = 0;
146356b2bdd1SGireesh Nagabhushana 	struct sge_rxq *rxq;
146456b2bdd1SGireesh Nagabhushana 	struct link_config lc_old, *lc = &pi->link_cfg;
146556b2bdd1SGireesh Nagabhushana 
146656b2bdd1SGireesh Nagabhushana 	/*
146756b2bdd1SGireesh Nagabhushana 	 * Save a copy of link_config. This can be used to restore link_config
14683dde7c95SVishal Kulkarni 	 * if t4_link_l1cfg() fails.
146956b2bdd1SGireesh Nagabhushana 	 */
147056b2bdd1SGireesh Nagabhushana 	bcopy(lc, &lc_old, sizeof (struct link_config));
147156b2bdd1SGireesh Nagabhushana 
147256b2bdd1SGireesh Nagabhushana 	(void) ddi_strtol(val, NULL, 0, &v);
147356b2bdd1SGireesh Nagabhushana 
147456b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0) {
147556b2bdd1SGireesh Nagabhushana 		if (v < 0 || v >= SGE_NTIMERS)
147656b2bdd1SGireesh Nagabhushana 			return (EINVAL);
147756b2bdd1SGireesh Nagabhushana 		if (v == pi->tmr_idx)
147856b2bdd1SGireesh Nagabhushana 			return (0);
147956b2bdd1SGireesh Nagabhushana 
148056b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
148156b2bdd1SGireesh Nagabhushana 		pi->tmr_idx = v;
148256b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
148356b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) |
148456b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(pi->pktc_idx >= 0);
148556b2bdd1SGireesh Nagabhushana 		}
148656b2bdd1SGireesh Nagabhushana 
148756b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_PKTC_IDX) == 0) {
148856b2bdd1SGireesh Nagabhushana 		if (v >= SGE_NCOUNTERS)
148956b2bdd1SGireesh Nagabhushana 			return (EINVAL);
149056b2bdd1SGireesh Nagabhushana 		if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1))
149156b2bdd1SGireesh Nagabhushana 			return (0);
149256b2bdd1SGireesh Nagabhushana 
149356b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
149456b2bdd1SGireesh Nagabhushana 		pi->pktc_idx = v < 0 ? -1 : v;
149556b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
149656b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) |
149756b2bdd1SGireesh Nagabhushana 			    /* takes effect right away */
149856b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(v >= 0);
149956b2bdd1SGireesh Nagabhushana 			/* LINTED: E_ASSIGN_NARROW_CONV */
150056b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */
150156b2bdd1SGireesh Nagabhushana 		}
150256b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_CSUM) == 0) {
150356b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
150456b2bdd1SGireesh Nagabhushana 			return (EINVAL);
150556b2bdd1SGireesh Nagabhushana 		if (v == 1)
150656b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_CSUM;
150756b2bdd1SGireesh Nagabhushana 		else
150856b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_CSUM;
150956b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_LSO) == 0) {
151056b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
151156b2bdd1SGireesh Nagabhushana 			return (EINVAL);
151256b2bdd1SGireesh Nagabhushana 		if (v == 1)
151356b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_LSO;
151456b2bdd1SGireesh Nagabhushana 		else
151556b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_LSO;
151656b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_TX_PAUSE) == 0) {
151756b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
151856b2bdd1SGireesh Nagabhushana 			return (EINVAL);
151956b2bdd1SGireesh Nagabhushana 
152056b2bdd1SGireesh Nagabhushana 		if (v != 0)
152156b2bdd1SGireesh Nagabhushana 			lc->requested_fc |= PAUSE_TX;
152256b2bdd1SGireesh Nagabhushana 		else
152356b2bdd1SGireesh Nagabhushana 			lc->requested_fc &= ~PAUSE_TX;
152456b2bdd1SGireesh Nagabhushana 
152556b2bdd1SGireesh Nagabhushana 		relink = 1;
152656b2bdd1SGireesh Nagabhushana 
152756b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_RX_PAUSE) == 0) {
152856b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
152956b2bdd1SGireesh Nagabhushana 			return (EINVAL);
153056b2bdd1SGireesh Nagabhushana 
153156b2bdd1SGireesh Nagabhushana 		if (v != 0)
153256b2bdd1SGireesh Nagabhushana 			lc->requested_fc |= PAUSE_RX;
153356b2bdd1SGireesh Nagabhushana 		else
153456b2bdd1SGireesh Nagabhushana 			lc->requested_fc &= ~PAUSE_RX;
153556b2bdd1SGireesh Nagabhushana 
153656b2bdd1SGireesh Nagabhushana 		relink = 1;
153756b2bdd1SGireesh Nagabhushana 	}
153856b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
153956b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0) {
154056b2bdd1SGireesh Nagabhushana 		if (v < 46 || v > MAX_MTU)
154156b2bdd1SGireesh Nagabhushana 			return (EINVAL);
154256b2bdd1SGireesh Nagabhushana 		if (v == pi->mtu)
154356b2bdd1SGireesh Nagabhushana 			return (0);
154456b2bdd1SGireesh Nagabhushana 
154556b2bdd1SGireesh Nagabhushana 		pi->mtu = (int)v;
154656b2bdd1SGireesh Nagabhushana 		(void) mac_maxsdu_update(pi->mh, v);
154756b2bdd1SGireesh Nagabhushana 		rx_mode = 1;
154856b2bdd1SGireesh Nagabhushana 	}
154956b2bdd1SGireesh Nagabhushana #endif
155056b2bdd1SGireesh Nagabhushana 	else
155156b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
155256b2bdd1SGireesh Nagabhushana 
155356b2bdd1SGireesh Nagabhushana 	if (!(relink || rx_mode))
155456b2bdd1SGireesh Nagabhushana 		return (0);
155556b2bdd1SGireesh Nagabhushana 
155656b2bdd1SGireesh Nagabhushana 	/* If we are here, either relink or rx_mode is 1 */
155756b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
155856b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
155956b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
156056b2bdd1SGireesh Nagabhushana 			if (rc != 0)
156156b2bdd1SGireesh Nagabhushana 				return (rc);
15623dde7c95SVishal Kulkarni 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc);
156356b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
156456b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
156556b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
156656b2bdd1SGireesh Nagabhushana 				    "start_link failed:%d", rc);
156756b2bdd1SGireesh Nagabhushana 				/* Restore link_config */
156856b2bdd1SGireesh Nagabhushana 				bcopy(&lc_old, lc, sizeof (struct link_config));
156956b2bdd1SGireesh Nagabhushana 			}
157056b2bdd1SGireesh Nagabhushana 		} else if (rx_mode != 0) {
157156b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
157256b2bdd1SGireesh Nagabhushana 			if (rc != 0)
157356b2bdd1SGireesh Nagabhushana 				return (rc);
157456b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1,
157556b2bdd1SGireesh Nagabhushana 			    -1, -1, false);
157656b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
157756b2bdd1SGireesh Nagabhushana 			if (rc != 0)  {
157856b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
157956b2bdd1SGireesh Nagabhushana 				    "set_rxmode failed: %d", rc);
158056b2bdd1SGireesh Nagabhushana 			}
158156b2bdd1SGireesh Nagabhushana 		}
158256b2bdd1SGireesh Nagabhushana 		return (rc);
158356b2bdd1SGireesh Nagabhushana 	}
158456b2bdd1SGireesh Nagabhushana 
158556b2bdd1SGireesh Nagabhushana 	return (0);
158656b2bdd1SGireesh Nagabhushana }
158756b2bdd1SGireesh Nagabhushana 
158856b2bdd1SGireesh Nagabhushana void
158956b2bdd1SGireesh Nagabhushana t4_mc_init(struct port_info *pi)
159056b2bdd1SGireesh Nagabhushana {
159156b2bdd1SGireesh Nagabhushana 	pi->props = t4_priv_props;
159256b2bdd1SGireesh Nagabhushana }
159356b2bdd1SGireesh Nagabhushana 
15943dde7c95SVishal Kulkarni void
15953dde7c95SVishal Kulkarni t4_mc_cb_init(struct port_info *pi)
15963dde7c95SVishal Kulkarni {
15973dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
15983dde7c95SVishal Kulkarni 		pi->mc = &t4_m_ring_callbacks;
15993dde7c95SVishal Kulkarni 	else
16003dde7c95SVishal Kulkarni 		pi->mc = &t4_m_callbacks;
16013dde7c95SVishal Kulkarni }
16023dde7c95SVishal Kulkarni 
160356b2bdd1SGireesh Nagabhushana void
160456b2bdd1SGireesh Nagabhushana t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
160556b2bdd1SGireesh Nagabhushana {
160656b2bdd1SGireesh Nagabhushana 	struct port_info *pi = sc->port[idx];
160756b2bdd1SGireesh Nagabhushana 
160856b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN);
160956b2bdd1SGireesh Nagabhushana }
161056b2bdd1SGireesh Nagabhushana 
161156b2bdd1SGireesh Nagabhushana /* ARGSUSED */
161256b2bdd1SGireesh Nagabhushana void
161356b2bdd1SGireesh Nagabhushana t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m)
161456b2bdd1SGireesh Nagabhushana {
161556b2bdd1SGireesh Nagabhushana 	mac_rx(pi->mh, NULL, m);
161656b2bdd1SGireesh Nagabhushana }
16173dde7c95SVishal Kulkarni 
16183dde7c95SVishal Kulkarni void
16193dde7c95SVishal Kulkarni t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq)
16203dde7c95SVishal Kulkarni {
16213dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
16223dde7c95SVishal Kulkarni 		mac_tx_ring_update(pi->mh, txq->ring_handle);
16233dde7c95SVishal Kulkarni 	else
16243dde7c95SVishal Kulkarni 		mac_tx_update(pi->mh);
16253dde7c95SVishal Kulkarni }
1626