]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[karo-tx-linux.git] / drivers / net / ethernet / qlogic / netxen / netxen_nic_ethtool.c
1 /*
2  * Copyright (C) 2003 - 2009 NetXen, Inc.
3  * Copyright (C) 2009 - QLogic Corporation.
4  * All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  *
19  * The full GNU General Public License is included in this distribution
20  * in the file called "COPYING".
21  *
22  */
23
24 #include <linux/types.h>
25 #include <linux/delay.h>
26 #include <linux/pci.h>
27 #include <asm/io.h>
28 #include <linux/netdevice.h>
29 #include <linux/ethtool.h>
30
31 #include "netxen_nic.h"
32 #include "netxen_nic_hw.h"
33
34 struct netxen_nic_stats {
35         char stat_string[ETH_GSTRING_LEN];
36         int sizeof_stat;
37         int stat_offset;
38 };
39
40 #define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \
41                         offsetof(struct netxen_adapter, m)
42
43 #define NETXEN_NIC_PORT_WINDOW 0x10000
44 #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
45
46 static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
47         {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
48         {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
49         {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
50         {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
51         {"csummed", NETXEN_NIC_STAT(stats.csummed)},
52         {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)},
53         {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)},
54         {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
55         {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
56 };
57
58 #define NETXEN_NIC_STATS_LEN    ARRAY_SIZE(netxen_nic_gstrings_stats)
59
60 static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
61         "Register_Test_on_offline",
62         "Link_Test_on_offline"
63 };
64
65 #define NETXEN_NIC_TEST_LEN     ARRAY_SIZE(netxen_nic_gstrings_test)
66
67 #define NETXEN_NIC_REGS_COUNT 30
68 #define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
69 #define NETXEN_MAX_EEPROM_LEN   1024
70
71 static int netxen_nic_get_eeprom_len(struct net_device *dev)
72 {
73         return NETXEN_FLASH_TOTAL_SIZE;
74 }
75
76 static void
77 netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
78 {
79         struct netxen_adapter *adapter = netdev_priv(dev);
80         u32 fw_major = 0;
81         u32 fw_minor = 0;
82         u32 fw_build = 0;
83
84         strlcpy(drvinfo->driver, netxen_nic_driver_name,
85                 sizeof(drvinfo->driver));
86         strlcpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID,
87                 sizeof(drvinfo->version));
88         fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
89         fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
90         fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
91         snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
92                 "%d.%d.%d", fw_major, fw_minor, fw_build);
93
94         strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
95                 sizeof(drvinfo->bus_info));
96 }
97
98 static int
99 netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
100 {
101         struct netxen_adapter *adapter = netdev_priv(dev);
102         int check_sfp_module = 0;
103
104         /* read which mode */
105         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
106                 ecmd->supported = (SUPPORTED_10baseT_Half |
107                                    SUPPORTED_10baseT_Full |
108                                    SUPPORTED_100baseT_Half |
109                                    SUPPORTED_100baseT_Full |
110                                    SUPPORTED_1000baseT_Half |
111                                    SUPPORTED_1000baseT_Full);
112
113                 ecmd->advertising = (ADVERTISED_100baseT_Half |
114                                      ADVERTISED_100baseT_Full |
115                                      ADVERTISED_1000baseT_Half |
116                                      ADVERTISED_1000baseT_Full);
117
118                 ecmd->port = PORT_TP;
119
120                 ethtool_cmd_speed_set(ecmd, adapter->link_speed);
121                 ecmd->duplex = adapter->link_duplex;
122                 ecmd->autoneg = adapter->link_autoneg;
123
124         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
125                 u32 val;
126
127                 val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
128                 if (val == NETXEN_PORT_MODE_802_3_AP) {
129                         ecmd->supported = SUPPORTED_1000baseT_Full;
130                         ecmd->advertising = ADVERTISED_1000baseT_Full;
131                 } else {
132                         ecmd->supported = SUPPORTED_10000baseT_Full;
133                         ecmd->advertising = ADVERTISED_10000baseT_Full;
134                 }
135
136                 if (netif_running(dev) && adapter->has_link_events) {
137                         ethtool_cmd_speed_set(ecmd, adapter->link_speed);
138                         ecmd->autoneg = adapter->link_autoneg;
139                         ecmd->duplex = adapter->link_duplex;
140                         goto skip;
141                 }
142
143                 ecmd->port = PORT_TP;
144
145                 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
146                         u16 pcifn = adapter->ahw.pci_func;
147
148                         val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));
149                         ethtool_cmd_speed_set(ecmd, P3_LINK_SPEED_MHZ *
150                                               P3_LINK_SPEED_VAL(pcifn, val));
151                 } else
152                         ethtool_cmd_speed_set(ecmd, SPEED_10000);
153
154                 ecmd->duplex = DUPLEX_FULL;
155                 ecmd->autoneg = AUTONEG_DISABLE;
156         } else
157                 return -EIO;
158
159 skip:
160         ecmd->phy_address = adapter->physical_port;
161         ecmd->transceiver = XCVR_EXTERNAL;
162
163         switch (adapter->ahw.board_type) {
164         case NETXEN_BRDTYPE_P2_SB35_4G:
165         case NETXEN_BRDTYPE_P2_SB31_2G:
166         case NETXEN_BRDTYPE_P3_REF_QG:
167         case NETXEN_BRDTYPE_P3_4_GB:
168         case NETXEN_BRDTYPE_P3_4_GB_MM:
169
170                 ecmd->supported |= SUPPORTED_Autoneg;
171                 ecmd->advertising |= ADVERTISED_Autoneg;
172         case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
173         case NETXEN_BRDTYPE_P3_10G_CX4:
174         case NETXEN_BRDTYPE_P3_10G_CX4_LP:
175         case NETXEN_BRDTYPE_P3_10000_BASE_T:
176                 ecmd->supported |= SUPPORTED_TP;
177                 ecmd->advertising |= ADVERTISED_TP;
178                 ecmd->port = PORT_TP;
179                 ecmd->autoneg = (adapter->ahw.board_type ==
180                                  NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
181                     (AUTONEG_DISABLE) : (adapter->link_autoneg);
182                 break;
183         case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
184         case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
185         case NETXEN_BRDTYPE_P3_IMEZ:
186         case NETXEN_BRDTYPE_P3_XG_LOM:
187         case NETXEN_BRDTYPE_P3_HMEZ:
188                 ecmd->supported |= SUPPORTED_MII;
189                 ecmd->advertising |= ADVERTISED_MII;
190                 ecmd->port = PORT_MII;
191                 ecmd->autoneg = AUTONEG_DISABLE;
192                 break;
193         case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
194         case NETXEN_BRDTYPE_P3_10G_SFP_CT:
195         case NETXEN_BRDTYPE_P3_10G_SFP_QT:
196                 ecmd->advertising |= ADVERTISED_TP;
197                 ecmd->supported |= SUPPORTED_TP;
198                 check_sfp_module = netif_running(dev) &&
199                         adapter->has_link_events;
200         case NETXEN_BRDTYPE_P2_SB31_10G:
201         case NETXEN_BRDTYPE_P3_10G_XFP:
202                 ecmd->supported |= SUPPORTED_FIBRE;
203                 ecmd->advertising |= ADVERTISED_FIBRE;
204                 ecmd->port = PORT_FIBRE;
205                 ecmd->autoneg = AUTONEG_DISABLE;
206                 break;
207         case NETXEN_BRDTYPE_P3_10G_TP:
208                 if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
209                         ecmd->autoneg = AUTONEG_DISABLE;
210                         ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
211                         ecmd->advertising |=
212                                 (ADVERTISED_FIBRE | ADVERTISED_TP);
213                         ecmd->port = PORT_FIBRE;
214                         check_sfp_module = netif_running(dev) &&
215                                 adapter->has_link_events;
216                 } else {
217                         ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
218                         ecmd->advertising |=
219                                 (ADVERTISED_TP | ADVERTISED_Autoneg);
220                         ecmd->port = PORT_TP;
221                 }
222                 break;
223         default:
224                 printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
225                                 adapter->ahw.board_type);
226                 return -EIO;
227         }
228
229         if (check_sfp_module) {
230                 switch (adapter->module_type) {
231                 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
232                 case LINKEVENT_MODULE_OPTICAL_SRLR:
233                 case LINKEVENT_MODULE_OPTICAL_LRM:
234                 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
235                         ecmd->port = PORT_FIBRE;
236                         break;
237                 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
238                 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
239                 case LINKEVENT_MODULE_TWINAX:
240                         ecmd->port = PORT_TP;
241                         break;
242                 default:
243                         ecmd->port = -1;
244                 }
245         }
246
247         if (!netif_running(dev) || !adapter->ahw.linkup) {
248                 ecmd->duplex = DUPLEX_UNKNOWN;
249                 ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN);
250         }
251
252         return 0;
253 }
254
255 static int
256 netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
257 {
258         struct netxen_adapter *adapter = netdev_priv(dev);
259         u32 speed = ethtool_cmd_speed(ecmd);
260         int ret;
261
262         if (adapter->ahw.port_type != NETXEN_NIC_GBE)
263                 return -EOPNOTSUPP;
264
265         if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
266                 return -EOPNOTSUPP;
267
268         ret = nx_fw_cmd_set_gbe_port(adapter, speed, ecmd->duplex,
269                                      ecmd->autoneg);
270         if (ret == NX_RCODE_NOT_SUPPORTED)
271                 return -EOPNOTSUPP;
272         else if (ret)
273                 return -EIO;
274
275         adapter->link_speed = speed;
276         adapter->link_duplex = ecmd->duplex;
277         adapter->link_autoneg = ecmd->autoneg;
278
279         if (!netif_running(dev))
280                 return 0;
281
282         dev->netdev_ops->ndo_stop(dev);
283         return dev->netdev_ops->ndo_open(dev);
284 }
285
286 static int netxen_nic_get_regs_len(struct net_device *dev)
287 {
288         return NETXEN_NIC_REGS_LEN;
289 }
290
291 static void
292 netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
293 {
294         struct netxen_adapter *adapter = netdev_priv(dev);
295         struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
296         struct nx_host_sds_ring *sds_ring;
297         u32 *regs_buff = p;
298         int ring, i = 0;
299         int port = adapter->physical_port;
300
301         memset(p, 0, NETXEN_NIC_REGS_LEN);
302
303         regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
304             (adapter->pdev)->device;
305
306         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
307                 return;
308
309         regs_buff[i++] = NXRD32(adapter, CRB_CMDPEG_STATE);
310         regs_buff[i++] = NXRD32(adapter, CRB_RCVPEG_STATE);
311         regs_buff[i++] = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
312         regs_buff[i++] = NXRDIO(adapter, adapter->crb_int_state_reg);
313         regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
314         regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_STATE);
315         regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
316         regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
317         regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS2);
318
319         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_0+0x3c);
320         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_1+0x3c);
321         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_2+0x3c);
322         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_3+0x3c);
323
324         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
325
326                 regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_4+0x3c);
327                 i += 2;
328
329                 regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE_P3);
330                 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
331
332         } else {
333                 i++;
334
335                 regs_buff[i++] = NXRD32(adapter,
336                                         NETXEN_NIU_XGE_CONFIG_0+(0x10000*port));
337                 regs_buff[i++] = NXRD32(adapter,
338                                         NETXEN_NIU_XGE_CONFIG_1+(0x10000*port));
339
340                 regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE);
341                 regs_buff[i++] = NXRDIO(adapter,
342                                  adapter->tx_ring->crb_cmd_consumer);
343         }
344
345         regs_buff[i++] = NXRDIO(adapter, adapter->tx_ring->crb_cmd_producer);
346
347         regs_buff[i++] = NXRDIO(adapter,
348                          recv_ctx->rds_rings[0].crb_rcv_producer);
349         regs_buff[i++] = NXRDIO(adapter,
350                          recv_ctx->rds_rings[1].crb_rcv_producer);
351
352         regs_buff[i++] = adapter->max_sds_rings;
353
354         for (ring = 0; ring < adapter->max_sds_rings; ring++) {
355                 sds_ring = &(recv_ctx->sds_rings[ring]);
356                 regs_buff[i++] = NXRDIO(adapter,
357                                         sds_ring->crb_sts_consumer);
358         }
359 }
360
361 static u32 netxen_nic_test_link(struct net_device *dev)
362 {
363         struct netxen_adapter *adapter = netdev_priv(dev);
364         u32 val, port;
365
366         port = adapter->physical_port;
367         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
368                 val = NXRD32(adapter, CRB_XG_STATE_P3);
369                 val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
370                 return (val == XG_LINK_UP_P3) ? 0 : 1;
371         } else {
372                 val = NXRD32(adapter, CRB_XG_STATE);
373                 val = (val >> port*8) & 0xff;
374                 return (val == XG_LINK_UP) ? 0 : 1;
375         }
376 }
377
378 static int
379 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
380                       u8 *bytes)
381 {
382         struct netxen_adapter *adapter = netdev_priv(dev);
383         int offset;
384         int ret;
385
386         if (eeprom->len == 0)
387                 return -EINVAL;
388
389         eeprom->magic = (adapter->pdev)->vendor |
390                         ((adapter->pdev)->device << 16);
391         offset = eeprom->offset;
392
393         ret = netxen_rom_fast_read_words(adapter, offset, bytes,
394                                                 eeprom->len);
395         if (ret < 0)
396                 return ret;
397
398         return 0;
399 }
400
401 static void
402 netxen_nic_get_ringparam(struct net_device *dev,
403                 struct ethtool_ringparam *ring)
404 {
405         struct netxen_adapter *adapter = netdev_priv(dev);
406
407         ring->rx_pending = adapter->num_rxd;
408         ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
409         ring->rx_jumbo_pending += adapter->num_lro_rxd;
410         ring->tx_pending = adapter->num_txd;
411
412         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
413                 ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
414                 ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
415         } else {
416                 ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
417                 ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
418         }
419
420         ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
421 }
422
423 static u32
424 netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
425 {
426         u32 num_desc;
427         num_desc = max(val, min);
428         num_desc = min(num_desc, max);
429         num_desc = roundup_pow_of_two(num_desc);
430
431         if (val != num_desc) {
432                 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
433                        netxen_nic_driver_name, r_name, num_desc, val);
434         }
435
436         return num_desc;
437 }
438
439 static int
440 netxen_nic_set_ringparam(struct net_device *dev,
441                 struct ethtool_ringparam *ring)
442 {
443         struct netxen_adapter *adapter = netdev_priv(dev);
444         u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
445         u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
446         u16 num_rxd, num_jumbo_rxd, num_txd;
447
448         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
449                 return -EOPNOTSUPP;
450
451         if (ring->rx_mini_pending)
452                 return -EOPNOTSUPP;
453
454         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
455                 max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
456                 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
457         }
458
459         num_rxd = netxen_validate_ringparam(ring->rx_pending,
460                         MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
461
462         num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
463                         MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
464
465         num_txd = netxen_validate_ringparam(ring->tx_pending,
466                         MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
467
468         if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
469                         num_jumbo_rxd == adapter->num_jumbo_rxd)
470                 return 0;
471
472         adapter->num_rxd = num_rxd;
473         adapter->num_jumbo_rxd = num_jumbo_rxd;
474         adapter->num_txd = num_txd;
475
476         return netxen_nic_reset_context(adapter);
477 }
478
479 static void
480 netxen_nic_get_pauseparam(struct net_device *dev,
481                           struct ethtool_pauseparam *pause)
482 {
483         struct netxen_adapter *adapter = netdev_priv(dev);
484         __u32 val;
485         int port = adapter->physical_port;
486
487         pause->autoneg = 0;
488
489         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
490                 if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
491                         return;
492                 /* get flow control settings */
493                 val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
494                 pause->rx_pause = netxen_gb_get_rx_flowctl(val);
495                 val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
496                 switch (port) {
497                 case 0:
498                         pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
499                         break;
500                 case 1:
501                         pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
502                         break;
503                 case 2:
504                         pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
505                         break;
506                 case 3:
507                 default:
508                         pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
509                         break;
510                 }
511         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
512                 if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
513                         return;
514                 pause->rx_pause = 1;
515                 val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
516                 if (port == 0)
517                         pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
518                 else
519                         pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
520         } else {
521                 printk(KERN_ERR"%s: Unknown board type: %x\n",
522                                 netxen_nic_driver_name, adapter->ahw.port_type);
523         }
524 }
525
526 static int
527 netxen_nic_set_pauseparam(struct net_device *dev,
528                           struct ethtool_pauseparam *pause)
529 {
530         struct netxen_adapter *adapter = netdev_priv(dev);
531         __u32 val;
532         int port = adapter->physical_port;
533
534         /* not supported */
535         if (pause->autoneg)
536                 return -EINVAL;
537
538         /* read mode */
539         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
540                 if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
541                         return -EIO;
542                 /* set flow control */
543                 val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
544
545                 if (pause->rx_pause)
546                         netxen_gb_rx_flowctl(val);
547                 else
548                         netxen_gb_unset_rx_flowctl(val);
549
550                 NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
551                                 val);
552                 /* set autoneg */
553                 val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
554                 switch (port) {
555                 case 0:
556                         if (pause->tx_pause)
557                                 netxen_gb_unset_gb0_mask(val);
558                         else
559                                 netxen_gb_set_gb0_mask(val);
560                         break;
561                 case 1:
562                         if (pause->tx_pause)
563                                 netxen_gb_unset_gb1_mask(val);
564                         else
565                                 netxen_gb_set_gb1_mask(val);
566                         break;
567                 case 2:
568                         if (pause->tx_pause)
569                                 netxen_gb_unset_gb2_mask(val);
570                         else
571                                 netxen_gb_set_gb2_mask(val);
572                         break;
573                 case 3:
574                 default:
575                         if (pause->tx_pause)
576                                 netxen_gb_unset_gb3_mask(val);
577                         else
578                                 netxen_gb_set_gb3_mask(val);
579                         break;
580                 }
581                 NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
582         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
583                 if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
584                         return -EIO;
585                 val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
586                 if (port == 0) {
587                         if (pause->tx_pause)
588                                 netxen_xg_unset_xg0_mask(val);
589                         else
590                                 netxen_xg_set_xg0_mask(val);
591                 } else {
592                         if (pause->tx_pause)
593                                 netxen_xg_unset_xg1_mask(val);
594                         else
595                                 netxen_xg_set_xg1_mask(val);
596                 }
597                 NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
598         } else {
599                 printk(KERN_ERR "%s: Unknown board type: %x\n",
600                                 netxen_nic_driver_name,
601                                 adapter->ahw.port_type);
602         }
603         return 0;
604 }
605
606 static int netxen_nic_reg_test(struct net_device *dev)
607 {
608         struct netxen_adapter *adapter = netdev_priv(dev);
609         u32 data_read, data_written;
610
611         data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
612         if ((data_read & 0xffff) != adapter->pdev->vendor)
613                 return 1;
614
615         if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
616                 return 0;
617
618         data_written = (u32)0xa5a5a5a5;
619
620         NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
621         data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
622         if (data_written != data_read)
623                 return 1;
624
625         return 0;
626 }
627
628 static int netxen_get_sset_count(struct net_device *dev, int sset)
629 {
630         switch (sset) {
631         case ETH_SS_TEST:
632                 return NETXEN_NIC_TEST_LEN;
633         case ETH_SS_STATS:
634                 return NETXEN_NIC_STATS_LEN;
635         default:
636                 return -EOPNOTSUPP;
637         }
638 }
639
640 static void
641 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
642                      u64 *data)
643 {
644         memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
645         if ((data[0] = netxen_nic_reg_test(dev)))
646                 eth_test->flags |= ETH_TEST_FL_FAILED;
647         /* link test */
648         if ((data[1] = (u64) netxen_nic_test_link(dev)))
649                 eth_test->flags |= ETH_TEST_FL_FAILED;
650 }
651
652 static void
653 netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
654 {
655         int index;
656
657         switch (stringset) {
658         case ETH_SS_TEST:
659                 memcpy(data, *netxen_nic_gstrings_test,
660                        NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
661                 break;
662         case ETH_SS_STATS:
663                 for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
664                         memcpy(data + index * ETH_GSTRING_LEN,
665                                netxen_nic_gstrings_stats[index].stat_string,
666                                ETH_GSTRING_LEN);
667                 }
668                 break;
669         }
670 }
671
672 static void
673 netxen_nic_get_ethtool_stats(struct net_device *dev,
674                              struct ethtool_stats *stats, u64 *data)
675 {
676         struct netxen_adapter *adapter = netdev_priv(dev);
677         int index;
678
679         for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
680                 char *p =
681                     (char *)adapter +
682                     netxen_nic_gstrings_stats[index].stat_offset;
683                 data[index] =
684                     (netxen_nic_gstrings_stats[index].sizeof_stat ==
685                      sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
686         }
687 }
688
689 static void
690 netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
691 {
692         struct netxen_adapter *adapter = netdev_priv(dev);
693         u32 wol_cfg = 0;
694
695         wol->supported = 0;
696         wol->wolopts = 0;
697
698         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
699                 return;
700
701         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
702         if (wol_cfg & (1UL << adapter->portnum))
703                 wol->supported |= WAKE_MAGIC;
704
705         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
706         if (wol_cfg & (1UL << adapter->portnum))
707                 wol->wolopts |= WAKE_MAGIC;
708 }
709
710 static int
711 netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
712 {
713         struct netxen_adapter *adapter = netdev_priv(dev);
714         u32 wol_cfg = 0;
715
716         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
717                 return -EOPNOTSUPP;
718
719         if (wol->wolopts & ~WAKE_MAGIC)
720                 return -EOPNOTSUPP;
721
722         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
723         if (!(wol_cfg & (1 << adapter->portnum)))
724                 return -EOPNOTSUPP;
725
726         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
727         if (wol->wolopts & WAKE_MAGIC)
728                 wol_cfg |= 1UL << adapter->portnum;
729         else
730                 wol_cfg &= ~(1UL << adapter->portnum);
731         NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
732
733         return 0;
734 }
735
736 /*
737  * Set the coalescing parameters. Currently only normal is supported.
738  * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
739  * firmware coalescing to default.
740  */
741 static int netxen_set_intr_coalesce(struct net_device *netdev,
742                         struct ethtool_coalesce *ethcoal)
743 {
744         struct netxen_adapter *adapter = netdev_priv(netdev);
745
746         if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
747                 return -EINVAL;
748
749         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
750                 return -EINVAL;
751
752         /*
753         * Return Error if unsupported values or
754         * unsupported parameters are set.
755         */
756         if (ethcoal->rx_coalesce_usecs > 0xffff ||
757                 ethcoal->rx_max_coalesced_frames > 0xffff ||
758                 ethcoal->tx_coalesce_usecs > 0xffff ||
759                 ethcoal->tx_max_coalesced_frames > 0xffff ||
760                 ethcoal->rx_coalesce_usecs_irq ||
761                 ethcoal->rx_max_coalesced_frames_irq ||
762                 ethcoal->tx_coalesce_usecs_irq ||
763                 ethcoal->tx_max_coalesced_frames_irq ||
764                 ethcoal->stats_block_coalesce_usecs ||
765                 ethcoal->use_adaptive_rx_coalesce ||
766                 ethcoal->use_adaptive_tx_coalesce ||
767                 ethcoal->pkt_rate_low ||
768                 ethcoal->rx_coalesce_usecs_low ||
769                 ethcoal->rx_max_coalesced_frames_low ||
770                 ethcoal->tx_coalesce_usecs_low ||
771                 ethcoal->tx_max_coalesced_frames_low ||
772                 ethcoal->pkt_rate_high ||
773                 ethcoal->rx_coalesce_usecs_high ||
774                 ethcoal->rx_max_coalesced_frames_high ||
775                 ethcoal->tx_coalesce_usecs_high ||
776                 ethcoal->tx_max_coalesced_frames_high)
777                 return -EINVAL;
778
779         if (!ethcoal->rx_coalesce_usecs ||
780                 !ethcoal->rx_max_coalesced_frames) {
781                 adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
782                 adapter->coal.normal.data.rx_time_us =
783                         NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
784                 adapter->coal.normal.data.rx_packets =
785                         NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
786         } else {
787                 adapter->coal.flags = 0;
788                 adapter->coal.normal.data.rx_time_us =
789                 ethcoal->rx_coalesce_usecs;
790                 adapter->coal.normal.data.rx_packets =
791                 ethcoal->rx_max_coalesced_frames;
792         }
793         adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
794         adapter->coal.normal.data.tx_packets =
795         ethcoal->tx_max_coalesced_frames;
796
797         netxen_config_intr_coalesce(adapter);
798
799         return 0;
800 }
801
802 static int netxen_get_intr_coalesce(struct net_device *netdev,
803                         struct ethtool_coalesce *ethcoal)
804 {
805         struct netxen_adapter *adapter = netdev_priv(netdev);
806
807         if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
808                 return -EINVAL;
809
810         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
811                 return -EINVAL;
812
813         ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
814         ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
815         ethcoal->rx_max_coalesced_frames =
816                 adapter->coal.normal.data.rx_packets;
817         ethcoal->tx_max_coalesced_frames =
818                 adapter->coal.normal.data.tx_packets;
819
820         return 0;
821 }
822
823 static int
824 netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
825 {
826         struct netxen_adapter *adapter = netdev_priv(netdev);
827         struct netxen_minidump *mdump = &adapter->mdump;
828         if (adapter->fw_mdump_rdy)
829                 dump->len = mdump->md_dump_size;
830         else
831                 dump->len = 0;
832
833         if (!mdump->md_enabled)
834                 dump->flag = ETH_FW_DUMP_DISABLE;
835         else
836                 dump->flag = mdump->md_capture_mask;
837
838         dump->version = adapter->fw_version;
839         return 0;
840 }
841
842 static int
843 netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
844 {
845         int i;
846         struct netxen_adapter *adapter = netdev_priv(netdev);
847         struct netxen_minidump *mdump = &adapter->mdump;
848
849         switch (val->flag) {
850         case NX_FORCE_FW_DUMP_KEY:
851                 if (!mdump->md_enabled) {
852                         netdev_info(netdev, "FW dump not enabled\n");
853                         return 0;
854                 }
855                 if (adapter->fw_mdump_rdy) {
856                         netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");
857                         return 0;
858                 }
859                 netdev_info(netdev, "Forcing a fw dump\n");
860                 nx_dev_request_reset(adapter);
861                 break;
862         case NX_DISABLE_FW_DUMP:
863                 if (mdump->md_enabled) {
864                         netdev_info(netdev, "Disabling FW Dump\n");
865                         mdump->md_enabled = 0;
866                 }
867                 break;
868         case NX_ENABLE_FW_DUMP:
869                 if (!mdump->md_enabled) {
870                         netdev_info(netdev, "Enabling FW dump\n");
871                         mdump->md_enabled = 1;
872                 }
873                 break;
874         case NX_FORCE_FW_RESET:
875                 netdev_info(netdev, "Forcing FW reset\n");
876                 nx_dev_request_reset(adapter);
877                 adapter->flags &= ~NETXEN_FW_RESET_OWNER;
878                 break;
879         default:
880                 for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
881                         if (val->flag == FW_DUMP_LEVELS[i]) {
882                                 mdump->md_capture_mask = val->flag;
883                                 netdev_info(netdev,
884                                         "Driver mask changed to: 0x%x\n",
885                                         mdump->md_capture_mask);
886                                 return 0;
887                         }
888                 }
889                 netdev_info(netdev,
890                         "Invalid dump level: 0x%x\n", val->flag);
891                 return -EINVAL;
892         }
893
894         return 0;
895 }
896
897 static int
898 netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
899                         void *buffer)
900 {
901         int i, copy_sz;
902         u32 *hdr_ptr, *data;
903         struct netxen_adapter *adapter = netdev_priv(netdev);
904         struct netxen_minidump *mdump = &adapter->mdump;
905
906
907         if (!adapter->fw_mdump_rdy) {
908                 netdev_info(netdev, "Dump not available\n");
909                 return -EINVAL;
910         }
911         /* Copy template header first */
912         copy_sz = mdump->md_template_size;
913         hdr_ptr = (u32 *) mdump->md_template;
914         data = buffer;
915         for (i = 0; i < copy_sz/sizeof(u32); i++)
916                 *data++ = cpu_to_le32(*hdr_ptr++);
917
918         /* Copy captured dump data */
919         memcpy(buffer + copy_sz,
920                 mdump->md_capture_buff + mdump->md_template_size,
921                         mdump->md_capture_size);
922         dump->len = copy_sz + mdump->md_capture_size;
923         dump->flag = mdump->md_capture_mask;
924
925         /* Free dump area once data has been captured */
926         vfree(mdump->md_capture_buff);
927         mdump->md_capture_buff = NULL;
928         adapter->fw_mdump_rdy = 0;
929         netdev_info(netdev, "extracted the fw dump Successfully\n");
930         return 0;
931 }
932
933 const struct ethtool_ops netxen_nic_ethtool_ops = {
934         .get_settings = netxen_nic_get_settings,
935         .set_settings = netxen_nic_set_settings,
936         .get_drvinfo = netxen_nic_get_drvinfo,
937         .get_regs_len = netxen_nic_get_regs_len,
938         .get_regs = netxen_nic_get_regs,
939         .get_link = ethtool_op_get_link,
940         .get_eeprom_len = netxen_nic_get_eeprom_len,
941         .get_eeprom = netxen_nic_get_eeprom,
942         .get_ringparam = netxen_nic_get_ringparam,
943         .set_ringparam = netxen_nic_set_ringparam,
944         .get_pauseparam = netxen_nic_get_pauseparam,
945         .set_pauseparam = netxen_nic_set_pauseparam,
946         .get_wol = netxen_nic_get_wol,
947         .set_wol = netxen_nic_set_wol,
948         .self_test = netxen_nic_diag_test,
949         .get_strings = netxen_nic_get_strings,
950         .get_ethtool_stats = netxen_nic_get_ethtool_stats,
951         .get_sset_count = netxen_get_sset_count,
952         .get_coalesce = netxen_get_intr_coalesce,
953         .set_coalesce = netxen_set_intr_coalesce,
954         .get_dump_flag = netxen_get_dump_flag,
955         .get_dump_data = netxen_get_dump_data,
956         .set_dump = netxen_set_dump,
957 };