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