]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
net: dsa/slave: Fix compilation warnings
[mirror_ubuntu-eoan-kernel.git] / drivers / net / ethernet / qlogic / qlcnic / qlcnic_ethtool.c
CommitLineData
af19b491 1/*
40839129
SV
2 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2010 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)
25
26static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
27 {"xmit_called",
28 QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)},
29 {"xmit_finished",
30 QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)},
31 {"rx_dropped",
32 QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
33 {"tx_dropped",
34 QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
35 {"csummed",
36 QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
37 {"rx_pkts",
38 QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
39 {"lro_pkts",
40 QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
41 {"rx_bytes",
42 QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
43 {"tx_bytes",
44 QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
8bfe8b91
SC
45 {"lrobytes",
46 QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
47 {"lso_frames",
48 QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
49 {"xmit_on",
50 QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
51 {"xmit_off",
52 QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
53 {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
54 QLC_OFF(stats.skb_alloc_failure)},
8ae6df97
AKS
55 {"null rxbuf",
56 QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
57 {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
58 QLC_OFF(stats.rx_dma_map_error)},
59 {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
60 QLC_OFF(stats.tx_dma_map_error)},
8bfe8b91 61
af19b491
AKS
62};
63
3666e0b0 64static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
65 "rx unicast frames",
66 "rx multicast frames",
67 "rx broadcast frames",
68 "rx dropped frames",
69 "rx errors",
70 "rx local frames",
71 "rx numbytes",
72 "tx unicast frames",
73 "tx multicast frames",
74 "tx broadcast frames",
75 "tx dropped frames",
76 "tx errors",
77 "tx local frames",
78 "tx numbytes",
79};
80
54a8997c
JK
81static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
82 "mac_tx_frames",
83 "mac_tx_bytes",
84 "mac_tx_mcast_pkts",
85 "mac_tx_bcast_pkts",
86 "mac_tx_pause_cnt",
87 "mac_tx_ctrl_pkt",
88 "mac_tx_lt_64b_pkts",
89 "mac_tx_lt_127b_pkts",
90 "mac_tx_lt_255b_pkts",
91 "mac_tx_lt_511b_pkts",
92 "mac_tx_lt_1023b_pkts",
93 "mac_tx_lt_1518b_pkts",
94 "mac_tx_gt_1518b_pkts",
95 "mac_rx_frames",
96 "mac_rx_bytes",
97 "mac_rx_mcast_pkts",
98 "mac_rx_bcast_pkts",
99 "mac_rx_pause_cnt",
100 "mac_rx_ctrl_pkt",
101 "mac_rx_lt_64b_pkts",
102 "mac_rx_lt_127b_pkts",
103 "mac_rx_lt_255b_pkts",
104 "mac_rx_lt_511b_pkts",
105 "mac_rx_lt_1023b_pkts",
106 "mac_rx_lt_1518b_pkts",
107 "mac_rx_gt_1518b_pkts",
108 "mac_rx_length_error",
109 "mac_rx_length_small",
110 "mac_rx_length_large",
111 "mac_rx_jabber",
112 "mac_rx_dropped",
113 "mac_rx_crc_error",
114 "mac_align_error",
115};
116
117#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
118#define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings)
3666e0b0 119#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
54a8997c 120#define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN
af19b491
AKS
121
122static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
123 "Register_Test_on_offline",
7eb9855d 124 "Link_Test_on_offline",
22c8c934 125 "Interrupt_Test_offline",
e1428d26
AKS
126 "Internal_Loopback_offline",
127 "External_Loopback_offline"
af19b491
AKS
128};
129
130#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
131
132#define QLCNIC_RING_REGS_COUNT 20
133#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
134#define QLCNIC_MAX_EEPROM_LEN 1024
135
136static const u32 diag_registers[] = {
137 CRB_CMDPEG_STATE,
138 CRB_RCVPEG_STATE,
ff1b1bf8 139 CRB_XG_STATE_P3P,
af19b491
AKS
140 CRB_FW_CAPABILITIES_1,
141 ISR_INT_STATE_REG,
31018e06 142 QLCNIC_CRB_DRV_ACTIVE,
af19b491
AKS
143 QLCNIC_CRB_DEV_STATE,
144 QLCNIC_CRB_DRV_STATE,
145 QLCNIC_CRB_DRV_SCRATCH,
146 QLCNIC_CRB_DEV_PARTITION_INFO,
147 QLCNIC_CRB_DRV_IDC_VER,
148 QLCNIC_PEG_ALIVE_COUNTER,
149 QLCNIC_PEG_HALT_STATUS1,
150 QLCNIC_PEG_HALT_STATUS2,
151 QLCNIC_CRB_PEG_NET_0+0x3c,
152 QLCNIC_CRB_PEG_NET_1+0x3c,
153 QLCNIC_CRB_PEG_NET_2+0x3c,
154 QLCNIC_CRB_PEG_NET_4+0x3c,
155 -1
156};
157
2cffcdbf
RB
158#define QLCNIC_MGMT_API_VERSION 2
159#define QLCNIC_DEV_INFO_SIZE 1
160#define QLCNIC_ETHTOOL_REGS_VER 2
af19b491
AKS
161static int qlcnic_get_regs_len(struct net_device *dev)
162{
2cffcdbf
RB
163 return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
164 QLCNIC_DEV_INFO_SIZE + 1;
af19b491
AKS
165}
166
167static int qlcnic_get_eeprom_len(struct net_device *dev)
168{
169 return QLCNIC_FLASH_TOTAL_SIZE;
170}
171
172static void
173qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
174{
175 struct qlcnic_adapter *adapter = netdev_priv(dev);
176 u32 fw_major, fw_minor, fw_build;
177
178 fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
179 fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
180 fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
68aad78c
RJ
181 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
182 "%d.%d.%d", fw_major, fw_minor, fw_build);
183
184 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
185 sizeof(drvinfo->bus_info));
186 strlcpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
187 strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
188 sizeof(drvinfo->version));
af19b491
AKS
189}
190
191static int
192qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
193{
194 struct qlcnic_adapter *adapter = netdev_priv(dev);
195 int check_sfp_module = 0;
af19b491
AKS
196
197 /* read which mode */
b1fc6d3c 198 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
199 ecmd->supported = (SUPPORTED_10baseT_Half |
200 SUPPORTED_10baseT_Full |
201 SUPPORTED_100baseT_Half |
202 SUPPORTED_100baseT_Full |
203 SUPPORTED_1000baseT_Half |
204 SUPPORTED_1000baseT_Full);
205
206 ecmd->advertising = (ADVERTISED_100baseT_Half |
207 ADVERTISED_100baseT_Full |
208 ADVERTISED_1000baseT_Half |
209 ADVERTISED_1000baseT_Full);
210
70739497 211 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
af19b491
AKS
212 ecmd->duplex = adapter->link_duplex;
213 ecmd->autoneg = adapter->link_autoneg;
214
b1fc6d3c 215 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
216 u32 val;
217
218 val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
219 if (val == QLCNIC_PORT_MODE_802_3_AP) {
220 ecmd->supported = SUPPORTED_1000baseT_Full;
221 ecmd->advertising = ADVERTISED_1000baseT_Full;
222 } else {
223 ecmd->supported = SUPPORTED_10000baseT_Full;
224 ecmd->advertising = ADVERTISED_10000baseT_Full;
225 }
226
227 if (netif_running(dev) && adapter->has_link_events) {
70739497 228 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
af19b491
AKS
229 ecmd->autoneg = adapter->link_autoneg;
230 ecmd->duplex = adapter->link_duplex;
231 goto skip;
232 }
233
476a4b6d
SC
234 ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
235 ecmd->duplex = DUPLEX_UNKNOWN;
af19b491
AKS
236 ecmd->autoneg = AUTONEG_DISABLE;
237 } else
238 return -EIO;
239
240skip:
241 ecmd->phy_address = adapter->physical_port;
242 ecmd->transceiver = XCVR_EXTERNAL;
243
b1fc6d3c 244 switch (adapter->ahw->board_type) {
ff1b1bf8
SV
245 case QLCNIC_BRDTYPE_P3P_REF_QG:
246 case QLCNIC_BRDTYPE_P3P_4_GB:
247 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
af19b491
AKS
248
249 ecmd->supported |= SUPPORTED_Autoneg;
250 ecmd->advertising |= ADVERTISED_Autoneg;
ff1b1bf8
SV
251 case QLCNIC_BRDTYPE_P3P_10G_CX4:
252 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
253 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
af19b491
AKS
254 ecmd->supported |= SUPPORTED_TP;
255 ecmd->advertising |= ADVERTISED_TP;
256 ecmd->port = PORT_TP;
257 ecmd->autoneg = adapter->link_autoneg;
258 break;
ff1b1bf8
SV
259 case QLCNIC_BRDTYPE_P3P_IMEZ:
260 case QLCNIC_BRDTYPE_P3P_XG_LOM:
261 case QLCNIC_BRDTYPE_P3P_HMEZ:
af19b491
AKS
262 ecmd->supported |= SUPPORTED_MII;
263 ecmd->advertising |= ADVERTISED_MII;
264 ecmd->port = PORT_MII;
265 ecmd->autoneg = AUTONEG_DISABLE;
266 break;
ff1b1bf8
SV
267 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
268 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
269 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
af19b491
AKS
270 ecmd->advertising |= ADVERTISED_TP;
271 ecmd->supported |= SUPPORTED_TP;
272 check_sfp_module = netif_running(dev) &&
273 adapter->has_link_events;
ff1b1bf8 274 case QLCNIC_BRDTYPE_P3P_10G_XFP:
af19b491
AKS
275 ecmd->supported |= SUPPORTED_FIBRE;
276 ecmd->advertising |= ADVERTISED_FIBRE;
277 ecmd->port = PORT_FIBRE;
278 ecmd->autoneg = AUTONEG_DISABLE;
279 break;
ff1b1bf8 280 case QLCNIC_BRDTYPE_P3P_10G_TP:
b1fc6d3c 281 if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
282 ecmd->autoneg = AUTONEG_DISABLE;
283 ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
284 ecmd->advertising |=
285 (ADVERTISED_FIBRE | ADVERTISED_TP);
286 ecmd->port = PORT_FIBRE;
287 check_sfp_module = netif_running(dev) &&
288 adapter->has_link_events;
289 } else {
290 ecmd->autoneg = AUTONEG_ENABLE;
291 ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
292 ecmd->advertising |=
293 (ADVERTISED_TP | ADVERTISED_Autoneg);
294 ecmd->port = PORT_TP;
295 }
296 break;
297 default:
298 dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
b1fc6d3c 299 adapter->ahw->board_type);
af19b491
AKS
300 return -EIO;
301 }
302
303 if (check_sfp_module) {
304 switch (adapter->module_type) {
305 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
306 case LINKEVENT_MODULE_OPTICAL_SRLR:
307 case LINKEVENT_MODULE_OPTICAL_LRM:
308 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
309 ecmd->port = PORT_FIBRE;
310 break;
311 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
312 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
313 case LINKEVENT_MODULE_TWINAX:
314 ecmd->port = PORT_TP;
315 break;
316 default:
317 ecmd->port = PORT_OTHER;
318 }
319 }
320
321 return 0;
322}
323
324static int
325qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
326{
7e610caa
SC
327 u32 config = 0;
328 u32 ret = 0;
af19b491 329 struct qlcnic_adapter *adapter = netdev_priv(dev);
7e610caa
SC
330
331 if (adapter->ahw->port_type != QLCNIC_GBE)
332 return -EOPNOTSUPP;
af19b491
AKS
333
334 /* read which mode */
7e610caa
SC
335 if (ecmd->duplex)
336 config |= 0x1;
af19b491 337
7e610caa
SC
338 if (ecmd->autoneg)
339 config |= 0x2;
340
341 switch (ethtool_cmd_speed(ecmd)) {
342 case SPEED_10:
343 config |= (0 << 8);
344 break;
345 case SPEED_100:
346 config |= (1 << 8);
347 break;
348 case SPEED_1000:
349 config |= (10 << 8);
350 break;
351 default:
352 return -EIO;
353 }
354
355 ret = qlcnic_fw_cmd_set_port(adapter, config);
356
357 if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
af19b491 358 return -EOPNOTSUPP;
7e610caa
SC
359 else if (ret)
360 return -EIO;
361
362 adapter->link_speed = ethtool_cmd_speed(ecmd);
363 adapter->link_duplex = ecmd->duplex;
364 adapter->link_autoneg = ecmd->autoneg;
af19b491
AKS
365
366 if (!netif_running(dev))
367 return 0;
368
369 dev->netdev_ops->ndo_stop(dev);
370 return dev->netdev_ops->ndo_open(dev);
371}
372
373static void
374qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
375{
376 struct qlcnic_adapter *adapter = netdev_priv(dev);
b1fc6d3c 377 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
af19b491
AKS
378 struct qlcnic_host_sds_ring *sds_ring;
379 u32 *regs_buff = p;
c265eb6e 380 int ring, i = 0, j = 0;
af19b491
AKS
381
382 memset(p, 0, qlcnic_get_regs_len(dev));
2cffcdbf 383 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
b1fc6d3c 384 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
af19b491 385
2cffcdbf
RB
386 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
387 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
388
c265eb6e
AKS
389 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
390 regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
af19b491 391
8a15ad1f 392 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
ce668443
AKS
393 return;
394
af19b491
AKS
395 regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
396
397 regs_buff[i++] = 1; /* No. of tx ring */
398 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
399 regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
400
401 regs_buff[i++] = 2; /* No. of rx ring */
402 regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
403 regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
404
405 regs_buff[i++] = adapter->max_sds_rings;
406
407 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
408 sds_ring = &(recv_ctx->sds_rings[ring]);
409 regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
410 }
411}
412
413static u32 qlcnic_test_link(struct net_device *dev)
414{
415 struct qlcnic_adapter *adapter = netdev_priv(dev);
416 u32 val;
417
ff1b1bf8 418 val = QLCRD32(adapter, CRB_XG_STATE_P3P);
b1fc6d3c 419 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
ff1b1bf8 420 return (val == XG_LINK_UP_P3P) ? 0 : 1;
af19b491
AKS
421}
422
423static int
424qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
425 u8 *bytes)
426{
427 struct qlcnic_adapter *adapter = netdev_priv(dev);
428 int offset;
429 int ret;
430
431 if (eeprom->len == 0)
432 return -EINVAL;
433
434 eeprom->magic = (adapter->pdev)->vendor |
435 ((adapter->pdev)->device << 16);
436 offset = eeprom->offset;
437
438 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
439 eeprom->len);
440 if (ret < 0)
441 return ret;
442
443 return 0;
444}
445
446static void
447qlcnic_get_ringparam(struct net_device *dev,
448 struct ethtool_ringparam *ring)
449{
450 struct qlcnic_adapter *adapter = netdev_priv(dev);
451
452 ring->rx_pending = adapter->num_rxd;
453 ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
af19b491
AKS
454 ring->tx_pending = adapter->num_txd;
455
90d19005
SC
456 ring->rx_max_pending = adapter->max_rxd;
457 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
af19b491 458 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
af19b491
AKS
459}
460
461static u32
462qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
463{
464 u32 num_desc;
465 num_desc = max(val, min);
466 num_desc = min(num_desc, max);
467 num_desc = roundup_pow_of_two(num_desc);
468
469 if (val != num_desc) {
470 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
471 qlcnic_driver_name, r_name, num_desc, val);
472 }
473
474 return num_desc;
475}
476
477static int
478qlcnic_set_ringparam(struct net_device *dev,
479 struct ethtool_ringparam *ring)
480{
481 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
482 u16 num_rxd, num_jumbo_rxd, num_txd;
483
af19b491
AKS
484 if (ring->rx_mini_pending)
485 return -EOPNOTSUPP;
486
af19b491 487 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
90d19005 488 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
af19b491
AKS
489
490 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
90d19005
SC
491 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
492 "rx jumbo");
af19b491
AKS
493
494 num_txd = qlcnic_validate_ringparam(ring->tx_pending,
495 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
496
497 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
498 num_jumbo_rxd == adapter->num_jumbo_rxd)
499 return 0;
500
501 adapter->num_rxd = num_rxd;
502 adapter->num_jumbo_rxd = num_jumbo_rxd;
503 adapter->num_txd = num_txd;
504
505 return qlcnic_reset_context(adapter);
506}
507
f94bc1e7
SC
508static void qlcnic_get_channels(struct net_device *dev,
509 struct ethtool_channels *channel)
510{
511 struct qlcnic_adapter *adapter = netdev_priv(dev);
512
513 channel->max_rx = rounddown_pow_of_two(min_t(int,
514 adapter->max_rx_ques, num_online_cpus()));
515 channel->max_tx = adapter->max_tx_ques;
516
517 channel->rx_count = adapter->max_sds_rings;
518 channel->tx_count = adapter->max_tx_ques;
519}
520
521static int qlcnic_set_channels(struct net_device *dev,
522 struct ethtool_channels *channel)
523{
524 struct qlcnic_adapter *adapter = netdev_priv(dev);
525 int err;
526
527 if (channel->other_count || channel->combined_count ||
528 channel->tx_count != channel->max_tx)
529 return -EINVAL;
530
531 err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count);
532 if (err)
533 return err;
534
535 err = qlcnic_set_max_rss(adapter, channel->rx_count);
536 netdev_info(dev, "allocated 0x%x sds rings\n",
537 adapter->max_sds_rings);
538 return err;
539}
540
af19b491
AKS
541static void
542qlcnic_get_pauseparam(struct net_device *netdev,
543 struct ethtool_pauseparam *pause)
544{
545 struct qlcnic_adapter *adapter = netdev_priv(netdev);
546 int port = adapter->physical_port;
547 __u32 val;
548
b1fc6d3c 549 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
550 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
551 return;
552 /* get flow control settings */
553 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
554 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
555 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
556 switch (port) {
557 case 0:
558 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
559 break;
560 case 1:
561 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
562 break;
563 case 2:
564 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
565 break;
566 case 3:
567 default:
568 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
569 break;
570 }
b1fc6d3c 571 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
572 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
573 return;
574 pause->rx_pause = 1;
575 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
576 if (port == 0)
577 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
578 else
579 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
580 } else {
581 dev_err(&netdev->dev, "Unknown board type: %x\n",
b1fc6d3c 582 adapter->ahw->port_type);
af19b491
AKS
583 }
584}
585
586static int
587qlcnic_set_pauseparam(struct net_device *netdev,
588 struct ethtool_pauseparam *pause)
589{
590 struct qlcnic_adapter *adapter = netdev_priv(netdev);
591 int port = adapter->physical_port;
592 __u32 val;
593
594 /* read mode */
b1fc6d3c 595 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
596 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
597 return -EIO;
598 /* set flow control */
599 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
600
601 if (pause->rx_pause)
602 qlcnic_gb_rx_flowctl(val);
603 else
604 qlcnic_gb_unset_rx_flowctl(val);
605
606 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
607 val);
608 /* set autoneg */
609 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
610 switch (port) {
611 case 0:
612 if (pause->tx_pause)
613 qlcnic_gb_unset_gb0_mask(val);
614 else
615 qlcnic_gb_set_gb0_mask(val);
616 break;
617 case 1:
618 if (pause->tx_pause)
619 qlcnic_gb_unset_gb1_mask(val);
620 else
621 qlcnic_gb_set_gb1_mask(val);
622 break;
623 case 2:
624 if (pause->tx_pause)
625 qlcnic_gb_unset_gb2_mask(val);
626 else
627 qlcnic_gb_set_gb2_mask(val);
628 break;
629 case 3:
630 default:
631 if (pause->tx_pause)
632 qlcnic_gb_unset_gb3_mask(val);
633 else
634 qlcnic_gb_set_gb3_mask(val);
635 break;
636 }
637 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
b1fc6d3c 638 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
6d181688
RB
639 if (!pause->rx_pause || pause->autoneg)
640 return -EOPNOTSUPP;
641
af19b491
AKS
642 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
643 return -EIO;
6d181688 644
af19b491
AKS
645 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
646 if (port == 0) {
647 if (pause->tx_pause)
648 qlcnic_xg_unset_xg0_mask(val);
649 else
650 qlcnic_xg_set_xg0_mask(val);
651 } else {
652 if (pause->tx_pause)
653 qlcnic_xg_unset_xg1_mask(val);
654 else
655 qlcnic_xg_set_xg1_mask(val);
656 }
657 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
658 } else {
659 dev_err(&netdev->dev, "Unknown board type: %x\n",
b1fc6d3c 660 adapter->ahw->port_type);
af19b491
AKS
661 }
662 return 0;
663}
664
665static int qlcnic_reg_test(struct net_device *dev)
666{
667 struct qlcnic_adapter *adapter = netdev_priv(dev);
deffab05 668 u32 data_read;
af19b491
AKS
669
670 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
671 if ((data_read & 0xffff) != adapter->pdev->vendor)
672 return 1;
673
af19b491
AKS
674 return 0;
675}
676
677static int qlcnic_get_sset_count(struct net_device *dev, int sset)
678{
3666e0b0 679 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
680 switch (sset) {
681 case ETH_SS_TEST:
682 return QLCNIC_TEST_LEN;
683 case ETH_SS_STATS:
3666e0b0 684 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
54a8997c
JK
685 return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
686 return QLCNIC_TOTAL_STATS_LEN;
af19b491
AKS
687 default:
688 return -EOPNOTSUPP;
689 }
690}
691
7eb9855d
AKS
692static int qlcnic_irq_test(struct net_device *netdev)
693{
694 struct qlcnic_adapter *adapter = netdev_priv(netdev);
695 int max_sds_rings = adapter->max_sds_rings;
696 int ret;
7777de9a 697 struct qlcnic_cmd_args cmd;
7eb9855d
AKS
698
699 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
700 return -EIO;
701
702 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
703 if (ret)
704 goto clear_it;
705
706 adapter->diag_cnt = 0;
7777de9a
AC
707 memset(&cmd, 0, sizeof(cmd));
708 cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
709 cmd.req.arg1 = adapter->ahw->pci_func;
710 qlcnic_issue_cmd(adapter, &cmd);
711 ret = cmd.rsp.cmd;
712
7eb9855d
AKS
713 if (ret)
714 goto done;
715
716 msleep(10);
717
718 ret = !adapter->diag_cnt;
719
720done:
721 qlcnic_diag_free_res(netdev, max_sds_rings);
722
723clear_it:
724 adapter->max_sds_rings = max_sds_rings;
725 clear_bit(__QLCNIC_RESETTING, &adapter->state);
726 return ret;
727}
728
22c8c934
SC
729#define QLCNIC_ILB_PKT_SIZE 64
730#define QLCNIC_NUM_ILB_PKT 16
731#define QLCNIC_ILB_MAX_RCV_LOOP 10
732
733static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
734{
735 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
736
737 memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
738
739 memcpy(data, mac, ETH_ALEN);
740 memcpy(data + ETH_ALEN, mac, ETH_ALEN);
741
742 memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
743}
744
745int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
746{
747 unsigned char buff[QLCNIC_ILB_PKT_SIZE];
748 qlcnic_create_loopback_buff(buff, mac);
749 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
750}
751
df3cfbe3 752static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
22c8c934
SC
753{
754 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
755 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
756 struct sk_buff *skb;
757 int i, loop, cnt = 0;
758
759 for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
dae2e9f4 760 skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
22c8c934
SC
761 qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
762 skb_put(skb, QLCNIC_ILB_PKT_SIZE);
763
764 adapter->diag_cnt = 0;
765 qlcnic_xmit_frame(skb, adapter->netdev);
766
767 loop = 0;
768 do {
769 msleep(1);
770 qlcnic_process_rcv_ring_diag(sds_ring);
771 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
772 break;
773 } while (!adapter->diag_cnt);
774
775 dev_kfree_skb_any(skb);
776
777 if (!adapter->diag_cnt)
df3cfbe3
M
778 QLCDB(adapter, DRV,
779 "LB Test: packet #%d was not received\n", i + 1);
22c8c934
SC
780 else
781 cnt++;
782 }
783 if (cnt != i) {
e1428d26 784 dev_warn(&adapter->pdev->dev, "LB Test failed\n");
df3cfbe3
M
785 if (mode != QLCNIC_ILB_MODE) {
786 dev_warn(&adapter->pdev->dev,
787 "WARNING: Please make sure external"
788 "loopback connector is plugged in\n");
789 }
22c8c934
SC
790 return -1;
791 }
792 return 0;
793}
794
e1428d26 795static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
22c8c934
SC
796{
797 struct qlcnic_adapter *adapter = netdev_priv(netdev);
798 int max_sds_rings = adapter->max_sds_rings;
799 struct qlcnic_host_sds_ring *sds_ring;
800 int loop = 0;
801 int ret;
802
fef0c060
AKS
803 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
804 netdev_info(netdev, "Firmware is not loopback test capable\n");
805 return -EOPNOTSUPP;
806 }
807
df3cfbe3 808 QLCDB(adapter, DRV, "%s loopback test in progress\n",
e1428d26 809 mode == QLCNIC_ILB_MODE ? "internal" : "external");
22c8c934
SC
810 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
811 netdev_warn(netdev, "Loopback test not supported for non "
812 "privilege function\n");
813 return 0;
814 }
815
816 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
fef0c060 817 return -EBUSY;
22c8c934
SC
818
819 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
820 if (ret)
821 goto clear_it;
822
823 sds_ring = &adapter->recv_ctx->sds_rings[0];
824
e1428d26 825 ret = qlcnic_set_lb_mode(adapter, mode);
22c8c934
SC
826 if (ret)
827 goto free_res;
828
fef0c060 829 adapter->diag_cnt = 0;
22c8c934
SC
830 do {
831 msleep(500);
832 qlcnic_process_rcv_ring_diag(sds_ring);
fef0c060
AKS
833 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
834 netdev_info(netdev, "firmware didnt respond to loopback"
835 " configure request\n");
836 ret = -QLCNIC_FW_NOT_RESPOND;
837 goto free_res;
838 } else if (adapter->diag_cnt) {
839 ret = adapter->diag_cnt;
840 goto free_res;
841 }
22c8c934
SC
842 } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
843
df3cfbe3 844 ret = qlcnic_do_lb_test(adapter, mode);
22c8c934
SC
845
846 qlcnic_clear_lb_mode(adapter);
847
848 free_res:
849 qlcnic_diag_free_res(netdev, max_sds_rings);
850
851 clear_it:
852 adapter->max_sds_rings = max_sds_rings;
853 clear_bit(__QLCNIC_RESETTING, &adapter->state);
854 return ret;
855}
856
af19b491
AKS
857static void
858qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
859 u64 *data)
860{
861 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
897d3596 862
8dec32cc
SC
863 data[0] = qlcnic_reg_test(dev);
864 if (data[0])
865 eth_test->flags |= ETH_TEST_FL_FAILED;
866
867 data[1] = (u64) qlcnic_test_link(dev);
868 if (data[1])
869 eth_test->flags |= ETH_TEST_FL_FAILED;
870
13b93ed9 871 if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
7eb9855d
AKS
872 data[2] = qlcnic_irq_test(dev);
873 if (data[2])
874 eth_test->flags |= ETH_TEST_FL_FAILED;
cdaff185 875
e1428d26 876 data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
22c8c934
SC
877 if (data[3])
878 eth_test->flags |= ETH_TEST_FL_FAILED;
e1428d26
AKS
879 if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
880 data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
881 if (data[4])
882 eth_test->flags |= ETH_TEST_FL_FAILED;
883 eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
884 }
7eb9855d 885 }
af19b491
AKS
886}
887
888static void
889qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
890{
3666e0b0 891 struct qlcnic_adapter *adapter = netdev_priv(dev);
54a8997c 892 int index, i, j;
af19b491
AKS
893
894 switch (stringset) {
895 case ETH_SS_TEST:
896 memcpy(data, *qlcnic_gstrings_test,
897 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
898 break;
899 case ETH_SS_STATS:
900 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
901 memcpy(data + index * ETH_GSTRING_LEN,
902 qlcnic_gstrings_stats[index].stat_string,
903 ETH_GSTRING_LEN);
904 }
54a8997c
JK
905 for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) {
906 memcpy(data + index * ETH_GSTRING_LEN,
907 qlcnic_mac_stats_strings[j],
908 ETH_GSTRING_LEN);
909 }
3666e0b0 910 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
911 return;
912 for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
913 memcpy(data + index * ETH_GSTRING_LEN,
914 qlcnic_device_gstrings_stats[i],
915 ETH_GSTRING_LEN);
916 }
af19b491
AKS
917 }
918}
919
3666e0b0 920static void
54a8997c 921qlcnic_fill_stats(int *index, u64 *data, void *stats, int type)
3666e0b0 922{
923 int ind = *index;
924
54a8997c
JK
925 if (type == QLCNIC_MAC_STATS) {
926 struct qlcnic_mac_statistics *mac_stats =
927 (struct qlcnic_mac_statistics *)stats;
928 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
929 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
930 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
931 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
932 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
933 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
934 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
935 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
936 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
937 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
938 data[ind++] =
939 QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
940 data[ind++] =
941 QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
942 data[ind++] =
943 QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
944 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
945 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
946 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
947 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
948 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
949 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
950 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
951 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
952 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
953 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
954 data[ind++] =
955 QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
956 data[ind++] =
957 QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
958 data[ind++] =
959 QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
960 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
961 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
962 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
963 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
964 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
965 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
966 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
967 } else if (type == QLCNIC_ESW_STATS) {
968 struct __qlcnic_esw_statistics *esw_stats =
969 (struct __qlcnic_esw_statistics *)stats;
970 data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
971 data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
972 data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
973 data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
974 data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors);
975 data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames);
976 data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes);
977 }
3666e0b0 978
979 *index = ind;
980}
981
af19b491
AKS
982static void
983qlcnic_get_ethtool_stats(struct net_device *dev,
984 struct ethtool_stats *stats, u64 * data)
985{
986 struct qlcnic_adapter *adapter = netdev_priv(dev);
3666e0b0 987 struct qlcnic_esw_statistics port_stats;
54a8997c 988 struct qlcnic_mac_statistics mac_stats;
3666e0b0 989 int index, ret;
af19b491
AKS
990
991 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
992 char *p =
993 (char *)adapter +
994 qlcnic_gstrings_stats[index].stat_offset;
995 data[index] =
996 (qlcnic_gstrings_stats[index].sizeof_stat ==
997 sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
998 }
3666e0b0 999
54a8997c
JK
1000 /* Retrieve MAC statistics from firmware */
1001 memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
1002 qlcnic_get_mac_stats(adapter, &mac_stats);
1003 qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS);
1004
3666e0b0 1005 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1006 return;
1007
1008 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
b1fc6d3c 1009 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
3666e0b0 1010 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
1011 if (ret)
1012 return;
1013
54a8997c 1014 qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS);
3666e0b0 1015
b1fc6d3c 1016 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
3666e0b0 1017 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
1018 if (ret)
1019 return;
1020
54a8997c 1021 qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS);
af19b491
AKS
1022}
1023
94469f75 1024static int qlcnic_set_led(struct net_device *dev,
1025 enum ethtool_phys_id_state state)
897d3596
SC
1026{
1027 struct qlcnic_adapter *adapter = netdev_priv(dev);
c75822a3 1028 int max_sds_rings = adapter->max_sds_rings;
10ee0fae
SC
1029 int err = -EIO, active = 1;
1030
1031 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
1032 netdev_warn(dev, "LED test not supported for non "
1033 "privilege function\n");
1034 return -EOPNOTSUPP;
1035 }
c75822a3 1036
94469f75 1037 switch (state) {
1038 case ETHTOOL_ID_ACTIVE:
728a98b8
SC
1039 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1040 return -EBUSY;
1041
10ee0fae
SC
1042 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1043 break;
94469f75 1044
10ee0fae
SC
1045 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1046 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
1047 break;
89b4208e 1048 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
c75822a3 1049 }
8a15ad1f 1050
10ee0fae
SC
1051 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
1052 err = 0;
1053 break;
1054 }
94469f75 1055
897d3596
SC
1056 dev_err(&adapter->pdev->dev,
1057 "Failed to set LED blink state.\n");
94469f75 1058 break;
897d3596 1059
94469f75 1060 case ETHTOOL_ID_INACTIVE:
10ee0fae
SC
1061 active = 0;
1062
1063 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1064 break;
1065
1066 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1067 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
1068 break;
1069 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
1070 }
1071
89b4208e
SC
1072 if (adapter->nic_ops->config_led(adapter, 0, 0xf))
1073 dev_err(&adapter->pdev->dev,
1074 "Failed to reset LED blink state.\n");
897d3596 1075
94469f75 1076 break;
1077
1078 default:
1079 return -EINVAL;
897d3596
SC
1080 }
1081
10ee0fae 1082 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
c75822a3 1083 qlcnic_diag_free_res(dev, max_sds_rings);
c75822a3 1084
10ee0fae
SC
1085 if (!active || err)
1086 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
728a98b8 1087
10ee0fae 1088 return err;
897d3596
SC
1089}
1090
af19b491
AKS
1091static void
1092qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1093{
1094 struct qlcnic_adapter *adapter = netdev_priv(dev);
1095 u32 wol_cfg;
1096
1097 wol->supported = 0;
1098 wol->wolopts = 0;
1099
1100 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1101 if (wol_cfg & (1UL << adapter->portnum))
1102 wol->supported |= WAKE_MAGIC;
1103
1104 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1105 if (wol_cfg & (1UL << adapter->portnum))
1106 wol->wolopts |= WAKE_MAGIC;
1107}
1108
1109static int
1110qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1111{
1112 struct qlcnic_adapter *adapter = netdev_priv(dev);
1113 u32 wol_cfg;
1114
1115 if (wol->wolopts & ~WAKE_MAGIC)
1116 return -EOPNOTSUPP;
1117
1118 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1119 if (!(wol_cfg & (1 << adapter->portnum)))
1120 return -EOPNOTSUPP;
1121
1122 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1123 if (wol->wolopts & WAKE_MAGIC)
1124 wol_cfg |= 1UL << adapter->portnum;
1125 else
1126 wol_cfg &= ~(1UL << adapter->portnum);
1127
1128 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1129
1130 return 0;
1131}
1132
1133/*
1134 * Set the coalescing parameters. Currently only normal is supported.
1135 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1136 * firmware coalescing to default.
1137 */
1138static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1139 struct ethtool_coalesce *ethcoal)
1140{
1141 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1142
8a15ad1f 1143 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
af19b491
AKS
1144 return -EINVAL;
1145
1146 /*
1147 * Return Error if unsupported values or
1148 * unsupported parameters are set.
1149 */
1150 if (ethcoal->rx_coalesce_usecs > 0xffff ||
1151 ethcoal->rx_max_coalesced_frames > 0xffff ||
8816d009
AC
1152 ethcoal->tx_coalesce_usecs ||
1153 ethcoal->tx_max_coalesced_frames ||
af19b491
AKS
1154 ethcoal->rx_coalesce_usecs_irq ||
1155 ethcoal->rx_max_coalesced_frames_irq ||
1156 ethcoal->tx_coalesce_usecs_irq ||
1157 ethcoal->tx_max_coalesced_frames_irq ||
1158 ethcoal->stats_block_coalesce_usecs ||
1159 ethcoal->use_adaptive_rx_coalesce ||
1160 ethcoal->use_adaptive_tx_coalesce ||
1161 ethcoal->pkt_rate_low ||
1162 ethcoal->rx_coalesce_usecs_low ||
1163 ethcoal->rx_max_coalesced_frames_low ||
1164 ethcoal->tx_coalesce_usecs_low ||
1165 ethcoal->tx_max_coalesced_frames_low ||
1166 ethcoal->pkt_rate_high ||
1167 ethcoal->rx_coalesce_usecs_high ||
1168 ethcoal->rx_max_coalesced_frames_high ||
1169 ethcoal->tx_coalesce_usecs_high ||
1170 ethcoal->tx_max_coalesced_frames_high)
1171 return -EINVAL;
1172
1173 if (!ethcoal->rx_coalesce_usecs ||
1174 !ethcoal->rx_max_coalesced_frames) {
8816d009
AC
1175 adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
1176 adapter->ahw->coal.rx_time_us =
af19b491 1177 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
8816d009 1178 adapter->ahw->coal.rx_packets =
af19b491
AKS
1179 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
1180 } else {
8816d009
AC
1181 adapter->ahw->coal.flag = 0;
1182 adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
1183 adapter->ahw->coal.rx_packets =
1184 ethcoal->rx_max_coalesced_frames;
af19b491 1185 }
af19b491
AKS
1186
1187 qlcnic_config_intr_coalesce(adapter);
1188
1189 return 0;
1190}
1191
1192static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1193 struct ethtool_coalesce *ethcoal)
1194{
1195 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1196
1197 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1198 return -EINVAL;
1199
8816d009
AC
1200 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1201 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
af19b491
AKS
1202
1203 return 0;
1204}
1205
65b5b420
AKS
1206static u32 qlcnic_get_msglevel(struct net_device *netdev)
1207{
1208 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1209
1210 return adapter->msg_enable;
1211}
1212
1213static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1214{
1215 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1216
1217 adapter->msg_enable = msglvl;
1218}
1219
b3c68731
AC
1220static int
1221qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1222{
1223 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1224 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1225
b43e5ee7
SC
1226 if (!fw_dump->tmpl_hdr) {
1227 netdev_err(adapter->netdev, "FW Dump not supported\n");
1228 return -ENOTSUPP;
1229 }
1230
3d46512c
AC
1231 if (fw_dump->clr)
1232 dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
1233 else
1234 dump->len = 0;
bcebe559
M
1235
1236 if (!fw_dump->enable)
1237 dump->flag = ETH_FW_DUMP_DISABLE;
1238 else
1239 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1240
b3c68731
AC
1241 dump->version = adapter->fw_version;
1242 return 0;
1243}
1244
1245static int
1246qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1247 void *buffer)
1248{
1249 int i, copy_sz;
1250 u32 *hdr_ptr, *data;
1251 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1252 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1253
b43e5ee7
SC
1254 if (!fw_dump->tmpl_hdr) {
1255 netdev_err(netdev, "FW Dump not supported\n");
1256 return -ENOTSUPP;
1257 }
1258
b3c68731
AC
1259 if (!fw_dump->clr) {
1260 netdev_info(netdev, "Dump not available\n");
b3c68731
AC
1261 return -EINVAL;
1262 }
1263 /* Copy template header first */
1264 copy_sz = fw_dump->tmpl_hdr->size;
1265 hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
43d620c8 1266 data = buffer;
b3c68731
AC
1267 for (i = 0; i < copy_sz/sizeof(u32); i++)
1268 *data++ = cpu_to_le32(*hdr_ptr++);
1269
1270 /* Copy captured dump data */
1271 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1272 dump->len = copy_sz + fw_dump->size;
1273 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1274
1275 /* Free dump area once data has been captured */
1276 vfree(fw_dump->data);
1277 fw_dump->data = NULL;
1278 fw_dump->clr = 0;
c47884e4 1279 netdev_info(netdev, "extracted the FW dump Successfully\n");
b3c68731
AC
1280 return 0;
1281}
1282
1283static int
1284qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1285{
4fbec4d8 1286 int i;
b3c68731
AC
1287 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1288 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
b43e5ee7 1289 u32 state;
b3c68731 1290
3d46512c
AC
1291 switch (val->flag) {
1292 case QLCNIC_FORCE_FW_DUMP_KEY:
b43e5ee7
SC
1293 if (!fw_dump->tmpl_hdr) {
1294 netdev_err(netdev, "FW dump not supported\n");
1295 return -ENOTSUPP;
1296 }
9d6a6440
AC
1297 if (!fw_dump->enable) {
1298 netdev_info(netdev, "FW dump not enabled\n");
4fbec4d8 1299 return 0;
9d6a6440
AC
1300 }
1301 if (fw_dump->clr) {
c47884e4 1302 netdev_info(netdev,
9d6a6440 1303 "Previous dump not cleared, not forcing dump\n");
4fbec4d8 1304 return 0;
9d6a6440 1305 }
b3c68731
AC
1306 netdev_info(netdev, "Forcing a FW dump\n");
1307 qlcnic_dev_request_reset(adapter);
3d46512c
AC
1308 break;
1309 case QLCNIC_DISABLE_FW_DUMP:
b43e5ee7 1310 if (fw_dump->enable && fw_dump->tmpl_hdr) {
9d6a6440
AC
1311 netdev_info(netdev, "Disabling FW dump\n");
1312 fw_dump->enable = 0;
1313 }
4fbec4d8 1314 return 0;
3d46512c 1315 case QLCNIC_ENABLE_FW_DUMP:
b43e5ee7
SC
1316 if (!fw_dump->tmpl_hdr) {
1317 netdev_err(netdev, "FW dump not supported\n");
1318 return -ENOTSUPP;
1319 }
1320 if (!fw_dump->enable) {
9d6a6440
AC
1321 netdev_info(netdev, "Enabling FW dump\n");
1322 fw_dump->enable = 1;
1323 }
4fbec4d8 1324 return 0;
3d46512c
AC
1325 case QLCNIC_FORCE_FW_RESET:
1326 netdev_info(netdev, "Forcing a FW reset\n");
1327 qlcnic_dev_request_reset(adapter);
1328 adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
4fbec4d8 1329 return 0;
b43e5ee7
SC
1330 case QLCNIC_SET_QUIESCENT:
1331 case QLCNIC_RESET_QUIESCENT:
1332 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
1333 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
1334 netdev_info(netdev, "Device in FAILED state\n");
4fbec4d8 1335 return 0;
3d46512c 1336 default:
b43e5ee7
SC
1337 if (!fw_dump->tmpl_hdr) {
1338 netdev_err(netdev, "FW dump not supported\n");
1339 return -ENOTSUPP;
1340 }
4fbec4d8
MC
1341 for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
1342 if (val->flag == FW_DUMP_LEVELS[i]) {
1343 fw_dump->tmpl_hdr->drv_cap_mask =
1344 val->flag;
1345 netdev_info(netdev, "Driver mask changed to: 0x%x\n",
1346 fw_dump->tmpl_hdr->drv_cap_mask);
1347 return 0;
1348 }
b3c68731 1349 }
4fbec4d8
MC
1350 netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag);
1351 return -EINVAL;
b3c68731 1352 }
4fbec4d8 1353 return 0;
b3c68731
AC
1354}
1355
af19b491
AKS
1356const struct ethtool_ops qlcnic_ethtool_ops = {
1357 .get_settings = qlcnic_get_settings,
1358 .set_settings = qlcnic_set_settings,
1359 .get_drvinfo = qlcnic_get_drvinfo,
1360 .get_regs_len = qlcnic_get_regs_len,
1361 .get_regs = qlcnic_get_regs,
1362 .get_link = ethtool_op_get_link,
1363 .get_eeprom_len = qlcnic_get_eeprom_len,
1364 .get_eeprom = qlcnic_get_eeprom,
1365 .get_ringparam = qlcnic_get_ringparam,
1366 .set_ringparam = qlcnic_set_ringparam,
f94bc1e7
SC
1367 .get_channels = qlcnic_get_channels,
1368 .set_channels = qlcnic_set_channels,
af19b491
AKS
1369 .get_pauseparam = qlcnic_get_pauseparam,
1370 .set_pauseparam = qlcnic_set_pauseparam,
af19b491
AKS
1371 .get_wol = qlcnic_get_wol,
1372 .set_wol = qlcnic_set_wol,
1373 .self_test = qlcnic_diag_test,
1374 .get_strings = qlcnic_get_strings,
1375 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1376 .get_sset_count = qlcnic_get_sset_count,
af19b491
AKS
1377 .get_coalesce = qlcnic_get_intr_coalesce,
1378 .set_coalesce = qlcnic_set_intr_coalesce,
94469f75 1379 .set_phys_id = qlcnic_set_led,
65b5b420
AKS
1380 .set_msglevel = qlcnic_set_msglevel,
1381 .get_msglevel = qlcnic_get_msglevel,
b3c68731
AC
1382 .get_dump_flag = qlcnic_get_dump_flag,
1383 .get_dump_data = qlcnic_get_dump_data,
1384 .set_dump = qlcnic_set_dump,
af19b491 1385};
b43e5ee7
SC
1386
1387const struct ethtool_ops qlcnic_ethtool_failed_ops = {
1388 .get_settings = qlcnic_get_settings,
1389 .get_drvinfo = qlcnic_get_drvinfo,
1390 .set_msglevel = qlcnic_set_msglevel,
1391 .get_msglevel = qlcnic_get_msglevel,
1392};