netxen: separate register and memory access lock
[linux-2.6.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 LICENSE.
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 42
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                 ecmd->speed = 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                         ecmd->speed = 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                         ecmd->speed = P3_LINK_SPEED_MHZ *
150                                         P3_LINK_SPEED_VAL(pcifn, val);
151                 } else
152                         ecmd->speed = 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->autoneg = AUTONEG_ENABLE;
218                         ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
219                         ecmd->advertising |=
220                                 (ADVERTISED_TP | ADVERTISED_Autoneg);
221                         ecmd->port = PORT_TP;
222                 }
223                 break;
224         default:
225                 printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
226                                 adapter->ahw.board_type);
227                 return -EIO;
228         }
229
230         if (check_sfp_module) {
231                 switch (adapter->module_type) {
232                 case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
233                 case LINKEVENT_MODULE_OPTICAL_SRLR:
234                 case LINKEVENT_MODULE_OPTICAL_LRM:
235                 case LINKEVENT_MODULE_OPTICAL_SFP_1G:
236                         ecmd->port = PORT_FIBRE;
237                         break;
238                 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
239                 case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
240                 case LINKEVENT_MODULE_TWINAX:
241                         ecmd->port = PORT_TP;
242                         break;
243                 default:
244                         ecmd->port = -1;
245                 }
246         }
247
248         return 0;
249 }
250
251 static int
252 netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
253 {
254         struct netxen_adapter *adapter = netdev_priv(dev);
255         __u32 status;
256
257         /* read which mode */
258         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
259                 /* autonegotiation */
260                 if (adapter->phy_write
261                     && adapter->phy_write(adapter,
262                                           NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
263                                           ecmd->autoneg) != 0)
264                         return -EIO;
265                 else
266                         adapter->link_autoneg = ecmd->autoneg;
267
268                 if (adapter->phy_read
269                     && adapter->phy_read(adapter,
270                                          NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
271                                          &status) != 0)
272                         return -EIO;
273
274                 /* speed */
275                 switch (ecmd->speed) {
276                 case SPEED_10:
277                         netxen_set_phy_speed(status, 0);
278                         break;
279                 case SPEED_100:
280                         netxen_set_phy_speed(status, 1);
281                         break;
282                 case SPEED_1000:
283                         netxen_set_phy_speed(status, 2);
284                         break;
285                 }
286                 /* set duplex mode */
287                 if (ecmd->duplex == DUPLEX_HALF)
288                         netxen_clear_phy_duplex(status);
289                 if (ecmd->duplex == DUPLEX_FULL)
290                         netxen_set_phy_duplex(status);
291                 if (adapter->phy_write
292                     && adapter->phy_write(adapter,
293                                           NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
294                                           *((int *)&status)) != 0)
295                         return -EIO;
296                 else {
297                         adapter->link_speed = ecmd->speed;
298                         adapter->link_duplex = ecmd->duplex;
299                 }
300         } else
301                 return -EOPNOTSUPP;
302
303         if (!netif_running(dev))
304                 return 0;
305
306         dev->netdev_ops->ndo_stop(dev);
307         return dev->netdev_ops->ndo_open(dev);
308 }
309
310 static int netxen_nic_get_regs_len(struct net_device *dev)
311 {
312         return NETXEN_NIC_REGS_LEN;
313 }
314
315 struct netxen_niu_regs {
316         __u32 reg[NETXEN_NIC_REGS_COUNT];
317 };
318
319 static struct netxen_niu_regs niu_registers[] = {
320         {
321          /* GB Mode */
322          {
323           NETXEN_NIU_GB_SERDES_RESET,
324           NETXEN_NIU_GB0_MII_MODE,
325           NETXEN_NIU_GB1_MII_MODE,
326           NETXEN_NIU_GB2_MII_MODE,
327           NETXEN_NIU_GB3_MII_MODE,
328           NETXEN_NIU_GB0_GMII_MODE,
329           NETXEN_NIU_GB1_GMII_MODE,
330           NETXEN_NIU_GB2_GMII_MODE,
331           NETXEN_NIU_GB3_GMII_MODE,
332           NETXEN_NIU_REMOTE_LOOPBACK,
333           NETXEN_NIU_GB0_HALF_DUPLEX,
334           NETXEN_NIU_GB1_HALF_DUPLEX,
335           NETXEN_NIU_RESET_SYS_FIFOS,
336           NETXEN_NIU_GB_CRC_DROP,
337           NETXEN_NIU_GB_DROP_WRONGADDR,
338           NETXEN_NIU_TEST_MUX_CTL,
339
340           NETXEN_NIU_GB_MAC_CONFIG_0(0),
341           NETXEN_NIU_GB_MAC_CONFIG_1(0),
342           NETXEN_NIU_GB_HALF_DUPLEX_CTRL(0),
343           NETXEN_NIU_GB_MAX_FRAME_SIZE(0),
344           NETXEN_NIU_GB_TEST_REG(0),
345           NETXEN_NIU_GB_MII_MGMT_CONFIG(0),
346           NETXEN_NIU_GB_MII_MGMT_COMMAND(0),
347           NETXEN_NIU_GB_MII_MGMT_ADDR(0),
348           NETXEN_NIU_GB_MII_MGMT_CTRL(0),
349           NETXEN_NIU_GB_MII_MGMT_STATUS(0),
350           NETXEN_NIU_GB_MII_MGMT_INDICATE(0),
351           NETXEN_NIU_GB_INTERFACE_CTRL(0),
352           NETXEN_NIU_GB_INTERFACE_STATUS(0),
353           NETXEN_NIU_GB_STATION_ADDR_0(0),
354           NETXEN_NIU_GB_STATION_ADDR_1(0),
355           -1,
356           }
357          },
358         {
359          /* XG Mode */
360          {
361           NETXEN_NIU_XG_SINGLE_TERM,
362           NETXEN_NIU_XG_DRIVE_HI,
363           NETXEN_NIU_XG_DRIVE_LO,
364           NETXEN_NIU_XG_DTX,
365           NETXEN_NIU_XG_DEQ,
366           NETXEN_NIU_XG_WORD_ALIGN,
367           NETXEN_NIU_XG_RESET,
368           NETXEN_NIU_XG_POWER_DOWN,
369           NETXEN_NIU_XG_RESET_PLL,
370           NETXEN_NIU_XG_SERDES_LOOPBACK,
371           NETXEN_NIU_XG_DO_BYTE_ALIGN,
372           NETXEN_NIU_XG_TX_ENABLE,
373           NETXEN_NIU_XG_RX_ENABLE,
374           NETXEN_NIU_XG_STATUS,
375           NETXEN_NIU_XG_PAUSE_THRESHOLD,
376           NETXEN_NIU_XGE_CONFIG_0,
377           NETXEN_NIU_XGE_CONFIG_1,
378           NETXEN_NIU_XGE_IPG,
379           NETXEN_NIU_XGE_STATION_ADDR_0_HI,
380           NETXEN_NIU_XGE_STATION_ADDR_0_1,
381           NETXEN_NIU_XGE_STATION_ADDR_1_LO,
382           NETXEN_NIU_XGE_STATUS,
383           NETXEN_NIU_XGE_MAX_FRAME_SIZE,
384           NETXEN_NIU_XGE_PAUSE_FRAME_VALUE,
385           NETXEN_NIU_XGE_TX_BYTE_CNT,
386           NETXEN_NIU_XGE_TX_FRAME_CNT,
387           NETXEN_NIU_XGE_RX_BYTE_CNT,
388           NETXEN_NIU_XGE_RX_FRAME_CNT,
389           NETXEN_NIU_XGE_AGGR_ERROR_CNT,
390           NETXEN_NIU_XGE_MULTICAST_FRAME_CNT,
391           NETXEN_NIU_XGE_UNICAST_FRAME_CNT,
392           NETXEN_NIU_XGE_CRC_ERROR_CNT,
393           NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR,
394           NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR,
395           NETXEN_NIU_XGE_LOCAL_ERROR_CNT,
396           NETXEN_NIU_XGE_REMOTE_ERROR_CNT,
397           NETXEN_NIU_XGE_CONTROL_CHAR_CNT,
398           NETXEN_NIU_XGE_PAUSE_FRAME_CNT,
399           -1,
400           }
401          }
402 };
403
404 static void
405 netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
406 {
407         struct netxen_adapter *adapter = netdev_priv(dev);
408         __u32 mode, *regs_buff = p;
409         int i, window;
410
411         memset(p, 0, NETXEN_NIC_REGS_LEN);
412         regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
413             (adapter->pdev)->device;
414         /* which mode */
415         regs_buff[0] = NXRD32(adapter, NETXEN_NIU_MODE);
416         mode = regs_buff[0];
417
418         /* Common registers to all the modes */
419         regs_buff[2] = NXRD32(adapter, NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER);
420         /* GB/XGB Mode */
421         mode = (mode / 2) - 1;
422         window = 0;
423         if (mode <= 1) {
424                 for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) {
425                         /* GB: port specific registers */
426                         if (mode == 0 && i >= 19)
427                                 window = adapter->physical_port *
428                                         NETXEN_NIC_PORT_WINDOW;
429
430                         regs_buff[i] = NXRD32(adapter,
431                                 niu_registers[mode].reg[i - 3] + window);
432                 }
433
434         }
435 }
436
437 static u32 netxen_nic_test_link(struct net_device *dev)
438 {
439         struct netxen_adapter *adapter = netdev_priv(dev);
440         __u32 status;
441         int val;
442
443         /* read which mode */
444         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
445                 if (adapter->phy_read
446                     && adapter->phy_read(adapter,
447                                          NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
448                                          &status) != 0)
449                         return -EIO;
450                 else {
451                         val = netxen_get_phy_link(status);
452                         return !val;
453                 }
454         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
455                 val = NXRD32(adapter, CRB_XG_STATE);
456                 return (val == XG_LINK_UP) ? 0 : 1;
457         }
458         return -EIO;
459 }
460
461 static int
462 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
463                       u8 * bytes)
464 {
465         struct netxen_adapter *adapter = netdev_priv(dev);
466         int offset;
467         int ret;
468
469         if (eeprom->len == 0)
470                 return -EINVAL;
471
472         eeprom->magic = (adapter->pdev)->vendor |
473                         ((adapter->pdev)->device << 16);
474         offset = eeprom->offset;
475
476         ret = netxen_rom_fast_read_words(adapter, offset, bytes,
477                                                 eeprom->len);
478         if (ret < 0)
479                 return ret;
480
481         return 0;
482 }
483
484 static void
485 netxen_nic_get_ringparam(struct net_device *dev,
486                 struct ethtool_ringparam *ring)
487 {
488         struct netxen_adapter *adapter = netdev_priv(dev);
489
490         ring->rx_pending = adapter->num_rxd;
491         ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
492         ring->rx_jumbo_pending += adapter->num_lro_rxd;
493         ring->tx_pending = adapter->num_txd;
494
495         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
496                 ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
497                 ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
498         } else {
499                 ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
500                 ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
501         }
502
503         ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
504
505         ring->rx_mini_max_pending = 0;
506         ring->rx_mini_pending = 0;
507 }
508
509 static u32
510 netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
511 {
512         u32 num_desc;
513         num_desc = max(val, min);
514         num_desc = min(num_desc, max);
515         num_desc = roundup_pow_of_two(num_desc);
516
517         if (val != num_desc) {
518                 printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
519                        netxen_nic_driver_name, r_name, num_desc, val);
520         }
521
522         return num_desc;
523 }
524
525 static int
526 netxen_nic_set_ringparam(struct net_device *dev,
527                 struct ethtool_ringparam *ring)
528 {
529         struct netxen_adapter *adapter = netdev_priv(dev);
530         u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
531         u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
532         u16 num_rxd, num_jumbo_rxd, num_txd;
533
534         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
535                 return -EOPNOTSUPP;
536
537         if (ring->rx_mini_pending)
538                 return -EOPNOTSUPP;
539
540         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
541                 max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
542                 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
543         }
544
545         num_rxd = netxen_validate_ringparam(ring->rx_pending,
546                         MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
547
548         num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
549                         MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
550
551         num_txd = netxen_validate_ringparam(ring->tx_pending,
552                         MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
553
554         if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
555                         num_jumbo_rxd == adapter->num_jumbo_rxd)
556                 return 0;
557
558         adapter->num_rxd = num_rxd;
559         adapter->num_jumbo_rxd = num_jumbo_rxd;
560         adapter->num_txd = num_txd;
561
562         return netxen_nic_reset_context(adapter);
563 }
564
565 static void
566 netxen_nic_get_pauseparam(struct net_device *dev,
567                           struct ethtool_pauseparam *pause)
568 {
569         struct netxen_adapter *adapter = netdev_priv(dev);
570         __u32 val;
571         int port = adapter->physical_port;
572
573         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
574                 if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
575                         return;
576                 /* get flow control settings */
577                 val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
578                 pause->rx_pause = netxen_gb_get_rx_flowctl(val);
579                 val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
580                 switch (port) {
581                         case 0:
582                                 pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
583                                 break;
584                         case 1:
585                                 pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
586                                 break;
587                         case 2:
588                                 pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
589                                 break;
590                         case 3:
591                         default:
592                                 pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
593                                 break;
594                 }
595         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
596                 if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
597                         return;
598                 pause->rx_pause = 1;
599                 val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
600                 if (port == 0)
601                         pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
602                 else
603                         pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
604         } else {
605                 printk(KERN_ERR"%s: Unknown board type: %x\n",
606                                 netxen_nic_driver_name, adapter->ahw.port_type);
607         }
608 }
609
610 static int
611 netxen_nic_set_pauseparam(struct net_device *dev,
612                           struct ethtool_pauseparam *pause)
613 {
614         struct netxen_adapter *adapter = netdev_priv(dev);
615         __u32 val;
616         int port = adapter->physical_port;
617         /* read mode */
618         if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
619                 if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
620                         return -EIO;
621                 /* set flow control */
622                 val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
623
624                 if (pause->rx_pause)
625                         netxen_gb_rx_flowctl(val);
626                 else
627                         netxen_gb_unset_rx_flowctl(val);
628
629                 NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
630                                 val);
631                 /* set autoneg */
632                 val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
633                 switch (port) {
634                         case 0:
635                                 if (pause->tx_pause)
636                                         netxen_gb_unset_gb0_mask(val);
637                                 else
638                                         netxen_gb_set_gb0_mask(val);
639                                 break;
640                         case 1:
641                                 if (pause->tx_pause)
642                                         netxen_gb_unset_gb1_mask(val);
643                                 else
644                                         netxen_gb_set_gb1_mask(val);
645                                 break;
646                         case 2:
647                                 if (pause->tx_pause)
648                                         netxen_gb_unset_gb2_mask(val);
649                                 else
650                                         netxen_gb_set_gb2_mask(val);
651                                 break;
652                         case 3:
653                         default:
654                                 if (pause->tx_pause)
655                                         netxen_gb_unset_gb3_mask(val);
656                                 else
657                                         netxen_gb_set_gb3_mask(val);
658                                 break;
659                 }
660                 NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
661         } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
662                 if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
663                         return -EIO;
664                 val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
665                 if (port == 0) {
666                         if (pause->tx_pause)
667                                 netxen_xg_unset_xg0_mask(val);
668                         else
669                                 netxen_xg_set_xg0_mask(val);
670                 } else {
671                         if (pause->tx_pause)
672                                 netxen_xg_unset_xg1_mask(val);
673                         else
674                                 netxen_xg_set_xg1_mask(val);
675                 }
676                 NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
677         } else {
678                 printk(KERN_ERR "%s: Unknown board type: %x\n",
679                                 netxen_nic_driver_name,
680                                 adapter->ahw.port_type);
681         }
682         return 0;
683 }
684
685 static int netxen_nic_reg_test(struct net_device *dev)
686 {
687         struct netxen_adapter *adapter = netdev_priv(dev);
688         u32 data_read, data_written;
689
690         data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
691         if ((data_read & 0xffff) != PHAN_VENDOR_ID)
692         return 1;
693
694         data_written = (u32)0xa5a5a5a5;
695
696         NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
697         data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
698         if (data_written != data_read)
699                 return 1;
700
701         return 0;
702 }
703
704 static int netxen_get_sset_count(struct net_device *dev, int sset)
705 {
706         switch (sset) {
707         case ETH_SS_TEST:
708                 return NETXEN_NIC_TEST_LEN;
709         case ETH_SS_STATS:
710                 return NETXEN_NIC_STATS_LEN;
711         default:
712                 return -EOPNOTSUPP;
713         }
714 }
715
716 static void
717 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
718                      u64 * data)
719 {
720         memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
721         if ((data[0] = netxen_nic_reg_test(dev)))
722                 eth_test->flags |= ETH_TEST_FL_FAILED;
723         /* link test */
724         if ((data[1] = (u64) netxen_nic_test_link(dev)))
725                 eth_test->flags |= ETH_TEST_FL_FAILED;
726 }
727
728 static void
729 netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
730 {
731         int index;
732
733         switch (stringset) {
734         case ETH_SS_TEST:
735                 memcpy(data, *netxen_nic_gstrings_test,
736                        NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
737                 break;
738         case ETH_SS_STATS:
739                 for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
740                         memcpy(data + index * ETH_GSTRING_LEN,
741                                netxen_nic_gstrings_stats[index].stat_string,
742                                ETH_GSTRING_LEN);
743                 }
744                 break;
745         }
746 }
747
748 static void
749 netxen_nic_get_ethtool_stats(struct net_device *dev,
750                              struct ethtool_stats *stats, u64 * data)
751 {
752         struct netxen_adapter *adapter = netdev_priv(dev);
753         int index;
754
755         for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
756                 char *p =
757                     (char *)adapter +
758                     netxen_nic_gstrings_stats[index].stat_offset;
759                 data[index] =
760                     (netxen_nic_gstrings_stats[index].sizeof_stat ==
761                      sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
762         }
763 }
764
765 static u32 netxen_nic_get_rx_csum(struct net_device *dev)
766 {
767         struct netxen_adapter *adapter = netdev_priv(dev);
768         return adapter->rx_csum;
769 }
770
771 static int netxen_nic_set_rx_csum(struct net_device *dev, u32 data)
772 {
773         struct netxen_adapter *adapter = netdev_priv(dev);
774         adapter->rx_csum = !!data;
775         return 0;
776 }
777
778 static u32 netxen_nic_get_tso(struct net_device *dev)
779 {
780         struct netxen_adapter *adapter = netdev_priv(dev);
781
782         if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
783                 return (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) != 0;
784
785         return (dev->features & NETIF_F_TSO) != 0;
786 }
787
788 static int netxen_nic_set_tso(struct net_device *dev, u32 data)
789 {
790         if (data) {
791                 struct netxen_adapter *adapter = netdev_priv(dev);
792
793                 dev->features |= NETIF_F_TSO;
794                 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
795                         dev->features |= NETIF_F_TSO6;
796         } else
797                 dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
798
799         return 0;
800 }
801
802 static void
803 netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
804 {
805         struct netxen_adapter *adapter = netdev_priv(dev);
806         u32 wol_cfg = 0;
807
808         wol->supported = 0;
809         wol->wolopts = 0;
810
811         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
812                 return;
813
814         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
815         if (wol_cfg & (1UL << adapter->portnum))
816                 wol->supported |= WAKE_MAGIC;
817
818         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
819         if (wol_cfg & (1UL << adapter->portnum))
820                 wol->wolopts |= WAKE_MAGIC;
821 }
822
823 static int
824 netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
825 {
826         struct netxen_adapter *adapter = netdev_priv(dev);
827         u32 wol_cfg = 0;
828
829         if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
830                 return -EOPNOTSUPP;
831
832         if (wol->wolopts & ~WAKE_MAGIC)
833                 return -EOPNOTSUPP;
834
835         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
836         if (!(wol_cfg & (1 << adapter->portnum)))
837                 return -EOPNOTSUPP;
838
839         wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
840         if (wol->wolopts & WAKE_MAGIC)
841                 wol_cfg |= 1UL << adapter->portnum;
842         else
843                 wol_cfg &= ~(1UL << adapter->portnum);
844         NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
845
846         return 0;
847 }
848
849 /*
850  * Set the coalescing parameters. Currently only normal is supported.
851  * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
852  * firmware coalescing to default.
853  */
854 static int netxen_set_intr_coalesce(struct net_device *netdev,
855                         struct ethtool_coalesce *ethcoal)
856 {
857         struct netxen_adapter *adapter = netdev_priv(netdev);
858
859         if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
860                 return -EINVAL;
861
862         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
863                 return -EINVAL;
864
865         /*
866         * Return Error if unsupported values or
867         * unsupported parameters are set.
868         */
869         if (ethcoal->rx_coalesce_usecs > 0xffff ||
870                 ethcoal->rx_max_coalesced_frames > 0xffff ||
871                 ethcoal->tx_coalesce_usecs > 0xffff ||
872                 ethcoal->tx_max_coalesced_frames > 0xffff ||
873                 ethcoal->rx_coalesce_usecs_irq ||
874                 ethcoal->rx_max_coalesced_frames_irq ||
875                 ethcoal->tx_coalesce_usecs_irq ||
876                 ethcoal->tx_max_coalesced_frames_irq ||
877                 ethcoal->stats_block_coalesce_usecs ||
878                 ethcoal->use_adaptive_rx_coalesce ||
879                 ethcoal->use_adaptive_tx_coalesce ||
880                 ethcoal->pkt_rate_low ||
881                 ethcoal->rx_coalesce_usecs_low ||
882                 ethcoal->rx_max_coalesced_frames_low ||
883                 ethcoal->tx_coalesce_usecs_low ||
884                 ethcoal->tx_max_coalesced_frames_low ||
885                 ethcoal->pkt_rate_high ||
886                 ethcoal->rx_coalesce_usecs_high ||
887                 ethcoal->rx_max_coalesced_frames_high ||
888                 ethcoal->tx_coalesce_usecs_high ||
889                 ethcoal->tx_max_coalesced_frames_high)
890                 return -EINVAL;
891
892         if (!ethcoal->rx_coalesce_usecs ||
893                 !ethcoal->rx_max_coalesced_frames) {
894                 adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
895                 adapter->coal.normal.data.rx_time_us =
896                         NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
897                 adapter->coal.normal.data.rx_packets =
898                         NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
899         } else {
900                 adapter->coal.flags = 0;
901                 adapter->coal.normal.data.rx_time_us =
902                 ethcoal->rx_coalesce_usecs;
903                 adapter->coal.normal.data.rx_packets =
904                 ethcoal->rx_max_coalesced_frames;
905         }
906         adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
907         adapter->coal.normal.data.tx_packets =
908         ethcoal->tx_max_coalesced_frames;
909
910         netxen_config_intr_coalesce(adapter);
911
912         return 0;
913 }
914
915 static int netxen_get_intr_coalesce(struct net_device *netdev,
916                         struct ethtool_coalesce *ethcoal)
917 {
918         struct netxen_adapter *adapter = netdev_priv(netdev);
919
920         if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
921                 return -EINVAL;
922
923         if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
924                 return -EINVAL;
925
926         ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
927         ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
928         ethcoal->rx_max_coalesced_frames =
929                 adapter->coal.normal.data.rx_packets;
930         ethcoal->tx_max_coalesced_frames =
931                 adapter->coal.normal.data.tx_packets;
932
933         return 0;
934 }
935
936 static int netxen_nic_set_flags(struct net_device *netdev, u32 data)
937 {
938         struct netxen_adapter *adapter = netdev_priv(netdev);
939         int hw_lro;
940
941         if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
942                 return -EINVAL;
943
944         ethtool_op_set_flags(netdev, data);
945
946         hw_lro = (data & ETH_FLAG_LRO) ? NETXEN_NIC_LRO_ENABLED : 0;
947
948         if (netxen_config_hw_lro(adapter, hw_lro))
949                 return -EIO;
950
951         if ((hw_lro == 0) && netxen_send_lro_cleanup(adapter))
952                 return -EIO;
953
954
955         return 0;
956 }
957
958 const struct ethtool_ops netxen_nic_ethtool_ops = {
959         .get_settings = netxen_nic_get_settings,
960         .set_settings = netxen_nic_set_settings,
961         .get_drvinfo = netxen_nic_get_drvinfo,
962         .get_regs_len = netxen_nic_get_regs_len,
963         .get_regs = netxen_nic_get_regs,
964         .get_link = ethtool_op_get_link,
965         .get_eeprom_len = netxen_nic_get_eeprom_len,
966         .get_eeprom = netxen_nic_get_eeprom,
967         .get_ringparam = netxen_nic_get_ringparam,
968         .set_ringparam = netxen_nic_set_ringparam,
969         .get_pauseparam = netxen_nic_get_pauseparam,
970         .set_pauseparam = netxen_nic_set_pauseparam,
971         .set_tx_csum = ethtool_op_set_tx_csum,
972         .set_sg = ethtool_op_set_sg,
973         .get_tso = netxen_nic_get_tso,
974         .set_tso = netxen_nic_set_tso,
975         .get_wol = netxen_nic_get_wol,
976         .set_wol = netxen_nic_set_wol,
977         .self_test = netxen_nic_diag_test,
978         .get_strings = netxen_nic_get_strings,
979         .get_ethtool_stats = netxen_nic_get_ethtool_stats,
980         .get_sset_count = netxen_get_sset_count,
981         .get_rx_csum = netxen_nic_get_rx_csum,
982         .set_rx_csum = netxen_nic_set_rx_csum,
983         .get_coalesce = netxen_get_intr_coalesce,
984         .set_coalesce = netxen_set_intr_coalesce,
985         .get_flags = ethtool_op_get_flags,
986         .set_flags = netxen_nic_set_flags,
987 };