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