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