Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[pandora-kernel.git] / drivers / net / 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19  * MA  02111-1307, USA.
20  *
21  * The full GNU General Public License is included in this distribution
22  * in the file called "COPYING".
23  *
24  */
25
26 #include <linux/types.h>
27 #include <linux/delay.h>
28 #include <linux/pci.h>
29 #include <asm/io.h>
30 #include <linux/netdevice.h>
31 #include <linux/ethtool.h>
32
33 #include "netxen_nic.h"
34 #include "netxen_nic_hw.h"
35
36 struct netxen_nic_stats {
37         char stat_string[ETH_GSTRING_LEN];
38         int sizeof_stat;
39         int stat_offset;
40 };
41
42 #define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \
43                         offsetof(struct netxen_adapter, m)
44
45 #define NETXEN_NIC_PORT_WINDOW 0x10000
46 #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
47
48 static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
49         {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
50         {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
51         {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
52         {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
53         {"csummed", NETXEN_NIC_STAT(stats.csummed)},
54         {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)},
55         {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)},
56         {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
57         {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
58 };
59
60 #define NETXEN_NIC_STATS_LEN    ARRAY_SIZE(netxen_nic_gstrings_stats)
61
62 static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
63         "Register_Test_on_offline",
64         "Link_Test_on_offline"
65 };
66
67 #define NETXEN_NIC_TEST_LEN     ARRAY_SIZE(netxen_nic_gstrings_test)
68
69 #define NETXEN_NIC_REGS_COUNT 30
70 #define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
71 #define NETXEN_MAX_EEPROM_LEN   1024
72
73 static int netxen_nic_get_eeprom_len(struct net_device *dev)
74 {
75         return NETXEN_FLASH_TOTAL_SIZE;
76 }
77
78 static void
79 netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
80 {
81         struct netxen_adapter *adapter = netdev_priv(dev);
82         u32 fw_major = 0;
83         u32 fw_minor = 0;
84         u32 fw_build = 0;
85
86         strncpy(drvinfo->driver, netxen_nic_driver_name, 32);
87         strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32);
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         sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build);
92
93         strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
94         drvinfo->regdump_len = NETXEN_NIC_REGS_LEN;
95         drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev);
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         return 0;
248 }
249
250 static int
251 netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
252 {
253         struct netxen_adapter *adapter = netdev_priv(dev);
254         u32 speed = ethtool_cmd_speed(ecmd);
255         int ret;
256
257         if (adapter->ahw.port_type != NETXEN_NIC_GBE)
258                 return -EOPNOTSUPP;
259
260         if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
261                 return -EOPNOTSUPP;
262
263         ret = nx_fw_cmd_set_gbe_port(adapter, speed, ecmd->duplex,
264                                      ecmd->autoneg);
265         if (ret == NX_RCODE_NOT_SUPPORTED)
266                 return -EOPNOTSUPP;
267         else if (ret)
268                 return -EIO;
269
270         adapter->link_speed = speed;
271         adapter->link_duplex = ecmd->duplex;
272         adapter->link_autoneg = ecmd->autoneg;
273
274         if (!netif_running(dev))
275                 return 0;
276
277         dev->netdev_ops->ndo_stop(dev);
278         return dev->netdev_ops->ndo_open(dev);
279 }
280
281 static int netxen_nic_get_regs_len(struct net_device *dev)
282 {
283         return NETXEN_NIC_REGS_LEN;
284 }
285
286 static void
287 netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
288 {
289         struct netxen_adapter *adapter = netdev_priv(dev);
290         struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
291         struct nx_host_sds_ring *sds_ring;
292         u32 *regs_buff = p;
293         int ring, i = 0;
294         int port = adapter->physical_port;
295
296         memset(p, 0, NETXEN_NIC_REGS_LEN);
297
298         regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
299             (adapter->pdev)->device;
300
301         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
302                 return;
303
304         regs_buff[i++] = NXRD32(adapter, CRB_CMDPEG_STATE);
305         regs_buff[i++] = NXRD32(adapter, CRB_RCVPEG_STATE);
306         regs_buff[i++] = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
307         regs_buff[i++] = NXRDIO(adapter, adapter->crb_int_state_reg);
308         regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
309         regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_STATE);
310         regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
311         regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
312         regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS2);
313
314         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_0+0x3c);
315         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_1+0x3c);
316         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_2+0x3c);
317         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_3+0x3c);
318
319         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
320
321                 regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_4+0x3c);
322                 i += 2;
323
324                 regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE_P3);
325                 regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
326
327         } else {
328                 i++;
329
330                 regs_buff[i++] = NXRD32(adapter,
331                                         NETXEN_NIU_XGE_CONFIG_0+(0x10000*port));
332                 regs_buff[i++] = NXRD32(adapter,
333                                         NETXEN_NIU_XGE_CONFIG_1+(0x10000*port));
334
335                 regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE);
336                 regs_buff[i++] = NXRDIO(adapter,
337                                  adapter->tx_ring->crb_cmd_consumer);
338         }
339
340         regs_buff[i++] = NXRDIO(adapter, adapter->tx_ring->crb_cmd_producer);
341
342         regs_buff[i++] = NXRDIO(adapter,
343                          recv_ctx->rds_rings[0].crb_rcv_producer);
344         regs_buff[i++] = NXRDIO(adapter,
345                          recv_ctx->rds_rings[1].crb_rcv_producer);
346
347         regs_buff[i++] = adapter->max_sds_rings;
348
349         for (ring = 0; ring < adapter->max_sds_rings; ring++) {
350                 sds_ring = &(recv_ctx->sds_rings[ring]);
351                 regs_buff[i++] = NXRDIO(adapter,
352                                         sds_ring->crb_sts_consumer);
353         }
354 }
355
356 static u32 netxen_nic_test_link(struct net_device *dev)
357 {
358         struct netxen_adapter *adapter = netdev_priv(dev);
359         u32 val, port;
360
361         port = adapter->physical_port;
362         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
363                 val = NXRD32(adapter, CRB_XG_STATE_P3);
364                 val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
365                 return (val == XG_LINK_UP_P3) ? 0 : 1;
366         } else {
367                 val = NXRD32(adapter, CRB_XG_STATE);
368                 val = (val >> port*8) & 0xff;
369                 return (val == XG_LINK_UP) ? 0 : 1;
370         }
371 }
372
373 static int
374 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
375                       u8 * bytes)
376 {
377         struct netxen_adapter *adapter = netdev_priv(dev);
378         int offset;
379         int ret;
380
381         if (eeprom->len == 0)
382                 return -EINVAL;
383
384         eeprom->magic = (adapter->pdev)->vendor |
385                         ((adapter->pdev)->device << 16);
386         offset = eeprom->offset;
387
388         ret = netxen_rom_fast_read_words(adapter, offset, bytes,
389                                                 eeprom->len);
390         if (ret < 0)
391                 return ret;
392
393         return 0;
394 }
395
396 static void
397 netxen_nic_get_ringparam(struct net_device *dev,
398                 struct ethtool_ringparam *ring)
399 {
400         struct netxen_adapter *adapter = netdev_priv(dev);
401
402         ring->rx_pending = adapter->num_rxd;
403         ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
404         ring->rx_jumbo_pending += adapter->num_lro_rxd;
405         ring->tx_pending = adapter->num_txd;
406
407         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
408                 ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
409                 ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
410         } else {
411                 ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
412                 ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
413         }
414
415         ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
416
417         ring->rx_mini_max_pending = 0;
418         ring->rx_mini_pending = 0;
419 }
420
421 static u32
422 netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
423 {
424         u32 num_desc;
425         num_desc = max(val, min);
426         num_desc = min(num_desc, max);
427         num_desc = roundup_pow_of_two(num_desc);
428
429         if (val != num_desc) {
430                 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
431                        netxen_nic_driver_name, r_name, num_desc, val);
432         }
433
434         return num_desc;
435 }
436
437 static int
438 netxen_nic_set_ringparam(struct net_device *dev,
439                 struct ethtool_ringparam *ring)
440 {
441         struct netxen_adapter *adapter = netdev_priv(dev);
442         u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
443         u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
444         u16 num_rxd, num_jumbo_rxd, num_txd;
445
446         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
447                 return -EOPNOTSUPP;
448
449         if (ring->rx_mini_pending)
450                 return -EOPNOTSUPP;
451
452         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
453                 max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
454                 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
455         }
456
457         num_rxd = netxen_validate_ringparam(ring->rx_pending,
458                         MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
459
460         num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
461                         MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
462
463         num_txd = netxen_validate_ringparam(ring->tx_pending,
464                         MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
465
466         if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
467                         num_jumbo_rxd == adapter->num_jumbo_rxd)
468                 return 0;
469
470         adapter->num_rxd = num_rxd;
471         adapter->num_jumbo_rxd = num_jumbo_rxd;
472         adapter->num_txd = num_txd;
473
474         return netxen_nic_reset_context(adapter);
475 }
476
477 static void
478 netxen_nic_get_pauseparam(struct net_device *dev,
479                           struct ethtool_pauseparam *pause)
480 {
481         struct netxen_adapter *adapter = netdev_priv(dev);
482         __u32 val;
483         int port = adapter->physical_port;
484
485         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
486                 if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
487                         return;
488                 /* get flow control settings */
489                 val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
490                 pause->rx_pause = netxen_gb_get_rx_flowctl(val);
491                 val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
492                 switch (port) {
493                         case 0:
494                                 pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
495                                 break;
496                         case 1:
497                                 pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
498                                 break;
499                         case 2:
500                                 pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
501                                 break;
502                         case 3:
503                         default:
504                                 pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
505                                 break;
506                 }
507         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
508                 if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
509                         return;
510                 pause->rx_pause = 1;
511                 val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
512                 if (port == 0)
513                         pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
514                 else
515                         pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
516         } else {
517                 printk(KERN_ERR"%s: Unknown board type: %x\n",
518                                 netxen_nic_driver_name, adapter->ahw.port_type);
519         }
520 }
521
522 static int
523 netxen_nic_set_pauseparam(struct net_device *dev,
524                           struct ethtool_pauseparam *pause)
525 {
526         struct netxen_adapter *adapter = netdev_priv(dev);
527         __u32 val;
528         int port = adapter->physical_port;
529         /* read mode */
530         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
531                 if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
532                         return -EIO;
533                 /* set flow control */
534                 val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
535
536                 if (pause->rx_pause)
537                         netxen_gb_rx_flowctl(val);
538                 else
539                         netxen_gb_unset_rx_flowctl(val);
540
541                 NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
542                                 val);
543                 /* set autoneg */
544                 val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
545                 switch (port) {
546                         case 0:
547                                 if (pause->tx_pause)
548                                         netxen_gb_unset_gb0_mask(val);
549                                 else
550                                         netxen_gb_set_gb0_mask(val);
551                                 break;
552                         case 1:
553                                 if (pause->tx_pause)
554                                         netxen_gb_unset_gb1_mask(val);
555                                 else
556                                         netxen_gb_set_gb1_mask(val);
557                                 break;
558                         case 2:
559                                 if (pause->tx_pause)
560                                         netxen_gb_unset_gb2_mask(val);
561                                 else
562                                         netxen_gb_set_gb2_mask(val);
563                                 break;
564                         case 3:
565                         default:
566                                 if (pause->tx_pause)
567                                         netxen_gb_unset_gb3_mask(val);
568                                 else
569                                         netxen_gb_set_gb3_mask(val);
570                                 break;
571                 }
572                 NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
573         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
574                 if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
575                         return -EIO;
576                 val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
577                 if (port == 0) {
578                         if (pause->tx_pause)
579                                 netxen_xg_unset_xg0_mask(val);
580                         else
581                                 netxen_xg_set_xg0_mask(val);
582                 } else {
583                         if (pause->tx_pause)
584                                 netxen_xg_unset_xg1_mask(val);
585                         else
586                                 netxen_xg_set_xg1_mask(val);
587                 }
588                 NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
589         } else {
590                 printk(KERN_ERR "%s: Unknown board type: %x\n",
591                                 netxen_nic_driver_name,
592                                 adapter->ahw.port_type);
593         }
594         return 0;
595 }
596
597 static int netxen_nic_reg_test(struct net_device *dev)
598 {
599         struct netxen_adapter *adapter = netdev_priv(dev);
600         u32 data_read, data_written;
601
602         data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
603         if ((data_read & 0xffff) != adapter->pdev->vendor)
604                 return 1;
605
606         if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
607                 return 0;
608
609         data_written = (u32)0xa5a5a5a5;
610
611         NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
612         data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
613         if (data_written != data_read)
614                 return 1;
615
616         return 0;
617 }
618
619 static int netxen_get_sset_count(struct net_device *dev, int sset)
620 {
621         switch (sset) {
622         case ETH_SS_TEST:
623                 return NETXEN_NIC_TEST_LEN;
624         case ETH_SS_STATS:
625                 return NETXEN_NIC_STATS_LEN;
626         default:
627                 return -EOPNOTSUPP;
628         }
629 }
630
631 static void
632 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
633                      u64 * data)
634 {
635         memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
636         if ((data[0] = netxen_nic_reg_test(dev)))
637                 eth_test->flags |= ETH_TEST_FL_FAILED;
638         /* link test */
639         if ((data[1] = (u64) netxen_nic_test_link(dev)))
640                 eth_test->flags |= ETH_TEST_FL_FAILED;
641 }
642
643 static void
644 netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
645 {
646         int index;
647
648         switch (stringset) {
649         case ETH_SS_TEST:
650                 memcpy(data, *netxen_nic_gstrings_test,
651                        NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
652                 break;
653         case ETH_SS_STATS:
654                 for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
655                         memcpy(data + index * ETH_GSTRING_LEN,
656                                netxen_nic_gstrings_stats[index].stat_string,
657                                ETH_GSTRING_LEN);
658                 }
659                 break;
660         }
661 }
662
663 static void
664 netxen_nic_get_ethtool_stats(struct net_device *dev,
665                              struct ethtool_stats *stats, u64 * data)
666 {
667         struct netxen_adapter *adapter = netdev_priv(dev);
668         int index;
669
670         for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
671                 char *p =
672                     (char *)adapter +
673                     netxen_nic_gstrings_stats[index].stat_offset;
674                 data[index] =
675                     (netxen_nic_gstrings_stats[index].sizeof_stat ==
676                      sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
677         }
678 }
679
680 static void
681 netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
682 {
683         struct netxen_adapter *adapter = netdev_priv(dev);
684         u32 wol_cfg = 0;
685
686         wol->supported = 0;
687         wol->wolopts = 0;
688
689         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
690                 return;
691
692         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
693         if (wol_cfg & (1UL << adapter->portnum))
694                 wol->supported |= WAKE_MAGIC;
695
696         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
697         if (wol_cfg & (1UL << adapter->portnum))
698                 wol->wolopts |= WAKE_MAGIC;
699 }
700
701 static int
702 netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
703 {
704         struct netxen_adapter *adapter = netdev_priv(dev);
705         u32 wol_cfg = 0;
706
707         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
708                 return -EOPNOTSUPP;
709
710         if (wol->wolopts & ~WAKE_MAGIC)
711                 return -EOPNOTSUPP;
712
713         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
714         if (!(wol_cfg & (1 << adapter->portnum)))
715                 return -EOPNOTSUPP;
716
717         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
718         if (wol->wolopts & WAKE_MAGIC)
719                 wol_cfg |= 1UL << adapter->portnum;
720         else
721                 wol_cfg &= ~(1UL << adapter->portnum);
722         NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
723
724         return 0;
725 }
726
727 /*
728  * Set the coalescing parameters. Currently only normal is supported.
729  * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
730  * firmware coalescing to default.
731  */
732 static int netxen_set_intr_coalesce(struct net_device *netdev,
733                         struct ethtool_coalesce *ethcoal)
734 {
735         struct netxen_adapter *adapter = netdev_priv(netdev);
736
737         if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
738                 return -EINVAL;
739
740         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
741                 return -EINVAL;
742
743         /*
744         * Return Error if unsupported values or
745         * unsupported parameters are set.
746         */
747         if (ethcoal->rx_coalesce_usecs > 0xffff ||
748                 ethcoal->rx_max_coalesced_frames > 0xffff ||
749                 ethcoal->tx_coalesce_usecs > 0xffff ||
750                 ethcoal->tx_max_coalesced_frames > 0xffff ||
751                 ethcoal->rx_coalesce_usecs_irq ||
752                 ethcoal->rx_max_coalesced_frames_irq ||
753                 ethcoal->tx_coalesce_usecs_irq ||
754                 ethcoal->tx_max_coalesced_frames_irq ||
755                 ethcoal->stats_block_coalesce_usecs ||
756                 ethcoal->use_adaptive_rx_coalesce ||
757                 ethcoal->use_adaptive_tx_coalesce ||
758                 ethcoal->pkt_rate_low ||
759                 ethcoal->rx_coalesce_usecs_low ||
760                 ethcoal->rx_max_coalesced_frames_low ||
761                 ethcoal->tx_coalesce_usecs_low ||
762                 ethcoal->tx_max_coalesced_frames_low ||
763                 ethcoal->pkt_rate_high ||
764                 ethcoal->rx_coalesce_usecs_high ||
765                 ethcoal->rx_max_coalesced_frames_high ||
766                 ethcoal->tx_coalesce_usecs_high ||
767                 ethcoal->tx_max_coalesced_frames_high)
768                 return -EINVAL;
769
770         if (!ethcoal->rx_coalesce_usecs ||
771                 !ethcoal->rx_max_coalesced_frames) {
772                 adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
773                 adapter->coal.normal.data.rx_time_us =
774                         NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
775                 adapter->coal.normal.data.rx_packets =
776                         NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
777         } else {
778                 adapter->coal.flags = 0;
779                 adapter->coal.normal.data.rx_time_us =
780                 ethcoal->rx_coalesce_usecs;
781                 adapter->coal.normal.data.rx_packets =
782                 ethcoal->rx_max_coalesced_frames;
783         }
784         adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
785         adapter->coal.normal.data.tx_packets =
786         ethcoal->tx_max_coalesced_frames;
787
788         netxen_config_intr_coalesce(adapter);
789
790         return 0;
791 }
792
793 static int netxen_get_intr_coalesce(struct net_device *netdev,
794                         struct ethtool_coalesce *ethcoal)
795 {
796         struct netxen_adapter *adapter = netdev_priv(netdev);
797
798         if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
799                 return -EINVAL;
800
801         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
802                 return -EINVAL;
803
804         ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
805         ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
806         ethcoal->rx_max_coalesced_frames =
807                 adapter->coal.normal.data.rx_packets;
808         ethcoal->tx_max_coalesced_frames =
809                 adapter->coal.normal.data.tx_packets;
810
811         return 0;
812 }
813
814 const struct ethtool_ops netxen_nic_ethtool_ops = {
815         .get_settings = netxen_nic_get_settings,
816         .set_settings = netxen_nic_set_settings,
817         .get_drvinfo = netxen_nic_get_drvinfo,
818         .get_regs_len = netxen_nic_get_regs_len,
819         .get_regs = netxen_nic_get_regs,
820         .get_link = ethtool_op_get_link,
821         .get_eeprom_len = netxen_nic_get_eeprom_len,
822         .get_eeprom = netxen_nic_get_eeprom,
823         .get_ringparam = netxen_nic_get_ringparam,
824         .set_ringparam = netxen_nic_set_ringparam,
825         .get_pauseparam = netxen_nic_get_pauseparam,
826         .set_pauseparam = netxen_nic_set_pauseparam,
827         .get_wol = netxen_nic_get_wol,
828         .set_wol = netxen_nic_set_wol,
829         .self_test = netxen_nic_diag_test,
830         .get_strings = netxen_nic_get_strings,
831         .get_ethtool_stats = netxen_nic_get_ethtool_stats,
832         .get_sset_count = netxen_get_sset_count,
833         .get_coalesce = netxen_get_intr_coalesce,
834         .set_coalesce = netxen_set_intr_coalesce,
835 };