]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/net/qlcnic/qlcnic_ethtool.c
qlcnic: lro off message log from set rx checsum
[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);
706f23ad
SC
928 dev_info(&adapter->pdev->dev,
929 "disabling LRO as rx_csum is off\n");
24763d80 930 }
af19b491
AKS
931 adapter->rx_csum = !!data;
932 return 0;
933}
934
935static u32 qlcnic_get_tso(struct net_device *dev)
936{
937 return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
938}
939
940static int qlcnic_set_tso(struct net_device *dev, u32 data)
941{
ac8d0c4f
AC
942 struct qlcnic_adapter *adapter = netdev_priv(dev);
943 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO))
944 return -EOPNOTSUPP;
af19b491
AKS
945 if (data)
946 dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
947 else
948 dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
949
950 return 0;
951}
952
897d3596
SC
953static int qlcnic_blink_led(struct net_device *dev, u32 val)
954{
955 struct qlcnic_adapter *adapter = netdev_priv(dev);
956 int ret;
957
8a15ad1f
AKS
958 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
959 return -EIO;
960
2e9d722d 961 ret = adapter->nic_ops->config_led(adapter, 1, 0xf);
897d3596
SC
962 if (ret) {
963 dev_err(&adapter->pdev->dev,
964 "Failed to set LED blink state.\n");
965 return ret;
966 }
967
968 msleep_interruptible(val * 1000);
969
2e9d722d 970 ret = adapter->nic_ops->config_led(adapter, 0, 0xf);
897d3596
SC
971 if (ret) {
972 dev_err(&adapter->pdev->dev,
973 "Failed to reset LED blink state.\n");
974 return ret;
975 }
976
977 return 0;
978}
979
af19b491
AKS
980static void
981qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
982{
983 struct qlcnic_adapter *adapter = netdev_priv(dev);
984 u32 wol_cfg;
985
986 wol->supported = 0;
987 wol->wolopts = 0;
988
989 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
990 if (wol_cfg & (1UL << adapter->portnum))
991 wol->supported |= WAKE_MAGIC;
992
993 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
994 if (wol_cfg & (1UL << adapter->portnum))
995 wol->wolopts |= WAKE_MAGIC;
996}
997
998static int
999qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1000{
1001 struct qlcnic_adapter *adapter = netdev_priv(dev);
1002 u32 wol_cfg;
1003
1004 if (wol->wolopts & ~WAKE_MAGIC)
1005 return -EOPNOTSUPP;
1006
1007 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1008 if (!(wol_cfg & (1 << adapter->portnum)))
1009 return -EOPNOTSUPP;
1010
1011 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1012 if (wol->wolopts & WAKE_MAGIC)
1013 wol_cfg |= 1UL << adapter->portnum;
1014 else
1015 wol_cfg &= ~(1UL << adapter->portnum);
1016
1017 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1018
1019 return 0;
1020}
1021
1022/*
1023 * Set the coalescing parameters. Currently only normal is supported.
1024 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1025 * firmware coalescing to default.
1026 */
1027static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1028 struct ethtool_coalesce *ethcoal)
1029{
1030 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1031
8a15ad1f 1032 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
af19b491
AKS
1033 return -EINVAL;
1034
1035 /*
1036 * Return Error if unsupported values or
1037 * unsupported parameters are set.
1038 */
1039 if (ethcoal->rx_coalesce_usecs > 0xffff ||
1040 ethcoal->rx_max_coalesced_frames > 0xffff ||
1041 ethcoal->tx_coalesce_usecs > 0xffff ||
1042 ethcoal->tx_max_coalesced_frames > 0xffff ||
1043 ethcoal->rx_coalesce_usecs_irq ||
1044 ethcoal->rx_max_coalesced_frames_irq ||
1045 ethcoal->tx_coalesce_usecs_irq ||
1046 ethcoal->tx_max_coalesced_frames_irq ||
1047 ethcoal->stats_block_coalesce_usecs ||
1048 ethcoal->use_adaptive_rx_coalesce ||
1049 ethcoal->use_adaptive_tx_coalesce ||
1050 ethcoal->pkt_rate_low ||
1051 ethcoal->rx_coalesce_usecs_low ||
1052 ethcoal->rx_max_coalesced_frames_low ||
1053 ethcoal->tx_coalesce_usecs_low ||
1054 ethcoal->tx_max_coalesced_frames_low ||
1055 ethcoal->pkt_rate_high ||
1056 ethcoal->rx_coalesce_usecs_high ||
1057 ethcoal->rx_max_coalesced_frames_high ||
1058 ethcoal->tx_coalesce_usecs_high ||
1059 ethcoal->tx_max_coalesced_frames_high)
1060 return -EINVAL;
1061
1062 if (!ethcoal->rx_coalesce_usecs ||
1063 !ethcoal->rx_max_coalesced_frames) {
1064 adapter->coal.flags = QLCNIC_INTR_DEFAULT;
1065 adapter->coal.normal.data.rx_time_us =
1066 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
1067 adapter->coal.normal.data.rx_packets =
1068 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
1069 } else {
1070 adapter->coal.flags = 0;
1071 adapter->coal.normal.data.rx_time_us =
1072 ethcoal->rx_coalesce_usecs;
1073 adapter->coal.normal.data.rx_packets =
1074 ethcoal->rx_max_coalesced_frames;
1075 }
1076 adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
1077 adapter->coal.normal.data.tx_packets =
1078 ethcoal->tx_max_coalesced_frames;
1079
1080 qlcnic_config_intr_coalesce(adapter);
1081
1082 return 0;
1083}
1084
1085static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1086 struct ethtool_coalesce *ethcoal)
1087{
1088 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1089
1090 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1091 return -EINVAL;
1092
1093 ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
1094 ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
1095 ethcoal->rx_max_coalesced_frames =
1096 adapter->coal.normal.data.rx_packets;
1097 ethcoal->tx_max_coalesced_frames =
1098 adapter->coal.normal.data.tx_packets;
1099
1100 return 0;
1101}
1102
1103static int qlcnic_set_flags(struct net_device *netdev, u32 data)
1104{
1105 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1106 int hw_lro;
1107
deaec0f6 1108 if (data & ~ETH_FLAG_LRO)
97d1935a 1109 return -EINVAL;
deaec0f6 1110
af19b491
AKS
1111 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
1112 return -EINVAL;
1113
24763d80
SC
1114 if (!adapter->rx_csum) {
1115 dev_info(&adapter->pdev->dev, "rx csum is off, "
1116 "cannot toggle lro\n");
1117 return -EINVAL;
1118 }
1119
a2152d09 1120 if ((data & ETH_FLAG_LRO) && (netdev->features & NETIF_F_LRO))
24763d80
SC
1121 return 0;
1122
deaec0f6
SG
1123 if (data & ETH_FLAG_LRO) {
1124 hw_lro = QLCNIC_LRO_ENABLED;
1125 netdev->features |= NETIF_F_LRO;
1126 } else {
1127 hw_lro = 0;
1128 netdev->features &= ~NETIF_F_LRO;
1129 }
af19b491
AKS
1130
1131 if (qlcnic_config_hw_lro(adapter, hw_lro))
1132 return -EIO;
1133
1134 if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter))
1135 return -EIO;
1136
1137
1138 return 0;
1139}
1140
65b5b420
AKS
1141static u32 qlcnic_get_msglevel(struct net_device *netdev)
1142{
1143 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1144
1145 return adapter->msg_enable;
1146}
1147
1148static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1149{
1150 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1151
1152 adapter->msg_enable = msglvl;
1153}
1154
af19b491
AKS
1155const struct ethtool_ops qlcnic_ethtool_ops = {
1156 .get_settings = qlcnic_get_settings,
1157 .set_settings = qlcnic_set_settings,
1158 .get_drvinfo = qlcnic_get_drvinfo,
1159 .get_regs_len = qlcnic_get_regs_len,
1160 .get_regs = qlcnic_get_regs,
1161 .get_link = ethtool_op_get_link,
1162 .get_eeprom_len = qlcnic_get_eeprom_len,
1163 .get_eeprom = qlcnic_get_eeprom,
1164 .get_ringparam = qlcnic_get_ringparam,
1165 .set_ringparam = qlcnic_set_ringparam,
1166 .get_pauseparam = qlcnic_get_pauseparam,
1167 .set_pauseparam = qlcnic_set_pauseparam,
8bae5698 1168 .get_tx_csum = qlcnic_get_tx_csum,
0325d69b 1169 .set_tx_csum = qlcnic_set_tx_csum,
af19b491
AKS
1170 .set_sg = ethtool_op_set_sg,
1171 .get_tso = qlcnic_get_tso,
1172 .set_tso = qlcnic_set_tso,
1173 .get_wol = qlcnic_get_wol,
1174 .set_wol = qlcnic_set_wol,
1175 .self_test = qlcnic_diag_test,
1176 .get_strings = qlcnic_get_strings,
1177 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1178 .get_sset_count = qlcnic_get_sset_count,
1179 .get_rx_csum = qlcnic_get_rx_csum,
1180 .set_rx_csum = qlcnic_set_rx_csum,
1181 .get_coalesce = qlcnic_get_intr_coalesce,
1182 .set_coalesce = qlcnic_set_intr_coalesce,
1183 .get_flags = ethtool_op_get_flags,
1184 .set_flags = qlcnic_set_flags,
897d3596 1185 .phys_id = qlcnic_blink_led,
65b5b420
AKS
1186 .set_msglevel = qlcnic_set_msglevel,
1187 .get_msglevel = qlcnic_get_msglevel,
af19b491 1188};