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