]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/qlcnic/qlcnic_ethtool.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[net-next-2.6.git] / drivers / net / qlcnic / qlcnic_ethtool.c
CommitLineData
af19b491
AKS
1/*
2 * Copyright (C) 2009 - QLogic Corporation.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 * MA 02111-1307, USA.
19 *
20 * The full GNU General Public License is included in this distribution
21 * in the file called "COPYING".
22 *
23 */
24
25#include <linux/types.h>
26#include <linux/delay.h>
27#include <linux/pci.h>
28#include <linux/io.h>
29#include <linux/netdevice.h>
30#include <linux/ethtool.h>
31
32#include "qlcnic.h"
33
34struct qlcnic_stats {
35 char stat_string[ETH_GSTRING_LEN];
36 int sizeof_stat;
37 int stat_offset;
38};
39
40#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
41#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
42
43static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
44 {"xmit_called",
45 QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)},
46 {"xmit_finished",
47 QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)},
48 {"rx_dropped",
49 QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
50 {"tx_dropped",
51 QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
52 {"csummed",
53 QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
54 {"rx_pkts",
55 QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
56 {"lro_pkts",
57 QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
58 {"rx_bytes",
59 QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
60 {"tx_bytes",
61 QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
8bfe8b91
SC
62 {"lrobytes",
63 QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
64 {"lso_frames",
65 QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
66 {"xmit_on",
67 QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
68 {"xmit_off",
69 QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
70 {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
71 QLC_OFF(stats.skb_alloc_failure)},
8ae6df97
AKS
72 {"null rxbuf",
73 QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
74 {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
75 QLC_OFF(stats.rx_dma_map_error)},
76 {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
77 QLC_OFF(stats.tx_dma_map_error)},
8bfe8b91 78
af19b491
AKS
79};
80
3666e0b0 81static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
82 "rx unicast frames",
83 "rx multicast frames",
84 "rx broadcast frames",
85 "rx dropped frames",
86 "rx errors",
87 "rx local frames",
88 "rx numbytes",
89 "tx unicast frames",
90 "tx multicast frames",
91 "tx broadcast frames",
92 "tx dropped frames",
93 "tx errors",
94 "tx local frames",
95 "tx numbytes",
96};
97
af19b491 98#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
3666e0b0 99#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
af19b491
AKS
100
101static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
102 "Register_Test_on_offline",
7eb9855d 103 "Link_Test_on_offline",
cdaff185
AKS
104 "Interrupt_Test_offline",
105 "Loopback_Test_offline"
af19b491
AKS
106};
107
108#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
109
110#define QLCNIC_RING_REGS_COUNT 20
111#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
112#define QLCNIC_MAX_EEPROM_LEN 1024
113
114static const u32 diag_registers[] = {
115 CRB_CMDPEG_STATE,
116 CRB_RCVPEG_STATE,
ff1b1bf8 117 CRB_XG_STATE_P3P,
af19b491
AKS
118 CRB_FW_CAPABILITIES_1,
119 ISR_INT_STATE_REG,
31018e06 120 QLCNIC_CRB_DRV_ACTIVE,
af19b491
AKS
121 QLCNIC_CRB_DEV_STATE,
122 QLCNIC_CRB_DRV_STATE,
123 QLCNIC_CRB_DRV_SCRATCH,
124 QLCNIC_CRB_DEV_PARTITION_INFO,
125 QLCNIC_CRB_DRV_IDC_VER,
126 QLCNIC_PEG_ALIVE_COUNTER,
127 QLCNIC_PEG_HALT_STATUS1,
128 QLCNIC_PEG_HALT_STATUS2,
129 QLCNIC_CRB_PEG_NET_0+0x3c,
130 QLCNIC_CRB_PEG_NET_1+0x3c,
131 QLCNIC_CRB_PEG_NET_2+0x3c,
132 QLCNIC_CRB_PEG_NET_4+0x3c,
133 -1
134};
135
2cffcdbf
RB
136#define QLCNIC_MGMT_API_VERSION 2
137#define QLCNIC_DEV_INFO_SIZE 1
138#define QLCNIC_ETHTOOL_REGS_VER 2
af19b491
AKS
139static int qlcnic_get_regs_len(struct net_device *dev)
140{
2cffcdbf
RB
141 return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
142 QLCNIC_DEV_INFO_SIZE + 1;
af19b491
AKS
143}
144
145static int qlcnic_get_eeprom_len(struct net_device *dev)
146{
147 return QLCNIC_FLASH_TOTAL_SIZE;
148}
149
150static void
151qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
152{
153 struct qlcnic_adapter *adapter = netdev_priv(dev);
154 u32 fw_major, fw_minor, fw_build;
155
156 fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
157 fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
158 fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
159 sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
160
161 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
162 strlcpy(drvinfo->driver, qlcnic_driver_name, 32);
163 strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID, 32);
164}
165
166static int
167qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
168{
169 struct qlcnic_adapter *adapter = netdev_priv(dev);
170 int check_sfp_module = 0;
171 u16 pcifn = adapter->ahw.pci_func;
172
173 /* read which mode */
174 if (adapter->ahw.port_type == QLCNIC_GBE) {
175 ecmd->supported = (SUPPORTED_10baseT_Half |
176 SUPPORTED_10baseT_Full |
177 SUPPORTED_100baseT_Half |
178 SUPPORTED_100baseT_Full |
179 SUPPORTED_1000baseT_Half |
180 SUPPORTED_1000baseT_Full);
181
182 ecmd->advertising = (ADVERTISED_100baseT_Half |
183 ADVERTISED_100baseT_Full |
184 ADVERTISED_1000baseT_Half |
185 ADVERTISED_1000baseT_Full);
186
187 ecmd->speed = adapter->link_speed;
188 ecmd->duplex = adapter->link_duplex;
189 ecmd->autoneg = adapter->link_autoneg;
190
191 } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
192 u32 val;
193
194 val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
195 if (val == QLCNIC_PORT_MODE_802_3_AP) {
196 ecmd->supported = SUPPORTED_1000baseT_Full;
197 ecmd->advertising = ADVERTISED_1000baseT_Full;
198 } else {
199 ecmd->supported = SUPPORTED_10000baseT_Full;
200 ecmd->advertising = ADVERTISED_10000baseT_Full;
201 }
202
203 if (netif_running(dev) && adapter->has_link_events) {
204 ecmd->speed = adapter->link_speed;
205 ecmd->autoneg = adapter->link_autoneg;
206 ecmd->duplex = adapter->link_duplex;
207 goto skip;
208 }
209
ff1b1bf8
SV
210 val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
211 ecmd->speed = P3P_LINK_SPEED_MHZ *
212 P3P_LINK_SPEED_VAL(pcifn, val);
af19b491
AKS
213 ecmd->duplex = DUPLEX_FULL;
214 ecmd->autoneg = AUTONEG_DISABLE;
215 } else
216 return -EIO;
217
218skip:
219 ecmd->phy_address = adapter->physical_port;
220 ecmd->transceiver = XCVR_EXTERNAL;
221
222 switch (adapter->ahw.board_type) {
ff1b1bf8
SV
223 case QLCNIC_BRDTYPE_P3P_REF_QG:
224 case QLCNIC_BRDTYPE_P3P_4_GB:
225 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
af19b491
AKS
226
227 ecmd->supported |= SUPPORTED_Autoneg;
228 ecmd->advertising |= ADVERTISED_Autoneg;
ff1b1bf8
SV
229 case QLCNIC_BRDTYPE_P3P_10G_CX4:
230 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
231 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
af19b491
AKS
232 ecmd->supported |= SUPPORTED_TP;
233 ecmd->advertising |= ADVERTISED_TP;
234 ecmd->port = PORT_TP;
235 ecmd->autoneg = adapter->link_autoneg;
236 break;
ff1b1bf8
SV
237 case QLCNIC_BRDTYPE_P3P_IMEZ:
238 case QLCNIC_BRDTYPE_P3P_XG_LOM:
239 case QLCNIC_BRDTYPE_P3P_HMEZ:
af19b491
AKS
240 ecmd->supported |= SUPPORTED_MII;
241 ecmd->advertising |= ADVERTISED_MII;
242 ecmd->port = PORT_MII;
243 ecmd->autoneg = AUTONEG_DISABLE;
244 break;
ff1b1bf8
SV
245 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
246 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
247 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
af19b491
AKS
248 ecmd->advertising |= ADVERTISED_TP;
249 ecmd->supported |= SUPPORTED_TP;
250 check_sfp_module = netif_running(dev) &&
251 adapter->has_link_events;
ff1b1bf8 252 case QLCNIC_BRDTYPE_P3P_10G_XFP:
af19b491
AKS
253 ecmd->supported |= SUPPORTED_FIBRE;
254 ecmd->advertising |= ADVERTISED_FIBRE;
255 ecmd->port = PORT_FIBRE;
256 ecmd->autoneg = AUTONEG_DISABLE;
257 break;
ff1b1bf8 258 case QLCNIC_BRDTYPE_P3P_10G_TP:
af19b491
AKS
259 if (adapter->ahw.port_type == QLCNIC_XGBE) {
260 ecmd->autoneg = AUTONEG_DISABLE;
261 ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
262 ecmd->advertising |=
263 (ADVERTISED_FIBRE | ADVERTISED_TP);
264 ecmd->port = PORT_FIBRE;
265 check_sfp_module = netif_running(dev) &&
266 adapter->has_link_events;
267 } else {
268 ecmd->autoneg = AUTONEG_ENABLE;
269 ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
270 ecmd->advertising |=
271 (ADVERTISED_TP | ADVERTISED_Autoneg);
272 ecmd->port = PORT_TP;
273 }
274 break;
275 default:
276 dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
277 adapter->ahw.board_type);
278 return -EIO;
279 }
280
281 if (check_sfp_module) {
282 switch (adapter->module_type) {
283 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
284 case LINKEVENT_MODULE_OPTICAL_SRLR:
285 case LINKEVENT_MODULE_OPTICAL_LRM:
286 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
287 ecmd->port = PORT_FIBRE;
288 break;
289 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
290 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
291 case LINKEVENT_MODULE_TWINAX:
292 ecmd->port = PORT_TP;
293 break;
294 default:
295 ecmd->port = PORT_OTHER;
296 }
297 }
298
299 return 0;
300}
301
302static int
303qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
304{
305 struct qlcnic_adapter *adapter = netdev_priv(dev);
306 __u32 status;
307
308 /* read which mode */
309 if (adapter->ahw.port_type == QLCNIC_GBE) {
310 /* autonegotiation */
311 if (qlcnic_fw_cmd_set_phy(adapter,
312 QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG,
313 ecmd->autoneg) != 0)
314 return -EIO;
315 else
316 adapter->link_autoneg = ecmd->autoneg;
317
318 if (qlcnic_fw_cmd_query_phy(adapter,
319 QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
320 &status) != 0)
321 return -EIO;
322
323 switch (ecmd->speed) {
324 case SPEED_10:
325 qlcnic_set_phy_speed(status, 0);
326 break;
327 case SPEED_100:
328 qlcnic_set_phy_speed(status, 1);
329 break;
330 case SPEED_1000:
331 qlcnic_set_phy_speed(status, 2);
332 break;
333 }
334
335 if (ecmd->duplex == DUPLEX_HALF)
336 qlcnic_clear_phy_duplex(status);
337 if (ecmd->duplex == DUPLEX_FULL)
338 qlcnic_set_phy_duplex(status);
339 if (qlcnic_fw_cmd_set_phy(adapter,
340 QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
341 *((int *)&status)) != 0)
342 return -EIO;
343 else {
344 adapter->link_speed = ecmd->speed;
345 adapter->link_duplex = ecmd->duplex;
346 }
347 } else
348 return -EOPNOTSUPP;
349
350 if (!netif_running(dev))
351 return 0;
352
353 dev->netdev_ops->ndo_stop(dev);
354 return dev->netdev_ops->ndo_open(dev);
355}
356
357static void
358qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
359{
360 struct qlcnic_adapter *adapter = netdev_priv(dev);
361 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
362 struct qlcnic_host_sds_ring *sds_ring;
363 u32 *regs_buff = p;
c265eb6e 364 int ring, i = 0, j = 0;
af19b491
AKS
365
366 memset(p, 0, qlcnic_get_regs_len(dev));
2cffcdbf
RB
367 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
368 (adapter->ahw.revision_id << 16) | (adapter->pdev)->device;
af19b491 369
2cffcdbf
RB
370 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
371 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
372
c265eb6e
AKS
373 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
374 regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
af19b491 375
8a15ad1f 376 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
ce668443
AKS
377 return;
378
af19b491
AKS
379 regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
380
381 regs_buff[i++] = 1; /* No. of tx ring */
382 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
383 regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
384
385 regs_buff[i++] = 2; /* No. of rx ring */
386 regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
387 regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
388
389 regs_buff[i++] = adapter->max_sds_rings;
390
391 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
392 sds_ring = &(recv_ctx->sds_rings[ring]);
393 regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
394 }
395}
396
397static u32 qlcnic_test_link(struct net_device *dev)
398{
399 struct qlcnic_adapter *adapter = netdev_priv(dev);
400 u32 val;
401
ff1b1bf8
SV
402 val = QLCRD32(adapter, CRB_XG_STATE_P3P);
403 val = XG_LINK_STATE_P3P(adapter->ahw.pci_func, val);
404 return (val == XG_LINK_UP_P3P) ? 0 : 1;
af19b491
AKS
405}
406
407static int
408qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
409 u8 *bytes)
410{
411 struct qlcnic_adapter *adapter = netdev_priv(dev);
412 int offset;
413 int ret;
414
415 if (eeprom->len == 0)
416 return -EINVAL;
417
418 eeprom->magic = (adapter->pdev)->vendor |
419 ((adapter->pdev)->device << 16);
420 offset = eeprom->offset;
421
422 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
423 eeprom->len);
424 if (ret < 0)
425 return ret;
426
427 return 0;
428}
429
430static void
431qlcnic_get_ringparam(struct net_device *dev,
432 struct ethtool_ringparam *ring)
433{
434 struct qlcnic_adapter *adapter = netdev_priv(dev);
435
436 ring->rx_pending = adapter->num_rxd;
437 ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
af19b491
AKS
438 ring->tx_pending = adapter->num_txd;
439
90d19005
SC
440 ring->rx_max_pending = adapter->max_rxd;
441 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
af19b491
AKS
442 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
443
444 ring->rx_mini_max_pending = 0;
445 ring->rx_mini_pending = 0;
446}
447
448static u32
449qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
450{
451 u32 num_desc;
452 num_desc = max(val, min);
453 num_desc = min(num_desc, max);
454 num_desc = roundup_pow_of_two(num_desc);
455
456 if (val != num_desc) {
457 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
458 qlcnic_driver_name, r_name, num_desc, val);
459 }
460
461 return num_desc;
462}
463
464static int
465qlcnic_set_ringparam(struct net_device *dev,
466 struct ethtool_ringparam *ring)
467{
468 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
469 u16 num_rxd, num_jumbo_rxd, num_txd;
470
af19b491
AKS
471 if (ring->rx_mini_pending)
472 return -EOPNOTSUPP;
473
af19b491 474 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
90d19005 475 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
af19b491
AKS
476
477 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
90d19005
SC
478 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
479 "rx jumbo");
af19b491
AKS
480
481 num_txd = qlcnic_validate_ringparam(ring->tx_pending,
482 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
483
484 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
485 num_jumbo_rxd == adapter->num_jumbo_rxd)
486 return 0;
487
488 adapter->num_rxd = num_rxd;
489 adapter->num_jumbo_rxd = num_jumbo_rxd;
490 adapter->num_txd = num_txd;
491
492 return qlcnic_reset_context(adapter);
493}
494
495static void
496qlcnic_get_pauseparam(struct net_device *netdev,
497 struct ethtool_pauseparam *pause)
498{
499 struct qlcnic_adapter *adapter = netdev_priv(netdev);
500 int port = adapter->physical_port;
501 __u32 val;
502
503 if (adapter->ahw.port_type == QLCNIC_GBE) {
504 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
505 return;
506 /* get flow control settings */
507 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
508 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
509 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
510 switch (port) {
511 case 0:
512 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
513 break;
514 case 1:
515 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
516 break;
517 case 2:
518 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
519 break;
520 case 3:
521 default:
522 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
523 break;
524 }
525 } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
526 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
527 return;
528 pause->rx_pause = 1;
529 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
530 if (port == 0)
531 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
532 else
533 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
534 } else {
535 dev_err(&netdev->dev, "Unknown board type: %x\n",
536 adapter->ahw.port_type);
537 }
538}
539
540static int
541qlcnic_set_pauseparam(struct net_device *netdev,
542 struct ethtool_pauseparam *pause)
543{
544 struct qlcnic_adapter *adapter = netdev_priv(netdev);
545 int port = adapter->physical_port;
546 __u32 val;
547
548 /* read mode */
549 if (adapter->ahw.port_type == QLCNIC_GBE) {
550 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
551 return -EIO;
552 /* set flow control */
553 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
554
555 if (pause->rx_pause)
556 qlcnic_gb_rx_flowctl(val);
557 else
558 qlcnic_gb_unset_rx_flowctl(val);
559
560 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
561 val);
562 /* set autoneg */
563 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
564 switch (port) {
565 case 0:
566 if (pause->tx_pause)
567 qlcnic_gb_unset_gb0_mask(val);
568 else
569 qlcnic_gb_set_gb0_mask(val);
570 break;
571 case 1:
572 if (pause->tx_pause)
573 qlcnic_gb_unset_gb1_mask(val);
574 else
575 qlcnic_gb_set_gb1_mask(val);
576 break;
577 case 2:
578 if (pause->tx_pause)
579 qlcnic_gb_unset_gb2_mask(val);
580 else
581 qlcnic_gb_set_gb2_mask(val);
582 break;
583 case 3:
584 default:
585 if (pause->tx_pause)
586 qlcnic_gb_unset_gb3_mask(val);
587 else
588 qlcnic_gb_set_gb3_mask(val);
589 break;
590 }
591 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
592 } else if (adapter->ahw.port_type == QLCNIC_XGBE) {
6d181688
RB
593 if (!pause->rx_pause || pause->autoneg)
594 return -EOPNOTSUPP;
595
af19b491
AKS
596 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
597 return -EIO;
6d181688 598
af19b491
AKS
599 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
600 if (port == 0) {
601 if (pause->tx_pause)
602 qlcnic_xg_unset_xg0_mask(val);
603 else
604 qlcnic_xg_set_xg0_mask(val);
605 } else {
606 if (pause->tx_pause)
607 qlcnic_xg_unset_xg1_mask(val);
608 else
609 qlcnic_xg_set_xg1_mask(val);
610 }
611 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
612 } else {
613 dev_err(&netdev->dev, "Unknown board type: %x\n",
614 adapter->ahw.port_type);
615 }
616 return 0;
617}
618
619static int qlcnic_reg_test(struct net_device *dev)
620{
621 struct qlcnic_adapter *adapter = netdev_priv(dev);
deffab05 622 u32 data_read;
af19b491
AKS
623
624 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
625 if ((data_read & 0xffff) != adapter->pdev->vendor)
626 return 1;
627
af19b491
AKS
628 return 0;
629}
630
631static int qlcnic_get_sset_count(struct net_device *dev, int sset)
632{
3666e0b0 633 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
634 switch (sset) {
635 case ETH_SS_TEST:
636 return QLCNIC_TEST_LEN;
637 case ETH_SS_STATS:
3666e0b0 638 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
639 return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
af19b491
AKS
640 return QLCNIC_STATS_LEN;
641 default:
642 return -EOPNOTSUPP;
643 }
644}
645
cdaff185 646#define QLC_ILB_PKT_SIZE 64
31dee692
AKS
647#define QLC_NUM_ILB_PKT 16
648#define QLC_ILB_MAX_RCV_LOOP 10
cdaff185
AKS
649
650static void qlcnic_create_loopback_buff(unsigned char *data)
651{
652 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
653 memset(data, 0x4e, QLC_ILB_PKT_SIZE);
654 memset(data, 0xff, 12);
655 memcpy(data + 12, random_data, sizeof(random_data));
656}
657
658int qlcnic_check_loopback_buff(unsigned char *data)
659{
660 unsigned char buff[QLC_ILB_PKT_SIZE];
661 qlcnic_create_loopback_buff(buff);
662 return memcmp(data, buff, QLC_ILB_PKT_SIZE);
663}
664
665static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
666{
667 struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx;
668 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
669 struct sk_buff *skb;
31dee692 670 int i, loop, cnt = 0;
cdaff185 671
31dee692 672 for (i = 0; i < QLC_NUM_ILB_PKT; i++) {
cdaff185
AKS
673 skb = dev_alloc_skb(QLC_ILB_PKT_SIZE);
674 qlcnic_create_loopback_buff(skb->data);
675 skb_put(skb, QLC_ILB_PKT_SIZE);
676
677 adapter->diag_cnt = 0;
cdaff185
AKS
678 qlcnic_xmit_frame(skb, adapter->netdev);
679
31dee692
AKS
680 loop = 0;
681 do {
682 msleep(1);
683 qlcnic_process_rcv_ring_diag(sds_ring);
684 } while (loop++ < QLC_ILB_MAX_RCV_LOOP &&
685 !adapter->diag_cnt);
cdaff185
AKS
686
687 dev_kfree_skb_any(skb);
31dee692 688
cdaff185 689 if (!adapter->diag_cnt)
31dee692
AKS
690 dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
691 " not recevied\n", i + 1);
692 else
693 cnt++;
694 }
695 if (cnt != i) {
696 dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
697 return -1;
cdaff185
AKS
698 }
699 return 0;
700}
701
702static int qlcnic_loopback_test(struct net_device *netdev)
703{
704 struct qlcnic_adapter *adapter = netdev_priv(netdev);
705 int max_sds_rings = adapter->max_sds_rings;
706 int ret;
707
36a1898d
AKS
708 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
709 dev_warn(&adapter->pdev->dev, "Loopback test not supported"
710 "for non privilege function\n");
711 return 0;
712 }
713
cdaff185
AKS
714 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
715 return -EIO;
716
b8c17620
AKS
717 if (qlcnic_request_quiscent_mode(adapter)) {
718 clear_bit(__QLCNIC_RESETTING, &adapter->state);
719 return -EIO;
720 }
721
cdaff185
AKS
722 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
723 if (ret)
724 goto clear_it;
725
36a1898d 726 ret = qlcnic_set_ilb_mode(adapter);
cdaff185
AKS
727 if (ret)
728 goto done;
729
730 ret = qlcnic_do_ilb_test(adapter);
731
36a1898d 732 qlcnic_clear_ilb_mode(adapter);
cdaff185
AKS
733
734done:
735 qlcnic_diag_free_res(netdev, max_sds_rings);
736
737clear_it:
b8c17620 738 qlcnic_clear_quiscent_mode(adapter);
cdaff185
AKS
739 adapter->max_sds_rings = max_sds_rings;
740 clear_bit(__QLCNIC_RESETTING, &adapter->state);
741 return ret;
742}
743
7eb9855d
AKS
744static int qlcnic_irq_test(struct net_device *netdev)
745{
746 struct qlcnic_adapter *adapter = netdev_priv(netdev);
747 int max_sds_rings = adapter->max_sds_rings;
748 int ret;
749
750 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
751 return -EIO;
752
753 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
754 if (ret)
755 goto clear_it;
756
757 adapter->diag_cnt = 0;
758 ret = qlcnic_issue_cmd(adapter, adapter->ahw.pci_func,
2e9d722d
AC
759 adapter->fw_hal_version, adapter->portnum,
760 0, 0, 0x00000011);
7eb9855d
AKS
761 if (ret)
762 goto done;
763
764 msleep(10);
765
766 ret = !adapter->diag_cnt;
767
768done:
769 qlcnic_diag_free_res(netdev, max_sds_rings);
770
771clear_it:
772 adapter->max_sds_rings = max_sds_rings;
773 clear_bit(__QLCNIC_RESETTING, &adapter->state);
774 return ret;
775}
776
af19b491
AKS
777static void
778qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
779 u64 *data)
780{
781 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
897d3596 782
8dec32cc
SC
783 data[0] = qlcnic_reg_test(dev);
784 if (data[0])
785 eth_test->flags |= ETH_TEST_FL_FAILED;
786
787 data[1] = (u64) qlcnic_test_link(dev);
788 if (data[1])
789 eth_test->flags |= ETH_TEST_FL_FAILED;
790
7eb9855d
AKS
791 if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
792 data[2] = qlcnic_irq_test(dev);
793 if (data[2])
794 eth_test->flags |= ETH_TEST_FL_FAILED;
cdaff185
AKS
795
796 data[3] = qlcnic_loopback_test(dev);
797 if (data[3])
798 eth_test->flags |= ETH_TEST_FL_FAILED;
799
7eb9855d 800 }
af19b491
AKS
801}
802
803static void
804qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
805{
3666e0b0 806 struct qlcnic_adapter *adapter = netdev_priv(dev);
807 int index, i;
af19b491
AKS
808
809 switch (stringset) {
810 case ETH_SS_TEST:
811 memcpy(data, *qlcnic_gstrings_test,
812 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
813 break;
814 case ETH_SS_STATS:
815 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
816 memcpy(data + index * ETH_GSTRING_LEN,
817 qlcnic_gstrings_stats[index].stat_string,
818 ETH_GSTRING_LEN);
819 }
3666e0b0 820 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
821 return;
822 for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
823 memcpy(data + index * ETH_GSTRING_LEN,
824 qlcnic_device_gstrings_stats[i],
825 ETH_GSTRING_LEN);
826 }
af19b491
AKS
827 }
828}
829
3666e0b0 830#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
831 (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
832
833static void
834qlcnic_fill_device_stats(int *index, u64 *data,
835 struct __qlcnic_esw_statistics *stats)
836{
837 int ind = *index;
838
839 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
840 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
841 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
842 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
843 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
844 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
845 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
846
847 *index = ind;
848}
849
af19b491
AKS
850static void
851qlcnic_get_ethtool_stats(struct net_device *dev,
852 struct ethtool_stats *stats, u64 * data)
853{
854 struct qlcnic_adapter *adapter = netdev_priv(dev);
3666e0b0 855 struct qlcnic_esw_statistics port_stats;
856 int index, ret;
af19b491
AKS
857
858 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
859 char *p =
860 (char *)adapter +
861 qlcnic_gstrings_stats[index].stat_offset;
862 data[index] =
863 (qlcnic_gstrings_stats[index].sizeof_stat ==
864 sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
865 }
3666e0b0 866
867 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
868 return;
869
870 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
871 ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
872 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
873 if (ret)
874 return;
875
876 qlcnic_fill_device_stats(&index, data, &port_stats.rx);
877
878 ret = qlcnic_get_port_stats(adapter, adapter->ahw.pci_func,
879 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
880 if (ret)
881 return;
882
883 qlcnic_fill_device_stats(&index, data, &port_stats.tx);
af19b491
AKS
884}
885
0325d69b
RB
886static int qlcnic_set_tx_csum(struct net_device *dev, u32 data)
887{
888 struct qlcnic_adapter *adapter = netdev_priv(dev);
889
890 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED))
891 return -EOPNOTSUPP;
892 if (data)
893 dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
894 else
895 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
896
897 return 0;
898
899}
8bae5698
SC
900static u32 qlcnic_get_tx_csum(struct net_device *dev)
901{
902 return dev->features & NETIF_F_IP_CSUM;
903}
904
af19b491
AKS
905static u32 qlcnic_get_rx_csum(struct net_device *dev)
906{
907 struct qlcnic_adapter *adapter = netdev_priv(dev);
908 return adapter->rx_csum;
909}
910
911static int qlcnic_set_rx_csum(struct net_device *dev, u32 data)
912{
913 struct qlcnic_adapter *adapter = netdev_priv(dev);
24763d80 914
0325d69b
RB
915 if ((adapter->flags & QLCNIC_ESWITCH_ENABLED))
916 return -EOPNOTSUPP;
24763d80
SC
917 if (!!data) {
918 adapter->rx_csum = !!data;
919 return 0;
920 }
921
a2152d09 922 if (dev->features & NETIF_F_LRO) {
24763d80
SC
923 if (qlcnic_config_hw_lro(adapter, QLCNIC_LRO_DISABLED))
924 return -EIO;
925
926 dev->features &= ~NETIF_F_LRO;
927 qlcnic_send_lro_cleanup(adapter);
928 }
af19b491 929 adapter->rx_csum = !!data;
24763d80 930 dev_info(&adapter->pdev->dev, "disabling LRO as rx_csum is off\n");
af19b491
AKS
931 return 0;
932}
933
934static u32 qlcnic_get_tso(struct net_device *dev)
935{
936 return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
937}
938
939static int qlcnic_set_tso(struct net_device *dev, u32 data)
940{
ac8d0c4f
AC
941 struct qlcnic_adapter *adapter = netdev_priv(dev);
942 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO))
943 return -EOPNOTSUPP;
af19b491
AKS
944 if (data)
945 dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
946 else
947 dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
948
949 return 0;
950}
951
897d3596
SC
952static int qlcnic_blink_led(struct net_device *dev, u32 val)
953{
954 struct qlcnic_adapter *adapter = netdev_priv(dev);
955 int ret;
956
8a15ad1f
AKS
957 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
958 return -EIO;
959
2e9d722d 960 ret = adapter->nic_ops->config_led(adapter, 1, 0xf);
897d3596
SC
961 if (ret) {
962 dev_err(&adapter->pdev->dev,
963 "Failed to set LED blink state.\n");
964 return ret;
965 }
966
967 msleep_interruptible(val * 1000);
968
2e9d722d 969 ret = adapter->nic_ops->config_led(adapter, 0, 0xf);
897d3596
SC
970 if (ret) {
971 dev_err(&adapter->pdev->dev,
972 "Failed to reset LED blink state.\n");
973 return ret;
974 }
975
976 return 0;
977}
978
af19b491
AKS
979static void
980qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
981{
982 struct qlcnic_adapter *adapter = netdev_priv(dev);
983 u32 wol_cfg;
984
985 wol->supported = 0;
986 wol->wolopts = 0;
987
988 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
989 if (wol_cfg & (1UL << adapter->portnum))
990 wol->supported |= WAKE_MAGIC;
991
992 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
993 if (wol_cfg & (1UL << adapter->portnum))
994 wol->wolopts |= WAKE_MAGIC;
995}
996
997static int
998qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
999{
1000 struct qlcnic_adapter *adapter = netdev_priv(dev);
1001 u32 wol_cfg;
1002
1003 if (wol->wolopts & ~WAKE_MAGIC)
1004 return -EOPNOTSUPP;
1005
1006 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1007 if (!(wol_cfg & (1 << adapter->portnum)))
1008 return -EOPNOTSUPP;
1009
1010 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1011 if (wol->wolopts & WAKE_MAGIC)
1012 wol_cfg |= 1UL << adapter->portnum;
1013 else
1014 wol_cfg &= ~(1UL << adapter->portnum);
1015
1016 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1017
1018 return 0;
1019}
1020
1021/*
1022 * Set the coalescing parameters. Currently only normal is supported.
1023 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1024 * firmware coalescing to default.
1025 */
1026static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1027 struct ethtool_coalesce *ethcoal)
1028{
1029 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1030
8a15ad1f 1031 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
af19b491
AKS
1032 return -EINVAL;
1033
1034 /*
1035 * Return Error if unsupported values or
1036 * unsupported parameters are set.
1037 */
1038 if (ethcoal->rx_coalesce_usecs > 0xffff ||
1039 ethcoal->rx_max_coalesced_frames > 0xffff ||
1040 ethcoal->tx_coalesce_usecs > 0xffff ||
1041 ethcoal->tx_max_coalesced_frames > 0xffff ||
1042 ethcoal->rx_coalesce_usecs_irq ||
1043 ethcoal->rx_max_coalesced_frames_irq ||
1044 ethcoal->tx_coalesce_usecs_irq ||
1045 ethcoal->tx_max_coalesced_frames_irq ||
1046 ethcoal->stats_block_coalesce_usecs ||
1047 ethcoal->use_adaptive_rx_coalesce ||
1048 ethcoal->use_adaptive_tx_coalesce ||
1049 ethcoal->pkt_rate_low ||
1050 ethcoal->rx_coalesce_usecs_low ||
1051 ethcoal->rx_max_coalesced_frames_low ||
1052 ethcoal->tx_coalesce_usecs_low ||
1053 ethcoal->tx_max_coalesced_frames_low ||
1054 ethcoal->pkt_rate_high ||
1055 ethcoal->rx_coalesce_usecs_high ||
1056 ethcoal->rx_max_coalesced_frames_high ||
1057 ethcoal->tx_coalesce_usecs_high ||
1058 ethcoal->tx_max_coalesced_frames_high)
1059 return -EINVAL;
1060
1061 if (!ethcoal->rx_coalesce_usecs ||
1062 !ethcoal->rx_max_coalesced_frames) {
1063 adapter->coal.flags = QLCNIC_INTR_DEFAULT;
1064 adapter->coal.normal.data.rx_time_us =
1065 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
1066 adapter->coal.normal.data.rx_packets =
1067 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
1068 } else {
1069 adapter->coal.flags = 0;
1070 adapter->coal.normal.data.rx_time_us =
1071 ethcoal->rx_coalesce_usecs;
1072 adapter->coal.normal.data.rx_packets =
1073 ethcoal->rx_max_coalesced_frames;
1074 }
1075 adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
1076 adapter->coal.normal.data.tx_packets =
1077 ethcoal->tx_max_coalesced_frames;
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
1092 ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
1093 ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
1094 ethcoal->rx_max_coalesced_frames =
1095 adapter->coal.normal.data.rx_packets;
1096 ethcoal->tx_max_coalesced_frames =
1097 adapter->coal.normal.data.tx_packets;
1098
1099 return 0;
1100}
1101
1102static int qlcnic_set_flags(struct net_device *netdev, u32 data)
1103{
1104 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1105 int hw_lro;
1106
deaec0f6 1107 if (data & ~ETH_FLAG_LRO)
97d1935a 1108 return -EINVAL;
deaec0f6 1109
af19b491
AKS
1110 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
1111 return -EINVAL;
1112
24763d80
SC
1113 if (!adapter->rx_csum) {
1114 dev_info(&adapter->pdev->dev, "rx csum is off, "
1115 "cannot toggle lro\n");
1116 return -EINVAL;
1117 }
1118
a2152d09 1119 if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO))
24763d80
SC
1120 return 0;
1121
deaec0f6
SG
1122 if (data & ETH_FLAG_LRO) {
1123 hw_lro = QLCNIC_LRO_ENABLED;
1124 netdev->features |= NETIF_F_LRO;
1125 } else {
1126 hw_lro = 0;
1127 netdev->features &= ~NETIF_F_LRO;
1128 }
af19b491
AKS
1129
1130 if (qlcnic_config_hw_lro(adapter, hw_lro))
1131 return -EIO;
1132
1133 if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter))
1134 return -EIO;
1135
1136
1137 return 0;
1138}
1139
65b5b420
AKS
1140static u32 qlcnic_get_msglevel(struct net_device *netdev)
1141{
1142 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1143
1144 return adapter->msg_enable;
1145}
1146
1147static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1148{
1149 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1150
1151 adapter->msg_enable = msglvl;
1152}
1153
af19b491
AKS
1154const struct ethtool_ops qlcnic_ethtool_ops = {
1155 .get_settings = qlcnic_get_settings,
1156 .set_settings = qlcnic_set_settings,
1157 .get_drvinfo = qlcnic_get_drvinfo,
1158 .get_regs_len = qlcnic_get_regs_len,
1159 .get_regs = qlcnic_get_regs,
1160 .get_link = ethtool_op_get_link,
1161 .get_eeprom_len = qlcnic_get_eeprom_len,
1162 .get_eeprom = qlcnic_get_eeprom,
1163 .get_ringparam = qlcnic_get_ringparam,
1164 .set_ringparam = qlcnic_set_ringparam,
1165 .get_pauseparam = qlcnic_get_pauseparam,
1166 .set_pauseparam = qlcnic_set_pauseparam,
8bae5698 1167 .get_tx_csum = qlcnic_get_tx_csum,
0325d69b 1168 .set_tx_csum = qlcnic_set_tx_csum,
af19b491
AKS
1169 .set_sg = ethtool_op_set_sg,
1170 .get_tso = qlcnic_get_tso,
1171 .set_tso = qlcnic_set_tso,
1172 .get_wol = qlcnic_get_wol,
1173 .set_wol = qlcnic_set_wol,
1174 .self_test = qlcnic_diag_test,
1175 .get_strings = qlcnic_get_strings,
1176 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1177 .get_sset_count = qlcnic_get_sset_count,
1178 .get_rx_csum = qlcnic_get_rx_csum,
1179 .set_rx_csum = qlcnic_set_rx_csum,
1180 .get_coalesce = qlcnic_get_intr_coalesce,
1181 .set_coalesce = qlcnic_set_intr_coalesce,
1182 .get_flags = ethtool_op_get_flags,
1183 .set_flags = qlcnic_set_flags,
897d3596 1184 .phys_id = qlcnic_blink_led,
65b5b420
AKS
1185 .set_msglevel = qlcnic_set_msglevel,
1186 .get_msglevel = qlcnic_get_msglevel,
af19b491 1187};