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