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