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