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