1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2013-2015 Chelsio Communications. All rights reserved.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/firmware.h>
7*4882a593Smuzhiyun #include <linux/mdio.h>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include "cxgb4.h"
10*4882a593Smuzhiyun #include "t4_regs.h"
11*4882a593Smuzhiyun #include "t4fw_api.h"
12*4882a593Smuzhiyun #include "cxgb4_cudbg.h"
13*4882a593Smuzhiyun #include "cxgb4_filter.h"
14*4882a593Smuzhiyun #include "cxgb4_tc_flower.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define EEPROM_MAGIC 0x38E2F10C
17*4882a593Smuzhiyun
get_msglevel(struct net_device * dev)18*4882a593Smuzhiyun static u32 get_msglevel(struct net_device *dev)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun return netdev2adap(dev)->msg_enable;
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun
set_msglevel(struct net_device * dev,u32 val)23*4882a593Smuzhiyun static void set_msglevel(struct net_device *dev, u32 val)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun netdev2adap(dev)->msg_enable = val;
26*4882a593Smuzhiyun }
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun enum cxgb4_ethtool_tests {
29*4882a593Smuzhiyun CXGB4_ETHTOOL_LB_TEST,
30*4882a593Smuzhiyun CXGB4_ETHTOOL_MAX_TEST,
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun static const char cxgb4_selftest_strings[CXGB4_ETHTOOL_MAX_TEST][ETH_GSTRING_LEN] = {
34*4882a593Smuzhiyun "Loop back test (offline)",
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static const char * const flash_region_strings[] = {
38*4882a593Smuzhiyun "All",
39*4882a593Smuzhiyun "Firmware",
40*4882a593Smuzhiyun "PHY Firmware",
41*4882a593Smuzhiyun "Boot",
42*4882a593Smuzhiyun "Boot CFG",
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun static const char stats_strings[][ETH_GSTRING_LEN] = {
46*4882a593Smuzhiyun "tx_octets_ok ",
47*4882a593Smuzhiyun "tx_frames_ok ",
48*4882a593Smuzhiyun "tx_broadcast_frames ",
49*4882a593Smuzhiyun "tx_multicast_frames ",
50*4882a593Smuzhiyun "tx_unicast_frames ",
51*4882a593Smuzhiyun "tx_error_frames ",
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun "tx_frames_64 ",
54*4882a593Smuzhiyun "tx_frames_65_to_127 ",
55*4882a593Smuzhiyun "tx_frames_128_to_255 ",
56*4882a593Smuzhiyun "tx_frames_256_to_511 ",
57*4882a593Smuzhiyun "tx_frames_512_to_1023 ",
58*4882a593Smuzhiyun "tx_frames_1024_to_1518 ",
59*4882a593Smuzhiyun "tx_frames_1519_to_max ",
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun "tx_frames_dropped ",
62*4882a593Smuzhiyun "tx_pause_frames ",
63*4882a593Smuzhiyun "tx_ppp0_frames ",
64*4882a593Smuzhiyun "tx_ppp1_frames ",
65*4882a593Smuzhiyun "tx_ppp2_frames ",
66*4882a593Smuzhiyun "tx_ppp3_frames ",
67*4882a593Smuzhiyun "tx_ppp4_frames ",
68*4882a593Smuzhiyun "tx_ppp5_frames ",
69*4882a593Smuzhiyun "tx_ppp6_frames ",
70*4882a593Smuzhiyun "tx_ppp7_frames ",
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun "rx_octets_ok ",
73*4882a593Smuzhiyun "rx_frames_ok ",
74*4882a593Smuzhiyun "rx_broadcast_frames ",
75*4882a593Smuzhiyun "rx_multicast_frames ",
76*4882a593Smuzhiyun "rx_unicast_frames ",
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun "rx_frames_too_long ",
79*4882a593Smuzhiyun "rx_jabber_errors ",
80*4882a593Smuzhiyun "rx_fcs_errors ",
81*4882a593Smuzhiyun "rx_length_errors ",
82*4882a593Smuzhiyun "rx_symbol_errors ",
83*4882a593Smuzhiyun "rx_runt_frames ",
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun "rx_frames_64 ",
86*4882a593Smuzhiyun "rx_frames_65_to_127 ",
87*4882a593Smuzhiyun "rx_frames_128_to_255 ",
88*4882a593Smuzhiyun "rx_frames_256_to_511 ",
89*4882a593Smuzhiyun "rx_frames_512_to_1023 ",
90*4882a593Smuzhiyun "rx_frames_1024_to_1518 ",
91*4882a593Smuzhiyun "rx_frames_1519_to_max ",
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun "rx_pause_frames ",
94*4882a593Smuzhiyun "rx_ppp0_frames ",
95*4882a593Smuzhiyun "rx_ppp1_frames ",
96*4882a593Smuzhiyun "rx_ppp2_frames ",
97*4882a593Smuzhiyun "rx_ppp3_frames ",
98*4882a593Smuzhiyun "rx_ppp4_frames ",
99*4882a593Smuzhiyun "rx_ppp5_frames ",
100*4882a593Smuzhiyun "rx_ppp6_frames ",
101*4882a593Smuzhiyun "rx_ppp7_frames ",
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun "rx_bg0_frames_dropped ",
104*4882a593Smuzhiyun "rx_bg1_frames_dropped ",
105*4882a593Smuzhiyun "rx_bg2_frames_dropped ",
106*4882a593Smuzhiyun "rx_bg3_frames_dropped ",
107*4882a593Smuzhiyun "rx_bg0_frames_trunc ",
108*4882a593Smuzhiyun "rx_bg1_frames_trunc ",
109*4882a593Smuzhiyun "rx_bg2_frames_trunc ",
110*4882a593Smuzhiyun "rx_bg3_frames_trunc ",
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun "tso ",
113*4882a593Smuzhiyun "uso ",
114*4882a593Smuzhiyun "tx_csum_offload ",
115*4882a593Smuzhiyun "rx_csum_good ",
116*4882a593Smuzhiyun "vlan_extractions ",
117*4882a593Smuzhiyun "vlan_insertions ",
118*4882a593Smuzhiyun "gro_packets ",
119*4882a593Smuzhiyun "gro_merged ",
120*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
121*4882a593Smuzhiyun "tx_tls_encrypted_packets",
122*4882a593Smuzhiyun "tx_tls_encrypted_bytes ",
123*4882a593Smuzhiyun "tx_tls_ctx ",
124*4882a593Smuzhiyun "tx_tls_ooo ",
125*4882a593Smuzhiyun "tx_tls_skip_no_sync_data",
126*4882a593Smuzhiyun "tx_tls_drop_no_sync_data",
127*4882a593Smuzhiyun "tx_tls_drop_bypass_req ",
128*4882a593Smuzhiyun #endif
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun static char adapter_stats_strings[][ETH_GSTRING_LEN] = {
132*4882a593Smuzhiyun "db_drop ",
133*4882a593Smuzhiyun "db_full ",
134*4882a593Smuzhiyun "db_empty ",
135*4882a593Smuzhiyun "write_coal_success ",
136*4882a593Smuzhiyun "write_coal_fail ",
137*4882a593Smuzhiyun };
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun static char loopback_stats_strings[][ETH_GSTRING_LEN] = {
140*4882a593Smuzhiyun "-------Loopback----------- ",
141*4882a593Smuzhiyun "octets_ok ",
142*4882a593Smuzhiyun "frames_ok ",
143*4882a593Smuzhiyun "bcast_frames ",
144*4882a593Smuzhiyun "mcast_frames ",
145*4882a593Smuzhiyun "ucast_frames ",
146*4882a593Smuzhiyun "error_frames ",
147*4882a593Smuzhiyun "frames_64 ",
148*4882a593Smuzhiyun "frames_65_to_127 ",
149*4882a593Smuzhiyun "frames_128_to_255 ",
150*4882a593Smuzhiyun "frames_256_to_511 ",
151*4882a593Smuzhiyun "frames_512_to_1023 ",
152*4882a593Smuzhiyun "frames_1024_to_1518 ",
153*4882a593Smuzhiyun "frames_1519_to_max ",
154*4882a593Smuzhiyun "frames_dropped ",
155*4882a593Smuzhiyun "bg0_frames_dropped ",
156*4882a593Smuzhiyun "bg1_frames_dropped ",
157*4882a593Smuzhiyun "bg2_frames_dropped ",
158*4882a593Smuzhiyun "bg3_frames_dropped ",
159*4882a593Smuzhiyun "bg0_frames_trunc ",
160*4882a593Smuzhiyun "bg1_frames_trunc ",
161*4882a593Smuzhiyun "bg2_frames_trunc ",
162*4882a593Smuzhiyun "bg3_frames_trunc ",
163*4882a593Smuzhiyun };
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun static const char cxgb4_priv_flags_strings[][ETH_GSTRING_LEN] = {
166*4882a593Smuzhiyun [PRIV_FLAG_PORT_TX_VM_BIT] = "port_tx_vm_wr",
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun
get_sset_count(struct net_device * dev,int sset)169*4882a593Smuzhiyun static int get_sset_count(struct net_device *dev, int sset)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun switch (sset) {
172*4882a593Smuzhiyun case ETH_SS_STATS:
173*4882a593Smuzhiyun return ARRAY_SIZE(stats_strings) +
174*4882a593Smuzhiyun ARRAY_SIZE(adapter_stats_strings) +
175*4882a593Smuzhiyun ARRAY_SIZE(loopback_stats_strings);
176*4882a593Smuzhiyun case ETH_SS_PRIV_FLAGS:
177*4882a593Smuzhiyun return ARRAY_SIZE(cxgb4_priv_flags_strings);
178*4882a593Smuzhiyun case ETH_SS_TEST:
179*4882a593Smuzhiyun return ARRAY_SIZE(cxgb4_selftest_strings);
180*4882a593Smuzhiyun default:
181*4882a593Smuzhiyun return -EOPNOTSUPP;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
get_regs_len(struct net_device * dev)185*4882a593Smuzhiyun static int get_regs_len(struct net_device *dev)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun struct adapter *adap = netdev2adap(dev);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun return t4_get_regs_len(adap);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
get_eeprom_len(struct net_device * dev)192*4882a593Smuzhiyun static int get_eeprom_len(struct net_device *dev)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun return EEPROMSIZE;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)197*4882a593Smuzhiyun static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
200*4882a593Smuzhiyun u32 exprom_vers;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun strlcpy(info->driver, cxgb4_driver_name, sizeof(info->driver));
203*4882a593Smuzhiyun strlcpy(info->bus_info, pci_name(adapter->pdev),
204*4882a593Smuzhiyun sizeof(info->bus_info));
205*4882a593Smuzhiyun info->regdump_len = get_regs_len(dev);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun if (adapter->params.fw_vers)
208*4882a593Smuzhiyun snprintf(info->fw_version, sizeof(info->fw_version),
209*4882a593Smuzhiyun "%u.%u.%u.%u, TP %u.%u.%u.%u",
210*4882a593Smuzhiyun FW_HDR_FW_VER_MAJOR_G(adapter->params.fw_vers),
211*4882a593Smuzhiyun FW_HDR_FW_VER_MINOR_G(adapter->params.fw_vers),
212*4882a593Smuzhiyun FW_HDR_FW_VER_MICRO_G(adapter->params.fw_vers),
213*4882a593Smuzhiyun FW_HDR_FW_VER_BUILD_G(adapter->params.fw_vers),
214*4882a593Smuzhiyun FW_HDR_FW_VER_MAJOR_G(adapter->params.tp_vers),
215*4882a593Smuzhiyun FW_HDR_FW_VER_MINOR_G(adapter->params.tp_vers),
216*4882a593Smuzhiyun FW_HDR_FW_VER_MICRO_G(adapter->params.tp_vers),
217*4882a593Smuzhiyun FW_HDR_FW_VER_BUILD_G(adapter->params.tp_vers));
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (!t4_get_exprom_version(adapter, &exprom_vers))
220*4882a593Smuzhiyun snprintf(info->erom_version, sizeof(info->erom_version),
221*4882a593Smuzhiyun "%u.%u.%u.%u",
222*4882a593Smuzhiyun FW_HDR_FW_VER_MAJOR_G(exprom_vers),
223*4882a593Smuzhiyun FW_HDR_FW_VER_MINOR_G(exprom_vers),
224*4882a593Smuzhiyun FW_HDR_FW_VER_MICRO_G(exprom_vers),
225*4882a593Smuzhiyun FW_HDR_FW_VER_BUILD_G(exprom_vers));
226*4882a593Smuzhiyun info->n_priv_flags = ARRAY_SIZE(cxgb4_priv_flags_strings);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
get_strings(struct net_device * dev,u32 stringset,u8 * data)229*4882a593Smuzhiyun static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun if (stringset == ETH_SS_STATS) {
232*4882a593Smuzhiyun memcpy(data, stats_strings, sizeof(stats_strings));
233*4882a593Smuzhiyun data += sizeof(stats_strings);
234*4882a593Smuzhiyun memcpy(data, adapter_stats_strings,
235*4882a593Smuzhiyun sizeof(adapter_stats_strings));
236*4882a593Smuzhiyun data += sizeof(adapter_stats_strings);
237*4882a593Smuzhiyun memcpy(data, loopback_stats_strings,
238*4882a593Smuzhiyun sizeof(loopback_stats_strings));
239*4882a593Smuzhiyun } else if (stringset == ETH_SS_PRIV_FLAGS) {
240*4882a593Smuzhiyun memcpy(data, cxgb4_priv_flags_strings,
241*4882a593Smuzhiyun sizeof(cxgb4_priv_flags_strings));
242*4882a593Smuzhiyun } else if (stringset == ETH_SS_TEST) {
243*4882a593Smuzhiyun memcpy(data, cxgb4_selftest_strings,
244*4882a593Smuzhiyun sizeof(cxgb4_selftest_strings));
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun /* port stats maintained per queue of the port. They should be in the same
249*4882a593Smuzhiyun * order as in stats_strings above.
250*4882a593Smuzhiyun */
251*4882a593Smuzhiyun struct queue_port_stats {
252*4882a593Smuzhiyun u64 tso;
253*4882a593Smuzhiyun u64 uso;
254*4882a593Smuzhiyun u64 tx_csum;
255*4882a593Smuzhiyun u64 rx_csum;
256*4882a593Smuzhiyun u64 vlan_ex;
257*4882a593Smuzhiyun u64 vlan_ins;
258*4882a593Smuzhiyun u64 gro_pkts;
259*4882a593Smuzhiyun u64 gro_merged;
260*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
261*4882a593Smuzhiyun u64 tx_tls_encrypted_packets;
262*4882a593Smuzhiyun u64 tx_tls_encrypted_bytes;
263*4882a593Smuzhiyun u64 tx_tls_ctx;
264*4882a593Smuzhiyun u64 tx_tls_ooo;
265*4882a593Smuzhiyun u64 tx_tls_skip_no_sync_data;
266*4882a593Smuzhiyun u64 tx_tls_drop_no_sync_data;
267*4882a593Smuzhiyun u64 tx_tls_drop_bypass_req;
268*4882a593Smuzhiyun #endif
269*4882a593Smuzhiyun };
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun struct adapter_stats {
272*4882a593Smuzhiyun u64 db_drop;
273*4882a593Smuzhiyun u64 db_full;
274*4882a593Smuzhiyun u64 db_empty;
275*4882a593Smuzhiyun u64 wc_success;
276*4882a593Smuzhiyun u64 wc_fail;
277*4882a593Smuzhiyun };
278*4882a593Smuzhiyun
collect_sge_port_stats(const struct adapter * adap,const struct port_info * p,struct queue_port_stats * s)279*4882a593Smuzhiyun static void collect_sge_port_stats(const struct adapter *adap,
280*4882a593Smuzhiyun const struct port_info *p,
281*4882a593Smuzhiyun struct queue_port_stats *s)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun const struct sge_eth_txq *tx = &adap->sge.ethtxq[p->first_qset];
284*4882a593Smuzhiyun const struct sge_eth_rxq *rx = &adap->sge.ethrxq[p->first_qset];
285*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
286*4882a593Smuzhiyun const struct ch_ktls_port_stats_debug *ktls_stats;
287*4882a593Smuzhiyun #endif
288*4882a593Smuzhiyun struct sge_eohw_txq *eohw_tx;
289*4882a593Smuzhiyun unsigned int i;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun memset(s, 0, sizeof(*s));
292*4882a593Smuzhiyun for (i = 0; i < p->nqsets; i++, rx++, tx++) {
293*4882a593Smuzhiyun s->tso += tx->tso;
294*4882a593Smuzhiyun s->uso += tx->uso;
295*4882a593Smuzhiyun s->tx_csum += tx->tx_cso;
296*4882a593Smuzhiyun s->rx_csum += rx->stats.rx_cso;
297*4882a593Smuzhiyun s->vlan_ex += rx->stats.vlan_ex;
298*4882a593Smuzhiyun s->vlan_ins += tx->vlan_ins;
299*4882a593Smuzhiyun s->gro_pkts += rx->stats.lro_pkts;
300*4882a593Smuzhiyun s->gro_merged += rx->stats.lro_merged;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun if (adap->sge.eohw_txq) {
304*4882a593Smuzhiyun eohw_tx = &adap->sge.eohw_txq[p->first_qset];
305*4882a593Smuzhiyun for (i = 0; i < p->nqsets; i++, eohw_tx++) {
306*4882a593Smuzhiyun s->tso += eohw_tx->tso;
307*4882a593Smuzhiyun s->uso += eohw_tx->uso;
308*4882a593Smuzhiyun s->tx_csum += eohw_tx->tx_cso;
309*4882a593Smuzhiyun s->vlan_ins += eohw_tx->vlan_ins;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CHELSIO_TLS_DEVICE)
313*4882a593Smuzhiyun ktls_stats = &adap->ch_ktls_stats.ktls_port[p->port_id];
314*4882a593Smuzhiyun s->tx_tls_encrypted_packets =
315*4882a593Smuzhiyun atomic64_read(&ktls_stats->ktls_tx_encrypted_packets);
316*4882a593Smuzhiyun s->tx_tls_encrypted_bytes =
317*4882a593Smuzhiyun atomic64_read(&ktls_stats->ktls_tx_encrypted_bytes);
318*4882a593Smuzhiyun s->tx_tls_ctx = atomic64_read(&ktls_stats->ktls_tx_ctx);
319*4882a593Smuzhiyun s->tx_tls_ooo = atomic64_read(&ktls_stats->ktls_tx_ooo);
320*4882a593Smuzhiyun s->tx_tls_skip_no_sync_data =
321*4882a593Smuzhiyun atomic64_read(&ktls_stats->ktls_tx_skip_no_sync_data);
322*4882a593Smuzhiyun s->tx_tls_drop_no_sync_data =
323*4882a593Smuzhiyun atomic64_read(&ktls_stats->ktls_tx_drop_no_sync_data);
324*4882a593Smuzhiyun s->tx_tls_drop_bypass_req =
325*4882a593Smuzhiyun atomic64_read(&ktls_stats->ktls_tx_drop_bypass_req);
326*4882a593Smuzhiyun #endif
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
collect_adapter_stats(struct adapter * adap,struct adapter_stats * s)329*4882a593Smuzhiyun static void collect_adapter_stats(struct adapter *adap, struct adapter_stats *s)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun u64 val1, val2;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun memset(s, 0, sizeof(*s));
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun s->db_drop = adap->db_stats.db_drop;
336*4882a593Smuzhiyun s->db_full = adap->db_stats.db_full;
337*4882a593Smuzhiyun s->db_empty = adap->db_stats.db_empty;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun if (!is_t4(adap->params.chip)) {
340*4882a593Smuzhiyun int v;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun v = t4_read_reg(adap, SGE_STAT_CFG_A);
343*4882a593Smuzhiyun if (STATSOURCE_T5_G(v) == 7) {
344*4882a593Smuzhiyun val2 = t4_read_reg(adap, SGE_STAT_MATCH_A);
345*4882a593Smuzhiyun val1 = t4_read_reg(adap, SGE_STAT_TOTAL_A);
346*4882a593Smuzhiyun s->wc_success = val1 - val2;
347*4882a593Smuzhiyun s->wc_fail = val2;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
get_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)352*4882a593Smuzhiyun static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
353*4882a593Smuzhiyun u64 *data)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
356*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
357*4882a593Smuzhiyun struct lb_port_stats s;
358*4882a593Smuzhiyun int i;
359*4882a593Smuzhiyun u64 *p0;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun t4_get_port_stats_offset(adapter, pi->tx_chan,
362*4882a593Smuzhiyun (struct port_stats *)data,
363*4882a593Smuzhiyun &pi->stats_base);
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun data += sizeof(struct port_stats) / sizeof(u64);
366*4882a593Smuzhiyun collect_sge_port_stats(adapter, pi, (struct queue_port_stats *)data);
367*4882a593Smuzhiyun data += sizeof(struct queue_port_stats) / sizeof(u64);
368*4882a593Smuzhiyun collect_adapter_stats(adapter, (struct adapter_stats *)data);
369*4882a593Smuzhiyun data += sizeof(struct adapter_stats) / sizeof(u64);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun *data++ = (u64)pi->port_id;
372*4882a593Smuzhiyun memset(&s, 0, sizeof(s));
373*4882a593Smuzhiyun t4_get_lb_stats(adapter, pi->port_id, &s);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun p0 = &s.octets;
376*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(loopback_stats_strings) - 1; i++)
377*4882a593Smuzhiyun *data++ = (unsigned long long)*p0++;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun
get_regs(struct net_device * dev,struct ethtool_regs * regs,void * buf)380*4882a593Smuzhiyun static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
381*4882a593Smuzhiyun void *buf)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun struct adapter *adap = netdev2adap(dev);
384*4882a593Smuzhiyun size_t buf_size;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun buf_size = t4_get_regs_len(adap);
387*4882a593Smuzhiyun regs->version = mk_adap_vers(adap);
388*4882a593Smuzhiyun t4_get_regs(adap, buf, buf_size);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
restart_autoneg(struct net_device * dev)391*4882a593Smuzhiyun static int restart_autoneg(struct net_device *dev)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun struct port_info *p = netdev_priv(dev);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun if (!netif_running(dev))
396*4882a593Smuzhiyun return -EAGAIN;
397*4882a593Smuzhiyun if (p->link_cfg.autoneg != AUTONEG_ENABLE)
398*4882a593Smuzhiyun return -EINVAL;
399*4882a593Smuzhiyun t4_restart_aneg(p->adapter, p->adapter->pf, p->tx_chan);
400*4882a593Smuzhiyun return 0;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun
identify_port(struct net_device * dev,enum ethtool_phys_id_state state)403*4882a593Smuzhiyun static int identify_port(struct net_device *dev,
404*4882a593Smuzhiyun enum ethtool_phys_id_state state)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun unsigned int val;
407*4882a593Smuzhiyun struct adapter *adap = netdev2adap(dev);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun if (state == ETHTOOL_ID_ACTIVE)
410*4882a593Smuzhiyun val = 0xffff;
411*4882a593Smuzhiyun else if (state == ETHTOOL_ID_INACTIVE)
412*4882a593Smuzhiyun val = 0;
413*4882a593Smuzhiyun else
414*4882a593Smuzhiyun return -EINVAL;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun return t4_identify_port(adap, adap->pf, netdev2pinfo(dev)->viid, val);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun /**
420*4882a593Smuzhiyun * from_fw_port_mod_type - translate Firmware Port/Module type to Ethtool
421*4882a593Smuzhiyun * @port_type: Firmware Port Type
422*4882a593Smuzhiyun * @mod_type: Firmware Module Type
423*4882a593Smuzhiyun *
424*4882a593Smuzhiyun * Translate Firmware Port/Module type to Ethtool Port Type.
425*4882a593Smuzhiyun */
from_fw_port_mod_type(enum fw_port_type port_type,enum fw_port_module_type mod_type)426*4882a593Smuzhiyun static int from_fw_port_mod_type(enum fw_port_type port_type,
427*4882a593Smuzhiyun enum fw_port_module_type mod_type)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun if (port_type == FW_PORT_TYPE_BT_SGMII ||
430*4882a593Smuzhiyun port_type == FW_PORT_TYPE_BT_XFI ||
431*4882a593Smuzhiyun port_type == FW_PORT_TYPE_BT_XAUI) {
432*4882a593Smuzhiyun return PORT_TP;
433*4882a593Smuzhiyun } else if (port_type == FW_PORT_TYPE_FIBER_XFI ||
434*4882a593Smuzhiyun port_type == FW_PORT_TYPE_FIBER_XAUI) {
435*4882a593Smuzhiyun return PORT_FIBRE;
436*4882a593Smuzhiyun } else if (port_type == FW_PORT_TYPE_SFP ||
437*4882a593Smuzhiyun port_type == FW_PORT_TYPE_QSFP_10G ||
438*4882a593Smuzhiyun port_type == FW_PORT_TYPE_QSA ||
439*4882a593Smuzhiyun port_type == FW_PORT_TYPE_QSFP ||
440*4882a593Smuzhiyun port_type == FW_PORT_TYPE_CR4_QSFP ||
441*4882a593Smuzhiyun port_type == FW_PORT_TYPE_CR_QSFP ||
442*4882a593Smuzhiyun port_type == FW_PORT_TYPE_CR2_QSFP ||
443*4882a593Smuzhiyun port_type == FW_PORT_TYPE_SFP28) {
444*4882a593Smuzhiyun if (mod_type == FW_PORT_MOD_TYPE_LR ||
445*4882a593Smuzhiyun mod_type == FW_PORT_MOD_TYPE_SR ||
446*4882a593Smuzhiyun mod_type == FW_PORT_MOD_TYPE_ER ||
447*4882a593Smuzhiyun mod_type == FW_PORT_MOD_TYPE_LRM)
448*4882a593Smuzhiyun return PORT_FIBRE;
449*4882a593Smuzhiyun else if (mod_type == FW_PORT_MOD_TYPE_TWINAX_PASSIVE ||
450*4882a593Smuzhiyun mod_type == FW_PORT_MOD_TYPE_TWINAX_ACTIVE)
451*4882a593Smuzhiyun return PORT_DA;
452*4882a593Smuzhiyun else
453*4882a593Smuzhiyun return PORT_OTHER;
454*4882a593Smuzhiyun } else if (port_type == FW_PORT_TYPE_KR4_100G ||
455*4882a593Smuzhiyun port_type == FW_PORT_TYPE_KR_SFP28 ||
456*4882a593Smuzhiyun port_type == FW_PORT_TYPE_KR_XLAUI) {
457*4882a593Smuzhiyun return PORT_NONE;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun return PORT_OTHER;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /**
464*4882a593Smuzhiyun * speed_to_fw_caps - translate Port Speed to Firmware Port Capabilities
465*4882a593Smuzhiyun * @speed: speed in Kb/s
466*4882a593Smuzhiyun *
467*4882a593Smuzhiyun * Translates a specific Port Speed into a Firmware Port Capabilities
468*4882a593Smuzhiyun * value.
469*4882a593Smuzhiyun */
speed_to_fw_caps(int speed)470*4882a593Smuzhiyun static unsigned int speed_to_fw_caps(int speed)
471*4882a593Smuzhiyun {
472*4882a593Smuzhiyun if (speed == 100)
473*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_100M;
474*4882a593Smuzhiyun if (speed == 1000)
475*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_1G;
476*4882a593Smuzhiyun if (speed == 10000)
477*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_10G;
478*4882a593Smuzhiyun if (speed == 25000)
479*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_25G;
480*4882a593Smuzhiyun if (speed == 40000)
481*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_40G;
482*4882a593Smuzhiyun if (speed == 50000)
483*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_50G;
484*4882a593Smuzhiyun if (speed == 100000)
485*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_100G;
486*4882a593Smuzhiyun if (speed == 200000)
487*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_200G;
488*4882a593Smuzhiyun if (speed == 400000)
489*4882a593Smuzhiyun return FW_PORT_CAP32_SPEED_400G;
490*4882a593Smuzhiyun return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /**
494*4882a593Smuzhiyun * fw_caps_to_lmm - translate Firmware to ethtool Link Mode Mask
495*4882a593Smuzhiyun * @port_type: Firmware Port Type
496*4882a593Smuzhiyun * @fw_caps: Firmware Port Capabilities
497*4882a593Smuzhiyun * @link_mode_mask: ethtool Link Mode Mask
498*4882a593Smuzhiyun *
499*4882a593Smuzhiyun * Translate a Firmware Port Capabilities specification to an ethtool
500*4882a593Smuzhiyun * Link Mode Mask.
501*4882a593Smuzhiyun */
fw_caps_to_lmm(enum fw_port_type port_type,fw_port_cap32_t fw_caps,unsigned long * link_mode_mask)502*4882a593Smuzhiyun static void fw_caps_to_lmm(enum fw_port_type port_type,
503*4882a593Smuzhiyun fw_port_cap32_t fw_caps,
504*4882a593Smuzhiyun unsigned long *link_mode_mask)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun #define SET_LMM(__lmm_name) \
507*4882a593Smuzhiyun do { \
508*4882a593Smuzhiyun __set_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
509*4882a593Smuzhiyun link_mode_mask); \
510*4882a593Smuzhiyun } while (0)
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun #define FW_CAPS_TO_LMM(__fw_name, __lmm_name) \
513*4882a593Smuzhiyun do { \
514*4882a593Smuzhiyun if (fw_caps & FW_PORT_CAP32_ ## __fw_name) \
515*4882a593Smuzhiyun SET_LMM(__lmm_name); \
516*4882a593Smuzhiyun } while (0)
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun switch (port_type) {
519*4882a593Smuzhiyun case FW_PORT_TYPE_BT_SGMII:
520*4882a593Smuzhiyun case FW_PORT_TYPE_BT_XFI:
521*4882a593Smuzhiyun case FW_PORT_TYPE_BT_XAUI:
522*4882a593Smuzhiyun SET_LMM(TP);
523*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_100M, 100baseT_Full);
524*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
525*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseT_Full);
526*4882a593Smuzhiyun break;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun case FW_PORT_TYPE_KX4:
529*4882a593Smuzhiyun case FW_PORT_TYPE_KX:
530*4882a593Smuzhiyun SET_LMM(Backplane);
531*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseKX_Full);
532*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKX4_Full);
533*4882a593Smuzhiyun break;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun case FW_PORT_TYPE_KR:
536*4882a593Smuzhiyun SET_LMM(Backplane);
537*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
538*4882a593Smuzhiyun break;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun case FW_PORT_TYPE_BP_AP:
541*4882a593Smuzhiyun SET_LMM(Backplane);
542*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseKX_Full);
543*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseR_FEC);
544*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
545*4882a593Smuzhiyun break;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun case FW_PORT_TYPE_BP4_AP:
548*4882a593Smuzhiyun SET_LMM(Backplane);
549*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseKX_Full);
550*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseR_FEC);
551*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
552*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKX4_Full);
553*4882a593Smuzhiyun break;
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun case FW_PORT_TYPE_FIBER_XFI:
556*4882a593Smuzhiyun case FW_PORT_TYPE_FIBER_XAUI:
557*4882a593Smuzhiyun case FW_PORT_TYPE_SFP:
558*4882a593Smuzhiyun case FW_PORT_TYPE_QSFP_10G:
559*4882a593Smuzhiyun case FW_PORT_TYPE_QSA:
560*4882a593Smuzhiyun SET_LMM(FIBRE);
561*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
562*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseT_Full);
563*4882a593Smuzhiyun break;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun case FW_PORT_TYPE_BP40_BA:
566*4882a593Smuzhiyun case FW_PORT_TYPE_QSFP:
567*4882a593Smuzhiyun SET_LMM(FIBRE);
568*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
569*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseT_Full);
570*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
571*4882a593Smuzhiyun break;
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun case FW_PORT_TYPE_CR_QSFP:
574*4882a593Smuzhiyun case FW_PORT_TYPE_SFP28:
575*4882a593Smuzhiyun SET_LMM(FIBRE);
576*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
577*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseT_Full);
578*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
579*4882a593Smuzhiyun break;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun case FW_PORT_TYPE_KR_SFP28:
582*4882a593Smuzhiyun SET_LMM(Backplane);
583*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
584*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
585*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_25G, 25000baseKR_Full);
586*4882a593Smuzhiyun break;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun case FW_PORT_TYPE_KR_XLAUI:
589*4882a593Smuzhiyun SET_LMM(Backplane);
590*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseKX_Full);
591*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
592*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_40G, 40000baseKR4_Full);
593*4882a593Smuzhiyun break;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun case FW_PORT_TYPE_CR2_QSFP:
596*4882a593Smuzhiyun SET_LMM(FIBRE);
597*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_50G, 50000baseSR2_Full);
598*4882a593Smuzhiyun break;
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun case FW_PORT_TYPE_KR4_100G:
601*4882a593Smuzhiyun case FW_PORT_TYPE_CR4_QSFP:
602*4882a593Smuzhiyun SET_LMM(FIBRE);
603*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
604*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
605*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_40G, 40000baseSR4_Full);
606*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
607*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_50G, 50000baseCR2_Full);
608*4882a593Smuzhiyun FW_CAPS_TO_LMM(SPEED_100G, 100000baseCR4_Full);
609*4882a593Smuzhiyun break;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun default:
612*4882a593Smuzhiyun break;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun if (fw_caps & FW_PORT_CAP32_FEC_V(FW_PORT_CAP32_FEC_M)) {
616*4882a593Smuzhiyun FW_CAPS_TO_LMM(FEC_RS, FEC_RS);
617*4882a593Smuzhiyun FW_CAPS_TO_LMM(FEC_BASER_RS, FEC_BASER);
618*4882a593Smuzhiyun } else {
619*4882a593Smuzhiyun SET_LMM(FEC_NONE);
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun FW_CAPS_TO_LMM(ANEG, Autoneg);
623*4882a593Smuzhiyun FW_CAPS_TO_LMM(802_3_PAUSE, Pause);
624*4882a593Smuzhiyun FW_CAPS_TO_LMM(802_3_ASM_DIR, Asym_Pause);
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun #undef FW_CAPS_TO_LMM
627*4882a593Smuzhiyun #undef SET_LMM
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun /**
631*4882a593Smuzhiyun * lmm_to_fw_caps - translate ethtool Link Mode Mask to Firmware
632*4882a593Smuzhiyun * capabilities
633*4882a593Smuzhiyun * @link_mode_mask: ethtool Link Mode Mask
634*4882a593Smuzhiyun *
635*4882a593Smuzhiyun * Translate ethtool Link Mode Mask into a Firmware Port capabilities
636*4882a593Smuzhiyun * value.
637*4882a593Smuzhiyun */
lmm_to_fw_caps(const unsigned long * link_mode_mask)638*4882a593Smuzhiyun static unsigned int lmm_to_fw_caps(const unsigned long *link_mode_mask)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun unsigned int fw_caps = 0;
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun #define LMM_TO_FW_CAPS(__lmm_name, __fw_name) \
643*4882a593Smuzhiyun do { \
644*4882a593Smuzhiyun if (test_bit(ETHTOOL_LINK_MODE_ ## __lmm_name ## _BIT, \
645*4882a593Smuzhiyun link_mode_mask)) \
646*4882a593Smuzhiyun fw_caps |= FW_PORT_CAP32_ ## __fw_name; \
647*4882a593Smuzhiyun } while (0)
648*4882a593Smuzhiyun
649*4882a593Smuzhiyun LMM_TO_FW_CAPS(100baseT_Full, SPEED_100M);
650*4882a593Smuzhiyun LMM_TO_FW_CAPS(1000baseT_Full, SPEED_1G);
651*4882a593Smuzhiyun LMM_TO_FW_CAPS(10000baseT_Full, SPEED_10G);
652*4882a593Smuzhiyun LMM_TO_FW_CAPS(40000baseSR4_Full, SPEED_40G);
653*4882a593Smuzhiyun LMM_TO_FW_CAPS(25000baseCR_Full, SPEED_25G);
654*4882a593Smuzhiyun LMM_TO_FW_CAPS(50000baseCR2_Full, SPEED_50G);
655*4882a593Smuzhiyun LMM_TO_FW_CAPS(100000baseCR4_Full, SPEED_100G);
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun #undef LMM_TO_FW_CAPS
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun return fw_caps;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * link_ksettings)662*4882a593Smuzhiyun static int get_link_ksettings(struct net_device *dev,
663*4882a593Smuzhiyun struct ethtool_link_ksettings *link_ksettings)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
666*4882a593Smuzhiyun struct ethtool_link_settings *base = &link_ksettings->base;
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* For the nonce, the Firmware doesn't send up Port State changes
669*4882a593Smuzhiyun * when the Virtual Interface attached to the Port is down. So
670*4882a593Smuzhiyun * if it's down, let's grab any changes.
671*4882a593Smuzhiyun */
672*4882a593Smuzhiyun if (!netif_running(dev))
673*4882a593Smuzhiyun (void)t4_update_port_info(pi);
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
676*4882a593Smuzhiyun ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
677*4882a593Smuzhiyun ethtool_link_ksettings_zero_link_mode(link_ksettings, lp_advertising);
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun base->port = from_fw_port_mod_type(pi->port_type, pi->mod_type);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun if (pi->mdio_addr >= 0) {
682*4882a593Smuzhiyun base->phy_address = pi->mdio_addr;
683*4882a593Smuzhiyun base->mdio_support = (pi->port_type == FW_PORT_TYPE_BT_SGMII
684*4882a593Smuzhiyun ? ETH_MDIO_SUPPORTS_C22
685*4882a593Smuzhiyun : ETH_MDIO_SUPPORTS_C45);
686*4882a593Smuzhiyun } else {
687*4882a593Smuzhiyun base->phy_address = 255;
688*4882a593Smuzhiyun base->mdio_support = 0;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
691*4882a593Smuzhiyun fw_caps_to_lmm(pi->port_type, pi->link_cfg.pcaps,
692*4882a593Smuzhiyun link_ksettings->link_modes.supported);
693*4882a593Smuzhiyun fw_caps_to_lmm(pi->port_type,
694*4882a593Smuzhiyun t4_link_acaps(pi->adapter,
695*4882a593Smuzhiyun pi->lport,
696*4882a593Smuzhiyun &pi->link_cfg),
697*4882a593Smuzhiyun link_ksettings->link_modes.advertising);
698*4882a593Smuzhiyun fw_caps_to_lmm(pi->port_type, pi->link_cfg.lpacaps,
699*4882a593Smuzhiyun link_ksettings->link_modes.lp_advertising);
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun base->speed = (netif_carrier_ok(dev)
702*4882a593Smuzhiyun ? pi->link_cfg.speed
703*4882a593Smuzhiyun : SPEED_UNKNOWN);
704*4882a593Smuzhiyun base->duplex = DUPLEX_FULL;
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun base->autoneg = pi->link_cfg.autoneg;
707*4882a593Smuzhiyun if (pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG)
708*4882a593Smuzhiyun ethtool_link_ksettings_add_link_mode(link_ksettings,
709*4882a593Smuzhiyun supported, Autoneg);
710*4882a593Smuzhiyun if (pi->link_cfg.autoneg)
711*4882a593Smuzhiyun ethtool_link_ksettings_add_link_mode(link_ksettings,
712*4882a593Smuzhiyun advertising, Autoneg);
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun return 0;
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun
set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * link_ksettings)717*4882a593Smuzhiyun static int set_link_ksettings(struct net_device *dev,
718*4882a593Smuzhiyun const struct ethtool_link_ksettings *link_ksettings)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
721*4882a593Smuzhiyun struct link_config *lc = &pi->link_cfg;
722*4882a593Smuzhiyun const struct ethtool_link_settings *base = &link_ksettings->base;
723*4882a593Smuzhiyun struct link_config old_lc;
724*4882a593Smuzhiyun unsigned int fw_caps;
725*4882a593Smuzhiyun int ret = 0;
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun /* only full-duplex supported */
728*4882a593Smuzhiyun if (base->duplex != DUPLEX_FULL)
729*4882a593Smuzhiyun return -EINVAL;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun old_lc = *lc;
732*4882a593Smuzhiyun if (!(lc->pcaps & FW_PORT_CAP32_ANEG) ||
733*4882a593Smuzhiyun base->autoneg == AUTONEG_DISABLE) {
734*4882a593Smuzhiyun fw_caps = speed_to_fw_caps(base->speed);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun /* Speed must be supported by Physical Port Capabilities. */
737*4882a593Smuzhiyun if (!(lc->pcaps & fw_caps))
738*4882a593Smuzhiyun return -EINVAL;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun lc->speed_caps = fw_caps;
741*4882a593Smuzhiyun lc->acaps = fw_caps;
742*4882a593Smuzhiyun } else {
743*4882a593Smuzhiyun fw_caps =
744*4882a593Smuzhiyun lmm_to_fw_caps(link_ksettings->link_modes.advertising);
745*4882a593Smuzhiyun if (!(lc->pcaps & fw_caps))
746*4882a593Smuzhiyun return -EINVAL;
747*4882a593Smuzhiyun lc->speed_caps = 0;
748*4882a593Smuzhiyun lc->acaps = fw_caps | FW_PORT_CAP32_ANEG;
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun lc->autoneg = base->autoneg;
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun /* If the firmware rejects the Link Configuration request, back out
753*4882a593Smuzhiyun * the changes and report the error.
754*4882a593Smuzhiyun */
755*4882a593Smuzhiyun ret = t4_link_l1cfg(pi->adapter, pi->adapter->mbox, pi->tx_chan, lc);
756*4882a593Smuzhiyun if (ret)
757*4882a593Smuzhiyun *lc = old_lc;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun return ret;
760*4882a593Smuzhiyun }
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun /* Translate the Firmware FEC value into the ethtool value. */
fwcap_to_eth_fec(unsigned int fw_fec)763*4882a593Smuzhiyun static inline unsigned int fwcap_to_eth_fec(unsigned int fw_fec)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun unsigned int eth_fec = 0;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun if (fw_fec & FW_PORT_CAP32_FEC_RS)
768*4882a593Smuzhiyun eth_fec |= ETHTOOL_FEC_RS;
769*4882a593Smuzhiyun if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
770*4882a593Smuzhiyun eth_fec |= ETHTOOL_FEC_BASER;
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun /* if nothing is set, then FEC is off */
773*4882a593Smuzhiyun if (!eth_fec)
774*4882a593Smuzhiyun eth_fec = ETHTOOL_FEC_OFF;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun return eth_fec;
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun /* Translate Common Code FEC value into ethtool value. */
cc_to_eth_fec(unsigned int cc_fec)780*4882a593Smuzhiyun static inline unsigned int cc_to_eth_fec(unsigned int cc_fec)
781*4882a593Smuzhiyun {
782*4882a593Smuzhiyun unsigned int eth_fec = 0;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun if (cc_fec & FEC_AUTO)
785*4882a593Smuzhiyun eth_fec |= ETHTOOL_FEC_AUTO;
786*4882a593Smuzhiyun if (cc_fec & FEC_RS)
787*4882a593Smuzhiyun eth_fec |= ETHTOOL_FEC_RS;
788*4882a593Smuzhiyun if (cc_fec & FEC_BASER_RS)
789*4882a593Smuzhiyun eth_fec |= ETHTOOL_FEC_BASER;
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun /* if nothing is set, then FEC is off */
792*4882a593Smuzhiyun if (!eth_fec)
793*4882a593Smuzhiyun eth_fec = ETHTOOL_FEC_OFF;
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun return eth_fec;
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* Translate ethtool FEC value into Common Code value. */
eth_to_cc_fec(unsigned int eth_fec)799*4882a593Smuzhiyun static inline unsigned int eth_to_cc_fec(unsigned int eth_fec)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun unsigned int cc_fec = 0;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun if (eth_fec & ETHTOOL_FEC_OFF)
804*4882a593Smuzhiyun return cc_fec;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun if (eth_fec & ETHTOOL_FEC_AUTO)
807*4882a593Smuzhiyun cc_fec |= FEC_AUTO;
808*4882a593Smuzhiyun if (eth_fec & ETHTOOL_FEC_RS)
809*4882a593Smuzhiyun cc_fec |= FEC_RS;
810*4882a593Smuzhiyun if (eth_fec & ETHTOOL_FEC_BASER)
811*4882a593Smuzhiyun cc_fec |= FEC_BASER_RS;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun return cc_fec;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
get_fecparam(struct net_device * dev,struct ethtool_fecparam * fec)816*4882a593Smuzhiyun static int get_fecparam(struct net_device *dev, struct ethtool_fecparam *fec)
817*4882a593Smuzhiyun {
818*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
819*4882a593Smuzhiyun const struct link_config *lc = &pi->link_cfg;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun /* Translate the Firmware FEC Support into the ethtool value. We
822*4882a593Smuzhiyun * always support IEEE 802.3 "automatic" selection of Link FEC type if
823*4882a593Smuzhiyun * any FEC is supported.
824*4882a593Smuzhiyun */
825*4882a593Smuzhiyun fec->fec = fwcap_to_eth_fec(lc->pcaps);
826*4882a593Smuzhiyun if (fec->fec != ETHTOOL_FEC_OFF)
827*4882a593Smuzhiyun fec->fec |= ETHTOOL_FEC_AUTO;
828*4882a593Smuzhiyun
829*4882a593Smuzhiyun /* Translate the current internal FEC parameters into the
830*4882a593Smuzhiyun * ethtool values.
831*4882a593Smuzhiyun */
832*4882a593Smuzhiyun fec->active_fec = cc_to_eth_fec(lc->fec);
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun return 0;
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun
set_fecparam(struct net_device * dev,struct ethtool_fecparam * fec)837*4882a593Smuzhiyun static int set_fecparam(struct net_device *dev, struct ethtool_fecparam *fec)
838*4882a593Smuzhiyun {
839*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
840*4882a593Smuzhiyun struct link_config *lc = &pi->link_cfg;
841*4882a593Smuzhiyun struct link_config old_lc;
842*4882a593Smuzhiyun int ret;
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun /* Save old Link Configuration in case the L1 Configure below
845*4882a593Smuzhiyun * fails.
846*4882a593Smuzhiyun */
847*4882a593Smuzhiyun old_lc = *lc;
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun /* Try to perform the L1 Configure and return the result of that
850*4882a593Smuzhiyun * effort. If it fails, revert the attempted change.
851*4882a593Smuzhiyun */
852*4882a593Smuzhiyun lc->requested_fec = eth_to_cc_fec(fec->fec);
853*4882a593Smuzhiyun ret = t4_link_l1cfg(pi->adapter, pi->adapter->mbox,
854*4882a593Smuzhiyun pi->tx_chan, lc);
855*4882a593Smuzhiyun if (ret)
856*4882a593Smuzhiyun *lc = old_lc;
857*4882a593Smuzhiyun return ret;
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
get_pauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)860*4882a593Smuzhiyun static void get_pauseparam(struct net_device *dev,
861*4882a593Smuzhiyun struct ethtool_pauseparam *epause)
862*4882a593Smuzhiyun {
863*4882a593Smuzhiyun struct port_info *p = netdev_priv(dev);
864*4882a593Smuzhiyun
865*4882a593Smuzhiyun epause->autoneg = (p->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
866*4882a593Smuzhiyun epause->rx_pause = (p->link_cfg.advertised_fc & PAUSE_RX) != 0;
867*4882a593Smuzhiyun epause->tx_pause = (p->link_cfg.advertised_fc & PAUSE_TX) != 0;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun
set_pauseparam(struct net_device * dev,struct ethtool_pauseparam * epause)870*4882a593Smuzhiyun static int set_pauseparam(struct net_device *dev,
871*4882a593Smuzhiyun struct ethtool_pauseparam *epause)
872*4882a593Smuzhiyun {
873*4882a593Smuzhiyun struct port_info *p = netdev_priv(dev);
874*4882a593Smuzhiyun struct link_config *lc = &p->link_cfg;
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun if (epause->autoneg == AUTONEG_DISABLE)
877*4882a593Smuzhiyun lc->requested_fc = 0;
878*4882a593Smuzhiyun else if (lc->pcaps & FW_PORT_CAP32_ANEG)
879*4882a593Smuzhiyun lc->requested_fc = PAUSE_AUTONEG;
880*4882a593Smuzhiyun else
881*4882a593Smuzhiyun return -EINVAL;
882*4882a593Smuzhiyun
883*4882a593Smuzhiyun if (epause->rx_pause)
884*4882a593Smuzhiyun lc->requested_fc |= PAUSE_RX;
885*4882a593Smuzhiyun if (epause->tx_pause)
886*4882a593Smuzhiyun lc->requested_fc |= PAUSE_TX;
887*4882a593Smuzhiyun if (netif_running(dev))
888*4882a593Smuzhiyun return t4_link_l1cfg(p->adapter, p->adapter->mbox, p->tx_chan,
889*4882a593Smuzhiyun lc);
890*4882a593Smuzhiyun return 0;
891*4882a593Smuzhiyun }
892*4882a593Smuzhiyun
get_sge_param(struct net_device * dev,struct ethtool_ringparam * e)893*4882a593Smuzhiyun static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
894*4882a593Smuzhiyun {
895*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
896*4882a593Smuzhiyun const struct sge *s = &pi->adapter->sge;
897*4882a593Smuzhiyun
898*4882a593Smuzhiyun e->rx_max_pending = MAX_RX_BUFFERS;
899*4882a593Smuzhiyun e->rx_mini_max_pending = MAX_RSPQ_ENTRIES;
900*4882a593Smuzhiyun e->rx_jumbo_max_pending = 0;
901*4882a593Smuzhiyun e->tx_max_pending = MAX_TXQ_ENTRIES;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun e->rx_pending = s->ethrxq[pi->first_qset].fl.size - 8;
904*4882a593Smuzhiyun e->rx_mini_pending = s->ethrxq[pi->first_qset].rspq.size;
905*4882a593Smuzhiyun e->rx_jumbo_pending = 0;
906*4882a593Smuzhiyun e->tx_pending = s->ethtxq[pi->first_qset].q.size;
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun
set_sge_param(struct net_device * dev,struct ethtool_ringparam * e)909*4882a593Smuzhiyun static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun int i;
912*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
913*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
914*4882a593Smuzhiyun struct sge *s = &adapter->sge;
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun if (e->rx_pending > MAX_RX_BUFFERS || e->rx_jumbo_pending ||
917*4882a593Smuzhiyun e->tx_pending > MAX_TXQ_ENTRIES ||
918*4882a593Smuzhiyun e->rx_mini_pending > MAX_RSPQ_ENTRIES ||
919*4882a593Smuzhiyun e->rx_mini_pending < MIN_RSPQ_ENTRIES ||
920*4882a593Smuzhiyun e->rx_pending < MIN_FL_ENTRIES || e->tx_pending < MIN_TXQ_ENTRIES)
921*4882a593Smuzhiyun return -EINVAL;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun if (adapter->flags & CXGB4_FULL_INIT_DONE)
924*4882a593Smuzhiyun return -EBUSY;
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun for (i = 0; i < pi->nqsets; ++i) {
927*4882a593Smuzhiyun s->ethtxq[pi->first_qset + i].q.size = e->tx_pending;
928*4882a593Smuzhiyun s->ethrxq[pi->first_qset + i].fl.size = e->rx_pending + 8;
929*4882a593Smuzhiyun s->ethrxq[pi->first_qset + i].rspq.size = e->rx_mini_pending;
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun return 0;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun /**
935*4882a593Smuzhiyun * set_rx_intr_params - set a net devices's RX interrupt holdoff paramete!
936*4882a593Smuzhiyun * @dev: the network device
937*4882a593Smuzhiyun * @us: the hold-off time in us, or 0 to disable timer
938*4882a593Smuzhiyun * @cnt: the hold-off packet count, or 0 to disable counter
939*4882a593Smuzhiyun *
940*4882a593Smuzhiyun * Set the RX interrupt hold-off parameters for a network device.
941*4882a593Smuzhiyun */
set_rx_intr_params(struct net_device * dev,unsigned int us,unsigned int cnt)942*4882a593Smuzhiyun static int set_rx_intr_params(struct net_device *dev,
943*4882a593Smuzhiyun unsigned int us, unsigned int cnt)
944*4882a593Smuzhiyun {
945*4882a593Smuzhiyun int i, err;
946*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
947*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
948*4882a593Smuzhiyun struct sge_eth_rxq *q = &adap->sge.ethrxq[pi->first_qset];
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun for (i = 0; i < pi->nqsets; i++, q++) {
951*4882a593Smuzhiyun err = cxgb4_set_rspq_intr_params(&q->rspq, us, cnt);
952*4882a593Smuzhiyun if (err)
953*4882a593Smuzhiyun return err;
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun return 0;
956*4882a593Smuzhiyun }
957*4882a593Smuzhiyun
set_adaptive_rx_setting(struct net_device * dev,int adaptive_rx)958*4882a593Smuzhiyun static int set_adaptive_rx_setting(struct net_device *dev, int adaptive_rx)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun int i;
961*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
962*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
963*4882a593Smuzhiyun struct sge_eth_rxq *q = &adap->sge.ethrxq[pi->first_qset];
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun for (i = 0; i < pi->nqsets; i++, q++)
966*4882a593Smuzhiyun q->rspq.adaptive_rx = adaptive_rx;
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun return 0;
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
get_adaptive_rx_setting(struct net_device * dev)971*4882a593Smuzhiyun static int get_adaptive_rx_setting(struct net_device *dev)
972*4882a593Smuzhiyun {
973*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
974*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
975*4882a593Smuzhiyun struct sge_eth_rxq *q = &adap->sge.ethrxq[pi->first_qset];
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun return q->rspq.adaptive_rx;
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun /* Return the current global Adapter SGE Doorbell Queue Timer Tick for all
981*4882a593Smuzhiyun * Ethernet TX Queues.
982*4882a593Smuzhiyun */
get_dbqtimer_tick(struct net_device * dev)983*4882a593Smuzhiyun static int get_dbqtimer_tick(struct net_device *dev)
984*4882a593Smuzhiyun {
985*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
986*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
989*4882a593Smuzhiyun return 0;
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun return adap->sge.dbqtimer_tick;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun /* Return the SGE Doorbell Queue Timer Value for the Ethernet TX Queues
995*4882a593Smuzhiyun * associated with a Network Device.
996*4882a593Smuzhiyun */
get_dbqtimer(struct net_device * dev)997*4882a593Smuzhiyun static int get_dbqtimer(struct net_device *dev)
998*4882a593Smuzhiyun {
999*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1000*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
1001*4882a593Smuzhiyun struct sge_eth_txq *txq;
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun txq = &adap->sge.ethtxq[pi->first_qset];
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
1006*4882a593Smuzhiyun return 0;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun /* all of the TX Queues use the same Timer Index */
1009*4882a593Smuzhiyun return adap->sge.dbqtimer_val[txq->dbqtimerix];
1010*4882a593Smuzhiyun }
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun /* Set the global Adapter SGE Doorbell Queue Timer Tick for all Ethernet TX
1013*4882a593Smuzhiyun * Queues. This is the fundamental "Tick" that sets the scale of values which
1014*4882a593Smuzhiyun * can be used. Individual Ethernet TX Queues index into a relatively small
1015*4882a593Smuzhiyun * array of Tick Multipliers. Changing the base Tick will thus change all of
1016*4882a593Smuzhiyun * the resulting Timer Values associated with those multipliers for all
1017*4882a593Smuzhiyun * Ethernet TX Queues.
1018*4882a593Smuzhiyun */
set_dbqtimer_tick(struct net_device * dev,int usecs)1019*4882a593Smuzhiyun static int set_dbqtimer_tick(struct net_device *dev, int usecs)
1020*4882a593Smuzhiyun {
1021*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1022*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
1023*4882a593Smuzhiyun struct sge *s = &adap->sge;
1024*4882a593Smuzhiyun u32 param, val;
1025*4882a593Smuzhiyun int ret;
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
1028*4882a593Smuzhiyun return 0;
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun /* return early if it's the same Timer Tick we're already using */
1031*4882a593Smuzhiyun if (s->dbqtimer_tick == usecs)
1032*4882a593Smuzhiyun return 0;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun /* attempt to set the new Timer Tick value */
1035*4882a593Smuzhiyun param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
1036*4882a593Smuzhiyun FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMERTICK));
1037*4882a593Smuzhiyun val = usecs;
1038*4882a593Smuzhiyun ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val);
1039*4882a593Smuzhiyun if (ret)
1040*4882a593Smuzhiyun return ret;
1041*4882a593Smuzhiyun s->dbqtimer_tick = usecs;
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun /* if successful, reread resulting dependent Timer values */
1044*4882a593Smuzhiyun ret = t4_read_sge_dbqtimers(adap, ARRAY_SIZE(s->dbqtimer_val),
1045*4882a593Smuzhiyun s->dbqtimer_val);
1046*4882a593Smuzhiyun return ret;
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun /* Set the SGE Doorbell Queue Timer Value for the Ethernet TX Queues
1050*4882a593Smuzhiyun * associated with a Network Device. There is a relatively small array of
1051*4882a593Smuzhiyun * possible Timer Values so we need to pick the closest value available.
1052*4882a593Smuzhiyun */
set_dbqtimer(struct net_device * dev,int usecs)1053*4882a593Smuzhiyun static int set_dbqtimer(struct net_device *dev, int usecs)
1054*4882a593Smuzhiyun {
1055*4882a593Smuzhiyun int qix, timerix, min_timerix, delta, min_delta;
1056*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1057*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
1058*4882a593Smuzhiyun struct sge *s = &adap->sge;
1059*4882a593Smuzhiyun struct sge_eth_txq *txq;
1060*4882a593Smuzhiyun u32 param, val;
1061*4882a593Smuzhiyun int ret;
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun if (!(adap->flags & CXGB4_SGE_DBQ_TIMER))
1064*4882a593Smuzhiyun return 0;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun /* Find the SGE Doorbell Timer Value that's closest to the requested
1067*4882a593Smuzhiyun * value.
1068*4882a593Smuzhiyun */
1069*4882a593Smuzhiyun min_delta = INT_MAX;
1070*4882a593Smuzhiyun min_timerix = 0;
1071*4882a593Smuzhiyun for (timerix = 0; timerix < ARRAY_SIZE(s->dbqtimer_val); timerix++) {
1072*4882a593Smuzhiyun delta = s->dbqtimer_val[timerix] - usecs;
1073*4882a593Smuzhiyun if (delta < 0)
1074*4882a593Smuzhiyun delta = -delta;
1075*4882a593Smuzhiyun if (delta < min_delta) {
1076*4882a593Smuzhiyun min_delta = delta;
1077*4882a593Smuzhiyun min_timerix = timerix;
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun /* Return early if it's the same Timer Index we're already using.
1082*4882a593Smuzhiyun * We use the same Timer Index for all of the TX Queues for an
1083*4882a593Smuzhiyun * interface so it's only necessary to check the first one.
1084*4882a593Smuzhiyun */
1085*4882a593Smuzhiyun txq = &s->ethtxq[pi->first_qset];
1086*4882a593Smuzhiyun if (txq->dbqtimerix == min_timerix)
1087*4882a593Smuzhiyun return 0;
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun for (qix = 0; qix < pi->nqsets; qix++, txq++) {
1090*4882a593Smuzhiyun if (adap->flags & CXGB4_FULL_INIT_DONE) {
1091*4882a593Smuzhiyun param =
1092*4882a593Smuzhiyun (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) |
1093*4882a593Smuzhiyun FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DMAQ_EQ_TIMERIX) |
1094*4882a593Smuzhiyun FW_PARAMS_PARAM_YZ_V(txq->q.cntxt_id));
1095*4882a593Smuzhiyun val = min_timerix;
1096*4882a593Smuzhiyun ret = t4_set_params(adap, adap->mbox, adap->pf, 0,
1097*4882a593Smuzhiyun 1, ¶m, &val);
1098*4882a593Smuzhiyun if (ret)
1099*4882a593Smuzhiyun return ret;
1100*4882a593Smuzhiyun }
1101*4882a593Smuzhiyun txq->dbqtimerix = min_timerix;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun return 0;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun /* Set the global Adapter SGE Doorbell Queue Timer Tick for all Ethernet TX
1107*4882a593Smuzhiyun * Queues and the Timer Value for the Ethernet TX Queues associated with a
1108*4882a593Smuzhiyun * Network Device. Since changing the global Tick changes all of the
1109*4882a593Smuzhiyun * available Timer Values, we need to do this first before selecting the
1110*4882a593Smuzhiyun * resulting closest Timer Value. Moreover, since the Tick is global,
1111*4882a593Smuzhiyun * changing it affects the Timer Values for all Network Devices on the
1112*4882a593Smuzhiyun * adapter. So, before changing the Tick, we grab all of the current Timer
1113*4882a593Smuzhiyun * Values for other Network Devices on this Adapter and then attempt to select
1114*4882a593Smuzhiyun * new Timer Values which are close to the old values ...
1115*4882a593Smuzhiyun */
set_dbqtimer_tickval(struct net_device * dev,int tick_usecs,int timer_usecs)1116*4882a593Smuzhiyun static int set_dbqtimer_tickval(struct net_device *dev,
1117*4882a593Smuzhiyun int tick_usecs, int timer_usecs)
1118*4882a593Smuzhiyun {
1119*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1120*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
1121*4882a593Smuzhiyun int timer[MAX_NPORTS];
1122*4882a593Smuzhiyun unsigned int port;
1123*4882a593Smuzhiyun int ret;
1124*4882a593Smuzhiyun
1125*4882a593Smuzhiyun /* Grab the other adapter Network Interface current timers and fill in
1126*4882a593Smuzhiyun * the new one for this Network Interface.
1127*4882a593Smuzhiyun */
1128*4882a593Smuzhiyun for_each_port(adap, port)
1129*4882a593Smuzhiyun if (port == pi->port_id)
1130*4882a593Smuzhiyun timer[port] = timer_usecs;
1131*4882a593Smuzhiyun else
1132*4882a593Smuzhiyun timer[port] = get_dbqtimer(adap->port[port]);
1133*4882a593Smuzhiyun
1134*4882a593Smuzhiyun /* Change the global Tick first ... */
1135*4882a593Smuzhiyun ret = set_dbqtimer_tick(dev, tick_usecs);
1136*4882a593Smuzhiyun if (ret)
1137*4882a593Smuzhiyun return ret;
1138*4882a593Smuzhiyun
1139*4882a593Smuzhiyun /* ... and then set all of the Network Interface Timer Values ... */
1140*4882a593Smuzhiyun for_each_port(adap, port) {
1141*4882a593Smuzhiyun ret = set_dbqtimer(adap->port[port], timer[port]);
1142*4882a593Smuzhiyun if (ret)
1143*4882a593Smuzhiyun return ret;
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun
1146*4882a593Smuzhiyun return 0;
1147*4882a593Smuzhiyun }
1148*4882a593Smuzhiyun
set_coalesce(struct net_device * dev,struct ethtool_coalesce * coalesce)1149*4882a593Smuzhiyun static int set_coalesce(struct net_device *dev,
1150*4882a593Smuzhiyun struct ethtool_coalesce *coalesce)
1151*4882a593Smuzhiyun {
1152*4882a593Smuzhiyun int ret;
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun set_adaptive_rx_setting(dev, coalesce->use_adaptive_rx_coalesce);
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun ret = set_rx_intr_params(dev, coalesce->rx_coalesce_usecs,
1157*4882a593Smuzhiyun coalesce->rx_max_coalesced_frames);
1158*4882a593Smuzhiyun if (ret)
1159*4882a593Smuzhiyun return ret;
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun return set_dbqtimer_tickval(dev,
1162*4882a593Smuzhiyun coalesce->tx_coalesce_usecs_irq,
1163*4882a593Smuzhiyun coalesce->tx_coalesce_usecs);
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun
get_coalesce(struct net_device * dev,struct ethtool_coalesce * c)1166*4882a593Smuzhiyun static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
1167*4882a593Smuzhiyun {
1168*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
1169*4882a593Smuzhiyun const struct adapter *adap = pi->adapter;
1170*4882a593Smuzhiyun const struct sge_rspq *rq = &adap->sge.ethrxq[pi->first_qset].rspq;
1171*4882a593Smuzhiyun
1172*4882a593Smuzhiyun c->rx_coalesce_usecs = qtimer_val(adap, rq);
1173*4882a593Smuzhiyun c->rx_max_coalesced_frames = (rq->intr_params & QINTR_CNT_EN_F) ?
1174*4882a593Smuzhiyun adap->sge.counter_val[rq->pktcnt_idx] : 0;
1175*4882a593Smuzhiyun c->use_adaptive_rx_coalesce = get_adaptive_rx_setting(dev);
1176*4882a593Smuzhiyun c->tx_coalesce_usecs_irq = get_dbqtimer_tick(dev);
1177*4882a593Smuzhiyun c->tx_coalesce_usecs = get_dbqtimer(dev);
1178*4882a593Smuzhiyun return 0;
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun /* The next two routines implement eeprom read/write from physical addresses.
1182*4882a593Smuzhiyun */
eeprom_rd_phys(struct adapter * adap,unsigned int phys_addr,u32 * v)1183*4882a593Smuzhiyun static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
1184*4882a593Smuzhiyun {
1185*4882a593Smuzhiyun int vaddr = t4_eeprom_ptov(phys_addr, adap->pf, EEPROMPFSIZE);
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun if (vaddr >= 0)
1188*4882a593Smuzhiyun vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v);
1189*4882a593Smuzhiyun return vaddr < 0 ? vaddr : 0;
1190*4882a593Smuzhiyun }
1191*4882a593Smuzhiyun
eeprom_wr_phys(struct adapter * adap,unsigned int phys_addr,u32 v)1192*4882a593Smuzhiyun static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
1193*4882a593Smuzhiyun {
1194*4882a593Smuzhiyun int vaddr = t4_eeprom_ptov(phys_addr, adap->pf, EEPROMPFSIZE);
1195*4882a593Smuzhiyun
1196*4882a593Smuzhiyun if (vaddr >= 0)
1197*4882a593Smuzhiyun vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v);
1198*4882a593Smuzhiyun return vaddr < 0 ? vaddr : 0;
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun #define EEPROM_MAGIC 0x38E2F10C
1202*4882a593Smuzhiyun
get_eeprom(struct net_device * dev,struct ethtool_eeprom * e,u8 * data)1203*4882a593Smuzhiyun static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
1204*4882a593Smuzhiyun u8 *data)
1205*4882a593Smuzhiyun {
1206*4882a593Smuzhiyun int i, err = 0;
1207*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
1208*4882a593Smuzhiyun u8 *buf = kvzalloc(EEPROMSIZE, GFP_KERNEL);
1209*4882a593Smuzhiyun
1210*4882a593Smuzhiyun if (!buf)
1211*4882a593Smuzhiyun return -ENOMEM;
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun e->magic = EEPROM_MAGIC;
1214*4882a593Smuzhiyun for (i = e->offset & ~3; !err && i < e->offset + e->len; i += 4)
1215*4882a593Smuzhiyun err = eeprom_rd_phys(adapter, i, (u32 *)&buf[i]);
1216*4882a593Smuzhiyun
1217*4882a593Smuzhiyun if (!err)
1218*4882a593Smuzhiyun memcpy(data, buf + e->offset, e->len);
1219*4882a593Smuzhiyun kvfree(buf);
1220*4882a593Smuzhiyun return err;
1221*4882a593Smuzhiyun }
1222*4882a593Smuzhiyun
set_eeprom(struct net_device * dev,struct ethtool_eeprom * eeprom,u8 * data)1223*4882a593Smuzhiyun static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
1224*4882a593Smuzhiyun u8 *data)
1225*4882a593Smuzhiyun {
1226*4882a593Smuzhiyun u8 *buf;
1227*4882a593Smuzhiyun int err = 0;
1228*4882a593Smuzhiyun u32 aligned_offset, aligned_len, *p;
1229*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun if (eeprom->magic != EEPROM_MAGIC)
1232*4882a593Smuzhiyun return -EINVAL;
1233*4882a593Smuzhiyun
1234*4882a593Smuzhiyun aligned_offset = eeprom->offset & ~3;
1235*4882a593Smuzhiyun aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun if (adapter->pf > 0) {
1238*4882a593Smuzhiyun u32 start = 1024 + adapter->pf * EEPROMPFSIZE;
1239*4882a593Smuzhiyun
1240*4882a593Smuzhiyun if (aligned_offset < start ||
1241*4882a593Smuzhiyun aligned_offset + aligned_len > start + EEPROMPFSIZE)
1242*4882a593Smuzhiyun return -EPERM;
1243*4882a593Smuzhiyun }
1244*4882a593Smuzhiyun
1245*4882a593Smuzhiyun if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
1246*4882a593Smuzhiyun /* RMW possibly needed for first or last words.
1247*4882a593Smuzhiyun */
1248*4882a593Smuzhiyun buf = kvzalloc(aligned_len, GFP_KERNEL);
1249*4882a593Smuzhiyun if (!buf)
1250*4882a593Smuzhiyun return -ENOMEM;
1251*4882a593Smuzhiyun err = eeprom_rd_phys(adapter, aligned_offset, (u32 *)buf);
1252*4882a593Smuzhiyun if (!err && aligned_len > 4)
1253*4882a593Smuzhiyun err = eeprom_rd_phys(adapter,
1254*4882a593Smuzhiyun aligned_offset + aligned_len - 4,
1255*4882a593Smuzhiyun (u32 *)&buf[aligned_len - 4]);
1256*4882a593Smuzhiyun if (err)
1257*4882a593Smuzhiyun goto out;
1258*4882a593Smuzhiyun memcpy(buf + (eeprom->offset & 3), data, eeprom->len);
1259*4882a593Smuzhiyun } else {
1260*4882a593Smuzhiyun buf = data;
1261*4882a593Smuzhiyun }
1262*4882a593Smuzhiyun
1263*4882a593Smuzhiyun err = t4_seeprom_wp(adapter, false);
1264*4882a593Smuzhiyun if (err)
1265*4882a593Smuzhiyun goto out;
1266*4882a593Smuzhiyun
1267*4882a593Smuzhiyun for (p = (u32 *)buf; !err && aligned_len; aligned_len -= 4, p++) {
1268*4882a593Smuzhiyun err = eeprom_wr_phys(adapter, aligned_offset, *p);
1269*4882a593Smuzhiyun aligned_offset += 4;
1270*4882a593Smuzhiyun }
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun if (!err)
1273*4882a593Smuzhiyun err = t4_seeprom_wp(adapter, true);
1274*4882a593Smuzhiyun out:
1275*4882a593Smuzhiyun if (buf != data)
1276*4882a593Smuzhiyun kvfree(buf);
1277*4882a593Smuzhiyun return err;
1278*4882a593Smuzhiyun }
1279*4882a593Smuzhiyun
cxgb4_ethtool_flash_bootcfg(struct net_device * netdev,const u8 * data,u32 size)1280*4882a593Smuzhiyun static int cxgb4_ethtool_flash_bootcfg(struct net_device *netdev,
1281*4882a593Smuzhiyun const u8 *data, u32 size)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun struct adapter *adap = netdev2adap(netdev);
1284*4882a593Smuzhiyun int ret;
1285*4882a593Smuzhiyun
1286*4882a593Smuzhiyun ret = t4_load_bootcfg(adap, data, size);
1287*4882a593Smuzhiyun if (ret)
1288*4882a593Smuzhiyun dev_err(adap->pdev_dev, "Failed to load boot cfg image\n");
1289*4882a593Smuzhiyun
1290*4882a593Smuzhiyun return ret;
1291*4882a593Smuzhiyun }
1292*4882a593Smuzhiyun
cxgb4_ethtool_flash_boot(struct net_device * netdev,const u8 * bdata,u32 size)1293*4882a593Smuzhiyun static int cxgb4_ethtool_flash_boot(struct net_device *netdev,
1294*4882a593Smuzhiyun const u8 *bdata, u32 size)
1295*4882a593Smuzhiyun {
1296*4882a593Smuzhiyun struct adapter *adap = netdev2adap(netdev);
1297*4882a593Smuzhiyun unsigned int offset;
1298*4882a593Smuzhiyun u8 *data;
1299*4882a593Smuzhiyun int ret;
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun data = kmemdup(bdata, size, GFP_KERNEL);
1302*4882a593Smuzhiyun if (!data)
1303*4882a593Smuzhiyun return -ENOMEM;
1304*4882a593Smuzhiyun
1305*4882a593Smuzhiyun offset = OFFSET_G(t4_read_reg(adap, PF_REG(0, PCIE_PF_EXPROM_OFST_A)));
1306*4882a593Smuzhiyun
1307*4882a593Smuzhiyun ret = t4_load_boot(adap, data, offset, size);
1308*4882a593Smuzhiyun if (ret)
1309*4882a593Smuzhiyun dev_err(adap->pdev_dev, "Failed to load boot image\n");
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun kfree(data);
1312*4882a593Smuzhiyun return ret;
1313*4882a593Smuzhiyun }
1314*4882a593Smuzhiyun
1315*4882a593Smuzhiyun #define CXGB4_PHY_SIG 0x130000ea
1316*4882a593Smuzhiyun
cxgb4_validate_phy_image(const u8 * data,u32 * size)1317*4882a593Smuzhiyun static int cxgb4_validate_phy_image(const u8 *data, u32 *size)
1318*4882a593Smuzhiyun {
1319*4882a593Smuzhiyun struct cxgb4_fw_data *header;
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun header = (struct cxgb4_fw_data *)data;
1322*4882a593Smuzhiyun if (be32_to_cpu(header->signature) != CXGB4_PHY_SIG)
1323*4882a593Smuzhiyun return -EINVAL;
1324*4882a593Smuzhiyun
1325*4882a593Smuzhiyun return 0;
1326*4882a593Smuzhiyun }
1327*4882a593Smuzhiyun
cxgb4_ethtool_flash_phy(struct net_device * netdev,const u8 * data,u32 size)1328*4882a593Smuzhiyun static int cxgb4_ethtool_flash_phy(struct net_device *netdev,
1329*4882a593Smuzhiyun const u8 *data, u32 size)
1330*4882a593Smuzhiyun {
1331*4882a593Smuzhiyun struct adapter *adap = netdev2adap(netdev);
1332*4882a593Smuzhiyun int ret;
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun ret = cxgb4_validate_phy_image(data, NULL);
1335*4882a593Smuzhiyun if (ret) {
1336*4882a593Smuzhiyun dev_err(adap->pdev_dev, "PHY signature mismatch\n");
1337*4882a593Smuzhiyun return ret;
1338*4882a593Smuzhiyun }
1339*4882a593Smuzhiyun
1340*4882a593Smuzhiyun /* We have to RESET the chip/firmware because we need the
1341*4882a593Smuzhiyun * chip in uninitialized state for loading new PHY image.
1342*4882a593Smuzhiyun * Otherwise, the running firmware will only store the PHY
1343*4882a593Smuzhiyun * image in local RAM which will be lost after next reset.
1344*4882a593Smuzhiyun */
1345*4882a593Smuzhiyun ret = t4_fw_reset(adap, adap->mbox, PIORSTMODE_F | PIORST_F);
1346*4882a593Smuzhiyun if (ret < 0) {
1347*4882a593Smuzhiyun dev_err(adap->pdev_dev,
1348*4882a593Smuzhiyun "Set FW to RESET for flashing PHY FW failed. ret: %d\n",
1349*4882a593Smuzhiyun ret);
1350*4882a593Smuzhiyun return ret;
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun
1353*4882a593Smuzhiyun ret = t4_load_phy_fw(adap, MEMWIN_NIC, NULL, data, size);
1354*4882a593Smuzhiyun if (ret < 0) {
1355*4882a593Smuzhiyun dev_err(adap->pdev_dev, "Failed to load PHY FW. ret: %d\n",
1356*4882a593Smuzhiyun ret);
1357*4882a593Smuzhiyun return ret;
1358*4882a593Smuzhiyun }
1359*4882a593Smuzhiyun
1360*4882a593Smuzhiyun return 0;
1361*4882a593Smuzhiyun }
1362*4882a593Smuzhiyun
cxgb4_ethtool_flash_fw(struct net_device * netdev,const u8 * data,u32 size)1363*4882a593Smuzhiyun static int cxgb4_ethtool_flash_fw(struct net_device *netdev,
1364*4882a593Smuzhiyun const u8 *data, u32 size)
1365*4882a593Smuzhiyun {
1366*4882a593Smuzhiyun struct adapter *adap = netdev2adap(netdev);
1367*4882a593Smuzhiyun unsigned int mbox = PCIE_FW_MASTER_M + 1;
1368*4882a593Smuzhiyun int ret;
1369*4882a593Smuzhiyun
1370*4882a593Smuzhiyun /* If the adapter has been fully initialized then we'll go ahead and
1371*4882a593Smuzhiyun * try to get the firmware's cooperation in upgrading to the new
1372*4882a593Smuzhiyun * firmware image otherwise we'll try to do the entire job from the
1373*4882a593Smuzhiyun * host ... and we always "force" the operation in this path.
1374*4882a593Smuzhiyun */
1375*4882a593Smuzhiyun if (adap->flags & CXGB4_FULL_INIT_DONE)
1376*4882a593Smuzhiyun mbox = adap->mbox;
1377*4882a593Smuzhiyun
1378*4882a593Smuzhiyun ret = t4_fw_upgrade(adap, mbox, data, size, 1);
1379*4882a593Smuzhiyun if (ret)
1380*4882a593Smuzhiyun dev_err(adap->pdev_dev,
1381*4882a593Smuzhiyun "Failed to flash firmware\n");
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun return ret;
1384*4882a593Smuzhiyun }
1385*4882a593Smuzhiyun
cxgb4_ethtool_flash_region(struct net_device * netdev,const u8 * data,u32 size,u32 region)1386*4882a593Smuzhiyun static int cxgb4_ethtool_flash_region(struct net_device *netdev,
1387*4882a593Smuzhiyun const u8 *data, u32 size, u32 region)
1388*4882a593Smuzhiyun {
1389*4882a593Smuzhiyun struct adapter *adap = netdev2adap(netdev);
1390*4882a593Smuzhiyun int ret;
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun switch (region) {
1393*4882a593Smuzhiyun case CXGB4_ETHTOOL_FLASH_FW:
1394*4882a593Smuzhiyun ret = cxgb4_ethtool_flash_fw(netdev, data, size);
1395*4882a593Smuzhiyun break;
1396*4882a593Smuzhiyun case CXGB4_ETHTOOL_FLASH_PHY:
1397*4882a593Smuzhiyun ret = cxgb4_ethtool_flash_phy(netdev, data, size);
1398*4882a593Smuzhiyun break;
1399*4882a593Smuzhiyun case CXGB4_ETHTOOL_FLASH_BOOT:
1400*4882a593Smuzhiyun ret = cxgb4_ethtool_flash_boot(netdev, data, size);
1401*4882a593Smuzhiyun break;
1402*4882a593Smuzhiyun case CXGB4_ETHTOOL_FLASH_BOOTCFG:
1403*4882a593Smuzhiyun ret = cxgb4_ethtool_flash_bootcfg(netdev, data, size);
1404*4882a593Smuzhiyun break;
1405*4882a593Smuzhiyun default:
1406*4882a593Smuzhiyun ret = -EOPNOTSUPP;
1407*4882a593Smuzhiyun break;
1408*4882a593Smuzhiyun }
1409*4882a593Smuzhiyun
1410*4882a593Smuzhiyun if (!ret)
1411*4882a593Smuzhiyun dev_info(adap->pdev_dev,
1412*4882a593Smuzhiyun "loading %s successful, reload cxgb4 driver\n",
1413*4882a593Smuzhiyun flash_region_strings[region]);
1414*4882a593Smuzhiyun return ret;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun #define CXGB4_FW_SIG 0x4368656c
1418*4882a593Smuzhiyun #define CXGB4_FW_SIG_OFFSET 0x160
1419*4882a593Smuzhiyun
cxgb4_validate_fw_image(const u8 * data,u32 * size)1420*4882a593Smuzhiyun static int cxgb4_validate_fw_image(const u8 *data, u32 *size)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun struct cxgb4_fw_data *header;
1423*4882a593Smuzhiyun
1424*4882a593Smuzhiyun header = (struct cxgb4_fw_data *)&data[CXGB4_FW_SIG_OFFSET];
1425*4882a593Smuzhiyun if (be32_to_cpu(header->signature) != CXGB4_FW_SIG)
1426*4882a593Smuzhiyun return -EINVAL;
1427*4882a593Smuzhiyun
1428*4882a593Smuzhiyun if (size)
1429*4882a593Smuzhiyun *size = be16_to_cpu(((struct fw_hdr *)data)->len512) * 512;
1430*4882a593Smuzhiyun
1431*4882a593Smuzhiyun return 0;
1432*4882a593Smuzhiyun }
1433*4882a593Smuzhiyun
cxgb4_validate_bootcfg_image(const u8 * data,u32 * size)1434*4882a593Smuzhiyun static int cxgb4_validate_bootcfg_image(const u8 *data, u32 *size)
1435*4882a593Smuzhiyun {
1436*4882a593Smuzhiyun struct cxgb4_bootcfg_data *header;
1437*4882a593Smuzhiyun
1438*4882a593Smuzhiyun header = (struct cxgb4_bootcfg_data *)data;
1439*4882a593Smuzhiyun if (le16_to_cpu(header->signature) != BOOT_CFG_SIG)
1440*4882a593Smuzhiyun return -EINVAL;
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun return 0;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
cxgb4_validate_boot_image(const u8 * data,u32 * size)1445*4882a593Smuzhiyun static int cxgb4_validate_boot_image(const u8 *data, u32 *size)
1446*4882a593Smuzhiyun {
1447*4882a593Smuzhiyun struct cxgb4_pci_exp_rom_header *exp_header;
1448*4882a593Smuzhiyun struct cxgb4_pcir_data *pcir_header;
1449*4882a593Smuzhiyun struct legacy_pci_rom_hdr *header;
1450*4882a593Smuzhiyun const u8 *cur_header = data;
1451*4882a593Smuzhiyun u16 pcir_offset;
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun exp_header = (struct cxgb4_pci_exp_rom_header *)data;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun if (le16_to_cpu(exp_header->signature) != BOOT_SIGNATURE)
1456*4882a593Smuzhiyun return -EINVAL;
1457*4882a593Smuzhiyun
1458*4882a593Smuzhiyun if (size) {
1459*4882a593Smuzhiyun do {
1460*4882a593Smuzhiyun header = (struct legacy_pci_rom_hdr *)cur_header;
1461*4882a593Smuzhiyun pcir_offset = le16_to_cpu(header->pcir_offset);
1462*4882a593Smuzhiyun pcir_header = (struct cxgb4_pcir_data *)(cur_header +
1463*4882a593Smuzhiyun pcir_offset);
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun *size += header->size512 * 512;
1466*4882a593Smuzhiyun cur_header += header->size512 * 512;
1467*4882a593Smuzhiyun } while (!(pcir_header->indicator & CXGB4_HDR_INDI));
1468*4882a593Smuzhiyun }
1469*4882a593Smuzhiyun
1470*4882a593Smuzhiyun return 0;
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun
cxgb4_ethtool_get_flash_region(const u8 * data,u32 * size)1473*4882a593Smuzhiyun static int cxgb4_ethtool_get_flash_region(const u8 *data, u32 *size)
1474*4882a593Smuzhiyun {
1475*4882a593Smuzhiyun if (!cxgb4_validate_fw_image(data, size))
1476*4882a593Smuzhiyun return CXGB4_ETHTOOL_FLASH_FW;
1477*4882a593Smuzhiyun if (!cxgb4_validate_boot_image(data, size))
1478*4882a593Smuzhiyun return CXGB4_ETHTOOL_FLASH_BOOT;
1479*4882a593Smuzhiyun if (!cxgb4_validate_phy_image(data, size))
1480*4882a593Smuzhiyun return CXGB4_ETHTOOL_FLASH_PHY;
1481*4882a593Smuzhiyun if (!cxgb4_validate_bootcfg_image(data, size))
1482*4882a593Smuzhiyun return CXGB4_ETHTOOL_FLASH_BOOTCFG;
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun return -EOPNOTSUPP;
1485*4882a593Smuzhiyun }
1486*4882a593Smuzhiyun
set_flash(struct net_device * netdev,struct ethtool_flash * ef)1487*4882a593Smuzhiyun static int set_flash(struct net_device *netdev, struct ethtool_flash *ef)
1488*4882a593Smuzhiyun {
1489*4882a593Smuzhiyun struct adapter *adap = netdev2adap(netdev);
1490*4882a593Smuzhiyun const struct firmware *fw;
1491*4882a593Smuzhiyun unsigned int master;
1492*4882a593Smuzhiyun u8 master_vld = 0;
1493*4882a593Smuzhiyun const u8 *fw_data;
1494*4882a593Smuzhiyun size_t fw_size;
1495*4882a593Smuzhiyun u32 size = 0;
1496*4882a593Smuzhiyun u32 pcie_fw;
1497*4882a593Smuzhiyun int region;
1498*4882a593Smuzhiyun int ret;
1499*4882a593Smuzhiyun
1500*4882a593Smuzhiyun pcie_fw = t4_read_reg(adap, PCIE_FW_A);
1501*4882a593Smuzhiyun master = PCIE_FW_MASTER_G(pcie_fw);
1502*4882a593Smuzhiyun if (pcie_fw & PCIE_FW_MASTER_VLD_F)
1503*4882a593Smuzhiyun master_vld = 1;
1504*4882a593Smuzhiyun /* if csiostor is the master return */
1505*4882a593Smuzhiyun if (master_vld && (master != adap->pf)) {
1506*4882a593Smuzhiyun dev_warn(adap->pdev_dev,
1507*4882a593Smuzhiyun "cxgb4 driver needs to be loaded as MASTER to support FW flash\n");
1508*4882a593Smuzhiyun return -EOPNOTSUPP;
1509*4882a593Smuzhiyun }
1510*4882a593Smuzhiyun
1511*4882a593Smuzhiyun ef->data[sizeof(ef->data) - 1] = '\0';
1512*4882a593Smuzhiyun ret = request_firmware(&fw, ef->data, adap->pdev_dev);
1513*4882a593Smuzhiyun if (ret < 0)
1514*4882a593Smuzhiyun return ret;
1515*4882a593Smuzhiyun
1516*4882a593Smuzhiyun fw_data = fw->data;
1517*4882a593Smuzhiyun fw_size = fw->size;
1518*4882a593Smuzhiyun if (ef->region == ETHTOOL_FLASH_ALL_REGIONS) {
1519*4882a593Smuzhiyun while (fw_size > 0) {
1520*4882a593Smuzhiyun size = 0;
1521*4882a593Smuzhiyun region = cxgb4_ethtool_get_flash_region(fw_data, &size);
1522*4882a593Smuzhiyun if (region < 0 || !size) {
1523*4882a593Smuzhiyun ret = region;
1524*4882a593Smuzhiyun goto out_free_fw;
1525*4882a593Smuzhiyun }
1526*4882a593Smuzhiyun
1527*4882a593Smuzhiyun ret = cxgb4_ethtool_flash_region(netdev, fw_data, size,
1528*4882a593Smuzhiyun region);
1529*4882a593Smuzhiyun if (ret)
1530*4882a593Smuzhiyun goto out_free_fw;
1531*4882a593Smuzhiyun
1532*4882a593Smuzhiyun fw_data += size;
1533*4882a593Smuzhiyun fw_size -= size;
1534*4882a593Smuzhiyun }
1535*4882a593Smuzhiyun } else {
1536*4882a593Smuzhiyun ret = cxgb4_ethtool_flash_region(netdev, fw_data, fw_size,
1537*4882a593Smuzhiyun ef->region);
1538*4882a593Smuzhiyun }
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun out_free_fw:
1541*4882a593Smuzhiyun release_firmware(fw);
1542*4882a593Smuzhiyun return ret;
1543*4882a593Smuzhiyun }
1544*4882a593Smuzhiyun
get_ts_info(struct net_device * dev,struct ethtool_ts_info * ts_info)1545*4882a593Smuzhiyun static int get_ts_info(struct net_device *dev, struct ethtool_ts_info *ts_info)
1546*4882a593Smuzhiyun {
1547*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1548*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
1551*4882a593Smuzhiyun SOF_TIMESTAMPING_RX_SOFTWARE |
1552*4882a593Smuzhiyun SOF_TIMESTAMPING_SOFTWARE;
1553*4882a593Smuzhiyun
1554*4882a593Smuzhiyun ts_info->so_timestamping |= SOF_TIMESTAMPING_RX_HARDWARE |
1555*4882a593Smuzhiyun SOF_TIMESTAMPING_TX_HARDWARE |
1556*4882a593Smuzhiyun SOF_TIMESTAMPING_RAW_HARDWARE;
1557*4882a593Smuzhiyun
1558*4882a593Smuzhiyun ts_info->tx_types = (1 << HWTSTAMP_TX_OFF) |
1559*4882a593Smuzhiyun (1 << HWTSTAMP_TX_ON);
1560*4882a593Smuzhiyun
1561*4882a593Smuzhiyun ts_info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
1562*4882a593Smuzhiyun (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
1563*4882a593Smuzhiyun (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) |
1564*4882a593Smuzhiyun (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
1565*4882a593Smuzhiyun (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
1566*4882a593Smuzhiyun (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ);
1567*4882a593Smuzhiyun
1568*4882a593Smuzhiyun if (adapter->ptp_clock)
1569*4882a593Smuzhiyun ts_info->phc_index = ptp_clock_index(adapter->ptp_clock);
1570*4882a593Smuzhiyun else
1571*4882a593Smuzhiyun ts_info->phc_index = -1;
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun return 0;
1574*4882a593Smuzhiyun }
1575*4882a593Smuzhiyun
get_rss_table_size(struct net_device * dev)1576*4882a593Smuzhiyun static u32 get_rss_table_size(struct net_device *dev)
1577*4882a593Smuzhiyun {
1578*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun return pi->rss_size;
1581*4882a593Smuzhiyun }
1582*4882a593Smuzhiyun
get_rss_table(struct net_device * dev,u32 * p,u8 * key,u8 * hfunc)1583*4882a593Smuzhiyun static int get_rss_table(struct net_device *dev, u32 *p, u8 *key, u8 *hfunc)
1584*4882a593Smuzhiyun {
1585*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
1586*4882a593Smuzhiyun unsigned int n = pi->rss_size;
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun if (hfunc)
1589*4882a593Smuzhiyun *hfunc = ETH_RSS_HASH_TOP;
1590*4882a593Smuzhiyun if (!p)
1591*4882a593Smuzhiyun return 0;
1592*4882a593Smuzhiyun while (n--)
1593*4882a593Smuzhiyun p[n] = pi->rss[n];
1594*4882a593Smuzhiyun return 0;
1595*4882a593Smuzhiyun }
1596*4882a593Smuzhiyun
set_rss_table(struct net_device * dev,const u32 * p,const u8 * key,const u8 hfunc)1597*4882a593Smuzhiyun static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
1598*4882a593Smuzhiyun const u8 hfunc)
1599*4882a593Smuzhiyun {
1600*4882a593Smuzhiyun unsigned int i;
1601*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1602*4882a593Smuzhiyun
1603*4882a593Smuzhiyun /* We require at least one supported parameter to be changed and no
1604*4882a593Smuzhiyun * change in any of the unsupported parameters
1605*4882a593Smuzhiyun */
1606*4882a593Smuzhiyun if (key ||
1607*4882a593Smuzhiyun (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
1608*4882a593Smuzhiyun return -EOPNOTSUPP;
1609*4882a593Smuzhiyun if (!p)
1610*4882a593Smuzhiyun return 0;
1611*4882a593Smuzhiyun
1612*4882a593Smuzhiyun /* Interface must be brought up atleast once */
1613*4882a593Smuzhiyun if (pi->adapter->flags & CXGB4_FULL_INIT_DONE) {
1614*4882a593Smuzhiyun for (i = 0; i < pi->rss_size; i++)
1615*4882a593Smuzhiyun pi->rss[i] = p[i];
1616*4882a593Smuzhiyun
1617*4882a593Smuzhiyun return cxgb4_write_rss(pi, pi->rss);
1618*4882a593Smuzhiyun }
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun return -EPERM;
1621*4882a593Smuzhiyun }
1622*4882a593Smuzhiyun
cxgb4_get_filter_entry(struct adapter * adap,u32 ftid)1623*4882a593Smuzhiyun static struct filter_entry *cxgb4_get_filter_entry(struct adapter *adap,
1624*4882a593Smuzhiyun u32 ftid)
1625*4882a593Smuzhiyun {
1626*4882a593Smuzhiyun struct tid_info *t = &adap->tids;
1627*4882a593Smuzhiyun
1628*4882a593Smuzhiyun if (ftid >= t->hpftid_base && ftid < t->hpftid_base + t->nhpftids)
1629*4882a593Smuzhiyun return &t->hpftid_tab[ftid - t->hpftid_base];
1630*4882a593Smuzhiyun
1631*4882a593Smuzhiyun if (ftid >= t->ftid_base && ftid < t->ftid_base + t->nftids)
1632*4882a593Smuzhiyun return &t->ftid_tab[ftid - t->ftid_base];
1633*4882a593Smuzhiyun
1634*4882a593Smuzhiyun return lookup_tid(t, ftid);
1635*4882a593Smuzhiyun }
1636*4882a593Smuzhiyun
cxgb4_fill_filter_rule(struct ethtool_rx_flow_spec * fs,struct ch_filter_specification * dfs)1637*4882a593Smuzhiyun static void cxgb4_fill_filter_rule(struct ethtool_rx_flow_spec *fs,
1638*4882a593Smuzhiyun struct ch_filter_specification *dfs)
1639*4882a593Smuzhiyun {
1640*4882a593Smuzhiyun switch (dfs->val.proto) {
1641*4882a593Smuzhiyun case IPPROTO_TCP:
1642*4882a593Smuzhiyun if (dfs->type)
1643*4882a593Smuzhiyun fs->flow_type = TCP_V6_FLOW;
1644*4882a593Smuzhiyun else
1645*4882a593Smuzhiyun fs->flow_type = TCP_V4_FLOW;
1646*4882a593Smuzhiyun break;
1647*4882a593Smuzhiyun case IPPROTO_UDP:
1648*4882a593Smuzhiyun if (dfs->type)
1649*4882a593Smuzhiyun fs->flow_type = UDP_V6_FLOW;
1650*4882a593Smuzhiyun else
1651*4882a593Smuzhiyun fs->flow_type = UDP_V4_FLOW;
1652*4882a593Smuzhiyun break;
1653*4882a593Smuzhiyun }
1654*4882a593Smuzhiyun
1655*4882a593Smuzhiyun if (dfs->type) {
1656*4882a593Smuzhiyun fs->h_u.tcp_ip6_spec.psrc = cpu_to_be16(dfs->val.fport);
1657*4882a593Smuzhiyun fs->m_u.tcp_ip6_spec.psrc = cpu_to_be16(dfs->mask.fport);
1658*4882a593Smuzhiyun fs->h_u.tcp_ip6_spec.pdst = cpu_to_be16(dfs->val.lport);
1659*4882a593Smuzhiyun fs->m_u.tcp_ip6_spec.pdst = cpu_to_be16(dfs->mask.lport);
1660*4882a593Smuzhiyun memcpy(&fs->h_u.tcp_ip6_spec.ip6src, &dfs->val.fip[0],
1661*4882a593Smuzhiyun sizeof(fs->h_u.tcp_ip6_spec.ip6src));
1662*4882a593Smuzhiyun memcpy(&fs->m_u.tcp_ip6_spec.ip6src, &dfs->mask.fip[0],
1663*4882a593Smuzhiyun sizeof(fs->m_u.tcp_ip6_spec.ip6src));
1664*4882a593Smuzhiyun memcpy(&fs->h_u.tcp_ip6_spec.ip6dst, &dfs->val.lip[0],
1665*4882a593Smuzhiyun sizeof(fs->h_u.tcp_ip6_spec.ip6dst));
1666*4882a593Smuzhiyun memcpy(&fs->m_u.tcp_ip6_spec.ip6dst, &dfs->mask.lip[0],
1667*4882a593Smuzhiyun sizeof(fs->m_u.tcp_ip6_spec.ip6dst));
1668*4882a593Smuzhiyun fs->h_u.tcp_ip6_spec.tclass = dfs->val.tos;
1669*4882a593Smuzhiyun fs->m_u.tcp_ip6_spec.tclass = dfs->mask.tos;
1670*4882a593Smuzhiyun } else {
1671*4882a593Smuzhiyun fs->h_u.tcp_ip4_spec.psrc = cpu_to_be16(dfs->val.fport);
1672*4882a593Smuzhiyun fs->m_u.tcp_ip4_spec.psrc = cpu_to_be16(dfs->mask.fport);
1673*4882a593Smuzhiyun fs->h_u.tcp_ip4_spec.pdst = cpu_to_be16(dfs->val.lport);
1674*4882a593Smuzhiyun fs->m_u.tcp_ip4_spec.pdst = cpu_to_be16(dfs->mask.lport);
1675*4882a593Smuzhiyun memcpy(&fs->h_u.tcp_ip4_spec.ip4src, &dfs->val.fip[0],
1676*4882a593Smuzhiyun sizeof(fs->h_u.tcp_ip4_spec.ip4src));
1677*4882a593Smuzhiyun memcpy(&fs->m_u.tcp_ip4_spec.ip4src, &dfs->mask.fip[0],
1678*4882a593Smuzhiyun sizeof(fs->m_u.tcp_ip4_spec.ip4src));
1679*4882a593Smuzhiyun memcpy(&fs->h_u.tcp_ip4_spec.ip4dst, &dfs->val.lip[0],
1680*4882a593Smuzhiyun sizeof(fs->h_u.tcp_ip4_spec.ip4dst));
1681*4882a593Smuzhiyun memcpy(&fs->m_u.tcp_ip4_spec.ip4dst, &dfs->mask.lip[0],
1682*4882a593Smuzhiyun sizeof(fs->m_u.tcp_ip4_spec.ip4dst));
1683*4882a593Smuzhiyun fs->h_u.tcp_ip4_spec.tos = dfs->val.tos;
1684*4882a593Smuzhiyun fs->m_u.tcp_ip4_spec.tos = dfs->mask.tos;
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun fs->h_ext.vlan_tci = cpu_to_be16(dfs->val.ivlan);
1687*4882a593Smuzhiyun fs->m_ext.vlan_tci = cpu_to_be16(dfs->mask.ivlan);
1688*4882a593Smuzhiyun fs->flow_type |= FLOW_EXT;
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun if (dfs->action == FILTER_DROP)
1691*4882a593Smuzhiyun fs->ring_cookie = RX_CLS_FLOW_DISC;
1692*4882a593Smuzhiyun else
1693*4882a593Smuzhiyun fs->ring_cookie = dfs->iq;
1694*4882a593Smuzhiyun }
1695*4882a593Smuzhiyun
cxgb4_ntuple_get_filter(struct net_device * dev,struct ethtool_rxnfc * cmd,unsigned int loc)1696*4882a593Smuzhiyun static int cxgb4_ntuple_get_filter(struct net_device *dev,
1697*4882a593Smuzhiyun struct ethtool_rxnfc *cmd,
1698*4882a593Smuzhiyun unsigned int loc)
1699*4882a593Smuzhiyun {
1700*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
1701*4882a593Smuzhiyun struct adapter *adap = netdev2adap(dev);
1702*4882a593Smuzhiyun struct filter_entry *f;
1703*4882a593Smuzhiyun int ftid;
1704*4882a593Smuzhiyun
1705*4882a593Smuzhiyun if (!(adap->flags & CXGB4_FULL_INIT_DONE))
1706*4882a593Smuzhiyun return -EAGAIN;
1707*4882a593Smuzhiyun
1708*4882a593Smuzhiyun /* Check for maximum filter range */
1709*4882a593Smuzhiyun if (!adap->ethtool_filters)
1710*4882a593Smuzhiyun return -EOPNOTSUPP;
1711*4882a593Smuzhiyun
1712*4882a593Smuzhiyun if (loc >= adap->ethtool_filters->nentries)
1713*4882a593Smuzhiyun return -ERANGE;
1714*4882a593Smuzhiyun
1715*4882a593Smuzhiyun if (!test_bit(loc, adap->ethtool_filters->port[pi->port_id].bmap))
1716*4882a593Smuzhiyun return -ENOENT;
1717*4882a593Smuzhiyun
1718*4882a593Smuzhiyun ftid = adap->ethtool_filters->port[pi->port_id].loc_array[loc];
1719*4882a593Smuzhiyun
1720*4882a593Smuzhiyun /* Fetch filter_entry */
1721*4882a593Smuzhiyun f = cxgb4_get_filter_entry(adap, ftid);
1722*4882a593Smuzhiyun
1723*4882a593Smuzhiyun cxgb4_fill_filter_rule(&cmd->fs, &f->fs);
1724*4882a593Smuzhiyun
1725*4882a593Smuzhiyun return 0;
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun
get_rxnfc(struct net_device * dev,struct ethtool_rxnfc * info,u32 * rules)1728*4882a593Smuzhiyun static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
1729*4882a593Smuzhiyun u32 *rules)
1730*4882a593Smuzhiyun {
1731*4882a593Smuzhiyun const struct port_info *pi = netdev_priv(dev);
1732*4882a593Smuzhiyun struct adapter *adap = netdev2adap(dev);
1733*4882a593Smuzhiyun unsigned int count = 0, index = 0;
1734*4882a593Smuzhiyun int ret = 0;
1735*4882a593Smuzhiyun
1736*4882a593Smuzhiyun switch (info->cmd) {
1737*4882a593Smuzhiyun case ETHTOOL_GRXFH: {
1738*4882a593Smuzhiyun unsigned int v = pi->rss_mode;
1739*4882a593Smuzhiyun
1740*4882a593Smuzhiyun info->data = 0;
1741*4882a593Smuzhiyun switch (info->flow_type) {
1742*4882a593Smuzhiyun case TCP_V4_FLOW:
1743*4882a593Smuzhiyun if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F)
1744*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST |
1745*4882a593Smuzhiyun RXH_L4_B_0_1 | RXH_L4_B_2_3;
1746*4882a593Smuzhiyun else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F)
1747*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST;
1748*4882a593Smuzhiyun break;
1749*4882a593Smuzhiyun case UDP_V4_FLOW:
1750*4882a593Smuzhiyun if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F) &&
1751*4882a593Smuzhiyun (v & FW_RSS_VI_CONFIG_CMD_UDPEN_F))
1752*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST |
1753*4882a593Smuzhiyun RXH_L4_B_0_1 | RXH_L4_B_2_3;
1754*4882a593Smuzhiyun else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F)
1755*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST;
1756*4882a593Smuzhiyun break;
1757*4882a593Smuzhiyun case SCTP_V4_FLOW:
1758*4882a593Smuzhiyun case AH_ESP_V4_FLOW:
1759*4882a593Smuzhiyun case IPV4_FLOW:
1760*4882a593Smuzhiyun if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F)
1761*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST;
1762*4882a593Smuzhiyun break;
1763*4882a593Smuzhiyun case TCP_V6_FLOW:
1764*4882a593Smuzhiyun if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F)
1765*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST |
1766*4882a593Smuzhiyun RXH_L4_B_0_1 | RXH_L4_B_2_3;
1767*4882a593Smuzhiyun else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F)
1768*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST;
1769*4882a593Smuzhiyun break;
1770*4882a593Smuzhiyun case UDP_V6_FLOW:
1771*4882a593Smuzhiyun if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F) &&
1772*4882a593Smuzhiyun (v & FW_RSS_VI_CONFIG_CMD_UDPEN_F))
1773*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST |
1774*4882a593Smuzhiyun RXH_L4_B_0_1 | RXH_L4_B_2_3;
1775*4882a593Smuzhiyun else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F)
1776*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST;
1777*4882a593Smuzhiyun break;
1778*4882a593Smuzhiyun case SCTP_V6_FLOW:
1779*4882a593Smuzhiyun case AH_ESP_V6_FLOW:
1780*4882a593Smuzhiyun case IPV6_FLOW:
1781*4882a593Smuzhiyun if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F)
1782*4882a593Smuzhiyun info->data = RXH_IP_SRC | RXH_IP_DST;
1783*4882a593Smuzhiyun break;
1784*4882a593Smuzhiyun }
1785*4882a593Smuzhiyun return 0;
1786*4882a593Smuzhiyun }
1787*4882a593Smuzhiyun case ETHTOOL_GRXRINGS:
1788*4882a593Smuzhiyun info->data = pi->nqsets;
1789*4882a593Smuzhiyun return 0;
1790*4882a593Smuzhiyun case ETHTOOL_GRXCLSRLCNT:
1791*4882a593Smuzhiyun info->rule_cnt =
1792*4882a593Smuzhiyun adap->ethtool_filters->port[pi->port_id].in_use;
1793*4882a593Smuzhiyun return 0;
1794*4882a593Smuzhiyun case ETHTOOL_GRXCLSRULE:
1795*4882a593Smuzhiyun return cxgb4_ntuple_get_filter(dev, info, info->fs.location);
1796*4882a593Smuzhiyun case ETHTOOL_GRXCLSRLALL:
1797*4882a593Smuzhiyun info->data = adap->ethtool_filters->nentries;
1798*4882a593Smuzhiyun while (count < info->rule_cnt) {
1799*4882a593Smuzhiyun ret = cxgb4_ntuple_get_filter(dev, info, index);
1800*4882a593Smuzhiyun if (!ret)
1801*4882a593Smuzhiyun rules[count++] = index;
1802*4882a593Smuzhiyun index++;
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun return 0;
1805*4882a593Smuzhiyun }
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun return -EOPNOTSUPP;
1808*4882a593Smuzhiyun }
1809*4882a593Smuzhiyun
cxgb4_ntuple_del_filter(struct net_device * dev,struct ethtool_rxnfc * cmd)1810*4882a593Smuzhiyun static int cxgb4_ntuple_del_filter(struct net_device *dev,
1811*4882a593Smuzhiyun struct ethtool_rxnfc *cmd)
1812*4882a593Smuzhiyun {
1813*4882a593Smuzhiyun struct cxgb4_ethtool_filter_info *filter_info;
1814*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
1815*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1816*4882a593Smuzhiyun struct filter_entry *f;
1817*4882a593Smuzhiyun u32 filter_id;
1818*4882a593Smuzhiyun int ret;
1819*4882a593Smuzhiyun
1820*4882a593Smuzhiyun if (!(adapter->flags & CXGB4_FULL_INIT_DONE))
1821*4882a593Smuzhiyun return -EAGAIN; /* can still change nfilters */
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun if (!adapter->ethtool_filters)
1824*4882a593Smuzhiyun return -EOPNOTSUPP;
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun if (cmd->fs.location >= adapter->ethtool_filters->nentries) {
1827*4882a593Smuzhiyun dev_err(adapter->pdev_dev,
1828*4882a593Smuzhiyun "Location must be < %u",
1829*4882a593Smuzhiyun adapter->ethtool_filters->nentries);
1830*4882a593Smuzhiyun return -ERANGE;
1831*4882a593Smuzhiyun }
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun filter_info = &adapter->ethtool_filters->port[pi->port_id];
1834*4882a593Smuzhiyun
1835*4882a593Smuzhiyun if (!test_bit(cmd->fs.location, filter_info->bmap))
1836*4882a593Smuzhiyun return -ENOENT;
1837*4882a593Smuzhiyun
1838*4882a593Smuzhiyun filter_id = filter_info->loc_array[cmd->fs.location];
1839*4882a593Smuzhiyun f = cxgb4_get_filter_entry(adapter, filter_id);
1840*4882a593Smuzhiyun
1841*4882a593Smuzhiyun if (f->fs.prio)
1842*4882a593Smuzhiyun filter_id -= adapter->tids.hpftid_base;
1843*4882a593Smuzhiyun else if (!f->fs.hash)
1844*4882a593Smuzhiyun filter_id -= (adapter->tids.ftid_base - adapter->tids.nhpftids);
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun ret = cxgb4_flow_rule_destroy(dev, f->fs.tc_prio, &f->fs, filter_id);
1847*4882a593Smuzhiyun if (ret)
1848*4882a593Smuzhiyun goto err;
1849*4882a593Smuzhiyun
1850*4882a593Smuzhiyun clear_bit(cmd->fs.location, filter_info->bmap);
1851*4882a593Smuzhiyun filter_info->in_use--;
1852*4882a593Smuzhiyun
1853*4882a593Smuzhiyun err:
1854*4882a593Smuzhiyun return ret;
1855*4882a593Smuzhiyun }
1856*4882a593Smuzhiyun
1857*4882a593Smuzhiyun /* Add Ethtool n-tuple filters. */
cxgb4_ntuple_set_filter(struct net_device * netdev,struct ethtool_rxnfc * cmd)1858*4882a593Smuzhiyun static int cxgb4_ntuple_set_filter(struct net_device *netdev,
1859*4882a593Smuzhiyun struct ethtool_rxnfc *cmd)
1860*4882a593Smuzhiyun {
1861*4882a593Smuzhiyun struct ethtool_rx_flow_spec_input input = {};
1862*4882a593Smuzhiyun struct cxgb4_ethtool_filter_info *filter_info;
1863*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(netdev);
1864*4882a593Smuzhiyun struct port_info *pi = netdev_priv(netdev);
1865*4882a593Smuzhiyun struct ch_filter_specification fs;
1866*4882a593Smuzhiyun struct ethtool_rx_flow_rule *flow;
1867*4882a593Smuzhiyun u32 tid;
1868*4882a593Smuzhiyun int ret;
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun if (!(adapter->flags & CXGB4_FULL_INIT_DONE))
1871*4882a593Smuzhiyun return -EAGAIN; /* can still change nfilters */
1872*4882a593Smuzhiyun
1873*4882a593Smuzhiyun if (!adapter->ethtool_filters)
1874*4882a593Smuzhiyun return -EOPNOTSUPP;
1875*4882a593Smuzhiyun
1876*4882a593Smuzhiyun if (cmd->fs.location >= adapter->ethtool_filters->nentries) {
1877*4882a593Smuzhiyun dev_err(adapter->pdev_dev,
1878*4882a593Smuzhiyun "Location must be < %u",
1879*4882a593Smuzhiyun adapter->ethtool_filters->nentries);
1880*4882a593Smuzhiyun return -ERANGE;
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun
1883*4882a593Smuzhiyun if (test_bit(cmd->fs.location,
1884*4882a593Smuzhiyun adapter->ethtool_filters->port[pi->port_id].bmap))
1885*4882a593Smuzhiyun return -EEXIST;
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun memset(&fs, 0, sizeof(fs));
1888*4882a593Smuzhiyun
1889*4882a593Smuzhiyun input.fs = &cmd->fs;
1890*4882a593Smuzhiyun flow = ethtool_rx_flow_rule_create(&input);
1891*4882a593Smuzhiyun if (IS_ERR(flow)) {
1892*4882a593Smuzhiyun ret = PTR_ERR(flow);
1893*4882a593Smuzhiyun goto exit;
1894*4882a593Smuzhiyun }
1895*4882a593Smuzhiyun
1896*4882a593Smuzhiyun fs.hitcnts = 1;
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun ret = cxgb4_flow_rule_replace(netdev, flow->rule, cmd->fs.location,
1899*4882a593Smuzhiyun NULL, &fs, &tid);
1900*4882a593Smuzhiyun if (ret)
1901*4882a593Smuzhiyun goto free;
1902*4882a593Smuzhiyun
1903*4882a593Smuzhiyun filter_info = &adapter->ethtool_filters->port[pi->port_id];
1904*4882a593Smuzhiyun
1905*4882a593Smuzhiyun if (fs.prio)
1906*4882a593Smuzhiyun tid += adapter->tids.hpftid_base;
1907*4882a593Smuzhiyun else if (!fs.hash)
1908*4882a593Smuzhiyun tid += (adapter->tids.ftid_base - adapter->tids.nhpftids);
1909*4882a593Smuzhiyun
1910*4882a593Smuzhiyun filter_info->loc_array[cmd->fs.location] = tid;
1911*4882a593Smuzhiyun set_bit(cmd->fs.location, filter_info->bmap);
1912*4882a593Smuzhiyun filter_info->in_use++;
1913*4882a593Smuzhiyun
1914*4882a593Smuzhiyun free:
1915*4882a593Smuzhiyun ethtool_rx_flow_rule_destroy(flow);
1916*4882a593Smuzhiyun exit:
1917*4882a593Smuzhiyun return ret;
1918*4882a593Smuzhiyun }
1919*4882a593Smuzhiyun
set_rxnfc(struct net_device * dev,struct ethtool_rxnfc * cmd)1920*4882a593Smuzhiyun static int set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
1921*4882a593Smuzhiyun {
1922*4882a593Smuzhiyun int ret = -EOPNOTSUPP;
1923*4882a593Smuzhiyun
1924*4882a593Smuzhiyun switch (cmd->cmd) {
1925*4882a593Smuzhiyun case ETHTOOL_SRXCLSRLINS:
1926*4882a593Smuzhiyun ret = cxgb4_ntuple_set_filter(dev, cmd);
1927*4882a593Smuzhiyun break;
1928*4882a593Smuzhiyun case ETHTOOL_SRXCLSRLDEL:
1929*4882a593Smuzhiyun ret = cxgb4_ntuple_del_filter(dev, cmd);
1930*4882a593Smuzhiyun break;
1931*4882a593Smuzhiyun default:
1932*4882a593Smuzhiyun break;
1933*4882a593Smuzhiyun }
1934*4882a593Smuzhiyun
1935*4882a593Smuzhiyun return ret;
1936*4882a593Smuzhiyun }
1937*4882a593Smuzhiyun
set_dump(struct net_device * dev,struct ethtool_dump * eth_dump)1938*4882a593Smuzhiyun static int set_dump(struct net_device *dev, struct ethtool_dump *eth_dump)
1939*4882a593Smuzhiyun {
1940*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
1941*4882a593Smuzhiyun u32 len = 0;
1942*4882a593Smuzhiyun
1943*4882a593Smuzhiyun len = sizeof(struct cudbg_hdr) +
1944*4882a593Smuzhiyun sizeof(struct cudbg_entity_hdr) * CUDBG_MAX_ENTITY;
1945*4882a593Smuzhiyun len += cxgb4_get_dump_length(adapter, eth_dump->flag);
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun adapter->eth_dump.flag = eth_dump->flag;
1948*4882a593Smuzhiyun adapter->eth_dump.len = len;
1949*4882a593Smuzhiyun return 0;
1950*4882a593Smuzhiyun }
1951*4882a593Smuzhiyun
get_dump_flag(struct net_device * dev,struct ethtool_dump * eth_dump)1952*4882a593Smuzhiyun static int get_dump_flag(struct net_device *dev, struct ethtool_dump *eth_dump)
1953*4882a593Smuzhiyun {
1954*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
1955*4882a593Smuzhiyun
1956*4882a593Smuzhiyun eth_dump->flag = adapter->eth_dump.flag;
1957*4882a593Smuzhiyun eth_dump->len = adapter->eth_dump.len;
1958*4882a593Smuzhiyun eth_dump->version = adapter->eth_dump.version;
1959*4882a593Smuzhiyun return 0;
1960*4882a593Smuzhiyun }
1961*4882a593Smuzhiyun
get_dump_data(struct net_device * dev,struct ethtool_dump * eth_dump,void * buf)1962*4882a593Smuzhiyun static int get_dump_data(struct net_device *dev, struct ethtool_dump *eth_dump,
1963*4882a593Smuzhiyun void *buf)
1964*4882a593Smuzhiyun {
1965*4882a593Smuzhiyun struct adapter *adapter = netdev2adap(dev);
1966*4882a593Smuzhiyun u32 len = 0;
1967*4882a593Smuzhiyun int ret = 0;
1968*4882a593Smuzhiyun
1969*4882a593Smuzhiyun if (adapter->eth_dump.flag == CXGB4_ETH_DUMP_NONE)
1970*4882a593Smuzhiyun return -ENOENT;
1971*4882a593Smuzhiyun
1972*4882a593Smuzhiyun len = sizeof(struct cudbg_hdr) +
1973*4882a593Smuzhiyun sizeof(struct cudbg_entity_hdr) * CUDBG_MAX_ENTITY;
1974*4882a593Smuzhiyun len += cxgb4_get_dump_length(adapter, adapter->eth_dump.flag);
1975*4882a593Smuzhiyun if (eth_dump->len < len)
1976*4882a593Smuzhiyun return -ENOMEM;
1977*4882a593Smuzhiyun
1978*4882a593Smuzhiyun ret = cxgb4_cudbg_collect(adapter, buf, &len, adapter->eth_dump.flag);
1979*4882a593Smuzhiyun if (ret)
1980*4882a593Smuzhiyun return ret;
1981*4882a593Smuzhiyun
1982*4882a593Smuzhiyun eth_dump->flag = adapter->eth_dump.flag;
1983*4882a593Smuzhiyun eth_dump->len = len;
1984*4882a593Smuzhiyun eth_dump->version = adapter->eth_dump.version;
1985*4882a593Smuzhiyun return 0;
1986*4882a593Smuzhiyun }
1987*4882a593Smuzhiyun
cxgb4_get_module_info(struct net_device * dev,struct ethtool_modinfo * modinfo)1988*4882a593Smuzhiyun static int cxgb4_get_module_info(struct net_device *dev,
1989*4882a593Smuzhiyun struct ethtool_modinfo *modinfo)
1990*4882a593Smuzhiyun {
1991*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
1992*4882a593Smuzhiyun u8 sff8472_comp, sff_diag_type, sff_rev;
1993*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
1994*4882a593Smuzhiyun int ret;
1995*4882a593Smuzhiyun
1996*4882a593Smuzhiyun if (!t4_is_inserted_mod_type(pi->mod_type))
1997*4882a593Smuzhiyun return -EINVAL;
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun switch (pi->port_type) {
2000*4882a593Smuzhiyun case FW_PORT_TYPE_SFP:
2001*4882a593Smuzhiyun case FW_PORT_TYPE_QSA:
2002*4882a593Smuzhiyun case FW_PORT_TYPE_SFP28:
2003*4882a593Smuzhiyun ret = t4_i2c_rd(adapter, adapter->mbox, pi->tx_chan,
2004*4882a593Smuzhiyun I2C_DEV_ADDR_A0, SFF_8472_COMP_ADDR,
2005*4882a593Smuzhiyun SFF_8472_COMP_LEN, &sff8472_comp);
2006*4882a593Smuzhiyun if (ret)
2007*4882a593Smuzhiyun return ret;
2008*4882a593Smuzhiyun ret = t4_i2c_rd(adapter, adapter->mbox, pi->tx_chan,
2009*4882a593Smuzhiyun I2C_DEV_ADDR_A0, SFP_DIAG_TYPE_ADDR,
2010*4882a593Smuzhiyun SFP_DIAG_TYPE_LEN, &sff_diag_type);
2011*4882a593Smuzhiyun if (ret)
2012*4882a593Smuzhiyun return ret;
2013*4882a593Smuzhiyun
2014*4882a593Smuzhiyun if (!sff8472_comp || (sff_diag_type & SFP_DIAG_ADDRMODE)) {
2015*4882a593Smuzhiyun modinfo->type = ETH_MODULE_SFF_8079;
2016*4882a593Smuzhiyun modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
2017*4882a593Smuzhiyun } else {
2018*4882a593Smuzhiyun modinfo->type = ETH_MODULE_SFF_8472;
2019*4882a593Smuzhiyun if (sff_diag_type & SFP_DIAG_IMPLEMENTED)
2020*4882a593Smuzhiyun modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
2021*4882a593Smuzhiyun else
2022*4882a593Smuzhiyun modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2;
2023*4882a593Smuzhiyun }
2024*4882a593Smuzhiyun break;
2025*4882a593Smuzhiyun
2026*4882a593Smuzhiyun case FW_PORT_TYPE_QSFP:
2027*4882a593Smuzhiyun case FW_PORT_TYPE_QSFP_10G:
2028*4882a593Smuzhiyun case FW_PORT_TYPE_CR_QSFP:
2029*4882a593Smuzhiyun case FW_PORT_TYPE_CR2_QSFP:
2030*4882a593Smuzhiyun case FW_PORT_TYPE_CR4_QSFP:
2031*4882a593Smuzhiyun ret = t4_i2c_rd(adapter, adapter->mbox, pi->tx_chan,
2032*4882a593Smuzhiyun I2C_DEV_ADDR_A0, SFF_REV_ADDR,
2033*4882a593Smuzhiyun SFF_REV_LEN, &sff_rev);
2034*4882a593Smuzhiyun /* For QSFP type ports, revision value >= 3
2035*4882a593Smuzhiyun * means the SFP is 8636 compliant.
2036*4882a593Smuzhiyun */
2037*4882a593Smuzhiyun if (ret)
2038*4882a593Smuzhiyun return ret;
2039*4882a593Smuzhiyun if (sff_rev >= 0x3) {
2040*4882a593Smuzhiyun modinfo->type = ETH_MODULE_SFF_8636;
2041*4882a593Smuzhiyun modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
2042*4882a593Smuzhiyun } else {
2043*4882a593Smuzhiyun modinfo->type = ETH_MODULE_SFF_8436;
2044*4882a593Smuzhiyun modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun break;
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun default:
2049*4882a593Smuzhiyun return -EINVAL;
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun return 0;
2053*4882a593Smuzhiyun }
2054*4882a593Smuzhiyun
cxgb4_get_module_eeprom(struct net_device * dev,struct ethtool_eeprom * eprom,u8 * data)2055*4882a593Smuzhiyun static int cxgb4_get_module_eeprom(struct net_device *dev,
2056*4882a593Smuzhiyun struct ethtool_eeprom *eprom, u8 *data)
2057*4882a593Smuzhiyun {
2058*4882a593Smuzhiyun int ret = 0, offset = eprom->offset, len = eprom->len;
2059*4882a593Smuzhiyun struct port_info *pi = netdev_priv(dev);
2060*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
2061*4882a593Smuzhiyun
2062*4882a593Smuzhiyun memset(data, 0, eprom->len);
2063*4882a593Smuzhiyun if (offset + len <= I2C_PAGE_SIZE)
2064*4882a593Smuzhiyun return t4_i2c_rd(adapter, adapter->mbox, pi->tx_chan,
2065*4882a593Smuzhiyun I2C_DEV_ADDR_A0, offset, len, data);
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun /* offset + len spans 0xa0 and 0xa1 pages */
2068*4882a593Smuzhiyun if (offset <= I2C_PAGE_SIZE) {
2069*4882a593Smuzhiyun /* read 0xa0 page */
2070*4882a593Smuzhiyun len = I2C_PAGE_SIZE - offset;
2071*4882a593Smuzhiyun ret = t4_i2c_rd(adapter, adapter->mbox, pi->tx_chan,
2072*4882a593Smuzhiyun I2C_DEV_ADDR_A0, offset, len, data);
2073*4882a593Smuzhiyun if (ret)
2074*4882a593Smuzhiyun return ret;
2075*4882a593Smuzhiyun offset = I2C_PAGE_SIZE;
2076*4882a593Smuzhiyun /* Remaining bytes to be read from second page =
2077*4882a593Smuzhiyun * Total length - bytes read from first page
2078*4882a593Smuzhiyun */
2079*4882a593Smuzhiyun len = eprom->len - len;
2080*4882a593Smuzhiyun }
2081*4882a593Smuzhiyun /* Read additional optical diagnostics from page 0xa2 if supported */
2082*4882a593Smuzhiyun return t4_i2c_rd(adapter, adapter->mbox, pi->tx_chan, I2C_DEV_ADDR_A2,
2083*4882a593Smuzhiyun offset, len, &data[eprom->len - len]);
2084*4882a593Smuzhiyun }
2085*4882a593Smuzhiyun
cxgb4_get_priv_flags(struct net_device * netdev)2086*4882a593Smuzhiyun static u32 cxgb4_get_priv_flags(struct net_device *netdev)
2087*4882a593Smuzhiyun {
2088*4882a593Smuzhiyun struct port_info *pi = netdev_priv(netdev);
2089*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
2090*4882a593Smuzhiyun
2091*4882a593Smuzhiyun return (adapter->eth_flags | pi->eth_flags);
2092*4882a593Smuzhiyun }
2093*4882a593Smuzhiyun
2094*4882a593Smuzhiyun /**
2095*4882a593Smuzhiyun * set_flags - set/unset specified flags if passed in new_flags
2096*4882a593Smuzhiyun * @cur_flags: pointer to current flags
2097*4882a593Smuzhiyun * @new_flags: new incoming flags
2098*4882a593Smuzhiyun * @flags: set of flags to set/unset
2099*4882a593Smuzhiyun */
set_flags(u32 * cur_flags,u32 new_flags,u32 flags)2100*4882a593Smuzhiyun static inline void set_flags(u32 *cur_flags, u32 new_flags, u32 flags)
2101*4882a593Smuzhiyun {
2102*4882a593Smuzhiyun *cur_flags = (*cur_flags & ~flags) | (new_flags & flags);
2103*4882a593Smuzhiyun }
2104*4882a593Smuzhiyun
cxgb4_set_priv_flags(struct net_device * netdev,u32 flags)2105*4882a593Smuzhiyun static int cxgb4_set_priv_flags(struct net_device *netdev, u32 flags)
2106*4882a593Smuzhiyun {
2107*4882a593Smuzhiyun struct port_info *pi = netdev_priv(netdev);
2108*4882a593Smuzhiyun struct adapter *adapter = pi->adapter;
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun set_flags(&adapter->eth_flags, flags, PRIV_FLAGS_ADAP);
2111*4882a593Smuzhiyun set_flags(&pi->eth_flags, flags, PRIV_FLAGS_PORT);
2112*4882a593Smuzhiyun
2113*4882a593Smuzhiyun return 0;
2114*4882a593Smuzhiyun }
2115*4882a593Smuzhiyun
cxgb4_lb_test(struct net_device * netdev,u64 * lb_status)2116*4882a593Smuzhiyun static void cxgb4_lb_test(struct net_device *netdev, u64 *lb_status)
2117*4882a593Smuzhiyun {
2118*4882a593Smuzhiyun int dev_state = netif_running(netdev);
2119*4882a593Smuzhiyun
2120*4882a593Smuzhiyun if (dev_state) {
2121*4882a593Smuzhiyun netif_tx_stop_all_queues(netdev);
2122*4882a593Smuzhiyun netif_carrier_off(netdev);
2123*4882a593Smuzhiyun }
2124*4882a593Smuzhiyun
2125*4882a593Smuzhiyun *lb_status = cxgb4_selftest_lb_pkt(netdev);
2126*4882a593Smuzhiyun
2127*4882a593Smuzhiyun if (dev_state) {
2128*4882a593Smuzhiyun netif_tx_start_all_queues(netdev);
2129*4882a593Smuzhiyun netif_carrier_on(netdev);
2130*4882a593Smuzhiyun }
2131*4882a593Smuzhiyun }
2132*4882a593Smuzhiyun
cxgb4_self_test(struct net_device * netdev,struct ethtool_test * eth_test,u64 * data)2133*4882a593Smuzhiyun static void cxgb4_self_test(struct net_device *netdev,
2134*4882a593Smuzhiyun struct ethtool_test *eth_test, u64 *data)
2135*4882a593Smuzhiyun {
2136*4882a593Smuzhiyun struct port_info *pi = netdev_priv(netdev);
2137*4882a593Smuzhiyun struct adapter *adap = pi->adapter;
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyun memset(data, 0, sizeof(u64) * CXGB4_ETHTOOL_MAX_TEST);
2140*4882a593Smuzhiyun
2141*4882a593Smuzhiyun if (!(adap->flags & CXGB4_FULL_INIT_DONE) ||
2142*4882a593Smuzhiyun !(adap->flags & CXGB4_FW_OK)) {
2143*4882a593Smuzhiyun eth_test->flags |= ETH_TEST_FL_FAILED;
2144*4882a593Smuzhiyun return;
2145*4882a593Smuzhiyun }
2146*4882a593Smuzhiyun
2147*4882a593Smuzhiyun if (eth_test->flags & ETH_TEST_FL_OFFLINE)
2148*4882a593Smuzhiyun cxgb4_lb_test(netdev, &data[CXGB4_ETHTOOL_LB_TEST]);
2149*4882a593Smuzhiyun
2150*4882a593Smuzhiyun if (data[CXGB4_ETHTOOL_LB_TEST])
2151*4882a593Smuzhiyun eth_test->flags |= ETH_TEST_FL_FAILED;
2152*4882a593Smuzhiyun }
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun static const struct ethtool_ops cxgb_ethtool_ops = {
2155*4882a593Smuzhiyun .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
2156*4882a593Smuzhiyun ETHTOOL_COALESCE_RX_MAX_FRAMES |
2157*4882a593Smuzhiyun ETHTOOL_COALESCE_TX_USECS_IRQ |
2158*4882a593Smuzhiyun ETHTOOL_COALESCE_USE_ADAPTIVE_RX,
2159*4882a593Smuzhiyun .get_link_ksettings = get_link_ksettings,
2160*4882a593Smuzhiyun .set_link_ksettings = set_link_ksettings,
2161*4882a593Smuzhiyun .get_fecparam = get_fecparam,
2162*4882a593Smuzhiyun .set_fecparam = set_fecparam,
2163*4882a593Smuzhiyun .get_drvinfo = get_drvinfo,
2164*4882a593Smuzhiyun .get_msglevel = get_msglevel,
2165*4882a593Smuzhiyun .set_msglevel = set_msglevel,
2166*4882a593Smuzhiyun .get_ringparam = get_sge_param,
2167*4882a593Smuzhiyun .set_ringparam = set_sge_param,
2168*4882a593Smuzhiyun .get_coalesce = get_coalesce,
2169*4882a593Smuzhiyun .set_coalesce = set_coalesce,
2170*4882a593Smuzhiyun .get_eeprom_len = get_eeprom_len,
2171*4882a593Smuzhiyun .get_eeprom = get_eeprom,
2172*4882a593Smuzhiyun .set_eeprom = set_eeprom,
2173*4882a593Smuzhiyun .get_pauseparam = get_pauseparam,
2174*4882a593Smuzhiyun .set_pauseparam = set_pauseparam,
2175*4882a593Smuzhiyun .get_link = ethtool_op_get_link,
2176*4882a593Smuzhiyun .get_strings = get_strings,
2177*4882a593Smuzhiyun .set_phys_id = identify_port,
2178*4882a593Smuzhiyun .nway_reset = restart_autoneg,
2179*4882a593Smuzhiyun .get_sset_count = get_sset_count,
2180*4882a593Smuzhiyun .get_ethtool_stats = get_stats,
2181*4882a593Smuzhiyun .get_regs_len = get_regs_len,
2182*4882a593Smuzhiyun .get_regs = get_regs,
2183*4882a593Smuzhiyun .get_rxnfc = get_rxnfc,
2184*4882a593Smuzhiyun .set_rxnfc = set_rxnfc,
2185*4882a593Smuzhiyun .get_rxfh_indir_size = get_rss_table_size,
2186*4882a593Smuzhiyun .get_rxfh = get_rss_table,
2187*4882a593Smuzhiyun .set_rxfh = set_rss_table,
2188*4882a593Smuzhiyun .self_test = cxgb4_self_test,
2189*4882a593Smuzhiyun .flash_device = set_flash,
2190*4882a593Smuzhiyun .get_ts_info = get_ts_info,
2191*4882a593Smuzhiyun .set_dump = set_dump,
2192*4882a593Smuzhiyun .get_dump_flag = get_dump_flag,
2193*4882a593Smuzhiyun .get_dump_data = get_dump_data,
2194*4882a593Smuzhiyun .get_module_info = cxgb4_get_module_info,
2195*4882a593Smuzhiyun .get_module_eeprom = cxgb4_get_module_eeprom,
2196*4882a593Smuzhiyun .get_priv_flags = cxgb4_get_priv_flags,
2197*4882a593Smuzhiyun .set_priv_flags = cxgb4_set_priv_flags,
2198*4882a593Smuzhiyun };
2199*4882a593Smuzhiyun
cxgb4_cleanup_ethtool_filters(struct adapter * adap)2200*4882a593Smuzhiyun void cxgb4_cleanup_ethtool_filters(struct adapter *adap)
2201*4882a593Smuzhiyun {
2202*4882a593Smuzhiyun struct cxgb4_ethtool_filter_info *eth_filter_info;
2203*4882a593Smuzhiyun u8 i;
2204*4882a593Smuzhiyun
2205*4882a593Smuzhiyun if (!adap->ethtool_filters)
2206*4882a593Smuzhiyun return;
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun eth_filter_info = adap->ethtool_filters->port;
2209*4882a593Smuzhiyun
2210*4882a593Smuzhiyun if (eth_filter_info) {
2211*4882a593Smuzhiyun for (i = 0; i < adap->params.nports; i++) {
2212*4882a593Smuzhiyun kvfree(eth_filter_info[i].loc_array);
2213*4882a593Smuzhiyun kfree(eth_filter_info[i].bmap);
2214*4882a593Smuzhiyun }
2215*4882a593Smuzhiyun kfree(eth_filter_info);
2216*4882a593Smuzhiyun }
2217*4882a593Smuzhiyun
2218*4882a593Smuzhiyun kfree(adap->ethtool_filters);
2219*4882a593Smuzhiyun }
2220*4882a593Smuzhiyun
cxgb4_init_ethtool_filters(struct adapter * adap)2221*4882a593Smuzhiyun int cxgb4_init_ethtool_filters(struct adapter *adap)
2222*4882a593Smuzhiyun {
2223*4882a593Smuzhiyun struct cxgb4_ethtool_filter_info *eth_filter_info;
2224*4882a593Smuzhiyun struct cxgb4_ethtool_filter *eth_filter;
2225*4882a593Smuzhiyun struct tid_info *tids = &adap->tids;
2226*4882a593Smuzhiyun u32 nentries, i;
2227*4882a593Smuzhiyun int ret;
2228*4882a593Smuzhiyun
2229*4882a593Smuzhiyun eth_filter = kzalloc(sizeof(*eth_filter), GFP_KERNEL);
2230*4882a593Smuzhiyun if (!eth_filter)
2231*4882a593Smuzhiyun return -ENOMEM;
2232*4882a593Smuzhiyun
2233*4882a593Smuzhiyun eth_filter_info = kcalloc(adap->params.nports,
2234*4882a593Smuzhiyun sizeof(*eth_filter_info),
2235*4882a593Smuzhiyun GFP_KERNEL);
2236*4882a593Smuzhiyun if (!eth_filter_info) {
2237*4882a593Smuzhiyun ret = -ENOMEM;
2238*4882a593Smuzhiyun goto free_eth_filter;
2239*4882a593Smuzhiyun }
2240*4882a593Smuzhiyun
2241*4882a593Smuzhiyun eth_filter->port = eth_filter_info;
2242*4882a593Smuzhiyun
2243*4882a593Smuzhiyun nentries = tids->nhpftids + tids->nftids;
2244*4882a593Smuzhiyun if (is_hashfilter(adap))
2245*4882a593Smuzhiyun nentries += tids->nhash +
2246*4882a593Smuzhiyun (adap->tids.stid_base - adap->tids.tid_base);
2247*4882a593Smuzhiyun eth_filter->nentries = nentries;
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun for (i = 0; i < adap->params.nports; i++) {
2250*4882a593Smuzhiyun eth_filter->port[i].loc_array = kvzalloc(nentries, GFP_KERNEL);
2251*4882a593Smuzhiyun if (!eth_filter->port[i].loc_array) {
2252*4882a593Smuzhiyun ret = -ENOMEM;
2253*4882a593Smuzhiyun goto free_eth_finfo;
2254*4882a593Smuzhiyun }
2255*4882a593Smuzhiyun
2256*4882a593Smuzhiyun eth_filter->port[i].bmap = kcalloc(BITS_TO_LONGS(nentries),
2257*4882a593Smuzhiyun sizeof(unsigned long),
2258*4882a593Smuzhiyun GFP_KERNEL);
2259*4882a593Smuzhiyun if (!eth_filter->port[i].bmap) {
2260*4882a593Smuzhiyun ret = -ENOMEM;
2261*4882a593Smuzhiyun goto free_eth_finfo;
2262*4882a593Smuzhiyun }
2263*4882a593Smuzhiyun }
2264*4882a593Smuzhiyun
2265*4882a593Smuzhiyun adap->ethtool_filters = eth_filter;
2266*4882a593Smuzhiyun return 0;
2267*4882a593Smuzhiyun
2268*4882a593Smuzhiyun free_eth_finfo:
2269*4882a593Smuzhiyun while (i-- > 0) {
2270*4882a593Smuzhiyun kfree(eth_filter->port[i].bmap);
2271*4882a593Smuzhiyun kvfree(eth_filter->port[i].loc_array);
2272*4882a593Smuzhiyun }
2273*4882a593Smuzhiyun kfree(eth_filter_info);
2274*4882a593Smuzhiyun
2275*4882a593Smuzhiyun free_eth_filter:
2276*4882a593Smuzhiyun kfree(eth_filter);
2277*4882a593Smuzhiyun
2278*4882a593Smuzhiyun return ret;
2279*4882a593Smuzhiyun }
2280*4882a593Smuzhiyun
cxgb4_set_ethtool_ops(struct net_device * netdev)2281*4882a593Smuzhiyun void cxgb4_set_ethtool_ops(struct net_device *netdev)
2282*4882a593Smuzhiyun {
2283*4882a593Smuzhiyun netdev->ethtool_ops = &cxgb_ethtool_ops;
2284*4882a593Smuzhiyun }
2285