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