156b2bdd1SGireesh Nagabhushana /*
256b2bdd1SGireesh Nagabhushana * This file and its contents are supplied under the terms of the
356b2bdd1SGireesh Nagabhushana * Common Development and Distribution License ("CDDL"), version 1.0.
456b2bdd1SGireesh Nagabhushana * You may only use this file in accordance with the terms of version
556b2bdd1SGireesh Nagabhushana * 1.0 of the CDDL.
656b2bdd1SGireesh Nagabhushana *
756b2bdd1SGireesh Nagabhushana * A full copy of the text of the CDDL should have accompanied this
856b2bdd1SGireesh Nagabhushana * source. A copy of the CDDL is also available via the Internet at
956b2bdd1SGireesh Nagabhushana * http://www.illumos.org/license/CDDL.
1056b2bdd1SGireesh Nagabhushana */
1156b2bdd1SGireesh Nagabhushana
1256b2bdd1SGireesh Nagabhushana /*
1356b2bdd1SGireesh Nagabhushana * This file is part of the Chelsio T4 support code.
1456b2bdd1SGireesh Nagabhushana *
1556b2bdd1SGireesh Nagabhushana * Copyright (C) 2010-2013 Chelsio Communications. All rights reserved.
1656b2bdd1SGireesh Nagabhushana *
1756b2bdd1SGireesh Nagabhushana * This program is distributed in the hope that it will be useful, but WITHOUT
1856b2bdd1SGireesh Nagabhushana * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1956b2bdd1SGireesh Nagabhushana * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
2056b2bdd1SGireesh Nagabhushana * release for licensing terms and conditions.
2156b2bdd1SGireesh Nagabhushana */
2256b2bdd1SGireesh Nagabhushana
23d77e6e0fSPaul Winder /*
24d77e6e0fSPaul Winder * Copyright 2020 RackTop Systems, Inc.
25*ece8d794SRobert Mustacchi * Copyright 2023 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
117*ece8d794SRobert Mustacchi /*
118*ece8d794SRobert Mustacchi * To determine the actual Ethernet mode that we're in we need to look at the
119*ece8d794SRobert Mustacchi * port type. That will tell us whether we're using a BASE-T PHY, have an
120*ece8d794SRobert Mustacchi * external SFP connection whose module type we also need to use to qualify
121*ece8d794SRobert Mustacchi * this, and then the link speed itself. Combining that tuple we can then get
122*ece8d794SRobert Mustacchi * the current media.
123*ece8d794SRobert Mustacchi *
124*ece8d794SRobert Mustacchi * Our tables below assume we have gotten it down so the last thing we need to
125*ece8d794SRobert Mustacchi * consider is a single speed. If port types end up supporting the same class of
126*ece8d794SRobert Mustacchi * transceiver at a given speed, then this will need to be changed to use
127*ece8d794SRobert Mustacchi * additional information to disambiguate that (which will require additional
128*ece8d794SRobert Mustacchi * logic from the firmware).
129*ece8d794SRobert Mustacchi */
130*ece8d794SRobert Mustacchi typedef struct {
131*ece8d794SRobert Mustacchi fw_port_cap32_t tmm_speed;
132*ece8d794SRobert Mustacchi mac_ether_media_t tmm_ether;
133*ece8d794SRobert Mustacchi } t4nex_media_map_t;
134*ece8d794SRobert Mustacchi
135*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_baset[] = {
136*ece8d794SRobert Mustacchi /*
137*ece8d794SRobert Mustacchi * We're assuming that the 100 Mb/s mode is 100BASE-TX. It's hard to say
138*ece8d794SRobert Mustacchi * for certain what the phy would have done, but given the rest of the
139*ece8d794SRobert Mustacchi * market, that seems the most likely one.
140*ece8d794SRobert Mustacchi */
141*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100M, ETHER_MEDIA_100BASE_TX },
142*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_T },
143*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_T }
144*ece8d794SRobert Mustacchi };
145*ece8d794SRobert Mustacchi
146*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_kx[] = {
147*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
148*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KX4 }
149*ece8d794SRobert Mustacchi };
150*ece8d794SRobert Mustacchi
151*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_cx[] = {
152*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CX4 }
153*ece8d794SRobert Mustacchi };
154*ece8d794SRobert Mustacchi
155*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_kr[] = {
156*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX },
157*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KR },
158*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_KR },
159*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_KR4 },
160*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_KR2 },
161*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_KR4 },
162*ece8d794SRobert Mustacchi };
163*ece8d794SRobert Mustacchi
164*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_lr[] = {
165*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_LX },
166*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LR },
167*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_LR },
168*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_LR4 },
169*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_LR2 },
170*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_LR4 },
171*ece8d794SRobert Mustacchi };
172*ece8d794SRobert Mustacchi
173*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_sr[] = {
174*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_SX },
175*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_SR },
176*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_SR },
177*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_SR4 },
178*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_SR2 },
179*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_SR4 },
180*ece8d794SRobert Mustacchi };
181*ece8d794SRobert Mustacchi
182*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_er[] = {
183*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ER },
184*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ER },
185*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ER4 },
186*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ER4 },
187*ece8d794SRobert Mustacchi };
188*ece8d794SRobert Mustacchi
189*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_cr[] = {
190*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
191*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CR },
192*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_CR },
193*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_CR4 },
194*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_CR2 },
195*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_CR4 },
196*ece8d794SRobert Mustacchi };
197*ece8d794SRobert Mustacchi
198*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_acc[] = {
199*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX },
200*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ACC },
201*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ACC },
202*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ACC4 },
203*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_ACC2 },
204*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ACC4 },
205*ece8d794SRobert Mustacchi };
206*ece8d794SRobert Mustacchi
207*ece8d794SRobert Mustacchi static const t4nex_media_map_t t4nex_map_lrm[] = {
208*ece8d794SRobert Mustacchi { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LRM },
209*ece8d794SRobert Mustacchi };
210*ece8d794SRobert Mustacchi
211*ece8d794SRobert Mustacchi static mac_ether_media_t
t4_port_to_media(struct port_info * pi)212*ece8d794SRobert Mustacchi t4_port_to_media(struct port_info *pi)
213*ece8d794SRobert Mustacchi {
214*ece8d794SRobert Mustacchi fw_port_cap32_t speed;
215*ece8d794SRobert Mustacchi struct link_config *lc = &pi->link_cfg;
216*ece8d794SRobert Mustacchi const t4nex_media_map_t *map = NULL;
217*ece8d794SRobert Mustacchi size_t count = 0;
218*ece8d794SRobert Mustacchi
219*ece8d794SRobert Mustacchi if (lc->link_ok != 0) {
220*ece8d794SRobert Mustacchi speed = t4_link_fwcap_to_fwspeed(lc->link_caps);
221*ece8d794SRobert Mustacchi } else {
222*ece8d794SRobert Mustacchi return (ETHER_MEDIA_UNKNOWN);
223*ece8d794SRobert Mustacchi }
224*ece8d794SRobert Mustacchi
225*ece8d794SRobert Mustacchi switch (pi->port_type) {
226*ece8d794SRobert Mustacchi case FW_PORT_TYPE_FIBER_XFI:
227*ece8d794SRobert Mustacchi case FW_PORT_TYPE_FIBER_XAUI:
228*ece8d794SRobert Mustacchi case FW_PORT_TYPE_SFP:
229*ece8d794SRobert Mustacchi case FW_PORT_TYPE_QSFP_10G:
230*ece8d794SRobert Mustacchi case FW_PORT_TYPE_QSA:
231*ece8d794SRobert Mustacchi case FW_PORT_TYPE_QSFP:
232*ece8d794SRobert Mustacchi case FW_PORT_TYPE_CR4_QSFP:
233*ece8d794SRobert Mustacchi case FW_PORT_TYPE_CR_QSFP:
234*ece8d794SRobert Mustacchi case FW_PORT_TYPE_CR2_QSFP:
235*ece8d794SRobert Mustacchi case FW_PORT_TYPE_SFP28:
236*ece8d794SRobert Mustacchi switch (pi->mod_type) {
237*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_LR:
238*ece8d794SRobert Mustacchi map = t4nex_map_lr;
239*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_lr);
240*ece8d794SRobert Mustacchi break;
241*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_SR:
242*ece8d794SRobert Mustacchi map = t4nex_map_sr;
243*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_sr);
244*ece8d794SRobert Mustacchi break;
245*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_ER:
246*ece8d794SRobert Mustacchi map = t4nex_map_er;
247*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_er);
248*ece8d794SRobert Mustacchi break;
249*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_TWINAX_PASSIVE:
250*ece8d794SRobert Mustacchi map = t4nex_map_cr;
251*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_cr);
252*ece8d794SRobert Mustacchi break;
253*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_TWINAX_ACTIVE:
254*ece8d794SRobert Mustacchi map = t4nex_map_acc;
255*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_acc);
256*ece8d794SRobert Mustacchi break;
257*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_LRM:
258*ece8d794SRobert Mustacchi map = t4nex_map_lrm;
259*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_lrm);
260*ece8d794SRobert Mustacchi break;
261*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_ERROR:
262*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_UNKNOWN:
263*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_NOTSUPPORTED:
264*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_NONE:
265*ece8d794SRobert Mustacchi case FW_PORT_MOD_TYPE_NA:
266*ece8d794SRobert Mustacchi default:
267*ece8d794SRobert Mustacchi break;
268*ece8d794SRobert Mustacchi }
269*ece8d794SRobert Mustacchi break;
270*ece8d794SRobert Mustacchi case FW_PORT_TYPE_KX4:
271*ece8d794SRobert Mustacchi case FW_PORT_TYPE_KX:
272*ece8d794SRobert Mustacchi map = t4nex_map_kx;
273*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_kx);
274*ece8d794SRobert Mustacchi break;
275*ece8d794SRobert Mustacchi case FW_PORT_TYPE_CX4:
276*ece8d794SRobert Mustacchi map = t4nex_map_cx;
277*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_cx);
278*ece8d794SRobert Mustacchi break;
279*ece8d794SRobert Mustacchi case FW_PORT_TYPE_KR:
280*ece8d794SRobert Mustacchi case FW_PORT_TYPE_BP_AP:
281*ece8d794SRobert Mustacchi case FW_PORT_TYPE_BP4_AP:
282*ece8d794SRobert Mustacchi case FW_PORT_TYPE_BP40_BA:
283*ece8d794SRobert Mustacchi case FW_PORT_TYPE_KR4_100G:
284*ece8d794SRobert Mustacchi case FW_PORT_TYPE_KR_SFP28:
285*ece8d794SRobert Mustacchi case FW_PORT_TYPE_KR_XLAUI:
286*ece8d794SRobert Mustacchi map = t4nex_map_kr;
287*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_kr);
288*ece8d794SRobert Mustacchi break;
289*ece8d794SRobert Mustacchi case FW_PORT_TYPE_BT_SGMII:
290*ece8d794SRobert Mustacchi case FW_PORT_TYPE_BT_XFI:
291*ece8d794SRobert Mustacchi case FW_PORT_TYPE_BT_XAUI:
292*ece8d794SRobert Mustacchi map = t4nex_map_baset;
293*ece8d794SRobert Mustacchi count = ARRAY_SIZE(t4nex_map_baset);
294*ece8d794SRobert Mustacchi break;
295*ece8d794SRobert Mustacchi case FW_PORT_TYPE_NONE:
296*ece8d794SRobert Mustacchi default:
297*ece8d794SRobert Mustacchi break;
298*ece8d794SRobert Mustacchi }
299*ece8d794SRobert Mustacchi
300*ece8d794SRobert Mustacchi for (size_t i = 0; i < count; i++) {
301*ece8d794SRobert Mustacchi if (map[i].tmm_speed == speed) {
302*ece8d794SRobert Mustacchi return (map[i].tmm_ether);
303*ece8d794SRobert Mustacchi }
304*ece8d794SRobert Mustacchi }
305*ece8d794SRobert Mustacchi
306*ece8d794SRobert Mustacchi /*
307*ece8d794SRobert Mustacchi * At this point we return unknown as we already checked for a down link
308*ece8d794SRobert Mustacchi * earlier.
309*ece8d794SRobert Mustacchi */
310*ece8d794SRobert Mustacchi return (ETHER_MEDIA_UNKNOWN);
311*ece8d794SRobert Mustacchi }
312*ece8d794SRobert Mustacchi
31356b2bdd1SGireesh Nagabhushana static int
t4_mc_getstat(void * arg,uint_t stat,uint64_t * val)31456b2bdd1SGireesh Nagabhushana t4_mc_getstat(void *arg, uint_t stat, uint64_t *val)
31556b2bdd1SGireesh Nagabhushana {
31656b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
31756b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
31856b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg;
31956b2bdd1SGireesh Nagabhushana
32056b2bdd1SGireesh Nagabhushana #define GET_STAT(name) \
32156b2bdd1SGireesh Nagabhushana t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L))
32256b2bdd1SGireesh Nagabhushana
32356b2bdd1SGireesh Nagabhushana switch (stat) {
32456b2bdd1SGireesh Nagabhushana case MAC_STAT_IFSPEED:
32556b2bdd1SGireesh Nagabhushana if (lc->link_ok != 0) {
3266feac2e3SRahul Lakkireddy *val = t4_link_fwcap_to_speed(lc->link_caps);
32756b2bdd1SGireesh Nagabhushana *val *= 1000000;
32856b2bdd1SGireesh Nagabhushana } else
32956b2bdd1SGireesh Nagabhushana *val = 0;
33056b2bdd1SGireesh Nagabhushana break;
33156b2bdd1SGireesh Nagabhushana
33256b2bdd1SGireesh Nagabhushana case MAC_STAT_MULTIRCV:
33356b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MCAST);
33456b2bdd1SGireesh Nagabhushana break;
33556b2bdd1SGireesh Nagabhushana
33656b2bdd1SGireesh Nagabhushana case MAC_STAT_BRDCSTRCV:
33756b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_BCAST);
33856b2bdd1SGireesh Nagabhushana break;
33956b2bdd1SGireesh Nagabhushana
34056b2bdd1SGireesh Nagabhushana case MAC_STAT_MULTIXMT:
34156b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_MCAST);
34256b2bdd1SGireesh Nagabhushana break;
34356b2bdd1SGireesh Nagabhushana
34456b2bdd1SGireesh Nagabhushana case MAC_STAT_BRDCSTXMT:
34556b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_BCAST);
34656b2bdd1SGireesh Nagabhushana break;
34756b2bdd1SGireesh Nagabhushana
34856b2bdd1SGireesh Nagabhushana case MAC_STAT_NORCVBUF:
34956b2bdd1SGireesh Nagabhushana *val = 0; /* TODO should come from rxq->nomem */
35056b2bdd1SGireesh Nagabhushana break;
35156b2bdd1SGireesh Nagabhushana
35256b2bdd1SGireesh Nagabhushana case MAC_STAT_IERRORS:
35356b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MTU_ERROR) +
35456b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_MTU_CRC_ERROR) +
35556b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_CRC_ERROR) +
35656b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LEN_ERROR) +
35756b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_SYM_ERROR) +
35856b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LESS_64B);
35956b2bdd1SGireesh Nagabhushana break;
36056b2bdd1SGireesh Nagabhushana
36156b2bdd1SGireesh Nagabhushana case MAC_STAT_UNKNOWNS:
36256b2bdd1SGireesh Nagabhushana return (ENOTSUP);
36356b2bdd1SGireesh Nagabhushana
36456b2bdd1SGireesh Nagabhushana case MAC_STAT_NOXMTBUF:
36556b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_DROP);
36656b2bdd1SGireesh Nagabhushana break;
36756b2bdd1SGireesh Nagabhushana
36856b2bdd1SGireesh Nagabhushana case MAC_STAT_OERRORS:
36956b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_ERROR);
37056b2bdd1SGireesh Nagabhushana break;
37156b2bdd1SGireesh Nagabhushana
37256b2bdd1SGireesh Nagabhushana case MAC_STAT_COLLISIONS:
37356b2bdd1SGireesh Nagabhushana return (ENOTSUP);
37456b2bdd1SGireesh Nagabhushana
37556b2bdd1SGireesh Nagabhushana case MAC_STAT_RBYTES:
37656b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_BYTES);
37756b2bdd1SGireesh Nagabhushana break;
37856b2bdd1SGireesh Nagabhushana
37956b2bdd1SGireesh Nagabhushana case MAC_STAT_IPACKETS:
38056b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_FRAMES);
38156b2bdd1SGireesh Nagabhushana break;
38256b2bdd1SGireesh Nagabhushana
38356b2bdd1SGireesh Nagabhushana case MAC_STAT_OBYTES:
38456b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_BYTES);
38556b2bdd1SGireesh Nagabhushana break;
38656b2bdd1SGireesh Nagabhushana
38756b2bdd1SGireesh Nagabhushana case MAC_STAT_OPACKETS:
38856b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_FRAMES);
38956b2bdd1SGireesh Nagabhushana break;
39056b2bdd1SGireesh Nagabhushana
39156b2bdd1SGireesh Nagabhushana case ETHER_STAT_ALIGN_ERRORS:
39256b2bdd1SGireesh Nagabhushana return (ENOTSUP);
39356b2bdd1SGireesh Nagabhushana
39456b2bdd1SGireesh Nagabhushana case ETHER_STAT_FCS_ERRORS:
39556b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_CRC_ERROR);
39656b2bdd1SGireesh Nagabhushana break;
39756b2bdd1SGireesh Nagabhushana
39856b2bdd1SGireesh Nagabhushana case ETHER_STAT_FIRST_COLLISIONS:
39956b2bdd1SGireesh Nagabhushana case ETHER_STAT_MULTI_COLLISIONS:
40056b2bdd1SGireesh Nagabhushana case ETHER_STAT_SQE_ERRORS:
40156b2bdd1SGireesh Nagabhushana case ETHER_STAT_DEFER_XMTS:
40256b2bdd1SGireesh Nagabhushana case ETHER_STAT_TX_LATE_COLLISIONS:
40356b2bdd1SGireesh Nagabhushana case ETHER_STAT_EX_COLLISIONS:
40456b2bdd1SGireesh Nagabhushana return (ENOTSUP);
40556b2bdd1SGireesh Nagabhushana
40656b2bdd1SGireesh Nagabhushana case ETHER_STAT_MACXMT_ERRORS:
40756b2bdd1SGireesh Nagabhushana *val = GET_STAT(TX_PORT_ERROR);
40856b2bdd1SGireesh Nagabhushana break;
40956b2bdd1SGireesh Nagabhushana
41056b2bdd1SGireesh Nagabhushana case ETHER_STAT_CARRIER_ERRORS:
41156b2bdd1SGireesh Nagabhushana return (ENOTSUP);
41256b2bdd1SGireesh Nagabhushana
41356b2bdd1SGireesh Nagabhushana case ETHER_STAT_TOOLONG_ERRORS:
41456b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MTU_ERROR);
41556b2bdd1SGireesh Nagabhushana break;
41656b2bdd1SGireesh Nagabhushana
41756b2bdd1SGireesh Nagabhushana case ETHER_STAT_MACRCV_ERRORS:
41856b2bdd1SGireesh Nagabhushana *val = GET_STAT(RX_PORT_MTU_ERROR) +
41956b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_MTU_CRC_ERROR) +
42056b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_CRC_ERROR) +
42156b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LEN_ERROR) +
42256b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_SYM_ERROR) +
42356b2bdd1SGireesh Nagabhushana GET_STAT(RX_PORT_LESS_64B);
42456b2bdd1SGireesh Nagabhushana break;
42556b2bdd1SGireesh Nagabhushana
42656b2bdd1SGireesh Nagabhushana case ETHER_STAT_XCVR_ADDR:
42756b2bdd1SGireesh Nagabhushana case ETHER_STAT_XCVR_ID:
42856b2bdd1SGireesh Nagabhushana return (ENOTSUP);
429*ece8d794SRobert Mustacchi case ETHER_STAT_XCVR_INUSE:
430*ece8d794SRobert Mustacchi *val = t4_port_to_media(pi);
431*ece8d794SRobert Mustacchi break;
43256b2bdd1SGireesh Nagabhushana
4333dde7c95SVishal Kulkarni case ETHER_STAT_CAP_100GFDX:
4347e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G);
4353dde7c95SVishal Kulkarni break;
4363dde7c95SVishal Kulkarni
4376feac2e3SRahul Lakkireddy case ETHER_STAT_CAP_50GFDX:
4386feac2e3SRahul Lakkireddy *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_50G);
4396feac2e3SRahul Lakkireddy break;
4406feac2e3SRahul Lakkireddy
4413dde7c95SVishal Kulkarni case ETHER_STAT_CAP_40GFDX:
4427e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G);
4433dde7c95SVishal Kulkarni break;
4443dde7c95SVishal Kulkarni
4453dde7c95SVishal Kulkarni case ETHER_STAT_CAP_25GFDX:
4467e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G);
4473dde7c95SVishal Kulkarni break;
4483dde7c95SVishal Kulkarni
4493dde7c95SVishal Kulkarni case ETHER_STAT_CAP_10GFDX:
4507e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G);
4513dde7c95SVishal Kulkarni break;
4523dde7c95SVishal Kulkarni
45356b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_1000FDX:
4547e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G);
45556b2bdd1SGireesh Nagabhushana break;
45656b2bdd1SGireesh Nagabhushana
45756b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_100FDX:
4587e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M);
45956b2bdd1SGireesh Nagabhushana break;
46056b2bdd1SGireesh Nagabhushana
4616feac2e3SRahul Lakkireddy case ETHER_STAT_CAP_1000HDX:
46256b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_100HDX:
46356b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_10FDX:
46456b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_10HDX:
46556b2bdd1SGireesh Nagabhushana return (ENOTSUP);
46656b2bdd1SGireesh Nagabhushana
46756b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_ASMPAUSE:
4686feac2e3SRahul Lakkireddy *val = !!(lc->pcaps & FW_PORT_CAP32_FC_RX);
46956b2bdd1SGireesh Nagabhushana break;
47056b2bdd1SGireesh Nagabhushana
47156b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_PAUSE:
4726feac2e3SRahul Lakkireddy *val = !!(lc->pcaps & FW_PORT_CAP32_FC_TX);
47356b2bdd1SGireesh Nagabhushana break;
47456b2bdd1SGireesh Nagabhushana
47556b2bdd1SGireesh Nagabhushana case ETHER_STAT_CAP_AUTONEG:
4767e6ad469SVishal Kulkarni *val = !!(lc->pcaps & FW_PORT_CAP32_ANEG);
47756b2bdd1SGireesh Nagabhushana break;
47856b2bdd1SGireesh Nagabhushana
47956b2bdd1SGireesh Nagabhushana /*
48056b2bdd1SGireesh Nagabhushana * We have set flow control configuration based on tx_pause and rx_pause
48156b2bdd1SGireesh Nagabhushana * values supported through ndd. Now, we need to translate the settings
48256b2bdd1SGireesh Nagabhushana * we have in link_config structure to adv_cap_asmpause and
48356b2bdd1SGireesh Nagabhushana * adv_cap_pause.
48456b2bdd1SGireesh Nagabhushana *
48556b2bdd1SGireesh Nagabhushana * There are 4 combinations possible and the translation is as below:
48656b2bdd1SGireesh Nagabhushana * tx_pause = 0 => We don't send pause frames during Rx congestion
48756b2bdd1SGireesh Nagabhushana * tx_pause = 1 => We send pause frames during Rx congestion
48856b2bdd1SGireesh Nagabhushana * rx_pause = 0 => We ignore received pause frames
48956b2bdd1SGireesh Nagabhushana * rx_pause = 1 => We pause transmission when we receive pause frames
49056b2bdd1SGireesh Nagabhushana *
49156b2bdd1SGireesh Nagabhushana * +----------------------------+----------------------------------+
49256b2bdd1SGireesh Nagabhushana * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause |
49356b2bdd1SGireesh Nagabhushana * +-------------------------+-------------------------------------+
49456b2bdd1SGireesh Nagabhushana * | 0 | 0 | 0 | 0 |
49556b2bdd1SGireesh Nagabhushana * | 0 | 1 | 1 | 0 |
49656b2bdd1SGireesh Nagabhushana * | 1 | 0 | 1 | 1 |
49756b2bdd1SGireesh Nagabhushana * | 1 | 1 | 0 | 1 |
49856b2bdd1SGireesh Nagabhushana * +----------------------------+----------------------------------+
49956b2bdd1SGireesh Nagabhushana */
50056b2bdd1SGireesh Nagabhushana
50156b2bdd1SGireesh Nagabhushana /* Advertised asymmetric pause capability */
50256b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_ASMPAUSE:
5036feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
5046feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_ASM_DIR);
5056feac2e3SRahul Lakkireddy else
5066feac2e3SRahul Lakkireddy *val = (!!(lc->admin_caps & FW_PORT_CAP32_FC_TX)) ^
5076feac2e3SRahul Lakkireddy (!!(lc->admin_caps & FW_PORT_CAP32_FC_RX));
50856b2bdd1SGireesh Nagabhushana break;
50956b2bdd1SGireesh Nagabhushana
51056b2bdd1SGireesh Nagabhushana /* Advertised pause capability */
51156b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_PAUSE:
5126feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
5136feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_PAUSE);
5146feac2e3SRahul Lakkireddy else
5156feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_FC_TX);
51656b2bdd1SGireesh Nagabhushana break;
51756b2bdd1SGireesh Nagabhushana
5183dde7c95SVishal Kulkarni case ETHER_STAT_ADV_CAP_100GFDX:
5196feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
5206feac2e3SRahul Lakkireddy break;
5216feac2e3SRahul Lakkireddy
5226feac2e3SRahul Lakkireddy case ETHER_STAT_ADV_CAP_50GFDX:
5236feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
5243dde7c95SVishal Kulkarni break;
5253dde7c95SVishal Kulkarni
5263dde7c95SVishal Kulkarni case ETHER_STAT_ADV_CAP_40GFDX:
5276feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
5283dde7c95SVishal Kulkarni break;
5293dde7c95SVishal Kulkarni
5303dde7c95SVishal Kulkarni case ETHER_STAT_ADV_CAP_25GFDX:
5316feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
5323dde7c95SVishal Kulkarni break;
5333dde7c95SVishal Kulkarni
5343dde7c95SVishal Kulkarni case ETHER_STAT_ADV_CAP_10GFDX:
5356feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
5363dde7c95SVishal Kulkarni break;
5373dde7c95SVishal Kulkarni
53856b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_1000FDX:
5396feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
5406feac2e3SRahul Lakkireddy break;
5416feac2e3SRahul Lakkireddy
5426feac2e3SRahul Lakkireddy case ETHER_STAT_ADV_CAP_100FDX:
5436feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
5443dde7c95SVishal Kulkarni break;
5453dde7c95SVishal Kulkarni
5463dde7c95SVishal Kulkarni case ETHER_STAT_ADV_CAP_AUTONEG:
5476feac2e3SRahul Lakkireddy *val = !!(lc->admin_caps & FW_PORT_CAP32_ANEG);
5483dde7c95SVishal Kulkarni break;
5493dde7c95SVishal Kulkarni
55056b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_1000HDX:
55156b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_100HDX:
55256b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_10FDX:
55356b2bdd1SGireesh Nagabhushana case ETHER_STAT_ADV_CAP_10HDX:
55456b2bdd1SGireesh Nagabhushana return (ENOTSUP); /* TODO */
55556b2bdd1SGireesh Nagabhushana
5566feac2e3SRahul Lakkireddy case ETHER_STAT_LP_CAP_ASMPAUSE:
5576feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5586feac2e3SRahul Lakkireddy return (ENOTSUP);
5596feac2e3SRahul Lakkireddy
5606feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
5616feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_ASM_DIR);
5626feac2e3SRahul Lakkireddy else
5636feac2e3SRahul Lakkireddy *val = (!!(lc->lpacaps & FW_PORT_CAP32_FC_TX)) ^
5646feac2e3SRahul Lakkireddy (!!(lc->lpacaps & FW_PORT_CAP32_FC_RX));
5656feac2e3SRahul Lakkireddy break;
5666feac2e3SRahul Lakkireddy
5676feac2e3SRahul Lakkireddy case ETHER_STAT_LP_CAP_PAUSE:
5686feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5696feac2e3SRahul Lakkireddy return (ENOTSUP);
5706feac2e3SRahul Lakkireddy
5716feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
5726feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_PAUSE);
5736feac2e3SRahul Lakkireddy else
5746feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_FC_TX);
5756feac2e3SRahul Lakkireddy break;
5763dde7c95SVishal Kulkarni
5773dde7c95SVishal Kulkarni case ETHER_STAT_LP_CAP_100GFDX:
5786feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5796feac2e3SRahul Lakkireddy return (ENOTSUP);
5806feac2e3SRahul Lakkireddy
5816feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100G);
5826feac2e3SRahul Lakkireddy break;
5836feac2e3SRahul Lakkireddy
5846feac2e3SRahul Lakkireddy case ETHER_STAT_LP_CAP_50GFDX:
5856feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5866feac2e3SRahul Lakkireddy return (ENOTSUP);
5876feac2e3SRahul Lakkireddy
5886feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_50G);
5893dde7c95SVishal Kulkarni break;
5903dde7c95SVishal Kulkarni
5913dde7c95SVishal Kulkarni case ETHER_STAT_LP_CAP_40GFDX:
5926feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
5936feac2e3SRahul Lakkireddy return (ENOTSUP);
5946feac2e3SRahul Lakkireddy
5956feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_40G);
5963dde7c95SVishal Kulkarni break;
5973dde7c95SVishal Kulkarni
5983dde7c95SVishal Kulkarni case ETHER_STAT_LP_CAP_25GFDX:
5996feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6006feac2e3SRahul Lakkireddy return (ENOTSUP);
6016feac2e3SRahul Lakkireddy
6026feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_25G);
6033dde7c95SVishal Kulkarni break;
6043dde7c95SVishal Kulkarni
6053dde7c95SVishal Kulkarni case ETHER_STAT_LP_CAP_10GFDX:
6066feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6076feac2e3SRahul Lakkireddy return (ENOTSUP);
6086feac2e3SRahul Lakkireddy
6096feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_10G);
6103dde7c95SVishal Kulkarni break;
6113dde7c95SVishal Kulkarni
61256b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_1000FDX:
6136feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6146feac2e3SRahul Lakkireddy return (ENOTSUP);
6156feac2e3SRahul Lakkireddy
6166feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_1G);
6176feac2e3SRahul Lakkireddy break;
6186feac2e3SRahul Lakkireddy
6196feac2e3SRahul Lakkireddy case ETHER_STAT_LP_CAP_100FDX:
6206feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6216feac2e3SRahul Lakkireddy return (ENOTSUP);
6226feac2e3SRahul Lakkireddy
6236feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100M);
6243dde7c95SVishal Kulkarni break;
6253dde7c95SVishal Kulkarni
6263dde7c95SVishal Kulkarni case ETHER_STAT_LP_CAP_AUTONEG:
6276feac2e3SRahul Lakkireddy if (!(lc->acaps & FW_PORT_CAP32_ANEG))
6286feac2e3SRahul Lakkireddy return (ENOTSUP);
6296feac2e3SRahul Lakkireddy
6306feac2e3SRahul Lakkireddy *val = !!(lc->lpacaps & FW_PORT_CAP32_ANEG);
6313dde7c95SVishal Kulkarni break;
6323dde7c95SVishal Kulkarni
63356b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_1000HDX:
63456b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_100HDX:
63556b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_10FDX:
63656b2bdd1SGireesh Nagabhushana case ETHER_STAT_LP_CAP_10HDX:
63756b2bdd1SGireesh Nagabhushana return (ENOTSUP);
63856b2bdd1SGireesh Nagabhushana
63956b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_ASMPAUSE:
6406feac2e3SRahul Lakkireddy *val = (!!(lc->link_caps & FW_PORT_CAP32_FC_TX)) ^
6416feac2e3SRahul Lakkireddy (!!(lc->link_caps & FW_PORT_CAP32_FC_RX));
64256b2bdd1SGireesh Nagabhushana break;
64356b2bdd1SGireesh Nagabhushana
64456b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_PAUSE:
6456feac2e3SRahul Lakkireddy *val = !!(lc->link_caps & FW_PORT_CAP32_FC_TX);
64656b2bdd1SGireesh Nagabhushana break;
64756b2bdd1SGireesh Nagabhushana
64856b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_AUTONEG:
6496feac2e3SRahul Lakkireddy *val = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
65056b2bdd1SGireesh Nagabhushana break;
65156b2bdd1SGireesh Nagabhushana
65256b2bdd1SGireesh Nagabhushana case ETHER_STAT_LINK_DUPLEX:
65356b2bdd1SGireesh Nagabhushana if (lc->link_ok != 0)
65456b2bdd1SGireesh Nagabhushana *val = LINK_DUPLEX_FULL;
65556b2bdd1SGireesh Nagabhushana else
65656b2bdd1SGireesh Nagabhushana *val = LINK_DUPLEX_UNKNOWN;
65756b2bdd1SGireesh Nagabhushana break;
65856b2bdd1SGireesh Nagabhushana
65956b2bdd1SGireesh Nagabhushana default:
66056b2bdd1SGireesh Nagabhushana return (ENOTSUP);
66156b2bdd1SGireesh Nagabhushana }
66256b2bdd1SGireesh Nagabhushana #undef GET_STAT
66356b2bdd1SGireesh Nagabhushana
66456b2bdd1SGireesh Nagabhushana return (0);
66556b2bdd1SGireesh Nagabhushana }
66656b2bdd1SGireesh Nagabhushana
66756b2bdd1SGireesh Nagabhushana static int
t4_mc_start(void * arg)66856b2bdd1SGireesh Nagabhushana t4_mc_start(void *arg)
66956b2bdd1SGireesh Nagabhushana {
67056b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
67156b2bdd1SGireesh Nagabhushana int rc;
67256b2bdd1SGireesh Nagabhushana
67356b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 0, 1);
67456b2bdd1SGireesh Nagabhushana if (rc != 0)
67556b2bdd1SGireesh Nagabhushana return (rc);
67656b2bdd1SGireesh Nagabhushana rc = t4_init_synchronized(pi);
67756b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 0);
67856b2bdd1SGireesh Nagabhushana
67956b2bdd1SGireesh Nagabhushana return (rc);
68056b2bdd1SGireesh Nagabhushana }
68156b2bdd1SGireesh Nagabhushana
68256b2bdd1SGireesh Nagabhushana static void
t4_mc_stop(void * arg)68356b2bdd1SGireesh Nagabhushana t4_mc_stop(void *arg)
68456b2bdd1SGireesh Nagabhushana {
68556b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
68656b2bdd1SGireesh Nagabhushana
68756b2bdd1SGireesh Nagabhushana while (begin_synchronized_op(pi, 0, 1) != 0)
68856b2bdd1SGireesh Nagabhushana continue;
68956b2bdd1SGireesh Nagabhushana (void) t4_uninit_synchronized(pi);
69056b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 0);
69156b2bdd1SGireesh Nagabhushana }
69256b2bdd1SGireesh Nagabhushana
69356b2bdd1SGireesh Nagabhushana static int
t4_mc_setpromisc(void * arg,boolean_t on)69456b2bdd1SGireesh Nagabhushana t4_mc_setpromisc(void *arg, boolean_t on)
69556b2bdd1SGireesh Nagabhushana {
69656b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
69756b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
69856b2bdd1SGireesh Nagabhushana int rc;
69956b2bdd1SGireesh Nagabhushana
70056b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
70156b2bdd1SGireesh Nagabhushana if (rc != 0)
70256b2bdd1SGireesh Nagabhushana return (rc);
70356b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1,
70456b2bdd1SGireesh Nagabhushana false);
70556b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
70656b2bdd1SGireesh Nagabhushana
70756b2bdd1SGireesh Nagabhushana return (rc);
70856b2bdd1SGireesh Nagabhushana }
70956b2bdd1SGireesh Nagabhushana
71056b2bdd1SGireesh Nagabhushana /*
71156b2bdd1SGireesh Nagabhushana * TODO: Starts failing as soon as the 336 entry table fills up. Need to use
71256b2bdd1SGireesh Nagabhushana * hash in that case.
71356b2bdd1SGireesh Nagabhushana */
71456b2bdd1SGireesh Nagabhushana static int
t4_mc_multicst(void * arg,boolean_t add,const uint8_t * mcaddr)71556b2bdd1SGireesh Nagabhushana t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr)
71656b2bdd1SGireesh Nagabhushana {
71756b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
71856b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
71956b2bdd1SGireesh Nagabhushana struct fw_vi_mac_cmd c;
72056b2bdd1SGireesh Nagabhushana int len16, rc;
72156b2bdd1SGireesh Nagabhushana
72256b2bdd1SGireesh Nagabhushana len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) +
72356b2bdd1SGireesh Nagabhushana sizeof (c.u.exact[0]), 16);
72456b2bdd1SGireesh Nagabhushana c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST |
72556b2bdd1SGireesh Nagabhushana F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid));
72656b2bdd1SGireesh Nagabhushana c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16));
72756b2bdd1SGireesh Nagabhushana c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID |
72856b2bdd1SGireesh Nagabhushana V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC :
72956b2bdd1SGireesh Nagabhushana FW_VI_MAC_MAC_BASED_FREE));
73056b2bdd1SGireesh Nagabhushana bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL);
73156b2bdd1SGireesh Nagabhushana
73256b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
73356b2bdd1SGireesh Nagabhushana if (rc != 0)
73456b2bdd1SGireesh Nagabhushana return (rc);
73556b2bdd1SGireesh Nagabhushana rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true);
73656b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
73756b2bdd1SGireesh Nagabhushana if (rc != 0)
73856b2bdd1SGireesh Nagabhushana return (rc);
73956b2bdd1SGireesh Nagabhushana #ifdef DEBUG
74056b2bdd1SGireesh Nagabhushana /*
74156b2bdd1SGireesh Nagabhushana * TODO: Firmware doesn't seem to return the correct index on removal
74256b2bdd1SGireesh Nagabhushana * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this
74356b2bdd1SGireesh Nagabhushana * code once it is fixed.
74456b2bdd1SGireesh Nagabhushana */
74556b2bdd1SGireesh Nagabhushana else {
74656b2bdd1SGireesh Nagabhushana uint16_t idx;
74756b2bdd1SGireesh Nagabhushana
74856b2bdd1SGireesh Nagabhushana idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx));
74956b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_NOTE,
75056b2bdd1SGireesh Nagabhushana "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0],
75156b2bdd1SGireesh Nagabhushana mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5],
75256b2bdd1SGireesh Nagabhushana add ? "added at index" : "removed from index", idx);
75356b2bdd1SGireesh Nagabhushana }
75456b2bdd1SGireesh Nagabhushana #endif
75556b2bdd1SGireesh Nagabhushana
75656b2bdd1SGireesh Nagabhushana return (0);
75756b2bdd1SGireesh Nagabhushana }
75856b2bdd1SGireesh Nagabhushana
7593dde7c95SVishal Kulkarni int
t4_mc_unicst(void * arg,const uint8_t * ucaddr)76056b2bdd1SGireesh Nagabhushana t4_mc_unicst(void *arg, const uint8_t *ucaddr)
76156b2bdd1SGireesh Nagabhushana {
76256b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
76356b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
76456b2bdd1SGireesh Nagabhushana int rc;
76556b2bdd1SGireesh Nagabhushana
7663dde7c95SVishal Kulkarni if (ucaddr == NULL)
7673dde7c95SVishal Kulkarni return (EINVAL);
7683dde7c95SVishal Kulkarni
76956b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
77056b2bdd1SGireesh Nagabhushana if (rc != 0)
77156b2bdd1SGireesh Nagabhushana return (rc);
7723dde7c95SVishal Kulkarni
7733dde7c95SVishal Kulkarni /* We will support adding only one mac address */
7743dde7c95SVishal Kulkarni if (pi->adapter->props.multi_rings && pi->macaddr_cnt) {
7753dde7c95SVishal Kulkarni end_synchronized_op(pi, 1);
7763dde7c95SVishal Kulkarni return (ENOSPC);
7773dde7c95SVishal Kulkarni }
77856b2bdd1SGireesh Nagabhushana rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr,
7797e6ad469SVishal Kulkarni true, &pi->smt_idx);
78056b2bdd1SGireesh Nagabhushana if (rc < 0)
78156b2bdd1SGireesh Nagabhushana rc = -rc;
78256b2bdd1SGireesh Nagabhushana else {
7833dde7c95SVishal Kulkarni pi->macaddr_cnt++;
78456b2bdd1SGireesh Nagabhushana pi->xact_addr_filt = rc;
78556b2bdd1SGireesh Nagabhushana rc = 0;
78656b2bdd1SGireesh Nagabhushana }
78756b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
78856b2bdd1SGireesh Nagabhushana
78956b2bdd1SGireesh Nagabhushana return (rc);
79056b2bdd1SGireesh Nagabhushana }
79156b2bdd1SGireesh Nagabhushana
7923dde7c95SVishal Kulkarni int
t4_addmac(void * arg,const uint8_t * ucaddr)7933dde7c95SVishal Kulkarni t4_addmac(void *arg, const uint8_t *ucaddr)
7943dde7c95SVishal Kulkarni {
7953dde7c95SVishal Kulkarni return (t4_mc_unicst(arg, ucaddr));
7963dde7c95SVishal Kulkarni }
7973dde7c95SVishal Kulkarni
7983dde7c95SVishal Kulkarni static int
t4_remmac(void * arg,const uint8_t * mac_addr)7993dde7c95SVishal Kulkarni t4_remmac(void *arg, const uint8_t *mac_addr)
8003dde7c95SVishal Kulkarni {
8013dde7c95SVishal Kulkarni struct port_info *pi = arg;
8023dde7c95SVishal Kulkarni int rc;
8033dde7c95SVishal Kulkarni
8043dde7c95SVishal Kulkarni rc = begin_synchronized_op(pi, 1, 1);
8053dde7c95SVishal Kulkarni if (rc != 0)
8063dde7c95SVishal Kulkarni return (rc);
8073dde7c95SVishal Kulkarni
8083dde7c95SVishal Kulkarni pi->macaddr_cnt--;
8093dde7c95SVishal Kulkarni end_synchronized_op(pi, 1);
8103dde7c95SVishal Kulkarni
8113dde7c95SVishal Kulkarni return (0);
8123dde7c95SVishal Kulkarni }
8133dde7c95SVishal Kulkarni
8143dde7c95SVishal Kulkarni /*
8153dde7c95SVishal Kulkarni * Callback funtion for MAC layer to register all groups.
8163dde7c95SVishal Kulkarni */
8173dde7c95SVishal Kulkarni void
t4_fill_group(void * arg,mac_ring_type_t rtype,const int rg_index,mac_group_info_t * infop,mac_group_handle_t gh)8183dde7c95SVishal Kulkarni t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index,
8193dde7c95SVishal Kulkarni mac_group_info_t *infop, mac_group_handle_t gh)
8203dde7c95SVishal Kulkarni {
8213dde7c95SVishal Kulkarni struct port_info *pi = arg;
8223dde7c95SVishal Kulkarni
8233dde7c95SVishal Kulkarni switch (rtype) {
8243dde7c95SVishal Kulkarni case MAC_RING_TYPE_RX: {
8253dde7c95SVishal Kulkarni infop->mgi_driver = (mac_group_driver_t)arg;
8263dde7c95SVishal Kulkarni infop->mgi_start = NULL;
8273dde7c95SVishal Kulkarni infop->mgi_stop = NULL;
8283dde7c95SVishal Kulkarni infop->mgi_addmac = t4_addmac;
8293dde7c95SVishal Kulkarni infop->mgi_remmac = t4_remmac;
8303dde7c95SVishal Kulkarni infop->mgi_count = pi->nrxq;
8313dde7c95SVishal Kulkarni break;
8323dde7c95SVishal Kulkarni }
8333dde7c95SVishal Kulkarni case MAC_RING_TYPE_TX:
8343dde7c95SVishal Kulkarni default:
8353dde7c95SVishal Kulkarni ASSERT(0);
8363dde7c95SVishal Kulkarni break;
8373dde7c95SVishal Kulkarni }
8383dde7c95SVishal Kulkarni }
8393dde7c95SVishal Kulkarni
8403dde7c95SVishal Kulkarni static int
t4_ring_start(mac_ring_driver_t rh,uint64_t mr_gen_num)8413dde7c95SVishal Kulkarni t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num)
8423dde7c95SVishal Kulkarni {
8433dde7c95SVishal Kulkarni struct sge_rxq *rxq = (struct sge_rxq *)rh;
8443dde7c95SVishal Kulkarni
8453dde7c95SVishal Kulkarni RXQ_LOCK(rxq);
8463dde7c95SVishal Kulkarni rxq->ring_gen_num = mr_gen_num;
8473dde7c95SVishal Kulkarni RXQ_UNLOCK(rxq);
8483dde7c95SVishal Kulkarni return (0);
8493dde7c95SVishal Kulkarni }
8503dde7c95SVishal Kulkarni
8513dde7c95SVishal Kulkarni /*
8523dde7c95SVishal Kulkarni * Enable interrupt on the specificed rx ring.
8533dde7c95SVishal Kulkarni */
8543dde7c95SVishal Kulkarni int
t4_ring_intr_enable(mac_intr_handle_t intrh)8553dde7c95SVishal Kulkarni t4_ring_intr_enable(mac_intr_handle_t intrh)
8563dde7c95SVishal Kulkarni {
8573dde7c95SVishal Kulkarni struct sge_rxq *rxq = (struct sge_rxq *)intrh;
8583dde7c95SVishal Kulkarni struct adapter *sc = rxq->port->adapter;
8593dde7c95SVishal Kulkarni struct sge_iq *iq;
8603dde7c95SVishal Kulkarni
8613dde7c95SVishal Kulkarni iq = &rxq->iq;
8623dde7c95SVishal Kulkarni RXQ_LOCK(rxq);
8633dde7c95SVishal Kulkarni iq->polling = 0;
8643dde7c95SVishal Kulkarni iq->state = IQS_IDLE;
8653dde7c95SVishal Kulkarni t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
8663dde7c95SVishal Kulkarni V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id));
8673dde7c95SVishal Kulkarni RXQ_UNLOCK(rxq);
8683dde7c95SVishal Kulkarni return (0);
8693dde7c95SVishal Kulkarni }
8703dde7c95SVishal Kulkarni
8713dde7c95SVishal Kulkarni /*
8723dde7c95SVishal Kulkarni * Disable interrupt on the specificed rx ring.
8733dde7c95SVishal Kulkarni */
8743dde7c95SVishal Kulkarni int
t4_ring_intr_disable(mac_intr_handle_t intrh)8753dde7c95SVishal Kulkarni t4_ring_intr_disable(mac_intr_handle_t intrh)
8763dde7c95SVishal Kulkarni {
8773dde7c95SVishal Kulkarni struct sge_rxq *rxq = (struct sge_rxq *)intrh;
8783dde7c95SVishal Kulkarni struct sge_iq *iq;
8793dde7c95SVishal Kulkarni
8803dde7c95SVishal Kulkarni /* Nothing to be done here wrt interrupt, as it
8813dde7c95SVishal Kulkarni * will not fire, until we write back to
8823dde7c95SVishal Kulkarni * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable.
8833dde7c95SVishal Kulkarni */
8843dde7c95SVishal Kulkarni
8853dde7c95SVishal Kulkarni iq = &rxq->iq;
8863dde7c95SVishal Kulkarni RXQ_LOCK(rxq);
8873dde7c95SVishal Kulkarni iq->polling = 1;
8883dde7c95SVishal Kulkarni iq->state = IQS_BUSY;
8893dde7c95SVishal Kulkarni RXQ_UNLOCK(rxq);
8903dde7c95SVishal Kulkarni return (0);
8913dde7c95SVishal Kulkarni }
8923dde7c95SVishal Kulkarni
8933dde7c95SVishal Kulkarni mblk_t *
t4_poll_ring(void * arg,int n_bytes)8943dde7c95SVishal Kulkarni t4_poll_ring(void *arg, int n_bytes)
8953dde7c95SVishal Kulkarni {
8963dde7c95SVishal Kulkarni struct sge_rxq *rxq = (struct sge_rxq *)arg;
8973dde7c95SVishal Kulkarni mblk_t *mp = NULL;
8983dde7c95SVishal Kulkarni
8993dde7c95SVishal Kulkarni ASSERT(n_bytes >= 0);
9003dde7c95SVishal Kulkarni if (n_bytes == 0)
9013dde7c95SVishal Kulkarni return (NULL);
9023dde7c95SVishal Kulkarni
9033dde7c95SVishal Kulkarni RXQ_LOCK(rxq);
9043dde7c95SVishal Kulkarni mp = t4_ring_rx(rxq, n_bytes);
9053dde7c95SVishal Kulkarni RXQ_UNLOCK(rxq);
9063dde7c95SVishal Kulkarni
9073dde7c95SVishal Kulkarni return (mp);
9083dde7c95SVishal Kulkarni }
9093dde7c95SVishal Kulkarni
9103dde7c95SVishal Kulkarni /*
9113dde7c95SVishal Kulkarni * Retrieve a value for one of the statistics for a particular rx ring
9123dde7c95SVishal Kulkarni */
9133dde7c95SVishal Kulkarni int
t4_rx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)9143dde7c95SVishal Kulkarni t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
9153dde7c95SVishal Kulkarni {
9163dde7c95SVishal Kulkarni struct sge_rxq *rxq = (struct sge_rxq *)rh;
9173dde7c95SVishal Kulkarni
9183dde7c95SVishal Kulkarni switch (stat) {
9193dde7c95SVishal Kulkarni case MAC_STAT_RBYTES:
9203dde7c95SVishal Kulkarni *val = rxq->rxbytes;
9213dde7c95SVishal Kulkarni break;
9223dde7c95SVishal Kulkarni
9233dde7c95SVishal Kulkarni case MAC_STAT_IPACKETS:
9243dde7c95SVishal Kulkarni *val = rxq->rxpkts;
9253dde7c95SVishal Kulkarni break;
9263dde7c95SVishal Kulkarni
9273dde7c95SVishal Kulkarni default:
9283dde7c95SVishal Kulkarni *val = 0;
9293dde7c95SVishal Kulkarni return (ENOTSUP);
9303dde7c95SVishal Kulkarni }
9313dde7c95SVishal Kulkarni
9323dde7c95SVishal Kulkarni return (0);
9333dde7c95SVishal Kulkarni }
9343dde7c95SVishal Kulkarni
9353dde7c95SVishal Kulkarni /*
9363dde7c95SVishal Kulkarni * Retrieve a value for one of the statistics for a particular tx ring
9373dde7c95SVishal Kulkarni */
9383dde7c95SVishal Kulkarni int
t4_tx_stat(mac_ring_driver_t rh,uint_t stat,uint64_t * val)9393dde7c95SVishal Kulkarni t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val)
9403dde7c95SVishal Kulkarni {
9413dde7c95SVishal Kulkarni struct sge_txq *txq = (struct sge_txq *)rh;
9423dde7c95SVishal Kulkarni
9433dde7c95SVishal Kulkarni switch (stat) {
9443dde7c95SVishal Kulkarni case MAC_STAT_RBYTES:
9453dde7c95SVishal Kulkarni *val = txq->txbytes;
9463dde7c95SVishal Kulkarni break;
9473dde7c95SVishal Kulkarni
9483dde7c95SVishal Kulkarni case MAC_STAT_IPACKETS:
9493dde7c95SVishal Kulkarni *val = txq->txpkts;
9503dde7c95SVishal Kulkarni break;
9513dde7c95SVishal Kulkarni
9523dde7c95SVishal Kulkarni default:
9533dde7c95SVishal Kulkarni *val = 0;
9543dde7c95SVishal Kulkarni return (ENOTSUP);
9553dde7c95SVishal Kulkarni }
9563dde7c95SVishal Kulkarni
9573dde7c95SVishal Kulkarni return (0);
9583dde7c95SVishal Kulkarni }
9593dde7c95SVishal Kulkarni
9603dde7c95SVishal Kulkarni /*
9613dde7c95SVishal Kulkarni * Callback funtion for MAC layer to register all rings
9623dde7c95SVishal Kulkarni * for given ring_group, noted by group_index.
9633dde7c95SVishal Kulkarni * Since we have only one group, ring index becomes
9643dde7c95SVishal Kulkarni * absolute index.
9653dde7c95SVishal Kulkarni */
9663dde7c95SVishal Kulkarni void
t4_fill_ring(void * arg,mac_ring_type_t rtype,const int group_index,const int ring_index,mac_ring_info_t * infop,mac_ring_handle_t rh)9673dde7c95SVishal Kulkarni t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index,
9683dde7c95SVishal Kulkarni const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
9693dde7c95SVishal Kulkarni {
9703dde7c95SVishal Kulkarni struct port_info *pi = arg;
9713dde7c95SVishal Kulkarni mac_intr_t *mintr;
9723dde7c95SVishal Kulkarni
9733dde7c95SVishal Kulkarni switch (rtype) {
9743dde7c95SVishal Kulkarni case MAC_RING_TYPE_RX: {
9753dde7c95SVishal Kulkarni struct sge_rxq *rxq;
9763dde7c95SVishal Kulkarni
9773dde7c95SVishal Kulkarni rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index];
9783dde7c95SVishal Kulkarni rxq->ring_handle = rh;
9793dde7c95SVishal Kulkarni
9803dde7c95SVishal Kulkarni infop->mri_driver = (mac_ring_driver_t)rxq;
9813dde7c95SVishal Kulkarni infop->mri_start = t4_ring_start;
9823dde7c95SVishal Kulkarni infop->mri_stop = NULL;
9833dde7c95SVishal Kulkarni infop->mri_poll = t4_poll_ring;
9843dde7c95SVishal Kulkarni infop->mri_stat = t4_rx_stat;
9853dde7c95SVishal Kulkarni
9863dde7c95SVishal Kulkarni mintr = &infop->mri_intr;
9873dde7c95SVishal Kulkarni mintr->mi_handle = (mac_intr_handle_t)rxq;
9883dde7c95SVishal Kulkarni mintr->mi_enable = t4_ring_intr_enable;
9893dde7c95SVishal Kulkarni mintr->mi_disable = t4_ring_intr_disable;
9903dde7c95SVishal Kulkarni
9913dde7c95SVishal Kulkarni break;
9923dde7c95SVishal Kulkarni }
9933dde7c95SVishal Kulkarni case MAC_RING_TYPE_TX: {
9943dde7c95SVishal Kulkarni struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index];
9953dde7c95SVishal Kulkarni txq->ring_handle = rh;
9963dde7c95SVishal Kulkarni infop->mri_driver = (mac_ring_driver_t)txq;
9973dde7c95SVishal Kulkarni infop->mri_start = NULL;
9983dde7c95SVishal Kulkarni infop->mri_stop = NULL;
9993dde7c95SVishal Kulkarni infop->mri_tx = t4_eth_tx;
10003dde7c95SVishal Kulkarni infop->mri_stat = t4_tx_stat;
10013dde7c95SVishal Kulkarni break;
10023dde7c95SVishal Kulkarni }
10033dde7c95SVishal Kulkarni default:
10043dde7c95SVishal Kulkarni ASSERT(0);
10053dde7c95SVishal Kulkarni break;
10063dde7c95SVishal Kulkarni }
10073dde7c95SVishal Kulkarni }
10083dde7c95SVishal Kulkarni
10093dde7c95SVishal Kulkarni mblk_t *
t4_mc_tx(void * arg,mblk_t * m)101056b2bdd1SGireesh Nagabhushana t4_mc_tx(void *arg, mblk_t *m)
101156b2bdd1SGireesh Nagabhushana {
101256b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
101356b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
101456b2bdd1SGireesh Nagabhushana struct sge_txq *txq = &sc->sge.txq[pi->first_txq];
101556b2bdd1SGireesh Nagabhushana
10163dde7c95SVishal Kulkarni return (t4_eth_tx(txq, m));
101756b2bdd1SGireesh Nagabhushana }
101856b2bdd1SGireesh Nagabhushana
1019017c366dSRobert Mustacchi static int
t4_mc_transceiver_info(void * arg,uint_t id,mac_transceiver_info_t * infop)1020017c366dSRobert Mustacchi t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
1021017c366dSRobert Mustacchi {
1022017c366dSRobert Mustacchi struct port_info *pi = arg;
1023017c366dSRobert Mustacchi
1024017c366dSRobert Mustacchi if (id != 0 || infop == NULL)
1025017c366dSRobert Mustacchi return (EINVAL);
1026017c366dSRobert Mustacchi
1027017c366dSRobert Mustacchi switch (pi->mod_type) {
1028017c366dSRobert Mustacchi case FW_PORT_MOD_TYPE_NONE:
1029017c366dSRobert Mustacchi mac_transceiver_info_set_present(infop, B_FALSE);
1030017c366dSRobert Mustacchi break;
1031017c366dSRobert Mustacchi case FW_PORT_MOD_TYPE_NOTSUPPORTED:
1032017c366dSRobert Mustacchi mac_transceiver_info_set_present(infop, B_TRUE);
1033017c366dSRobert Mustacchi mac_transceiver_info_set_usable(infop, B_FALSE);
1034017c366dSRobert Mustacchi break;
1035017c366dSRobert Mustacchi default:
1036017c366dSRobert Mustacchi mac_transceiver_info_set_present(infop, B_TRUE);
1037017c366dSRobert Mustacchi mac_transceiver_info_set_usable(infop, B_TRUE);
1038017c366dSRobert Mustacchi break;
1039017c366dSRobert Mustacchi }
1040017c366dSRobert Mustacchi
1041017c366dSRobert Mustacchi return (0);
1042017c366dSRobert Mustacchi }
1043017c366dSRobert Mustacchi
1044017c366dSRobert Mustacchi static int
t4_mc_transceiver_read(void * arg,uint_t id,uint_t page,void * bp,size_t nbytes,off_t offset,size_t * nread)1045017c366dSRobert Mustacchi t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
1046017c366dSRobert Mustacchi size_t nbytes, off_t offset, size_t *nread)
1047017c366dSRobert Mustacchi {
1048017c366dSRobert Mustacchi struct port_info *pi = arg;
1049017c366dSRobert Mustacchi struct adapter *sc = pi->adapter;
1050017c366dSRobert Mustacchi int rc;
1051017c366dSRobert Mustacchi size_t i, maxread;
1052017c366dSRobert Mustacchi /* LINTED: E_FUNC_VAR_UNUSED */
1053017c366dSRobert Mustacchi struct fw_ldst_cmd ldst __unused;
1054017c366dSRobert Mustacchi
1055017c366dSRobert Mustacchi if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
1056017c366dSRobert Mustacchi (page != 0xa0 && page != 0xa2) || offset < 0)
1057017c366dSRobert Mustacchi return (EINVAL);
1058017c366dSRobert Mustacchi
1059017c366dSRobert Mustacchi if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256))
1060017c366dSRobert Mustacchi return (EINVAL);
1061017c366dSRobert Mustacchi
1062017c366dSRobert Mustacchi rc = begin_synchronized_op(pi, 0, 1);
1063017c366dSRobert Mustacchi if (rc != 0)
1064017c366dSRobert Mustacchi return (rc);
1065017c366dSRobert Mustacchi
1066017c366dSRobert Mustacchi /*
1067017c366dSRobert Mustacchi * Firmware has a maximum size that we can read. Don't read more than it
1068017c366dSRobert Mustacchi * allows.
1069017c366dSRobert Mustacchi */
1070017c366dSRobert Mustacchi maxread = sizeof (ldst.u.i2c.data);
1071017c366dSRobert Mustacchi for (i = 0; i < nbytes; i += maxread) {
1072017c366dSRobert Mustacchi size_t toread = MIN(maxread, nbytes - i);
1073017c366dSRobert Mustacchi rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread,
1074017c366dSRobert Mustacchi bp);
1075017c366dSRobert Mustacchi if (rc != 0)
1076017c366dSRobert Mustacchi break;
1077017c366dSRobert Mustacchi offset += toread;
1078017c366dSRobert Mustacchi bp = (void *)((uintptr_t)bp + toread);
1079017c366dSRobert Mustacchi }
1080017c366dSRobert Mustacchi end_synchronized_op(pi, 0);
1081017c366dSRobert Mustacchi if (rc == 0)
1082017c366dSRobert Mustacchi *nread = nbytes;
1083017c366dSRobert Mustacchi return (rc);
1084017c366dSRobert Mustacchi }
1085017c366dSRobert Mustacchi
1086d87e4548SVishal Kulkarni static int
t4_port_led_set(void * arg,mac_led_mode_t mode,uint_t flags)1087d87e4548SVishal Kulkarni t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
1088d87e4548SVishal Kulkarni {
1089d87e4548SVishal Kulkarni struct port_info *pi = arg;
1090d87e4548SVishal Kulkarni struct adapter *sc = pi->adapter;
1091d87e4548SVishal Kulkarni int val, rc;
1092d87e4548SVishal Kulkarni
1093d87e4548SVishal Kulkarni if (flags != 0)
1094d87e4548SVishal Kulkarni return (EINVAL);
1095d87e4548SVishal Kulkarni
1096d87e4548SVishal Kulkarni switch (mode) {
1097d87e4548SVishal Kulkarni case MAC_LED_DEFAULT:
1098d87e4548SVishal Kulkarni val = 0;
1099d87e4548SVishal Kulkarni break;
1100d87e4548SVishal Kulkarni case MAC_LED_IDENT:
1101d87e4548SVishal Kulkarni val = 0xffff;
1102d87e4548SVishal Kulkarni break;
1103d87e4548SVishal Kulkarni
1104d87e4548SVishal Kulkarni default:
1105d87e4548SVishal Kulkarni return (ENOTSUP);
1106d87e4548SVishal Kulkarni }
1107d87e4548SVishal Kulkarni
1108d87e4548SVishal Kulkarni rc = begin_synchronized_op(pi, 1, 1);
1109d87e4548SVishal Kulkarni if (rc != 0)
1110d87e4548SVishal Kulkarni return (rc);
1111d87e4548SVishal Kulkarni rc = -t4_identify_port(sc, sc->mbox, pi->viid, val);
1112d87e4548SVishal Kulkarni end_synchronized_op(pi, 1);
1113d87e4548SVishal Kulkarni
1114d87e4548SVishal Kulkarni return (rc);
1115d87e4548SVishal Kulkarni }
1116d87e4548SVishal Kulkarni
111756b2bdd1SGireesh Nagabhushana static boolean_t
t4_mc_getcapab(void * arg,mac_capab_t cap,void * data)111856b2bdd1SGireesh Nagabhushana t4_mc_getcapab(void *arg, mac_capab_t cap, void *data)
111956b2bdd1SGireesh Nagabhushana {
112056b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
112156b2bdd1SGireesh Nagabhushana boolean_t status = B_TRUE;
1122017c366dSRobert Mustacchi mac_capab_transceiver_t *mct;
1123d87e4548SVishal Kulkarni mac_capab_led_t *mcl;
112456b2bdd1SGireesh Nagabhushana
112556b2bdd1SGireesh Nagabhushana switch (cap) {
112656b2bdd1SGireesh Nagabhushana case MAC_CAPAB_HCKSUM:
112756b2bdd1SGireesh Nagabhushana if (pi->features & CXGBE_HW_CSUM) {
112856b2bdd1SGireesh Nagabhushana uint32_t *d = data;
1129d75c6062SRobert Mustacchi *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM |
1130d75c6062SRobert Mustacchi HCKSUM_INET_FULL_V6;
113156b2bdd1SGireesh Nagabhushana } else
113256b2bdd1SGireesh Nagabhushana status = B_FALSE;
113356b2bdd1SGireesh Nagabhushana break;
113456b2bdd1SGireesh Nagabhushana
113556b2bdd1SGireesh Nagabhushana case MAC_CAPAB_LSO:
113656b2bdd1SGireesh Nagabhushana /* Enabling LSO requires Checksum offloading */
113756b2bdd1SGireesh Nagabhushana if (pi->features & CXGBE_HW_LSO &&
113856b2bdd1SGireesh Nagabhushana pi->features & CXGBE_HW_CSUM) {
113956b2bdd1SGireesh Nagabhushana mac_capab_lso_t *d = data;
114056b2bdd1SGireesh Nagabhushana
1141d75c6062SRobert Mustacchi d->lso_flags = LSO_TX_BASIC_TCP_IPV4 |
1142d75c6062SRobert Mustacchi LSO_TX_BASIC_TCP_IPV6;
114356b2bdd1SGireesh Nagabhushana d->lso_basic_tcp_ipv4.lso_max = 65535;
1144d75c6062SRobert Mustacchi d->lso_basic_tcp_ipv6.lso_max = 65535;
114556b2bdd1SGireesh Nagabhushana } else
114656b2bdd1SGireesh Nagabhushana status = B_FALSE;
114756b2bdd1SGireesh Nagabhushana break;
114856b2bdd1SGireesh Nagabhushana
11493dde7c95SVishal Kulkarni case MAC_CAPAB_RINGS: {
11503dde7c95SVishal Kulkarni mac_capab_rings_t *cap_rings = data;
11513dde7c95SVishal Kulkarni
11523dde7c95SVishal Kulkarni if (!pi->adapter->props.multi_rings) {
11533dde7c95SVishal Kulkarni status = B_FALSE;
11543dde7c95SVishal Kulkarni break;
11553dde7c95SVishal Kulkarni }
11563dde7c95SVishal Kulkarni switch (cap_rings->mr_type) {
11573dde7c95SVishal Kulkarni case MAC_RING_TYPE_RX:
11583dde7c95SVishal Kulkarni cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
11593dde7c95SVishal Kulkarni cap_rings->mr_rnum = pi->nrxq;
11603dde7c95SVishal Kulkarni cap_rings->mr_gnum = 1;
11613dde7c95SVishal Kulkarni cap_rings->mr_rget = t4_fill_ring;
11623dde7c95SVishal Kulkarni cap_rings->mr_gget = t4_fill_group;
11633dde7c95SVishal Kulkarni cap_rings->mr_gaddring = NULL;
11643dde7c95SVishal Kulkarni cap_rings->mr_gremring = NULL;
11653dde7c95SVishal Kulkarni break;
11663dde7c95SVishal Kulkarni case MAC_RING_TYPE_TX:
11673dde7c95SVishal Kulkarni cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
11683dde7c95SVishal Kulkarni cap_rings->mr_rnum = pi->ntxq;
11693dde7c95SVishal Kulkarni cap_rings->mr_gnum = 0;
11703dde7c95SVishal Kulkarni cap_rings->mr_rget = t4_fill_ring;
11713dde7c95SVishal Kulkarni cap_rings->mr_gget = NULL;
11723dde7c95SVishal Kulkarni break;
11733dde7c95SVishal Kulkarni }
11743dde7c95SVishal Kulkarni break;
11753dde7c95SVishal Kulkarni }
1176017c366dSRobert Mustacchi
1177017c366dSRobert Mustacchi case MAC_CAPAB_TRANSCEIVER:
1178017c366dSRobert Mustacchi mct = data;
1179017c366dSRobert Mustacchi
1180017c366dSRobert Mustacchi mct->mct_flags = 0;
1181017c366dSRobert Mustacchi mct->mct_ntransceivers = 1;
1182017c366dSRobert Mustacchi mct->mct_info = t4_mc_transceiver_info;
1183017c366dSRobert Mustacchi mct->mct_read = t4_mc_transceiver_read;
1184017c366dSRobert Mustacchi break;
1185d87e4548SVishal Kulkarni case MAC_CAPAB_LED:
1186d87e4548SVishal Kulkarni mcl = data;
1187d87e4548SVishal Kulkarni mcl->mcl_flags = 0;
1188d87e4548SVishal Kulkarni mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT;
1189d87e4548SVishal Kulkarni mcl->mcl_set = t4_port_led_set;
1190d87e4548SVishal Kulkarni break;
1191017c366dSRobert Mustacchi
119256b2bdd1SGireesh Nagabhushana default:
119356b2bdd1SGireesh Nagabhushana status = B_FALSE; /* cap not supported */
119456b2bdd1SGireesh Nagabhushana }
119556b2bdd1SGireesh Nagabhushana
119656b2bdd1SGireesh Nagabhushana return (status);
119756b2bdd1SGireesh Nagabhushana }
119856b2bdd1SGireesh Nagabhushana
t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,link_flowctrl_t * fc)11996feac2e3SRahul Lakkireddy static void t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps,
12006feac2e3SRahul Lakkireddy link_flowctrl_t *fc)
1201d77e6e0fSPaul Winder {
12026feac2e3SRahul Lakkireddy u8 pause_tx = 0, pause_rx = 0;
1203d77e6e0fSPaul Winder
12046feac2e3SRahul Lakkireddy if (caps & FW_PORT_CAP32_FC_TX)
12056feac2e3SRahul Lakkireddy pause_tx = 1;
1206d77e6e0fSPaul Winder
12076feac2e3SRahul Lakkireddy if (caps & FW_PORT_CAP32_FC_RX)
12086feac2e3SRahul Lakkireddy pause_rx = 1;
12096feac2e3SRahul Lakkireddy
12106feac2e3SRahul Lakkireddy if (pause_rx & pause_tx)
12116feac2e3SRahul Lakkireddy *fc = LINK_FLOWCTRL_BI;
12126feac2e3SRahul Lakkireddy else if (pause_tx)
12136feac2e3SRahul Lakkireddy *fc = LINK_FLOWCTRL_TX;
12146feac2e3SRahul Lakkireddy else if (pause_rx)
12156feac2e3SRahul Lakkireddy *fc = LINK_FLOWCTRL_RX;
12166feac2e3SRahul Lakkireddy else
12176feac2e3SRahul Lakkireddy *fc = LINK_FLOWCTRL_NONE;
12186feac2e3SRahul Lakkireddy }
12196feac2e3SRahul Lakkireddy
t4_mac_flowctrl_to_link_caps(struct port_info * pi,link_flowctrl_t fc,fw_port_cap32_t * new_caps)12206feac2e3SRahul Lakkireddy static int t4_mac_flowctrl_to_link_caps(struct port_info *pi,
12216feac2e3SRahul Lakkireddy link_flowctrl_t fc,
12226feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
12236feac2e3SRahul Lakkireddy {
12246feac2e3SRahul Lakkireddy cc_pause_t pause = 0;
12256feac2e3SRahul Lakkireddy
12266feac2e3SRahul Lakkireddy switch (fc) {
12276feac2e3SRahul Lakkireddy case LINK_FLOWCTRL_BI:
12286feac2e3SRahul Lakkireddy pause |= PAUSE_TX | PAUSE_RX;
12296feac2e3SRahul Lakkireddy break;
12306feac2e3SRahul Lakkireddy case LINK_FLOWCTRL_TX:
12316feac2e3SRahul Lakkireddy pause |= PAUSE_TX;
12326feac2e3SRahul Lakkireddy break;
12336feac2e3SRahul Lakkireddy case LINK_FLOWCTRL_RX:
12346feac2e3SRahul Lakkireddy pause |= PAUSE_RX;
12356feac2e3SRahul Lakkireddy break;
12366feac2e3SRahul Lakkireddy default:
12376feac2e3SRahul Lakkireddy break;
12386feac2e3SRahul Lakkireddy }
12396feac2e3SRahul Lakkireddy
12406feac2e3SRahul Lakkireddy if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG)
12416feac2e3SRahul Lakkireddy pause |= PAUSE_AUTONEG;
1242d77e6e0fSPaul Winder
12436feac2e3SRahul Lakkireddy return t4_link_set_pause(pi, pause, new_caps);
12446feac2e3SRahul Lakkireddy }
1245d77e6e0fSPaul Winder
t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)12466feac2e3SRahul Lakkireddy static link_fec_t t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps)
12476feac2e3SRahul Lakkireddy {
12486feac2e3SRahul Lakkireddy link_fec_t link_fec = 0;
12496feac2e3SRahul Lakkireddy
12506feac2e3SRahul Lakkireddy if (caps & FW_PORT_CAP32_FEC_RS)
1251d77e6e0fSPaul Winder link_fec |= LINK_FEC_RS;
1252d77e6e0fSPaul Winder
12536feac2e3SRahul Lakkireddy if (caps & FW_PORT_CAP32_FEC_BASER_RS)
1254d77e6e0fSPaul Winder link_fec |= LINK_FEC_BASE_R;
1255d77e6e0fSPaul Winder
12566feac2e3SRahul Lakkireddy if (caps & FW_PORT_CAP32_FEC_NO_FEC)
12576feac2e3SRahul Lakkireddy link_fec |= LINK_FEC_NONE;
12586feac2e3SRahul Lakkireddy
12596feac2e3SRahul Lakkireddy if ((link_fec & (link_fec - 1)) &&
12606feac2e3SRahul Lakkireddy !(caps & FW_PORT_CAP32_FORCE_FEC))
12616feac2e3SRahul Lakkireddy return LINK_FEC_AUTO;
12626feac2e3SRahul Lakkireddy
12636feac2e3SRahul Lakkireddy return link_fec;
1264d77e6e0fSPaul Winder }
1265d77e6e0fSPaul Winder
t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)12666feac2e3SRahul Lakkireddy static void t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps,
12676feac2e3SRahul Lakkireddy link_fec_t *fec)
12686feac2e3SRahul Lakkireddy {
12696feac2e3SRahul Lakkireddy *fec = t4_mac_port_caps_to_fec_cap(caps);
12706feac2e3SRahul Lakkireddy }
12716feac2e3SRahul Lakkireddy
t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,link_fec_t * fec)12726feac2e3SRahul Lakkireddy static void t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps,
12736feac2e3SRahul Lakkireddy link_fec_t *fec)
1274d77e6e0fSPaul Winder {
12756feac2e3SRahul Lakkireddy link_fec_t link_fec;
1276d77e6e0fSPaul Winder
12776feac2e3SRahul Lakkireddy caps &= ~FW_PORT_CAP32_FEC_NO_FEC;
12786feac2e3SRahul Lakkireddy link_fec = t4_mac_port_caps_to_fec_cap(caps);
12796feac2e3SRahul Lakkireddy *fec = link_fec ? link_fec : LINK_FEC_NONE;
12806feac2e3SRahul Lakkireddy }
12816feac2e3SRahul Lakkireddy
t4_mac_fec_cap_to_link_caps(struct port_info * pi,link_fec_t v,fw_port_cap32_t * new_caps)12826feac2e3SRahul Lakkireddy static int t4_mac_fec_cap_to_link_caps(struct port_info *pi, link_fec_t v,
12836feac2e3SRahul Lakkireddy fw_port_cap32_t *new_caps)
12846feac2e3SRahul Lakkireddy {
12856feac2e3SRahul Lakkireddy cc_fec_t fec = 0;
12866feac2e3SRahul Lakkireddy
12876feac2e3SRahul Lakkireddy if (v == LINK_FEC_AUTO) {
1288d77e6e0fSPaul Winder fec = FEC_AUTO;
12896feac2e3SRahul Lakkireddy goto out;
12906feac2e3SRahul Lakkireddy }
1291d77e6e0fSPaul Winder
12926feac2e3SRahul Lakkireddy if (v & LINK_FEC_NONE) {
12936feac2e3SRahul Lakkireddy v &= ~LINK_FEC_NONE;
12946feac2e3SRahul Lakkireddy fec |= FEC_NONE;
12956feac2e3SRahul Lakkireddy }
1296d77e6e0fSPaul Winder
12976feac2e3SRahul Lakkireddy if (v & LINK_FEC_RS) {
12986feac2e3SRahul Lakkireddy v &= ~LINK_FEC_RS;
12996feac2e3SRahul Lakkireddy fec |= FEC_RS;
13006feac2e3SRahul Lakkireddy }
13016feac2e3SRahul Lakkireddy
13026feac2e3SRahul Lakkireddy if (v & LINK_FEC_BASE_R) {
13036feac2e3SRahul Lakkireddy v &= ~LINK_FEC_BASE_R;
13046feac2e3SRahul Lakkireddy fec |= FEC_BASER_RS;
1305d77e6e0fSPaul Winder }
1306d77e6e0fSPaul Winder
1307d77e6e0fSPaul Winder if (v != 0)
1308d77e6e0fSPaul Winder return (-1);
1309d77e6e0fSPaul Winder
1310d77e6e0fSPaul Winder ASSERT3S(fec, !=, 0);
1311d77e6e0fSPaul Winder
13126feac2e3SRahul Lakkireddy fec |= FEC_FORCE;
13136feac2e3SRahul Lakkireddy
13146feac2e3SRahul Lakkireddy out:
13156feac2e3SRahul Lakkireddy return t4_link_set_fec(pi, fec, new_caps);
1316d77e6e0fSPaul Winder }
1317d77e6e0fSPaul Winder
131856b2bdd1SGireesh Nagabhushana /* ARGSUSED */
131956b2bdd1SGireesh Nagabhushana static int
t4_mc_setprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,const void * val)132056b2bdd1SGireesh Nagabhushana t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
132156b2bdd1SGireesh Nagabhushana const void *val)
132256b2bdd1SGireesh Nagabhushana {
132356b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
132456b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
13256feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
13266feac2e3SRahul Lakkireddy fw_port_cap32_t new_caps = lc->admin_caps;
13276feac2e3SRahul Lakkireddy int relink = 0, rx_mode = 0, rc = 0;
132856b2bdd1SGireesh Nagabhushana uint32_t v32 = *(uint32_t *)val;
13296feac2e3SRahul Lakkireddy uint8_t v8 = *(uint8_t *)val;
133056b2bdd1SGireesh Nagabhushana link_flowctrl_t fc;
1331d77e6e0fSPaul Winder link_fec_t fec;
133256b2bdd1SGireesh Nagabhushana
133356b2bdd1SGireesh Nagabhushana switch (id) {
133456b2bdd1SGireesh Nagabhushana case MAC_PROP_AUTONEG:
13356feac2e3SRahul Lakkireddy rc = t4_link_set_autoneg(pi, v8, &new_caps);
13366feac2e3SRahul Lakkireddy relink = 1;
133756b2bdd1SGireesh Nagabhushana break;
133856b2bdd1SGireesh Nagabhushana
133956b2bdd1SGireesh Nagabhushana case MAC_PROP_MTU:
134056b2bdd1SGireesh Nagabhushana if (v32 < 46 || v32 > MAX_MTU) {
134156b2bdd1SGireesh Nagabhushana rc = EINVAL;
134256b2bdd1SGireesh Nagabhushana } else if (v32 != pi->mtu) {
134356b2bdd1SGireesh Nagabhushana pi->mtu = v32;
134456b2bdd1SGireesh Nagabhushana (void) mac_maxsdu_update(pi->mh, v32);
134556b2bdd1SGireesh Nagabhushana rx_mode = 1;
134656b2bdd1SGireesh Nagabhushana }
134756b2bdd1SGireesh Nagabhushana
134856b2bdd1SGireesh Nagabhushana break;
134956b2bdd1SGireesh Nagabhushana
135056b2bdd1SGireesh Nagabhushana case MAC_PROP_FLOWCTRL:
135156b2bdd1SGireesh Nagabhushana fc = *(link_flowctrl_t *)val;
13526feac2e3SRahul Lakkireddy rc = t4_mac_flowctrl_to_link_caps(pi, fc, &new_caps);
13536feac2e3SRahul Lakkireddy relink = 1;
135456b2bdd1SGireesh Nagabhushana break;
135556b2bdd1SGireesh Nagabhushana
1356d77e6e0fSPaul Winder case MAC_PROP_EN_FEC_CAP:
1357d77e6e0fSPaul Winder fec = *(link_fec_t *)val;
13586feac2e3SRahul Lakkireddy rc = t4_mac_fec_cap_to_link_caps(pi, fec, &new_caps);
13596feac2e3SRahul Lakkireddy relink = 1;
1360d77e6e0fSPaul Winder break;
1361d77e6e0fSPaul Winder
13626feac2e3SRahul Lakkireddy case MAC_PROP_EN_100GFDX_CAP:
13636feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100G, v8,
13646feac2e3SRahul Lakkireddy &new_caps);
13656feac2e3SRahul Lakkireddy relink = 1;
13666feac2e3SRahul Lakkireddy break;
136756b2bdd1SGireesh Nagabhushana
13686feac2e3SRahul Lakkireddy case MAC_PROP_EN_50GFDX_CAP:
13696feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_50G, v8,
13706feac2e3SRahul Lakkireddy &new_caps);
13716feac2e3SRahul Lakkireddy relink = 1;
13726feac2e3SRahul Lakkireddy break;
13736feac2e3SRahul Lakkireddy
13746feac2e3SRahul Lakkireddy case MAC_PROP_EN_40GFDX_CAP:
13756feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_40G, v8,
13766feac2e3SRahul Lakkireddy &new_caps);
13776feac2e3SRahul Lakkireddy relink = 1;
13786feac2e3SRahul Lakkireddy break;
13796feac2e3SRahul Lakkireddy
13806feac2e3SRahul Lakkireddy case MAC_PROP_EN_25GFDX_CAP:
13816feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_25G, v8,
13826feac2e3SRahul Lakkireddy &new_caps);
13836feac2e3SRahul Lakkireddy relink = 1;
13846feac2e3SRahul Lakkireddy break;
13856feac2e3SRahul Lakkireddy
13866feac2e3SRahul Lakkireddy case MAC_PROP_EN_10GFDX_CAP:
13876feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_10G, v8,
13886feac2e3SRahul Lakkireddy &new_caps);
13896feac2e3SRahul Lakkireddy relink = 1;
139056b2bdd1SGireesh Nagabhushana break;
139156b2bdd1SGireesh Nagabhushana
139256b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_1000FDX_CAP:
13936feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_1G, v8,
13946feac2e3SRahul Lakkireddy &new_caps);
13956feac2e3SRahul Lakkireddy relink = 1;
139656b2bdd1SGireesh Nagabhushana break;
139756b2bdd1SGireesh Nagabhushana
139856b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_100FDX_CAP:
13996feac2e3SRahul Lakkireddy rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100M, v8,
14006feac2e3SRahul Lakkireddy &new_caps);
14016feac2e3SRahul Lakkireddy relink = 1;
140256b2bdd1SGireesh Nagabhushana break;
140356b2bdd1SGireesh Nagabhushana
140456b2bdd1SGireesh Nagabhushana case MAC_PROP_PRIVATE:
140556b2bdd1SGireesh Nagabhushana rc = setprop(pi, name, val);
140656b2bdd1SGireesh Nagabhushana break;
140756b2bdd1SGireesh Nagabhushana
140856b2bdd1SGireesh Nagabhushana default:
140956b2bdd1SGireesh Nagabhushana rc = ENOTSUP;
14106feac2e3SRahul Lakkireddy break;
141156b2bdd1SGireesh Nagabhushana }
141256b2bdd1SGireesh Nagabhushana
14136feac2e3SRahul Lakkireddy if (rc != 0)
14146feac2e3SRahul Lakkireddy return (rc);
14156feac2e3SRahul Lakkireddy
141656b2bdd1SGireesh Nagabhushana if (isset(&sc->open_device_map, pi->port_id) != 0) {
141756b2bdd1SGireesh Nagabhushana if (relink != 0) {
141856b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
141956b2bdd1SGireesh Nagabhushana if (rc != 0)
142056b2bdd1SGireesh Nagabhushana return (rc);
14216feac2e3SRahul Lakkireddy rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
14226feac2e3SRahul Lakkireddy new_caps);
142356b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
142456b2bdd1SGireesh Nagabhushana if (rc != 0) {
142556b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN,
14266feac2e3SRahul Lakkireddy "%s link config failed: %d",
14276feac2e3SRahul Lakkireddy __func__, rc);
14286feac2e3SRahul Lakkireddy return (rc);
142956b2bdd1SGireesh Nagabhushana }
143056b2bdd1SGireesh Nagabhushana }
143156b2bdd1SGireesh Nagabhushana
143256b2bdd1SGireesh Nagabhushana if (rx_mode != 0) {
143356b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
143456b2bdd1SGireesh Nagabhushana if (rc != 0)
143556b2bdd1SGireesh Nagabhushana return (rc);
143656b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1,
143756b2bdd1SGireesh Nagabhushana -1, -1, -1, false);
143856b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
143956b2bdd1SGireesh Nagabhushana if (rc != 0) {
144056b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN,
144156b2bdd1SGireesh Nagabhushana "set_rxmode failed: %d", rc);
14426feac2e3SRahul Lakkireddy return (rc);
144356b2bdd1SGireesh Nagabhushana }
144456b2bdd1SGireesh Nagabhushana }
144556b2bdd1SGireesh Nagabhushana }
144656b2bdd1SGireesh Nagabhushana
14476feac2e3SRahul Lakkireddy if (relink != 0)
14486feac2e3SRahul Lakkireddy lc->admin_caps = new_caps;
14496feac2e3SRahul Lakkireddy
14506feac2e3SRahul Lakkireddy return (0);
145156b2bdd1SGireesh Nagabhushana }
145256b2bdd1SGireesh Nagabhushana
145356b2bdd1SGireesh Nagabhushana static int
t4_mc_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,void * val)145456b2bdd1SGireesh Nagabhushana t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size,
145556b2bdd1SGireesh Nagabhushana void *val)
145656b2bdd1SGireesh Nagabhushana {
145756b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
145856b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg;
145956b2bdd1SGireesh Nagabhushana uint8_t *u = val;
14606feac2e3SRahul Lakkireddy int rc = 0;
146156b2bdd1SGireesh Nagabhushana
146256b2bdd1SGireesh Nagabhushana switch (id) {
146356b2bdd1SGireesh Nagabhushana case MAC_PROP_DUPLEX:
146456b2bdd1SGireesh Nagabhushana *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL :
146556b2bdd1SGireesh Nagabhushana LINK_DUPLEX_UNKNOWN;
146656b2bdd1SGireesh Nagabhushana break;
146756b2bdd1SGireesh Nagabhushana
146856b2bdd1SGireesh Nagabhushana case MAC_PROP_SPEED:
146956b2bdd1SGireesh Nagabhushana if (lc->link_ok != 0) {
14706feac2e3SRahul Lakkireddy *(uint64_t *)val = t4_link_fwcap_to_speed(lc->link_caps);
147156b2bdd1SGireesh Nagabhushana *(uint64_t *)val *= 1000000;
14726feac2e3SRahul Lakkireddy } else {
147356b2bdd1SGireesh Nagabhushana *(uint64_t *)val = 0;
14746feac2e3SRahul Lakkireddy }
147556b2bdd1SGireesh Nagabhushana break;
147656b2bdd1SGireesh Nagabhushana
147756b2bdd1SGireesh Nagabhushana case MAC_PROP_STATUS:
147856b2bdd1SGireesh Nagabhushana *(link_state_t *)val = lc->link_ok ? LINK_STATE_UP :
147956b2bdd1SGireesh Nagabhushana LINK_STATE_DOWN;
148056b2bdd1SGireesh Nagabhushana break;
148156b2bdd1SGireesh Nagabhushana
1482*ece8d794SRobert Mustacchi case MAC_PROP_MEDIA:
1483*ece8d794SRobert Mustacchi *(mac_ether_media_t *)val = t4_port_to_media(pi);
1484*ece8d794SRobert Mustacchi break;
1485*ece8d794SRobert Mustacchi
148656b2bdd1SGireesh Nagabhushana case MAC_PROP_AUTONEG:
14876feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_ANEG);
148856b2bdd1SGireesh Nagabhushana break;
148956b2bdd1SGireesh Nagabhushana
149056b2bdd1SGireesh Nagabhushana case MAC_PROP_MTU:
149156b2bdd1SGireesh Nagabhushana *(uint32_t *)val = pi->mtu;
149256b2bdd1SGireesh Nagabhushana break;
149356b2bdd1SGireesh Nagabhushana
149456b2bdd1SGireesh Nagabhushana case MAC_PROP_FLOWCTRL:
14956feac2e3SRahul Lakkireddy t4_mac_link_caps_to_flowctrl(lc->link_caps, val);
149656b2bdd1SGireesh Nagabhushana break;
149756b2bdd1SGireesh Nagabhushana
1498d77e6e0fSPaul Winder case MAC_PROP_ADV_FEC_CAP:
14996feac2e3SRahul Lakkireddy t4_mac_link_caps_to_fec_cap(lc->link_caps, val);
1500d77e6e0fSPaul Winder break;
1501d77e6e0fSPaul Winder
1502d77e6e0fSPaul Winder case MAC_PROP_EN_FEC_CAP:
15036feac2e3SRahul Lakkireddy t4_mac_admin_caps_to_fec_cap(lc->admin_caps, val);
1504d77e6e0fSPaul Winder break;
1505d77e6e0fSPaul Winder
15063dde7c95SVishal Kulkarni case MAC_PROP_ADV_100GFDX_CAP:
15076feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100G);
15086feac2e3SRahul Lakkireddy break;
15096feac2e3SRahul Lakkireddy
15103dde7c95SVishal Kulkarni case MAC_PROP_EN_100GFDX_CAP:
15116feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G);
15126feac2e3SRahul Lakkireddy break;
15136feac2e3SRahul Lakkireddy
15146feac2e3SRahul Lakkireddy case MAC_PROP_ADV_50GFDX_CAP:
15156feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_50G);
15166feac2e3SRahul Lakkireddy break;
15176feac2e3SRahul Lakkireddy
15186feac2e3SRahul Lakkireddy case MAC_PROP_EN_50GFDX_CAP:
15196feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G);
15203dde7c95SVishal Kulkarni break;
15213dde7c95SVishal Kulkarni
15223dde7c95SVishal Kulkarni case MAC_PROP_ADV_40GFDX_CAP:
15236feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_40G);
15246feac2e3SRahul Lakkireddy break;
15256feac2e3SRahul Lakkireddy
15263dde7c95SVishal Kulkarni case MAC_PROP_EN_40GFDX_CAP:
15276feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G);
15283dde7c95SVishal Kulkarni break;
15293dde7c95SVishal Kulkarni
15303dde7c95SVishal Kulkarni case MAC_PROP_ADV_25GFDX_CAP:
15316feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_25G);
15326feac2e3SRahul Lakkireddy break;
15336feac2e3SRahul Lakkireddy
15343dde7c95SVishal Kulkarni case MAC_PROP_EN_25GFDX_CAP:
15356feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G);
15363dde7c95SVishal Kulkarni break;
15373dde7c95SVishal Kulkarni
153856b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_10GFDX_CAP:
15396feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_10G);
15406feac2e3SRahul Lakkireddy break;
15416feac2e3SRahul Lakkireddy
154256b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_10GFDX_CAP:
15436feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G);
154456b2bdd1SGireesh Nagabhushana break;
154556b2bdd1SGireesh Nagabhushana
154656b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_1000FDX_CAP:
15476feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_1G);
15486feac2e3SRahul Lakkireddy break;
15496feac2e3SRahul Lakkireddy
155056b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_1000FDX_CAP:
15516feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G);
155256b2bdd1SGireesh Nagabhushana break;
155356b2bdd1SGireesh Nagabhushana
155456b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_100FDX_CAP:
15556feac2e3SRahul Lakkireddy *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100M);
15566feac2e3SRahul Lakkireddy break;
15576feac2e3SRahul Lakkireddy
155856b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_100FDX_CAP:
15596feac2e3SRahul Lakkireddy *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M);
156056b2bdd1SGireesh Nagabhushana break;
156156b2bdd1SGireesh Nagabhushana
156256b2bdd1SGireesh Nagabhushana case MAC_PROP_PRIVATE:
156356b2bdd1SGireesh Nagabhushana return (getprop(pi, name, size, val));
156456b2bdd1SGireesh Nagabhushana
156556b2bdd1SGireesh Nagabhushana default:
156656b2bdd1SGireesh Nagabhushana return (ENOTSUP);
156756b2bdd1SGireesh Nagabhushana }
156856b2bdd1SGireesh Nagabhushana
15696feac2e3SRahul Lakkireddy return (rc);
157056b2bdd1SGireesh Nagabhushana }
157156b2bdd1SGireesh Nagabhushana
157256b2bdd1SGireesh Nagabhushana static void
t4_mc_propinfo(void * arg,const char * name,mac_prop_id_t id,mac_prop_info_handle_t ph)157356b2bdd1SGireesh Nagabhushana t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id,
157456b2bdd1SGireesh Nagabhushana mac_prop_info_handle_t ph)
157556b2bdd1SGireesh Nagabhushana {
157656b2bdd1SGireesh Nagabhushana struct port_info *pi = arg;
157756b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg;
157856b2bdd1SGireesh Nagabhushana
157956b2bdd1SGireesh Nagabhushana switch (id) {
158056b2bdd1SGireesh Nagabhushana case MAC_PROP_DUPLEX:
158156b2bdd1SGireesh Nagabhushana case MAC_PROP_SPEED:
158256b2bdd1SGireesh Nagabhushana case MAC_PROP_STATUS:
158356b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
158456b2bdd1SGireesh Nagabhushana break;
158556b2bdd1SGireesh Nagabhushana
158656b2bdd1SGireesh Nagabhushana case MAC_PROP_AUTONEG:
15877e6ad469SVishal Kulkarni if (lc->pcaps & FW_PORT_CAP32_ANEG)
158856b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1);
158956b2bdd1SGireesh Nagabhushana else
159056b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
159156b2bdd1SGireesh Nagabhushana break;
159256b2bdd1SGireesh Nagabhushana
159356b2bdd1SGireesh Nagabhushana case MAC_PROP_MTU:
159456b2bdd1SGireesh Nagabhushana mac_prop_info_set_range_uint32(ph, 46, MAX_MTU);
159556b2bdd1SGireesh Nagabhushana break;
159656b2bdd1SGireesh Nagabhushana
159756b2bdd1SGireesh Nagabhushana case MAC_PROP_FLOWCTRL:
159856b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI);
159956b2bdd1SGireesh Nagabhushana break;
160056b2bdd1SGireesh Nagabhushana
1601d77e6e0fSPaul Winder case MAC_PROP_EN_FEC_CAP:
1602d77e6e0fSPaul Winder mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1603d77e6e0fSPaul Winder break;
1604d77e6e0fSPaul Winder
1605d77e6e0fSPaul Winder case MAC_PROP_ADV_FEC_CAP:
1606d77e6e0fSPaul Winder mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
1607d77e6e0fSPaul Winder mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO);
1608d77e6e0fSPaul Winder break;
1609d77e6e0fSPaul Winder
16106feac2e3SRahul Lakkireddy case MAC_PROP_EN_100GFDX_CAP:
16116feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_100G)
16126feac2e3SRahul Lakkireddy mac_prop_info_set_default_uint8(ph, 1);
16136feac2e3SRahul Lakkireddy else
16146feac2e3SRahul Lakkireddy mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16156feac2e3SRahul Lakkireddy break;
16166feac2e3SRahul Lakkireddy
16176feac2e3SRahul Lakkireddy case MAC_PROP_EN_50GFDX_CAP:
16186feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_50G)
16196feac2e3SRahul Lakkireddy mac_prop_info_set_default_uint8(ph, 1);
16206feac2e3SRahul Lakkireddy else
16216feac2e3SRahul Lakkireddy mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16226feac2e3SRahul Lakkireddy break;
16236feac2e3SRahul Lakkireddy
16246feac2e3SRahul Lakkireddy case MAC_PROP_EN_40GFDX_CAP:
16256feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_40G)
16266feac2e3SRahul Lakkireddy mac_prop_info_set_default_uint8(ph, 1);
16276feac2e3SRahul Lakkireddy else
16286feac2e3SRahul Lakkireddy mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16296feac2e3SRahul Lakkireddy break;
16306feac2e3SRahul Lakkireddy
16316feac2e3SRahul Lakkireddy case MAC_PROP_EN_25GFDX_CAP:
16326feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_25G)
16336feac2e3SRahul Lakkireddy mac_prop_info_set_default_uint8(ph, 1);
16346feac2e3SRahul Lakkireddy else
16356feac2e3SRahul Lakkireddy mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
16366feac2e3SRahul Lakkireddy break;
16376feac2e3SRahul Lakkireddy
163856b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_10GFDX_CAP:
16396feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_10G)
164056b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1);
164156b2bdd1SGireesh Nagabhushana else
164256b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
164356b2bdd1SGireesh Nagabhushana break;
164456b2bdd1SGireesh Nagabhushana
164556b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_1000FDX_CAP:
16466feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_1G)
164756b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1);
164856b2bdd1SGireesh Nagabhushana else
164956b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
165056b2bdd1SGireesh Nagabhushana break;
165156b2bdd1SGireesh Nagabhushana
165256b2bdd1SGireesh Nagabhushana case MAC_PROP_EN_100FDX_CAP:
16536feac2e3SRahul Lakkireddy if (lc->pcaps & FW_PORT_CAP32_SPEED_100M)
165456b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_uint8(ph, 1);
165556b2bdd1SGireesh Nagabhushana else
165656b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
165756b2bdd1SGireesh Nagabhushana break;
165856b2bdd1SGireesh Nagabhushana
16596feac2e3SRahul Lakkireddy case MAC_PROP_ADV_100GFDX_CAP:
16606feac2e3SRahul Lakkireddy case MAC_PROP_ADV_50GFDX_CAP:
16616feac2e3SRahul Lakkireddy case MAC_PROP_ADV_40GFDX_CAP:
16626feac2e3SRahul Lakkireddy case MAC_PROP_ADV_25GFDX_CAP:
166356b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_10GFDX_CAP:
166456b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_1000FDX_CAP:
166556b2bdd1SGireesh Nagabhushana case MAC_PROP_ADV_100FDX_CAP:
166656b2bdd1SGireesh Nagabhushana mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ);
166756b2bdd1SGireesh Nagabhushana break;
166856b2bdd1SGireesh Nagabhushana
166956b2bdd1SGireesh Nagabhushana case MAC_PROP_PRIVATE:
167056b2bdd1SGireesh Nagabhushana propinfo(pi, name, ph);
167156b2bdd1SGireesh Nagabhushana break;
167256b2bdd1SGireesh Nagabhushana
167356b2bdd1SGireesh Nagabhushana default:
167456b2bdd1SGireesh Nagabhushana break;
167556b2bdd1SGireesh Nagabhushana }
167656b2bdd1SGireesh Nagabhushana }
167756b2bdd1SGireesh Nagabhushana
16787e6ad469SVishal Kulkarni int
begin_synchronized_op(struct port_info * pi,int hold,int waitok)167956b2bdd1SGireesh Nagabhushana begin_synchronized_op(struct port_info *pi, int hold, int waitok)
168056b2bdd1SGireesh Nagabhushana {
168156b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
168256b2bdd1SGireesh Nagabhushana int rc = 0;
168356b2bdd1SGireesh Nagabhushana
168456b2bdd1SGireesh Nagabhushana ADAPTER_LOCK(sc);
168556b2bdd1SGireesh Nagabhushana while (!IS_DOOMED(pi) && IS_BUSY(sc)) {
168656b2bdd1SGireesh Nagabhushana if (!waitok) {
168756b2bdd1SGireesh Nagabhushana rc = EBUSY;
168856b2bdd1SGireesh Nagabhushana goto failed;
168956b2bdd1SGireesh Nagabhushana } else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) {
169056b2bdd1SGireesh Nagabhushana rc = EINTR;
169156b2bdd1SGireesh Nagabhushana goto failed;
169256b2bdd1SGireesh Nagabhushana }
169356b2bdd1SGireesh Nagabhushana }
169456b2bdd1SGireesh Nagabhushana if (IS_DOOMED(pi) != 0) { /* shouldn't happen on Solaris */
169556b2bdd1SGireesh Nagabhushana rc = ENXIO;
169656b2bdd1SGireesh Nagabhushana goto failed;
169756b2bdd1SGireesh Nagabhushana }
169856b2bdd1SGireesh Nagabhushana ASSERT(!IS_BUSY(sc));
169956b2bdd1SGireesh Nagabhushana /* LINTED: E_CONSTANT_CONDITION */
170056b2bdd1SGireesh Nagabhushana SET_BUSY(sc);
170156b2bdd1SGireesh Nagabhushana
170256b2bdd1SGireesh Nagabhushana if (!hold)
170356b2bdd1SGireesh Nagabhushana ADAPTER_UNLOCK(sc);
170456b2bdd1SGireesh Nagabhushana
170556b2bdd1SGireesh Nagabhushana return (0);
170656b2bdd1SGireesh Nagabhushana failed:
170756b2bdd1SGireesh Nagabhushana ADAPTER_UNLOCK(sc);
170856b2bdd1SGireesh Nagabhushana return (rc);
170956b2bdd1SGireesh Nagabhushana }
171056b2bdd1SGireesh Nagabhushana
17117e6ad469SVishal Kulkarni void
end_synchronized_op(struct port_info * pi,int held)171256b2bdd1SGireesh Nagabhushana end_synchronized_op(struct port_info *pi, int held)
171356b2bdd1SGireesh Nagabhushana {
171456b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
171556b2bdd1SGireesh Nagabhushana
171656b2bdd1SGireesh Nagabhushana if (!held)
171756b2bdd1SGireesh Nagabhushana ADAPTER_LOCK(sc);
171856b2bdd1SGireesh Nagabhushana
171956b2bdd1SGireesh Nagabhushana ADAPTER_LOCK_ASSERT_OWNED(sc);
172056b2bdd1SGireesh Nagabhushana ASSERT(IS_BUSY(sc));
172156b2bdd1SGireesh Nagabhushana /* LINTED: E_CONSTANT_CONDITION */
172256b2bdd1SGireesh Nagabhushana CLR_BUSY(sc);
172356b2bdd1SGireesh Nagabhushana cv_signal(&sc->cv);
172456b2bdd1SGireesh Nagabhushana ADAPTER_UNLOCK(sc);
172556b2bdd1SGireesh Nagabhushana }
172656b2bdd1SGireesh Nagabhushana
172756b2bdd1SGireesh Nagabhushana static int
t4_init_synchronized(struct port_info * pi)172856b2bdd1SGireesh Nagabhushana t4_init_synchronized(struct port_info *pi)
172956b2bdd1SGireesh Nagabhushana {
173056b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
173156b2bdd1SGireesh Nagabhushana int rc = 0;
173256b2bdd1SGireesh Nagabhushana
173356b2bdd1SGireesh Nagabhushana ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
173456b2bdd1SGireesh Nagabhushana
173556b2bdd1SGireesh Nagabhushana if (isset(&sc->open_device_map, pi->port_id) != 0)
173656b2bdd1SGireesh Nagabhushana return (0); /* already running */
173756b2bdd1SGireesh Nagabhushana
173856b2bdd1SGireesh Nagabhushana if (!(sc->flags & FULL_INIT_DONE) &&
173956b2bdd1SGireesh Nagabhushana ((rc = adapter_full_init(sc)) != 0))
174056b2bdd1SGireesh Nagabhushana return (rc); /* error message displayed already */
174156b2bdd1SGireesh Nagabhushana
174256b2bdd1SGireesh Nagabhushana if (!(pi->flags & PORT_INIT_DONE)) {
174356b2bdd1SGireesh Nagabhushana rc = port_full_init(pi);
174456b2bdd1SGireesh Nagabhushana if (rc != 0)
174556b2bdd1SGireesh Nagabhushana return (rc); /* error message displayed already */
174656b2bdd1SGireesh Nagabhushana } else
174756b2bdd1SGireesh Nagabhushana enable_port_queues(pi);
174856b2bdd1SGireesh Nagabhushana
174956b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false);
175056b2bdd1SGireesh Nagabhushana if (rc != 0) {
175156b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc);
175256b2bdd1SGireesh Nagabhushana goto done;
175356b2bdd1SGireesh Nagabhushana }
175456b2bdd1SGireesh Nagabhushana rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt,
17557e6ad469SVishal Kulkarni pi->hw_addr, true, &pi->smt_idx);
175656b2bdd1SGireesh Nagabhushana if (rc < 0) {
175756b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc);
175856b2bdd1SGireesh Nagabhushana rc = -rc;
175956b2bdd1SGireesh Nagabhushana goto done;
176056b2bdd1SGireesh Nagabhushana } else
176156b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */
176256b2bdd1SGireesh Nagabhushana pi->xact_addr_filt = rc;
176356b2bdd1SGireesh Nagabhushana
17646feac2e3SRahul Lakkireddy rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg,
17656feac2e3SRahul Lakkireddy pi->link_cfg.admin_caps);
176656b2bdd1SGireesh Nagabhushana if (rc != 0) {
176756b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc);
176856b2bdd1SGireesh Nagabhushana goto done;
176956b2bdd1SGireesh Nagabhushana }
177056b2bdd1SGireesh Nagabhushana
177156b2bdd1SGireesh Nagabhushana rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true);
177256b2bdd1SGireesh Nagabhushana if (rc != 0) {
177356b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc);
177456b2bdd1SGireesh Nagabhushana goto done;
177556b2bdd1SGireesh Nagabhushana }
177656b2bdd1SGireesh Nagabhushana
177756b2bdd1SGireesh Nagabhushana /* all ok */
177856b2bdd1SGireesh Nagabhushana setbit(&sc->open_device_map, pi->port_id);
177956b2bdd1SGireesh Nagabhushana done:
178056b2bdd1SGireesh Nagabhushana if (rc != 0)
178156b2bdd1SGireesh Nagabhushana (void) t4_uninit_synchronized(pi);
178256b2bdd1SGireesh Nagabhushana
178356b2bdd1SGireesh Nagabhushana return (rc);
178456b2bdd1SGireesh Nagabhushana }
178556b2bdd1SGireesh Nagabhushana
178656b2bdd1SGireesh Nagabhushana /*
178756b2bdd1SGireesh Nagabhushana * Idempotent.
178856b2bdd1SGireesh Nagabhushana */
178956b2bdd1SGireesh Nagabhushana static int
t4_uninit_synchronized(struct port_info * pi)179056b2bdd1SGireesh Nagabhushana t4_uninit_synchronized(struct port_info *pi)
179156b2bdd1SGireesh Nagabhushana {
179256b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
179356b2bdd1SGireesh Nagabhushana int rc;
179456b2bdd1SGireesh Nagabhushana
179556b2bdd1SGireesh Nagabhushana ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
179656b2bdd1SGireesh Nagabhushana
179756b2bdd1SGireesh Nagabhushana /*
179856b2bdd1SGireesh Nagabhushana * Disable the VI so that all its data in either direction is discarded
179956b2bdd1SGireesh Nagabhushana * by the MPS. Leave everything else (the queues, interrupts, and 1Hz
180056b2bdd1SGireesh Nagabhushana * tick) intact as the TP can deliver negative advice or data that it's
180156b2bdd1SGireesh Nagabhushana * holding in its RAM (for an offloaded connection) even after the VI is
180256b2bdd1SGireesh Nagabhushana * disabled.
180356b2bdd1SGireesh Nagabhushana */
180456b2bdd1SGireesh Nagabhushana rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false);
180556b2bdd1SGireesh Nagabhushana if (rc != 0) {
180656b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc);
180756b2bdd1SGireesh Nagabhushana return (rc);
180856b2bdd1SGireesh Nagabhushana }
180956b2bdd1SGireesh Nagabhushana
181056b2bdd1SGireesh Nagabhushana disable_port_queues(pi);
181156b2bdd1SGireesh Nagabhushana
181256b2bdd1SGireesh Nagabhushana clrbit(&sc->open_device_map, pi->port_id);
181356b2bdd1SGireesh Nagabhushana
181456b2bdd1SGireesh Nagabhushana pi->link_cfg.link_ok = 0;
181556b2bdd1SGireesh Nagabhushana mac_link_update(pi->mh, LINK_STATE_UNKNOWN);
181656b2bdd1SGireesh Nagabhushana
181756b2bdd1SGireesh Nagabhushana return (0);
181856b2bdd1SGireesh Nagabhushana }
181956b2bdd1SGireesh Nagabhushana
182056b2bdd1SGireesh Nagabhushana static void
propinfo(struct port_info * pi,const char * name,mac_prop_info_handle_t ph)182156b2bdd1SGireesh Nagabhushana propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph)
182256b2bdd1SGireesh Nagabhushana {
182356b2bdd1SGireesh Nagabhushana struct adapter *sc = pi->adapter;
182456b2bdd1SGireesh Nagabhushana struct driver_properties *p = &sc->props;
182556b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg;
182656b2bdd1SGireesh Nagabhushana int v;
182756b2bdd1SGireesh Nagabhushana char str[16];
182856b2bdd1SGireesh Nagabhushana
182956b2bdd1SGireesh Nagabhushana if (strcmp(name, T4PROP_TMR_IDX) == 0)
183056b2bdd1SGireesh Nagabhushana v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g;
183156b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
183256b2bdd1SGireesh Nagabhushana v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g;
183356b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_CSUM) == 0)
183456b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
183556b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_LSO) == 0)
183656b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
183756b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
18386feac2e3SRahul Lakkireddy v = (lc->pcaps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
183956b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
18406feac2e3SRahul Lakkireddy v = (lc->pcaps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
184156b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
184256b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_MTU) == 0)
184356b2bdd1SGireesh Nagabhushana v = ETHERMTU;
184456b2bdd1SGireesh Nagabhushana #endif
184556b2bdd1SGireesh Nagabhushana else
184656b2bdd1SGireesh Nagabhushana return;
184756b2bdd1SGireesh Nagabhushana
184856b2bdd1SGireesh Nagabhushana (void) snprintf(str, sizeof (str), "%d", v);
184956b2bdd1SGireesh Nagabhushana mac_prop_info_set_default_str(ph, str);
185056b2bdd1SGireesh Nagabhushana }
185156b2bdd1SGireesh Nagabhushana
185256b2bdd1SGireesh Nagabhushana static int
getprop(struct port_info * pi,const char * name,uint_t size,void * val)185356b2bdd1SGireesh Nagabhushana getprop(struct port_info *pi, const char *name, uint_t size, void *val)
185456b2bdd1SGireesh Nagabhushana {
185556b2bdd1SGireesh Nagabhushana struct link_config *lc = &pi->link_cfg;
185656b2bdd1SGireesh Nagabhushana int v;
185756b2bdd1SGireesh Nagabhushana
185856b2bdd1SGireesh Nagabhushana if (strcmp(name, T4PROP_TMR_IDX) == 0)
185956b2bdd1SGireesh Nagabhushana v = pi->tmr_idx;
186056b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_PKTC_IDX) == 0)
186156b2bdd1SGireesh Nagabhushana v = pi->pktc_idx;
186256b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_CSUM) == 0)
186356b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0;
186456b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_HW_LSO) == 0)
186556b2bdd1SGireesh Nagabhushana v = (pi->features & CXGBE_HW_LSO) ? 1 : 0;
186656b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_TX_PAUSE) == 0)
18676feac2e3SRahul Lakkireddy v = (lc->link_caps & FW_PORT_CAP32_FC_TX) ? 1 : 0;
186856b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_RX_PAUSE) == 0)
18696feac2e3SRahul Lakkireddy v = (lc->link_caps & FW_PORT_CAP32_FC_RX) ? 1 : 0;
187056b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
187156b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_MTU) == 0)
187256b2bdd1SGireesh Nagabhushana v = pi->mtu;
187356b2bdd1SGireesh Nagabhushana #endif
187456b2bdd1SGireesh Nagabhushana else
187556b2bdd1SGireesh Nagabhushana return (ENOTSUP);
187656b2bdd1SGireesh Nagabhushana
187756b2bdd1SGireesh Nagabhushana (void) snprintf(val, size, "%d", v);
187856b2bdd1SGireesh Nagabhushana return (0);
187956b2bdd1SGireesh Nagabhushana }
188056b2bdd1SGireesh Nagabhushana
188156b2bdd1SGireesh Nagabhushana static int
setprop(struct port_info * pi,const char * name,const void * val)188256b2bdd1SGireesh Nagabhushana setprop(struct port_info *pi, const char *name, const void *val)
188356b2bdd1SGireesh Nagabhushana {
18846feac2e3SRahul Lakkireddy struct link_config *lc = &pi->link_cfg;
18856feac2e3SRahul Lakkireddy fw_port_cap32_t new_caps = lc->admin_caps;
188656b2bdd1SGireesh Nagabhushana int i, rc = 0, relink = 0, rx_mode = 0;
18876feac2e3SRahul Lakkireddy struct adapter *sc = pi->adapter;
188856b2bdd1SGireesh Nagabhushana struct sge_rxq *rxq;
18896feac2e3SRahul Lakkireddy cc_pause_t fc = 0;
18906feac2e3SRahul Lakkireddy long v;
189156b2bdd1SGireesh Nagabhushana
189256b2bdd1SGireesh Nagabhushana (void) ddi_strtol(val, NULL, 0, &v);
189356b2bdd1SGireesh Nagabhushana
189456b2bdd1SGireesh Nagabhushana if (strcmp(name, T4PROP_TMR_IDX) == 0) {
189556b2bdd1SGireesh Nagabhushana if (v < 0 || v >= SGE_NTIMERS)
189656b2bdd1SGireesh Nagabhushana return (EINVAL);
189756b2bdd1SGireesh Nagabhushana if (v == pi->tmr_idx)
189856b2bdd1SGireesh Nagabhushana return (0);
189956b2bdd1SGireesh Nagabhushana
190056b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */
190156b2bdd1SGireesh Nagabhushana pi->tmr_idx = v;
190256b2bdd1SGireesh Nagabhushana for_each_rxq(pi, i, rxq) {
190356b2bdd1SGireesh Nagabhushana rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) |
190456b2bdd1SGireesh Nagabhushana V_QINTR_CNT_EN(pi->pktc_idx >= 0);
190556b2bdd1SGireesh Nagabhushana }
190656b2bdd1SGireesh Nagabhushana
190756b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_PKTC_IDX) == 0) {
190856b2bdd1SGireesh Nagabhushana if (v >= SGE_NCOUNTERS)
190956b2bdd1SGireesh Nagabhushana return (EINVAL);
191056b2bdd1SGireesh Nagabhushana if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1))
191156b2bdd1SGireesh Nagabhushana return (0);
191256b2bdd1SGireesh Nagabhushana
191356b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */
191456b2bdd1SGireesh Nagabhushana pi->pktc_idx = v < 0 ? -1 : v;
191556b2bdd1SGireesh Nagabhushana for_each_rxq(pi, i, rxq) {
191656b2bdd1SGireesh Nagabhushana rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) |
191756b2bdd1SGireesh Nagabhushana /* takes effect right away */
191856b2bdd1SGireesh Nagabhushana V_QINTR_CNT_EN(v >= 0);
191956b2bdd1SGireesh Nagabhushana /* LINTED: E_ASSIGN_NARROW_CONV */
192056b2bdd1SGireesh Nagabhushana rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */
192156b2bdd1SGireesh Nagabhushana }
192256b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_HW_CSUM) == 0) {
192356b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1)
192456b2bdd1SGireesh Nagabhushana return (EINVAL);
192556b2bdd1SGireesh Nagabhushana if (v == 1)
192656b2bdd1SGireesh Nagabhushana pi->features |= CXGBE_HW_CSUM;
192756b2bdd1SGireesh Nagabhushana else
192856b2bdd1SGireesh Nagabhushana pi->features &= ~CXGBE_HW_CSUM;
192956b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_HW_LSO) == 0) {
193056b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1)
193156b2bdd1SGireesh Nagabhushana return (EINVAL);
193256b2bdd1SGireesh Nagabhushana if (v == 1)
193356b2bdd1SGireesh Nagabhushana pi->features |= CXGBE_HW_LSO;
193456b2bdd1SGireesh Nagabhushana else
193556b2bdd1SGireesh Nagabhushana pi->features &= ~CXGBE_HW_LSO;
193656b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_TX_PAUSE) == 0) {
193756b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1)
193856b2bdd1SGireesh Nagabhushana return (EINVAL);
193956b2bdd1SGireesh Nagabhushana
19406feac2e3SRahul Lakkireddy if ((new_caps & FW_PORT_CAP32_FC_TX) && (v == 1))
19416feac2e3SRahul Lakkireddy fc |= PAUSE_TX;
19426feac2e3SRahul Lakkireddy if (new_caps & FW_PORT_CAP32_FC_RX)
19436feac2e3SRahul Lakkireddy fc |= PAUSE_RX;
19446feac2e3SRahul Lakkireddy if (lc->admin_caps & FW_PORT_CAP32_ANEG)
19456feac2e3SRahul Lakkireddy fc |= PAUSE_AUTONEG;
194656b2bdd1SGireesh Nagabhushana
19476feac2e3SRahul Lakkireddy t4_link_set_pause(pi, fc, &new_caps);
194856b2bdd1SGireesh Nagabhushana relink = 1;
194956b2bdd1SGireesh Nagabhushana
195056b2bdd1SGireesh Nagabhushana } else if (strcmp(name, T4PROP_RX_PAUSE) == 0) {
195156b2bdd1SGireesh Nagabhushana if (v != 0 && v != 1)
195256b2bdd1SGireesh Nagabhushana return (EINVAL);
195356b2bdd1SGireesh Nagabhushana
19546feac2e3SRahul Lakkireddy if (new_caps & FW_PORT_CAP32_FC_TX)
19556feac2e3SRahul Lakkireddy fc |= PAUSE_TX;
19566feac2e3SRahul Lakkireddy if ((new_caps & FW_PORT_CAP32_FC_RX) && (v == 1))
19576feac2e3SRahul Lakkireddy fc |= PAUSE_RX;
19586feac2e3SRahul Lakkireddy if (lc->admin_caps & FW_PORT_CAP32_ANEG)
19596feac2e3SRahul Lakkireddy fc |= PAUSE_AUTONEG;
196056b2bdd1SGireesh Nagabhushana
19616feac2e3SRahul Lakkireddy t4_link_set_pause(pi, fc, &new_caps);
196256b2bdd1SGireesh Nagabhushana relink = 1;
196356b2bdd1SGireesh Nagabhushana }
196456b2bdd1SGireesh Nagabhushana #if MAC_VERSION == 1
196556b2bdd1SGireesh Nagabhushana else if (strcmp(name, T4PROP_MTU) == 0) {
196656b2bdd1SGireesh Nagabhushana if (v < 46 || v > MAX_MTU)
196756b2bdd1SGireesh Nagabhushana return (EINVAL);
196856b2bdd1SGireesh Nagabhushana if (v == pi->mtu)
196956b2bdd1SGireesh Nagabhushana return (0);
197056b2bdd1SGireesh Nagabhushana
197156b2bdd1SGireesh Nagabhushana pi->mtu = (int)v;
197256b2bdd1SGireesh Nagabhushana (void) mac_maxsdu_update(pi->mh, v);
197356b2bdd1SGireesh Nagabhushana rx_mode = 1;
197456b2bdd1SGireesh Nagabhushana }
197556b2bdd1SGireesh Nagabhushana #endif
197656b2bdd1SGireesh Nagabhushana else
197756b2bdd1SGireesh Nagabhushana return (ENOTSUP);
197856b2bdd1SGireesh Nagabhushana
197956b2bdd1SGireesh Nagabhushana if (!(relink || rx_mode))
198056b2bdd1SGireesh Nagabhushana return (0);
198156b2bdd1SGireesh Nagabhushana
198256b2bdd1SGireesh Nagabhushana /* If we are here, either relink or rx_mode is 1 */
198356b2bdd1SGireesh Nagabhushana if (isset(&sc->open_device_map, pi->port_id) != 0) {
198456b2bdd1SGireesh Nagabhushana if (relink != 0) {
198556b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
198656b2bdd1SGireesh Nagabhushana if (rc != 0)
198756b2bdd1SGireesh Nagabhushana return (rc);
19886feac2e3SRahul Lakkireddy rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc,
19896feac2e3SRahul Lakkireddy new_caps);
199056b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
199156b2bdd1SGireesh Nagabhushana if (rc != 0) {
199256b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN,
19936feac2e3SRahul Lakkireddy "%s link config failed: %d",
19946feac2e3SRahul Lakkireddy __func__, rc);
19956feac2e3SRahul Lakkireddy return (rc);
199656b2bdd1SGireesh Nagabhushana }
199756b2bdd1SGireesh Nagabhushana } else if (rx_mode != 0) {
199856b2bdd1SGireesh Nagabhushana rc = begin_synchronized_op(pi, 1, 1);
199956b2bdd1SGireesh Nagabhushana if (rc != 0)
200056b2bdd1SGireesh Nagabhushana return (rc);
200156b2bdd1SGireesh Nagabhushana rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1,
200256b2bdd1SGireesh Nagabhushana -1, -1, false);
200356b2bdd1SGireesh Nagabhushana end_synchronized_op(pi, 1);
200456b2bdd1SGireesh Nagabhushana if (rc != 0) {
200556b2bdd1SGireesh Nagabhushana cxgb_printf(pi->dip, CE_WARN,
20066feac2e3SRahul Lakkireddy "set_rxmode failed: %d", rc);
20076feac2e3SRahul Lakkireddy return (rc);
200856b2bdd1SGireesh Nagabhushana }
200956b2bdd1SGireesh Nagabhushana }
201056b2bdd1SGireesh Nagabhushana }
201156b2bdd1SGireesh Nagabhushana
20126feac2e3SRahul Lakkireddy if (relink != 0)
20136feac2e3SRahul Lakkireddy lc->admin_caps = new_caps;
20146feac2e3SRahul Lakkireddy
201556b2bdd1SGireesh Nagabhushana return (0);
201656b2bdd1SGireesh Nagabhushana }
201756b2bdd1SGireesh Nagabhushana
201856b2bdd1SGireesh Nagabhushana void
t4_mc_init(struct port_info * pi)201956b2bdd1SGireesh Nagabhushana t4_mc_init(struct port_info *pi)
202056b2bdd1SGireesh Nagabhushana {
202156b2bdd1SGireesh Nagabhushana pi->props = t4_priv_props;
202256b2bdd1SGireesh Nagabhushana }
202356b2bdd1SGireesh Nagabhushana
20243dde7c95SVishal Kulkarni void
t4_mc_cb_init(struct port_info * pi)20253dde7c95SVishal Kulkarni t4_mc_cb_init(struct port_info *pi)
20263dde7c95SVishal Kulkarni {
20273dde7c95SVishal Kulkarni if (pi->adapter->props.multi_rings)
20283dde7c95SVishal Kulkarni pi->mc = &t4_m_ring_callbacks;
20293dde7c95SVishal Kulkarni else
20303dde7c95SVishal Kulkarni pi->mc = &t4_m_callbacks;
20313dde7c95SVishal Kulkarni }
20323dde7c95SVishal Kulkarni
203356b2bdd1SGireesh Nagabhushana void
t4_os_link_changed(struct adapter * sc,int idx,int link_stat)203456b2bdd1SGireesh Nagabhushana t4_os_link_changed(struct adapter *sc, int idx, int link_stat)
203556b2bdd1SGireesh Nagabhushana {
203656b2bdd1SGireesh Nagabhushana struct port_info *pi = sc->port[idx];
203756b2bdd1SGireesh Nagabhushana
203856b2bdd1SGireesh Nagabhushana mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN);
203956b2bdd1SGireesh Nagabhushana }
204056b2bdd1SGireesh Nagabhushana
204156b2bdd1SGireesh Nagabhushana /* ARGSUSED */
204256b2bdd1SGireesh Nagabhushana void
t4_mac_rx(struct port_info * pi,struct sge_rxq * rxq,mblk_t * m)204356b2bdd1SGireesh Nagabhushana t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m)
204456b2bdd1SGireesh Nagabhushana {
204556b2bdd1SGireesh Nagabhushana mac_rx(pi->mh, NULL, m);
204656b2bdd1SGireesh Nagabhushana }
20473dde7c95SVishal Kulkarni
20483dde7c95SVishal Kulkarni void
t4_mac_tx_update(struct port_info * pi,struct sge_txq * txq)20493dde7c95SVishal Kulkarni t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq)
20503dde7c95SVishal Kulkarni {
20513dde7c95SVishal Kulkarni if (pi->adapter->props.multi_rings)
20523dde7c95SVishal Kulkarni mac_tx_ring_update(pi->mh, txq->ring_handle);
20533dde7c95SVishal Kulkarni else
20543dde7c95SVishal Kulkarni mac_tx_update(pi->mh);
20553dde7c95SVishal Kulkarni }
2056