156b2bdd1SGireesh Nagabhushana /*
256b2bdd1SGireesh Nagabhushana  * This file and its contents are supplied under the terms of the
356b2bdd1SGireesh Nagabhushana  * Common Development and Distribution License ("CDDL"), version 1.0.
456b2bdd1SGireesh Nagabhushana  * You may only use this file in accordance with the terms of version
556b2bdd1SGireesh Nagabhushana  * 1.0 of the CDDL.
656b2bdd1SGireesh Nagabhushana  *
756b2bdd1SGireesh Nagabhushana  * A full copy of the text of the CDDL should have accompanied this
856b2bdd1SGireesh Nagabhushana  * source. A copy of the CDDL is also available via the Internet at
956b2bdd1SGireesh Nagabhushana  * http://www.illumos.org/license/CDDL.
1056b2bdd1SGireesh Nagabhushana  */
1156b2bdd1SGireesh Nagabhushana 
1256b2bdd1SGireesh Nagabhushana /*
1356b2bdd1SGireesh Nagabhushana  * This file is part of the Chelsio T4 support code.
1456b2bdd1SGireesh Nagabhushana  *
1556b2bdd1SGireesh Nagabhushana  * Copyright (C) 2010-2013 Chelsio Communications.  All rights reserved.
1656b2bdd1SGireesh Nagabhushana  *
1756b2bdd1SGireesh Nagabhushana  * This program is distributed in the hope that it will be useful, but WITHOUT
1856b2bdd1SGireesh Nagabhushana  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1956b2bdd1SGireesh Nagabhushana  * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
2056b2bdd1SGireesh Nagabhushana  * release for licensing terms and conditions.
2156b2bdd1SGireesh Nagabhushana  */
2256b2bdd1SGireesh Nagabhushana 
23d77e6e0fSPaul Winder /*
24d77e6e0fSPaul Winder  * Copyright 2020 RackTop Systems, Inc.
25*d75c6062SRobert 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) {
13056b2bdd1SGireesh Nagabhushana 			*val = lc->speed;
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 
2393dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_40GFDX:
2407e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
2413dde7c95SVishal Kulkarni 		break;
2423dde7c95SVishal Kulkarni 
2433dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_25GFDX:
2447e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
2453dde7c95SVishal Kulkarni 		break;
2463dde7c95SVishal Kulkarni 
2473dde7c95SVishal Kulkarni 	case ETHER_STAT_CAP_10GFDX:
2487e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
2493dde7c95SVishal Kulkarni 		break;
2503dde7c95SVishal Kulkarni 
25156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_1000FDX:
2527e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
25356b2bdd1SGireesh Nagabhushana 		break;
25456b2bdd1SGireesh Nagabhushana 
25556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_1000HDX:
25656b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
25756b2bdd1SGireesh Nagabhushana 
25856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100FDX:
2597e6ad469SVishal Kulkarni 		*val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
26056b2bdd1SGireesh Nagabhushana 		break;
26156b2bdd1SGireesh Nagabhushana 
26256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_100HDX:
26356b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
26456b2bdd1SGireesh Nagabhushana 
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:
27056b2bdd1SGireesh Nagabhushana 		*val = 0;
27156b2bdd1SGireesh Nagabhushana 		break;
27256b2bdd1SGireesh Nagabhushana 
27356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_CAP_PAUSE:
27456b2bdd1SGireesh Nagabhushana 		*val = 1;
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:
30556b2bdd1SGireesh Nagabhushana 		*val = (((lc->requested_fc & PAUSE_TX) ? 1 : 0) ^
30656b2bdd1SGireesh Nagabhushana 		    (lc->requested_fc & PAUSE_RX));
30756b2bdd1SGireesh Nagabhushana 		break;
30856b2bdd1SGireesh Nagabhushana 
30956b2bdd1SGireesh Nagabhushana 	/* Advertised pause capability */
31056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_PAUSE:
31156b2bdd1SGireesh Nagabhushana 		*val = (lc->requested_fc & PAUSE_TX) ? 1 : 0;
31256b2bdd1SGireesh Nagabhushana 		break;
31356b2bdd1SGireesh Nagabhushana 
3143dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_100GFDX:
3157e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_100G);
3163dde7c95SVishal Kulkarni 		break;
3173dde7c95SVishal Kulkarni 
3183dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_40GFDX:
3197e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_40G);
3203dde7c95SVishal Kulkarni 		break;
3213dde7c95SVishal Kulkarni 
3223dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_25GFDX:
3237e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_25G);
3243dde7c95SVishal Kulkarni 		break;
3253dde7c95SVishal Kulkarni 
3263dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_10GFDX:
3277e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_10G);
3283dde7c95SVishal Kulkarni 		break;
3293dde7c95SVishal Kulkarni 
33056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000FDX:
3317e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_1G);
3323dde7c95SVishal Kulkarni 		break;
3333dde7c95SVishal Kulkarni 
3343dde7c95SVishal Kulkarni 	case ETHER_STAT_ADV_CAP_AUTONEG:
3357e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_ANEG);
3363dde7c95SVishal Kulkarni 		break;
3373dde7c95SVishal Kulkarni 
33856b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_1000HDX:
33956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_100FDX:
34056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_100HDX:
34156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10FDX:
34256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_ADV_CAP_10HDX:
34356b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);	/* TODO */
34456b2bdd1SGireesh Nagabhushana 
3453dde7c95SVishal Kulkarni 
3463dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_100GFDX:
3477e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_100G);
3483dde7c95SVishal Kulkarni 		break;
3493dde7c95SVishal Kulkarni 
3503dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_40GFDX:
3517e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_40G);
3523dde7c95SVishal Kulkarni 		break;
3533dde7c95SVishal Kulkarni 
3543dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_25GFDX:
3557e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_25G);
3563dde7c95SVishal Kulkarni 		break;
3573dde7c95SVishal Kulkarni 
3583dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_10GFDX:
3597e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_10G);
3603dde7c95SVishal Kulkarni 		break;
3613dde7c95SVishal Kulkarni 
36256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000FDX:
3637e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_SPEED_1G);
3643dde7c95SVishal Kulkarni 		break;
3653dde7c95SVishal Kulkarni 
3663dde7c95SVishal Kulkarni 	case ETHER_STAT_LP_CAP_AUTONEG:
3677e6ad469SVishal Kulkarni 		*val = !!(lc->acaps & FW_PORT_CAP32_ANEG);
3683dde7c95SVishal Kulkarni 		break;
3693dde7c95SVishal Kulkarni 
37056b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_1000HDX:
37156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_100FDX:
37256b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_100HDX:
37356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10FDX:
37456b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_10HDX:
37556b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_ASMPAUSE:
37656b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LP_CAP_PAUSE:
37756b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
37856b2bdd1SGireesh Nagabhushana 
37956b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_ASMPAUSE:
38056b2bdd1SGireesh Nagabhushana 		*val = 0;
38156b2bdd1SGireesh Nagabhushana 		break;
38256b2bdd1SGireesh Nagabhushana 
38356b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_PAUSE:
38456b2bdd1SGireesh Nagabhushana 		*val = 1;
38556b2bdd1SGireesh Nagabhushana 		break;
38656b2bdd1SGireesh Nagabhushana 
38756b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_AUTONEG:
38856b2bdd1SGireesh Nagabhushana 		*val = lc->autoneg == AUTONEG_ENABLE;
38956b2bdd1SGireesh Nagabhushana 		break;
39056b2bdd1SGireesh Nagabhushana 
39156b2bdd1SGireesh Nagabhushana 	case ETHER_STAT_LINK_DUPLEX:
39256b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0)
39356b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_FULL;
39456b2bdd1SGireesh Nagabhushana 		else
39556b2bdd1SGireesh Nagabhushana 			*val = LINK_DUPLEX_UNKNOWN;
39656b2bdd1SGireesh Nagabhushana 		break;
39756b2bdd1SGireesh Nagabhushana 
39856b2bdd1SGireesh Nagabhushana 	default:
39956b2bdd1SGireesh Nagabhushana #ifdef DEBUG
40056b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE, "stat %d not implemented.", stat);
40156b2bdd1SGireesh Nagabhushana #endif
40256b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
40356b2bdd1SGireesh Nagabhushana 	}
40456b2bdd1SGireesh Nagabhushana #undef GET_STAT
40556b2bdd1SGireesh Nagabhushana 
40656b2bdd1SGireesh Nagabhushana 	return (0);
40756b2bdd1SGireesh Nagabhushana }
40856b2bdd1SGireesh Nagabhushana 
40956b2bdd1SGireesh Nagabhushana static int
41056b2bdd1SGireesh Nagabhushana t4_mc_start(void *arg)
41156b2bdd1SGireesh Nagabhushana {
41256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
41356b2bdd1SGireesh Nagabhushana 	int rc;
41456b2bdd1SGireesh Nagabhushana 
41556b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 0, 1);
41656b2bdd1SGireesh Nagabhushana 	if (rc != 0)
41756b2bdd1SGireesh Nagabhushana 		return (rc);
41856b2bdd1SGireesh Nagabhushana 	rc = t4_init_synchronized(pi);
41956b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
42056b2bdd1SGireesh Nagabhushana 
42156b2bdd1SGireesh Nagabhushana 	return (rc);
42256b2bdd1SGireesh Nagabhushana }
42356b2bdd1SGireesh Nagabhushana 
42456b2bdd1SGireesh Nagabhushana static void
42556b2bdd1SGireesh Nagabhushana t4_mc_stop(void *arg)
42656b2bdd1SGireesh Nagabhushana {
42756b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
42856b2bdd1SGireesh Nagabhushana 
42956b2bdd1SGireesh Nagabhushana 	while (begin_synchronized_op(pi, 0, 1) != 0)
43056b2bdd1SGireesh Nagabhushana 		continue;
43156b2bdd1SGireesh Nagabhushana 	(void) t4_uninit_synchronized(pi);
43256b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 0);
43356b2bdd1SGireesh Nagabhushana }
43456b2bdd1SGireesh Nagabhushana 
43556b2bdd1SGireesh Nagabhushana static int
43656b2bdd1SGireesh Nagabhushana t4_mc_setpromisc(void *arg, boolean_t on)
43756b2bdd1SGireesh Nagabhushana {
43856b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
43956b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
44056b2bdd1SGireesh Nagabhushana 	int rc;
44156b2bdd1SGireesh Nagabhushana 
44256b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
44356b2bdd1SGireesh Nagabhushana 	if (rc != 0)
44456b2bdd1SGireesh Nagabhushana 		return (rc);
44556b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
44656b2bdd1SGireesh Nagabhushana 	    false);
44756b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
44856b2bdd1SGireesh Nagabhushana 
44956b2bdd1SGireesh Nagabhushana 	return (rc);
45056b2bdd1SGireesh Nagabhushana }
45156b2bdd1SGireesh Nagabhushana 
45256b2bdd1SGireesh Nagabhushana /*
45356b2bdd1SGireesh Nagabhushana  * TODO: Starts failing as soon as the 336 entry table fills up.  Need to use
45456b2bdd1SGireesh Nagabhushana  * hash in that case.
45556b2bdd1SGireesh Nagabhushana  */
45656b2bdd1SGireesh Nagabhushana static int
45756b2bdd1SGireesh Nagabhushana t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
45856b2bdd1SGireesh Nagabhushana {
45956b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
46056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
46156b2bdd1SGireesh Nagabhushana 	struct fw_vi_mac_cmd c;
46256b2bdd1SGireesh Nagabhushana 	int len16, rc;
46356b2bdd1SGireesh Nagabhushana 
46456b2bdd1SGireesh Nagabhushana 	len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
46556b2bdd1SGireesh Nagabhushana 	    sizeof (c.u.exact[0]), 16);
46656b2bdd1SGireesh Nagabhushana 	c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
46756b2bdd1SGireesh Nagabhushana 	    F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
46856b2bdd1SGireesh Nagabhushana 	c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
46956b2bdd1SGireesh Nagabhushana 	c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
47056b2bdd1SGireesh Nagabhushana 	    V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
47156b2bdd1SGireesh Nagabhushana 	    FW_VI_MAC_MAC_BASED_FREE));
47256b2bdd1SGireesh Nagabhushana 	bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
47356b2bdd1SGireesh Nagabhushana 
47456b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
47556b2bdd1SGireesh Nagabhushana 	if (rc != 0)
47656b2bdd1SGireesh Nagabhushana 		return (rc);
47756b2bdd1SGireesh Nagabhushana 	rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
47856b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
47956b2bdd1SGireesh Nagabhushana 	if (rc != 0)
48056b2bdd1SGireesh Nagabhushana 		return (rc);
48156b2bdd1SGireesh Nagabhushana #ifdef DEBUG
48256b2bdd1SGireesh Nagabhushana 	/*
48356b2bdd1SGireesh Nagabhushana 	 * TODO: Firmware doesn't seem to return the correct index on removal
48456b2bdd1SGireesh Nagabhushana 	 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
48556b2bdd1SGireesh Nagabhushana 	 * code once it is fixed.
48656b2bdd1SGireesh Nagabhushana 	 */
48756b2bdd1SGireesh Nagabhushana 	else {
48856b2bdd1SGireesh Nagabhushana 		uint16_t idx;
48956b2bdd1SGireesh Nagabhushana 
49056b2bdd1SGireesh Nagabhushana 		idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
49156b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_NOTE,
49256b2bdd1SGireesh Nagabhushana 		    "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
49356b2bdd1SGireesh Nagabhushana 		    mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
49456b2bdd1SGireesh Nagabhushana 		    add ? "added at index" : "removed from index", idx);
49556b2bdd1SGireesh Nagabhushana 	}
49656b2bdd1SGireesh Nagabhushana #endif
49756b2bdd1SGireesh Nagabhushana 
49856b2bdd1SGireesh Nagabhushana 	return (0);
49956b2bdd1SGireesh Nagabhushana }
50056b2bdd1SGireesh Nagabhushana 
5013dde7c95SVishal Kulkarni int
50256b2bdd1SGireesh Nagabhushana t4_mc_unicst(void *arg, const uint8_t *ucaddr)
50356b2bdd1SGireesh Nagabhushana {
50456b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
50556b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
50656b2bdd1SGireesh Nagabhushana 	int rc;
50756b2bdd1SGireesh Nagabhushana 
5083dde7c95SVishal Kulkarni 	if (ucaddr == NULL)
5093dde7c95SVishal Kulkarni 		return (EINVAL);
5103dde7c95SVishal Kulkarni 
51156b2bdd1SGireesh Nagabhushana 	rc = begin_synchronized_op(pi, 1, 1);
51256b2bdd1SGireesh Nagabhushana 	if (rc != 0)
51356b2bdd1SGireesh Nagabhushana 		return (rc);
5143dde7c95SVishal Kulkarni 
5153dde7c95SVishal Kulkarni 	/* We will support adding only one mac address */
5163dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
5173dde7c95SVishal Kulkarni 		end_synchronized_op(pi, 1);
5183dde7c95SVishal Kulkarni 		return (ENOSPC);
5193dde7c95SVishal Kulkarni 	}
52056b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
5217e6ad469SVishal Kulkarni 			   true, &pi->smt_idx);
52256b2bdd1SGireesh Nagabhushana 	if (rc < 0)
52356b2bdd1SGireesh Nagabhushana 		rc = -rc;
52456b2bdd1SGireesh Nagabhushana 	else {
5253dde7c95SVishal Kulkarni 		pi->macaddr_cnt++;
52656b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
52756b2bdd1SGireesh Nagabhushana 		rc = 0;
52856b2bdd1SGireesh Nagabhushana 	}
52956b2bdd1SGireesh Nagabhushana 	end_synchronized_op(pi, 1);
53056b2bdd1SGireesh Nagabhushana 
53156b2bdd1SGireesh Nagabhushana 	return (rc);
53256b2bdd1SGireesh Nagabhushana }
53356b2bdd1SGireesh Nagabhushana 
5343dde7c95SVishal Kulkarni int
5353dde7c95SVishal Kulkarni t4_addmac(void *arg, const uint8_t *ucaddr)
5363dde7c95SVishal Kulkarni {
5373dde7c95SVishal Kulkarni 	return (t4_mc_unicst(arg, ucaddr));
5383dde7c95SVishal Kulkarni }
5393dde7c95SVishal Kulkarni 
5403dde7c95SVishal Kulkarni static int
5413dde7c95SVishal Kulkarni t4_remmac(void *arg, const uint8_t *mac_addr)
5423dde7c95SVishal Kulkarni {
5433dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
5443dde7c95SVishal Kulkarni 	int rc;
5453dde7c95SVishal Kulkarni 
5463dde7c95SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
5473dde7c95SVishal Kulkarni 	if (rc != 0)
5483dde7c95SVishal Kulkarni 		return (rc);
5493dde7c95SVishal Kulkarni 
5503dde7c95SVishal Kulkarni 	pi->macaddr_cnt--;
5513dde7c95SVishal Kulkarni 	end_synchronized_op(pi, 1);
5523dde7c95SVishal Kulkarni 
5533dde7c95SVishal Kulkarni 	return (0);
5543dde7c95SVishal Kulkarni }
5553dde7c95SVishal Kulkarni 
5563dde7c95SVishal Kulkarni /*
5573dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all groups.
5583dde7c95SVishal Kulkarni  */
5593dde7c95SVishal Kulkarni void
5603dde7c95SVishal Kulkarni t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
5613dde7c95SVishal Kulkarni 	      mac_group_info_t *infop, mac_group_handle_t gh)
5623dde7c95SVishal Kulkarni {
5633dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
5643dde7c95SVishal Kulkarni 
5653dde7c95SVishal Kulkarni 	switch (rtype) {
5663dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
5673dde7c95SVishal Kulkarni 		infop->mgi_driver = (mac_group_driver_t)arg;
5683dde7c95SVishal Kulkarni 		infop->mgi_start = NULL;
5693dde7c95SVishal Kulkarni 		infop->mgi_stop = NULL;
5703dde7c95SVishal Kulkarni 		infop->mgi_addmac = t4_addmac;
5713dde7c95SVishal Kulkarni 		infop->mgi_remmac = t4_remmac;
5723dde7c95SVishal Kulkarni 		infop->mgi_count = pi->nrxq;
5733dde7c95SVishal Kulkarni 		break;
5743dde7c95SVishal Kulkarni 	}
5753dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX:
5763dde7c95SVishal Kulkarni 	default:
5773dde7c95SVishal Kulkarni 		ASSERT(0);
5783dde7c95SVishal Kulkarni 		break;
5793dde7c95SVishal Kulkarni 	}
5803dde7c95SVishal Kulkarni }
5813dde7c95SVishal Kulkarni 
5823dde7c95SVishal Kulkarni static int
5833dde7c95SVishal Kulkarni t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
5843dde7c95SVishal Kulkarni {
5853dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
5863dde7c95SVishal Kulkarni 
5873dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
5883dde7c95SVishal Kulkarni 	rxq->ring_gen_num = mr_gen_num;
5893dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
5903dde7c95SVishal Kulkarni 	return (0);
5913dde7c95SVishal Kulkarni }
5923dde7c95SVishal Kulkarni 
5933dde7c95SVishal Kulkarni /*
5943dde7c95SVishal Kulkarni  * Enable interrupt on the specificed rx ring.
5953dde7c95SVishal Kulkarni  */
5963dde7c95SVishal Kulkarni int
5973dde7c95SVishal Kulkarni t4_ring_intr_enable(mac_intr_handle_t intrh)
5983dde7c95SVishal Kulkarni {
5993dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
6003dde7c95SVishal Kulkarni 	struct adapter *sc = rxq->port->adapter;
6013dde7c95SVishal Kulkarni 	struct sge_iq *iq;
6023dde7c95SVishal Kulkarni 
6033dde7c95SVishal Kulkarni 	iq = &rxq->iq;
6043dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6053dde7c95SVishal Kulkarni 	iq->polling = 0;
6063dde7c95SVishal Kulkarni 	iq->state = IQS_IDLE;
6073dde7c95SVishal Kulkarni 	t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
6083dde7c95SVishal Kulkarni 		     V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id));
6093dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6103dde7c95SVishal Kulkarni 	return (0);
6113dde7c95SVishal Kulkarni }
6123dde7c95SVishal Kulkarni 
6133dde7c95SVishal Kulkarni /*
6143dde7c95SVishal Kulkarni  * Disable interrupt on the specificed rx ring.
6153dde7c95SVishal Kulkarni  */
6163dde7c95SVishal Kulkarni int
6173dde7c95SVishal Kulkarni t4_ring_intr_disable(mac_intr_handle_t intrh)
6183dde7c95SVishal Kulkarni {
6193dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)intrh;
6203dde7c95SVishal Kulkarni 	struct sge_iq *iq;
6213dde7c95SVishal Kulkarni 
6223dde7c95SVishal Kulkarni 	/* Nothing to be done here wrt interrupt, as it
6233dde7c95SVishal Kulkarni 	 * will not fire, until we write back to
6243dde7c95SVishal Kulkarni 	 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable.
6253dde7c95SVishal Kulkarni 	 */
6263dde7c95SVishal Kulkarni 
6273dde7c95SVishal Kulkarni 	iq = &rxq->iq;
6283dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6293dde7c95SVishal Kulkarni 	iq->polling = 1;
6303dde7c95SVishal Kulkarni 	iq->state = IQS_BUSY;
6313dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6323dde7c95SVishal Kulkarni 	return (0);
6333dde7c95SVishal Kulkarni }
6343dde7c95SVishal Kulkarni 
6353dde7c95SVishal Kulkarni mblk_t *
6363dde7c95SVishal Kulkarni t4_poll_ring(void *arg, int n_bytes)
6373dde7c95SVishal Kulkarni {
6383dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)arg;
6393dde7c95SVishal Kulkarni 	mblk_t *mp = NULL;
6403dde7c95SVishal Kulkarni 
6413dde7c95SVishal Kulkarni 	ASSERT(n_bytes >= 0);
6423dde7c95SVishal Kulkarni 	if (n_bytes == 0)
6433dde7c95SVishal Kulkarni 		return (NULL);
6443dde7c95SVishal Kulkarni 
6453dde7c95SVishal Kulkarni 	RXQ_LOCK(rxq);
6463dde7c95SVishal Kulkarni 	mp = t4_ring_rx(rxq, n_bytes);
6473dde7c95SVishal Kulkarni 	RXQ_UNLOCK(rxq);
6483dde7c95SVishal Kulkarni 
6493dde7c95SVishal Kulkarni 	return (mp);
6503dde7c95SVishal Kulkarni }
6513dde7c95SVishal Kulkarni 
6523dde7c95SVishal Kulkarni /*
6533dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular rx ring
6543dde7c95SVishal Kulkarni  */
6553dde7c95SVishal Kulkarni int
6563dde7c95SVishal Kulkarni t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
6573dde7c95SVishal Kulkarni {
6583dde7c95SVishal Kulkarni 	struct sge_rxq *rxq = (struct sge_rxq *)rh;
6593dde7c95SVishal Kulkarni 
6603dde7c95SVishal Kulkarni 	switch (stat) {
6613dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
6623dde7c95SVishal Kulkarni 		*val = rxq->rxbytes;
6633dde7c95SVishal Kulkarni 		break;
6643dde7c95SVishal Kulkarni 
6653dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
6663dde7c95SVishal Kulkarni 		*val = rxq->rxpkts;
6673dde7c95SVishal Kulkarni 		break;
6683dde7c95SVishal Kulkarni 
6693dde7c95SVishal Kulkarni 	default:
6703dde7c95SVishal Kulkarni 		*val = 0;
6713dde7c95SVishal Kulkarni 		return (ENOTSUP);
6723dde7c95SVishal Kulkarni 	}
6733dde7c95SVishal Kulkarni 
6743dde7c95SVishal Kulkarni 	return (0);
6753dde7c95SVishal Kulkarni }
6763dde7c95SVishal Kulkarni 
6773dde7c95SVishal Kulkarni /*
6783dde7c95SVishal Kulkarni  * Retrieve a value for one of the statistics for a particular tx ring
6793dde7c95SVishal Kulkarni  */
6803dde7c95SVishal Kulkarni int
6813dde7c95SVishal Kulkarni t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
6823dde7c95SVishal Kulkarni {
6833dde7c95SVishal Kulkarni 	struct sge_txq *txq = (struct sge_txq *)rh;
6843dde7c95SVishal Kulkarni 
6853dde7c95SVishal Kulkarni 	switch (stat) {
6863dde7c95SVishal Kulkarni 	case MAC_STAT_RBYTES:
6873dde7c95SVishal Kulkarni 		*val = txq->txbytes;
6883dde7c95SVishal Kulkarni 		break;
6893dde7c95SVishal Kulkarni 
6903dde7c95SVishal Kulkarni 	case MAC_STAT_IPACKETS:
6913dde7c95SVishal Kulkarni 		*val = txq->txpkts;
6923dde7c95SVishal Kulkarni 		break;
6933dde7c95SVishal Kulkarni 
6943dde7c95SVishal Kulkarni 	default:
6953dde7c95SVishal Kulkarni 		*val = 0;
6963dde7c95SVishal Kulkarni 		return (ENOTSUP);
6973dde7c95SVishal Kulkarni 	}
6983dde7c95SVishal Kulkarni 
6993dde7c95SVishal Kulkarni 	return (0);
7003dde7c95SVishal Kulkarni }
7013dde7c95SVishal Kulkarni 
7023dde7c95SVishal Kulkarni /*
7033dde7c95SVishal Kulkarni  * Callback funtion for MAC layer to register all rings
7043dde7c95SVishal Kulkarni  * for given ring_group, noted by group_index.
7053dde7c95SVishal Kulkarni  * Since we have only one group, ring index becomes
7063dde7c95SVishal Kulkarni  * absolute index.
7073dde7c95SVishal Kulkarni  */
7083dde7c95SVishal Kulkarni void
7093dde7c95SVishal Kulkarni t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
7103dde7c95SVishal Kulkarni 	     const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
7113dde7c95SVishal Kulkarni {
7123dde7c95SVishal Kulkarni 	struct port_info *pi = arg;
7133dde7c95SVishal Kulkarni 	mac_intr_t *mintr;
7143dde7c95SVishal Kulkarni 
7153dde7c95SVishal Kulkarni 	switch (rtype) {
7163dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_RX: {
7173dde7c95SVishal Kulkarni 		struct sge_rxq *rxq;
7183dde7c95SVishal Kulkarni 
7193dde7c95SVishal Kulkarni 		rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
7203dde7c95SVishal Kulkarni 		rxq->ring_handle = rh;
7213dde7c95SVishal Kulkarni 
7223dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)rxq;
7233dde7c95SVishal Kulkarni 		infop->mri_start = t4_ring_start;
7243dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
7253dde7c95SVishal Kulkarni 		infop->mri_poll = t4_poll_ring;
7263dde7c95SVishal Kulkarni 		infop->mri_stat = t4_rx_stat;
7273dde7c95SVishal Kulkarni 
7283dde7c95SVishal Kulkarni 		mintr = &infop->mri_intr;
7293dde7c95SVishal Kulkarni 		mintr->mi_handle = (mac_intr_handle_t)rxq;
7303dde7c95SVishal Kulkarni 		mintr->mi_enable = t4_ring_intr_enable;
7313dde7c95SVishal Kulkarni 		mintr->mi_disable = t4_ring_intr_disable;
7323dde7c95SVishal Kulkarni 
7333dde7c95SVishal Kulkarni 		break;
7343dde7c95SVishal Kulkarni 	}
7353dde7c95SVishal Kulkarni 	case MAC_RING_TYPE_TX: {
7363dde7c95SVishal Kulkarni 		struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index];
7373dde7c95SVishal Kulkarni 		txq->ring_handle = rh;
7383dde7c95SVishal Kulkarni 		infop->mri_driver = (mac_ring_driver_t)txq;
7393dde7c95SVishal Kulkarni 		infop->mri_start = NULL;
7403dde7c95SVishal Kulkarni 		infop->mri_stop = NULL;
7413dde7c95SVishal Kulkarni 		infop->mri_tx = t4_eth_tx;
7423dde7c95SVishal Kulkarni 		infop->mri_stat = t4_tx_stat;
7433dde7c95SVishal Kulkarni 		break;
7443dde7c95SVishal Kulkarni 	}
7453dde7c95SVishal Kulkarni 	default:
7463dde7c95SVishal Kulkarni 		ASSERT(0);
7473dde7c95SVishal Kulkarni 		break;
7483dde7c95SVishal Kulkarni 	}
7493dde7c95SVishal Kulkarni }
7503dde7c95SVishal Kulkarni 
7513dde7c95SVishal Kulkarni mblk_t *
75256b2bdd1SGireesh Nagabhushana t4_mc_tx(void *arg, mblk_t *m)
75356b2bdd1SGireesh Nagabhushana {
75456b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
75556b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
75656b2bdd1SGireesh Nagabhushana 	struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
75756b2bdd1SGireesh Nagabhushana 
7583dde7c95SVishal Kulkarni 	return (t4_eth_tx(txq, m));
75956b2bdd1SGireesh Nagabhushana }
76056b2bdd1SGireesh Nagabhushana 
761017c366dSRobert Mustacchi static int
762017c366dSRobert Mustacchi t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
763017c366dSRobert Mustacchi {
764017c366dSRobert Mustacchi 	struct port_info *pi = arg;
765017c366dSRobert Mustacchi 
766017c366dSRobert Mustacchi 	if (id != 0 || infop == NULL)
767017c366dSRobert Mustacchi 		return (EINVAL);
768017c366dSRobert Mustacchi 
769017c366dSRobert Mustacchi 	switch (pi->mod_type) {
770017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NONE:
771017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_FALSE);
772017c366dSRobert Mustacchi 		break;
773017c366dSRobert Mustacchi 	case FW_PORT_MOD_TYPE_NOTSUPPORTED:
774017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
775017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_FALSE);
776017c366dSRobert Mustacchi 		break;
777017c366dSRobert Mustacchi 	default:
778017c366dSRobert Mustacchi 		mac_transceiver_info_set_present(infop, B_TRUE);
779017c366dSRobert Mustacchi 		mac_transceiver_info_set_usable(infop, B_TRUE);
780017c366dSRobert Mustacchi 		break;
781017c366dSRobert Mustacchi 	}
782017c366dSRobert Mustacchi 
783017c366dSRobert Mustacchi 	return (0);
784017c366dSRobert Mustacchi }
785017c366dSRobert Mustacchi 
786017c366dSRobert Mustacchi static int
787017c366dSRobert Mustacchi t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
788017c366dSRobert Mustacchi     size_t nbytes, off_t offset, size_t *nread)
789017c366dSRobert Mustacchi {
790017c366dSRobert Mustacchi 	struct port_info *pi = arg;
791017c366dSRobert Mustacchi 	struct adapter *sc = pi->adapter;
792017c366dSRobert Mustacchi 	int rc;
793017c366dSRobert Mustacchi 	size_t i, maxread;
794017c366dSRobert Mustacchi 	/* LINTED: E_FUNC_VAR_UNUSED */
795017c366dSRobert Mustacchi 	struct fw_ldst_cmd ldst __unused;
796017c366dSRobert Mustacchi 
797017c366dSRobert Mustacchi 	if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
798017c366dSRobert Mustacchi 	    (page != 0xa0 && page != 0xa2) || offset < 0)
799017c366dSRobert Mustacchi 		return (EINVAL);
800017c366dSRobert Mustacchi 
801017c366dSRobert Mustacchi 	if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
802017c366dSRobert Mustacchi 		return (EINVAL);
803017c366dSRobert Mustacchi 
804017c366dSRobert Mustacchi 	rc = begin_synchronized_op(pi, 0, 1);
805017c366dSRobert Mustacchi 	if (rc != 0)
806017c366dSRobert Mustacchi 		return (rc);
807017c366dSRobert Mustacchi 
808017c366dSRobert Mustacchi 	/*
809017c366dSRobert Mustacchi 	 * Firmware has a maximum size that we can read. Don't read more than it
810017c366dSRobert Mustacchi 	 * allows.
811017c366dSRobert Mustacchi 	 */
812017c366dSRobert Mustacchi 	maxread = sizeof (ldst.u.i2c.data);
813017c366dSRobert Mustacchi 	for (i = 0; i < nbytes; i += maxread) {
814017c366dSRobert Mustacchi 		size_t toread = MIN(maxread, nbytes - i);
815017c366dSRobert Mustacchi 		rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
816017c366dSRobert Mustacchi 		    bp);
817017c366dSRobert Mustacchi 		if (rc != 0)
818017c366dSRobert Mustacchi 			break;
819017c366dSRobert Mustacchi 		offset += toread;
820017c366dSRobert Mustacchi 		bp = (void *)((uintptr_t)bp + toread);
821017c366dSRobert Mustacchi 	}
822017c366dSRobert Mustacchi 	end_synchronized_op(pi, 0);
823017c366dSRobert Mustacchi 	if (rc == 0)
824017c366dSRobert Mustacchi 		*nread = nbytes;
825017c366dSRobert Mustacchi 	return (rc);
826017c366dSRobert Mustacchi }
827017c366dSRobert Mustacchi 
828d87e4548SVishal Kulkarni static int
829d87e4548SVishal Kulkarni t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
830d87e4548SVishal Kulkarni {
831d87e4548SVishal Kulkarni 	struct port_info *pi = arg;
832d87e4548SVishal Kulkarni 	struct adapter *sc = pi->adapter;
833d87e4548SVishal Kulkarni 	int val, rc;
834d87e4548SVishal Kulkarni 
835d87e4548SVishal Kulkarni 	if (flags != 0)
836d87e4548SVishal Kulkarni 		return (EINVAL);
837d87e4548SVishal Kulkarni 
838d87e4548SVishal Kulkarni 	switch (mode) {
839d87e4548SVishal Kulkarni 	case MAC_LED_DEFAULT:
840d87e4548SVishal Kulkarni 		val = 0;
841d87e4548SVishal Kulkarni 		break;
842d87e4548SVishal Kulkarni 	case MAC_LED_IDENT:
843d87e4548SVishal Kulkarni 		val = 0xffff;
844d87e4548SVishal Kulkarni 		break;
845d87e4548SVishal Kulkarni 
846d87e4548SVishal Kulkarni 	default:
847d87e4548SVishal Kulkarni 		return (ENOTSUP);
848d87e4548SVishal Kulkarni 	}
849d87e4548SVishal Kulkarni 
850d87e4548SVishal Kulkarni 	rc = begin_synchronized_op(pi, 1, 1);
851d87e4548SVishal Kulkarni 	if (rc != 0)
852d87e4548SVishal Kulkarni 		return (rc);
853d87e4548SVishal Kulkarni 	rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
854d87e4548SVishal Kulkarni 	end_synchronized_op(pi, 1);
855d87e4548SVishal Kulkarni 
856d87e4548SVishal Kulkarni 	return (rc);
857d87e4548SVishal Kulkarni }
858d87e4548SVishal Kulkarni 
85956b2bdd1SGireesh Nagabhushana static boolean_t
86056b2bdd1SGireesh Nagabhushana t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
86156b2bdd1SGireesh Nagabhushana {
86256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
86356b2bdd1SGireesh Nagabhushana 	boolean_t status = B_TRUE;
864017c366dSRobert Mustacchi 	mac_capab_transceiver_t *mct;
865d87e4548SVishal Kulkarni 	mac_capab_led_t *mcl;
86656b2bdd1SGireesh Nagabhushana 
86756b2bdd1SGireesh Nagabhushana 	switch (cap) {
86856b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_HCKSUM:
86956b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_CSUM) {
87056b2bdd1SGireesh Nagabhushana 			uint32_t *d = data;
871*d75c6062SRobert Mustacchi 			*d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM |
872*d75c6062SRobert Mustacchi 			    HCKSUM_INET_FULL_V6;
87356b2bdd1SGireesh Nagabhushana 		} else
87456b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
87556b2bdd1SGireesh Nagabhushana 		break;
87656b2bdd1SGireesh Nagabhushana 
87756b2bdd1SGireesh Nagabhushana 	case MAC_CAPAB_LSO:
87856b2bdd1SGireesh Nagabhushana 		/* Enabling LSO requires Checksum offloading */
87956b2bdd1SGireesh Nagabhushana 		if (pi->features & CXGBE_HW_LSO &&
88056b2bdd1SGireesh Nagabhushana 		    pi->features & CXGBE_HW_CSUM) {
88156b2bdd1SGireesh Nagabhushana 			mac_capab_lso_t *d = data;
88256b2bdd1SGireesh Nagabhushana 
883*d75c6062SRobert Mustacchi 			d->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
884*d75c6062SRobert Mustacchi 			    LSO_TX_BASIC_TCP_IPV6;
88556b2bdd1SGireesh Nagabhushana 			d->lso_basic_tcp_ipv4.lso_max = 65535;
886*d75c6062SRobert Mustacchi 			d->lso_basic_tcp_ipv6.lso_max = 65535;
88756b2bdd1SGireesh Nagabhushana 		} else
88856b2bdd1SGireesh Nagabhushana 			status = B_FALSE;
88956b2bdd1SGireesh Nagabhushana 		break;
89056b2bdd1SGireesh Nagabhushana 
8913dde7c95SVishal Kulkarni 	case MAC_CAPAB_RINGS: {
8923dde7c95SVishal Kulkarni 		mac_capab_rings_t *cap_rings = data;
8933dde7c95SVishal Kulkarni 
8943dde7c95SVishal Kulkarni 		if (!pi->adapter->props.multi_rings) {
8953dde7c95SVishal Kulkarni 			status = B_FALSE;
8963dde7c95SVishal Kulkarni 			break;
8973dde7c95SVishal Kulkarni 		}
8983dde7c95SVishal Kulkarni 		switch (cap_rings->mr_type) {
8993dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_RX:
9003dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
9013dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->nrxq;
9023dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 1;
9033dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
9043dde7c95SVishal Kulkarni 			cap_rings->mr_gget = t4_fill_group;
9053dde7c95SVishal Kulkarni 			cap_rings->mr_gaddring = NULL;
9063dde7c95SVishal Kulkarni 			cap_rings->mr_gremring = NULL;
9073dde7c95SVishal Kulkarni 			break;
9083dde7c95SVishal Kulkarni 		case MAC_RING_TYPE_TX:
9093dde7c95SVishal Kulkarni 			cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
9103dde7c95SVishal Kulkarni 			cap_rings->mr_rnum = pi->ntxq;
9113dde7c95SVishal Kulkarni 			cap_rings->mr_gnum = 0;
9123dde7c95SVishal Kulkarni 			cap_rings->mr_rget = t4_fill_ring;
9133dde7c95SVishal Kulkarni 			cap_rings->mr_gget = NULL;
9143dde7c95SVishal Kulkarni 			break;
9153dde7c95SVishal Kulkarni 		}
9163dde7c95SVishal Kulkarni 		break;
9173dde7c95SVishal Kulkarni 	}
918017c366dSRobert Mustacchi 
919017c366dSRobert Mustacchi 	case MAC_CAPAB_TRANSCEIVER:
920017c366dSRobert Mustacchi 		mct = data;
921017c366dSRobert Mustacchi 
922017c366dSRobert Mustacchi 		mct->mct_flags = 0;
923017c366dSRobert Mustacchi 		mct->mct_ntransceivers = 1;
924017c366dSRobert Mustacchi 		mct->mct_info = t4_mc_transceiver_info;
925017c366dSRobert Mustacchi 		mct->mct_read = t4_mc_transceiver_read;
926017c366dSRobert Mustacchi 		break;
927d87e4548SVishal Kulkarni 	case MAC_CAPAB_LED:
928d87e4548SVishal Kulkarni 		mcl = data;
929d87e4548SVishal Kulkarni 		mcl->mcl_flags = 0;
930d87e4548SVishal Kulkarni 		mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
931d87e4548SVishal Kulkarni 		mcl->mcl_set = t4_port_led_set;
932d87e4548SVishal Kulkarni 		break;
933017c366dSRobert Mustacchi 
93456b2bdd1SGireesh Nagabhushana 	default:
93556b2bdd1SGireesh Nagabhushana 		status = B_FALSE; /* cap not supported */
93656b2bdd1SGireesh Nagabhushana 	}
93756b2bdd1SGireesh Nagabhushana 
93856b2bdd1SGireesh Nagabhushana 	return (status);
93956b2bdd1SGireesh Nagabhushana }
94056b2bdd1SGireesh Nagabhushana 
941d77e6e0fSPaul Winder static link_fec_t
942d77e6e0fSPaul Winder fec_to_link_fec(cc_fec_t cc_fec)
943d77e6e0fSPaul Winder {
944d77e6e0fSPaul Winder 	link_fec_t link_fec = 0;
945d77e6e0fSPaul Winder 
946d77e6e0fSPaul Winder 	if ((cc_fec & (FEC_RS | FEC_BASER_RS)) == (FEC_RS | FEC_BASER_RS))
947d77e6e0fSPaul Winder 		return (LINK_FEC_AUTO);
948d77e6e0fSPaul Winder 
949d77e6e0fSPaul Winder 	if ((cc_fec & FEC_NONE) != 0)
950d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_NONE;
951d77e6e0fSPaul Winder 
952d77e6e0fSPaul Winder 	if ((cc_fec & FEC_AUTO) != 0)
953d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_AUTO;
954d77e6e0fSPaul Winder 
955d77e6e0fSPaul Winder 	if ((cc_fec & FEC_RS) != 0)
956d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_RS;
957d77e6e0fSPaul Winder 
958d77e6e0fSPaul Winder 	if ((cc_fec & FEC_BASER_RS) != 0)
959d77e6e0fSPaul Winder 		link_fec |= LINK_FEC_BASE_R;
960d77e6e0fSPaul Winder 
961d77e6e0fSPaul Winder 	return (link_fec);
962d77e6e0fSPaul Winder }
963d77e6e0fSPaul Winder 
964d77e6e0fSPaul Winder static int
965d77e6e0fSPaul Winder link_fec_to_fec(int v)
966d77e6e0fSPaul Winder {
967d77e6e0fSPaul Winder 	int fec = 0;
968d77e6e0fSPaul Winder 
969d77e6e0fSPaul Winder 	if ((v & LINK_FEC_AUTO) != 0) {
970d77e6e0fSPaul Winder 		fec = FEC_AUTO;
971d77e6e0fSPaul Winder 		v &= ~LINK_FEC_AUTO;
972d77e6e0fSPaul Winder 	} else {
973d77e6e0fSPaul Winder 		if ((v & LINK_FEC_NONE) != 0) {
974d77e6e0fSPaul Winder 			fec = FEC_NONE;
975d77e6e0fSPaul Winder 			v &= ~LINK_FEC_NONE;
976d77e6e0fSPaul Winder 		}
977d77e6e0fSPaul Winder 
978d77e6e0fSPaul Winder 		if ((v & LINK_FEC_RS) != 0) {
979d77e6e0fSPaul Winder 			fec |= FEC_RS;
980d77e6e0fSPaul Winder 			v &= ~LINK_FEC_RS;
981d77e6e0fSPaul Winder 		}
982d77e6e0fSPaul Winder 
983d77e6e0fSPaul Winder 		if ((v & LINK_FEC_BASE_R) != 0) {
984d77e6e0fSPaul Winder 			fec |= FEC_BASER_RS;
985d77e6e0fSPaul Winder 			v &= ~LINK_FEC_BASE_R;
986d77e6e0fSPaul Winder 		}
987d77e6e0fSPaul Winder 	}
988d77e6e0fSPaul Winder 
989d77e6e0fSPaul Winder 	if (v != 0)
990d77e6e0fSPaul Winder 		return (-1);
991d77e6e0fSPaul Winder 
992d77e6e0fSPaul Winder 	ASSERT3S(fec, !=, 0);
993d77e6e0fSPaul Winder 
994d77e6e0fSPaul Winder 	return (fec);
995d77e6e0fSPaul Winder }
996d77e6e0fSPaul Winder 
99756b2bdd1SGireesh Nagabhushana /* ARGSUSED */
99856b2bdd1SGireesh Nagabhushana static int
99956b2bdd1SGireesh Nagabhushana t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
100056b2bdd1SGireesh Nagabhushana     const void *val)
100156b2bdd1SGireesh Nagabhushana {
100256b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
100356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
100456b2bdd1SGireesh Nagabhushana 	struct link_config lc_copy, *lc = &pi->link_cfg;
100556b2bdd1SGireesh Nagabhushana 	uint8_t v8 = *(uint8_t *)val;
100656b2bdd1SGireesh Nagabhushana 	uint32_t v32 = *(uint32_t *)val;
100756b2bdd1SGireesh Nagabhushana 	int old, new = 0, relink = 0, rx_mode = 0, rc = 0;
1008d77e6e0fSPaul Winder 	boolean_t down_link = B_TRUE;
100956b2bdd1SGireesh Nagabhushana 	link_flowctrl_t fc;
1010d77e6e0fSPaul Winder 	link_fec_t fec;
101156b2bdd1SGireesh Nagabhushana 
101256b2bdd1SGireesh Nagabhushana 	/*
101356b2bdd1SGireesh Nagabhushana 	 * Save a copy of link_config. This can be used to restore link_config
10143dde7c95SVishal Kulkarni 	 * if t4_link_l1cfg() fails.
101556b2bdd1SGireesh Nagabhushana 	 */
101656b2bdd1SGireesh Nagabhushana 	bcopy(lc, &lc_copy, sizeof (struct link_config));
101756b2bdd1SGireesh Nagabhushana 
101856b2bdd1SGireesh Nagabhushana 	switch (id) {
101956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
10207e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG) {
102156b2bdd1SGireesh Nagabhushana 			old = lc->autoneg;
102256b2bdd1SGireesh Nagabhushana 			new = v8 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
102356b2bdd1SGireesh Nagabhushana 			if (old != new) {
102456b2bdd1SGireesh Nagabhushana 				/* LINTED: E_CONSTANT_CONDITION */
102556b2bdd1SGireesh Nagabhushana 				lc->autoneg = new;
102656b2bdd1SGireesh Nagabhushana 				relink = 1;
102756b2bdd1SGireesh Nagabhushana 				if (new == AUTONEG_DISABLE) {
102856b2bdd1SGireesh Nagabhushana 					/* Only 100M is available */
10297e6ad469SVishal Kulkarni 					lc->speed_caps =
10307e6ad469SVishal Kulkarni 					    FW_PORT_CAP32_SPEED_100M;
10317e6ad469SVishal Kulkarni 					lc->acaps =
10327e6ad469SVishal Kulkarni 					    FW_PORT_CAP32_SPEED_100M;
103356b2bdd1SGireesh Nagabhushana 				} else {
103456b2bdd1SGireesh Nagabhushana 					/*
103556b2bdd1SGireesh Nagabhushana 					 * Advertise autonegotiation capability
103656b2bdd1SGireesh Nagabhushana 					 * along with supported speeds
103756b2bdd1SGireesh Nagabhushana 					 */
10387e6ad469SVishal Kulkarni 					lc->acaps |= (FW_PORT_CAP32_ANEG |
10397e6ad469SVishal Kulkarni 					    (lc->pcaps &
10407e6ad469SVishal Kulkarni 					    (FW_PORT_CAP32_SPEED_100M |
10417e6ad469SVishal Kulkarni 					    FW_PORT_CAP32_SPEED_1G)));
10427e6ad469SVishal Kulkarni 					lc->speed_caps = 0;
104356b2bdd1SGireesh Nagabhushana 				}
104456b2bdd1SGireesh Nagabhushana 			}
104556b2bdd1SGireesh Nagabhushana 		} else
104656b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
104756b2bdd1SGireesh Nagabhushana 		break;
104856b2bdd1SGireesh Nagabhushana 
104956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
105056b2bdd1SGireesh Nagabhushana 		if (v32 < 46 || v32 > MAX_MTU) {
105156b2bdd1SGireesh Nagabhushana 			rc = EINVAL;
105256b2bdd1SGireesh Nagabhushana 		} else if (v32 != pi->mtu) {
105356b2bdd1SGireesh Nagabhushana 			pi->mtu = v32;
105456b2bdd1SGireesh Nagabhushana 			(void) mac_maxsdu_update(pi->mh, v32);
105556b2bdd1SGireesh Nagabhushana 			rx_mode = 1;
105656b2bdd1SGireesh Nagabhushana 		}
105756b2bdd1SGireesh Nagabhushana 
105856b2bdd1SGireesh Nagabhushana 		break;
105956b2bdd1SGireesh Nagabhushana 
106056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
106156b2bdd1SGireesh Nagabhushana 		fc = *(link_flowctrl_t *)val;
106256b2bdd1SGireesh Nagabhushana 		old = lc->requested_fc & (PAUSE_TX | PAUSE_RX);
106356b2bdd1SGireesh Nagabhushana 
106456b2bdd1SGireesh Nagabhushana 		if (fc == LINK_FLOWCTRL_BI)
106556b2bdd1SGireesh Nagabhushana 			new = (PAUSE_TX | PAUSE_RX);
106656b2bdd1SGireesh Nagabhushana 		else if (fc == LINK_FLOWCTRL_TX)
106756b2bdd1SGireesh Nagabhushana 			new = PAUSE_TX;
106856b2bdd1SGireesh Nagabhushana 		else if (fc == LINK_FLOWCTRL_RX)
106956b2bdd1SGireesh Nagabhushana 			new = PAUSE_RX;
107056b2bdd1SGireesh Nagabhushana 
107156b2bdd1SGireesh Nagabhushana 		if (new != old) {
107256b2bdd1SGireesh Nagabhushana 			lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX);
107356b2bdd1SGireesh Nagabhushana 			lc->requested_fc |= new;
107456b2bdd1SGireesh Nagabhushana 			relink = 1;
107556b2bdd1SGireesh Nagabhushana 		}
107656b2bdd1SGireesh Nagabhushana 		break;
107756b2bdd1SGireesh Nagabhushana 
1078d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1079d77e6e0fSPaul Winder 		if (!fec_supported(lc->pcaps)) {
1080d77e6e0fSPaul Winder 			rc = ENOTSUP;
1081d77e6e0fSPaul Winder 			break;
1082d77e6e0fSPaul Winder 		}
1083d77e6e0fSPaul Winder 
1084d77e6e0fSPaul Winder 		fec = *(link_fec_t *)val;
1085d77e6e0fSPaul Winder 		new = link_fec_to_fec(fec);
1086d77e6e0fSPaul Winder 		if (new < 0) {
1087d77e6e0fSPaul Winder 			rc = EINVAL;
1088d77e6e0fSPaul Winder 		} else if (new != lc->requested_fec) {
1089d77e6e0fSPaul Winder 			lc->requested_fec = new;
1090d77e6e0fSPaul Winder 			relink = 1;
1091d77e6e0fSPaul Winder 			/*
1092d77e6e0fSPaul Winder 			 * For fec, do not preemptively force the link
1093d77e6e0fSPaul Winder 			 * down. If changing fec causes the link state
1094d77e6e0fSPaul Winder 			 * to transition, then appropriate asynchronous
1095d77e6e0fSPaul Winder 			 * events are generated which correctly reflect
1096d77e6e0fSPaul Winder 			 * the link state.
1097d77e6e0fSPaul Winder 			 */
1098d77e6e0fSPaul Winder 			down_link = B_FALSE;
1099d77e6e0fSPaul Winder 		}
1100d77e6e0fSPaul Winder 		break;
1101d77e6e0fSPaul Winder 
110256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
11037e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG && is_10G_port(pi)) {
11047e6ad469SVishal Kulkarni 			old = lc->acaps & FW_PORT_CAP32_SPEED_10G;
11057e6ad469SVishal Kulkarni 			new = v8 ? FW_PORT_CAP32_SPEED_10G : 0;
110656b2bdd1SGireesh Nagabhushana 			if (new != old) {
11077e6ad469SVishal Kulkarni 				lc->acaps &= ~FW_PORT_CAP32_SPEED_10G;
11087e6ad469SVishal Kulkarni 				lc->acaps |= new;
110956b2bdd1SGireesh Nagabhushana 				relink = 1;
111056b2bdd1SGireesh Nagabhushana 			}
111156b2bdd1SGireesh Nagabhushana 		} else
111256b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
111356b2bdd1SGireesh Nagabhushana 
111456b2bdd1SGireesh Nagabhushana 		break;
111556b2bdd1SGireesh Nagabhushana 
111656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
111756b2bdd1SGireesh Nagabhushana 		/* Forced 1G */
111856b2bdd1SGireesh Nagabhushana 		if (lc->autoneg == AUTONEG_ENABLE) {
11197e6ad469SVishal Kulkarni 			old = lc->acaps & FW_PORT_CAP32_SPEED_1G;
11207e6ad469SVishal Kulkarni 			new = v8 ? FW_PORT_CAP32_SPEED_1G : 0;
112156b2bdd1SGireesh Nagabhushana 
112256b2bdd1SGireesh Nagabhushana 			if (old != new) {
11237e6ad469SVishal Kulkarni 				lc->acaps &= ~FW_PORT_CAP32_SPEED_1G;
11247e6ad469SVishal Kulkarni 				lc->acaps |= new;
112556b2bdd1SGireesh Nagabhushana 				relink = 1;
112656b2bdd1SGireesh Nagabhushana 			}
112756b2bdd1SGireesh Nagabhushana 		} else
112856b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
112956b2bdd1SGireesh Nagabhushana 		break;
113056b2bdd1SGireesh Nagabhushana 
113156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
113256b2bdd1SGireesh Nagabhushana 		/* Forced 100M */
113356b2bdd1SGireesh Nagabhushana 		if (lc->autoneg == AUTONEG_ENABLE) {
11347e6ad469SVishal Kulkarni 			old = lc->acaps & FW_PORT_CAP32_SPEED_100M;
11357e6ad469SVishal Kulkarni 			new = v8 ? FW_PORT_CAP32_SPEED_100M : 0;
113656b2bdd1SGireesh Nagabhushana 			if (old != new) {
11377e6ad469SVishal Kulkarni 				lc->acaps &= ~FW_PORT_CAP32_SPEED_100M;
11387e6ad469SVishal Kulkarni 				lc->acaps |= new;
113956b2bdd1SGireesh Nagabhushana 				relink = 1;
114056b2bdd1SGireesh Nagabhushana 			}
114156b2bdd1SGireesh Nagabhushana 		} else
114256b2bdd1SGireesh Nagabhushana 			rc = ENOTSUP;
114356b2bdd1SGireesh Nagabhushana 		break;
114456b2bdd1SGireesh Nagabhushana 
114556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
114656b2bdd1SGireesh Nagabhushana 		rc = setprop(pi, name, val);
114756b2bdd1SGireesh Nagabhushana 		break;
114856b2bdd1SGireesh Nagabhushana 
114956b2bdd1SGireesh Nagabhushana 	default:
115056b2bdd1SGireesh Nagabhushana 		rc = ENOTSUP;
115156b2bdd1SGireesh Nagabhushana 	}
115256b2bdd1SGireesh Nagabhushana 
115356b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
115456b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
1155d77e6e0fSPaul Winder 			if (down_link)
1156d77e6e0fSPaul Winder 				t4_os_link_changed(pi->adapter, pi->port_id, 0);
115756b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
115856b2bdd1SGireesh Nagabhushana 			if (rc != 0)
115956b2bdd1SGireesh Nagabhushana 				return (rc);
11603dde7c95SVishal Kulkarni 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan,
116156b2bdd1SGireesh Nagabhushana 			    &pi->link_cfg);
116256b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
116356b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
116456b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
116556b2bdd1SGireesh Nagabhushana 				    "start_link failed:%d", rc);
116656b2bdd1SGireesh Nagabhushana 
116756b2bdd1SGireesh Nagabhushana 				/* Restore link_config */
116856b2bdd1SGireesh Nagabhushana 				bcopy(&lc_copy, lc,
116956b2bdd1SGireesh Nagabhushana 				    sizeof (struct link_config));
117056b2bdd1SGireesh Nagabhushana 			}
117156b2bdd1SGireesh Nagabhushana 		}
117256b2bdd1SGireesh Nagabhushana 
117356b2bdd1SGireesh Nagabhushana 		if (rx_mode != 0) {
117456b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
117556b2bdd1SGireesh Nagabhushana 			if (rc != 0)
117656b2bdd1SGireesh Nagabhushana 				return (rc);
117756b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
117856b2bdd1SGireesh Nagabhushana 			    -1, -1, -1, false);
117956b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
118056b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
118156b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
118256b2bdd1SGireesh Nagabhushana 				    "set_rxmode failed: %d", rc);
118356b2bdd1SGireesh Nagabhushana 			}
118456b2bdd1SGireesh Nagabhushana 		}
118556b2bdd1SGireesh Nagabhushana 	}
118656b2bdd1SGireesh Nagabhushana 
118756b2bdd1SGireesh Nagabhushana 	return (rc);
118856b2bdd1SGireesh Nagabhushana }
118956b2bdd1SGireesh Nagabhushana 
119056b2bdd1SGireesh Nagabhushana static int
119156b2bdd1SGireesh Nagabhushana t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
119256b2bdd1SGireesh Nagabhushana     void *val)
119356b2bdd1SGireesh Nagabhushana {
119456b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
119556b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
119656b2bdd1SGireesh Nagabhushana 	uint8_t *u = val;
119756b2bdd1SGireesh Nagabhushana 
119856b2bdd1SGireesh Nagabhushana 	switch (id) {
119956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
120056b2bdd1SGireesh Nagabhushana 		*(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
120156b2bdd1SGireesh Nagabhushana 		    LINK_DUPLEX_UNKNOWN;
120256b2bdd1SGireesh Nagabhushana 		break;
120356b2bdd1SGireesh Nagabhushana 
120456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
120556b2bdd1SGireesh Nagabhushana 		if (lc->link_ok != 0) {
120656b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val = lc->speed;
120756b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val *= 1000000;
120856b2bdd1SGireesh Nagabhushana 		} else
120956b2bdd1SGireesh Nagabhushana 			*(uint64_t *)val = 0;
121056b2bdd1SGireesh Nagabhushana 		break;
121156b2bdd1SGireesh Nagabhushana 
121256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
121356b2bdd1SGireesh Nagabhushana 		*(link_state_t *)val = lc->link_ok ? LINK_STATE_UP :
121456b2bdd1SGireesh Nagabhushana 		    LINK_STATE_DOWN;
121556b2bdd1SGireesh Nagabhushana 		break;
121656b2bdd1SGireesh Nagabhushana 
121756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
121856b2bdd1SGireesh Nagabhushana 		*u = lc->autoneg == AUTONEG_ENABLE;
121956b2bdd1SGireesh Nagabhushana 		break;
122056b2bdd1SGireesh Nagabhushana 
122156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
122256b2bdd1SGireesh Nagabhushana 		*(uint32_t *)val = pi->mtu;
122356b2bdd1SGireesh Nagabhushana 		break;
122456b2bdd1SGireesh Nagabhushana 
122556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
122656b2bdd1SGireesh Nagabhushana 		if ((lc->requested_fc & (PAUSE_TX | PAUSE_RX)) ==
122756b2bdd1SGireesh Nagabhushana 		    (PAUSE_TX | PAUSE_RX))
122856b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_BI;
122956b2bdd1SGireesh Nagabhushana 		else if (lc->requested_fc & PAUSE_TX)
123056b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_TX;
123156b2bdd1SGireesh Nagabhushana 		else if (lc->requested_fc & PAUSE_RX)
123256b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_RX;
123356b2bdd1SGireesh Nagabhushana 		else
123456b2bdd1SGireesh Nagabhushana 			*(link_flowctrl_t *)val = LINK_FLOWCTRL_NONE;
123556b2bdd1SGireesh Nagabhushana 		break;
123656b2bdd1SGireesh Nagabhushana 
1237d77e6e0fSPaul Winder 	case MAC_PROP_ADV_FEC_CAP:
1238d77e6e0fSPaul Winder 		if (!fec_supported(lc->pcaps))
1239d77e6e0fSPaul Winder 			return (ENOTSUP);
1240d77e6e0fSPaul Winder 
1241d77e6e0fSPaul Winder 		*(link_fec_t *)val = fec_to_link_fec(lc->fec);
1242d77e6e0fSPaul Winder 		break;
1243d77e6e0fSPaul Winder 
1244d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1245d77e6e0fSPaul Winder 		if (!fec_supported(lc->pcaps))
1246d77e6e0fSPaul Winder 			return (ENOTSUP);
1247d77e6e0fSPaul Winder 
1248d77e6e0fSPaul Winder 		*(link_fec_t *)val = fec_to_link_fec(lc->requested_fec);
1249d77e6e0fSPaul Winder 		break;
1250d77e6e0fSPaul Winder 
12513dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_100GFDX_CAP:
12523dde7c95SVishal Kulkarni 	case MAC_PROP_EN_100GFDX_CAP:
12537e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_100G);
12543dde7c95SVishal Kulkarni 		break;
12553dde7c95SVishal Kulkarni 
12563dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_40GFDX_CAP:
12573dde7c95SVishal Kulkarni 	case MAC_PROP_EN_40GFDX_CAP:
12587e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_40G);
12593dde7c95SVishal Kulkarni 		break;
12603dde7c95SVishal Kulkarni 
12613dde7c95SVishal Kulkarni 	case MAC_PROP_ADV_25GFDX_CAP:
12623dde7c95SVishal Kulkarni 	case MAC_PROP_EN_25GFDX_CAP:
12637e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_25G);
12643dde7c95SVishal Kulkarni 		break;
12653dde7c95SVishal Kulkarni 
126656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
126756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
12687e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_10G);
126956b2bdd1SGireesh Nagabhushana 		break;
127056b2bdd1SGireesh Nagabhushana 
127156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
127256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
12737e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_1G);
127456b2bdd1SGireesh Nagabhushana 		break;
127556b2bdd1SGireesh Nagabhushana 
127656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
127756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
12787e6ad469SVishal Kulkarni 		*u = !!(lc->acaps & FW_PORT_CAP32_SPEED_100M);
127956b2bdd1SGireesh Nagabhushana 		break;
128056b2bdd1SGireesh Nagabhushana 
128156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
128256b2bdd1SGireesh Nagabhushana 		return (getprop(pi, name, size, val));
128356b2bdd1SGireesh Nagabhushana 
128456b2bdd1SGireesh Nagabhushana 	default:
128556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
128656b2bdd1SGireesh Nagabhushana 	}
128756b2bdd1SGireesh Nagabhushana 
128856b2bdd1SGireesh Nagabhushana 	return (0);
128956b2bdd1SGireesh Nagabhushana }
129056b2bdd1SGireesh Nagabhushana 
129156b2bdd1SGireesh Nagabhushana static void
129256b2bdd1SGireesh Nagabhushana t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
129356b2bdd1SGireesh Nagabhushana     mac_prop_info_handle_t ph)
129456b2bdd1SGireesh Nagabhushana {
129556b2bdd1SGireesh Nagabhushana 	struct port_info *pi = arg;
129656b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
129756b2bdd1SGireesh Nagabhushana 
129856b2bdd1SGireesh Nagabhushana 	switch (id) {
129956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_DUPLEX:
130056b2bdd1SGireesh Nagabhushana 	case MAC_PROP_SPEED:
130156b2bdd1SGireesh Nagabhushana 	case MAC_PROP_STATUS:
130256b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
130356b2bdd1SGireesh Nagabhushana 		break;
130456b2bdd1SGireesh Nagabhushana 
130556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_AUTONEG:
13067e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG)
130756b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
130856b2bdd1SGireesh Nagabhushana 		else
130956b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
131056b2bdd1SGireesh Nagabhushana 		break;
131156b2bdd1SGireesh Nagabhushana 
131256b2bdd1SGireesh Nagabhushana 	case MAC_PROP_MTU:
131356b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_range_uint32(ph, 46, MAX_MTU);
131456b2bdd1SGireesh Nagabhushana 		break;
131556b2bdd1SGireesh Nagabhushana 
131656b2bdd1SGireesh Nagabhushana 	case MAC_PROP_FLOWCTRL:
131756b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI);
131856b2bdd1SGireesh Nagabhushana 		break;
131956b2bdd1SGireesh Nagabhushana 
1320d77e6e0fSPaul Winder 	case MAC_PROP_EN_FEC_CAP:
1321d77e6e0fSPaul Winder 		mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1322d77e6e0fSPaul Winder 		break;
1323d77e6e0fSPaul Winder 
1324d77e6e0fSPaul Winder 	case MAC_PROP_ADV_FEC_CAP:
1325d77e6e0fSPaul Winder 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1326d77e6e0fSPaul Winder 		mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1327d77e6e0fSPaul Winder 		break;
1328d77e6e0fSPaul Winder 
132956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_10GFDX_CAP:
13307e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG &&
13317e6ad469SVishal Kulkarni 		    lc->pcaps & FW_PORT_CAP32_SPEED_10G)
133256b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
133356b2bdd1SGireesh Nagabhushana 		else
133456b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
133556b2bdd1SGireesh Nagabhushana 		break;
133656b2bdd1SGireesh Nagabhushana 
133756b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_1000FDX_CAP:
13387e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG &&
13397e6ad469SVishal Kulkarni 		    lc->pcaps & FW_PORT_CAP32_SPEED_1G)
134056b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
134156b2bdd1SGireesh Nagabhushana 		else
134256b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
134356b2bdd1SGireesh Nagabhushana 		break;
134456b2bdd1SGireesh Nagabhushana 
134556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_EN_100FDX_CAP:
13467e6ad469SVishal Kulkarni 		if (lc->pcaps & FW_PORT_CAP32_ANEG &&
13477e6ad469SVishal Kulkarni 		    lc->pcaps & FW_PORT_CAP32_SPEED_100M)
134856b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_default_uint8(ph, 1);
134956b2bdd1SGireesh Nagabhushana 		else
135056b2bdd1SGireesh Nagabhushana 			mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
135156b2bdd1SGireesh Nagabhushana 		break;
135256b2bdd1SGireesh Nagabhushana 
135356b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_10GFDX_CAP:
135456b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_1000FDX_CAP:
135556b2bdd1SGireesh Nagabhushana 	case MAC_PROP_ADV_100FDX_CAP:
135656b2bdd1SGireesh Nagabhushana 		mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
135756b2bdd1SGireesh Nagabhushana 		break;
135856b2bdd1SGireesh Nagabhushana 
135956b2bdd1SGireesh Nagabhushana 	case MAC_PROP_PRIVATE:
136056b2bdd1SGireesh Nagabhushana 		propinfo(pi, name, ph);
136156b2bdd1SGireesh Nagabhushana 		break;
136256b2bdd1SGireesh Nagabhushana 
136356b2bdd1SGireesh Nagabhushana 	default:
136456b2bdd1SGireesh Nagabhushana 		break;
136556b2bdd1SGireesh Nagabhushana 	}
136656b2bdd1SGireesh Nagabhushana }
136756b2bdd1SGireesh Nagabhushana 
13687e6ad469SVishal Kulkarni int
136956b2bdd1SGireesh Nagabhushana begin_synchronized_op(struct port_info *pi, int hold, int waitok)
137056b2bdd1SGireesh Nagabhushana {
137156b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
137256b2bdd1SGireesh Nagabhushana 	int rc = 0;
137356b2bdd1SGireesh Nagabhushana 
137456b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK(sc);
137556b2bdd1SGireesh Nagabhushana 	while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
137656b2bdd1SGireesh Nagabhushana 		if (!waitok) {
137756b2bdd1SGireesh Nagabhushana 			rc = EBUSY;
137856b2bdd1SGireesh Nagabhushana 			goto failed;
137956b2bdd1SGireesh Nagabhushana 		} else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) {
138056b2bdd1SGireesh Nagabhushana 			rc = EINTR;
138156b2bdd1SGireesh Nagabhushana 			goto failed;
138256b2bdd1SGireesh Nagabhushana 		}
138356b2bdd1SGireesh Nagabhushana 	}
138456b2bdd1SGireesh Nagabhushana 	if (IS_DOOMED(pi) != 0) {	/* shouldn't happen on Solaris */
138556b2bdd1SGireesh Nagabhushana 		rc = ENXIO;
138656b2bdd1SGireesh Nagabhushana 		goto failed;
138756b2bdd1SGireesh Nagabhushana 	}
138856b2bdd1SGireesh Nagabhushana 	ASSERT(!IS_BUSY(sc));
138956b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
139056b2bdd1SGireesh Nagabhushana 	SET_BUSY(sc);
139156b2bdd1SGireesh Nagabhushana 
139256b2bdd1SGireesh Nagabhushana 	if (!hold)
139356b2bdd1SGireesh Nagabhushana 		ADAPTER_UNLOCK(sc);
139456b2bdd1SGireesh Nagabhushana 
139556b2bdd1SGireesh Nagabhushana 	return (0);
139656b2bdd1SGireesh Nagabhushana failed:
139756b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
139856b2bdd1SGireesh Nagabhushana 	return (rc);
139956b2bdd1SGireesh Nagabhushana }
140056b2bdd1SGireesh Nagabhushana 
14017e6ad469SVishal Kulkarni void
140256b2bdd1SGireesh Nagabhushana end_synchronized_op(struct port_info *pi, int held)
140356b2bdd1SGireesh Nagabhushana {
140456b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
140556b2bdd1SGireesh Nagabhushana 
140656b2bdd1SGireesh Nagabhushana 	if (!held)
140756b2bdd1SGireesh Nagabhushana 		ADAPTER_LOCK(sc);
140856b2bdd1SGireesh Nagabhushana 
140956b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_OWNED(sc);
141056b2bdd1SGireesh Nagabhushana 	ASSERT(IS_BUSY(sc));
141156b2bdd1SGireesh Nagabhushana 	/* LINTED: E_CONSTANT_CONDITION */
141256b2bdd1SGireesh Nagabhushana 	CLR_BUSY(sc);
141356b2bdd1SGireesh Nagabhushana 	cv_signal(&sc->cv);
141456b2bdd1SGireesh Nagabhushana 	ADAPTER_UNLOCK(sc);
141556b2bdd1SGireesh Nagabhushana }
141656b2bdd1SGireesh Nagabhushana 
141756b2bdd1SGireesh Nagabhushana static int
141856b2bdd1SGireesh Nagabhushana t4_init_synchronized(struct port_info *pi)
141956b2bdd1SGireesh Nagabhushana {
142056b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
142156b2bdd1SGireesh Nagabhushana 	int rc = 0;
142256b2bdd1SGireesh Nagabhushana 
142356b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
142456b2bdd1SGireesh Nagabhushana 
142556b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0)
142656b2bdd1SGireesh Nagabhushana 		return (0);	/* already running */
142756b2bdd1SGireesh Nagabhushana 
142856b2bdd1SGireesh Nagabhushana 	if (!(sc->flags & FULL_INIT_DONE) &&
142956b2bdd1SGireesh Nagabhushana 	    ((rc = adapter_full_init(sc)) != 0))
143056b2bdd1SGireesh Nagabhushana 		return (rc);	/* error message displayed already */
143156b2bdd1SGireesh Nagabhushana 
143256b2bdd1SGireesh Nagabhushana 	if (!(pi->flags & PORT_INIT_DONE)) {
143356b2bdd1SGireesh Nagabhushana 		rc = port_full_init(pi);
143456b2bdd1SGireesh Nagabhushana 		if (rc != 0)
143556b2bdd1SGireesh Nagabhushana 			return (rc); /* error message displayed already */
143656b2bdd1SGireesh Nagabhushana 	} else
143756b2bdd1SGireesh Nagabhushana 		enable_port_queues(pi);
143856b2bdd1SGireesh Nagabhushana 
143956b2bdd1SGireesh Nagabhushana 	rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false);
144056b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
144156b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc);
144256b2bdd1SGireesh Nagabhushana 		goto done;
144356b2bdd1SGireesh Nagabhushana 	}
144456b2bdd1SGireesh Nagabhushana 	rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt,
14457e6ad469SVishal Kulkarni 	    pi->hw_addr, true, &pi->smt_idx);
144656b2bdd1SGireesh Nagabhushana 	if (rc < 0) {
144756b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc);
144856b2bdd1SGireesh Nagabhushana 		rc = -rc;
144956b2bdd1SGireesh Nagabhushana 		goto done;
145056b2bdd1SGireesh Nagabhushana 	} else
145156b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
145256b2bdd1SGireesh Nagabhushana 		pi->xact_addr_filt = rc;
145356b2bdd1SGireesh Nagabhushana 
14543dde7c95SVishal Kulkarni 	rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg);
145556b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
145656b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc);
145756b2bdd1SGireesh Nagabhushana 		goto done;
145856b2bdd1SGireesh Nagabhushana 	}
145956b2bdd1SGireesh Nagabhushana 
146056b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true);
146156b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
146256b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc);
146356b2bdd1SGireesh Nagabhushana 		goto done;
146456b2bdd1SGireesh Nagabhushana 	}
146556b2bdd1SGireesh Nagabhushana 
146656b2bdd1SGireesh Nagabhushana 	/* all ok */
146756b2bdd1SGireesh Nagabhushana 	setbit(&sc->open_device_map, pi->port_id);
146856b2bdd1SGireesh Nagabhushana done:
146956b2bdd1SGireesh Nagabhushana 	if (rc != 0)
147056b2bdd1SGireesh Nagabhushana 		(void) t4_uninit_synchronized(pi);
147156b2bdd1SGireesh Nagabhushana 
147256b2bdd1SGireesh Nagabhushana 	return (rc);
147356b2bdd1SGireesh Nagabhushana }
147456b2bdd1SGireesh Nagabhushana 
147556b2bdd1SGireesh Nagabhushana /*
147656b2bdd1SGireesh Nagabhushana  * Idempotent.
147756b2bdd1SGireesh Nagabhushana  */
147856b2bdd1SGireesh Nagabhushana static int
147956b2bdd1SGireesh Nagabhushana t4_uninit_synchronized(struct port_info *pi)
148056b2bdd1SGireesh Nagabhushana {
148156b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
148256b2bdd1SGireesh Nagabhushana 	int rc;
148356b2bdd1SGireesh Nagabhushana 
148456b2bdd1SGireesh Nagabhushana 	ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
148556b2bdd1SGireesh Nagabhushana 
148656b2bdd1SGireesh Nagabhushana 	/*
148756b2bdd1SGireesh Nagabhushana 	 * Disable the VI so that all its data in either direction is discarded
148856b2bdd1SGireesh Nagabhushana 	 * by the MPS.  Leave everything else (the queues, interrupts, and 1Hz
148956b2bdd1SGireesh Nagabhushana 	 * tick) intact as the TP can deliver negative advice or data that it's
149056b2bdd1SGireesh Nagabhushana 	 * holding in its RAM (for an offloaded connection) even after the VI is
149156b2bdd1SGireesh Nagabhushana 	 * disabled.
149256b2bdd1SGireesh Nagabhushana 	 */
149356b2bdd1SGireesh Nagabhushana 	rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false);
149456b2bdd1SGireesh Nagabhushana 	if (rc != 0) {
149556b2bdd1SGireesh Nagabhushana 		cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc);
149656b2bdd1SGireesh Nagabhushana 		return (rc);
149756b2bdd1SGireesh Nagabhushana 	}
149856b2bdd1SGireesh Nagabhushana 
149956b2bdd1SGireesh Nagabhushana 	disable_port_queues(pi);
150056b2bdd1SGireesh Nagabhushana 
150156b2bdd1SGireesh Nagabhushana 	clrbit(&sc->open_device_map, pi->port_id);
150256b2bdd1SGireesh Nagabhushana 
150356b2bdd1SGireesh Nagabhushana 	pi->link_cfg.link_ok = 0;
150456b2bdd1SGireesh Nagabhushana 	pi->link_cfg.speed = 0;
150556b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, LINK_STATE_UNKNOWN);
150656b2bdd1SGireesh Nagabhushana 
150756b2bdd1SGireesh Nagabhushana 	return (0);
150856b2bdd1SGireesh Nagabhushana }
150956b2bdd1SGireesh Nagabhushana 
151056b2bdd1SGireesh Nagabhushana static void
151156b2bdd1SGireesh Nagabhushana propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph)
151256b2bdd1SGireesh Nagabhushana {
151356b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
151456b2bdd1SGireesh Nagabhushana 	struct driver_properties *p = &sc->props;
151556b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
151656b2bdd1SGireesh Nagabhushana 	int v;
151756b2bdd1SGireesh Nagabhushana 	char str[16];
151856b2bdd1SGireesh Nagabhushana 
151956b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
152056b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g;
152156b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
152256b2bdd1SGireesh Nagabhushana 		v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g;
152356b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
152456b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
152556b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
152656b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
152756b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
152856b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_TX) ? 1 : 0;
152956b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
153056b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_RX) ? 1 : 0;
153156b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
153256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
153356b2bdd1SGireesh Nagabhushana 		v = ETHERMTU;
153456b2bdd1SGireesh Nagabhushana #endif
153556b2bdd1SGireesh Nagabhushana 	else
153656b2bdd1SGireesh Nagabhushana 		return;
153756b2bdd1SGireesh Nagabhushana 
153856b2bdd1SGireesh Nagabhushana 	(void) snprintf(str, sizeof (str), "%d", v);
153956b2bdd1SGireesh Nagabhushana 	mac_prop_info_set_default_str(ph, str);
154056b2bdd1SGireesh Nagabhushana }
154156b2bdd1SGireesh Nagabhushana 
154256b2bdd1SGireesh Nagabhushana static int
154356b2bdd1SGireesh Nagabhushana getprop(struct port_info *pi, const char *name, uint_t size, void *val)
154456b2bdd1SGireesh Nagabhushana {
154556b2bdd1SGireesh Nagabhushana 	struct link_config *lc = &pi->link_cfg;
154656b2bdd1SGireesh Nagabhushana 	int v;
154756b2bdd1SGireesh Nagabhushana 
154856b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0)
154956b2bdd1SGireesh Nagabhushana 		v = pi->tmr_idx;
155056b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
155156b2bdd1SGireesh Nagabhushana 		v = pi->pktc_idx;
155256b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_CSUM) == 0)
155356b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
155456b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_HW_LSO) == 0)
155556b2bdd1SGireesh Nagabhushana 		v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
155656b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
155756b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_TX) ? 1 : 0;
155856b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
155956b2bdd1SGireesh Nagabhushana 		v = (lc->fc & PAUSE_RX) ? 1 : 0;
156056b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
156156b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0)
156256b2bdd1SGireesh Nagabhushana 		v = pi->mtu;
156356b2bdd1SGireesh Nagabhushana #endif
156456b2bdd1SGireesh Nagabhushana 	else
156556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
156656b2bdd1SGireesh Nagabhushana 
156756b2bdd1SGireesh Nagabhushana 	(void) snprintf(val, size, "%d", v);
156856b2bdd1SGireesh Nagabhushana 	return (0);
156956b2bdd1SGireesh Nagabhushana }
157056b2bdd1SGireesh Nagabhushana 
157156b2bdd1SGireesh Nagabhushana static int
157256b2bdd1SGireesh Nagabhushana setprop(struct port_info *pi, const char *name, const void *val)
157356b2bdd1SGireesh Nagabhushana {
157456b2bdd1SGireesh Nagabhushana 	struct adapter *sc = pi->adapter;
157556b2bdd1SGireesh Nagabhushana 	long v;
157656b2bdd1SGireesh Nagabhushana 	int i, rc = 0, relink = 0, rx_mode = 0;
157756b2bdd1SGireesh Nagabhushana 	struct sge_rxq *rxq;
157856b2bdd1SGireesh Nagabhushana 	struct link_config lc_old, *lc = &pi->link_cfg;
157956b2bdd1SGireesh Nagabhushana 
158056b2bdd1SGireesh Nagabhushana 	/*
158156b2bdd1SGireesh Nagabhushana 	 * Save a copy of link_config. This can be used to restore link_config
15823dde7c95SVishal Kulkarni 	 * if t4_link_l1cfg() fails.
158356b2bdd1SGireesh Nagabhushana 	 */
158456b2bdd1SGireesh Nagabhushana 	bcopy(lc, &lc_old, sizeof (struct link_config));
158556b2bdd1SGireesh Nagabhushana 
158656b2bdd1SGireesh Nagabhushana 	(void) ddi_strtol(val, NULL, 0, &v);
158756b2bdd1SGireesh Nagabhushana 
158856b2bdd1SGireesh Nagabhushana 	if (strcmp(name, T4PROP_TMR_IDX) == 0) {
158956b2bdd1SGireesh Nagabhushana 		if (v < 0 || v >= SGE_NTIMERS)
159056b2bdd1SGireesh Nagabhushana 			return (EINVAL);
159156b2bdd1SGireesh Nagabhushana 		if (v == pi->tmr_idx)
159256b2bdd1SGireesh Nagabhushana 			return (0);
159356b2bdd1SGireesh Nagabhushana 
159456b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
159556b2bdd1SGireesh Nagabhushana 		pi->tmr_idx = v;
159656b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
159756b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) |
159856b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(pi->pktc_idx >= 0);
159956b2bdd1SGireesh Nagabhushana 		}
160056b2bdd1SGireesh Nagabhushana 
160156b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_PKTC_IDX) == 0) {
160256b2bdd1SGireesh Nagabhushana 		if (v >= SGE_NCOUNTERS)
160356b2bdd1SGireesh Nagabhushana 			return (EINVAL);
160456b2bdd1SGireesh Nagabhushana 		if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1))
160556b2bdd1SGireesh Nagabhushana 			return (0);
160656b2bdd1SGireesh Nagabhushana 
160756b2bdd1SGireesh Nagabhushana 		/* LINTED: E_ASSIGN_NARROW_CONV */
160856b2bdd1SGireesh Nagabhushana 		pi->pktc_idx = v < 0 ? -1 : v;
160956b2bdd1SGireesh Nagabhushana 		for_each_rxq(pi, i, rxq) {
161056b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) |
161156b2bdd1SGireesh Nagabhushana 			    /* takes effect right away */
161256b2bdd1SGireesh Nagabhushana 			    V_QINTR_CNT_EN(v >= 0);
161356b2bdd1SGireesh Nagabhushana 			/* LINTED: E_ASSIGN_NARROW_CONV */
161456b2bdd1SGireesh Nagabhushana 			rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */
161556b2bdd1SGireesh Nagabhushana 		}
161656b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_CSUM) == 0) {
161756b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
161856b2bdd1SGireesh Nagabhushana 			return (EINVAL);
161956b2bdd1SGireesh Nagabhushana 		if (v == 1)
162056b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_CSUM;
162156b2bdd1SGireesh Nagabhushana 		else
162256b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_CSUM;
162356b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_HW_LSO) == 0) {
162456b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
162556b2bdd1SGireesh Nagabhushana 			return (EINVAL);
162656b2bdd1SGireesh Nagabhushana 		if (v == 1)
162756b2bdd1SGireesh Nagabhushana 			pi->features |= CXGBE_HW_LSO;
162856b2bdd1SGireesh Nagabhushana 		else
162956b2bdd1SGireesh Nagabhushana 			pi->features &= ~CXGBE_HW_LSO;
163056b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_TX_PAUSE) == 0) {
163156b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
163256b2bdd1SGireesh Nagabhushana 			return (EINVAL);
163356b2bdd1SGireesh Nagabhushana 
163456b2bdd1SGireesh Nagabhushana 		if (v != 0)
163556b2bdd1SGireesh Nagabhushana 			lc->requested_fc |= PAUSE_TX;
163656b2bdd1SGireesh Nagabhushana 		else
163756b2bdd1SGireesh Nagabhushana 			lc->requested_fc &= ~PAUSE_TX;
163856b2bdd1SGireesh Nagabhushana 
163956b2bdd1SGireesh Nagabhushana 		relink = 1;
164056b2bdd1SGireesh Nagabhushana 
164156b2bdd1SGireesh Nagabhushana 	} else if (strcmp(name, T4PROP_RX_PAUSE) == 0) {
164256b2bdd1SGireesh Nagabhushana 		if (v != 0 && v != 1)
164356b2bdd1SGireesh Nagabhushana 			return (EINVAL);
164456b2bdd1SGireesh Nagabhushana 
164556b2bdd1SGireesh Nagabhushana 		if (v != 0)
164656b2bdd1SGireesh Nagabhushana 			lc->requested_fc |= PAUSE_RX;
164756b2bdd1SGireesh Nagabhushana 		else
164856b2bdd1SGireesh Nagabhushana 			lc->requested_fc &= ~PAUSE_RX;
164956b2bdd1SGireesh Nagabhushana 
165056b2bdd1SGireesh Nagabhushana 		relink = 1;
165156b2bdd1SGireesh Nagabhushana 	}
165256b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
165356b2bdd1SGireesh Nagabhushana 	else if (strcmp(name, T4PROP_MTU) == 0) {
165456b2bdd1SGireesh Nagabhushana 		if (v < 46 || v > MAX_MTU)
165556b2bdd1SGireesh Nagabhushana 			return (EINVAL);
165656b2bdd1SGireesh Nagabhushana 		if (v == pi->mtu)
165756b2bdd1SGireesh Nagabhushana 			return (0);
165856b2bdd1SGireesh Nagabhushana 
165956b2bdd1SGireesh Nagabhushana 		pi->mtu = (int)v;
166056b2bdd1SGireesh Nagabhushana 		(void) mac_maxsdu_update(pi->mh, v);
166156b2bdd1SGireesh Nagabhushana 		rx_mode = 1;
166256b2bdd1SGireesh Nagabhushana 	}
166356b2bdd1SGireesh Nagabhushana #endif
166456b2bdd1SGireesh Nagabhushana 	else
166556b2bdd1SGireesh Nagabhushana 		return (ENOTSUP);
166656b2bdd1SGireesh Nagabhushana 
166756b2bdd1SGireesh Nagabhushana 	if (!(relink || rx_mode))
166856b2bdd1SGireesh Nagabhushana 		return (0);
166956b2bdd1SGireesh Nagabhushana 
167056b2bdd1SGireesh Nagabhushana 	/* If we are here, either relink or rx_mode is 1 */
167156b2bdd1SGireesh Nagabhushana 	if (isset(&sc->open_device_map, pi->port_id) != 0) {
167256b2bdd1SGireesh Nagabhushana 		if (relink != 0) {
167356b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
167456b2bdd1SGireesh Nagabhushana 			if (rc != 0)
167556b2bdd1SGireesh Nagabhushana 				return (rc);
16763dde7c95SVishal Kulkarni 			rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc);
167756b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
167856b2bdd1SGireesh Nagabhushana 			if (rc != 0) {
167956b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
168056b2bdd1SGireesh Nagabhushana 				    "start_link failed:%d", rc);
168156b2bdd1SGireesh Nagabhushana 				/* Restore link_config */
168256b2bdd1SGireesh Nagabhushana 				bcopy(&lc_old, lc, sizeof (struct link_config));
168356b2bdd1SGireesh Nagabhushana 			}
168456b2bdd1SGireesh Nagabhushana 		} else if (rx_mode != 0) {
168556b2bdd1SGireesh Nagabhushana 			rc = begin_synchronized_op(pi, 1, 1);
168656b2bdd1SGireesh Nagabhushana 			if (rc != 0)
168756b2bdd1SGireesh Nagabhushana 				return (rc);
168856b2bdd1SGireesh Nagabhushana 			rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1,
168956b2bdd1SGireesh Nagabhushana 			    -1, -1, false);
169056b2bdd1SGireesh Nagabhushana 			end_synchronized_op(pi, 1);
169156b2bdd1SGireesh Nagabhushana 			if (rc != 0)  {
169256b2bdd1SGireesh Nagabhushana 				cxgb_printf(pi->dip, CE_WARN,
169356b2bdd1SGireesh Nagabhushana 				    "set_rxmode failed: %d", rc);
169456b2bdd1SGireesh Nagabhushana 			}
169556b2bdd1SGireesh Nagabhushana 		}
169656b2bdd1SGireesh Nagabhushana 		return (rc);
169756b2bdd1SGireesh Nagabhushana 	}
169856b2bdd1SGireesh Nagabhushana 
169956b2bdd1SGireesh Nagabhushana 	return (0);
170056b2bdd1SGireesh Nagabhushana }
170156b2bdd1SGireesh Nagabhushana 
170256b2bdd1SGireesh Nagabhushana void
170356b2bdd1SGireesh Nagabhushana t4_mc_init(struct port_info *pi)
170456b2bdd1SGireesh Nagabhushana {
170556b2bdd1SGireesh Nagabhushana 	pi->props = t4_priv_props;
170656b2bdd1SGireesh Nagabhushana }
170756b2bdd1SGireesh Nagabhushana 
17083dde7c95SVishal Kulkarni void
17093dde7c95SVishal Kulkarni t4_mc_cb_init(struct port_info *pi)
17103dde7c95SVishal Kulkarni {
17113dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
17123dde7c95SVishal Kulkarni 		pi->mc = &t4_m_ring_callbacks;
17133dde7c95SVishal Kulkarni 	else
17143dde7c95SVishal Kulkarni 		pi->mc = &t4_m_callbacks;
17153dde7c95SVishal Kulkarni }
17163dde7c95SVishal Kulkarni 
171756b2bdd1SGireesh Nagabhushana void
171856b2bdd1SGireesh Nagabhushana t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
171956b2bdd1SGireesh Nagabhushana {
172056b2bdd1SGireesh Nagabhushana 	struct port_info *pi = sc->port[idx];
172156b2bdd1SGireesh Nagabhushana 
172256b2bdd1SGireesh Nagabhushana 	mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN);
172356b2bdd1SGireesh Nagabhushana }
172456b2bdd1SGireesh Nagabhushana 
172556b2bdd1SGireesh Nagabhushana /* ARGSUSED */
172656b2bdd1SGireesh Nagabhushana void
172756b2bdd1SGireesh Nagabhushana t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m)
172856b2bdd1SGireesh Nagabhushana {
172956b2bdd1SGireesh Nagabhushana 	mac_rx(pi->mh, NULL, m);
173056b2bdd1SGireesh Nagabhushana }
17313dde7c95SVishal Kulkarni 
17323dde7c95SVishal Kulkarni void
17333dde7c95SVishal Kulkarni t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq)
17343dde7c95SVishal Kulkarni {
17353dde7c95SVishal Kulkarni 	if (pi->adapter->props.multi_rings)
17363dde7c95SVishal Kulkarni 		mac_tx_ring_update(pi->mh, txq->ring_handle);
17373dde7c95SVishal Kulkarni 	else
17383dde7c95SVishal Kulkarni 		mac_tx_update(pi->mh);
17393dde7c95SVishal Kulkarni }
1740