]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/net/qlcnic/qlcnic_ethtool.c
ethtool: cosmetic: Use ethtool ethtool_cmd_speed API
[mirror_ubuntu-zesty-kernel.git] / drivers / net / qlcnic / qlcnic_ethtool.c
CommitLineData
af19b491 1/*
40839129
SV
2 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2010 QLogic Corporation
af19b491 4 *
40839129 5 * See LICENSE.qlcnic for copyright and licensing details.
af19b491
AKS
6 */
7
8#include <linux/types.h>
9#include <linux/delay.h>
10#include <linux/pci.h>
11#include <linux/io.h>
12#include <linux/netdevice.h>
13#include <linux/ethtool.h>
14
15#include "qlcnic.h"
16
17struct qlcnic_stats {
18 char stat_string[ETH_GSTRING_LEN];
19 int sizeof_stat;
20 int stat_offset;
21};
22
23#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
24#define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
25
26static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
27 {"xmit_called",
28 QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)},
29 {"xmit_finished",
30 QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)},
31 {"rx_dropped",
32 QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
33 {"tx_dropped",
34 QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
35 {"csummed",
36 QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
37 {"rx_pkts",
38 QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
39 {"lro_pkts",
40 QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
41 {"rx_bytes",
42 QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
43 {"tx_bytes",
44 QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
8bfe8b91
SC
45 {"lrobytes",
46 QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
47 {"lso_frames",
48 QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
49 {"xmit_on",
50 QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
51 {"xmit_off",
52 QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
53 {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
54 QLC_OFF(stats.skb_alloc_failure)},
8ae6df97
AKS
55 {"null rxbuf",
56 QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
57 {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
58 QLC_OFF(stats.rx_dma_map_error)},
59 {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
60 QLC_OFF(stats.tx_dma_map_error)},
8bfe8b91 61
af19b491
AKS
62};
63
3666e0b0 64static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
65 "rx unicast frames",
66 "rx multicast frames",
67 "rx broadcast frames",
68 "rx dropped frames",
69 "rx errors",
70 "rx local frames",
71 "rx numbytes",
72 "tx unicast frames",
73 "tx multicast frames",
74 "tx broadcast frames",
75 "tx dropped frames",
76 "tx errors",
77 "tx local frames",
78 "tx numbytes",
79};
80
af19b491 81#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
3666e0b0 82#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
af19b491
AKS
83
84static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
85 "Register_Test_on_offline",
7eb9855d 86 "Link_Test_on_offline",
97319a27 87 "Interrupt_Test_offline"
af19b491
AKS
88};
89
90#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
91
92#define QLCNIC_RING_REGS_COUNT 20
93#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
94#define QLCNIC_MAX_EEPROM_LEN 1024
95
96static const u32 diag_registers[] = {
97 CRB_CMDPEG_STATE,
98 CRB_RCVPEG_STATE,
ff1b1bf8 99 CRB_XG_STATE_P3P,
af19b491
AKS
100 CRB_FW_CAPABILITIES_1,
101 ISR_INT_STATE_REG,
31018e06 102 QLCNIC_CRB_DRV_ACTIVE,
af19b491
AKS
103 QLCNIC_CRB_DEV_STATE,
104 QLCNIC_CRB_DRV_STATE,
105 QLCNIC_CRB_DRV_SCRATCH,
106 QLCNIC_CRB_DEV_PARTITION_INFO,
107 QLCNIC_CRB_DRV_IDC_VER,
108 QLCNIC_PEG_ALIVE_COUNTER,
109 QLCNIC_PEG_HALT_STATUS1,
110 QLCNIC_PEG_HALT_STATUS2,
111 QLCNIC_CRB_PEG_NET_0+0x3c,
112 QLCNIC_CRB_PEG_NET_1+0x3c,
113 QLCNIC_CRB_PEG_NET_2+0x3c,
114 QLCNIC_CRB_PEG_NET_4+0x3c,
115 -1
116};
117
2cffcdbf
RB
118#define QLCNIC_MGMT_API_VERSION 2
119#define QLCNIC_DEV_INFO_SIZE 1
120#define QLCNIC_ETHTOOL_REGS_VER 2
af19b491
AKS
121static int qlcnic_get_regs_len(struct net_device *dev)
122{
2cffcdbf
RB
123 return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
124 QLCNIC_DEV_INFO_SIZE + 1;
af19b491
AKS
125}
126
127static int qlcnic_get_eeprom_len(struct net_device *dev)
128{
129 return QLCNIC_FLASH_TOTAL_SIZE;
130}
131
132static void
133qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
134{
135 struct qlcnic_adapter *adapter = netdev_priv(dev);
136 u32 fw_major, fw_minor, fw_build;
137
138 fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
139 fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
140 fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
141 sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
142
143 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
144 strlcpy(drvinfo->driver, qlcnic_driver_name, 32);
145 strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID, 32);
146}
147
148static int
149qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
150{
151 struct qlcnic_adapter *adapter = netdev_priv(dev);
152 int check_sfp_module = 0;
b1fc6d3c 153 u16 pcifn = adapter->ahw->pci_func;
af19b491
AKS
154
155 /* read which mode */
b1fc6d3c 156 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
157 ecmd->supported = (SUPPORTED_10baseT_Half |
158 SUPPORTED_10baseT_Full |
159 SUPPORTED_100baseT_Half |
160 SUPPORTED_100baseT_Full |
161 SUPPORTED_1000baseT_Half |
162 SUPPORTED_1000baseT_Full);
163
164 ecmd->advertising = (ADVERTISED_100baseT_Half |
165 ADVERTISED_100baseT_Full |
166 ADVERTISED_1000baseT_Half |
167 ADVERTISED_1000baseT_Full);
168
70739497 169 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
af19b491
AKS
170 ecmd->duplex = adapter->link_duplex;
171 ecmd->autoneg = adapter->link_autoneg;
172
b1fc6d3c 173 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
174 u32 val;
175
176 val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
177 if (val == QLCNIC_PORT_MODE_802_3_AP) {
178 ecmd->supported = SUPPORTED_1000baseT_Full;
179 ecmd->advertising = ADVERTISED_1000baseT_Full;
180 } else {
181 ecmd->supported = SUPPORTED_10000baseT_Full;
182 ecmd->advertising = ADVERTISED_10000baseT_Full;
183 }
184
185 if (netif_running(dev) && adapter->has_link_events) {
70739497 186 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
af19b491
AKS
187 ecmd->autoneg = adapter->link_autoneg;
188 ecmd->duplex = adapter->link_duplex;
189 goto skip;
190 }
191
ff1b1bf8 192 val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
70739497
DD
193 ethtool_cmd_speed_set(ecmd, P3P_LINK_SPEED_MHZ *
194 P3P_LINK_SPEED_VAL(pcifn, val));
af19b491
AKS
195 ecmd->duplex = DUPLEX_FULL;
196 ecmd->autoneg = AUTONEG_DISABLE;
197 } else
198 return -EIO;
199
200skip:
201 ecmd->phy_address = adapter->physical_port;
202 ecmd->transceiver = XCVR_EXTERNAL;
203
b1fc6d3c 204 switch (adapter->ahw->board_type) {
ff1b1bf8
SV
205 case QLCNIC_BRDTYPE_P3P_REF_QG:
206 case QLCNIC_BRDTYPE_P3P_4_GB:
207 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
af19b491
AKS
208
209 ecmd->supported |= SUPPORTED_Autoneg;
210 ecmd->advertising |= ADVERTISED_Autoneg;
ff1b1bf8
SV
211 case QLCNIC_BRDTYPE_P3P_10G_CX4:
212 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
213 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
af19b491
AKS
214 ecmd->supported |= SUPPORTED_TP;
215 ecmd->advertising |= ADVERTISED_TP;
216 ecmd->port = PORT_TP;
217 ecmd->autoneg = adapter->link_autoneg;
218 break;
ff1b1bf8
SV
219 case QLCNIC_BRDTYPE_P3P_IMEZ:
220 case QLCNIC_BRDTYPE_P3P_XG_LOM:
221 case QLCNIC_BRDTYPE_P3P_HMEZ:
af19b491
AKS
222 ecmd->supported |= SUPPORTED_MII;
223 ecmd->advertising |= ADVERTISED_MII;
224 ecmd->port = PORT_MII;
225 ecmd->autoneg = AUTONEG_DISABLE;
226 break;
ff1b1bf8
SV
227 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
228 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
229 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
af19b491
AKS
230 ecmd->advertising |= ADVERTISED_TP;
231 ecmd->supported |= SUPPORTED_TP;
232 check_sfp_module = netif_running(dev) &&
233 adapter->has_link_events;
ff1b1bf8 234 case QLCNIC_BRDTYPE_P3P_10G_XFP:
af19b491
AKS
235 ecmd->supported |= SUPPORTED_FIBRE;
236 ecmd->advertising |= ADVERTISED_FIBRE;
237 ecmd->port = PORT_FIBRE;
238 ecmd->autoneg = AUTONEG_DISABLE;
239 break;
ff1b1bf8 240 case QLCNIC_BRDTYPE_P3P_10G_TP:
b1fc6d3c 241 if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
242 ecmd->autoneg = AUTONEG_DISABLE;
243 ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
244 ecmd->advertising |=
245 (ADVERTISED_FIBRE | ADVERTISED_TP);
246 ecmd->port = PORT_FIBRE;
247 check_sfp_module = netif_running(dev) &&
248 adapter->has_link_events;
249 } else {
250 ecmd->autoneg = AUTONEG_ENABLE;
251 ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
252 ecmd->advertising |=
253 (ADVERTISED_TP | ADVERTISED_Autoneg);
254 ecmd->port = PORT_TP;
255 }
256 break;
257 default:
258 dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
b1fc6d3c 259 adapter->ahw->board_type);
af19b491
AKS
260 return -EIO;
261 }
262
263 if (check_sfp_module) {
264 switch (adapter->module_type) {
265 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
266 case LINKEVENT_MODULE_OPTICAL_SRLR:
267 case LINKEVENT_MODULE_OPTICAL_LRM:
268 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
269 ecmd->port = PORT_FIBRE;
270 break;
271 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
272 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
273 case LINKEVENT_MODULE_TWINAX:
274 ecmd->port = PORT_TP;
275 break;
276 default:
277 ecmd->port = PORT_OTHER;
278 }
279 }
280
281 return 0;
282}
283
284static int
285qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
286{
7e610caa
SC
287 u32 config = 0;
288 u32 ret = 0;
af19b491 289 struct qlcnic_adapter *adapter = netdev_priv(dev);
7e610caa
SC
290
291 if (adapter->ahw->port_type != QLCNIC_GBE)
292 return -EOPNOTSUPP;
af19b491
AKS
293
294 /* read which mode */
7e610caa
SC
295 if (ecmd->duplex)
296 config |= 0x1;
af19b491 297
7e610caa
SC
298 if (ecmd->autoneg)
299 config |= 0x2;
300
301 switch (ethtool_cmd_speed(ecmd)) {
302 case SPEED_10:
303 config |= (0 << 8);
304 break;
305 case SPEED_100:
306 config |= (1 << 8);
307 break;
308 case SPEED_1000:
309 config |= (10 << 8);
310 break;
311 default:
312 return -EIO;
313 }
314
315 ret = qlcnic_fw_cmd_set_port(adapter, config);
316
317 if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
af19b491 318 return -EOPNOTSUPP;
7e610caa
SC
319 else if (ret)
320 return -EIO;
321
322 adapter->link_speed = ethtool_cmd_speed(ecmd);
323 adapter->link_duplex = ecmd->duplex;
324 adapter->link_autoneg = ecmd->autoneg;
af19b491
AKS
325
326 if (!netif_running(dev))
327 return 0;
328
329 dev->netdev_ops->ndo_stop(dev);
330 return dev->netdev_ops->ndo_open(dev);
331}
332
333static void
334qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
335{
336 struct qlcnic_adapter *adapter = netdev_priv(dev);
b1fc6d3c 337 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
af19b491
AKS
338 struct qlcnic_host_sds_ring *sds_ring;
339 u32 *regs_buff = p;
c265eb6e 340 int ring, i = 0, j = 0;
af19b491
AKS
341
342 memset(p, 0, qlcnic_get_regs_len(dev));
2cffcdbf 343 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
b1fc6d3c 344 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
af19b491 345
2cffcdbf
RB
346 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
347 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
348
c265eb6e
AKS
349 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
350 regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
af19b491 351
8a15ad1f 352 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
ce668443
AKS
353 return;
354
af19b491
AKS
355 regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
356
357 regs_buff[i++] = 1; /* No. of tx ring */
358 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
359 regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
360
361 regs_buff[i++] = 2; /* No. of rx ring */
362 regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
363 regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
364
365 regs_buff[i++] = adapter->max_sds_rings;
366
367 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
368 sds_ring = &(recv_ctx->sds_rings[ring]);
369 regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
370 }
371}
372
373static u32 qlcnic_test_link(struct net_device *dev)
374{
375 struct qlcnic_adapter *adapter = netdev_priv(dev);
376 u32 val;
377
ff1b1bf8 378 val = QLCRD32(adapter, CRB_XG_STATE_P3P);
b1fc6d3c 379 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
ff1b1bf8 380 return (val == XG_LINK_UP_P3P) ? 0 : 1;
af19b491
AKS
381}
382
383static int
384qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
385 u8 *bytes)
386{
387 struct qlcnic_adapter *adapter = netdev_priv(dev);
388 int offset;
389 int ret;
390
391 if (eeprom->len == 0)
392 return -EINVAL;
393
394 eeprom->magic = (adapter->pdev)->vendor |
395 ((adapter->pdev)->device << 16);
396 offset = eeprom->offset;
397
398 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
399 eeprom->len);
400 if (ret < 0)
401 return ret;
402
403 return 0;
404}
405
406static void
407qlcnic_get_ringparam(struct net_device *dev,
408 struct ethtool_ringparam *ring)
409{
410 struct qlcnic_adapter *adapter = netdev_priv(dev);
411
412 ring->rx_pending = adapter->num_rxd;
413 ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
af19b491
AKS
414 ring->tx_pending = adapter->num_txd;
415
90d19005
SC
416 ring->rx_max_pending = adapter->max_rxd;
417 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
af19b491
AKS
418 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
419
420 ring->rx_mini_max_pending = 0;
421 ring->rx_mini_pending = 0;
422}
423
424static u32
425qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
426{
427 u32 num_desc;
428 num_desc = max(val, min);
429 num_desc = min(num_desc, max);
430 num_desc = roundup_pow_of_two(num_desc);
431
432 if (val != num_desc) {
433 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
434 qlcnic_driver_name, r_name, num_desc, val);
435 }
436
437 return num_desc;
438}
439
440static int
441qlcnic_set_ringparam(struct net_device *dev,
442 struct ethtool_ringparam *ring)
443{
444 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
445 u16 num_rxd, num_jumbo_rxd, num_txd;
446
af19b491
AKS
447 if (ring->rx_mini_pending)
448 return -EOPNOTSUPP;
449
af19b491 450 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
90d19005 451 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
af19b491
AKS
452
453 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
90d19005
SC
454 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
455 "rx jumbo");
af19b491
AKS
456
457 num_txd = qlcnic_validate_ringparam(ring->tx_pending,
458 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
459
460 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
461 num_jumbo_rxd == adapter->num_jumbo_rxd)
462 return 0;
463
464 adapter->num_rxd = num_rxd;
465 adapter->num_jumbo_rxd = num_jumbo_rxd;
466 adapter->num_txd = num_txd;
467
468 return qlcnic_reset_context(adapter);
469}
470
f94bc1e7
SC
471static void qlcnic_get_channels(struct net_device *dev,
472 struct ethtool_channels *channel)
473{
474 struct qlcnic_adapter *adapter = netdev_priv(dev);
475
476 channel->max_rx = rounddown_pow_of_two(min_t(int,
477 adapter->max_rx_ques, num_online_cpus()));
478 channel->max_tx = adapter->max_tx_ques;
479
480 channel->rx_count = adapter->max_sds_rings;
481 channel->tx_count = adapter->max_tx_ques;
482}
483
484static int qlcnic_set_channels(struct net_device *dev,
485 struct ethtool_channels *channel)
486{
487 struct qlcnic_adapter *adapter = netdev_priv(dev);
488 int err;
489
490 if (channel->other_count || channel->combined_count ||
491 channel->tx_count != channel->max_tx)
492 return -EINVAL;
493
494 err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count);
495 if (err)
496 return err;
497
498 err = qlcnic_set_max_rss(adapter, channel->rx_count);
499 netdev_info(dev, "allocated 0x%x sds rings\n",
500 adapter->max_sds_rings);
501 return err;
502}
503
af19b491
AKS
504static void
505qlcnic_get_pauseparam(struct net_device *netdev,
506 struct ethtool_pauseparam *pause)
507{
508 struct qlcnic_adapter *adapter = netdev_priv(netdev);
509 int port = adapter->physical_port;
510 __u32 val;
511
b1fc6d3c 512 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
513 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
514 return;
515 /* get flow control settings */
516 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
517 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
518 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
519 switch (port) {
520 case 0:
521 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
522 break;
523 case 1:
524 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
525 break;
526 case 2:
527 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
528 break;
529 case 3:
530 default:
531 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
532 break;
533 }
b1fc6d3c 534 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
af19b491
AKS
535 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
536 return;
537 pause->rx_pause = 1;
538 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
539 if (port == 0)
540 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
541 else
542 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
543 } else {
544 dev_err(&netdev->dev, "Unknown board type: %x\n",
b1fc6d3c 545 adapter->ahw->port_type);
af19b491
AKS
546 }
547}
548
549static int
550qlcnic_set_pauseparam(struct net_device *netdev,
551 struct ethtool_pauseparam *pause)
552{
553 struct qlcnic_adapter *adapter = netdev_priv(netdev);
554 int port = adapter->physical_port;
555 __u32 val;
556
557 /* read mode */
b1fc6d3c 558 if (adapter->ahw->port_type == QLCNIC_GBE) {
af19b491
AKS
559 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
560 return -EIO;
561 /* set flow control */
562 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
563
564 if (pause->rx_pause)
565 qlcnic_gb_rx_flowctl(val);
566 else
567 qlcnic_gb_unset_rx_flowctl(val);
568
569 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
570 val);
571 /* set autoneg */
572 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
573 switch (port) {
574 case 0:
575 if (pause->tx_pause)
576 qlcnic_gb_unset_gb0_mask(val);
577 else
578 qlcnic_gb_set_gb0_mask(val);
579 break;
580 case 1:
581 if (pause->tx_pause)
582 qlcnic_gb_unset_gb1_mask(val);
583 else
584 qlcnic_gb_set_gb1_mask(val);
585 break;
586 case 2:
587 if (pause->tx_pause)
588 qlcnic_gb_unset_gb2_mask(val);
589 else
590 qlcnic_gb_set_gb2_mask(val);
591 break;
592 case 3:
593 default:
594 if (pause->tx_pause)
595 qlcnic_gb_unset_gb3_mask(val);
596 else
597 qlcnic_gb_set_gb3_mask(val);
598 break;
599 }
600 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
b1fc6d3c 601 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
6d181688
RB
602 if (!pause->rx_pause || pause->autoneg)
603 return -EOPNOTSUPP;
604
af19b491
AKS
605 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
606 return -EIO;
6d181688 607
af19b491
AKS
608 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
609 if (port == 0) {
610 if (pause->tx_pause)
611 qlcnic_xg_unset_xg0_mask(val);
612 else
613 qlcnic_xg_set_xg0_mask(val);
614 } else {
615 if (pause->tx_pause)
616 qlcnic_xg_unset_xg1_mask(val);
617 else
618 qlcnic_xg_set_xg1_mask(val);
619 }
620 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
621 } else {
622 dev_err(&netdev->dev, "Unknown board type: %x\n",
b1fc6d3c 623 adapter->ahw->port_type);
af19b491
AKS
624 }
625 return 0;
626}
627
628static int qlcnic_reg_test(struct net_device *dev)
629{
630 struct qlcnic_adapter *adapter = netdev_priv(dev);
deffab05 631 u32 data_read;
af19b491
AKS
632
633 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
634 if ((data_read & 0xffff) != adapter->pdev->vendor)
635 return 1;
636
af19b491
AKS
637 return 0;
638}
639
640static int qlcnic_get_sset_count(struct net_device *dev, int sset)
641{
3666e0b0 642 struct qlcnic_adapter *adapter = netdev_priv(dev);
af19b491
AKS
643 switch (sset) {
644 case ETH_SS_TEST:
645 return QLCNIC_TEST_LEN;
646 case ETH_SS_STATS:
3666e0b0 647 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
648 return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
af19b491
AKS
649 return QLCNIC_STATS_LEN;
650 default:
651 return -EOPNOTSUPP;
652 }
653}
654
7eb9855d
AKS
655static int qlcnic_irq_test(struct net_device *netdev)
656{
657 struct qlcnic_adapter *adapter = netdev_priv(netdev);
658 int max_sds_rings = adapter->max_sds_rings;
659 int ret;
660
661 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
662 return -EIO;
663
664 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
665 if (ret)
666 goto clear_it;
667
668 adapter->diag_cnt = 0;
b1fc6d3c
AC
669 ret = qlcnic_issue_cmd(adapter, adapter->ahw->pci_func,
670 adapter->fw_hal_version, adapter->ahw->pci_func,
2e9d722d 671 0, 0, 0x00000011);
7eb9855d
AKS
672 if (ret)
673 goto done;
674
675 msleep(10);
676
677 ret = !adapter->diag_cnt;
678
679done:
680 qlcnic_diag_free_res(netdev, max_sds_rings);
681
682clear_it:
683 adapter->max_sds_rings = max_sds_rings;
684 clear_bit(__QLCNIC_RESETTING, &adapter->state);
685 return ret;
686}
687
af19b491
AKS
688static void
689qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
690 u64 *data)
691{
692 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
897d3596 693
8dec32cc
SC
694 data[0] = qlcnic_reg_test(dev);
695 if (data[0])
696 eth_test->flags |= ETH_TEST_FL_FAILED;
697
698 data[1] = (u64) qlcnic_test_link(dev);
699 if (data[1])
700 eth_test->flags |= ETH_TEST_FL_FAILED;
701
13b93ed9 702 if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
7eb9855d
AKS
703 data[2] = qlcnic_irq_test(dev);
704 if (data[2])
705 eth_test->flags |= ETH_TEST_FL_FAILED;
cdaff185 706
cdaff185 707
7eb9855d 708 }
af19b491
AKS
709}
710
711static void
712qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
713{
3666e0b0 714 struct qlcnic_adapter *adapter = netdev_priv(dev);
715 int index, i;
af19b491
AKS
716
717 switch (stringset) {
718 case ETH_SS_TEST:
719 memcpy(data, *qlcnic_gstrings_test,
720 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
721 break;
722 case ETH_SS_STATS:
723 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
724 memcpy(data + index * ETH_GSTRING_LEN,
725 qlcnic_gstrings_stats[index].stat_string,
726 ETH_GSTRING_LEN);
727 }
3666e0b0 728 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
729 return;
730 for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
731 memcpy(data + index * ETH_GSTRING_LEN,
732 qlcnic_device_gstrings_stats[i],
733 ETH_GSTRING_LEN);
734 }
af19b491
AKS
735 }
736}
737
3666e0b0 738#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
739 (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
740
741static void
742qlcnic_fill_device_stats(int *index, u64 *data,
743 struct __qlcnic_esw_statistics *stats)
744{
745 int ind = *index;
746
747 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
748 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
749 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
750 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
751 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
752 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
753 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
754
755 *index = ind;
756}
757
af19b491
AKS
758static void
759qlcnic_get_ethtool_stats(struct net_device *dev,
760 struct ethtool_stats *stats, u64 * data)
761{
762 struct qlcnic_adapter *adapter = netdev_priv(dev);
3666e0b0 763 struct qlcnic_esw_statistics port_stats;
764 int index, ret;
af19b491
AKS
765
766 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
767 char *p =
768 (char *)adapter +
769 qlcnic_gstrings_stats[index].stat_offset;
770 data[index] =
771 (qlcnic_gstrings_stats[index].sizeof_stat ==
772 sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
773 }
3666e0b0 774
775 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
776 return;
777
778 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
b1fc6d3c 779 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
3666e0b0 780 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
781 if (ret)
782 return;
783
784 qlcnic_fill_device_stats(&index, data, &port_stats.rx);
785
b1fc6d3c 786 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
3666e0b0 787 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
788 if (ret)
789 return;
790
791 qlcnic_fill_device_stats(&index, data, &port_stats.tx);
af19b491
AKS
792}
793
94469f75 794static int qlcnic_set_led(struct net_device *dev,
795 enum ethtool_phys_id_state state)
897d3596
SC
796{
797 struct qlcnic_adapter *adapter = netdev_priv(dev);
c75822a3 798 int max_sds_rings = adapter->max_sds_rings;
c75822a3 799
94469f75 800 switch (state) {
801 case ETHTOOL_ID_ACTIVE:
94469f75 802 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
803 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
804 return -EIO;
805
806 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) {
807 clear_bit(__QLCNIC_RESETTING, &adapter->state);
808 return -EIO;
809 }
89b4208e 810 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
c75822a3 811 }
8a15ad1f 812
94469f75 813 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0)
814 return 0;
815
897d3596
SC
816 dev_err(&adapter->pdev->dev,
817 "Failed to set LED blink state.\n");
94469f75 818 break;
897d3596 819
94469f75 820 case ETHTOOL_ID_INACTIVE:
89b4208e
SC
821 if (adapter->nic_ops->config_led(adapter, 0, 0xf))
822 dev_err(&adapter->pdev->dev,
823 "Failed to reset LED blink state.\n");
897d3596 824
94469f75 825 break;
826
827 default:
828 return -EINVAL;
897d3596
SC
829 }
830
89b4208e 831 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) {
c75822a3
SC
832 qlcnic_diag_free_res(dev, max_sds_rings);
833 clear_bit(__QLCNIC_RESETTING, &adapter->state);
834 }
c75822a3 835
94469f75 836 return -EIO;
897d3596
SC
837}
838
af19b491
AKS
839static void
840qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
841{
842 struct qlcnic_adapter *adapter = netdev_priv(dev);
843 u32 wol_cfg;
844
845 wol->supported = 0;
846 wol->wolopts = 0;
847
848 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
849 if (wol_cfg & (1UL << adapter->portnum))
850 wol->supported |= WAKE_MAGIC;
851
852 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
853 if (wol_cfg & (1UL << adapter->portnum))
854 wol->wolopts |= WAKE_MAGIC;
855}
856
857static int
858qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
859{
860 struct qlcnic_adapter *adapter = netdev_priv(dev);
861 u32 wol_cfg;
862
863 if (wol->wolopts & ~WAKE_MAGIC)
864 return -EOPNOTSUPP;
865
866 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
867 if (!(wol_cfg & (1 << adapter->portnum)))
868 return -EOPNOTSUPP;
869
870 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
871 if (wol->wolopts & WAKE_MAGIC)
872 wol_cfg |= 1UL << adapter->portnum;
873 else
874 wol_cfg &= ~(1UL << adapter->portnum);
875
876 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
877
878 return 0;
879}
880
881/*
882 * Set the coalescing parameters. Currently only normal is supported.
883 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
884 * firmware coalescing to default.
885 */
886static int qlcnic_set_intr_coalesce(struct net_device *netdev,
887 struct ethtool_coalesce *ethcoal)
888{
889 struct qlcnic_adapter *adapter = netdev_priv(netdev);
890
8a15ad1f 891 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
af19b491
AKS
892 return -EINVAL;
893
894 /*
895 * Return Error if unsupported values or
896 * unsupported parameters are set.
897 */
898 if (ethcoal->rx_coalesce_usecs > 0xffff ||
899 ethcoal->rx_max_coalesced_frames > 0xffff ||
8816d009
AC
900 ethcoal->tx_coalesce_usecs ||
901 ethcoal->tx_max_coalesced_frames ||
af19b491
AKS
902 ethcoal->rx_coalesce_usecs_irq ||
903 ethcoal->rx_max_coalesced_frames_irq ||
904 ethcoal->tx_coalesce_usecs_irq ||
905 ethcoal->tx_max_coalesced_frames_irq ||
906 ethcoal->stats_block_coalesce_usecs ||
907 ethcoal->use_adaptive_rx_coalesce ||
908 ethcoal->use_adaptive_tx_coalesce ||
909 ethcoal->pkt_rate_low ||
910 ethcoal->rx_coalesce_usecs_low ||
911 ethcoal->rx_max_coalesced_frames_low ||
912 ethcoal->tx_coalesce_usecs_low ||
913 ethcoal->tx_max_coalesced_frames_low ||
914 ethcoal->pkt_rate_high ||
915 ethcoal->rx_coalesce_usecs_high ||
916 ethcoal->rx_max_coalesced_frames_high ||
917 ethcoal->tx_coalesce_usecs_high ||
918 ethcoal->tx_max_coalesced_frames_high)
919 return -EINVAL;
920
921 if (!ethcoal->rx_coalesce_usecs ||
922 !ethcoal->rx_max_coalesced_frames) {
8816d009
AC
923 adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
924 adapter->ahw->coal.rx_time_us =
af19b491 925 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
8816d009 926 adapter->ahw->coal.rx_packets =
af19b491
AKS
927 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
928 } else {
8816d009
AC
929 adapter->ahw->coal.flag = 0;
930 adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
931 adapter->ahw->coal.rx_packets =
932 ethcoal->rx_max_coalesced_frames;
af19b491 933 }
af19b491
AKS
934
935 qlcnic_config_intr_coalesce(adapter);
936
937 return 0;
938}
939
940static int qlcnic_get_intr_coalesce(struct net_device *netdev,
941 struct ethtool_coalesce *ethcoal)
942{
943 struct qlcnic_adapter *adapter = netdev_priv(netdev);
944
945 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
946 return -EINVAL;
947
8816d009
AC
948 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
949 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
af19b491
AKS
950
951 return 0;
952}
953
65b5b420
AKS
954static u32 qlcnic_get_msglevel(struct net_device *netdev)
955{
956 struct qlcnic_adapter *adapter = netdev_priv(netdev);
957
958 return adapter->msg_enable;
959}
960
961static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
962{
963 struct qlcnic_adapter *adapter = netdev_priv(netdev);
964
965 adapter->msg_enable = msglvl;
966}
967
af19b491
AKS
968const struct ethtool_ops qlcnic_ethtool_ops = {
969 .get_settings = qlcnic_get_settings,
970 .set_settings = qlcnic_set_settings,
971 .get_drvinfo = qlcnic_get_drvinfo,
972 .get_regs_len = qlcnic_get_regs_len,
973 .get_regs = qlcnic_get_regs,
974 .get_link = ethtool_op_get_link,
975 .get_eeprom_len = qlcnic_get_eeprom_len,
976 .get_eeprom = qlcnic_get_eeprom,
977 .get_ringparam = qlcnic_get_ringparam,
978 .set_ringparam = qlcnic_set_ringparam,
f94bc1e7
SC
979 .get_channels = qlcnic_get_channels,
980 .set_channels = qlcnic_set_channels,
af19b491
AKS
981 .get_pauseparam = qlcnic_get_pauseparam,
982 .set_pauseparam = qlcnic_set_pauseparam,
af19b491
AKS
983 .get_wol = qlcnic_get_wol,
984 .set_wol = qlcnic_set_wol,
985 .self_test = qlcnic_diag_test,
986 .get_strings = qlcnic_get_strings,
987 .get_ethtool_stats = qlcnic_get_ethtool_stats,
988 .get_sset_count = qlcnic_get_sset_count,
af19b491
AKS
989 .get_coalesce = qlcnic_get_intr_coalesce,
990 .set_coalesce = qlcnic_set_intr_coalesce,
94469f75 991 .set_phys_id = qlcnic_set_led,
65b5b420
AKS
992 .set_msglevel = qlcnic_set_msglevel,
993 .get_msglevel = qlcnic_get_msglevel,
af19b491 994};