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