blob: 9e9e78a5c4d7e1721a6542908eada4dd04084011 [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
Jitendra Kalsaria54a89972012-04-26 10:31:30 +000081static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = {
82 "mac_tx_frames",
83 "mac_tx_bytes",
84 "mac_tx_mcast_pkts",
85 "mac_tx_bcast_pkts",
86 "mac_tx_pause_cnt",
87 "mac_tx_ctrl_pkt",
88 "mac_tx_lt_64b_pkts",
89 "mac_tx_lt_127b_pkts",
90 "mac_tx_lt_255b_pkts",
91 "mac_tx_lt_511b_pkts",
92 "mac_tx_lt_1023b_pkts",
93 "mac_tx_lt_1518b_pkts",
94 "mac_tx_gt_1518b_pkts",
95 "mac_rx_frames",
96 "mac_rx_bytes",
97 "mac_rx_mcast_pkts",
98 "mac_rx_bcast_pkts",
99 "mac_rx_pause_cnt",
100 "mac_rx_ctrl_pkt",
101 "mac_rx_lt_64b_pkts",
102 "mac_rx_lt_127b_pkts",
103 "mac_rx_lt_255b_pkts",
104 "mac_rx_lt_511b_pkts",
105 "mac_rx_lt_1023b_pkts",
106 "mac_rx_lt_1518b_pkts",
107 "mac_rx_gt_1518b_pkts",
108 "mac_rx_length_error",
109 "mac_rx_length_small",
110 "mac_rx_length_large",
111 "mac_rx_jabber",
112 "mac_rx_dropped",
113 "mac_rx_crc_error",
114 "mac_align_error",
115};
116
117#define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats)
118#define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings)
amit salecha3666e0b2010-10-18 01:47:48 +0000119#define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats)
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000120#define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000121
122static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
123 "Register_Test_on_offline",
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000124 "Link_Test_on_offline",
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000125 "Interrupt_Test_offline",
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000126 "Internal_Loopback_offline",
127 "External_Loopback_offline"
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000128};
129
130#define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test)
131
132#define QLCNIC_RING_REGS_COUNT 20
133#define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32))
134#define QLCNIC_MAX_EEPROM_LEN 1024
135
136static const u32 diag_registers[] = {
137 CRB_CMDPEG_STATE,
138 CRB_RCVPEG_STATE,
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000139 CRB_XG_STATE_P3P,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000140 CRB_FW_CAPABILITIES_1,
141 ISR_INT_STATE_REG,
Amit Kumar Salecha31018e02010-08-25 04:03:05 +0000142 QLCNIC_CRB_DRV_ACTIVE,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000143 QLCNIC_CRB_DEV_STATE,
144 QLCNIC_CRB_DRV_STATE,
145 QLCNIC_CRB_DRV_SCRATCH,
146 QLCNIC_CRB_DEV_PARTITION_INFO,
147 QLCNIC_CRB_DRV_IDC_VER,
148 QLCNIC_PEG_ALIVE_COUNTER,
149 QLCNIC_PEG_HALT_STATUS1,
150 QLCNIC_PEG_HALT_STATUS2,
151 QLCNIC_CRB_PEG_NET_0+0x3c,
152 QLCNIC_CRB_PEG_NET_1+0x3c,
153 QLCNIC_CRB_PEG_NET_2+0x3c,
154 QLCNIC_CRB_PEG_NET_4+0x3c,
155 -1
156};
157
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000158#define QLCNIC_MGMT_API_VERSION 2
159#define QLCNIC_DEV_INFO_SIZE 1
160#define QLCNIC_ETHTOOL_REGS_VER 2
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000161static int qlcnic_get_regs_len(struct net_device *dev)
162{
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000163 return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
164 QLCNIC_DEV_INFO_SIZE + 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000165}
166
167static int qlcnic_get_eeprom_len(struct net_device *dev)
168{
169 return QLCNIC_FLASH_TOTAL_SIZE;
170}
171
172static void
173qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
174{
175 struct qlcnic_adapter *adapter = netdev_priv(dev);
176 u32 fw_major, fw_minor, fw_build;
177
178 fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
179 fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
180 fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB);
Rick Jones68aad782011-11-07 13:29:27 +0000181 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
182 "%d.%d.%d", fw_major, fw_minor, fw_build);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000183
Rick Jones68aad782011-11-07 13:29:27 +0000184 strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
185 sizeof(drvinfo->bus_info));
186 strlcpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
187 strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
188 sizeof(drvinfo->version));
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000189}
190
191static int
192qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
193{
194 struct qlcnic_adapter *adapter = netdev_priv(dev);
195 int check_sfp_module = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000196
197 /* read which mode */
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000198 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000199 ecmd->supported = (SUPPORTED_10baseT_Half |
200 SUPPORTED_10baseT_Full |
201 SUPPORTED_100baseT_Half |
202 SUPPORTED_100baseT_Full |
203 SUPPORTED_1000baseT_Half |
204 SUPPORTED_1000baseT_Full);
205
206 ecmd->advertising = (ADVERTISED_100baseT_Half |
207 ADVERTISED_100baseT_Full |
208 ADVERTISED_1000baseT_Half |
209 ADVERTISED_1000baseT_Full);
210
David Decotigny70739492011-04-27 18:32:40 +0000211 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000212 ecmd->duplex = adapter->link_duplex;
213 ecmd->autoneg = adapter->link_autoneg;
214
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000215 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000216 u32 val;
217
218 val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR);
219 if (val == QLCNIC_PORT_MODE_802_3_AP) {
220 ecmd->supported = SUPPORTED_1000baseT_Full;
221 ecmd->advertising = ADVERTISED_1000baseT_Full;
222 } else {
223 ecmd->supported = SUPPORTED_10000baseT_Full;
224 ecmd->advertising = ADVERTISED_10000baseT_Full;
225 }
226
227 if (netif_running(dev) && adapter->has_link_events) {
David Decotigny70739492011-04-27 18:32:40 +0000228 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000229 ecmd->autoneg = adapter->link_autoneg;
230 ecmd->duplex = adapter->link_duplex;
231 goto skip;
232 }
233
Sony Chacko476a4b62012-02-03 13:45:42 +0000234 ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
235 ecmd->duplex = DUPLEX_UNKNOWN;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000236 ecmd->autoneg = AUTONEG_DISABLE;
237 } else
238 return -EIO;
239
240skip:
241 ecmd->phy_address = adapter->physical_port;
242 ecmd->transceiver = XCVR_EXTERNAL;
243
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000244 switch (adapter->ahw->board_type) {
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000245 case QLCNIC_BRDTYPE_P3P_REF_QG:
246 case QLCNIC_BRDTYPE_P3P_4_GB:
247 case QLCNIC_BRDTYPE_P3P_4_GB_MM:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000248
249 ecmd->supported |= SUPPORTED_Autoneg;
250 ecmd->advertising |= ADVERTISED_Autoneg;
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000251 case QLCNIC_BRDTYPE_P3P_10G_CX4:
252 case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
253 case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000254 ecmd->supported |= SUPPORTED_TP;
255 ecmd->advertising |= ADVERTISED_TP;
256 ecmd->port = PORT_TP;
257 ecmd->autoneg = adapter->link_autoneg;
258 break;
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000259 case QLCNIC_BRDTYPE_P3P_IMEZ:
260 case QLCNIC_BRDTYPE_P3P_XG_LOM:
261 case QLCNIC_BRDTYPE_P3P_HMEZ:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000262 ecmd->supported |= SUPPORTED_MII;
263 ecmd->advertising |= ADVERTISED_MII;
264 ecmd->port = PORT_MII;
265 ecmd->autoneg = AUTONEG_DISABLE;
266 break;
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000267 case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
268 case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
269 case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000270 ecmd->advertising |= ADVERTISED_TP;
271 ecmd->supported |= SUPPORTED_TP;
272 check_sfp_module = netif_running(dev) &&
273 adapter->has_link_events;
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000274 case QLCNIC_BRDTYPE_P3P_10G_XFP:
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000275 ecmd->supported |= SUPPORTED_FIBRE;
276 ecmd->advertising |= ADVERTISED_FIBRE;
277 ecmd->port = PORT_FIBRE;
278 ecmd->autoneg = AUTONEG_DISABLE;
279 break;
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000280 case QLCNIC_BRDTYPE_P3P_10G_TP:
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000281 if (adapter->ahw->port_type == QLCNIC_XGBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000282 ecmd->autoneg = AUTONEG_DISABLE;
283 ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
284 ecmd->advertising |=
285 (ADVERTISED_FIBRE | ADVERTISED_TP);
286 ecmd->port = PORT_FIBRE;
287 check_sfp_module = netif_running(dev) &&
288 adapter->has_link_events;
289 } else {
290 ecmd->autoneg = AUTONEG_ENABLE;
291 ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
292 ecmd->advertising |=
293 (ADVERTISED_TP | ADVERTISED_Autoneg);
294 ecmd->port = PORT_TP;
295 }
296 break;
297 default:
298 dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000299 adapter->ahw->board_type);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000300 return -EIO;
301 }
302
303 if (check_sfp_module) {
304 switch (adapter->module_type) {
305 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
306 case LINKEVENT_MODULE_OPTICAL_SRLR:
307 case LINKEVENT_MODULE_OPTICAL_LRM:
308 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
309 ecmd->port = PORT_FIBRE;
310 break;
311 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
312 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
313 case LINKEVENT_MODULE_TWINAX:
314 ecmd->port = PORT_TP;
315 break;
316 default:
317 ecmd->port = PORT_OTHER;
318 }
319 }
320
321 return 0;
322}
323
324static int
325qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
326{
Sony Chacko7e610ca2011-04-28 11:48:19 +0000327 u32 config = 0;
328 u32 ret = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000329 struct qlcnic_adapter *adapter = netdev_priv(dev);
Sony Chacko7e610ca2011-04-28 11:48:19 +0000330
331 if (adapter->ahw->port_type != QLCNIC_GBE)
332 return -EOPNOTSUPP;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000333
334 /* read which mode */
Sony Chacko7e610ca2011-04-28 11:48:19 +0000335 if (ecmd->duplex)
336 config |= 0x1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000337
Sony Chacko7e610ca2011-04-28 11:48:19 +0000338 if (ecmd->autoneg)
339 config |= 0x2;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000340
Sony Chacko7e610ca2011-04-28 11:48:19 +0000341 switch (ethtool_cmd_speed(ecmd)) {
342 case SPEED_10:
343 config |= (0 << 8);
344 break;
345 case SPEED_100:
346 config |= (1 << 8);
347 break;
348 case SPEED_1000:
349 config |= (10 << 8);
350 break;
351 default:
352 return -EIO;
353 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000354
Sony Chacko7e610ca2011-04-28 11:48:19 +0000355 ret = qlcnic_fw_cmd_set_port(adapter, config);
356
357 if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000358 return -EOPNOTSUPP;
Sony Chacko7e610ca2011-04-28 11:48:19 +0000359 else if (ret)
360 return -EIO;
361
362 adapter->link_speed = ethtool_cmd_speed(ecmd);
363 adapter->link_duplex = ecmd->duplex;
364 adapter->link_autoneg = ecmd->autoneg;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000365
366 if (!netif_running(dev))
367 return 0;
368
369 dev->netdev_ops->ndo_stop(dev);
370 return dev->netdev_ops->ndo_open(dev);
371}
372
373static void
374qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
375{
376 struct qlcnic_adapter *adapter = netdev_priv(dev);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000377 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000378 struct qlcnic_host_sds_ring *sds_ring;
379 u32 *regs_buff = p;
Amit Kumar Salechac265eb62010-10-04 04:20:11 +0000380 int ring, i = 0, j = 0;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000381
382 memset(p, 0, qlcnic_get_regs_len(dev));
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000383 regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000384 (adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000385
Rajesh Borundia2cffcdb2010-08-31 17:17:45 +0000386 regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
387 regs_buff[1] = QLCNIC_MGMT_API_VERSION;
388
Amit Kumar Salechac265eb62010-10-04 04:20:11 +0000389 for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
390 regs_buff[i] = QLCRD32(adapter, diag_registers[j]);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000391
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +0000392 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
Amit Kumar Salechace668442010-02-01 05:24:57 +0000393 return;
394
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000395 regs_buff[i++] = 0xFFEFCDAB; /* Marker btw regs and ring count*/
396
397 regs_buff[i++] = 1; /* No. of tx ring */
398 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
399 regs_buff[i++] = readl(adapter->tx_ring->crb_cmd_producer);
400
401 regs_buff[i++] = 2; /* No. of rx ring */
402 regs_buff[i++] = readl(recv_ctx->rds_rings[0].crb_rcv_producer);
403 regs_buff[i++] = readl(recv_ctx->rds_rings[1].crb_rcv_producer);
404
405 regs_buff[i++] = adapter->max_sds_rings;
406
407 for (ring = 0; ring < adapter->max_sds_rings; ring++) {
408 sds_ring = &(recv_ctx->sds_rings[ring]);
409 regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
410 }
411}
412
413static u32 qlcnic_test_link(struct net_device *dev)
414{
415 struct qlcnic_adapter *adapter = netdev_priv(dev);
416 u32 val;
417
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000418 val = QLCRD32(adapter, CRB_XG_STATE_P3P);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000419 val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
Sritej Velagaff1b1bf82010-10-07 23:46:10 +0000420 return (val == XG_LINK_UP_P3P) ? 0 : 1;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000421}
422
423static int
424qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
425 u8 *bytes)
426{
427 struct qlcnic_adapter *adapter = netdev_priv(dev);
428 int offset;
429 int ret;
430
431 if (eeprom->len == 0)
432 return -EINVAL;
433
434 eeprom->magic = (adapter->pdev)->vendor |
435 ((adapter->pdev)->device << 16);
436 offset = eeprom->offset;
437
438 ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
439 eeprom->len);
440 if (ret < 0)
441 return ret;
442
443 return 0;
444}
445
446static void
447qlcnic_get_ringparam(struct net_device *dev,
448 struct ethtool_ringparam *ring)
449{
450 struct qlcnic_adapter *adapter = netdev_priv(dev);
451
452 ring->rx_pending = adapter->num_rxd;
453 ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000454 ring->tx_pending = adapter->num_txd;
455
Sony Chacko90d19002010-10-26 17:53:08 +0000456 ring->rx_max_pending = adapter->max_rxd;
457 ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000458 ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000459}
460
461static u32
462qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
463{
464 u32 num_desc;
465 num_desc = max(val, min);
466 num_desc = min(num_desc, max);
467 num_desc = roundup_pow_of_two(num_desc);
468
469 if (val != num_desc) {
470 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
471 qlcnic_driver_name, r_name, num_desc, val);
472 }
473
474 return num_desc;
475}
476
477static int
478qlcnic_set_ringparam(struct net_device *dev,
479 struct ethtool_ringparam *ring)
480{
481 struct qlcnic_adapter *adapter = netdev_priv(dev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000482 u16 num_rxd, num_jumbo_rxd, num_txd;
483
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000484 if (ring->rx_mini_pending)
485 return -EOPNOTSUPP;
486
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000487 num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
Sony Chacko90d19002010-10-26 17:53:08 +0000488 MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000489
490 num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
Sony Chacko90d19002010-10-26 17:53:08 +0000491 MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
492 "rx jumbo");
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000493
494 num_txd = qlcnic_validate_ringparam(ring->tx_pending,
495 MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
496
497 if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
498 num_jumbo_rxd == adapter->num_jumbo_rxd)
499 return 0;
500
501 adapter->num_rxd = num_rxd;
502 adapter->num_jumbo_rxd = num_jumbo_rxd;
503 adapter->num_txd = num_txd;
504
505 return qlcnic_reset_context(adapter);
506}
507
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +0000508static void qlcnic_get_channels(struct net_device *dev,
509 struct ethtool_channels *channel)
510{
511 struct qlcnic_adapter *adapter = netdev_priv(dev);
512
513 channel->max_rx = rounddown_pow_of_two(min_t(int,
514 adapter->max_rx_ques, num_online_cpus()));
515 channel->max_tx = adapter->max_tx_ques;
516
517 channel->rx_count = adapter->max_sds_rings;
518 channel->tx_count = adapter->max_tx_ques;
519}
520
521static int qlcnic_set_channels(struct net_device *dev,
522 struct ethtool_channels *channel)
523{
524 struct qlcnic_adapter *adapter = netdev_priv(dev);
525 int err;
526
527 if (channel->other_count || channel->combined_count ||
528 channel->tx_count != channel->max_tx)
529 return -EINVAL;
530
531 err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count);
532 if (err)
533 return err;
534
535 err = qlcnic_set_max_rss(adapter, channel->rx_count);
536 netdev_info(dev, "allocated 0x%x sds rings\n",
537 adapter->max_sds_rings);
538 return err;
539}
540
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000541static void
542qlcnic_get_pauseparam(struct net_device *netdev,
543 struct ethtool_pauseparam *pause)
544{
545 struct qlcnic_adapter *adapter = netdev_priv(netdev);
546 int port = adapter->physical_port;
547 __u32 val;
548
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000549 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000550 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
551 return;
552 /* get flow control settings */
553 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
554 pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
555 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
556 switch (port) {
557 case 0:
558 pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
559 break;
560 case 1:
561 pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
562 break;
563 case 2:
564 pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
565 break;
566 case 3:
567 default:
568 pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
569 break;
570 }
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000571 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000572 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
573 return;
574 pause->rx_pause = 1;
575 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
576 if (port == 0)
577 pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
578 else
579 pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
580 } else {
581 dev_err(&netdev->dev, "Unknown board type: %x\n",
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000582 adapter->ahw->port_type);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000583 }
584}
585
586static int
587qlcnic_set_pauseparam(struct net_device *netdev,
588 struct ethtool_pauseparam *pause)
589{
590 struct qlcnic_adapter *adapter = netdev_priv(netdev);
591 int port = adapter->physical_port;
592 __u32 val;
593
594 /* read mode */
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000595 if (adapter->ahw->port_type == QLCNIC_GBE) {
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000596 if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
597 return -EIO;
598 /* set flow control */
599 val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port));
600
601 if (pause->rx_pause)
602 qlcnic_gb_rx_flowctl(val);
603 else
604 qlcnic_gb_unset_rx_flowctl(val);
605
606 QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
607 val);
608 /* set autoneg */
609 val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL);
610 switch (port) {
611 case 0:
612 if (pause->tx_pause)
613 qlcnic_gb_unset_gb0_mask(val);
614 else
615 qlcnic_gb_set_gb0_mask(val);
616 break;
617 case 1:
618 if (pause->tx_pause)
619 qlcnic_gb_unset_gb1_mask(val);
620 else
621 qlcnic_gb_set_gb1_mask(val);
622 break;
623 case 2:
624 if (pause->tx_pause)
625 qlcnic_gb_unset_gb2_mask(val);
626 else
627 qlcnic_gb_set_gb2_mask(val);
628 break;
629 case 3:
630 default:
631 if (pause->tx_pause)
632 qlcnic_gb_unset_gb3_mask(val);
633 else
634 qlcnic_gb_set_gb3_mask(val);
635 break;
636 }
637 QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000638 } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
Rajesh Borundia6d181682010-07-13 20:33:31 +0000639 if (!pause->rx_pause || pause->autoneg)
640 return -EOPNOTSUPP;
641
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000642 if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
643 return -EIO;
Rajesh Borundia6d181682010-07-13 20:33:31 +0000644
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000645 val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
646 if (port == 0) {
647 if (pause->tx_pause)
648 qlcnic_xg_unset_xg0_mask(val);
649 else
650 qlcnic_xg_set_xg0_mask(val);
651 } else {
652 if (pause->tx_pause)
653 qlcnic_xg_unset_xg1_mask(val);
654 else
655 qlcnic_xg_set_xg1_mask(val);
656 }
657 QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
658 } else {
659 dev_err(&netdev->dev, "Unknown board type: %x\n",
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +0000660 adapter->ahw->port_type);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000661 }
662 return 0;
663}
664
665static int qlcnic_reg_test(struct net_device *dev)
666{
667 struct qlcnic_adapter *adapter = netdev_priv(dev);
Amit Kumar Salechadeffab02010-05-13 03:07:43 +0000668 u32 data_read;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000669
670 data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0));
671 if ((data_read & 0xffff) != adapter->pdev->vendor)
672 return 1;
673
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000674 return 0;
675}
676
677static int qlcnic_get_sset_count(struct net_device *dev, int sset)
678{
amit salecha3666e0b2010-10-18 01:47:48 +0000679 struct qlcnic_adapter *adapter = netdev_priv(dev);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000680 switch (sset) {
681 case ETH_SS_TEST:
682 return QLCNIC_TEST_LEN;
683 case ETH_SS_STATS:
amit salecha3666e0b2010-10-18 01:47:48 +0000684 if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000685 return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN;
686 return QLCNIC_TOTAL_STATS_LEN;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000687 default:
688 return -EOPNOTSUPP;
689 }
690}
691
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000692static int qlcnic_irq_test(struct net_device *netdev)
693{
694 struct qlcnic_adapter *adapter = netdev_priv(netdev);
695 int max_sds_rings = adapter->max_sds_rings;
696 int ret;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000697 struct qlcnic_cmd_args cmd;
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000698
699 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
700 return -EIO;
701
702 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
703 if (ret)
704 goto clear_it;
705
706 adapter->diag_cnt = 0;
Anirban Chakraborty7777de92011-09-13 08:06:18 +0000707 memset(&cmd, 0, sizeof(cmd));
708 cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
709 cmd.req.arg1 = adapter->ahw->pci_func;
710 qlcnic_issue_cmd(adapter, &cmd);
711 ret = cmd.rsp.cmd;
712
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000713 if (ret)
714 goto done;
715
716 msleep(10);
717
718 ret = !adapter->diag_cnt;
719
720done:
721 qlcnic_diag_free_res(netdev, max_sds_rings);
722
723clear_it:
724 adapter->max_sds_rings = max_sds_rings;
725 clear_bit(__QLCNIC_RESETTING, &adapter->state);
726 return ret;
727}
728
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000729#define QLCNIC_ILB_PKT_SIZE 64
730#define QLCNIC_NUM_ILB_PKT 16
731#define QLCNIC_ILB_MAX_RCV_LOOP 10
732
733static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
734{
735 unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
736
737 memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
738
739 memcpy(data, mac, ETH_ALEN);
740 memcpy(data + ETH_ALEN, mac, ETH_ALEN);
741
742 memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
743}
744
745int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
746{
747 unsigned char buff[QLCNIC_ILB_PKT_SIZE];
748 qlcnic_create_loopback_buff(buff, mac);
749 return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
750}
751
Manish chopradf3cfbe2011-08-29 12:50:27 +0000752static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000753{
754 struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
755 struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
756 struct sk_buff *skb;
757 int i, loop, cnt = 0;
758
759 for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
Pradeep A. Dalvidae2e9f2012-02-06 11:16:13 +0000760 skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000761 qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
762 skb_put(skb, QLCNIC_ILB_PKT_SIZE);
763
764 adapter->diag_cnt = 0;
765 qlcnic_xmit_frame(skb, adapter->netdev);
766
767 loop = 0;
768 do {
769 msleep(1);
770 qlcnic_process_rcv_ring_diag(sds_ring);
771 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
772 break;
773 } while (!adapter->diag_cnt);
774
775 dev_kfree_skb_any(skb);
776
777 if (!adapter->diag_cnt)
Manish chopradf3cfbe2011-08-29 12:50:27 +0000778 QLCDB(adapter, DRV,
779 "LB Test: packet #%d was not received\n", i + 1);
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000780 else
781 cnt++;
782 }
783 if (cnt != i) {
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000784 dev_warn(&adapter->pdev->dev, "LB Test failed\n");
Manish chopradf3cfbe2011-08-29 12:50:27 +0000785 if (mode != QLCNIC_ILB_MODE) {
786 dev_warn(&adapter->pdev->dev,
787 "WARNING: Please make sure external"
788 "loopback connector is plugged in\n");
789 }
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000790 return -1;
791 }
792 return 0;
793}
794
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000795static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000796{
797 struct qlcnic_adapter *adapter = netdev_priv(netdev);
798 int max_sds_rings = adapter->max_sds_rings;
799 struct qlcnic_host_sds_ring *sds_ring;
800 int loop = 0;
801 int ret;
802
Amit Kumar Salechafef0c062011-07-14 03:16:54 +0000803 if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
804 netdev_info(netdev, "Firmware is not loopback test capable\n");
805 return -EOPNOTSUPP;
806 }
807
Manish chopradf3cfbe2011-08-29 12:50:27 +0000808 QLCDB(adapter, DRV, "%s loopback test in progress\n",
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000809 mode == QLCNIC_ILB_MODE ? "internal" : "external");
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000810 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
811 netdev_warn(netdev, "Loopback test not supported for non "
812 "privilege function\n");
813 return 0;
814 }
815
816 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
Amit Kumar Salechafef0c062011-07-14 03:16:54 +0000817 return -EBUSY;
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000818
819 ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
820 if (ret)
821 goto clear_it;
822
823 sds_ring = &adapter->recv_ctx->sds_rings[0];
824
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000825 ret = qlcnic_set_lb_mode(adapter, mode);
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000826 if (ret)
827 goto free_res;
828
Amit Kumar Salechafef0c062011-07-14 03:16:54 +0000829 adapter->diag_cnt = 0;
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000830 do {
831 msleep(500);
832 qlcnic_process_rcv_ring_diag(sds_ring);
Amit Kumar Salechafef0c062011-07-14 03:16:54 +0000833 if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
834 netdev_info(netdev, "firmware didnt respond to loopback"
835 " configure request\n");
836 ret = -QLCNIC_FW_NOT_RESPOND;
837 goto free_res;
838 } else if (adapter->diag_cnt) {
839 ret = adapter->diag_cnt;
840 goto free_res;
841 }
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000842 } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
843
Manish chopradf3cfbe2011-08-29 12:50:27 +0000844 ret = qlcnic_do_lb_test(adapter, mode);
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000845
846 qlcnic_clear_lb_mode(adapter);
847
848 free_res:
849 qlcnic_diag_free_res(netdev, max_sds_rings);
850
851 clear_it:
852 adapter->max_sds_rings = max_sds_rings;
853 clear_bit(__QLCNIC_RESETTING, &adapter->state);
854 return ret;
855}
856
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000857static void
858qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
859 u64 *data)
860{
861 memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
Sucheta Chakraborty897d3592010-02-01 05:24:58 +0000862
Sony Chacko8dec32cc2010-08-17 00:34:24 +0000863 data[0] = qlcnic_reg_test(dev);
864 if (data[0])
865 eth_test->flags |= ETH_TEST_FL_FAILED;
866
867 data[1] = (u64) qlcnic_test_link(dev);
868 if (data[1])
869 eth_test->flags |= ETH_TEST_FL_FAILED;
870
Sony Chacko13b93ed2011-01-10 00:15:22 +0000871 if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000872 data[2] = qlcnic_irq_test(dev);
873 if (data[2])
874 eth_test->flags |= ETH_TEST_FL_FAILED;
Amit Kumar Salechacdaff182010-02-01 05:25:00 +0000875
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000876 data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
Sucheta Chakraborty22c8c932011-06-22 02:52:23 +0000877 if (data[3])
878 eth_test->flags |= ETH_TEST_FL_FAILED;
Amit Kumar Salechae1428d22011-06-29 20:00:50 +0000879 if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
880 data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
881 if (data[4])
882 eth_test->flags |= ETH_TEST_FL_FAILED;
883 eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
884 }
Amit Kumar Salecha7eb98552010-02-01 05:24:59 +0000885 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000886}
887
888static void
889qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
890{
amit salecha3666e0b2010-10-18 01:47:48 +0000891 struct qlcnic_adapter *adapter = netdev_priv(dev);
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000892 int index, i, j;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000893
894 switch (stringset) {
895 case ETH_SS_TEST:
896 memcpy(data, *qlcnic_gstrings_test,
897 QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
898 break;
899 case ETH_SS_STATS:
900 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
901 memcpy(data + index * ETH_GSTRING_LEN,
902 qlcnic_gstrings_stats[index].stat_string,
903 ETH_GSTRING_LEN);
904 }
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000905 for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) {
906 memcpy(data + index * ETH_GSTRING_LEN,
907 qlcnic_mac_stats_strings[j],
908 ETH_GSTRING_LEN);
909 }
amit salecha3666e0b2010-10-18 01:47:48 +0000910 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
911 return;
912 for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) {
913 memcpy(data + index * ETH_GSTRING_LEN,
914 qlcnic_device_gstrings_stats[i],
915 ETH_GSTRING_LEN);
916 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000917 }
918}
919
amit salecha3666e0b2010-10-18 01:47:48 +0000920static void
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000921qlcnic_fill_stats(int *index, u64 *data, void *stats, int type)
amit salecha3666e0b2010-10-18 01:47:48 +0000922{
923 int ind = *index;
924
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000925 if (type == QLCNIC_MAC_STATS) {
926 struct qlcnic_mac_statistics *mac_stats =
927 (struct qlcnic_mac_statistics *)stats;
928 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
929 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
930 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
931 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
932 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
933 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
934 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
935 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
936 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
937 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
938 data[ind++] =
939 QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
940 data[ind++] =
941 QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
942 data[ind++] =
943 QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
944 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
945 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
946 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
947 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
948 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
949 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
950 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
951 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
952 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
953 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
954 data[ind++] =
955 QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
956 data[ind++] =
957 QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
958 data[ind++] =
959 QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
960 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
961 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
962 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
963 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
964 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
965 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
966 data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
967 } else if (type == QLCNIC_ESW_STATS) {
968 struct __qlcnic_esw_statistics *esw_stats =
969 (struct __qlcnic_esw_statistics *)stats;
970 data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
971 data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
972 data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
973 data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
974 data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors);
975 data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames);
976 data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes);
977 }
amit salecha3666e0b2010-10-18 01:47:48 +0000978
979 *index = ind;
980}
981
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000982static void
983qlcnic_get_ethtool_stats(struct net_device *dev,
984 struct ethtool_stats *stats, u64 * data)
985{
986 struct qlcnic_adapter *adapter = netdev_priv(dev);
amit salecha3666e0b2010-10-18 01:47:48 +0000987 struct qlcnic_esw_statistics port_stats;
Jitendra Kalsaria54a89972012-04-26 10:31:30 +0000988 struct qlcnic_mac_statistics mac_stats;
amit salecha3666e0b2010-10-18 01:47:48 +0000989 int index, ret;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +0000990
991 for (index = 0; index < QLCNIC_STATS_LEN; index++) {
992 char *p =
993 (char *)adapter +
994 qlcnic_gstrings_stats[index].stat_offset;
995 data[index] =
996 (qlcnic_gstrings_stats[index].sizeof_stat ==
997 sizeof(u64)) ? *(u64 *)p:(*(u32 *)p);
998 }
amit salecha3666e0b2010-10-18 01:47:48 +0000999
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001000 /* Retrieve MAC statistics from firmware */
1001 memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
1002 qlcnic_get_mac_stats(adapter, &mac_stats);
1003 qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS);
1004
amit salecha3666e0b2010-10-18 01:47:48 +00001005 if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1006 return;
1007
1008 memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001009 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
amit salecha3666e0b2010-10-18 01:47:48 +00001010 QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
1011 if (ret)
1012 return;
1013
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001014 qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS);
amit salecha3666e0b2010-10-18 01:47:48 +00001015
Anirban Chakrabortyb1fc6d32011-04-01 14:28:05 +00001016 ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
amit salecha3666e0b2010-10-18 01:47:48 +00001017 QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
1018 if (ret)
1019 return;
1020
Jitendra Kalsaria54a89972012-04-26 10:31:30 +00001021 qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS);
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001022}
1023
stephen hemminger94469f72011-04-06 11:47:23 +00001024static int qlcnic_set_led(struct net_device *dev,
1025 enum ethtool_phys_id_state state)
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001026{
1027 struct qlcnic_adapter *adapter = netdev_priv(dev);
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +00001028 int max_sds_rings = adapter->max_sds_rings;
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001029 int err = -EIO, active = 1;
1030
1031 if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
1032 netdev_warn(dev, "LED test not supported for non "
1033 "privilege function\n");
1034 return -EOPNOTSUPP;
1035 }
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001036
stephen hemminger94469f72011-04-06 11:47:23 +00001037 switch (state) {
1038 case ETHTOOL_ID_ACTIVE:
Sucheta Chakraborty728a98b2011-08-29 12:50:30 +00001039 if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1040 return -EBUSY;
1041
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001042 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1043 break;
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +00001044
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001045 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1046 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
1047 break;
Sucheta Chakraborty89b42082011-04-27 14:43:44 +00001048 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +00001049 }
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001050
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001051 if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
1052 err = 0;
1053 break;
1054 }
stephen hemminger94469f72011-04-06 11:47:23 +00001055
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001056 dev_err(&adapter->pdev->dev,
1057 "Failed to set LED blink state.\n");
stephen hemminger94469f72011-04-06 11:47:23 +00001058 break;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001059
stephen hemminger94469f72011-04-06 11:47:23 +00001060 case ETHTOOL_ID_INACTIVE:
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001061 active = 0;
1062
1063 if (test_bit(__QLCNIC_RESETTING, &adapter->state))
1064 break;
1065
1066 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
1067 if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
1068 break;
1069 set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
1070 }
1071
Sucheta Chakraborty89b42082011-04-27 14:43:44 +00001072 if (adapter->nic_ops->config_led(adapter, 0, 0xf))
1073 dev_err(&adapter->pdev->dev,
1074 "Failed to reset LED blink state.\n");
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001075
stephen hemminger94469f72011-04-06 11:47:23 +00001076 break;
1077
1078 default:
1079 return -EINVAL;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001080 }
1081
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001082 if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +00001083 qlcnic_diag_free_res(dev, max_sds_rings);
Sucheta Chakrabortyc75822a2010-12-16 22:59:00 +00001084
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001085 if (!active || err)
1086 clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
Sucheta Chakraborty728a98b2011-08-29 12:50:30 +00001087
Sucheta Chakraborty10ee0fa2011-10-28 12:57:15 +00001088 return err;
Sucheta Chakraborty897d3592010-02-01 05:24:58 +00001089}
1090
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001091static void
1092qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1093{
1094 struct qlcnic_adapter *adapter = netdev_priv(dev);
1095 u32 wol_cfg;
1096
1097 wol->supported = 0;
1098 wol->wolopts = 0;
1099
1100 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1101 if (wol_cfg & (1UL << adapter->portnum))
1102 wol->supported |= WAKE_MAGIC;
1103
1104 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1105 if (wol_cfg & (1UL << adapter->portnum))
1106 wol->wolopts |= WAKE_MAGIC;
1107}
1108
1109static int
1110qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1111{
1112 struct qlcnic_adapter *adapter = netdev_priv(dev);
1113 u32 wol_cfg;
1114
1115 if (wol->wolopts & ~WAKE_MAGIC)
1116 return -EOPNOTSUPP;
1117
1118 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV);
1119 if (!(wol_cfg & (1 << adapter->portnum)))
1120 return -EOPNOTSUPP;
1121
1122 wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG);
1123 if (wol->wolopts & WAKE_MAGIC)
1124 wol_cfg |= 1UL << adapter->portnum;
1125 else
1126 wol_cfg &= ~(1UL << adapter->portnum);
1127
1128 QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1129
1130 return 0;
1131}
1132
1133/*
1134 * Set the coalescing parameters. Currently only normal is supported.
1135 * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1136 * firmware coalescing to default.
1137 */
1138static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1139 struct ethtool_coalesce *ethcoal)
1140{
1141 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1142
Amit Kumar Salecha8a15ad12010-06-22 03:19:01 +00001143 if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001144 return -EINVAL;
1145
1146 /*
1147 * Return Error if unsupported values or
1148 * unsupported parameters are set.
1149 */
1150 if (ethcoal->rx_coalesce_usecs > 0xffff ||
1151 ethcoal->rx_max_coalesced_frames > 0xffff ||
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001152 ethcoal->tx_coalesce_usecs ||
1153 ethcoal->tx_max_coalesced_frames ||
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001154 ethcoal->rx_coalesce_usecs_irq ||
1155 ethcoal->rx_max_coalesced_frames_irq ||
1156 ethcoal->tx_coalesce_usecs_irq ||
1157 ethcoal->tx_max_coalesced_frames_irq ||
1158 ethcoal->stats_block_coalesce_usecs ||
1159 ethcoal->use_adaptive_rx_coalesce ||
1160 ethcoal->use_adaptive_tx_coalesce ||
1161 ethcoal->pkt_rate_low ||
1162 ethcoal->rx_coalesce_usecs_low ||
1163 ethcoal->rx_max_coalesced_frames_low ||
1164 ethcoal->tx_coalesce_usecs_low ||
1165 ethcoal->tx_max_coalesced_frames_low ||
1166 ethcoal->pkt_rate_high ||
1167 ethcoal->rx_coalesce_usecs_high ||
1168 ethcoal->rx_max_coalesced_frames_high ||
1169 ethcoal->tx_coalesce_usecs_high ||
1170 ethcoal->tx_max_coalesced_frames_high)
1171 return -EINVAL;
1172
1173 if (!ethcoal->rx_coalesce_usecs ||
1174 !ethcoal->rx_max_coalesced_frames) {
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001175 adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT;
1176 adapter->ahw->coal.rx_time_us =
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001177 QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US;
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001178 adapter->ahw->coal.rx_packets =
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001179 QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS;
1180 } else {
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001181 adapter->ahw->coal.flag = 0;
1182 adapter->ahw->coal.rx_time_us = ethcoal->rx_coalesce_usecs;
1183 adapter->ahw->coal.rx_packets =
1184 ethcoal->rx_max_coalesced_frames;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001185 }
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001186
1187 qlcnic_config_intr_coalesce(adapter);
1188
1189 return 0;
1190}
1191
1192static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1193 struct ethtool_coalesce *ethcoal)
1194{
1195 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1196
1197 if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1198 return -EINVAL;
1199
Anirban Chakraborty8816d002011-04-01 14:28:21 +00001200 ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1201 ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001202
1203 return 0;
1204}
1205
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00001206static u32 qlcnic_get_msglevel(struct net_device *netdev)
1207{
1208 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1209
1210 return adapter->msg_enable;
1211}
1212
1213static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1214{
1215 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1216
1217 adapter->msg_enable = msglvl;
1218}
1219
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001220static int
1221qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1222{
1223 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1224 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1225
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001226 if (!fw_dump->tmpl_hdr) {
1227 netdev_err(adapter->netdev, "FW Dump not supported\n");
1228 return -ENOTSUPP;
1229 }
1230
Anirban Chakraborty3d465122011-07-29 13:30:26 +00001231 if (fw_dump->clr)
1232 dump->len = fw_dump->tmpl_hdr->size + fw_dump->size;
1233 else
1234 dump->len = 0;
Manish choprabcebe552012-05-15 01:13:39 +00001235
1236 if (!fw_dump->enable)
1237 dump->flag = ETH_FW_DUMP_DISABLE;
1238 else
1239 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1240
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001241 dump->version = adapter->fw_version;
1242 return 0;
1243}
1244
1245static int
1246qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1247 void *buffer)
1248{
1249 int i, copy_sz;
1250 u32 *hdr_ptr, *data;
1251 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1252 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1253
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001254 if (!fw_dump->tmpl_hdr) {
1255 netdev_err(netdev, "FW Dump not supported\n");
1256 return -ENOTSUPP;
1257 }
1258
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001259 if (!fw_dump->clr) {
1260 netdev_info(netdev, "Dump not available\n");
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001261 return -EINVAL;
1262 }
1263 /* Copy template header first */
1264 copy_sz = fw_dump->tmpl_hdr->size;
1265 hdr_ptr = (u32 *) fw_dump->tmpl_hdr;
Joe Perches43d620c2011-06-16 19:08:06 +00001266 data = buffer;
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001267 for (i = 0; i < copy_sz/sizeof(u32); i++)
1268 *data++ = cpu_to_le32(*hdr_ptr++);
1269
1270 /* Copy captured dump data */
1271 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1272 dump->len = copy_sz + fw_dump->size;
1273 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask;
1274
1275 /* Free dump area once data has been captured */
1276 vfree(fw_dump->data);
1277 fw_dump->data = NULL;
1278 fw_dump->clr = 0;
Manish choprac47884e42012-02-03 13:45:44 +00001279 netdev_info(netdev, "extracted the FW dump Successfully\n");
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001280 return 0;
1281}
1282
1283static int
1284qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1285{
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001286 int i;
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001287 struct qlcnic_adapter *adapter = netdev_priv(netdev);
1288 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001289 u32 state;
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001290
Anirban Chakraborty3d465122011-07-29 13:30:26 +00001291 switch (val->flag) {
1292 case QLCNIC_FORCE_FW_DUMP_KEY:
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001293 if (!fw_dump->tmpl_hdr) {
1294 netdev_err(netdev, "FW dump not supported\n");
1295 return -ENOTSUPP;
1296 }
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00001297 if (!fw_dump->enable) {
1298 netdev_info(netdev, "FW dump not enabled\n");
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001299 return 0;
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00001300 }
1301 if (fw_dump->clr) {
Manish choprac47884e42012-02-03 13:45:44 +00001302 netdev_info(netdev,
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00001303 "Previous dump not cleared, not forcing dump\n");
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001304 return 0;
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00001305 }
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001306 netdev_info(netdev, "Forcing a FW dump\n");
1307 qlcnic_dev_request_reset(adapter);
Anirban Chakraborty3d465122011-07-29 13:30:26 +00001308 break;
1309 case QLCNIC_DISABLE_FW_DUMP:
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001310 if (fw_dump->enable && fw_dump->tmpl_hdr) {
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00001311 netdev_info(netdev, "Disabling FW dump\n");
1312 fw_dump->enable = 0;
1313 }
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001314 return 0;
Anirban Chakraborty3d465122011-07-29 13:30:26 +00001315 case QLCNIC_ENABLE_FW_DUMP:
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001316 if (!fw_dump->tmpl_hdr) {
1317 netdev_err(netdev, "FW dump not supported\n");
1318 return -ENOTSUPP;
1319 }
1320 if (!fw_dump->enable) {
Anirban Chakraborty9d6a6442011-06-22 02:52:22 +00001321 netdev_info(netdev, "Enabling FW dump\n");
1322 fw_dump->enable = 1;
1323 }
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001324 return 0;
Anirban Chakraborty3d465122011-07-29 13:30:26 +00001325 case QLCNIC_FORCE_FW_RESET:
1326 netdev_info(netdev, "Forcing a FW reset\n");
1327 qlcnic_dev_request_reset(adapter);
1328 adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001329 return 0;
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001330 case QLCNIC_SET_QUIESCENT:
1331 case QLCNIC_RESET_QUIESCENT:
1332 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
1333 if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
1334 netdev_info(netdev, "Device in FAILED state\n");
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001335 return 0;
Anirban Chakraborty3d465122011-07-29 13:30:26 +00001336 default:
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001337 if (!fw_dump->tmpl_hdr) {
1338 netdev_err(netdev, "FW dump not supported\n");
1339 return -ENOTSUPP;
1340 }
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001341 for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
1342 if (val->flag == FW_DUMP_LEVELS[i]) {
1343 fw_dump->tmpl_hdr->drv_cap_mask =
1344 val->flag;
1345 netdev_info(netdev, "Driver mask changed to: 0x%x\n",
1346 fw_dump->tmpl_hdr->drv_cap_mask);
1347 return 0;
1348 }
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001349 }
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001350 netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag);
1351 return -EINVAL;
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001352 }
Manish Chopra4fbec4d2012-04-26 10:31:31 +00001353 return 0;
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001354}
1355
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001356const struct ethtool_ops qlcnic_ethtool_ops = {
1357 .get_settings = qlcnic_get_settings,
1358 .set_settings = qlcnic_set_settings,
1359 .get_drvinfo = qlcnic_get_drvinfo,
1360 .get_regs_len = qlcnic_get_regs_len,
1361 .get_regs = qlcnic_get_regs,
1362 .get_link = ethtool_op_get_link,
1363 .get_eeprom_len = qlcnic_get_eeprom_len,
1364 .get_eeprom = qlcnic_get_eeprom,
1365 .get_ringparam = qlcnic_get_ringparam,
1366 .set_ringparam = qlcnic_set_ringparam,
Sucheta Chakrabortyf94bc1e2011-04-28 11:48:18 +00001367 .get_channels = qlcnic_get_channels,
1368 .set_channels = qlcnic_set_channels,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001369 .get_pauseparam = qlcnic_get_pauseparam,
1370 .set_pauseparam = qlcnic_set_pauseparam,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001371 .get_wol = qlcnic_get_wol,
1372 .set_wol = qlcnic_set_wol,
1373 .self_test = qlcnic_diag_test,
1374 .get_strings = qlcnic_get_strings,
1375 .get_ethtool_stats = qlcnic_get_ethtool_stats,
1376 .get_sset_count = qlcnic_get_sset_count,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001377 .get_coalesce = qlcnic_get_intr_coalesce,
1378 .set_coalesce = qlcnic_set_intr_coalesce,
stephen hemminger94469f72011-04-06 11:47:23 +00001379 .set_phys_id = qlcnic_set_led,
Amit Kumar Salecha65b5b422010-04-01 19:01:33 +00001380 .set_msglevel = qlcnic_set_msglevel,
1381 .get_msglevel = qlcnic_get_msglevel,
Anirban Chakrabortyb3c68732011-05-12 12:48:34 +00001382 .get_dump_flag = qlcnic_get_dump_flag,
1383 .get_dump_data = qlcnic_get_dump_data,
1384 .set_dump = qlcnic_set_dump,
Amit Kumar Salechaaf19b492010-01-13 00:37:25 +00001385};
Sucheta Chakrabortyb43e5ee2012-04-26 10:31:29 +00001386
1387const struct ethtool_ops qlcnic_ethtool_failed_ops = {
1388 .get_settings = qlcnic_get_settings,
1389 .get_drvinfo = qlcnic_get_drvinfo,
1390 .set_msglevel = qlcnic_set_msglevel,
1391 .get_msglevel = qlcnic_get_msglevel,
1392};