blob: de65847f3559290a58c8d59f0b765e6f54eb23d8 [file] [log] [blame]
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001/*
Sritej Velaga40839129f2010-12-02 20:41:56 +00002 * QLogic qlcnic NIC Driver
3 * Copyright (c) 2009-2010 QLogic Corporation
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00004 *
Sritej Velaga40839129f2010-12-02 20:41:56 +00005 * See LICENSE.qlcnic for copyright and licensing details.
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00006 */
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)},
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +000045 {"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)},
Amit Kumar Salecha8ae6df92010-04-22 02:51:35 +000055 {"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)},
Sucheta Chakraborty8bfe8b92010-03-08 00:14:46 +000061
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000062};
63
amit salecha3666e0b2010-10-18 01:47:48 +000064static 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
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000081#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
amit salecha3666e0b2010-10-18 01:47:48 +000082#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000083
84static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
85 "Register_Test_on_offline",
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +000086 "Link_Test_on_offline",
Sucheta Chakraborty97319a272010-12-02 20:41:23 +000087 "Interrupt_Test_offline"
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +000088};
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,
Sritej Velagaff1b1bf2010-10-07 23:46:10 +000099 CRB_XG_STATE_P3P,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000100 CRB_FW_CAPABILITIES_1,
101 ISR_INT_STATE_REG,
Amit Kumar Salecha31018e02010-08-25 04:03:05 +0000102 QLCNIC_CRB_DRV_ACTIVE,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000103 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
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000118#define QLCNIC_MGMT_API_VERSION 2
119#define QLCNIC_DEV_INFO_SIZE 1
120#define QLCNIC_ETHTOOL_REGS_VER 2
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000121static int qlcnic_get_regs_len(struct net_device *dev)
122{
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000123 return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
124 QLCNIC_DEV_INFO_SIZE + 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000125}
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;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000153 u16 pcifn = adapter->ahw->pci_func;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000154
155 /* read which mode */
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000156 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000157 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
169 ecmd->speed = adapter->link_speed;
170 ecmd->duplex = adapter->link_duplex;
171 ecmd->autoneg = adapter->link_autoneg;
172
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000173 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000174 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) {
186 ecmd->speed = adapter->link_speed;
187 ecmd->autoneg = adapter->link_autoneg;
188 ecmd->duplex = adapter->link_duplex;
189 goto skip;
190 }
191
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000192 val = QLCRD32(adapter, P3P_LINK_SPEED_REG(pcifn));
193 ecmd->speed = P3P_LINK_SPEED_MHZ *
194 P3P_LINK_SPEED_VAL(pcifn, val);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000195 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
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000204 switch (adapter->ahw->board_type) {
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000205 case QLCNIC_BRDTYPE_P3P_REF_QG:
206 case QLCNIC_BRDTYPE_P3P_4_GB:
207 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000208
209 ecmd->supported |= SUPPORTED_Autoneg;
210 ecmd->advertising |= ADVERTISED_Autoneg;
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000211 case QLCNIC_BRDTYPE_P3P_10G_CX4:
212 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
213 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000214 ecmd->supported |= SUPPORTED_TP;
215 ecmd->advertising |= ADVERTISED_TP;
216 ecmd->port = PORT_TP;
217 ecmd->autoneg = adapter->link_autoneg;
218 break;
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000219 case QLCNIC_BRDTYPE_P3P_IMEZ:
220 case QLCNIC_BRDTYPE_P3P_XG_LOM:
221 case QLCNIC_BRDTYPE_P3P_HMEZ:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000222 ecmd->supported |= SUPPORTED_MII;
223 ecmd->advertising |= ADVERTISED_MII;
224 ecmd->port = PORT_MII;
225 ecmd->autoneg = AUTONEG_DISABLE;
226 break;
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000227 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
228 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
229 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000230 ecmd->advertising |= ADVERTISED_TP;
231 ecmd->supported |= SUPPORTED_TP;
232 check_sfp_module = netif_running(dev) &&
233 adapter->has_link_events;
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000234 case QLCNIC_BRDTYPE_P3P_10G_XFP:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000235 ecmd->supported |= SUPPORTED_FIBRE;
236 ecmd->advertising |= ADVERTISED_FIBRE;
237 ecmd->port = PORT_FIBRE;
238 ecmd->autoneg = AUTONEG_DISABLE;
239 break;
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000240 case QLCNIC_BRDTYPE_P3P_10G_TP:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000241 if (adapter->ahw->port_type == QLCNIC_XGBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000242 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",
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000259 adapter->ahw->board_type);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000260 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{
287 struct qlcnic_adapter *adapter = netdev_priv(dev);
288 __u32 status;
289
290 /* read which mode */
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000291 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000292 /* autonegotiation */
293 if (qlcnic_fw_cmd_set_phy(adapter,
294 QLCNIC_NIU_GB_MII_MGMT_ADDR_AUTONEG,
295 ecmd->autoneg) != 0)
296 return -EIO;
297 else
298 adapter->link_autoneg = ecmd->autoneg;
299
300 if (qlcnic_fw_cmd_query_phy(adapter,
301 QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
302 &status) != 0)
303 return -EIO;
304
305 switch (ecmd->speed) {
306 case SPEED_10:
307 qlcnic_set_phy_speed(status, 0);
308 break;
309 case SPEED_100:
310 qlcnic_set_phy_speed(status, 1);
311 break;
312 case SPEED_1000:
313 qlcnic_set_phy_speed(status, 2);
314 break;
315 }
316
317 if (ecmd->duplex == DUPLEX_HALF)
318 qlcnic_clear_phy_duplex(status);
319 if (ecmd->duplex == DUPLEX_FULL)
320 qlcnic_set_phy_duplex(status);
321 if (qlcnic_fw_cmd_set_phy(adapter,
322 QLCNIC_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
323 *((int *)&status)) != 0)
324 return -EIO;
325 else {
326 adapter->link_speed = ecmd->speed;
327 adapter->link_duplex = ecmd->duplex;
328 }
329 } else
330 return -EOPNOTSUPP;
331
332 if (!netif_running(dev))
333 return 0;
334
335 dev->netdev_ops->ndo_stop(dev);
336 return dev->netdev_ops->ndo_open(dev);
337}
338
339static void
340qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
341{
342 struct qlcnic_adapter *adapter = netdev_priv(dev);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000343 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000344 struct qlcnic_host_sds_ring *sds_ring;
345 u32 *regs_buff = p;
Amit Kumar Salechac265eb62010-10-04 04:20:11 +0000346 int ring, i = 0, j = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000347
348 memset(p, 0, qlcnic_get_regs_len(dev));
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000349 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000350 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000351
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000352 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
353 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
354
Amit Kumar Salechac265eb62010-10-04 04:20:11 +0000355 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
356 regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000357
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000358 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
Amit Kumar Salechace668442010-02-01 05:24:57 +0000359 return;
360
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000361 regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
362
363 regs_buff[i++] = 1; /* No. of tx ring */
364 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
365 regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
366
367 regs_buff[i++] = 2; /* No. of rx ring */
368 regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
369 regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
370
371 regs_buff[i++] = adapter->max_sds_rings;
372
373 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
374 sds_ring = &(recv_ctx->sds_rings[ring]);
375 regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
376 }
377}
378
379static u32 qlcnic_test_link(struct net_device *dev)
380{
381 struct qlcnic_adapter *adapter = netdev_priv(dev);
382 u32 val;
383
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000384 val = QLCRD32(adapter, CRB_XG_STATE_P3P);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000385 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
Sritej Velagaff1b1bf2010-10-07 23:46:10 +0000386 return (val == XG_LINK_UP_P3P) ? 0 : 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000387}
388
389static int
390qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
391 u8 *bytes)
392{
393 struct qlcnic_adapter *adapter = netdev_priv(dev);
394 int offset;
395 int ret;
396
397 if (eeprom->len == 0)
398 return -EINVAL;
399
400 eeprom->magic = (adapter->pdev)->vendor |
401 ((adapter->pdev)->device << 16);
402 offset = eeprom->offset;
403
404 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
405 eeprom->len);
406 if (ret < 0)
407 return ret;
408
409 return 0;
410}
411
412static void
413qlcnic_get_ringparam(struct net_device *dev,
414 struct ethtool_ringparam *ring)
415{
416 struct qlcnic_adapter *adapter = netdev_priv(dev);
417
418 ring->rx_pending = adapter->num_rxd;
419 ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000420 ring->tx_pending = adapter->num_txd;
421
Sony Chacko90d19002010-10-26 17:53:08 +0000422 ring->rx_max_pending = adapter->max_rxd;
423 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000424 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
425
426 ring->rx_mini_max_pending = 0;
427 ring->rx_mini_pending = 0;
428}
429
430static u32
431qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
432{
433 u32 num_desc;
434 num_desc = max(val, min);
435 num_desc = min(num_desc, max);
436 num_desc = roundup_pow_of_two(num_desc);
437
438 if (val != num_desc) {
439 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
440 qlcnic_driver_name, r_name, num_desc, val);
441 }
442
443 return num_desc;
444}
445
446static int
447qlcnic_set_ringparam(struct net_device *dev,
448 struct ethtool_ringparam *ring)
449{
450 struct qlcnic_adapter *adapter = netdev_priv(dev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000451 u16 num_rxd, num_jumbo_rxd, num_txd;
452
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000453 if (ring->rx_mini_pending)
454 return -EOPNOTSUPP;
455
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000456 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
Sony Chacko90d19002010-10-26 17:53:08 +0000457 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000458
459 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
Sony Chacko90d19002010-10-26 17:53:08 +0000460 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
461 "rx jumbo");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000462
463 num_txd = qlcnic_validate_ringparam(ring->tx_pending,
464 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
465
466 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
467 num_jumbo_rxd == adapter->num_jumbo_rxd)
468 return 0;
469
470 adapter->num_rxd = num_rxd;
471 adapter->num_jumbo_rxd = num_jumbo_rxd;
472 adapter->num_txd = num_txd;
473
474 return qlcnic_reset_context(adapter);
475}
476
477static void
478qlcnic_get_pauseparam(struct net_device *netdev,
479 struct ethtool_pauseparam *pause)
480{
481 struct qlcnic_adapter *adapter = netdev_priv(netdev);
482 int port = adapter->physical_port;
483 __u32 val;
484
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000485 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000486 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
487 return;
488 /* get flow control settings */
489 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
490 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
491 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
492 switch (port) {
493 case 0:
494 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
495 break;
496 case 1:
497 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
498 break;
499 case 2:
500 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
501 break;
502 case 3:
503 default:
504 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
505 break;
506 }
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000507 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000508 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
509 return;
510 pause->rx_pause = 1;
511 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
512 if (port == 0)
513 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
514 else
515 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
516 } else {
517 dev_err(&netdev->dev, "Unknown board type: %x\n",
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000518 adapter->ahw->port_type);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000519 }
520}
521
522static int
523qlcnic_set_pauseparam(struct net_device *netdev,
524 struct ethtool_pauseparam *pause)
525{
526 struct qlcnic_adapter *adapter = netdev_priv(netdev);
527 int port = adapter->physical_port;
528 __u32 val;
529
530 /* read mode */
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000531 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000532 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
533 return -EIO;
534 /* set flow control */
535 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
536
537 if (pause->rx_pause)
538 qlcnic_gb_rx_flowctl(val);
539 else
540 qlcnic_gb_unset_rx_flowctl(val);
541
542 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
543 val);
544 /* set autoneg */
545 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
546 switch (port) {
547 case 0:
548 if (pause->tx_pause)
549 qlcnic_gb_unset_gb0_mask(val);
550 else
551 qlcnic_gb_set_gb0_mask(val);
552 break;
553 case 1:
554 if (pause->tx_pause)
555 qlcnic_gb_unset_gb1_mask(val);
556 else
557 qlcnic_gb_set_gb1_mask(val);
558 break;
559 case 2:
560 if (pause->tx_pause)
561 qlcnic_gb_unset_gb2_mask(val);
562 else
563 qlcnic_gb_set_gb2_mask(val);
564 break;
565 case 3:
566 default:
567 if (pause->tx_pause)
568 qlcnic_gb_unset_gb3_mask(val);
569 else
570 qlcnic_gb_set_gb3_mask(val);
571 break;
572 }
573 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000574 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
Rajesh Borundia6d181682010-07-13 20:33:31 +0000575 if (!pause->rx_pause || pause->autoneg)
576 return -EOPNOTSUPP;
577
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000578 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
579 return -EIO;
Rajesh Borundia6d181682010-07-13 20:33:31 +0000580
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000581 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
582 if (port == 0) {
583 if (pause->tx_pause)
584 qlcnic_xg_unset_xg0_mask(val);
585 else
586 qlcnic_xg_set_xg0_mask(val);
587 } else {
588 if (pause->tx_pause)
589 qlcnic_xg_unset_xg1_mask(val);
590 else
591 qlcnic_xg_set_xg1_mask(val);
592 }
593 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
594 } else {
595 dev_err(&netdev->dev, "Unknown board type: %x\n",
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000596 adapter->ahw->port_type);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000597 }
598 return 0;
599}
600
601static int qlcnic_reg_test(struct net_device *dev)
602{
603 struct qlcnic_adapter *adapter = netdev_priv(dev);
Amit Kumar Salechadeffab02010-05-13 03:07:43 +0000604 u32 data_read;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000605
606 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
607 if ((data_read & 0xffff) != adapter->pdev->vendor)
608 return 1;
609
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000610 return 0;
611}
612
613static int qlcnic_get_sset_count(struct net_device *dev, int sset)
614{
amit salecha3666e0b2010-10-18 01:47:48 +0000615 struct qlcnic_adapter *adapter = netdev_priv(dev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000616 switch (sset) {
617 case ETH_SS_TEST:
618 return QLCNIC_TEST_LEN;
619 case ETH_SS_STATS:
amit salecha3666e0b2010-10-18 01:47:48 +0000620 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
621 return QLCNIC_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000622 return QLCNIC_STATS_LEN;
623 default:
624 return -EOPNOTSUPP;
625 }
626}
627
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000628static int qlcnic_irq_test(struct net_device *netdev)
629{
630 struct qlcnic_adapter *adapter = netdev_priv(netdev);
631 int max_sds_rings = adapter->max_sds_rings;
632 int ret;
633
634 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
635 return -EIO;
636
637 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
638 if (ret)
639 goto clear_it;
640
641 adapter->diag_cnt = 0;
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000642 ret = qlcnic_issue_cmd(adapter, adapter->ahw->pci_func,
643 adapter->fw_hal_version, adapter->ahw->pci_func,
Anirban Chakraborty2e9d7222010-06-01 11:28:51 +0000644 0, 0, 0x00000011);
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000645 if (ret)
646 goto done;
647
648 msleep(10);
649
650 ret = !adapter->diag_cnt;
651
652done:
653 qlcnic_diag_free_res(netdev, max_sds_rings);
654
655clear_it:
656 adapter->max_sds_rings = max_sds_rings;
657 clear_bit(__QLCNIC_RESETTING, &adapter->state);
658 return ret;
659}
660
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000661static void
662qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
663 u64 *data)
664{
665 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000666
Sony Chacko8dec32cc2010-08-17 00:34:24 +0000667 data[0] = qlcnic_reg_test(dev);
668 if (data[0])
669 eth_test->flags |= ETH_TEST_FL_FAILED;
670
671 data[1] = (u64) qlcnic_test_link(dev);
672 if (data[1])
673 eth_test->flags |= ETH_TEST_FL_FAILED;
674
Sony Chacko13b93ed2011-01-10 00:15:22 +0000675 if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000676 data[2] = qlcnic_irq_test(dev);
677 if (data[2])
678 eth_test->flags |= ETH_TEST_FL_FAILED;
Amit Kumar Salechacdaff182010-02-01 05:25:00 +0000679
Amit Kumar Salechacdaff182010-02-01 05:25:00 +0000680
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000681 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000682}
683
684static void
685qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
686{
amit salecha3666e0b2010-10-18 01:47:48 +0000687 struct qlcnic_adapter *adapter = netdev_priv(dev);
688 int index, i;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000689
690 switch (stringset) {
691 case ETH_SS_TEST:
692 memcpy(data, *qlcnic_gstrings_test,
693 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
694 break;
695 case ETH_SS_STATS:
696 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
697 memcpy(data + index * ETH_GSTRING_LEN,
698 qlcnic_gstrings_stats[index].stat_string,
699 ETH_GSTRING_LEN);
700 }
amit salecha3666e0b2010-10-18 01:47:48 +0000701 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
702 return;
703 for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
704 memcpy(data + index * ETH_GSTRING_LEN,
705 qlcnic_device_gstrings_stats[i],
706 ETH_GSTRING_LEN);
707 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000708 }
709}
710
amit salecha3666e0b2010-10-18 01:47:48 +0000711#define QLCNIC_FILL_ESWITCH_STATS(VAL1) \
712 (((VAL1) == QLCNIC_ESW_STATS_NOT_AVAIL) ? 0 : VAL1)
713
714static void
715qlcnic_fill_device_stats(int *index, u64 *data,
716 struct __qlcnic_esw_statistics *stats)
717{
718 int ind = *index;
719
720 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->unicast_frames);
721 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->multicast_frames);
722 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->broadcast_frames);
723 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->dropped_frames);
724 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->errors);
725 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->local_frames);
726 data[ind++] = QLCNIC_FILL_ESWITCH_STATS(stats->numbytes);
727
728 *index = ind;
729}
730
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000731static void
732qlcnic_get_ethtool_stats(struct net_device *dev,
733 struct ethtool_stats *stats, u64 * data)
734{
735 struct qlcnic_adapter *adapter = netdev_priv(dev);
amit salecha3666e0b2010-10-18 01:47:48 +0000736 struct qlcnic_esw_statistics port_stats;
737 int index, ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000738
739 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
740 char *p =
741 (char *)adapter +
742 qlcnic_gstrings_stats[index].stat_offset;
743 data[index] =
744 (qlcnic_gstrings_stats[index].sizeof_stat ==
745 sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
746 }
amit salecha3666e0b2010-10-18 01:47:48 +0000747
748 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
749 return;
750
751 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000752 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
amit salecha3666e0b2010-10-18 01:47:48 +0000753 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
754 if (ret)
755 return;
756
757 qlcnic_fill_device_stats(&index, data, &port_stats.rx);
758
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000759 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
amit salecha3666e0b2010-10-18 01:47:48 +0000760 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
761 if (ret)
762 return;
763
764 qlcnic_fill_device_stats(&index, data, &port_stats.tx);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000765}
766
stephen hemminger94469f72011-04-06 11:47:23 +0000767static int qlcnic_set_led(struct net_device *dev,
768 enum ethtool_phys_id_state state)
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000769{
770 struct qlcnic_adapter *adapter = netdev_priv(dev);
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +0000771 int max_sds_rings = adapter->max_sds_rings;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000772
stephen hemminger94469f72011-04-06 11:47:23 +0000773 switch (state) {
774 case ETHTOOL_ID_ACTIVE:
stephen hemminger94469f72011-04-06 11:47:23 +0000775 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
776 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
777 return -EIO;
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +0000778
stephen hemminger94469f72011-04-06 11:47:23 +0000779 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST)) {
780 clear_bit(__QLCNIC_RESETTING, &adapter->state);
781 return -EIO;
782 }
Sucheta Chakraborty89b42082011-04-27 14:43:44 +0000783 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +0000784 }
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000785
stephen hemminger94469f72011-04-06 11:47:23 +0000786 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0)
787 return 0;
788
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000789 dev_err(&adapter->pdev->dev,
790 "Failed to set LED blink state.\n");
stephen hemminger94469f72011-04-06 11:47:23 +0000791 break;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000792
stephen hemminger94469f72011-04-06 11:47:23 +0000793 case ETHTOOL_ID_INACTIVE:
Sucheta Chakraborty89b42082011-04-27 14:43:44 +0000794 if (adapter->nic_ops->config_led(adapter, 0, 0xf))
795 dev_err(&adapter->pdev->dev,
796 "Failed to reset LED blink state.\n");
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000797
stephen hemminger94469f72011-04-06 11:47:23 +0000798 break;
799
800 default:
801 return -EINVAL;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000802 }
803
Sucheta Chakraborty89b42082011-04-27 14:43:44 +0000804 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) {
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +0000805 qlcnic_diag_free_res(dev, max_sds_rings);
806 clear_bit(__QLCNIC_RESETTING, &adapter->state);
807 }
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +0000808
stephen hemminger94469f72011-04-06 11:47:23 +0000809 return -EIO;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000810}
811
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000812static void
813qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
814{
815 struct qlcnic_adapter *adapter = netdev_priv(dev);
816 u32 wol_cfg;
817
818 wol->supported = 0;
819 wol->wolopts = 0;
820
821 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
822 if (wol_cfg & (1UL << adapter->portnum))
823 wol->supported |= WAKE_MAGIC;
824
825 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
826 if (wol_cfg & (1UL << adapter->portnum))
827 wol->wolopts |= WAKE_MAGIC;
828}
829
830static int
831qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
832{
833 struct qlcnic_adapter *adapter = netdev_priv(dev);
834 u32 wol_cfg;
835
836 if (wol->wolopts & ~WAKE_MAGIC)
837 return -EOPNOTSUPP;
838
839 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
840 if (!(wol_cfg & (1 << adapter->portnum)))
841 return -EOPNOTSUPP;
842
843 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
844 if (wol->wolopts & WAKE_MAGIC)
845 wol_cfg |= 1UL << adapter->portnum;
846 else
847 wol_cfg &= ~(1UL << adapter->portnum);
848
849 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
850
851 return 0;
852}
853
854/*
855 * Set the coalescing parameters. Currently only normal is supported.
856 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
857 * firmware coalescing to default.
858 */
859static int qlcnic_set_intr_coalesce(struct net_device *netdev,
860 struct ethtool_coalesce *ethcoal)
861{
862 struct qlcnic_adapter *adapter = netdev_priv(netdev);
863
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000864 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000865 return -EINVAL;
866
867 /*
868 * Return Error if unsupported values or
869 * unsupported parameters are set.
870 */
871 if (ethcoal->rx_coalesce_usecs > 0xffff ||
872 ethcoal->rx_max_coalesced_frames > 0xffff ||
Anirban Chakraborty8816d002011-04-01 14:28:21 +0000873 ethcoal->tx_coalesce_usecs ||
874 ethcoal->tx_max_coalesced_frames ||
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000875 ethcoal->rx_coalesce_usecs_irq ||
876 ethcoal->rx_max_coalesced_frames_irq ||
877 ethcoal->tx_coalesce_usecs_irq ||
878 ethcoal->tx_max_coalesced_frames_irq ||
879 ethcoal->stats_block_coalesce_usecs ||
880 ethcoal->use_adaptive_rx_coalesce ||
881 ethcoal->use_adaptive_tx_coalesce ||
882 ethcoal->pkt_rate_low ||
883 ethcoal->rx_coalesce_usecs_low ||
884 ethcoal->rx_max_coalesced_frames_low ||
885 ethcoal->tx_coalesce_usecs_low ||
886 ethcoal->tx_max_coalesced_frames_low ||
887 ethcoal->pkt_rate_high ||
888 ethcoal->rx_coalesce_usecs_high ||
889 ethcoal->rx_max_coalesced_frames_high ||
890 ethcoal->tx_coalesce_usecs_high ||
891 ethcoal->tx_max_coalesced_frames_high)
892 return -EINVAL;
893
894 if (!ethcoal->rx_coalesce_usecs ||
895 !ethcoal->rx_max_coalesced_frames) {
Anirban Chakraborty8816d002011-04-01 14:28:21 +0000896 adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
897 adapter->ahw->coal.rx_time_us =
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000898 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
Anirban Chakraborty8816d002011-04-01 14:28:21 +0000899 adapter->ahw->coal.rx_packets =
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000900 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
901 } else {
Anirban Chakraborty8816d002011-04-01 14:28:21 +0000902 adapter->ahw->coal.flag = 0;
903 adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
904 adapter->ahw->coal.rx_packets =
905 ethcoal->rx_max_coalesced_frames;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000906 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000907
908 qlcnic_config_intr_coalesce(adapter);
909
910 return 0;
911}
912
913static int qlcnic_get_intr_coalesce(struct net_device *netdev,
914 struct ethtool_coalesce *ethcoal)
915{
916 struct qlcnic_adapter *adapter = netdev_priv(netdev);
917
918 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
919 return -EINVAL;
920
Anirban Chakraborty8816d002011-04-01 14:28:21 +0000921 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
922 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000923
924 return 0;
925}
926
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +0000927static u32 qlcnic_get_msglevel(struct net_device *netdev)
928{
929 struct qlcnic_adapter *adapter = netdev_priv(netdev);
930
931 return adapter->msg_enable;
932}
933
934static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
935{
936 struct qlcnic_adapter *adapter = netdev_priv(netdev);
937
938 adapter->msg_enable = msglvl;
939}
940
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000941const struct ethtool_ops qlcnic_ethtool_ops = {
942 .get_settings = qlcnic_get_settings,
943 .set_settings = qlcnic_set_settings,
944 .get_drvinfo = qlcnic_get_drvinfo,
945 .get_regs_len = qlcnic_get_regs_len,
946 .get_regs = qlcnic_get_regs,
947 .get_link = ethtool_op_get_link,
948 .get_eeprom_len = qlcnic_get_eeprom_len,
949 .get_eeprom = qlcnic_get_eeprom,
950 .get_ringparam = qlcnic_get_ringparam,
951 .set_ringparam = qlcnic_set_ringparam,
952 .get_pauseparam = qlcnic_get_pauseparam,
953 .set_pauseparam = qlcnic_set_pauseparam,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000954 .get_wol = qlcnic_get_wol,
955 .set_wol = qlcnic_set_wol,
956 .self_test = qlcnic_diag_test,
957 .get_strings = qlcnic_get_strings,
958 .get_ethtool_stats = qlcnic_get_ethtool_stats,
959 .get_sset_count = qlcnic_get_sset_count,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000960 .get_coalesce = qlcnic_get_intr_coalesce,
961 .set_coalesce = qlcnic_set_intr_coalesce,
stephen hemminger94469f72011-04-06 11:47:23 +0000962 .set_phys_id = qlcnic_set_led,
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +0000963 .set_msglevel = qlcnic_set_msglevel,
964 .get_msglevel = qlcnic_get_msglevel,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000965};