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