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