aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
diff options
context:
space:
mode:
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-04-08 22:06:30 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2011-08-10 23:03:49 -0400
commitaa43c2158d5ae1dc76cccb08cd57a3ffd32c3825 (patch)
treecdb471f2b2440d551e634f9cbeacf1675daf3ba8 /drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
parentdee1ad47f2ee75f5146d83ca757c1b7861c34c3b (diff)
qlogic: Move the QLogic drivers
Moves the QLogic drivers into drivers/net/ethernet/qlogic/ and the necessary Kconfig and Makefile changes. CC: Ron Mercer <ron.mercer@qlogic.com> CC: Amit Kumar Salecha <amit.salecha@qlogic.com> CC: Anirban Chakraborty <anirban.chakraborty@qlogic.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Acked-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c1234
1 files changed, 1234 insertions, 0 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
new file mode 100644
index 000000000000..7c64f2ffc219
--- /dev/null
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -0,0 +1,1234 @@
1/*
2 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2010 QLogic Corporation
4 *
5 * See LICENSE.qlcnic for copyright and licensing details.
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)},
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)},
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)},
61
62};
63
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
81#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
82#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
83
84static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
85 "Register_Test_on_offline",
86 "Link_Test_on_offline",
87 "Interrupt_Test_offline",
88 "Internal_Loopback_offline",
89 "External_Loopback_offline"
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,
101 CRB_XG_STATE_P3P,
102 CRB_FW_CAPABILITIES_1,
103 ISR_INT_STATE_REG,
104 QLCNIC_CRB_DRV_ACTIVE,
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
120#define QLCNIC_MGMT_API_VERSION 2
121#define QLCNIC_DEV_INFO_SIZE 1
122#define QLCNIC_ETHTOOL_REGS_VER 2
123static int qlcnic_get_regs_len(struct net_device *dev)
124{
125 return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
126 QLCNIC_DEV_INFO_SIZE + 1;
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;
155 u16 pcifn = adapter->ahw->pci_func;
156
157 /* read which mode */
158 if (adapter->ahw->port_type == QLCNIC_GBE) {
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
171 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
172 ecmd->duplex = adapter->link_duplex;
173 ecmd->autoneg = adapter->link_autoneg;
174
175 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
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) {
188 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
189 ecmd->autoneg = adapter->link_autoneg;
190 ecmd->duplex = adapter->link_duplex;
191 goto skip;
192 }
193
194 val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
195 ethtool_cmd_speed_set(ecmd, P3P_LINK_SPEED_MHZ *
196 P3P_LINK_SPEED_VAL(pcifn, val));
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
206 switch (adapter->ahw->board_type) {
207 case QLCNIC_BRDTYPE_P3P_REF_QG:
208 case QLCNIC_BRDTYPE_P3P_4_GB:
209 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
210
211 ecmd->supported |= SUPPORTED_Autoneg;
212 ecmd->advertising |= ADVERTISED_Autoneg;
213 case QLCNIC_BRDTYPE_P3P_10G_CX4:
214 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
215 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
216 ecmd->supported |= SUPPORTED_TP;
217 ecmd->advertising |= ADVERTISED_TP;
218 ecmd->port = PORT_TP;
219 ecmd->autoneg = adapter->link_autoneg;
220 break;
221 case QLCNIC_BRDTYPE_P3P_IMEZ:
222 case QLCNIC_BRDTYPE_P3P_XG_LOM:
223 case QLCNIC_BRDTYPE_P3P_HMEZ:
224 ecmd->supported |= SUPPORTED_MII;
225 ecmd->advertising |= ADVERTISED_MII;
226 ecmd->port = PORT_MII;
227 ecmd->autoneg = AUTONEG_DISABLE;
228 break;
229 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
230 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
231 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
232 ecmd->advertising |= ADVERTISED_TP;
233 ecmd->supported |= SUPPORTED_TP;
234 check_sfp_module = netif_running(dev) &&
235 adapter->has_link_events;
236 case QLCNIC_BRDTYPE_P3P_10G_XFP:
237 ecmd->supported |= SUPPORTED_FIBRE;
238 ecmd->advertising |= ADVERTISED_FIBRE;
239 ecmd->port = PORT_FIBRE;
240 ecmd->autoneg = AUTONEG_DISABLE;
241 break;
242 case QLCNIC_BRDTYPE_P3P_10G_TP:
243 if (adapter->ahw->port_type == QLCNIC_XGBE) {
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",
261 adapter->ahw->board_type);
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{
289 u32 config = 0;
290 u32 ret = 0;
291 struct qlcnic_adapter *adapter = netdev_priv(dev);
292
293 if (adapter->ahw->port_type != QLCNIC_GBE)
294 return -EOPNOTSUPP;
295
296 /* read which mode */
297 if (ecmd->duplex)
298 config |= 0x1;
299
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)
320 return -EOPNOTSUPP;
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;
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);
339 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
340 struct qlcnic_host_sds_ring *sds_ring;
341 u32 *regs_buff = p;
342 int ring, i = 0, j = 0;
343
344 memset(p, 0, qlcnic_get_regs_len(dev));
345 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
346 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
347
348 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
349 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
350
351 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
352 regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
353
354 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
355 return;
356
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
380 val = QLCRD32(adapter, CRB_XG_STATE_P3P);
381 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
382 return (val == XG_LINK_UP_P3P) ? 0 : 1;
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;
416 ring->tx_pending = adapter->num_txd;
417
418 ring->rx_max_pending = adapter->max_rxd;
419 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
420 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
421
422 ring->rx_mini_max_pending = 0;
423 ring->rx_mini_pending = 0;
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);
447 u16 num_rxd, num_jumbo_rxd, num_txd;
448
449 if (ring->rx_mini_pending)
450 return -EOPNOTSUPP;
451
452 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
453 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
454
455 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
456 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
457 "rx jumbo");
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
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
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
514 if (adapter->ahw->port_type == QLCNIC_GBE) {
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 }
536 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
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",
547 adapter->ahw->port_type);
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 */
560 if (adapter->ahw->port_type == QLCNIC_GBE) {
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);
603 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
604 if (!pause->rx_pause || pause->autoneg)
605 return -EOPNOTSUPP;
606
607 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
608 return -EIO;
609
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",
625 adapter->ahw->port_type);
626 }
627 return 0;
628}
629
630static int qlcnic_reg_test(struct net_device *dev)
631{
632 struct qlcnic_adapter *adapter = netdev_priv(dev);
633 u32 data_read;
634
635 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
636 if ((data_read & 0xffff) != adapter->pdev->vendor)
637 return 1;
638
639 return 0;
640}
641
642static int qlcnic_get_sset_count(struct net_device *dev, int sset)
643{
644 struct qlcnic_adapter *adapter = netdev_priv(dev);
645 switch (sset) {
646 case ETH_SS_TEST:
647 return QLCNIC_TEST_LEN;
648 case ETH_SS_STATS:
649 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
650 return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
651 return QLCNIC_STATS_LEN;
652 default:
653 return -EOPNOTSUPP;
654 }
655}
656
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;
662
663 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
664 return -EIO;
665
666 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
667 if (ret)
668 goto clear_it;
669
670 adapter->diag_cnt = 0;
671 ret = qlcnic_issue_cmd(adapter, adapter->ahw->pci_func,
672 adapter->fw_hal_version, adapter->ahw->pci_func,
673 0, 0, 0x00000011);
674 if (ret)
675 goto done;
676
677 msleep(10);
678
679 ret = !adapter->diag_cnt;
680
681done:
682 qlcnic_diag_free_res(netdev, max_sds_rings);
683
684clear_it:
685 adapter->max_sds_rings = max_sds_rings;
686 clear_bit(__QLCNIC_RESETTING, &adapter->state);
687 return ret;
688}
689
690#define QLCNIC_ILB_PKT_SIZE 64
691#define QLCNIC_NUM_ILB_PKT 16
692#define QLCNIC_ILB_MAX_RCV_LOOP 10
693
694static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
695{
696 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
697
698 memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
699
700 memcpy(data, mac, ETH_ALEN);
701 memcpy(data + ETH_ALEN, mac, ETH_ALEN);
702
703 memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
704}
705
706int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
707{
708 unsigned char buff[QLCNIC_ILB_PKT_SIZE];
709 qlcnic_create_loopback_buff(buff, mac);
710 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
711}
712
713static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
714{
715 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
716 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
717 struct sk_buff *skb;
718 int i, loop, cnt = 0;
719
720 for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
721 skb = dev_alloc_skb(QLCNIC_ILB_PKT_SIZE);
722 qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
723 skb_put(skb, QLCNIC_ILB_PKT_SIZE);
724
725 adapter->diag_cnt = 0;
726 qlcnic_xmit_frame(skb, adapter->netdev);
727
728 loop = 0;
729 do {
730 msleep(1);
731 qlcnic_process_rcv_ring_diag(sds_ring);
732 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
733 break;
734 } while (!adapter->diag_cnt);
735
736 dev_kfree_skb_any(skb);
737
738 if (!adapter->diag_cnt)
739 dev_warn(&adapter->pdev->dev, "LB Test: %dth packet"
740 " not recevied\n", i + 1);
741 else
742 cnt++;
743 }
744 if (cnt != i) {
745 dev_warn(&adapter->pdev->dev, "LB Test failed\n");
746 return -1;
747 }
748 return 0;
749}
750
751static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
752{
753 struct qlcnic_adapter *adapter = netdev_priv(netdev);
754 int max_sds_rings = adapter->max_sds_rings;
755 struct qlcnic_host_sds_ring *sds_ring;
756 int loop = 0;
757 int ret;
758
759 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
760 netdev_info(netdev, "Firmware is not loopback test capable\n");
761 return -EOPNOTSUPP;
762 }
763
764 netdev_info(netdev, "%s loopback test in progress\n",
765 mode == QLCNIC_ILB_MODE ? "internal" : "external");
766 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
767 netdev_warn(netdev, "Loopback test not supported for non "
768 "privilege function\n");
769 return 0;
770 }
771
772 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
773 return -EBUSY;
774
775 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
776 if (ret)
777 goto clear_it;
778
779 sds_ring = &adapter->recv_ctx->sds_rings[0];
780
781 ret = qlcnic_set_lb_mode(adapter, mode);
782 if (ret)
783 goto free_res;
784
785 adapter->diag_cnt = 0;
786 do {
787 msleep(500);
788 qlcnic_process_rcv_ring_diag(sds_ring);
789 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
790 netdev_info(netdev, "firmware didnt respond to loopback"
791 " configure request\n");
792 ret = -QLCNIC_FW_NOT_RESPOND;
793 goto free_res;
794 } else if (adapter->diag_cnt) {
795 ret = adapter->diag_cnt;
796 goto free_res;
797 }
798 } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
799
800 ret = qlcnic_do_lb_test(adapter);
801
802 qlcnic_clear_lb_mode(adapter);
803
804 free_res:
805 qlcnic_diag_free_res(netdev, max_sds_rings);
806
807 clear_it:
808 adapter->max_sds_rings = max_sds_rings;
809 clear_bit(__QLCNIC_RESETTING, &adapter->state);
810 return ret;
811}
812
813static void
814qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
815 u64 *data)
816{
817 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
818
819 data[0] = qlcnic_reg_test(dev);
820 if (data[0])
821 eth_test->flags |= ETH_TEST_FL_FAILED;
822
823 data[1] = (u64) qlcnic_test_link(dev);
824 if (data[1])
825 eth_test->flags |= ETH_TEST_FL_FAILED;
826
827 if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
828 data[2] = qlcnic_irq_test(dev);
829 if (data[2])
830 eth_test->flags |= ETH_TEST_FL_FAILED;
831
832 data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
833 if (data[3])
834 eth_test->flags |= ETH_TEST_FL_FAILED;
835
836 if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
837 data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
838 if (data[4])
839 eth_test->flags |= ETH_TEST_FL_FAILED;
840 eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
841 }
842 }
843}
844
845static void
846qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
847{
848 struct qlcnic_adapter *adapter = netdev_priv(dev);
849 int index, i;
850
851 switch (stringset) {
852 case ETH_SS_TEST:
853 memcpy(data, *qlcnic_gstrings_test,
854 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
855 break;
856 case ETH_SS_STATS:
857 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
858 memcpy(data + index * ETH_GSTRING_LEN,
859 qlcnic_gstrings_stats[index].stat_string,
860 ETH_GSTRING_LEN);
861 }
862 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
863 return;
864 for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
865 memcpy(data + index * ETH_GSTRING_LEN,
866 qlcnic_device_gstrings_stats[i],
867 ETH_GSTRING_LEN);
868 }
869 }
870}
871
872#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
873 (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
874
875static void
876qlcnic_fill_device_stats(int *index, u64 *data,
877 struct __qlcnic_esw_statistics *stats)
878{
879 int ind = *index;
880
881 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
882 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
883 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
884 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
885 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
886 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
887 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
888
889 *index = ind;
890}
891
892static void
893qlcnic_get_ethtool_stats(struct net_device *dev,
894 struct ethtool_stats *stats, u64 * data)
895{
896 struct qlcnic_adapter *adapter = netdev_priv(dev);
897 struct qlcnic_esw_statistics port_stats;
898 int index, ret;
899
900 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
901 char *p =
902 (char *)adapter +
903 qlcnic_gstrings_stats[index].stat_offset;
904 data[index] =
905 (qlcnic_gstrings_stats[index].sizeof_stat ==
906 sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
907 }
908
909 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
910 return;
911
912 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
913 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
914 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
915 if (ret)
916 return;
917
918 qlcnic_fill_device_stats(&index, data, &port_stats.rx);
919
920 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
921 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
922 if (ret)
923 return;
924
925 qlcnic_fill_device_stats(&index, data, &port_stats.tx);
926}
927
928static int qlcnic_set_led(struct net_device *dev,
929 enum ethtool_phys_id_state state)
930{
931 struct qlcnic_adapter *adapter = netdev_priv(dev);
932 int max_sds_rings = adapter->max_sds_rings;
933
934 switch (state) {
935 case ETHTOOL_ID_ACTIVE:
936 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
937 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
938 return -EIO;
939
940 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) {
941 clear_bit(__QLCNIC_RESETTING, &adapter->state);
942 return -EIO;
943 }
944 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
945 }
946
947 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0)
948 return 0;
949
950 dev_err(&adapter->pdev->dev,
951 "Failed to set LED blink state.\n");
952 break;
953
954 case ETHTOOL_ID_INACTIVE:
955 if (adapter->nic_ops->config_led(adapter, 0, 0xf))
956 dev_err(&adapter->pdev->dev,
957 "Failed to reset LED blink state.\n");
958
959 break;
960
961 default:
962 return -EINVAL;
963 }
964
965 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) {
966 qlcnic_diag_free_res(dev, max_sds_rings);
967 clear_bit(__QLCNIC_RESETTING, &adapter->state);
968 }
969
970 return -EIO;
971}
972
973static void
974qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
975{
976 struct qlcnic_adapter *adapter = netdev_priv(dev);
977 u32 wol_cfg;
978
979 wol->supported = 0;
980 wol->wolopts = 0;
981
982 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
983 if (wol_cfg & (1UL << adapter->portnum))
984 wol->supported |= WAKE_MAGIC;
985
986 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
987 if (wol_cfg & (1UL << adapter->portnum))
988 wol->wolopts |= WAKE_MAGIC;
989}
990
991static int
992qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
993{
994 struct qlcnic_adapter *adapter = netdev_priv(dev);
995 u32 wol_cfg;
996
997 if (wol->wolopts & ~WAKE_MAGIC)
998 return -EOPNOTSUPP;
999
1000 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1001 if (!(wol_cfg & (1 << adapter->portnum)))
1002 return -EOPNOTSUPP;
1003
1004 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1005 if (wol->wolopts & WAKE_MAGIC)
1006 wol_cfg |= 1UL << adapter->portnum;
1007 else
1008 wol_cfg &= ~(1UL << adapter->portnum);
1009
1010 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1011
1012 return 0;
1013}
1014
1015/*
1016 * Set the coalescing parameters. Currently only normal is supported.
1017 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1018 * firmware coalescing to default.
1019 */
1020static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1021 struct ethtool_coalesce *ethcoal)
1022{
1023 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1024
1025 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
1026 return -EINVAL;
1027
1028 /*
1029 * Return Error if unsupported values or
1030 * unsupported parameters are set.
1031 */
1032 if (ethcoal->rx_coalesce_usecs > 0xffff ||
1033 ethcoal->rx_max_coalesced_frames > 0xffff ||
1034 ethcoal->tx_coalesce_usecs ||
1035 ethcoal->tx_max_coalesced_frames ||
1036 ethcoal->rx_coalesce_usecs_irq ||
1037 ethcoal->rx_max_coalesced_frames_irq ||
1038 ethcoal->tx_coalesce_usecs_irq ||
1039 ethcoal->tx_max_coalesced_frames_irq ||
1040 ethcoal->stats_block_coalesce_usecs ||
1041 ethcoal->use_adaptive_rx_coalesce ||
1042 ethcoal->use_adaptive_tx_coalesce ||
1043 ethcoal->pkt_rate_low ||
1044 ethcoal->rx_coalesce_usecs_low ||
1045 ethcoal->rx_max_coalesced_frames_low ||
1046 ethcoal->tx_coalesce_usecs_low ||
1047 ethcoal->tx_max_coalesced_frames_low ||
1048 ethcoal->pkt_rate_high ||
1049 ethcoal->rx_coalesce_usecs_high ||
1050 ethcoal->rx_max_coalesced_frames_high ||
1051 ethcoal->tx_coalesce_usecs_high ||
1052 ethcoal->tx_max_coalesced_frames_high)
1053 return -EINVAL;
1054
1055 if (!ethcoal->rx_coalesce_usecs ||
1056 !ethcoal->rx_max_coalesced_frames) {
1057 adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
1058 adapter->ahw->coal.rx_time_us =
1059 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
1060 adapter->ahw->coal.rx_packets =
1061 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
1062 } else {
1063 adapter->ahw->coal.flag = 0;
1064 adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
1065 adapter->ahw->coal.rx_packets =
1066 ethcoal->rx_max_coalesced_frames;
1067 }
1068
1069 qlcnic_config_intr_coalesce(adapter);
1070
1071 return 0;
1072}
1073
1074static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1075 struct ethtool_coalesce *ethcoal)
1076{
1077 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1078
1079 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1080 return -EINVAL;
1081
1082 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1083 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
1084
1085 return 0;
1086}
1087
1088static u32 qlcnic_get_msglevel(struct net_device *netdev)
1089{
1090 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1091
1092 return adapter->msg_enable;
1093}
1094
1095static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1096{
1097 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1098
1099 adapter->msg_enable = msglvl;
1100}
1101
1102static int
1103qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1104{
1105 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1106 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1107
1108 if (fw_dump->clr)
1109 dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
1110 else
1111 dump->len = 0;
1112 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1113 dump->version = adapter->fw_version;
1114 return 0;
1115}
1116
1117static int
1118qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1119 void *buffer)
1120{
1121 int i, copy_sz;
1122 u32 *hdr_ptr, *data;
1123 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1124 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1125
1126 if (!fw_dump->clr) {
1127 netdev_info(netdev, "Dump not available\n");
1128 qlcnic_api_unlock(adapter);
1129 return -EINVAL;
1130 }
1131 /* Copy template header first */
1132 copy_sz = fw_dump->tmpl_hdr->size;
1133 hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
1134 data = buffer;
1135 for (i = 0; i < copy_sz/sizeof(u32); i++)
1136 *data++ = cpu_to_le32(*hdr_ptr++);
1137
1138 /* Copy captured dump data */
1139 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1140 dump->len = copy_sz + fw_dump->size;
1141 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1142
1143 /* Free dump area once data has been captured */
1144 vfree(fw_dump->data);
1145 fw_dump->data = NULL;
1146 fw_dump->clr = 0;
1147
1148 return 0;
1149}
1150
1151static int
1152qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1153{
1154 int ret = 0;
1155 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1156 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1157
1158 switch (val->flag) {
1159 case QLCNIC_FORCE_FW_DUMP_KEY:
1160 if (!fw_dump->enable) {
1161 netdev_info(netdev, "FW dump not enabled\n");
1162 return ret;
1163 }
1164 if (fw_dump->clr) {
1165 dev_info(&adapter->pdev->dev,
1166 "Previous dump not cleared, not forcing dump\n");
1167 return ret;
1168 }
1169 netdev_info(netdev, "Forcing a FW dump\n");
1170 qlcnic_dev_request_reset(adapter);
1171 break;
1172 case QLCNIC_DISABLE_FW_DUMP:
1173 if (fw_dump->enable) {
1174 netdev_info(netdev, "Disabling FW dump\n");
1175 fw_dump->enable = 0;
1176 }
1177 break;
1178 case QLCNIC_ENABLE_FW_DUMP:
1179 if (!fw_dump->enable && fw_dump->tmpl_hdr) {
1180 netdev_info(netdev, "Enabling FW dump\n");
1181 fw_dump->enable = 1;
1182 }
1183 break;
1184 case QLCNIC_FORCE_FW_RESET:
1185 netdev_info(netdev, "Forcing a FW reset\n");
1186 qlcnic_dev_request_reset(adapter);
1187 adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
1188 break;
1189 default:
1190 if (val->flag > QLCNIC_DUMP_MASK_MAX ||
1191 val->flag < QLCNIC_DUMP_MASK_MIN) {
1192 netdev_info(netdev,
1193 "Invalid dump level: 0x%x\n", val->flag);
1194 ret = -EINVAL;
1195 goto out;
1196 }
1197 fw_dump->tmpl_hdr->drv_cap_mask = val->flag & 0xff;
1198 netdev_info(netdev, "Driver mask changed to: 0x%x\n",
1199 fw_dump->tmpl_hdr->drv_cap_mask);
1200 }
1201out:
1202 return ret;
1203}
1204
1205const struct ethtool_ops qlcnic_ethtool_ops = {
1206 .get_settings = qlcnic_get_settings,
1207 .set_settings = qlcnic_set_settings,
1208 .get_drvinfo = qlcnic_get_drvinfo,
1209 .get_regs_len = qlcnic_get_regs_len,
1210 .get_regs = qlcnic_get_regs,
1211 .get_link = ethtool_op_get_link,
1212 .get_eeprom_len = qlcnic_get_eeprom_len,
1213 .get_eeprom = qlcnic_get_eeprom,
1214 .get_ringparam = qlcnic_get_ringparam,
1215 .set_ringparam = qlcnic_set_ringparam,
1216 .get_channels = qlcnic_get_channels,
1217 .set_channels = qlcnic_set_channels,
1218 .get_pauseparam = qlcnic_get_pauseparam,
1219 .set_pauseparam = qlcnic_set_pauseparam,
1220 .get_wol = qlcnic_get_wol,
1221 .set_wol = qlcnic_set_wol,
1222 .self_test = qlcnic_diag_test,
1223 .get_strings = qlcnic_get_strings,
1224 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1225 .get_sset_count = qlcnic_get_sset_count,
1226 .get_coalesce = qlcnic_get_intr_coalesce,
1227 .set_coalesce = qlcnic_set_intr_coalesce,
1228 .set_phys_id = qlcnic_set_led,
1229 .set_msglevel = qlcnic_set_msglevel,
1230 .get_msglevel = qlcnic_get_msglevel,
1231 .get_dump_flag = qlcnic_get_dump_flag,
1232 .get_dump_data = qlcnic_get_dump_data,
1233 .set_dump = qlcnic_set_dump,
1234};