1*56b2bdd1SGireesh Nagabhushana /* 2*56b2bdd1SGireesh Nagabhushana * This file and its contents are supplied under the terms of the 3*56b2bdd1SGireesh Nagabhushana * Common Development and Distribution License ("CDDL"), version 1.0. 4*56b2bdd1SGireesh Nagabhushana * You may only use this file in accordance with the terms of version 5*56b2bdd1SGireesh Nagabhushana * 1.0 of the CDDL. 6*56b2bdd1SGireesh Nagabhushana * 7*56b2bdd1SGireesh Nagabhushana * A full copy of the text of the CDDL should have accompanied this 8*56b2bdd1SGireesh Nagabhushana * source. A copy of the CDDL is also available via the Internet at 9*56b2bdd1SGireesh Nagabhushana * http://www.illumos.org/license/CDDL. 10*56b2bdd1SGireesh Nagabhushana */ 11*56b2bdd1SGireesh Nagabhushana 12*56b2bdd1SGireesh Nagabhushana /* 13*56b2bdd1SGireesh Nagabhushana * This file is part of the Chelsio T4 support code. 14*56b2bdd1SGireesh Nagabhushana * 15*56b2bdd1SGireesh Nagabhushana * Copyright (C) 2010-2013 Chelsio Communications. All rights reserved. 16*56b2bdd1SGireesh Nagabhushana * 17*56b2bdd1SGireesh Nagabhushana * This program is distributed in the hope that it will be useful, but WITHOUT 18*56b2bdd1SGireesh Nagabhushana * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19*56b2bdd1SGireesh Nagabhushana * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this 20*56b2bdd1SGireesh Nagabhushana * release for licensing terms and conditions. 21*56b2bdd1SGireesh Nagabhushana */ 22*56b2bdd1SGireesh Nagabhushana 23*56b2bdd1SGireesh Nagabhushana #include <sys/ddi.h> 24*56b2bdd1SGireesh Nagabhushana #include <sys/sunddi.h> 25*56b2bdd1SGireesh Nagabhushana #include <sys/dlpi.h> 26*56b2bdd1SGireesh Nagabhushana #include <sys/mac_provider.h> 27*56b2bdd1SGireesh Nagabhushana #include <sys/mac_ether.h> 28*56b2bdd1SGireesh Nagabhushana #include <sys/strsubr.h> 29*56b2bdd1SGireesh Nagabhushana #include <sys/queue.h> 30*56b2bdd1SGireesh Nagabhushana 31*56b2bdd1SGireesh Nagabhushana #include "common/common.h" 32*56b2bdd1SGireesh Nagabhushana #include "common/t4_regs.h" 33*56b2bdd1SGireesh Nagabhushana 34*56b2bdd1SGireesh Nagabhushana static int t4_mc_getstat(void *arg, uint_t stat, uint64_t *val); 35*56b2bdd1SGireesh Nagabhushana static int t4_mc_start(void *arg); 36*56b2bdd1SGireesh Nagabhushana static void t4_mc_stop(void *arg); 37*56b2bdd1SGireesh Nagabhushana static int t4_mc_setpromisc(void *arg, boolean_t on); 38*56b2bdd1SGireesh Nagabhushana static int t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr); 39*56b2bdd1SGireesh Nagabhushana static int t4_mc_unicst(void *arg, const uint8_t *ucaddr); 40*56b2bdd1SGireesh Nagabhushana static mblk_t *t4_mc_tx(void *arg, mblk_t *m); 41*56b2bdd1SGireesh Nagabhushana static boolean_t t4_mc_getcapab(void *arg, mac_capab_t cap, void *data); 42*56b2bdd1SGireesh Nagabhushana static int t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, 43*56b2bdd1SGireesh Nagabhushana uint_t size, const void *val); 44*56b2bdd1SGireesh Nagabhushana static int t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, 45*56b2bdd1SGireesh Nagabhushana uint_t size, void *val); 46*56b2bdd1SGireesh Nagabhushana static void t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id, 47*56b2bdd1SGireesh Nagabhushana mac_prop_info_handle_t ph); 48*56b2bdd1SGireesh Nagabhushana 49*56b2bdd1SGireesh Nagabhushana static int begin_synchronized_op(struct port_info *pi, int hold, int waitok); 50*56b2bdd1SGireesh Nagabhushana static void end_synchronized_op(struct port_info *pi, int held); 51*56b2bdd1SGireesh Nagabhushana static int t4_init_synchronized(struct port_info *pi); 52*56b2bdd1SGireesh Nagabhushana static int t4_uninit_synchronized(struct port_info *pi); 53*56b2bdd1SGireesh Nagabhushana static void propinfo(struct port_info *pi, const char *name, 54*56b2bdd1SGireesh Nagabhushana mac_prop_info_handle_t ph); 55*56b2bdd1SGireesh Nagabhushana static int getprop(struct port_info *pi, const char *name, uint_t size, 56*56b2bdd1SGireesh Nagabhushana void *val); 57*56b2bdd1SGireesh Nagabhushana static int setprop(struct port_info *pi, const char *name, const void *val); 58*56b2bdd1SGireesh Nagabhushana 59*56b2bdd1SGireesh Nagabhushana mac_callbacks_t t4_m_callbacks = { 60*56b2bdd1SGireesh Nagabhushana .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES, 61*56b2bdd1SGireesh Nagabhushana .mc_getstat = t4_mc_getstat, 62*56b2bdd1SGireesh Nagabhushana .mc_start = t4_mc_start, 63*56b2bdd1SGireesh Nagabhushana .mc_stop = t4_mc_stop, 64*56b2bdd1SGireesh Nagabhushana .mc_setpromisc = t4_mc_setpromisc, 65*56b2bdd1SGireesh Nagabhushana .mc_multicst = t4_mc_multicst, 66*56b2bdd1SGireesh Nagabhushana .mc_unicst = t4_mc_unicst, 67*56b2bdd1SGireesh Nagabhushana .mc_tx = t4_mc_tx, 68*56b2bdd1SGireesh Nagabhushana .mc_getcapab = t4_mc_getcapab, 69*56b2bdd1SGireesh Nagabhushana .mc_setprop = t4_mc_setprop, 70*56b2bdd1SGireesh Nagabhushana .mc_getprop = t4_mc_getprop, 71*56b2bdd1SGireesh Nagabhushana .mc_propinfo = t4_mc_propinfo, 72*56b2bdd1SGireesh Nagabhushana }; 73*56b2bdd1SGireesh Nagabhushana 74*56b2bdd1SGireesh Nagabhushana #define T4PROP_TMR_IDX "_holdoff_timer_idx" 75*56b2bdd1SGireesh Nagabhushana #define T4PROP_PKTC_IDX "_holdoff_pktc_idx" 76*56b2bdd1SGireesh Nagabhushana #define T4PROP_MTU "_mtu" 77*56b2bdd1SGireesh Nagabhushana #define T4PROP_HW_CSUM "_hw_csum" 78*56b2bdd1SGireesh Nagabhushana #define T4PROP_HW_LSO "_hw_lso" 79*56b2bdd1SGireesh Nagabhushana #define T4PROP_TX_PAUSE "_tx_pause" 80*56b2bdd1SGireesh Nagabhushana #define T4PROP_RX_PAUSE "_rx_pause" 81*56b2bdd1SGireesh Nagabhushana 82*56b2bdd1SGireesh Nagabhushana char *t4_priv_props[] = { 83*56b2bdd1SGireesh Nagabhushana T4PROP_TMR_IDX, 84*56b2bdd1SGireesh Nagabhushana T4PROP_PKTC_IDX, 85*56b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1 86*56b2bdd1SGireesh Nagabhushana /* MAC_VERSION 1 doesn't seem to use MAC_PROP_MTU, hmmmm */ 87*56b2bdd1SGireesh Nagabhushana T4PROP_MTU, 88*56b2bdd1SGireesh Nagabhushana #endif 89*56b2bdd1SGireesh Nagabhushana T4PROP_HW_CSUM, 90*56b2bdd1SGireesh Nagabhushana T4PROP_HW_LSO, 91*56b2bdd1SGireesh Nagabhushana T4PROP_TX_PAUSE, 92*56b2bdd1SGireesh Nagabhushana T4PROP_RX_PAUSE, 93*56b2bdd1SGireesh Nagabhushana NULL 94*56b2bdd1SGireesh Nagabhushana }; 95*56b2bdd1SGireesh Nagabhushana 96*56b2bdd1SGireesh Nagabhushana static int 97*56b2bdd1SGireesh Nagabhushana t4_mc_getstat(void *arg, uint_t stat, uint64_t *val) 98*56b2bdd1SGireesh Nagabhushana { 99*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 100*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 101*56b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg; 102*56b2bdd1SGireesh Nagabhushana 103*56b2bdd1SGireesh Nagabhushana #define GET_STAT(name) \ 104*56b2bdd1SGireesh Nagabhushana t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L)) 105*56b2bdd1SGireesh Nagabhushana 106*56b2bdd1SGireesh Nagabhushana switch (stat) { 107*56b2bdd1SGireesh Nagabhushana case MAC_STAT_IFSPEED: 108*56b2bdd1SGireesh Nagabhushana if (lc->link_ok != 0) { 109*56b2bdd1SGireesh Nagabhushana *val = lc->speed; 110*56b2bdd1SGireesh Nagabhushana *val *= 1000000; 111*56b2bdd1SGireesh Nagabhushana } else 112*56b2bdd1SGireesh Nagabhushana *val = 0; 113*56b2bdd1SGireesh Nagabhushana break; 114*56b2bdd1SGireesh Nagabhushana 115*56b2bdd1SGireesh Nagabhushana case MAC_STAT_MULTIRCV: 116*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MCAST); 117*56b2bdd1SGireesh Nagabhushana break; 118*56b2bdd1SGireesh Nagabhushana 119*56b2bdd1SGireesh Nagabhushana case MAC_STAT_BRDCSTRCV: 120*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_BCAST); 121*56b2bdd1SGireesh Nagabhushana break; 122*56b2bdd1SGireesh Nagabhushana 123*56b2bdd1SGireesh Nagabhushana case MAC_STAT_MULTIXMT: 124*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_MCAST); 125*56b2bdd1SGireesh Nagabhushana break; 126*56b2bdd1SGireesh Nagabhushana 127*56b2bdd1SGireesh Nagabhushana case MAC_STAT_BRDCSTXMT: 128*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_BCAST); 129*56b2bdd1SGireesh Nagabhushana break; 130*56b2bdd1SGireesh Nagabhushana 131*56b2bdd1SGireesh Nagabhushana case MAC_STAT_NORCVBUF: 132*56b2bdd1SGireesh Nagabhushana *val = 0; /* TODO should come from rxq->nomem */ 133*56b2bdd1SGireesh Nagabhushana break; 134*56b2bdd1SGireesh Nagabhushana 135*56b2bdd1SGireesh Nagabhushana case MAC_STAT_IERRORS: 136*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MTU_ERROR) + 137*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_MTU_CRC_ERROR) + 138*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_CRC_ERROR) + 139*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LEN_ERROR) + 140*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_SYM_ERROR) + 141*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LESS_64B); 142*56b2bdd1SGireesh Nagabhushana break; 143*56b2bdd1SGireesh Nagabhushana 144*56b2bdd1SGireesh Nagabhushana case MAC_STAT_UNKNOWNS: 145*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 146*56b2bdd1SGireesh Nagabhushana 147*56b2bdd1SGireesh Nagabhushana case MAC_STAT_NOXMTBUF: 148*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_DROP); 149*56b2bdd1SGireesh Nagabhushana break; 150*56b2bdd1SGireesh Nagabhushana 151*56b2bdd1SGireesh Nagabhushana case MAC_STAT_OERRORS: 152*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_ERROR); 153*56b2bdd1SGireesh Nagabhushana break; 154*56b2bdd1SGireesh Nagabhushana 155*56b2bdd1SGireesh Nagabhushana case MAC_STAT_COLLISIONS: 156*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 157*56b2bdd1SGireesh Nagabhushana 158*56b2bdd1SGireesh Nagabhushana case MAC_STAT_RBYTES: 159*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_BYTES); 160*56b2bdd1SGireesh Nagabhushana break; 161*56b2bdd1SGireesh Nagabhushana 162*56b2bdd1SGireesh Nagabhushana case MAC_STAT_IPACKETS: 163*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_FRAMES); 164*56b2bdd1SGireesh Nagabhushana break; 165*56b2bdd1SGireesh Nagabhushana 166*56b2bdd1SGireesh Nagabhushana case MAC_STAT_OBYTES: 167*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_BYTES); 168*56b2bdd1SGireesh Nagabhushana break; 169*56b2bdd1SGireesh Nagabhushana 170*56b2bdd1SGireesh Nagabhushana case MAC_STAT_OPACKETS: 171*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_FRAMES); 172*56b2bdd1SGireesh Nagabhushana break; 173*56b2bdd1SGireesh Nagabhushana 174*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ALIGN_ERRORS: 175*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 176*56b2bdd1SGireesh Nagabhushana 177*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_FCS_ERRORS: 178*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_CRC_ERROR); 179*56b2bdd1SGireesh Nagabhushana break; 180*56b2bdd1SGireesh Nagabhushana 181*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_FIRST_COLLISIONS: 182*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_MULTI_COLLISIONS: 183*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_SQE_ERRORS: 184*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_DEFER_XMTS: 185*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_TX_LATE_COLLISIONS: 186*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_EX_COLLISIONS: 187*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 188*56b2bdd1SGireesh Nagabhushana 189*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_MACXMT_ERRORS: 190*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_ERROR); 191*56b2bdd1SGireesh Nagabhushana break; 192*56b2bdd1SGireesh Nagabhushana 193*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CARRIER_ERRORS: 194*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 195*56b2bdd1SGireesh Nagabhushana 196*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_TOOLONG_ERRORS: 197*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MTU_ERROR); 198*56b2bdd1SGireesh Nagabhushana break; 199*56b2bdd1SGireesh Nagabhushana 200*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_MACRCV_ERRORS: 201*56b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MTU_ERROR) + 202*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_MTU_CRC_ERROR) + 203*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_CRC_ERROR) + 204*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LEN_ERROR) + 205*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_SYM_ERROR) + 206*56b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LESS_64B); 207*56b2bdd1SGireesh Nagabhushana break; 208*56b2bdd1SGireesh Nagabhushana 209*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_XCVR_ADDR: 210*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_XCVR_ID: 211*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_XCVR_INUSE: 212*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 213*56b2bdd1SGireesh Nagabhushana 214*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_1000FDX: 215*56b2bdd1SGireesh Nagabhushana *val = !!(lc->supported & FW_PORT_CAP_SPEED_1G); 216*56b2bdd1SGireesh Nagabhushana break; 217*56b2bdd1SGireesh Nagabhushana 218*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_1000HDX: 219*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 220*56b2bdd1SGireesh Nagabhushana 221*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_100FDX: 222*56b2bdd1SGireesh Nagabhushana *val = !!(lc->supported & FW_PORT_CAP_SPEED_100M); 223*56b2bdd1SGireesh Nagabhushana break; 224*56b2bdd1SGireesh Nagabhushana 225*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_100HDX: 226*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 227*56b2bdd1SGireesh Nagabhushana 228*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_10FDX: 229*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_10HDX: 230*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 231*56b2bdd1SGireesh Nagabhushana 232*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_ASMPAUSE: 233*56b2bdd1SGireesh Nagabhushana *val = 0; 234*56b2bdd1SGireesh Nagabhushana break; 235*56b2bdd1SGireesh Nagabhushana 236*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_PAUSE: 237*56b2bdd1SGireesh Nagabhushana *val = 1; 238*56b2bdd1SGireesh Nagabhushana break; 239*56b2bdd1SGireesh Nagabhushana 240*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_AUTONEG: 241*56b2bdd1SGireesh Nagabhushana *val = !!(lc->supported & FW_PORT_CAP_ANEG); 242*56b2bdd1SGireesh Nagabhushana break; 243*56b2bdd1SGireesh Nagabhushana 244*56b2bdd1SGireesh Nagabhushana /* 245*56b2bdd1SGireesh Nagabhushana * We have set flow control configuration based on tx_pause and rx_pause 246*56b2bdd1SGireesh Nagabhushana * values supported through ndd. Now, we need to translate the settings 247*56b2bdd1SGireesh Nagabhushana * we have in link_config structure to adv_cap_asmpause and 248*56b2bdd1SGireesh Nagabhushana * adv_cap_pause. 249*56b2bdd1SGireesh Nagabhushana * 250*56b2bdd1SGireesh Nagabhushana * There are 4 combinations possible and the translation is as below: 251*56b2bdd1SGireesh Nagabhushana * tx_pause = 0 => We don't send pause frames during Rx congestion 252*56b2bdd1SGireesh Nagabhushana * tx_pause = 1 => We send pause frames during Rx congestion 253*56b2bdd1SGireesh Nagabhushana * rx_pause = 0 => We ignore received pause frames 254*56b2bdd1SGireesh Nagabhushana * rx_pause = 1 => We pause transmission when we receive pause frames 255*56b2bdd1SGireesh Nagabhushana * 256*56b2bdd1SGireesh Nagabhushana * +----------------------------+----------------------------------+ 257*56b2bdd1SGireesh Nagabhushana * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause | 258*56b2bdd1SGireesh Nagabhushana * +-------------------------+-------------------------------------+ 259*56b2bdd1SGireesh Nagabhushana * | 0 | 0 | 0 | 0 | 260*56b2bdd1SGireesh Nagabhushana * | 0 | 1 | 1 | 0 | 261*56b2bdd1SGireesh Nagabhushana * | 1 | 0 | 1 | 1 | 262*56b2bdd1SGireesh Nagabhushana * | 1 | 1 | 0 | 1 | 263*56b2bdd1SGireesh Nagabhushana * +----------------------------+----------------------------------+ 264*56b2bdd1SGireesh Nagabhushana */ 265*56b2bdd1SGireesh Nagabhushana 266*56b2bdd1SGireesh Nagabhushana /* Advertised asymmetric pause capability */ 267*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_ASMPAUSE: 268*56b2bdd1SGireesh Nagabhushana *val = (((lc->requested_fc & PAUSE_TX) ? 1 : 0) ^ 269*56b2bdd1SGireesh Nagabhushana (lc->requested_fc & PAUSE_RX)); 270*56b2bdd1SGireesh Nagabhushana break; 271*56b2bdd1SGireesh Nagabhushana 272*56b2bdd1SGireesh Nagabhushana /* Advertised pause capability */ 273*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_PAUSE: 274*56b2bdd1SGireesh Nagabhushana *val = (lc->requested_fc & PAUSE_TX) ? 1 : 0; 275*56b2bdd1SGireesh Nagabhushana break; 276*56b2bdd1SGireesh Nagabhushana 277*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_1000FDX: 278*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_1000HDX: 279*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_100FDX: 280*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_100HDX: 281*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_10FDX: 282*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_10HDX: 283*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_AUTONEG: 284*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); /* TODO */ 285*56b2bdd1SGireesh Nagabhushana 286*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_1000FDX: 287*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_1000HDX: 288*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_100FDX: 289*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_100HDX: 290*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_10FDX: 291*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_10HDX: 292*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_ASMPAUSE: 293*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_PAUSE: 294*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_AUTONEG: 295*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 296*56b2bdd1SGireesh Nagabhushana 297*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_ASMPAUSE: 298*56b2bdd1SGireesh Nagabhushana *val = 0; 299*56b2bdd1SGireesh Nagabhushana break; 300*56b2bdd1SGireesh Nagabhushana 301*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_PAUSE: 302*56b2bdd1SGireesh Nagabhushana *val = 1; 303*56b2bdd1SGireesh Nagabhushana break; 304*56b2bdd1SGireesh Nagabhushana 305*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_AUTONEG: 306*56b2bdd1SGireesh Nagabhushana *val = lc->autoneg == AUTONEG_ENABLE; 307*56b2bdd1SGireesh Nagabhushana break; 308*56b2bdd1SGireesh Nagabhushana 309*56b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_DUPLEX: 310*56b2bdd1SGireesh Nagabhushana if (lc->link_ok != 0) 311*56b2bdd1SGireesh Nagabhushana *val = LINK_DUPLEX_FULL; 312*56b2bdd1SGireesh Nagabhushana else 313*56b2bdd1SGireesh Nagabhushana *val = LINK_DUPLEX_UNKNOWN; 314*56b2bdd1SGireesh Nagabhushana break; 315*56b2bdd1SGireesh Nagabhushana 316*56b2bdd1SGireesh Nagabhushana default: 317*56b2bdd1SGireesh Nagabhushana #ifdef DEBUG 318*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_NOTE, "stat %d not implemented.", stat); 319*56b2bdd1SGireesh Nagabhushana #endif 320*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 321*56b2bdd1SGireesh Nagabhushana } 322*56b2bdd1SGireesh Nagabhushana #undef GET_STAT 323*56b2bdd1SGireesh Nagabhushana 324*56b2bdd1SGireesh Nagabhushana return (0); 325*56b2bdd1SGireesh Nagabhushana } 326*56b2bdd1SGireesh Nagabhushana 327*56b2bdd1SGireesh Nagabhushana static int 328*56b2bdd1SGireesh Nagabhushana t4_mc_start(void *arg) 329*56b2bdd1SGireesh Nagabhushana { 330*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 331*56b2bdd1SGireesh Nagabhushana int rc; 332*56b2bdd1SGireesh Nagabhushana 333*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 0, 1); 334*56b2bdd1SGireesh Nagabhushana if (rc != 0) 335*56b2bdd1SGireesh Nagabhushana return (rc); 336*56b2bdd1SGireesh Nagabhushana rc = t4_init_synchronized(pi); 337*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 0); 338*56b2bdd1SGireesh Nagabhushana 339*56b2bdd1SGireesh Nagabhushana return (rc); 340*56b2bdd1SGireesh Nagabhushana } 341*56b2bdd1SGireesh Nagabhushana 342*56b2bdd1SGireesh Nagabhushana static void 343*56b2bdd1SGireesh Nagabhushana t4_mc_stop(void *arg) 344*56b2bdd1SGireesh Nagabhushana { 345*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 346*56b2bdd1SGireesh Nagabhushana 347*56b2bdd1SGireesh Nagabhushana while (begin_synchronized_op(pi, 0, 1) != 0) 348*56b2bdd1SGireesh Nagabhushana continue; 349*56b2bdd1SGireesh Nagabhushana (void) t4_uninit_synchronized(pi); 350*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 0); 351*56b2bdd1SGireesh Nagabhushana } 352*56b2bdd1SGireesh Nagabhushana 353*56b2bdd1SGireesh Nagabhushana static int 354*56b2bdd1SGireesh Nagabhushana t4_mc_setpromisc(void *arg, boolean_t on) 355*56b2bdd1SGireesh Nagabhushana { 356*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 357*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 358*56b2bdd1SGireesh Nagabhushana int rc; 359*56b2bdd1SGireesh Nagabhushana 360*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 361*56b2bdd1SGireesh Nagabhushana if (rc != 0) 362*56b2bdd1SGireesh Nagabhushana return (rc); 363*56b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1, 364*56b2bdd1SGireesh Nagabhushana false); 365*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 366*56b2bdd1SGireesh Nagabhushana 367*56b2bdd1SGireesh Nagabhushana return (rc); 368*56b2bdd1SGireesh Nagabhushana } 369*56b2bdd1SGireesh Nagabhushana 370*56b2bdd1SGireesh Nagabhushana /* 371*56b2bdd1SGireesh Nagabhushana * TODO: Starts failing as soon as the 336 entry table fills up. Need to use 372*56b2bdd1SGireesh Nagabhushana * hash in that case. 373*56b2bdd1SGireesh Nagabhushana */ 374*56b2bdd1SGireesh Nagabhushana static int 375*56b2bdd1SGireesh Nagabhushana t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr) 376*56b2bdd1SGireesh Nagabhushana { 377*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 378*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 379*56b2bdd1SGireesh Nagabhushana struct fw_vi_mac_cmd c; 380*56b2bdd1SGireesh Nagabhushana int len16, rc; 381*56b2bdd1SGireesh Nagabhushana 382*56b2bdd1SGireesh Nagabhushana len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) + 383*56b2bdd1SGireesh Nagabhushana sizeof (c.u.exact[0]), 16); 384*56b2bdd1SGireesh Nagabhushana c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST | 385*56b2bdd1SGireesh Nagabhushana F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid)); 386*56b2bdd1SGireesh Nagabhushana c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16)); 387*56b2bdd1SGireesh Nagabhushana c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID | 388*56b2bdd1SGireesh Nagabhushana V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC : 389*56b2bdd1SGireesh Nagabhushana FW_VI_MAC_MAC_BASED_FREE)); 390*56b2bdd1SGireesh Nagabhushana bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL); 391*56b2bdd1SGireesh Nagabhushana 392*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 393*56b2bdd1SGireesh Nagabhushana if (rc != 0) 394*56b2bdd1SGireesh Nagabhushana return (rc); 395*56b2bdd1SGireesh Nagabhushana rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true); 396*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 397*56b2bdd1SGireesh Nagabhushana if (rc != 0) 398*56b2bdd1SGireesh Nagabhushana return (rc); 399*56b2bdd1SGireesh Nagabhushana #ifdef DEBUG 400*56b2bdd1SGireesh Nagabhushana /* 401*56b2bdd1SGireesh Nagabhushana * TODO: Firmware doesn't seem to return the correct index on removal 402*56b2bdd1SGireesh Nagabhushana * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this 403*56b2bdd1SGireesh Nagabhushana * code once it is fixed. 404*56b2bdd1SGireesh Nagabhushana */ 405*56b2bdd1SGireesh Nagabhushana else { 406*56b2bdd1SGireesh Nagabhushana uint16_t idx; 407*56b2bdd1SGireesh Nagabhushana 408*56b2bdd1SGireesh Nagabhushana idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx)); 409*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_NOTE, 410*56b2bdd1SGireesh Nagabhushana "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0], 411*56b2bdd1SGireesh Nagabhushana mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5], 412*56b2bdd1SGireesh Nagabhushana add ? "added at index" : "removed from index", idx); 413*56b2bdd1SGireesh Nagabhushana } 414*56b2bdd1SGireesh Nagabhushana #endif 415*56b2bdd1SGireesh Nagabhushana 416*56b2bdd1SGireesh Nagabhushana return (0); 417*56b2bdd1SGireesh Nagabhushana } 418*56b2bdd1SGireesh Nagabhushana 419*56b2bdd1SGireesh Nagabhushana static int 420*56b2bdd1SGireesh Nagabhushana t4_mc_unicst(void *arg, const uint8_t *ucaddr) 421*56b2bdd1SGireesh Nagabhushana { 422*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 423*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 424*56b2bdd1SGireesh Nagabhushana int rc; 425*56b2bdd1SGireesh Nagabhushana 426*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 427*56b2bdd1SGireesh Nagabhushana if (rc != 0) 428*56b2bdd1SGireesh Nagabhushana return (rc); 429*56b2bdd1SGireesh Nagabhushana rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr, 430*56b2bdd1SGireesh Nagabhushana true, true); 431*56b2bdd1SGireesh Nagabhushana if (rc < 0) 432*56b2bdd1SGireesh Nagabhushana rc = -rc; 433*56b2bdd1SGireesh Nagabhushana else { 434*56b2bdd1SGireesh Nagabhushana /* LINTED: E_CONSTANT_CONDITION */ 435*56b2bdd1SGireesh Nagabhushana pi->xact_addr_filt = rc; 436*56b2bdd1SGireesh Nagabhushana rc = 0; 437*56b2bdd1SGireesh Nagabhushana } 438*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 439*56b2bdd1SGireesh Nagabhushana 440*56b2bdd1SGireesh Nagabhushana return (rc); 441*56b2bdd1SGireesh Nagabhushana } 442*56b2bdd1SGireesh Nagabhushana 443*56b2bdd1SGireesh Nagabhushana static mblk_t * 444*56b2bdd1SGireesh Nagabhushana t4_mc_tx(void *arg, mblk_t *m) 445*56b2bdd1SGireesh Nagabhushana { 446*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 447*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 448*56b2bdd1SGireesh Nagabhushana struct sge_txq *txq = &sc->sge.txq[pi->first_txq]; 449*56b2bdd1SGireesh Nagabhushana 450*56b2bdd1SGireesh Nagabhushana return (t4_eth_tx(pi, txq, m)); 451*56b2bdd1SGireesh Nagabhushana } 452*56b2bdd1SGireesh Nagabhushana 453*56b2bdd1SGireesh Nagabhushana static boolean_t 454*56b2bdd1SGireesh Nagabhushana t4_mc_getcapab(void *arg, mac_capab_t cap, void *data) 455*56b2bdd1SGireesh Nagabhushana { 456*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 457*56b2bdd1SGireesh Nagabhushana boolean_t status = B_TRUE; 458*56b2bdd1SGireesh Nagabhushana 459*56b2bdd1SGireesh Nagabhushana switch (cap) { 460*56b2bdd1SGireesh Nagabhushana case MAC_CAPAB_HCKSUM: 461*56b2bdd1SGireesh Nagabhushana if (pi->features & CXGBE_HW_CSUM) { 462*56b2bdd1SGireesh Nagabhushana uint32_t *d = data; 463*56b2bdd1SGireesh Nagabhushana *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM; 464*56b2bdd1SGireesh Nagabhushana } else 465*56b2bdd1SGireesh Nagabhushana status = B_FALSE; 466*56b2bdd1SGireesh Nagabhushana break; 467*56b2bdd1SGireesh Nagabhushana 468*56b2bdd1SGireesh Nagabhushana case MAC_CAPAB_LSO: 469*56b2bdd1SGireesh Nagabhushana /* Enabling LSO requires Checksum offloading */ 470*56b2bdd1SGireesh Nagabhushana if (pi->features & CXGBE_HW_LSO && 471*56b2bdd1SGireesh Nagabhushana pi->features & CXGBE_HW_CSUM) { 472*56b2bdd1SGireesh Nagabhushana mac_capab_lso_t *d = data; 473*56b2bdd1SGireesh Nagabhushana 474*56b2bdd1SGireesh Nagabhushana d->lso_flags = LSO_TX_BASIC_TCP_IPV4; 475*56b2bdd1SGireesh Nagabhushana d->lso_basic_tcp_ipv4.lso_max = 65535; 476*56b2bdd1SGireesh Nagabhushana } else 477*56b2bdd1SGireesh Nagabhushana status = B_FALSE; 478*56b2bdd1SGireesh Nagabhushana break; 479*56b2bdd1SGireesh Nagabhushana 480*56b2bdd1SGireesh Nagabhushana default: 481*56b2bdd1SGireesh Nagabhushana status = B_FALSE; /* cap not supported */ 482*56b2bdd1SGireesh Nagabhushana } 483*56b2bdd1SGireesh Nagabhushana 484*56b2bdd1SGireesh Nagabhushana return (status); 485*56b2bdd1SGireesh Nagabhushana } 486*56b2bdd1SGireesh Nagabhushana 487*56b2bdd1SGireesh Nagabhushana /* ARGSUSED */ 488*56b2bdd1SGireesh Nagabhushana static int 489*56b2bdd1SGireesh Nagabhushana t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 490*56b2bdd1SGireesh Nagabhushana const void *val) 491*56b2bdd1SGireesh Nagabhushana { 492*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 493*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 494*56b2bdd1SGireesh Nagabhushana struct link_config lc_copy, *lc = &pi->link_cfg; 495*56b2bdd1SGireesh Nagabhushana uint8_t v8 = *(uint8_t *)val; 496*56b2bdd1SGireesh Nagabhushana uint32_t v32 = *(uint32_t *)val; 497*56b2bdd1SGireesh Nagabhushana int old, new = 0, relink = 0, rx_mode = 0, rc = 0; 498*56b2bdd1SGireesh Nagabhushana link_flowctrl_t fc; 499*56b2bdd1SGireesh Nagabhushana 500*56b2bdd1SGireesh Nagabhushana /* 501*56b2bdd1SGireesh Nagabhushana * Save a copy of link_config. This can be used to restore link_config 502*56b2bdd1SGireesh Nagabhushana * if t4_link_start() fails. 503*56b2bdd1SGireesh Nagabhushana */ 504*56b2bdd1SGireesh Nagabhushana bcopy(lc, &lc_copy, sizeof (struct link_config)); 505*56b2bdd1SGireesh Nagabhushana 506*56b2bdd1SGireesh Nagabhushana switch (id) { 507*56b2bdd1SGireesh Nagabhushana case MAC_PROP_AUTONEG: 508*56b2bdd1SGireesh Nagabhushana if (lc->supported & FW_PORT_CAP_ANEG) { 509*56b2bdd1SGireesh Nagabhushana old = lc->autoneg; 510*56b2bdd1SGireesh Nagabhushana new = v8 ? AUTONEG_ENABLE : AUTONEG_DISABLE; 511*56b2bdd1SGireesh Nagabhushana if (old != new) { 512*56b2bdd1SGireesh Nagabhushana /* LINTED: E_CONSTANT_CONDITION */ 513*56b2bdd1SGireesh Nagabhushana lc->autoneg = new; 514*56b2bdd1SGireesh Nagabhushana relink = 1; 515*56b2bdd1SGireesh Nagabhushana if (new == AUTONEG_DISABLE) { 516*56b2bdd1SGireesh Nagabhushana /* Only 100M is available */ 517*56b2bdd1SGireesh Nagabhushana lc->requested_speed = 518*56b2bdd1SGireesh Nagabhushana FW_PORT_CAP_SPEED_100M; 519*56b2bdd1SGireesh Nagabhushana lc->advertising = 520*56b2bdd1SGireesh Nagabhushana FW_PORT_CAP_SPEED_100M; 521*56b2bdd1SGireesh Nagabhushana } else { 522*56b2bdd1SGireesh Nagabhushana /* 523*56b2bdd1SGireesh Nagabhushana * Advertise autonegotiation capability 524*56b2bdd1SGireesh Nagabhushana * along with supported speeds 525*56b2bdd1SGireesh Nagabhushana */ 526*56b2bdd1SGireesh Nagabhushana lc->advertising |= (FW_PORT_CAP_ANEG | 527*56b2bdd1SGireesh Nagabhushana (lc->supported & 528*56b2bdd1SGireesh Nagabhushana (FW_PORT_CAP_SPEED_100M | 529*56b2bdd1SGireesh Nagabhushana FW_PORT_CAP_SPEED_1G))); 530*56b2bdd1SGireesh Nagabhushana lc->requested_speed = 0; 531*56b2bdd1SGireesh Nagabhushana } 532*56b2bdd1SGireesh Nagabhushana } 533*56b2bdd1SGireesh Nagabhushana } else 534*56b2bdd1SGireesh Nagabhushana rc = ENOTSUP; 535*56b2bdd1SGireesh Nagabhushana break; 536*56b2bdd1SGireesh Nagabhushana 537*56b2bdd1SGireesh Nagabhushana case MAC_PROP_MTU: 538*56b2bdd1SGireesh Nagabhushana if (v32 < 46 || v32 > MAX_MTU) { 539*56b2bdd1SGireesh Nagabhushana rc = EINVAL; 540*56b2bdd1SGireesh Nagabhushana } else if (v32 != pi->mtu) { 541*56b2bdd1SGireesh Nagabhushana pi->mtu = v32; 542*56b2bdd1SGireesh Nagabhushana (void) mac_maxsdu_update(pi->mh, v32); 543*56b2bdd1SGireesh Nagabhushana rx_mode = 1; 544*56b2bdd1SGireesh Nagabhushana } 545*56b2bdd1SGireesh Nagabhushana 546*56b2bdd1SGireesh Nagabhushana break; 547*56b2bdd1SGireesh Nagabhushana 548*56b2bdd1SGireesh Nagabhushana case MAC_PROP_FLOWCTRL: 549*56b2bdd1SGireesh Nagabhushana fc = *(link_flowctrl_t *)val; 550*56b2bdd1SGireesh Nagabhushana old = lc->requested_fc & (PAUSE_TX | PAUSE_RX); 551*56b2bdd1SGireesh Nagabhushana 552*56b2bdd1SGireesh Nagabhushana if (fc == LINK_FLOWCTRL_BI) 553*56b2bdd1SGireesh Nagabhushana new = (PAUSE_TX | PAUSE_RX); 554*56b2bdd1SGireesh Nagabhushana else if (fc == LINK_FLOWCTRL_TX) 555*56b2bdd1SGireesh Nagabhushana new = PAUSE_TX; 556*56b2bdd1SGireesh Nagabhushana else if (fc == LINK_FLOWCTRL_RX) 557*56b2bdd1SGireesh Nagabhushana new = PAUSE_RX; 558*56b2bdd1SGireesh Nagabhushana 559*56b2bdd1SGireesh Nagabhushana if (new != old) { 560*56b2bdd1SGireesh Nagabhushana lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX); 561*56b2bdd1SGireesh Nagabhushana lc->requested_fc |= new; 562*56b2bdd1SGireesh Nagabhushana relink = 1; 563*56b2bdd1SGireesh Nagabhushana } 564*56b2bdd1SGireesh Nagabhushana break; 565*56b2bdd1SGireesh Nagabhushana 566*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_10GFDX_CAP: 567*56b2bdd1SGireesh Nagabhushana if (lc->supported & FW_PORT_CAP_ANEG && is_10G_port(pi)) { 568*56b2bdd1SGireesh Nagabhushana old = lc->advertising & FW_PORT_CAP_SPEED_10G; 569*56b2bdd1SGireesh Nagabhushana new = v8 ? FW_PORT_CAP_SPEED_10G : 0; 570*56b2bdd1SGireesh Nagabhushana if (new != old) { 571*56b2bdd1SGireesh Nagabhushana lc->advertising &= ~FW_PORT_CAP_SPEED_10G; 572*56b2bdd1SGireesh Nagabhushana lc->advertising |= new; 573*56b2bdd1SGireesh Nagabhushana relink = 1; 574*56b2bdd1SGireesh Nagabhushana } 575*56b2bdd1SGireesh Nagabhushana } else 576*56b2bdd1SGireesh Nagabhushana rc = ENOTSUP; 577*56b2bdd1SGireesh Nagabhushana 578*56b2bdd1SGireesh Nagabhushana break; 579*56b2bdd1SGireesh Nagabhushana 580*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_1000FDX_CAP: 581*56b2bdd1SGireesh Nagabhushana /* Forced 1G */ 582*56b2bdd1SGireesh Nagabhushana if (lc->autoneg == AUTONEG_ENABLE) { 583*56b2bdd1SGireesh Nagabhushana old = lc->advertising & FW_PORT_CAP_SPEED_1G; 584*56b2bdd1SGireesh Nagabhushana new = v8 ? FW_PORT_CAP_SPEED_1G : 0; 585*56b2bdd1SGireesh Nagabhushana 586*56b2bdd1SGireesh Nagabhushana if (old != new) { 587*56b2bdd1SGireesh Nagabhushana lc->advertising &= ~FW_PORT_CAP_SPEED_1G; 588*56b2bdd1SGireesh Nagabhushana lc->advertising |= new; 589*56b2bdd1SGireesh Nagabhushana relink = 1; 590*56b2bdd1SGireesh Nagabhushana } 591*56b2bdd1SGireesh Nagabhushana } else 592*56b2bdd1SGireesh Nagabhushana rc = ENOTSUP; 593*56b2bdd1SGireesh Nagabhushana break; 594*56b2bdd1SGireesh Nagabhushana 595*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_100FDX_CAP: 596*56b2bdd1SGireesh Nagabhushana /* Forced 100M */ 597*56b2bdd1SGireesh Nagabhushana if (lc->autoneg == AUTONEG_ENABLE) { 598*56b2bdd1SGireesh Nagabhushana old = lc->advertising & FW_PORT_CAP_SPEED_100M; 599*56b2bdd1SGireesh Nagabhushana new = v8 ? FW_PORT_CAP_SPEED_100M : 0; 600*56b2bdd1SGireesh Nagabhushana if (old != new) { 601*56b2bdd1SGireesh Nagabhushana lc->advertising &= ~FW_PORT_CAP_SPEED_100M; 602*56b2bdd1SGireesh Nagabhushana lc->advertising |= new; 603*56b2bdd1SGireesh Nagabhushana relink = 1; 604*56b2bdd1SGireesh Nagabhushana } 605*56b2bdd1SGireesh Nagabhushana } else 606*56b2bdd1SGireesh Nagabhushana rc = ENOTSUP; 607*56b2bdd1SGireesh Nagabhushana break; 608*56b2bdd1SGireesh Nagabhushana 609*56b2bdd1SGireesh Nagabhushana case MAC_PROP_PRIVATE: 610*56b2bdd1SGireesh Nagabhushana rc = setprop(pi, name, val); 611*56b2bdd1SGireesh Nagabhushana break; 612*56b2bdd1SGireesh Nagabhushana 613*56b2bdd1SGireesh Nagabhushana default: 614*56b2bdd1SGireesh Nagabhushana rc = ENOTSUP; 615*56b2bdd1SGireesh Nagabhushana } 616*56b2bdd1SGireesh Nagabhushana 617*56b2bdd1SGireesh Nagabhushana if (isset(&sc->open_device_map, pi->port_id) != 0) { 618*56b2bdd1SGireesh Nagabhushana if (relink != 0) { 619*56b2bdd1SGireesh Nagabhushana t4_os_link_changed(pi->adapter, pi->port_id, 0); 620*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 621*56b2bdd1SGireesh Nagabhushana if (rc != 0) 622*56b2bdd1SGireesh Nagabhushana return (rc); 623*56b2bdd1SGireesh Nagabhushana rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, 624*56b2bdd1SGireesh Nagabhushana &pi->link_cfg); 625*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 626*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 627*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, 628*56b2bdd1SGireesh Nagabhushana "start_link failed:%d", rc); 629*56b2bdd1SGireesh Nagabhushana 630*56b2bdd1SGireesh Nagabhushana /* Restore link_config */ 631*56b2bdd1SGireesh Nagabhushana bcopy(&lc_copy, lc, 632*56b2bdd1SGireesh Nagabhushana sizeof (struct link_config)); 633*56b2bdd1SGireesh Nagabhushana } 634*56b2bdd1SGireesh Nagabhushana } 635*56b2bdd1SGireesh Nagabhushana 636*56b2bdd1SGireesh Nagabhushana if (rx_mode != 0) { 637*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 638*56b2bdd1SGireesh Nagabhushana if (rc != 0) 639*56b2bdd1SGireesh Nagabhushana return (rc); 640*56b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1, 641*56b2bdd1SGireesh Nagabhushana -1, -1, -1, false); 642*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 643*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 644*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, 645*56b2bdd1SGireesh Nagabhushana "set_rxmode failed: %d", rc); 646*56b2bdd1SGireesh Nagabhushana } 647*56b2bdd1SGireesh Nagabhushana } 648*56b2bdd1SGireesh Nagabhushana } 649*56b2bdd1SGireesh Nagabhushana 650*56b2bdd1SGireesh Nagabhushana return (rc); 651*56b2bdd1SGireesh Nagabhushana } 652*56b2bdd1SGireesh Nagabhushana 653*56b2bdd1SGireesh Nagabhushana static int 654*56b2bdd1SGireesh Nagabhushana t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 655*56b2bdd1SGireesh Nagabhushana void *val) 656*56b2bdd1SGireesh Nagabhushana { 657*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 658*56b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg; 659*56b2bdd1SGireesh Nagabhushana uint8_t *u = val; 660*56b2bdd1SGireesh Nagabhushana 661*56b2bdd1SGireesh Nagabhushana switch (id) { 662*56b2bdd1SGireesh Nagabhushana case MAC_PROP_DUPLEX: 663*56b2bdd1SGireesh Nagabhushana *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL : 664*56b2bdd1SGireesh Nagabhushana LINK_DUPLEX_UNKNOWN; 665*56b2bdd1SGireesh Nagabhushana break; 666*56b2bdd1SGireesh Nagabhushana 667*56b2bdd1SGireesh Nagabhushana case MAC_PROP_SPEED: 668*56b2bdd1SGireesh Nagabhushana if (lc->link_ok != 0) { 669*56b2bdd1SGireesh Nagabhushana *(uint64_t *)val = lc->speed; 670*56b2bdd1SGireesh Nagabhushana *(uint64_t *)val *= 1000000; 671*56b2bdd1SGireesh Nagabhushana } else 672*56b2bdd1SGireesh Nagabhushana *(uint64_t *)val = 0; 673*56b2bdd1SGireesh Nagabhushana break; 674*56b2bdd1SGireesh Nagabhushana 675*56b2bdd1SGireesh Nagabhushana case MAC_PROP_STATUS: 676*56b2bdd1SGireesh Nagabhushana *(link_state_t *)val = lc->link_ok ? LINK_STATE_UP : 677*56b2bdd1SGireesh Nagabhushana LINK_STATE_DOWN; 678*56b2bdd1SGireesh Nagabhushana break; 679*56b2bdd1SGireesh Nagabhushana 680*56b2bdd1SGireesh Nagabhushana case MAC_PROP_AUTONEG: 681*56b2bdd1SGireesh Nagabhushana *u = lc->autoneg == AUTONEG_ENABLE; 682*56b2bdd1SGireesh Nagabhushana break; 683*56b2bdd1SGireesh Nagabhushana 684*56b2bdd1SGireesh Nagabhushana case MAC_PROP_MTU: 685*56b2bdd1SGireesh Nagabhushana *(uint32_t *)val = pi->mtu; 686*56b2bdd1SGireesh Nagabhushana break; 687*56b2bdd1SGireesh Nagabhushana 688*56b2bdd1SGireesh Nagabhushana case MAC_PROP_FLOWCTRL: 689*56b2bdd1SGireesh Nagabhushana if ((lc->requested_fc & (PAUSE_TX | PAUSE_RX)) == 690*56b2bdd1SGireesh Nagabhushana (PAUSE_TX | PAUSE_RX)) 691*56b2bdd1SGireesh Nagabhushana *(link_flowctrl_t *)val = LINK_FLOWCTRL_BI; 692*56b2bdd1SGireesh Nagabhushana else if (lc->requested_fc & PAUSE_TX) 693*56b2bdd1SGireesh Nagabhushana *(link_flowctrl_t *)val = LINK_FLOWCTRL_TX; 694*56b2bdd1SGireesh Nagabhushana else if (lc->requested_fc & PAUSE_RX) 695*56b2bdd1SGireesh Nagabhushana *(link_flowctrl_t *)val = LINK_FLOWCTRL_RX; 696*56b2bdd1SGireesh Nagabhushana else 697*56b2bdd1SGireesh Nagabhushana *(link_flowctrl_t *)val = LINK_FLOWCTRL_NONE; 698*56b2bdd1SGireesh Nagabhushana break; 699*56b2bdd1SGireesh Nagabhushana 700*56b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_10GFDX_CAP: 701*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_10GFDX_CAP: 702*56b2bdd1SGireesh Nagabhushana *u = !!(lc->advertising & FW_PORT_CAP_SPEED_10G); 703*56b2bdd1SGireesh Nagabhushana break; 704*56b2bdd1SGireesh Nagabhushana 705*56b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_1000FDX_CAP: 706*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_1000FDX_CAP: 707*56b2bdd1SGireesh Nagabhushana *u = !!(lc->advertising & FW_PORT_CAP_SPEED_1G); 708*56b2bdd1SGireesh Nagabhushana break; 709*56b2bdd1SGireesh Nagabhushana 710*56b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_100FDX_CAP: 711*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_100FDX_CAP: 712*56b2bdd1SGireesh Nagabhushana *u = !!(lc->advertising & FW_PORT_CAP_SPEED_100M); 713*56b2bdd1SGireesh Nagabhushana break; 714*56b2bdd1SGireesh Nagabhushana 715*56b2bdd1SGireesh Nagabhushana case MAC_PROP_PRIVATE: 716*56b2bdd1SGireesh Nagabhushana return (getprop(pi, name, size, val)); 717*56b2bdd1SGireesh Nagabhushana 718*56b2bdd1SGireesh Nagabhushana default: 719*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 720*56b2bdd1SGireesh Nagabhushana } 721*56b2bdd1SGireesh Nagabhushana 722*56b2bdd1SGireesh Nagabhushana return (0); 723*56b2bdd1SGireesh Nagabhushana } 724*56b2bdd1SGireesh Nagabhushana 725*56b2bdd1SGireesh Nagabhushana static void 726*56b2bdd1SGireesh Nagabhushana t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id, 727*56b2bdd1SGireesh Nagabhushana mac_prop_info_handle_t ph) 728*56b2bdd1SGireesh Nagabhushana { 729*56b2bdd1SGireesh Nagabhushana struct port_info *pi = arg; 730*56b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg; 731*56b2bdd1SGireesh Nagabhushana 732*56b2bdd1SGireesh Nagabhushana switch (id) { 733*56b2bdd1SGireesh Nagabhushana case MAC_PROP_DUPLEX: 734*56b2bdd1SGireesh Nagabhushana case MAC_PROP_SPEED: 735*56b2bdd1SGireesh Nagabhushana case MAC_PROP_STATUS: 736*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 737*56b2bdd1SGireesh Nagabhushana break; 738*56b2bdd1SGireesh Nagabhushana 739*56b2bdd1SGireesh Nagabhushana case MAC_PROP_AUTONEG: 740*56b2bdd1SGireesh Nagabhushana if (lc->supported & FW_PORT_CAP_ANEG) 741*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1); 742*56b2bdd1SGireesh Nagabhushana else 743*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 744*56b2bdd1SGireesh Nagabhushana break; 745*56b2bdd1SGireesh Nagabhushana 746*56b2bdd1SGireesh Nagabhushana case MAC_PROP_MTU: 747*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_range_uint32(ph, 46, MAX_MTU); 748*56b2bdd1SGireesh Nagabhushana break; 749*56b2bdd1SGireesh Nagabhushana 750*56b2bdd1SGireesh Nagabhushana case MAC_PROP_FLOWCTRL: 751*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI); 752*56b2bdd1SGireesh Nagabhushana break; 753*56b2bdd1SGireesh Nagabhushana 754*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_10GFDX_CAP: 755*56b2bdd1SGireesh Nagabhushana if (lc->supported & FW_PORT_CAP_ANEG && 756*56b2bdd1SGireesh Nagabhushana lc->supported & FW_PORT_CAP_SPEED_10G) 757*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1); 758*56b2bdd1SGireesh Nagabhushana else 759*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 760*56b2bdd1SGireesh Nagabhushana break; 761*56b2bdd1SGireesh Nagabhushana 762*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_1000FDX_CAP: 763*56b2bdd1SGireesh Nagabhushana if (lc->supported & FW_PORT_CAP_ANEG && 764*56b2bdd1SGireesh Nagabhushana lc->supported & FW_PORT_CAP_SPEED_1G) 765*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1); 766*56b2bdd1SGireesh Nagabhushana else 767*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 768*56b2bdd1SGireesh Nagabhushana break; 769*56b2bdd1SGireesh Nagabhushana 770*56b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_100FDX_CAP: 771*56b2bdd1SGireesh Nagabhushana if (lc->supported & FW_PORT_CAP_ANEG && 772*56b2bdd1SGireesh Nagabhushana lc->supported & FW_PORT_CAP_SPEED_100M) 773*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1); 774*56b2bdd1SGireesh Nagabhushana else 775*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 776*56b2bdd1SGireesh Nagabhushana break; 777*56b2bdd1SGireesh Nagabhushana 778*56b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_10GFDX_CAP: 779*56b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_1000FDX_CAP: 780*56b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_100FDX_CAP: 781*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 782*56b2bdd1SGireesh Nagabhushana break; 783*56b2bdd1SGireesh Nagabhushana 784*56b2bdd1SGireesh Nagabhushana case MAC_PROP_PRIVATE: 785*56b2bdd1SGireesh Nagabhushana propinfo(pi, name, ph); 786*56b2bdd1SGireesh Nagabhushana break; 787*56b2bdd1SGireesh Nagabhushana 788*56b2bdd1SGireesh Nagabhushana default: 789*56b2bdd1SGireesh Nagabhushana break; 790*56b2bdd1SGireesh Nagabhushana } 791*56b2bdd1SGireesh Nagabhushana } 792*56b2bdd1SGireesh Nagabhushana 793*56b2bdd1SGireesh Nagabhushana static int 794*56b2bdd1SGireesh Nagabhushana begin_synchronized_op(struct port_info *pi, int hold, int waitok) 795*56b2bdd1SGireesh Nagabhushana { 796*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 797*56b2bdd1SGireesh Nagabhushana int rc = 0; 798*56b2bdd1SGireesh Nagabhushana 799*56b2bdd1SGireesh Nagabhushana ADAPTER_LOCK(sc); 800*56b2bdd1SGireesh Nagabhushana while (!IS_DOOMED(pi) && IS_BUSY(sc)) { 801*56b2bdd1SGireesh Nagabhushana if (!waitok) { 802*56b2bdd1SGireesh Nagabhushana rc = EBUSY; 803*56b2bdd1SGireesh Nagabhushana goto failed; 804*56b2bdd1SGireesh Nagabhushana } else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) { 805*56b2bdd1SGireesh Nagabhushana rc = EINTR; 806*56b2bdd1SGireesh Nagabhushana goto failed; 807*56b2bdd1SGireesh Nagabhushana } 808*56b2bdd1SGireesh Nagabhushana } 809*56b2bdd1SGireesh Nagabhushana if (IS_DOOMED(pi) != 0) { /* shouldn't happen on Solaris */ 810*56b2bdd1SGireesh Nagabhushana rc = ENXIO; 811*56b2bdd1SGireesh Nagabhushana goto failed; 812*56b2bdd1SGireesh Nagabhushana } 813*56b2bdd1SGireesh Nagabhushana ASSERT(!IS_BUSY(sc)); 814*56b2bdd1SGireesh Nagabhushana /* LINTED: E_CONSTANT_CONDITION */ 815*56b2bdd1SGireesh Nagabhushana SET_BUSY(sc); 816*56b2bdd1SGireesh Nagabhushana 817*56b2bdd1SGireesh Nagabhushana if (!hold) 818*56b2bdd1SGireesh Nagabhushana ADAPTER_UNLOCK(sc); 819*56b2bdd1SGireesh Nagabhushana 820*56b2bdd1SGireesh Nagabhushana return (0); 821*56b2bdd1SGireesh Nagabhushana failed: 822*56b2bdd1SGireesh Nagabhushana ADAPTER_UNLOCK(sc); 823*56b2bdd1SGireesh Nagabhushana return (rc); 824*56b2bdd1SGireesh Nagabhushana } 825*56b2bdd1SGireesh Nagabhushana 826*56b2bdd1SGireesh Nagabhushana static void 827*56b2bdd1SGireesh Nagabhushana end_synchronized_op(struct port_info *pi, int held) 828*56b2bdd1SGireesh Nagabhushana { 829*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 830*56b2bdd1SGireesh Nagabhushana 831*56b2bdd1SGireesh Nagabhushana if (!held) 832*56b2bdd1SGireesh Nagabhushana ADAPTER_LOCK(sc); 833*56b2bdd1SGireesh Nagabhushana 834*56b2bdd1SGireesh Nagabhushana ADAPTER_LOCK_ASSERT_OWNED(sc); 835*56b2bdd1SGireesh Nagabhushana ASSERT(IS_BUSY(sc)); 836*56b2bdd1SGireesh Nagabhushana /* LINTED: E_CONSTANT_CONDITION */ 837*56b2bdd1SGireesh Nagabhushana CLR_BUSY(sc); 838*56b2bdd1SGireesh Nagabhushana cv_signal(&sc->cv); 839*56b2bdd1SGireesh Nagabhushana ADAPTER_UNLOCK(sc); 840*56b2bdd1SGireesh Nagabhushana } 841*56b2bdd1SGireesh Nagabhushana 842*56b2bdd1SGireesh Nagabhushana static int 843*56b2bdd1SGireesh Nagabhushana t4_init_synchronized(struct port_info *pi) 844*56b2bdd1SGireesh Nagabhushana { 845*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 846*56b2bdd1SGireesh Nagabhushana int rc = 0; 847*56b2bdd1SGireesh Nagabhushana 848*56b2bdd1SGireesh Nagabhushana ADAPTER_LOCK_ASSERT_NOTOWNED(sc); 849*56b2bdd1SGireesh Nagabhushana 850*56b2bdd1SGireesh Nagabhushana if (isset(&sc->open_device_map, pi->port_id) != 0) 851*56b2bdd1SGireesh Nagabhushana return (0); /* already running */ 852*56b2bdd1SGireesh Nagabhushana 853*56b2bdd1SGireesh Nagabhushana if (!(sc->flags & FULL_INIT_DONE) && 854*56b2bdd1SGireesh Nagabhushana ((rc = adapter_full_init(sc)) != 0)) 855*56b2bdd1SGireesh Nagabhushana return (rc); /* error message displayed already */ 856*56b2bdd1SGireesh Nagabhushana 857*56b2bdd1SGireesh Nagabhushana if (!(pi->flags & PORT_INIT_DONE)) { 858*56b2bdd1SGireesh Nagabhushana rc = port_full_init(pi); 859*56b2bdd1SGireesh Nagabhushana if (rc != 0) 860*56b2bdd1SGireesh Nagabhushana return (rc); /* error message displayed already */ 861*56b2bdd1SGireesh Nagabhushana } else 862*56b2bdd1SGireesh Nagabhushana enable_port_queues(pi); 863*56b2bdd1SGireesh Nagabhushana 864*56b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false); 865*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 866*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc); 867*56b2bdd1SGireesh Nagabhushana goto done; 868*56b2bdd1SGireesh Nagabhushana } 869*56b2bdd1SGireesh Nagabhushana rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, 870*56b2bdd1SGireesh Nagabhushana pi->hw_addr, true, true); 871*56b2bdd1SGireesh Nagabhushana if (rc < 0) { 872*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc); 873*56b2bdd1SGireesh Nagabhushana rc = -rc; 874*56b2bdd1SGireesh Nagabhushana goto done; 875*56b2bdd1SGireesh Nagabhushana } else 876*56b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */ 877*56b2bdd1SGireesh Nagabhushana pi->xact_addr_filt = rc; 878*56b2bdd1SGireesh Nagabhushana 879*56b2bdd1SGireesh Nagabhushana rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, &pi->link_cfg); 880*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 881*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc); 882*56b2bdd1SGireesh Nagabhushana goto done; 883*56b2bdd1SGireesh Nagabhushana } 884*56b2bdd1SGireesh Nagabhushana 885*56b2bdd1SGireesh Nagabhushana rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true); 886*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 887*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc); 888*56b2bdd1SGireesh Nagabhushana goto done; 889*56b2bdd1SGireesh Nagabhushana } 890*56b2bdd1SGireesh Nagabhushana 891*56b2bdd1SGireesh Nagabhushana /* all ok */ 892*56b2bdd1SGireesh Nagabhushana setbit(&sc->open_device_map, pi->port_id); 893*56b2bdd1SGireesh Nagabhushana done: 894*56b2bdd1SGireesh Nagabhushana if (rc != 0) 895*56b2bdd1SGireesh Nagabhushana (void) t4_uninit_synchronized(pi); 896*56b2bdd1SGireesh Nagabhushana 897*56b2bdd1SGireesh Nagabhushana return (rc); 898*56b2bdd1SGireesh Nagabhushana } 899*56b2bdd1SGireesh Nagabhushana 900*56b2bdd1SGireesh Nagabhushana /* 901*56b2bdd1SGireesh Nagabhushana * Idempotent. 902*56b2bdd1SGireesh Nagabhushana */ 903*56b2bdd1SGireesh Nagabhushana static int 904*56b2bdd1SGireesh Nagabhushana t4_uninit_synchronized(struct port_info *pi) 905*56b2bdd1SGireesh Nagabhushana { 906*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 907*56b2bdd1SGireesh Nagabhushana int rc; 908*56b2bdd1SGireesh Nagabhushana 909*56b2bdd1SGireesh Nagabhushana ADAPTER_LOCK_ASSERT_NOTOWNED(sc); 910*56b2bdd1SGireesh Nagabhushana 911*56b2bdd1SGireesh Nagabhushana /* 912*56b2bdd1SGireesh Nagabhushana * Disable the VI so that all its data in either direction is discarded 913*56b2bdd1SGireesh Nagabhushana * by the MPS. Leave everything else (the queues, interrupts, and 1Hz 914*56b2bdd1SGireesh Nagabhushana * tick) intact as the TP can deliver negative advice or data that it's 915*56b2bdd1SGireesh Nagabhushana * holding in its RAM (for an offloaded connection) even after the VI is 916*56b2bdd1SGireesh Nagabhushana * disabled. 917*56b2bdd1SGireesh Nagabhushana */ 918*56b2bdd1SGireesh Nagabhushana rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false); 919*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 920*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc); 921*56b2bdd1SGireesh Nagabhushana return (rc); 922*56b2bdd1SGireesh Nagabhushana } 923*56b2bdd1SGireesh Nagabhushana 924*56b2bdd1SGireesh Nagabhushana disable_port_queues(pi); 925*56b2bdd1SGireesh Nagabhushana 926*56b2bdd1SGireesh Nagabhushana clrbit(&sc->open_device_map, pi->port_id); 927*56b2bdd1SGireesh Nagabhushana 928*56b2bdd1SGireesh Nagabhushana pi->link_cfg.link_ok = 0; 929*56b2bdd1SGireesh Nagabhushana pi->link_cfg.speed = 0; 930*56b2bdd1SGireesh Nagabhushana mac_link_update(pi->mh, LINK_STATE_UNKNOWN); 931*56b2bdd1SGireesh Nagabhushana 932*56b2bdd1SGireesh Nagabhushana return (0); 933*56b2bdd1SGireesh Nagabhushana } 934*56b2bdd1SGireesh Nagabhushana 935*56b2bdd1SGireesh Nagabhushana static void 936*56b2bdd1SGireesh Nagabhushana propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph) 937*56b2bdd1SGireesh Nagabhushana { 938*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 939*56b2bdd1SGireesh Nagabhushana struct driver_properties *p = &sc->props; 940*56b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg; 941*56b2bdd1SGireesh Nagabhushana int v; 942*56b2bdd1SGireesh Nagabhushana char str[16]; 943*56b2bdd1SGireesh Nagabhushana 944*56b2bdd1SGireesh Nagabhushana if (strcmp(name, T4PROP_TMR_IDX) == 0) 945*56b2bdd1SGireesh Nagabhushana v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g; 946*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_PKTC_IDX) == 0) 947*56b2bdd1SGireesh Nagabhushana v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g; 948*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_CSUM) == 0) 949*56b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 950*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_LSO) == 0) 951*56b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 952*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_TX_PAUSE) == 0) 953*56b2bdd1SGireesh Nagabhushana v = (lc->fc & PAUSE_TX) ? 1 : 0; 954*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_RX_PAUSE) == 0) 955*56b2bdd1SGireesh Nagabhushana v = (lc->fc & PAUSE_RX) ? 1 : 0; 956*56b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1 957*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_MTU) == 0) 958*56b2bdd1SGireesh Nagabhushana v = ETHERMTU; 959*56b2bdd1SGireesh Nagabhushana #endif 960*56b2bdd1SGireesh Nagabhushana else 961*56b2bdd1SGireesh Nagabhushana return; 962*56b2bdd1SGireesh Nagabhushana 963*56b2bdd1SGireesh Nagabhushana (void) snprintf(str, sizeof (str), "%d", v); 964*56b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_str(ph, str); 965*56b2bdd1SGireesh Nagabhushana } 966*56b2bdd1SGireesh Nagabhushana 967*56b2bdd1SGireesh Nagabhushana static int 968*56b2bdd1SGireesh Nagabhushana getprop(struct port_info *pi, const char *name, uint_t size, void *val) 969*56b2bdd1SGireesh Nagabhushana { 970*56b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg; 971*56b2bdd1SGireesh Nagabhushana int v; 972*56b2bdd1SGireesh Nagabhushana 973*56b2bdd1SGireesh Nagabhushana if (strcmp(name, T4PROP_TMR_IDX) == 0) 974*56b2bdd1SGireesh Nagabhushana v = pi->tmr_idx; 975*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_PKTC_IDX) == 0) 976*56b2bdd1SGireesh Nagabhushana v = pi->pktc_idx; 977*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_CSUM) == 0) 978*56b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 979*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_LSO) == 0) 980*56b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 981*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_TX_PAUSE) == 0) 982*56b2bdd1SGireesh Nagabhushana v = (lc->fc & PAUSE_TX) ? 1 : 0; 983*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_RX_PAUSE) == 0) 984*56b2bdd1SGireesh Nagabhushana v = (lc->fc & PAUSE_RX) ? 1 : 0; 985*56b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1 986*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_MTU) == 0) 987*56b2bdd1SGireesh Nagabhushana v = pi->mtu; 988*56b2bdd1SGireesh Nagabhushana #endif 989*56b2bdd1SGireesh Nagabhushana else 990*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 991*56b2bdd1SGireesh Nagabhushana 992*56b2bdd1SGireesh Nagabhushana (void) snprintf(val, size, "%d", v); 993*56b2bdd1SGireesh Nagabhushana return (0); 994*56b2bdd1SGireesh Nagabhushana } 995*56b2bdd1SGireesh Nagabhushana 996*56b2bdd1SGireesh Nagabhushana static int 997*56b2bdd1SGireesh Nagabhushana setprop(struct port_info *pi, const char *name, const void *val) 998*56b2bdd1SGireesh Nagabhushana { 999*56b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter; 1000*56b2bdd1SGireesh Nagabhushana long v; 1001*56b2bdd1SGireesh Nagabhushana int i, rc = 0, relink = 0, rx_mode = 0; 1002*56b2bdd1SGireesh Nagabhushana struct sge_rxq *rxq; 1003*56b2bdd1SGireesh Nagabhushana struct link_config lc_old, *lc = &pi->link_cfg; 1004*56b2bdd1SGireesh Nagabhushana 1005*56b2bdd1SGireesh Nagabhushana /* 1006*56b2bdd1SGireesh Nagabhushana * Save a copy of link_config. This can be used to restore link_config 1007*56b2bdd1SGireesh Nagabhushana * if t4_link_start() fails. 1008*56b2bdd1SGireesh Nagabhushana */ 1009*56b2bdd1SGireesh Nagabhushana bcopy(lc, &lc_old, sizeof (struct link_config)); 1010*56b2bdd1SGireesh Nagabhushana 1011*56b2bdd1SGireesh Nagabhushana (void) ddi_strtol(val, NULL, 0, &v); 1012*56b2bdd1SGireesh Nagabhushana 1013*56b2bdd1SGireesh Nagabhushana if (strcmp(name, T4PROP_TMR_IDX) == 0) { 1014*56b2bdd1SGireesh Nagabhushana if (v < 0 || v >= SGE_NTIMERS) 1015*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1016*56b2bdd1SGireesh Nagabhushana if (v == pi->tmr_idx) 1017*56b2bdd1SGireesh Nagabhushana return (0); 1018*56b2bdd1SGireesh Nagabhushana 1019*56b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */ 1020*56b2bdd1SGireesh Nagabhushana pi->tmr_idx = v; 1021*56b2bdd1SGireesh Nagabhushana for_each_rxq(pi, i, rxq) { 1022*56b2bdd1SGireesh Nagabhushana rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) | 1023*56b2bdd1SGireesh Nagabhushana V_QINTR_CNT_EN(pi->pktc_idx >= 0); 1024*56b2bdd1SGireesh Nagabhushana } 1025*56b2bdd1SGireesh Nagabhushana 1026*56b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_PKTC_IDX) == 0) { 1027*56b2bdd1SGireesh Nagabhushana if (v >= SGE_NCOUNTERS) 1028*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1029*56b2bdd1SGireesh Nagabhushana if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1)) 1030*56b2bdd1SGireesh Nagabhushana return (0); 1031*56b2bdd1SGireesh Nagabhushana 1032*56b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */ 1033*56b2bdd1SGireesh Nagabhushana pi->pktc_idx = v < 0 ? -1 : v; 1034*56b2bdd1SGireesh Nagabhushana for_each_rxq(pi, i, rxq) { 1035*56b2bdd1SGireesh Nagabhushana rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) | 1036*56b2bdd1SGireesh Nagabhushana /* takes effect right away */ 1037*56b2bdd1SGireesh Nagabhushana V_QINTR_CNT_EN(v >= 0); 1038*56b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */ 1039*56b2bdd1SGireesh Nagabhushana rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */ 1040*56b2bdd1SGireesh Nagabhushana } 1041*56b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_HW_CSUM) == 0) { 1042*56b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1) 1043*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1044*56b2bdd1SGireesh Nagabhushana if (v == 1) 1045*56b2bdd1SGireesh Nagabhushana pi->features |= CXGBE_HW_CSUM; 1046*56b2bdd1SGireesh Nagabhushana else 1047*56b2bdd1SGireesh Nagabhushana pi->features &= ~CXGBE_HW_CSUM; 1048*56b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_HW_LSO) == 0) { 1049*56b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1) 1050*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1051*56b2bdd1SGireesh Nagabhushana if (v == 1) 1052*56b2bdd1SGireesh Nagabhushana pi->features |= CXGBE_HW_LSO; 1053*56b2bdd1SGireesh Nagabhushana else 1054*56b2bdd1SGireesh Nagabhushana pi->features &= ~CXGBE_HW_LSO; 1055*56b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_TX_PAUSE) == 0) { 1056*56b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1) 1057*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1058*56b2bdd1SGireesh Nagabhushana 1059*56b2bdd1SGireesh Nagabhushana if (v != 0) 1060*56b2bdd1SGireesh Nagabhushana lc->requested_fc |= PAUSE_TX; 1061*56b2bdd1SGireesh Nagabhushana else 1062*56b2bdd1SGireesh Nagabhushana lc->requested_fc &= ~PAUSE_TX; 1063*56b2bdd1SGireesh Nagabhushana 1064*56b2bdd1SGireesh Nagabhushana relink = 1; 1065*56b2bdd1SGireesh Nagabhushana 1066*56b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_RX_PAUSE) == 0) { 1067*56b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1) 1068*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1069*56b2bdd1SGireesh Nagabhushana 1070*56b2bdd1SGireesh Nagabhushana if (v != 0) 1071*56b2bdd1SGireesh Nagabhushana lc->requested_fc |= PAUSE_RX; 1072*56b2bdd1SGireesh Nagabhushana else 1073*56b2bdd1SGireesh Nagabhushana lc->requested_fc &= ~PAUSE_RX; 1074*56b2bdd1SGireesh Nagabhushana 1075*56b2bdd1SGireesh Nagabhushana relink = 1; 1076*56b2bdd1SGireesh Nagabhushana } 1077*56b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1 1078*56b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_MTU) == 0) { 1079*56b2bdd1SGireesh Nagabhushana if (v < 46 || v > MAX_MTU) 1080*56b2bdd1SGireesh Nagabhushana return (EINVAL); 1081*56b2bdd1SGireesh Nagabhushana if (v == pi->mtu) 1082*56b2bdd1SGireesh Nagabhushana return (0); 1083*56b2bdd1SGireesh Nagabhushana 1084*56b2bdd1SGireesh Nagabhushana pi->mtu = (int)v; 1085*56b2bdd1SGireesh Nagabhushana (void) mac_maxsdu_update(pi->mh, v); 1086*56b2bdd1SGireesh Nagabhushana rx_mode = 1; 1087*56b2bdd1SGireesh Nagabhushana } 1088*56b2bdd1SGireesh Nagabhushana #endif 1089*56b2bdd1SGireesh Nagabhushana else 1090*56b2bdd1SGireesh Nagabhushana return (ENOTSUP); 1091*56b2bdd1SGireesh Nagabhushana 1092*56b2bdd1SGireesh Nagabhushana if (!(relink || rx_mode)) 1093*56b2bdd1SGireesh Nagabhushana return (0); 1094*56b2bdd1SGireesh Nagabhushana 1095*56b2bdd1SGireesh Nagabhushana /* If we are here, either relink or rx_mode is 1 */ 1096*56b2bdd1SGireesh Nagabhushana if (isset(&sc->open_device_map, pi->port_id) != 0) { 1097*56b2bdd1SGireesh Nagabhushana if (relink != 0) { 1098*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 1099*56b2bdd1SGireesh Nagabhushana if (rc != 0) 1100*56b2bdd1SGireesh Nagabhushana return (rc); 1101*56b2bdd1SGireesh Nagabhushana rc = -t4_link_start(sc, sc->mbox, pi->tx_chan, lc); 1102*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 1103*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 1104*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, 1105*56b2bdd1SGireesh Nagabhushana "start_link failed:%d", rc); 1106*56b2bdd1SGireesh Nagabhushana /* Restore link_config */ 1107*56b2bdd1SGireesh Nagabhushana bcopy(&lc_old, lc, sizeof (struct link_config)); 1108*56b2bdd1SGireesh Nagabhushana } 1109*56b2bdd1SGireesh Nagabhushana } else if (rx_mode != 0) { 1110*56b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1); 1111*56b2bdd1SGireesh Nagabhushana if (rc != 0) 1112*56b2bdd1SGireesh Nagabhushana return (rc); 1113*56b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1, 1114*56b2bdd1SGireesh Nagabhushana -1, -1, false); 1115*56b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1); 1116*56b2bdd1SGireesh Nagabhushana if (rc != 0) { 1117*56b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, 1118*56b2bdd1SGireesh Nagabhushana "set_rxmode failed: %d", rc); 1119*56b2bdd1SGireesh Nagabhushana } 1120*56b2bdd1SGireesh Nagabhushana } 1121*56b2bdd1SGireesh Nagabhushana return (rc); 1122*56b2bdd1SGireesh Nagabhushana } 1123*56b2bdd1SGireesh Nagabhushana 1124*56b2bdd1SGireesh Nagabhushana return (0); 1125*56b2bdd1SGireesh Nagabhushana } 1126*56b2bdd1SGireesh Nagabhushana 1127*56b2bdd1SGireesh Nagabhushana void 1128*56b2bdd1SGireesh Nagabhushana t4_mc_init(struct port_info *pi) 1129*56b2bdd1SGireesh Nagabhushana { 1130*56b2bdd1SGireesh Nagabhushana pi->mc = &t4_m_callbacks; 1131*56b2bdd1SGireesh Nagabhushana pi->props = t4_priv_props; 1132*56b2bdd1SGireesh Nagabhushana } 1133*56b2bdd1SGireesh Nagabhushana 1134*56b2bdd1SGireesh Nagabhushana void 1135*56b2bdd1SGireesh Nagabhushana t4_os_link_changed(struct adapter *sc, int idx, int link_stat) 1136*56b2bdd1SGireesh Nagabhushana { 1137*56b2bdd1SGireesh Nagabhushana struct port_info *pi = sc->port[idx]; 1138*56b2bdd1SGireesh Nagabhushana 1139*56b2bdd1SGireesh Nagabhushana mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN); 1140*56b2bdd1SGireesh Nagabhushana } 1141*56b2bdd1SGireesh Nagabhushana 1142*56b2bdd1SGireesh Nagabhushana /* ARGSUSED */ 1143*56b2bdd1SGireesh Nagabhushana void 1144*56b2bdd1SGireesh Nagabhushana t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m) 1145*56b2bdd1SGireesh Nagabhushana { 1146*56b2bdd1SGireesh Nagabhushana mac_rx(pi->mh, NULL, m); 1147*56b2bdd1SGireesh Nagabhushana } 1148