]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
Merge remote-tracking branch 'regulator/fix/max77802' into regulator-linus
[mirror_ubuntu-artful-kernel.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_ethtool.c
CommitLineData
af19b491 1/*
40839129 2 * QLogic qlcnic NIC Driver
577ae39d 3 * Copyright (c) 2009-2013 QLogic Corporation
af19b491 4 *
40839129 5 * See LICENSE.qlcnic for copyright and licensing details.
af19b491
AKS
6 */
7
8#include <linux/types.h>
9#include <linux/delay.h>
10#include <linux/pci.h>
11#include <linux/io.h>
12#include <linux/netdevice.h>
13#include <linux/ethtool.h>
14
15#include "qlcnic.h"
16
17struct qlcnic_stats {
18 char stat_string[ETH_GSTRING_LEN];
19 int sizeof_stat;
20 int stat_offset;
21};
22
23#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
24#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
7e38d04b
SC
25static const u32 qlcnic_fw_dump_level[] = {
26 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
27};
af19b491
AKS
28
29static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
f27c75b3
HM
30 {"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
31 {"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
7e38d04b 32 {"xmit_called", QLC_SIZEOF(stats.xmitcalled),
f27c75b3 33 QLC_OFF(stats.xmitcalled)},
7e38d04b 34 {"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
f27c75b3
HM
35 QLC_OFF(stats.xmitfinished)},
36 {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
37 QLC_OFF(stats.tx_dma_map_error)},
38 {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
7e38d04b 39 {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
f27c75b3
HM
40 {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
41 QLC_OFF(stats.rx_dma_map_error)},
7e38d04b 42 {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
7e38d04b 43 {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
f27c75b3
HM
44 {"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
45 {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
46 {"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
47 {"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
7e38d04b
SC
48 {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
49 {"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
381709de
SS
50 {"encap_lso_frames", QLC_SIZEOF(stats.encap_lso_frames),
51 QLC_OFF(stats.encap_lso_frames)},
52 {"encap_tx_csummed", QLC_SIZEOF(stats.encap_tx_csummed),
53 QLC_OFF(stats.encap_tx_csummed)},
2b3d7b75
SS
54 {"encap_rx_csummed", QLC_SIZEOF(stats.encap_rx_csummed),
55 QLC_OFF(stats.encap_rx_csummed)},
8bfe8b91 56 {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
7e38d04b 57 QLC_OFF(stats.skb_alloc_failure)},
7e38d04b 58 {"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
f27c75b3 59 QLC_OFF(stats.mac_filter_limit_overrun)},
7e38d04b
SC
60 {"spurious intr", QLC_SIZEOF(stats.spurious_intr),
61 QLC_OFF(stats.spurious_intr)},
819bfe76
RB
62 {"mbx spurious intr", QLC_SIZEOF(stats.mbx_spurious_intr),
63 QLC_OFF(stats.mbx_spurious_intr)},
af19b491
AKS
64};
65
3666e0b0 66static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
3666e0b0 67 "tx unicast frames",
68 "tx multicast frames",
69 "tx broadcast frames",
70 "tx dropped frames",
71 "tx errors",
72 "tx local frames",
73 "tx numbytes",
f27c75b3
HM
74 "rx unicast frames",
75 "rx multicast frames",
76 "rx broadcast frames",
77 "rx dropped frames",
78 "rx errors",
79 "rx local frames",
80 "rx numbytes",
3666e0b0 81};
82
7e38d04b
SC
83static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
84 "ctx_tx_bytes",
85 "ctx_tx_pkts",
86 "ctx_tx_errors",
87 "ctx_tx_dropped_pkts",
88 "ctx_tx_num_buffers",
89};
90
91static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
54a8997c
JK
92 "mac_tx_frames",
93 "mac_tx_bytes",
94 "mac_tx_mcast_pkts",
95 "mac_tx_bcast_pkts",
96 "mac_tx_pause_cnt",
97 "mac_tx_ctrl_pkt",
98 "mac_tx_lt_64b_pkts",
99 "mac_tx_lt_127b_pkts",
100 "mac_tx_lt_255b_pkts",
101 "mac_tx_lt_511b_pkts",
102 "mac_tx_lt_1023b_pkts",
103 "mac_tx_lt_1518b_pkts",
104 "mac_tx_gt_1518b_pkts",
105 "mac_rx_frames",
106 "mac_rx_bytes",
107 "mac_rx_mcast_pkts",
108 "mac_rx_bcast_pkts",
109 "mac_rx_pause_cnt",
110 "mac_rx_ctrl_pkt",
111 "mac_rx_lt_64b_pkts",
112 "mac_rx_lt_127b_pkts",
113 "mac_rx_lt_255b_pkts",
114 "mac_rx_lt_511b_pkts",
115 "mac_rx_lt_1023b_pkts",
116 "mac_rx_lt_1518b_pkts",
117 "mac_rx_gt_1518b_pkts",
118 "mac_rx_length_error",
119 "mac_rx_length_small",
120 "mac_rx_length_large",
121 "mac_rx_jabber",
122 "mac_rx_dropped",
7e38d04b 123 "mac_crc_error",
54a8997c 124 "mac_align_error",
52290740
SS
125 "eswitch_frames",
126 "eswitch_bytes",
127 "eswitch_multicast_frames",
128 "eswitch_broadcast_frames",
129 "eswitch_unicast_frames",
130 "eswitch_error_free_frames",
131 "eswitch_error_free_bytes",
54a8997c
JK
132};
133
7e38d04b 134#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
aa4a1f7d 135
f27c75b3 136static const char qlcnic_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
aa4a1f7d
HM
137 "xmit_on",
138 "xmit_off",
139 "xmit_called",
140 "xmit_finished",
f27c75b3 141 "tx_bytes",
aa4a1f7d
HM
142};
143
f27c75b3
HM
144#define QLCNIC_TX_STATS_LEN ARRAY_SIZE(qlcnic_tx_queue_stats_strings)
145
7e38d04b
SC
146static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
147 "ctx_rx_bytes",
148 "ctx_rx_pkts",
149 "ctx_lro_pkt_cnt",
150 "ctx_ip_csum_error",
151 "ctx_rx_pkts_wo_ctx",
8c046410
SS
152 "ctx_rx_pkts_drop_wo_sds_on_card",
153 "ctx_rx_pkts_drop_wo_sds_on_host",
7e38d04b
SC
154 "ctx_rx_osized_pkts",
155 "ctx_rx_pkts_dropped_wo_rds",
156 "ctx_rx_unexpected_mcast_pkts",
157 "ctx_invalid_mac_address",
8c046410 158 "ctx_rx_rds_ring_prim_attempted",
7e38d04b
SC
159 "ctx_rx_rds_ring_prim_success",
160 "ctx_num_lro_flows_added",
161 "ctx_num_lro_flows_removed",
162 "ctx_num_lro_flows_active",
163 "ctx_pkts_dropped_unknown",
164};
af19b491
AKS
165
166static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
167 "Register_Test_on_offline",
7eb9855d 168 "Link_Test_on_offline",
22c8c934 169 "Interrupt_Test_offline",
e1428d26 170 "Internal_Loopback_offline",
2e3ea7e7 171 "External_Loopback_offline",
7e38d04b 172 "EEPROM_Test_offline"
af19b491
AKS
173};
174
175#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
176
d6e9c89a 177static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
7e38d04b 178{
d6e9c89a
SS
179 return ARRAY_SIZE(qlcnic_gstrings_stats) +
180 ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
181 QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
7e38d04b
SC
182}
183
d6e9c89a 184static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
7e38d04b 185{
d6e9c89a
SS
186 return ARRAY_SIZE(qlcnic_gstrings_stats) +
187 ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
7e38d04b 188 ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
d6e9c89a
SS
189 ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
190 QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
7e38d04b
SC
191}
192
193static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
194{
d6e9c89a
SS
195 int len = -1;
196
197 if (qlcnic_82xx_check(adapter)) {
198 len = qlcnic_82xx_statistics(adapter);
199 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
200 len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
201 } else if (qlcnic_83xx_check(adapter)) {
202 len = qlcnic_83xx_statistics(adapter);
203 }
204
205 return len;
7e38d04b
SC
206}
207
710a1a49
PP
208#define QLCNIC_TX_INTR_NOT_CONFIGURED 0X78563412
209
af19b491
AKS
210#define QLCNIC_MAX_EEPROM_LEN 1024
211
212static const u32 diag_registers[] = {
2c6196d2
SS
213 QLCNIC_CMDPEG_STATE,
214 QLCNIC_RCVPEG_STATE,
215 QLCNIC_FW_CAPABILITIES,
31018e06 216 QLCNIC_CRB_DRV_ACTIVE,
af19b491
AKS
217 QLCNIC_CRB_DEV_STATE,
218 QLCNIC_CRB_DRV_STATE,
219 QLCNIC_CRB_DRV_SCRATCH,
220 QLCNIC_CRB_DEV_PARTITION_INFO,
221 QLCNIC_CRB_DRV_IDC_VER,
222 QLCNIC_PEG_ALIVE_COUNTER,
223 QLCNIC_PEG_HALT_STATUS1,
224 QLCNIC_PEG_HALT_STATUS2,
7e38d04b
SC
225 -1
226};
227
2c6196d2 228
7e38d04b
SC
229static const u32 ext_diag_registers[] = {
230 CRB_XG_STATE_P3P,
231 ISR_INT_STATE_REG,
af19b491
AKS
232 QLCNIC_CRB_PEG_NET_0+0x3c,
233 QLCNIC_CRB_PEG_NET_1+0x3c,
234 QLCNIC_CRB_PEG_NET_2+0x3c,
235 QLCNIC_CRB_PEG_NET_4+0x3c,
236 -1
237};
238
2f514c52 239#define QLCNIC_MGMT_API_VERSION 3
710a1a49
PP
240#define QLCNIC_ETHTOOL_REGS_VER 4
241
242static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
243{
34e8c406 244 int ring_regs_cnt = (adapter->drv_tx_rings * 5) +
710a1a49 245 (adapter->max_rds_rings * 2) +
34e8c406 246 (adapter->drv_sds_rings * 3) + 5;
710a1a49
PP
247 return ring_regs_cnt * sizeof(u32);
248}
7e38d04b 249
af19b491
AKS
250static int qlcnic_get_regs_len(struct net_device *dev)
251{
7e38d04b
SC
252 struct qlcnic_adapter *adapter = netdev_priv(dev);
253 u32 len;
254
255 if (qlcnic_83xx_check(adapter))
256 len = qlcnic_83xx_get_regs_len(adapter);
257 else
258 len = sizeof(ext_diag_registers) + sizeof(diag_registers);
259
710a1a49
PP
260 len += ((QLCNIC_DEV_INFO_SIZE + 2) * sizeof(u32));
261 len += qlcnic_get_ring_regs_len(adapter);
262 return len;
af19b491
AKS
263}
264
265static int qlcnic_get_eeprom_len(struct net_device *dev)
266{
267 return QLCNIC_FLASH_TOTAL_SIZE;
268}
269
270static void
271qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
272{
273 struct qlcnic_adapter *adapter = netdev_priv(dev);
274 u32 fw_major, fw_minor, fw_build;
7e38d04b
SC
275 fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
276 fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
277 fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
68aad78c
RJ
278 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
279 "%d.%d.%d", fw_major, fw_minor, fw_build);
280
281 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
282 sizeof(drvinfo->bus_info));
283 strlcpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
284 strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
285 sizeof(drvinfo->version));
af19b491
AKS
286}
287
49cef10f
PR
288static int qlcnic_82xx_get_link_ksettings(struct qlcnic_adapter *adapter,
289 struct ethtool_link_ksettings *ecmd)
b938662d 290{
7e38d04b
SC
291 struct qlcnic_hardware_context *ahw = adapter->ahw;
292 u32 speed, reg;
4bd8e738 293 int check_sfp_module = 0, err = 0;
7e38d04b 294 u16 pcifn = ahw->pci_func;
49cef10f 295 u32 supported, advertising;
af19b491
AKS
296
297 /* read which mode */
b1fc6d3c 298 if (adapter->ahw->port_type == QLCNIC_GBE) {
49cef10f 299 supported = (SUPPORTED_10baseT_Half |
af19b491
AKS
300 SUPPORTED_10baseT_Full |
301 SUPPORTED_100baseT_Half |
302 SUPPORTED_100baseT_Full |
303 SUPPORTED_1000baseT_Half |
304 SUPPORTED_1000baseT_Full);
305
49cef10f 306 advertising = (ADVERTISED_100baseT_Half |
af19b491
AKS
307 ADVERTISED_100baseT_Full |
308 ADVERTISED_1000baseT_Half |
309 ADVERTISED_1000baseT_Full);
310
49cef10f
PR
311 ecmd->base.speed = adapter->ahw->link_speed;
312 ecmd->base.duplex = adapter->ahw->link_duplex;
313 ecmd->base.autoneg = adapter->ahw->link_autoneg;
af19b491 314
b1fc6d3c 315 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
7e38d04b 316 u32 val = 0;
4bd8e738 317 val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err);
af19b491 318
af19b491 319 if (val == QLCNIC_PORT_MODE_802_3_AP) {
49cef10f
PR
320 supported = SUPPORTED_1000baseT_Full;
321 advertising = ADVERTISED_1000baseT_Full;
af19b491 322 } else {
49cef10f
PR
323 supported = SUPPORTED_10000baseT_Full;
324 advertising = ADVERTISED_10000baseT_Full;
af19b491
AKS
325 }
326
b938662d 327 if (netif_running(adapter->netdev) && ahw->has_link_events) {
beb3d3a4
RB
328 if (ahw->linkup) {
329 reg = QLCRD32(adapter,
4bd8e738 330 P3P_LINK_SPEED_REG(pcifn), &err);
beb3d3a4
RB
331 speed = P3P_LINK_SPEED_VAL(pcifn, reg);
332 ahw->link_speed = speed * P3P_LINK_SPEED_MHZ;
333 }
334
49cef10f
PR
335 ecmd->base.speed = ahw->link_speed;
336 ecmd->base.autoneg = ahw->link_autoneg;
337 ecmd->base.duplex = ahw->link_duplex;
af19b491
AKS
338 goto skip;
339 }
340
49cef10f
PR
341 ecmd->base.speed = SPEED_UNKNOWN;
342 ecmd->base.duplex = DUPLEX_UNKNOWN;
343 ecmd->base.autoneg = AUTONEG_DISABLE;
af19b491
AKS
344 } else
345 return -EIO;
346
347skip:
49cef10f 348 ecmd->base.phy_address = adapter->ahw->physical_port;
af19b491 349
b1fc6d3c 350 switch (adapter->ahw->board_type) {
ff1b1bf8
SV
351 case QLCNIC_BRDTYPE_P3P_REF_QG:
352 case QLCNIC_BRDTYPE_P3P_4_GB:
353 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
af19b491 354
49cef10f
PR
355 supported |= SUPPORTED_Autoneg;
356 advertising |= ADVERTISED_Autoneg;
ff1b1bf8
SV
357 case QLCNIC_BRDTYPE_P3P_10G_CX4:
358 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
359 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
49cef10f
PR
360 supported |= SUPPORTED_TP;
361 advertising |= ADVERTISED_TP;
362 ecmd->base.port = PORT_TP;
363 ecmd->base.autoneg = adapter->ahw->link_autoneg;
af19b491 364 break;
ff1b1bf8
SV
365 case QLCNIC_BRDTYPE_P3P_IMEZ:
366 case QLCNIC_BRDTYPE_P3P_XG_LOM:
367 case QLCNIC_BRDTYPE_P3P_HMEZ:
49cef10f
PR
368 supported |= SUPPORTED_MII;
369 advertising |= ADVERTISED_MII;
370 ecmd->base.port = PORT_MII;
371 ecmd->base.autoneg = AUTONEG_DISABLE;
af19b491 372 break;
ff1b1bf8
SV
373 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
374 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
375 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
49cef10f
PR
376 advertising |= ADVERTISED_TP;
377 supported |= SUPPORTED_TP;
b938662d
HM
378 check_sfp_module = netif_running(adapter->netdev) &&
379 ahw->has_link_events;
ff1b1bf8 380 case QLCNIC_BRDTYPE_P3P_10G_XFP:
49cef10f
PR
381 supported |= SUPPORTED_FIBRE;
382 advertising |= ADVERTISED_FIBRE;
383 ecmd->base.port = PORT_FIBRE;
384 ecmd->base.autoneg = AUTONEG_DISABLE;
af19b491 385 break;
ff1b1bf8 386 case QLCNIC_BRDTYPE_P3P_10G_TP:
b1fc6d3c 387 if (adapter->ahw->port_type == QLCNIC_XGBE) {
49cef10f
PR
388 ecmd->base.autoneg = AUTONEG_DISABLE;
389 supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
390 advertising |=
af19b491 391 (ADVERTISED_FIBRE | ADVERTISED_TP);
49cef10f 392 ecmd->base.port = PORT_FIBRE;
b938662d
HM
393 check_sfp_module = netif_running(adapter->netdev) &&
394 ahw->has_link_events;
af19b491 395 } else {
49cef10f
PR
396 ecmd->base.autoneg = AUTONEG_ENABLE;
397 supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
398 advertising |=
af19b491 399 (ADVERTISED_TP | ADVERTISED_Autoneg);
49cef10f 400 ecmd->base.port = PORT_TP;
af19b491
AKS
401 }
402 break;
403 default:
404 dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
b1fc6d3c 405 adapter->ahw->board_type);
af19b491
AKS
406 return -EIO;
407 }
408
409 if (check_sfp_module) {
79788450 410 switch (adapter->ahw->module_type) {
af19b491
AKS
411 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
412 case LINKEVENT_MODULE_OPTICAL_SRLR:
413 case LINKEVENT_MODULE_OPTICAL_LRM:
414 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
49cef10f 415 ecmd->base.port = PORT_FIBRE;
af19b491
AKS
416 break;
417 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
418 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
419 case LINKEVENT_MODULE_TWINAX:
49cef10f 420 ecmd->base.port = PORT_TP;
af19b491
AKS
421 break;
422 default:
49cef10f 423 ecmd->base.port = PORT_OTHER;
af19b491
AKS
424 }
425 }
426
49cef10f
PR
427 ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
428 supported);
429 ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
430 advertising);
431
af19b491
AKS
432 return 0;
433}
434
49cef10f
PR
435static int qlcnic_get_link_ksettings(struct net_device *dev,
436 struct ethtool_link_ksettings *ecmd)
21041400 437{
438 struct qlcnic_adapter *adapter = netdev_priv(dev);
439
440 if (qlcnic_82xx_check(adapter))
49cef10f 441 return qlcnic_82xx_get_link_ksettings(adapter, ecmd);
21041400 442 else if (qlcnic_83xx_check(adapter))
49cef10f 443 return qlcnic_83xx_get_link_ksettings(adapter, ecmd);
21041400 444
445 return -EIO;
446}
447
448
7e38d04b 449static int qlcnic_set_port_config(struct qlcnic_adapter *adapter,
49cef10f 450 const struct ethtool_link_ksettings *ecmd)
af19b491 451{
7e38d04b 452 u32 ret = 0, config = 0;
af19b491 453 /* read which mode */
49cef10f 454 if (ecmd->base.duplex)
7e610caa 455 config |= 0x1;
af19b491 456
49cef10f 457 if (ecmd->base.autoneg)
7e610caa
SC
458 config |= 0x2;
459
49cef10f 460 switch (ecmd->base.speed) {
7e610caa
SC
461 case SPEED_10:
462 config |= (0 << 8);
463 break;
464 case SPEED_100:
465 config |= (1 << 8);
466 break;
467 case SPEED_1000:
468 config |= (10 << 8);
469 break;
470 default:
471 return -EIO;
472 }
473
474 ret = qlcnic_fw_cmd_set_port(adapter, config);
475
476 if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
af19b491 477 return -EOPNOTSUPP;
7e610caa
SC
478 else if (ret)
479 return -EIO;
7e38d04b
SC
480 return ret;
481}
482
49cef10f
PR
483static int qlcnic_set_link_ksettings(struct net_device *dev,
484 const struct ethtool_link_ksettings *ecmd)
7e38d04b
SC
485{
486 u32 ret = 0;
487 struct qlcnic_adapter *adapter = netdev_priv(dev);
488
f9c3fe2f
CM
489 if (qlcnic_83xx_check(adapter))
490 qlcnic_83xx_get_port_type(adapter);
491
7e38d04b
SC
492 if (adapter->ahw->port_type != QLCNIC_GBE)
493 return -EOPNOTSUPP;
494
495 if (qlcnic_83xx_check(adapter))
49cef10f 496 ret = qlcnic_83xx_set_link_ksettings(adapter, ecmd);
7e38d04b
SC
497 else
498 ret = qlcnic_set_port_config(adapter, ecmd);
499
500 if (!ret)
501 return ret;
7e610caa 502
49cef10f
PR
503 adapter->ahw->link_speed = ecmd->base.speed;
504 adapter->ahw->link_duplex = ecmd->base.duplex;
505 adapter->ahw->link_autoneg = ecmd->base.autoneg;
af19b491
AKS
506
507 if (!netif_running(dev))
508 return 0;
509
510 dev->netdev_ops->ndo_stop(dev);
511 return dev->netdev_ops->ndo_open(dev);
512}
513
7e38d04b
SC
514static int qlcnic_82xx_get_registers(struct qlcnic_adapter *adapter,
515 u32 *regs_buff)
516{
4bd8e738 517 int i, j = 0, err = 0;
7e38d04b
SC
518
519 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
520 regs_buff[i] = QLC_SHARED_REG_RD32(adapter, diag_registers[j]);
521 j = 0;
522 while (ext_diag_registers[j] != -1)
4bd8e738
HM
523 regs_buff[i++] = QLCRD32(adapter, ext_diag_registers[j++],
524 &err);
7e38d04b
SC
525 return i;
526}
527
af19b491
AKS
528static void
529qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
530{
531 struct qlcnic_adapter *adapter = netdev_priv(dev);
b1fc6d3c 532 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
af19b491 533 struct qlcnic_host_sds_ring *sds_ring;
710a1a49
PP
534 struct qlcnic_host_rds_ring *rds_rings;
535 struct qlcnic_host_tx_ring *tx_ring;
af19b491 536 u32 *regs_buff = p;
7e38d04b 537 int ring, i = 0;
af19b491
AKS
538
539 memset(p, 0, qlcnic_get_regs_len(dev));
7e38d04b 540
2cffcdbf 541 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
b1fc6d3c 542 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
af19b491 543
2cffcdbf
RB
544 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
545 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
546
2f514c52
JK
547 if (adapter->ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
548 regs_buff[2] = adapter->ahw->max_vnic_func;
549
7e38d04b
SC
550 if (qlcnic_82xx_check(adapter))
551 i = qlcnic_82xx_get_registers(adapter, regs_buff);
552 else
553 i = qlcnic_83xx_get_registers(adapter, regs_buff);
af19b491 554
8a15ad1f 555 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
ce668443
AKS
556 return;
557
710a1a49
PP
558 /* Marker btw regs and TX ring count */
559 regs_buff[i++] = 0xFFEFCDAB;
560
34e8c406
HM
561 regs_buff[i++] = adapter->drv_tx_rings; /* No. of TX ring */
562 for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
710a1a49
PP
563 tx_ring = &adapter->tx_ring[ring];
564 regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer));
565 regs_buff[i++] = tx_ring->sw_consumer;
566 regs_buff[i++] = readl(tx_ring->crb_cmd_producer);
567 regs_buff[i++] = tx_ring->producer;
568 if (tx_ring->crb_intr_mask)
569 regs_buff[i++] = readl(tx_ring->crb_intr_mask);
570 else
571 regs_buff[i++] = QLCNIC_TX_INTR_NOT_CONFIGURED;
572 }
af19b491 573
710a1a49
PP
574 regs_buff[i++] = adapter->max_rds_rings; /* No. of RX ring */
575 for (ring = 0; ring < adapter->max_rds_rings; ring++) {
576 rds_rings = &recv_ctx->rds_rings[ring];
577 regs_buff[i++] = readl(rds_rings->crb_rcv_producer);
578 regs_buff[i++] = rds_rings->producer;
579 }
af19b491 580
34e8c406
HM
581 regs_buff[i++] = adapter->drv_sds_rings; /* No. of SDS ring */
582 for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
af19b491
AKS
583 sds_ring = &(recv_ctx->sds_rings[ring]);
584 regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
710a1a49
PP
585 regs_buff[i++] = sds_ring->consumer;
586 regs_buff[i++] = readl(sds_ring->crb_intr_mask);
af19b491
AKS
587 }
588}
589
590static u32 qlcnic_test_link(struct net_device *dev)
591{
592 struct qlcnic_adapter *adapter = netdev_priv(dev);
4bd8e738 593 int err = 0;
af19b491
AKS
594 u32 val;
595
7e38d04b
SC
596 if (qlcnic_83xx_check(adapter)) {
597 val = qlcnic_83xx_test_link(adapter);
598 return (val & 1) ? 0 : 1;
599 }
4bd8e738
HM
600 val = QLCRD32(adapter, CRB_XG_STATE_P3P, &err);
601 if (err == -EIO)
602 return err;
b1fc6d3c 603 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
ff1b1bf8 604 return (val == XG_LINK_UP_P3P) ? 0 : 1;
af19b491
AKS
605}
606
607static int
608qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
609 u8 *bytes)
610{
611 struct qlcnic_adapter *adapter = netdev_priv(dev);
612 int offset;
7e38d04b 613 int ret = -1;
af19b491 614
7e38d04b
SC
615 if (qlcnic_83xx_check(adapter))
616 return 0;
af19b491
AKS
617 if (eeprom->len == 0)
618 return -EINVAL;
619
620 eeprom->magic = (adapter->pdev)->vendor |
621 ((adapter->pdev)->device << 16);
622 offset = eeprom->offset;
623
7e38d04b
SC
624 if (qlcnic_82xx_check(adapter))
625 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
626 eeprom->len);
af19b491
AKS
627 if (ret < 0)
628 return ret;
629
630 return 0;
631}
632
633static void
634qlcnic_get_ringparam(struct net_device *dev,
635 struct ethtool_ringparam *ring)
636{
637 struct qlcnic_adapter *adapter = netdev_priv(dev);
638
639 ring->rx_pending = adapter->num_rxd;
640 ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
af19b491
AKS
641 ring->tx_pending = adapter->num_txd;
642
90d19005
SC
643 ring->rx_max_pending = adapter->max_rxd;
644 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
af19b491 645 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
af19b491
AKS
646}
647
648static u32
649qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
650{
651 u32 num_desc;
652 num_desc = max(val, min);
653 num_desc = min(num_desc, max);
654 num_desc = roundup_pow_of_two(num_desc);
655
656 if (val != num_desc) {
657 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
658 qlcnic_driver_name, r_name, num_desc, val);
659 }
660
661 return num_desc;
662}
663
664static int
665qlcnic_set_ringparam(struct net_device *dev,
666 struct ethtool_ringparam *ring)
667{
668 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
669 u16 num_rxd, num_jumbo_rxd, num_txd;
670
af19b491
AKS
671 if (ring->rx_mini_pending)
672 return -EOPNOTSUPP;
673
af19b491 674 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
90d19005 675 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
af19b491
AKS
676
677 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
90d19005
SC
678 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
679 "rx jumbo");
af19b491
AKS
680
681 num_txd = qlcnic_validate_ringparam(ring->tx_pending,
682 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
683
684 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
685 num_jumbo_rxd == adapter->num_jumbo_rxd)
686 return 0;
687
688 adapter->num_rxd = num_rxd;
689 adapter->num_jumbo_rxd = num_jumbo_rxd;
690 adapter->num_txd = num_txd;
691
692 return qlcnic_reset_context(adapter);
693}
694
34e8c406
HM
695static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
696 u8 rx_ring, u8 tx_ring)
697{
f9566265
HM
698 if (rx_ring == 0 || tx_ring == 0)
699 return -EINVAL;
700
34e8c406
HM
701 if (rx_ring != 0) {
702 if (rx_ring > adapter->max_sds_rings) {
f9566265
HM
703 netdev_err(adapter->netdev,
704 "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
34e8c406
HM
705 rx_ring, adapter->max_sds_rings);
706 return -EINVAL;
707 }
708 }
709
710 if (tx_ring != 0) {
b17a44d8 711 if (tx_ring > adapter->max_tx_rings) {
34e8c406
HM
712 netdev_err(adapter->netdev,
713 "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
714 tx_ring, adapter->max_tx_rings);
715 return -EINVAL;
716 }
34e8c406
HM
717 }
718
719 return 0;
720}
721
f94bc1e7
SC
722static void qlcnic_get_channels(struct net_device *dev,
723 struct ethtool_channels *channel)
724{
725 struct qlcnic_adapter *adapter = netdev_priv(dev);
f94bc1e7 726
34e8c406
HM
727 channel->max_rx = adapter->max_sds_rings;
728 channel->max_tx = adapter->max_tx_rings;
729 channel->rx_count = adapter->drv_sds_rings;
730 channel->tx_count = adapter->drv_tx_rings;
f94bc1e7
SC
731}
732
733static int qlcnic_set_channels(struct net_device *dev,
34e8c406 734 struct ethtool_channels *channel)
f94bc1e7
SC
735{
736 struct qlcnic_adapter *adapter = netdev_priv(dev);
737 int err;
738
18e0d625
SS
739 if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
740 netdev_err(dev, "No RSS/TSS support in non MSI-X mode\n");
741 return -EINVAL;
742 }
743
aa4a1f7d 744 if (channel->other_count || channel->combined_count)
f94bc1e7
SC
745 return -EINVAL;
746
34e8c406
HM
747 err = qlcnic_validate_ring_count(adapter, channel->rx_count,
748 channel->tx_count);
749 if (err)
750 return err;
751
18e0d625 752 if (adapter->drv_sds_rings != channel->rx_count) {
34e8c406
HM
753 err = qlcnic_validate_rings(adapter, channel->rx_count,
754 QLCNIC_RX_QUEUE);
755 if (err) {
756 netdev_err(dev, "Unable to configure %u SDS rings\n",
757 channel->rx_count);
aa4a1f7d 758 return err;
34e8c406 759 }
cb9327d5 760 adapter->drv_rss_rings = channel->rx_count;
aa4a1f7d
HM
761 }
762
18e0d625 763 if (adapter->drv_tx_rings != channel->tx_count) {
34e8c406
HM
764 err = qlcnic_validate_rings(adapter, channel->tx_count,
765 QLCNIC_TX_QUEUE);
766 if (err) {
767 netdev_err(dev, "Unable to configure %u Tx rings\n",
768 channel->tx_count);
aa4a1f7d 769 return err;
34e8c406 770 }
cb9327d5 771 adapter->drv_tss_rings = channel->tx_count;
aa4a1f7d 772 }
f94bc1e7 773
cb9327d5
HM
774 adapter->flags |= QLCNIC_TSS_RSS;
775
776 err = qlcnic_setup_rings(adapter);
34e8c406
HM
777 netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n",
778 adapter->drv_sds_rings, adapter->drv_tx_rings);
779
f94bc1e7
SC
780 return err;
781}
782
af19b491
AKS
783static void
784qlcnic_get_pauseparam(struct net_device *netdev,
785 struct ethtool_pauseparam *pause)
786{
787 struct qlcnic_adapter *adapter = netdev_priv(netdev);
79788450 788 int port = adapter->ahw->physical_port;
4bd8e738 789 int err = 0;
af19b491
AKS
790 __u32 val;
791
7e38d04b
SC
792 if (qlcnic_83xx_check(adapter)) {
793 qlcnic_83xx_get_pauseparam(adapter, pause);
794 return;
795 }
b1fc6d3c 796 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
797 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
798 return;
799 /* get flow control settings */
4bd8e738
HM
800 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
801 if (err == -EIO)
802 return;
af19b491 803 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
4bd8e738
HM
804 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
805 if (err == -EIO)
806 return;
af19b491
AKS
807 switch (port) {
808 case 0:
809 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
810 break;
811 case 1:
812 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
813 break;
814 case 2:
815 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
816 break;
817 case 3:
818 default:
819 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
820 break;
821 }
b1fc6d3c 822 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
823 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
824 return;
825 pause->rx_pause = 1;
4bd8e738
HM
826 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
827 if (err == -EIO)
828 return;
af19b491
AKS
829 if (port == 0)
830 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
831 else
832 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
833 } else {
834 dev_err(&netdev->dev, "Unknown board type: %x\n",
b1fc6d3c 835 adapter->ahw->port_type);
af19b491
AKS
836 }
837}
838
839static int
840qlcnic_set_pauseparam(struct net_device *netdev,
841 struct ethtool_pauseparam *pause)
842{
843 struct qlcnic_adapter *adapter = netdev_priv(netdev);
79788450 844 int port = adapter->ahw->physical_port;
4bd8e738 845 int err = 0;
af19b491
AKS
846 __u32 val;
847
7e38d04b
SC
848 if (qlcnic_83xx_check(adapter))
849 return qlcnic_83xx_set_pauseparam(adapter, pause);
850
af19b491 851 /* read mode */
b1fc6d3c 852 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
853 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
854 return -EIO;
855 /* set flow control */
4bd8e738
HM
856 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
857 if (err == -EIO)
858 return err;
af19b491
AKS
859
860 if (pause->rx_pause)
861 qlcnic_gb_rx_flowctl(val);
862 else
863 qlcnic_gb_unset_rx_flowctl(val);
864
865 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
866 val);
7e38d04b 867 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val);
af19b491 868 /* set autoneg */
4bd8e738
HM
869 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
870 if (err == -EIO)
871 return err;
af19b491
AKS
872 switch (port) {
873 case 0:
874 if (pause->tx_pause)
875 qlcnic_gb_unset_gb0_mask(val);
876 else
877 qlcnic_gb_set_gb0_mask(val);
878 break;
879 case 1:
880 if (pause->tx_pause)
881 qlcnic_gb_unset_gb1_mask(val);
882 else
883 qlcnic_gb_set_gb1_mask(val);
884 break;
885 case 2:
886 if (pause->tx_pause)
887 qlcnic_gb_unset_gb2_mask(val);
888 else
889 qlcnic_gb_set_gb2_mask(val);
890 break;
891 case 3:
892 default:
893 if (pause->tx_pause)
894 qlcnic_gb_unset_gb3_mask(val);
895 else
896 qlcnic_gb_set_gb3_mask(val);
897 break;
898 }
899 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
b1fc6d3c 900 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
6d181688
RB
901 if (!pause->rx_pause || pause->autoneg)
902 return -EOPNOTSUPP;
903
af19b491
AKS
904 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
905 return -EIO;
6d181688 906
4bd8e738
HM
907 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
908 if (err == -EIO)
909 return err;
af19b491
AKS
910 if (port == 0) {
911 if (pause->tx_pause)
912 qlcnic_xg_unset_xg0_mask(val);
913 else
914 qlcnic_xg_set_xg0_mask(val);
915 } else {
916 if (pause->tx_pause)
917 qlcnic_xg_unset_xg1_mask(val);
918 else
919 qlcnic_xg_set_xg1_mask(val);
920 }
921 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
922 } else {
923 dev_err(&netdev->dev, "Unknown board type: %x\n",
b1fc6d3c 924 adapter->ahw->port_type);
af19b491
AKS
925 }
926 return 0;
927}
928
929static int qlcnic_reg_test(struct net_device *dev)
930{
931 struct qlcnic_adapter *adapter = netdev_priv(dev);
deffab05 932 u32 data_read;
4bd8e738 933 int err = 0;
af19b491 934
7e38d04b
SC
935 if (qlcnic_83xx_check(adapter))
936 return qlcnic_83xx_reg_test(adapter);
937
4bd8e738
HM
938 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0), &err);
939 if (err == -EIO)
940 return err;
af19b491
AKS
941 if ((data_read & 0xffff) != adapter->pdev->vendor)
942 return 1;
943
af19b491
AKS
944 return 0;
945}
946
7e38d04b
SC
947static int qlcnic_eeprom_test(struct net_device *dev)
948{
949 struct qlcnic_adapter *adapter = netdev_priv(dev);
950
951 if (qlcnic_82xx_check(adapter))
952 return 0;
953
954 return qlcnic_83xx_flash_test(adapter);
955}
956
af19b491
AKS
957static int qlcnic_get_sset_count(struct net_device *dev, int sset)
958{
7e38d04b 959
3666e0b0 960 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
961 switch (sset) {
962 case ETH_SS_TEST:
963 return QLCNIC_TEST_LEN;
964 case ETH_SS_STATS:
d6e9c89a 965 return qlcnic_dev_statistics_len(adapter);
af19b491
AKS
966 default:
967 return -EOPNOTSUPP;
968 }
969}
970
7eb9855d
AKS
971static int qlcnic_irq_test(struct net_device *netdev)
972{
973 struct qlcnic_adapter *adapter = netdev_priv(netdev);
58ead415 974 struct qlcnic_hardware_context *ahw = adapter->ahw;
7777de9a 975 struct qlcnic_cmd_args cmd;
34e8c406 976 int ret, drv_sds_rings = adapter->drv_sds_rings;
3bf517df 977 int drv_tx_rings = adapter->drv_tx_rings;
58ead415
JK
978
979 if (qlcnic_83xx_check(adapter))
980 return qlcnic_83xx_interrupt_test(netdev);
7eb9855d
AKS
981
982 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
983 return -EIO;
984
985 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
986 if (ret)
58ead415 987 goto clear_diag_irq;
7eb9855d 988
58ead415 989 ahw->diag_cnt = 0;
b6b4316c
SS
990 ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
991 if (ret)
992 goto free_diag_res;
7e2cf4fe 993
58ead415
JK
994 cmd.req.arg[1] = ahw->pci_func;
995 ret = qlcnic_issue_cmd(adapter, &cmd);
7eb9855d
AKS
996 if (ret)
997 goto done;
998
7e2cf4fe 999 usleep_range(1000, 12000);
58ead415 1000 ret = !ahw->diag_cnt;
7eb9855d
AKS
1001
1002done:
7e2cf4fe 1003 qlcnic_free_mbx_args(&cmd);
b6b4316c
SS
1004
1005free_diag_res:
34e8c406 1006 qlcnic_diag_free_res(netdev, drv_sds_rings);
7eb9855d 1007
58ead415 1008clear_diag_irq:
34e8c406 1009 adapter->drv_sds_rings = drv_sds_rings;
3bf517df 1010 adapter->drv_tx_rings = drv_tx_rings;
7eb9855d 1011 clear_bit(__QLCNIC_RESETTING, &adapter->state);
aa4a1f7d 1012
7eb9855d
AKS
1013 return ret;
1014}
1015
d1a1105e
RB
1016#define QLCNIC_ILB_PKT_SIZE 64
1017#define QLCNIC_NUM_ILB_PKT 16
1018#define QLCNIC_ILB_MAX_RCV_LOOP 10
1019#define QLCNIC_LB_PKT_POLL_DELAY_MSEC 1
1020#define QLCNIC_LB_PKT_POLL_COUNT 20
22c8c934
SC
1021
1022static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
1023{
1024 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
1025
1026 memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
1027
1028 memcpy(data, mac, ETH_ALEN);
1029 memcpy(data + ETH_ALEN, mac, ETH_ALEN);
1030
1031 memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
1032}
1033
1034int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
1035{
1036 unsigned char buff[QLCNIC_ILB_PKT_SIZE];
1037 qlcnic_create_loopback_buff(buff, mac);
1038 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
1039}
1040
ba4468db 1041int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
22c8c934
SC
1042{
1043 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1044 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
1045 struct sk_buff *skb;
1046 int i, loop, cnt = 0;
1047
1048 for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
dae2e9f4 1049 skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
22c8c934
SC
1050 qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
1051 skb_put(skb, QLCNIC_ILB_PKT_SIZE);
79788450 1052 adapter->ahw->diag_cnt = 0;
22c8c934 1053 qlcnic_xmit_frame(skb, adapter->netdev);
22c8c934 1054 loop = 0;
7e38d04b 1055
22c8c934 1056 do {
d1a1105e 1057 msleep(QLCNIC_LB_PKT_POLL_DELAY_MSEC);
22c8c934 1058 qlcnic_process_rcv_ring_diag(sds_ring);
d1a1105e 1059 if (loop++ > QLCNIC_LB_PKT_POLL_COUNT)
22c8c934 1060 break;
79788450 1061 } while (!adapter->ahw->diag_cnt);
22c8c934
SC
1062
1063 dev_kfree_skb_any(skb);
1064
79788450 1065 if (!adapter->ahw->diag_cnt)
7e38d04b
SC
1066 dev_warn(&adapter->pdev->dev,
1067 "LB Test: packet #%d was not received\n",
1068 i + 1);
22c8c934
SC
1069 else
1070 cnt++;
1071 }
1072 if (cnt != i) {
7e38d04b
SC
1073 dev_err(&adapter->pdev->dev,
1074 "LB Test: failed, TX[%d], RX[%d]\n", i, cnt);
1075 if (mode != QLCNIC_ILB_MODE)
df3cfbe3 1076 dev_warn(&adapter->pdev->dev,
7e38d04b 1077 "WARNING: Please check loopback cable\n");
22c8c934
SC
1078 return -1;
1079 }
1080 return 0;
1081}
1082
21041400 1083static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
22c8c934
SC
1084{
1085 struct qlcnic_adapter *adapter = netdev_priv(netdev);
34e8c406
HM
1086 int drv_tx_rings = adapter->drv_tx_rings;
1087 int drv_sds_rings = adapter->drv_sds_rings;
22c8c934 1088 struct qlcnic_host_sds_ring *sds_ring;
7e38d04b 1089 struct qlcnic_hardware_context *ahw = adapter->ahw;
22c8c934
SC
1090 int loop = 0;
1091 int ret;
1092
7e38d04b 1093 if (qlcnic_83xx_check(adapter))
ba4468db
JK
1094 return qlcnic_83xx_loopback_test(netdev, mode);
1095
7e38d04b
SC
1096 if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
1097 dev_info(&adapter->pdev->dev,
1098 "Firmware do not support loopback test\n");
fef0c060
AKS
1099 return -EOPNOTSUPP;
1100 }
ba4468db 1101
7e38d04b
SC
1102 dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n",
1103 mode == QLCNIC_ILB_MODE ? "internal" : "external");
1104 if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
1105 dev_warn(&adapter->pdev->dev,
1106 "Loopback test not supported in nonprivileged mode\n");
22c8c934
SC
1107 return 0;
1108 }
1109
1110 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
fef0c060 1111 return -EBUSY;
22c8c934
SC
1112
1113 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
1114 if (ret)
1115 goto clear_it;
1116
1117 sds_ring = &adapter->recv_ctx->sds_rings[0];
e1428d26 1118 ret = qlcnic_set_lb_mode(adapter, mode);
22c8c934
SC
1119 if (ret)
1120 goto free_res;
1121
7e38d04b 1122 ahw->diag_cnt = 0;
22c8c934
SC
1123 do {
1124 msleep(500);
1125 qlcnic_process_rcv_ring_diag(sds_ring);
fef0c060 1126 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
b9c11984
JK
1127 netdev_info(netdev,
1128 "Firmware didn't sent link up event to loopback request\n");
1129 ret = -ETIMEDOUT;
fef0c060 1130 goto free_res;
79788450
SC
1131 } else if (adapter->ahw->diag_cnt) {
1132 ret = adapter->ahw->diag_cnt;
fef0c060
AKS
1133 goto free_res;
1134 }
7e38d04b 1135 } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
ba4468db 1136
df3cfbe3 1137 ret = qlcnic_do_lb_test(adapter, mode);
ba4468db 1138
7e2cf4fe 1139 qlcnic_clear_lb_mode(adapter, mode);
22c8c934
SC
1140
1141 free_res:
34e8c406 1142 qlcnic_diag_free_res(netdev, drv_sds_rings);
22c8c934
SC
1143
1144 clear_it:
34e8c406
HM
1145 adapter->drv_sds_rings = drv_sds_rings;
1146 adapter->drv_tx_rings = drv_tx_rings;
22c8c934
SC
1147 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1148 return ret;
1149}
1150
af19b491
AKS
1151static void
1152qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
1153 u64 *data)
1154{
1155 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
897d3596 1156
8dec32cc
SC
1157 data[0] = qlcnic_reg_test(dev);
1158 if (data[0])
1159 eth_test->flags |= ETH_TEST_FL_FAILED;
1160
1161 data[1] = (u64) qlcnic_test_link(dev);
1162 if (data[1])
1163 eth_test->flags |= ETH_TEST_FL_FAILED;
1164
13b93ed9 1165 if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
7eb9855d
AKS
1166 data[2] = qlcnic_irq_test(dev);
1167 if (data[2])
1168 eth_test->flags |= ETH_TEST_FL_FAILED;
cdaff185 1169
e1428d26 1170 data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
22c8c934
SC
1171 if (data[3])
1172 eth_test->flags |= ETH_TEST_FL_FAILED;
7e38d04b 1173
2e3ea7e7
SS
1174 if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
1175 data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
1176 if (data[4])
1177 eth_test->flags |= ETH_TEST_FL_FAILED;
1178 eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
1179 }
1180
1181 data[5] = qlcnic_eeprom_test(dev);
1182 if (data[5])
7e38d04b 1183 eth_test->flags |= ETH_TEST_FL_FAILED;
7eb9855d 1184 }
af19b491
AKS
1185}
1186
1187static void
7e38d04b 1188qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
af19b491 1189{
3666e0b0 1190 struct qlcnic_adapter *adapter = netdev_priv(dev);
7e38d04b 1191 int index, i, num_stats;
af19b491
AKS
1192
1193 switch (stringset) {
1194 case ETH_SS_TEST:
1195 memcpy(data, *qlcnic_gstrings_test,
1196 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
1197 break;
1198 case ETH_SS_STATS:
f27c75b3 1199 num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings);
34e8c406 1200 for (i = 0; i < adapter->drv_tx_rings; i++) {
aa4a1f7d 1201 for (index = 0; index < num_stats; index++) {
f27c75b3
HM
1202 sprintf(data, "tx_queue_%d %s", i,
1203 qlcnic_tx_queue_stats_strings[index]);
aa4a1f7d
HM
1204 data += ETH_GSTRING_LEN;
1205 }
1206 }
1207
af19b491
AKS
1208 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
1209 memcpy(data + index * ETH_GSTRING_LEN,
1210 qlcnic_gstrings_stats[index].stat_string,
1211 ETH_GSTRING_LEN);
1212 }
aa4a1f7d 1213
7e38d04b
SC
1214 if (qlcnic_83xx_check(adapter)) {
1215 num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
1216 for (i = 0; i < num_stats; i++, index++)
1217 memcpy(data + index * ETH_GSTRING_LEN,
1218 qlcnic_83xx_tx_stats_strings[i],
1219 ETH_GSTRING_LEN);
1220 num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
1221 for (i = 0; i < num_stats; i++, index++)
1222 memcpy(data + index * ETH_GSTRING_LEN,
1223 qlcnic_83xx_mac_stats_strings[i],
1224 ETH_GSTRING_LEN);
1225 num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
1226 for (i = 0; i < num_stats; i++, index++)
1227 memcpy(data + index * ETH_GSTRING_LEN,
1228 qlcnic_83xx_rx_stats_strings[i],
1229 ETH_GSTRING_LEN);
1230 return;
1231 } else {
1232 num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
1233 for (i = 0; i < num_stats; i++, index++)
1234 memcpy(data + index * ETH_GSTRING_LEN,
1235 qlcnic_83xx_mac_stats_strings[i],
1236 ETH_GSTRING_LEN);
54a8997c 1237 }
3666e0b0 1238 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1239 return;
7e38d04b
SC
1240 num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats);
1241 for (i = 0; i < num_stats; index++, i++) {
3666e0b0 1242 memcpy(data + index * ETH_GSTRING_LEN,
1243 qlcnic_device_gstrings_stats[i],
1244 ETH_GSTRING_LEN);
1245 }
af19b491
AKS
1246 }
1247}
1248
9434dbfe 1249static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
3666e0b0 1250{
54a8997c
JK
1251 if (type == QLCNIC_MAC_STATS) {
1252 struct qlcnic_mac_statistics *mac_stats =
1253 (struct qlcnic_mac_statistics *)stats;
7e38d04b
SC
1254 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
1255 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
1256 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
1257 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
1258 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
1259 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
1260 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
1261 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
1262 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
1263 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
1264 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
1265 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
1266 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
1267 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
1268 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
1269 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
1270 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
1271 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
1272 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
1273 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
1274 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
1275 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
1276 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
1277 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
1278 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
1279 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
1280 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
1281 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
1282 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
1283 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
1284 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
1285 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
1286 *data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
54a8997c
JK
1287 } else if (type == QLCNIC_ESW_STATS) {
1288 struct __qlcnic_esw_statistics *esw_stats =
1289 (struct __qlcnic_esw_statistics *)stats;
7e38d04b
SC
1290 *data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
1291 *data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
1292 *data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
1293 *data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
1294 *data++ = QLCNIC_FILL_STATS(esw_stats->errors);
1295 *data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);
1296 *data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);
54a8997c 1297 }
9434dbfe 1298 return data;
3666e0b0 1299}
1300
1ac6762a 1301void qlcnic_update_stats(struct qlcnic_adapter *adapter)
f27c75b3 1302{
a0eaf75c 1303 struct qlcnic_tx_queue_stats tx_stats;
f27c75b3
HM
1304 struct qlcnic_host_tx_ring *tx_ring;
1305 int ring;
1306
a0eaf75c 1307 memset(&tx_stats, 0, sizeof(tx_stats));
34e8c406 1308 for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
f27c75b3 1309 tx_ring = &adapter->tx_ring[ring];
a0eaf75c
RB
1310 tx_stats.xmit_on += tx_ring->tx_stats.xmit_on;
1311 tx_stats.xmit_off += tx_ring->tx_stats.xmit_off;
1312 tx_stats.xmit_called += tx_ring->tx_stats.xmit_called;
1313 tx_stats.xmit_finished += tx_ring->tx_stats.xmit_finished;
1314 tx_stats.tx_bytes += tx_ring->tx_stats.tx_bytes;
f27c75b3 1315 }
a0eaf75c
RB
1316
1317 adapter->stats.xmit_on = tx_stats.xmit_on;
1318 adapter->stats.xmit_off = tx_stats.xmit_off;
1319 adapter->stats.xmitcalled = tx_stats.xmit_called;
1320 adapter->stats.xmitfinished = tx_stats.xmit_finished;
1321 adapter->stats.txbytes = tx_stats.tx_bytes;
f27c75b3
HM
1322}
1323
1324static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
1325{
1326 struct qlcnic_host_tx_ring *tx_ring;
1327
1328 tx_ring = (struct qlcnic_host_tx_ring *)stats;
1329
1330 *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_on);
1331 *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_off);
1332 *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_called);
1333 *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_finished);
1334 *data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.tx_bytes);
1335
1336 return data;
1337}
1338
7e38d04b
SC
1339static void qlcnic_get_ethtool_stats(struct net_device *dev,
1340 struct ethtool_stats *stats, u64 *data)
af19b491
AKS
1341{
1342 struct qlcnic_adapter *adapter = netdev_priv(dev);
aa4a1f7d 1343 struct qlcnic_host_tx_ring *tx_ring;
3666e0b0 1344 struct qlcnic_esw_statistics port_stats;
54a8997c 1345 struct qlcnic_mac_statistics mac_stats;
c0230301 1346 int index, ret, length, size, ring;
7e38d04b
SC
1347 char *p;
1348
c0230301 1349 memset(data, 0, stats->n_stats * sizeof(u64));
f27c75b3 1350
34e8c406 1351 for (ring = 0, index = 0; ring < adapter->drv_tx_rings; ring++) {
6c0fd0df 1352 if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
aa4a1f7d 1353 tx_ring = &adapter->tx_ring[ring];
f27c75b3
HM
1354 data = qlcnic_fill_tx_queue_stats(data, tx_ring);
1355 qlcnic_update_stats(adapter);
3456399b
MC
1356 } else {
1357 data += QLCNIC_TX_STATS_LEN;
aa4a1f7d
HM
1358 }
1359 }
f27c75b3 1360
7e38d04b
SC
1361 length = QLCNIC_STATS_LEN;
1362 for (index = 0; index < length; index++) {
1363 p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset;
1364 size = qlcnic_gstrings_stats[index].sizeof_stat;
1365 *data++ = (size == sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p));
af19b491 1366 }
3666e0b0 1367
7e38d04b
SC
1368 if (qlcnic_83xx_check(adapter)) {
1369 if (adapter->ahw->linkup)
1370 qlcnic_83xx_get_stats(adapter, data);
1371 return;
1372 } else {
1373 /* Retrieve MAC statistics from firmware */
1374 memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
1375 qlcnic_get_mac_stats(adapter, &mac_stats);
9434dbfe 1376 data = qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
7e38d04b 1377 }
54a8997c 1378
3666e0b0 1379 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1380 return;
1381
1382 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
b1fc6d3c 1383 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
3666e0b0 1384 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
1385 if (ret)
1386 return;
1387
9434dbfe 1388 data = qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
b1fc6d3c 1389 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
3666e0b0 1390 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
1391 if (ret)
1392 return;
1393
7e38d04b 1394 qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS);
af19b491
AKS
1395}
1396
94469f75 1397static int qlcnic_set_led(struct net_device *dev,
1398 enum ethtool_phys_id_state state)
897d3596
SC
1399{
1400 struct qlcnic_adapter *adapter = netdev_priv(dev);
34e8c406 1401 int drv_sds_rings = adapter->drv_sds_rings;
10ee0fae
SC
1402 int err = -EIO, active = 1;
1403
7e38d04b 1404 if (qlcnic_83xx_check(adapter))
d16951d9
HM
1405 return qlcnic_83xx_set_led(dev, state);
1406
79788450 1407 if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
10ee0fae
SC
1408 netdev_warn(dev, "LED test not supported for non "
1409 "privilege function\n");
1410 return -EOPNOTSUPP;
1411 }
c75822a3 1412
94469f75 1413 switch (state) {
1414 case ETHTOOL_ID_ACTIVE:
728a98b8
SC
1415 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1416 return -EBUSY;
1417
10ee0fae
SC
1418 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1419 break;
94469f75 1420
10ee0fae
SC
1421 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1422 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
1423 break;
89b4208e 1424 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
c75822a3 1425 }
8a15ad1f 1426
10ee0fae
SC
1427 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
1428 err = 0;
1429 break;
1430 }
94469f75 1431
897d3596
SC
1432 dev_err(&adapter->pdev->dev,
1433 "Failed to set LED blink state.\n");
94469f75 1434 break;
897d3596 1435
94469f75 1436 case ETHTOOL_ID_INACTIVE:
10ee0fae
SC
1437 active = 0;
1438
1439 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1440 break;
1441
1442 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1443 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
1444 break;
1445 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
1446 }
1447
89b4208e
SC
1448 if (adapter->nic_ops->config_led(adapter, 0, 0xf))
1449 dev_err(&adapter->pdev->dev,
1450 "Failed to reset LED blink state.\n");
897d3596 1451
94469f75 1452 break;
1453
1454 default:
1455 return -EINVAL;
897d3596
SC
1456 }
1457
10ee0fae 1458 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
34e8c406 1459 qlcnic_diag_free_res(dev, drv_sds_rings);
c75822a3 1460
10ee0fae
SC
1461 if (!active || err)
1462 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
728a98b8 1463
10ee0fae 1464 return err;
897d3596
SC
1465}
1466
af19b491
AKS
1467static void
1468qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1469{
1470 struct qlcnic_adapter *adapter = netdev_priv(dev);
1471 u32 wol_cfg;
4bd8e738 1472 int err = 0;
af19b491 1473
7e38d04b
SC
1474 if (qlcnic_83xx_check(adapter))
1475 return;
af19b491
AKS
1476 wol->supported = 0;
1477 wol->wolopts = 0;
1478
4bd8e738
HM
1479 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
1480 if (err == -EIO)
1481 return;
af19b491
AKS
1482 if (wol_cfg & (1UL << adapter->portnum))
1483 wol->supported |= WAKE_MAGIC;
1484
4bd8e738 1485 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
af19b491
AKS
1486 if (wol_cfg & (1UL << adapter->portnum))
1487 wol->wolopts |= WAKE_MAGIC;
1488}
1489
1490static int
1491qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1492{
1493 struct qlcnic_adapter *adapter = netdev_priv(dev);
1494 u32 wol_cfg;
4bd8e738 1495 int err = 0;
af19b491 1496
7e38d04b 1497 if (qlcnic_83xx_check(adapter))
af19b491 1498 return -EOPNOTSUPP;
7e38d04b
SC
1499 if (wol->wolopts & ~WAKE_MAGIC)
1500 return -EINVAL;
af19b491 1501
4bd8e738
HM
1502 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
1503 if (err == -EIO)
1504 return err;
af19b491
AKS
1505 if (!(wol_cfg & (1 << adapter->portnum)))
1506 return -EOPNOTSUPP;
1507
4bd8e738
HM
1508 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
1509 if (err == -EIO)
1510 return err;
af19b491
AKS
1511 if (wol->wolopts & WAKE_MAGIC)
1512 wol_cfg |= 1UL << adapter->portnum;
1513 else
1514 wol_cfg &= ~(1UL << adapter->portnum);
1515
1516 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1517
1518 return 0;
1519}
1520
1521/*
1522 * Set the coalescing parameters. Currently only normal is supported.
1523 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1524 * firmware coalescing to default.
1525 */
1526static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1527 struct ethtool_coalesce *ethcoal)
1528{
1529 struct qlcnic_adapter *adapter = netdev_priv(netdev);
a514722a 1530 int err;
af19b491 1531
8a15ad1f 1532 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
af19b491
AKS
1533 return -EINVAL;
1534
1535 /*
1536 * Return Error if unsupported values or
1537 * unsupported parameters are set.
1538 */
1539 if (ethcoal->rx_coalesce_usecs > 0xffff ||
a514722a
HM
1540 ethcoal->rx_max_coalesced_frames > 0xffff ||
1541 ethcoal->tx_coalesce_usecs > 0xffff ||
1542 ethcoal->tx_max_coalesced_frames > 0xffff ||
1543 ethcoal->rx_coalesce_usecs_irq ||
1544 ethcoal->rx_max_coalesced_frames_irq ||
1545 ethcoal->tx_coalesce_usecs_irq ||
1546 ethcoal->tx_max_coalesced_frames_irq ||
1547 ethcoal->stats_block_coalesce_usecs ||
1548 ethcoal->use_adaptive_rx_coalesce ||
1549 ethcoal->use_adaptive_tx_coalesce ||
1550 ethcoal->pkt_rate_low ||
1551 ethcoal->rx_coalesce_usecs_low ||
1552 ethcoal->rx_max_coalesced_frames_low ||
1553 ethcoal->tx_coalesce_usecs_low ||
1554 ethcoal->tx_max_coalesced_frames_low ||
1555 ethcoal->pkt_rate_high ||
1556 ethcoal->rx_coalesce_usecs_high ||
1557 ethcoal->rx_max_coalesced_frames_high ||
1558 ethcoal->tx_coalesce_usecs_high ||
1559 ethcoal->tx_max_coalesced_frames_high)
af19b491
AKS
1560 return -EINVAL;
1561
a514722a 1562 err = qlcnic_config_intr_coalesce(adapter, ethcoal);
be273dc1 1563
a514722a 1564 return err;
af19b491
AKS
1565}
1566
1567static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1568 struct ethtool_coalesce *ethcoal)
1569{
1570 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1571
1572 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1573 return -EINVAL;
1574
8816d009
AC
1575 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1576 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
be273dc1
HM
1577 ethcoal->tx_coalesce_usecs = adapter->ahw->coal.tx_time_us;
1578 ethcoal->tx_max_coalesced_frames = adapter->ahw->coal.tx_packets;
af19b491
AKS
1579
1580 return 0;
1581}
1582
65b5b420
AKS
1583static u32 qlcnic_get_msglevel(struct net_device *netdev)
1584{
1585 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1586
79788450 1587 return adapter->ahw->msg_enable;
65b5b420
AKS
1588}
1589
1590static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1591{
1592 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1593
79788450 1594 adapter->ahw->msg_enable = msglvl;
65b5b420
AKS
1595}
1596
890b6e02
SS
1597int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter)
1598{
1599 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1600 u32 val;
1601
1602 if (qlcnic_84xx_check(adapter)) {
1603 if (qlcnic_83xx_lock_driver(adapter))
1604 return -EBUSY;
1605
1606 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1607 val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP;
1608 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1609
1610 qlcnic_83xx_unlock_driver(adapter);
1611 } else {
1612 fw_dump->enable = true;
1613 }
1614
1615 dev_info(&adapter->pdev->dev, "FW dump enabled\n");
1616
1617 return 0;
1618}
1619
1620static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter)
1621{
1622 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1623 u32 val;
1624
1625 if (qlcnic_84xx_check(adapter)) {
1626 if (qlcnic_83xx_lock_driver(adapter))
1627 return -EBUSY;
1628
1629 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1630 val |= QLC_83XX_IDC_DISABLE_FW_DUMP;
1631 QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1632
1633 qlcnic_83xx_unlock_driver(adapter);
1634 } else {
1635 fw_dump->enable = false;
1636 }
1637
1638 dev_info(&adapter->pdev->dev, "FW dump disabled\n");
1639
1640 return 0;
1641}
1642
1643bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter)
1644{
1645 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1646 bool state;
1647 u32 val;
1648
1649 if (qlcnic_84xx_check(adapter)) {
1650 val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1651 state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true;
1652 } else {
1653 state = fw_dump->enable;
1654 }
1655
1656 return state;
1657}
1658
b3c68731
AC
1659static int
1660qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1661{
1662 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1663 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1664
b43e5ee7
SC
1665 if (!fw_dump->tmpl_hdr) {
1666 netdev_err(adapter->netdev, "FW Dump not supported\n");
1667 return -ENOTSUPP;
1668 }
1669
3d46512c 1670 if (fw_dump->clr)
225837a0 1671 dump->len = fw_dump->tmpl_hdr_size + fw_dump->size;
3d46512c
AC
1672 else
1673 dump->len = 0;
bcebe559 1674
890b6e02 1675 if (!qlcnic_check_fw_dump_state(adapter))
bcebe559
M
1676 dump->flag = ETH_FW_DUMP_DISABLE;
1677 else
225837a0 1678 dump->flag = fw_dump->cap_mask;
bcebe559 1679
b3c68731
AC
1680 dump->version = adapter->fw_version;
1681 return 0;
1682}
1683
1684static int
1685qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1686 void *buffer)
1687{
1688 int i, copy_sz;
63507592
SS
1689 u32 *hdr_ptr;
1690 __le32 *data;
b3c68731
AC
1691 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1692 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1693
b43e5ee7
SC
1694 if (!fw_dump->tmpl_hdr) {
1695 netdev_err(netdev, "FW Dump not supported\n");
1696 return -ENOTSUPP;
1697 }
1698
b3c68731
AC
1699 if (!fw_dump->clr) {
1700 netdev_info(netdev, "Dump not available\n");
b3c68731
AC
1701 return -EINVAL;
1702 }
225837a0 1703
b3c68731 1704 /* Copy template header first */
225837a0
SS
1705 copy_sz = fw_dump->tmpl_hdr_size;
1706 hdr_ptr = (u32 *)fw_dump->tmpl_hdr;
43d620c8 1707 data = buffer;
b3c68731
AC
1708 for (i = 0; i < copy_sz/sizeof(u32); i++)
1709 *data++ = cpu_to_le32(*hdr_ptr++);
1710
1711 /* Copy captured dump data */
1712 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1713 dump->len = copy_sz + fw_dump->size;
225837a0 1714 dump->flag = fw_dump->cap_mask;
b3c68731
AC
1715
1716 /* Free dump area once data has been captured */
1717 vfree(fw_dump->data);
1718 fw_dump->data = NULL;
1719 fw_dump->clr = 0;
c47884e4 1720 netdev_info(netdev, "extracted the FW dump Successfully\n");
b3c68731
AC
1721 return 0;
1722}
1723
890b6e02
SS
1724static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask)
1725{
1726 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1727 struct net_device *netdev = adapter->netdev;
1728
1729 if (!qlcnic_check_fw_dump_state(adapter)) {
1730 netdev_info(netdev,
1731 "Can not change driver mask to 0x%x. FW dump not enabled\n",
1732 mask);
1733 return -EOPNOTSUPP;
1734 }
1735
225837a0
SS
1736 fw_dump->cap_mask = mask;
1737
1738 /* Store new capture mask in template header as well*/
1739 qlcnic_store_cap_mask(adapter, fw_dump->tmpl_hdr, mask);
1740
890b6e02
SS
1741 netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask);
1742 return 0;
1743}
1744
b3c68731
AC
1745static int
1746qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1747{
b3c68731
AC
1748 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1749 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
890b6e02
SS
1750 bool valid_mask = false;
1751 int i, ret = 0;
b3c68731 1752
3d46512c
AC
1753 switch (val->flag) {
1754 case QLCNIC_FORCE_FW_DUMP_KEY:
b43e5ee7
SC
1755 if (!fw_dump->tmpl_hdr) {
1756 netdev_err(netdev, "FW dump not supported\n");
890b6e02
SS
1757 ret = -EOPNOTSUPP;
1758 break;
b43e5ee7 1759 }
890b6e02
SS
1760
1761 if (!qlcnic_check_fw_dump_state(adapter)) {
9d6a6440 1762 netdev_info(netdev, "FW dump not enabled\n");
890b6e02
SS
1763 ret = -EOPNOTSUPP;
1764 break;
9d6a6440 1765 }
890b6e02 1766
9d6a6440 1767 if (fw_dump->clr) {
c47884e4 1768 netdev_info(netdev,
890b6e02
SS
1769 "Previous dump not cleared, not forcing dump\n");
1770 break;
9d6a6440 1771 }
890b6e02 1772
b3c68731 1773 netdev_info(netdev, "Forcing a FW dump\n");
7e38d04b 1774 qlcnic_dev_request_reset(adapter, val->flag);
3d46512c
AC
1775 break;
1776 case QLCNIC_DISABLE_FW_DUMP:
890b6e02
SS
1777 if (!fw_dump->tmpl_hdr) {
1778 netdev_err(netdev, "FW dump not supported\n");
1779 ret = -EOPNOTSUPP;
1780 break;
9d6a6440 1781 }
890b6e02
SS
1782
1783 ret = qlcnic_disable_fw_dump_state(adapter);
1784 break;
1785
3d46512c 1786 case QLCNIC_ENABLE_FW_DUMP:
b43e5ee7
SC
1787 if (!fw_dump->tmpl_hdr) {
1788 netdev_err(netdev, "FW dump not supported\n");
890b6e02
SS
1789 ret = -EOPNOTSUPP;
1790 break;
9d6a6440 1791 }
890b6e02
SS
1792
1793 ret = qlcnic_enable_fw_dump_state(adapter);
1794 break;
1795
3d46512c
AC
1796 case QLCNIC_FORCE_FW_RESET:
1797 netdev_info(netdev, "Forcing a FW reset\n");
7e38d04b 1798 qlcnic_dev_request_reset(adapter, val->flag);
3d46512c 1799 adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
890b6e02 1800 break;
3cc4a678 1801
b43e5ee7
SC
1802 case QLCNIC_SET_QUIESCENT:
1803 case QLCNIC_RESET_QUIESCENT:
78ea2d97
SC
1804 if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
1805 netdev_info(netdev, "Device is in non-operational state\n");
890b6e02
SS
1806 break;
1807
3d46512c 1808 default:
b43e5ee7
SC
1809 if (!fw_dump->tmpl_hdr) {
1810 netdev_err(netdev, "FW dump not supported\n");
890b6e02
SS
1811 ret = -EOPNOTSUPP;
1812 break;
b43e5ee7 1813 }
890b6e02 1814
7e38d04b
SC
1815 for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
1816 if (val->flag == qlcnic_fw_dump_level[i]) {
890b6e02
SS
1817 valid_mask = true;
1818 break;
4fbec4d8 1819 }
b3c68731 1820 }
890b6e02
SS
1821
1822 if (valid_mask) {
1823 ret = qlcnic_set_dump_mask(adapter, val->flag);
1824 } else {
1825 netdev_info(netdev, "Invalid dump level: 0x%x\n",
1826 val->flag);
1827 ret = -EINVAL;
1828 }
b3c68731 1829 }
890b6e02 1830 return ret;
b3c68731
AC
1831}
1832
af19b491 1833const struct ethtool_ops qlcnic_ethtool_ops = {
af19b491
AKS
1834 .get_drvinfo = qlcnic_get_drvinfo,
1835 .get_regs_len = qlcnic_get_regs_len,
1836 .get_regs = qlcnic_get_regs,
1837 .get_link = ethtool_op_get_link,
1838 .get_eeprom_len = qlcnic_get_eeprom_len,
1839 .get_eeprom = qlcnic_get_eeprom,
1840 .get_ringparam = qlcnic_get_ringparam,
1841 .set_ringparam = qlcnic_set_ringparam,
f94bc1e7
SC
1842 .get_channels = qlcnic_get_channels,
1843 .set_channels = qlcnic_set_channels,
af19b491
AKS
1844 .get_pauseparam = qlcnic_get_pauseparam,
1845 .set_pauseparam = qlcnic_set_pauseparam,
af19b491
AKS
1846 .get_wol = qlcnic_get_wol,
1847 .set_wol = qlcnic_set_wol,
1848 .self_test = qlcnic_diag_test,
1849 .get_strings = qlcnic_get_strings,
1850 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1851 .get_sset_count = qlcnic_get_sset_count,
af19b491
AKS
1852 .get_coalesce = qlcnic_get_intr_coalesce,
1853 .set_coalesce = qlcnic_set_intr_coalesce,
94469f75 1854 .set_phys_id = qlcnic_set_led,
65b5b420
AKS
1855 .set_msglevel = qlcnic_set_msglevel,
1856 .get_msglevel = qlcnic_get_msglevel,
b3c68731
AC
1857 .get_dump_flag = qlcnic_get_dump_flag,
1858 .get_dump_data = qlcnic_get_dump_data,
1859 .set_dump = qlcnic_set_dump,
49cef10f
PR
1860 .get_link_ksettings = qlcnic_get_link_ksettings,
1861 .set_link_ksettings = qlcnic_set_link_ksettings,
af19b491 1862};
d1a1105e
RB
1863
1864const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops = {
d1a1105e
RB
1865 .get_drvinfo = qlcnic_get_drvinfo,
1866 .get_regs_len = qlcnic_get_regs_len,
1867 .get_regs = qlcnic_get_regs,
1868 .get_link = ethtool_op_get_link,
1869 .get_eeprom_len = qlcnic_get_eeprom_len,
1870 .get_eeprom = qlcnic_get_eeprom,
1871 .get_ringparam = qlcnic_get_ringparam,
1872 .set_ringparam = qlcnic_set_ringparam,
1873 .get_channels = qlcnic_get_channels,
1874 .get_pauseparam = qlcnic_get_pauseparam,
1875 .get_wol = qlcnic_get_wol,
1876 .get_strings = qlcnic_get_strings,
1877 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1878 .get_sset_count = qlcnic_get_sset_count,
1879 .get_coalesce = qlcnic_get_intr_coalesce,
1880 .set_coalesce = qlcnic_set_intr_coalesce,
1881 .set_msglevel = qlcnic_set_msglevel,
1882 .get_msglevel = qlcnic_get_msglevel,
49cef10f 1883 .get_link_ksettings = qlcnic_get_link_ksettings,
d1a1105e 1884};
66451615
SC
1885
1886const struct ethtool_ops qlcnic_ethtool_failed_ops = {
66451615
SC
1887 .get_drvinfo = qlcnic_get_drvinfo,
1888 .set_msglevel = qlcnic_set_msglevel,
1889 .get_msglevel = qlcnic_get_msglevel,
1890 .set_dump = qlcnic_set_dump,
49cef10f 1891 .get_link_ksettings = qlcnic_get_link_ksettings,
66451615 1892};