Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2003 - 2009 NetXen, Inc.
0004  * Copyright (C) 2009 - QLogic Corporation.
0005  * All rights reserved.
0006  */
0007 
0008 #include <linux/types.h>
0009 #include <linux/delay.h>
0010 #include <linux/pci.h>
0011 #include <asm/io.h>
0012 #include <linux/netdevice.h>
0013 #include <linux/ethtool.h>
0014 
0015 #include "netxen_nic.h"
0016 #include "netxen_nic_hw.h"
0017 
0018 struct netxen_nic_stats {
0019     char stat_string[ETH_GSTRING_LEN];
0020     int sizeof_stat;
0021     int stat_offset;
0022 };
0023 
0024 #define NETXEN_NIC_STAT(m) sizeof(((struct netxen_adapter *)0)->m), \
0025             offsetof(struct netxen_adapter, m)
0026 
0027 #define NETXEN_NIC_PORT_WINDOW 0x10000
0028 #define NETXEN_NIC_INVALID_DATA 0xDEADBEEF
0029 
0030 static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
0031     {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)},
0032     {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)},
0033     {"rx_dropped", NETXEN_NIC_STAT(stats.rxdropped)},
0034     {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
0035     {"csummed", NETXEN_NIC_STAT(stats.csummed)},
0036     {"rx_pkts", NETXEN_NIC_STAT(stats.rx_pkts)},
0037     {"lro_pkts", NETXEN_NIC_STAT(stats.lro_pkts)},
0038     {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
0039     {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)},
0040 };
0041 
0042 #define NETXEN_NIC_STATS_LEN    ARRAY_SIZE(netxen_nic_gstrings_stats)
0043 
0044 static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
0045     "Register_Test_on_offline",
0046     "Link_Test_on_offline"
0047 };
0048 
0049 #define NETXEN_NIC_TEST_LEN ARRAY_SIZE(netxen_nic_gstrings_test)
0050 
0051 #define NETXEN_NIC_REGS_COUNT 30
0052 #define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32))
0053 #define NETXEN_MAX_EEPROM_LEN   1024
0054 
0055 static int netxen_nic_get_eeprom_len(struct net_device *dev)
0056 {
0057     return NETXEN_FLASH_TOTAL_SIZE;
0058 }
0059 
0060 static void
0061 netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
0062 {
0063     struct netxen_adapter *adapter = netdev_priv(dev);
0064     u32 fw_major = 0;
0065     u32 fw_minor = 0;
0066     u32 fw_build = 0;
0067 
0068     strlcpy(drvinfo->driver, netxen_nic_driver_name,
0069         sizeof(drvinfo->driver));
0070     strlcpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID,
0071         sizeof(drvinfo->version));
0072     fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
0073     fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
0074     fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB);
0075     snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
0076         "%d.%d.%d", fw_major, fw_minor, fw_build);
0077 
0078     strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
0079         sizeof(drvinfo->bus_info));
0080 }
0081 
0082 static int
0083 netxen_nic_get_link_ksettings(struct net_device *dev,
0084                   struct ethtool_link_ksettings *cmd)
0085 {
0086     struct netxen_adapter *adapter = netdev_priv(dev);
0087     int check_sfp_module = 0;
0088     u32 supported, advertising;
0089 
0090     /* read which mode */
0091     if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
0092         supported = (SUPPORTED_10baseT_Half |
0093                    SUPPORTED_10baseT_Full |
0094                    SUPPORTED_100baseT_Half |
0095                    SUPPORTED_100baseT_Full |
0096                    SUPPORTED_1000baseT_Half |
0097                    SUPPORTED_1000baseT_Full);
0098 
0099         advertising = (ADVERTISED_100baseT_Half |
0100                      ADVERTISED_100baseT_Full |
0101                      ADVERTISED_1000baseT_Half |
0102                      ADVERTISED_1000baseT_Full);
0103 
0104         cmd->base.port = PORT_TP;
0105 
0106         cmd->base.speed = adapter->link_speed;
0107         cmd->base.duplex = adapter->link_duplex;
0108         cmd->base.autoneg = adapter->link_autoneg;
0109 
0110     } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
0111         u32 val;
0112 
0113         val = NXRD32(adapter, NETXEN_PORT_MODE_ADDR);
0114         if (val == NETXEN_PORT_MODE_802_3_AP) {
0115             supported = SUPPORTED_1000baseT_Full;
0116             advertising = ADVERTISED_1000baseT_Full;
0117         } else {
0118             supported = SUPPORTED_10000baseT_Full;
0119             advertising = ADVERTISED_10000baseT_Full;
0120         }
0121 
0122         if (netif_running(dev) && adapter->has_link_events) {
0123             cmd->base.speed = adapter->link_speed;
0124             cmd->base.autoneg = adapter->link_autoneg;
0125             cmd->base.duplex = adapter->link_duplex;
0126             goto skip;
0127         }
0128 
0129         cmd->base.port = PORT_TP;
0130 
0131         if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
0132             u16 pcifn = adapter->ahw.pci_func;
0133 
0134             val = NXRD32(adapter, P3_LINK_SPEED_REG(pcifn));
0135             cmd->base.speed = P3_LINK_SPEED_MHZ *
0136                 P3_LINK_SPEED_VAL(pcifn, val);
0137         } else
0138             cmd->base.speed = SPEED_10000;
0139 
0140         cmd->base.duplex = DUPLEX_FULL;
0141         cmd->base.autoneg = AUTONEG_DISABLE;
0142     } else
0143         return -EIO;
0144 
0145 skip:
0146     cmd->base.phy_address = adapter->physical_port;
0147 
0148     switch (adapter->ahw.board_type) {
0149     case NETXEN_BRDTYPE_P2_SB35_4G:
0150     case NETXEN_BRDTYPE_P2_SB31_2G:
0151     case NETXEN_BRDTYPE_P3_REF_QG:
0152     case NETXEN_BRDTYPE_P3_4_GB:
0153     case NETXEN_BRDTYPE_P3_4_GB_MM:
0154         supported |= SUPPORTED_Autoneg;
0155         advertising |= ADVERTISED_Autoneg;
0156         fallthrough;
0157     case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
0158     case NETXEN_BRDTYPE_P3_10G_CX4:
0159     case NETXEN_BRDTYPE_P3_10G_CX4_LP:
0160     case NETXEN_BRDTYPE_P3_10000_BASE_T:
0161         supported |= SUPPORTED_TP;
0162         advertising |= ADVERTISED_TP;
0163         cmd->base.port = PORT_TP;
0164         cmd->base.autoneg = (adapter->ahw.board_type ==
0165                  NETXEN_BRDTYPE_P2_SB31_10G_CX4) ?
0166             (AUTONEG_DISABLE) : (adapter->link_autoneg);
0167         break;
0168     case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
0169     case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
0170     case NETXEN_BRDTYPE_P3_IMEZ:
0171     case NETXEN_BRDTYPE_P3_XG_LOM:
0172     case NETXEN_BRDTYPE_P3_HMEZ:
0173         supported |= SUPPORTED_MII;
0174         advertising |= ADVERTISED_MII;
0175         cmd->base.port = PORT_MII;
0176         cmd->base.autoneg = AUTONEG_DISABLE;
0177         break;
0178     case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
0179     case NETXEN_BRDTYPE_P3_10G_SFP_CT:
0180     case NETXEN_BRDTYPE_P3_10G_SFP_QT:
0181         advertising |= ADVERTISED_TP;
0182         supported |= SUPPORTED_TP;
0183         check_sfp_module = netif_running(dev) &&
0184             adapter->has_link_events;
0185         fallthrough;
0186     case NETXEN_BRDTYPE_P2_SB31_10G:
0187     case NETXEN_BRDTYPE_P3_10G_XFP:
0188         supported |= SUPPORTED_FIBRE;
0189         advertising |= ADVERTISED_FIBRE;
0190         cmd->base.port = PORT_FIBRE;
0191         cmd->base.autoneg = AUTONEG_DISABLE;
0192         break;
0193     case NETXEN_BRDTYPE_P3_10G_TP:
0194         if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
0195             cmd->base.autoneg = AUTONEG_DISABLE;
0196             supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
0197             advertising |=
0198                 (ADVERTISED_FIBRE | ADVERTISED_TP);
0199             cmd->base.port = PORT_FIBRE;
0200             check_sfp_module = netif_running(dev) &&
0201                 adapter->has_link_events;
0202         } else {
0203             supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
0204             advertising |=
0205                 (ADVERTISED_TP | ADVERTISED_Autoneg);
0206             cmd->base.port = PORT_TP;
0207         }
0208         break;
0209     default:
0210         printk(KERN_ERR "netxen-nic: Unsupported board model %d\n",
0211                 adapter->ahw.board_type);
0212         return -EIO;
0213     }
0214 
0215     if (check_sfp_module) {
0216         switch (adapter->module_type) {
0217         case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
0218         case LINKEVENT_MODULE_OPTICAL_SRLR:
0219         case LINKEVENT_MODULE_OPTICAL_LRM:
0220         case LINKEVENT_MODULE_OPTICAL_SFP_1G:
0221             cmd->base.port = PORT_FIBRE;
0222             break;
0223         case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
0224         case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
0225         case LINKEVENT_MODULE_TWINAX:
0226             cmd->base.port = PORT_TP;
0227             break;
0228         default:
0229             cmd->base.port = -1;
0230         }
0231     }
0232 
0233     if (!netif_running(dev) || !adapter->ahw.linkup) {
0234         cmd->base.duplex = DUPLEX_UNKNOWN;
0235         cmd->base.speed = SPEED_UNKNOWN;
0236     }
0237 
0238     ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
0239                         supported);
0240     ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
0241                         advertising);
0242 
0243     return 0;
0244 }
0245 
0246 static int
0247 netxen_nic_set_link_ksettings(struct net_device *dev,
0248                   const struct ethtool_link_ksettings *cmd)
0249 {
0250     struct netxen_adapter *adapter = netdev_priv(dev);
0251     u32 speed = cmd->base.speed;
0252     int ret;
0253 
0254     if (adapter->ahw.port_type != NETXEN_NIC_GBE)
0255         return -EOPNOTSUPP;
0256 
0257     if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
0258         return -EOPNOTSUPP;
0259 
0260     ret = nx_fw_cmd_set_gbe_port(adapter, speed, cmd->base.duplex,
0261                      cmd->base.autoneg);
0262     if (ret == NX_RCODE_NOT_SUPPORTED)
0263         return -EOPNOTSUPP;
0264     else if (ret)
0265         return -EIO;
0266 
0267     adapter->link_speed = speed;
0268     adapter->link_duplex = cmd->base.duplex;
0269     adapter->link_autoneg = cmd->base.autoneg;
0270 
0271     if (!netif_running(dev))
0272         return 0;
0273 
0274     dev->netdev_ops->ndo_stop(dev);
0275     return dev->netdev_ops->ndo_open(dev);
0276 }
0277 
0278 static int netxen_nic_get_regs_len(struct net_device *dev)
0279 {
0280     return NETXEN_NIC_REGS_LEN;
0281 }
0282 
0283 static void
0284 netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
0285 {
0286     struct netxen_adapter *adapter = netdev_priv(dev);
0287     struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
0288     struct nx_host_sds_ring *sds_ring;
0289     u32 *regs_buff = p;
0290     int ring, i = 0;
0291     int port = adapter->physical_port;
0292 
0293     memset(p, 0, NETXEN_NIC_REGS_LEN);
0294 
0295     regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
0296         (adapter->pdev)->device;
0297 
0298     if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
0299         return;
0300 
0301     regs_buff[i++] = NXRD32(adapter, CRB_CMDPEG_STATE);
0302     regs_buff[i++] = NXRD32(adapter, CRB_RCVPEG_STATE);
0303     regs_buff[i++] = NXRD32(adapter, CRB_FW_CAPABILITIES_1);
0304     regs_buff[i++] = NXRDIO(adapter, adapter->crb_int_state_reg);
0305     regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_REF_COUNT);
0306     regs_buff[i++] = NXRD32(adapter, NX_CRB_DEV_STATE);
0307     regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER);
0308     regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1);
0309     regs_buff[i++] = NXRD32(adapter, NETXEN_PEG_HALT_STATUS2);
0310 
0311     regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_0+0x3c);
0312     regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_1+0x3c);
0313     regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_2+0x3c);
0314     regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_3+0x3c);
0315 
0316     if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
0317 
0318         regs_buff[i++] = NXRD32(adapter, NETXEN_CRB_PEG_NET_4+0x3c);
0319         i += 2;
0320 
0321         regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE_P3);
0322         regs_buff[i++] = le32_to_cpu(*(adapter->tx_ring->hw_consumer));
0323 
0324     } else {
0325         i++;
0326 
0327         regs_buff[i++] = NXRD32(adapter,
0328                     NETXEN_NIU_XGE_CONFIG_0+(0x10000*port));
0329         regs_buff[i++] = NXRD32(adapter,
0330                     NETXEN_NIU_XGE_CONFIG_1+(0x10000*port));
0331 
0332         regs_buff[i++] = NXRD32(adapter, CRB_XG_STATE);
0333         regs_buff[i++] = NXRDIO(adapter,
0334                  adapter->tx_ring->crb_cmd_consumer);
0335     }
0336 
0337     regs_buff[i++] = NXRDIO(adapter, adapter->tx_ring->crb_cmd_producer);
0338 
0339     regs_buff[i++] = NXRDIO(adapter,
0340              recv_ctx->rds_rings[0].crb_rcv_producer);
0341     regs_buff[i++] = NXRDIO(adapter,
0342              recv_ctx->rds_rings[1].crb_rcv_producer);
0343 
0344     regs_buff[i++] = adapter->max_sds_rings;
0345 
0346     for (ring = 0; ring < adapter->max_sds_rings; ring++) {
0347         sds_ring = &(recv_ctx->sds_rings[ring]);
0348         regs_buff[i++] = NXRDIO(adapter,
0349                     sds_ring->crb_sts_consumer);
0350     }
0351 }
0352 
0353 static u32 netxen_nic_test_link(struct net_device *dev)
0354 {
0355     struct netxen_adapter *adapter = netdev_priv(dev);
0356     u32 val, port;
0357 
0358     port = adapter->physical_port;
0359     if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
0360         val = NXRD32(adapter, CRB_XG_STATE_P3);
0361         val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
0362         return (val == XG_LINK_UP_P3) ? 0 : 1;
0363     } else {
0364         val = NXRD32(adapter, CRB_XG_STATE);
0365         val = (val >> port*8) & 0xff;
0366         return (val == XG_LINK_UP) ? 0 : 1;
0367     }
0368 }
0369 
0370 static int
0371 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
0372               u8 *bytes)
0373 {
0374     struct netxen_adapter *adapter = netdev_priv(dev);
0375     int offset;
0376     int ret;
0377 
0378     if (eeprom->len == 0)
0379         return -EINVAL;
0380 
0381     eeprom->magic = (adapter->pdev)->vendor |
0382             ((adapter->pdev)->device << 16);
0383     offset = eeprom->offset;
0384 
0385     ret = netxen_rom_fast_read_words(adapter, offset, bytes,
0386                         eeprom->len);
0387     if (ret < 0)
0388         return ret;
0389 
0390     return 0;
0391 }
0392 
0393 static void
0394 netxen_nic_get_ringparam(struct net_device *dev,
0395              struct ethtool_ringparam *ring,
0396              struct kernel_ethtool_ringparam *kernel_ring,
0397              struct netlink_ext_ack *extack)
0398 {
0399     struct netxen_adapter *adapter = netdev_priv(dev);
0400 
0401     ring->rx_pending = adapter->num_rxd;
0402     ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
0403     ring->rx_jumbo_pending += adapter->num_lro_rxd;
0404     ring->tx_pending = adapter->num_txd;
0405 
0406     if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
0407         ring->rx_max_pending = MAX_RCV_DESCRIPTORS_1G;
0408         ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_1G;
0409     } else {
0410         ring->rx_max_pending = MAX_RCV_DESCRIPTORS_10G;
0411         ring->rx_jumbo_max_pending = MAX_JUMBO_RCV_DESCRIPTORS_10G;
0412     }
0413 
0414     ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
0415 }
0416 
0417 static u32
0418 netxen_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
0419 {
0420     u32 num_desc;
0421     num_desc = max(val, min);
0422     num_desc = min(num_desc, max);
0423     num_desc = roundup_pow_of_two(num_desc);
0424 
0425     if (val != num_desc) {
0426         printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
0427                netxen_nic_driver_name, r_name, num_desc, val);
0428     }
0429 
0430     return num_desc;
0431 }
0432 
0433 static int
0434 netxen_nic_set_ringparam(struct net_device *dev,
0435              struct ethtool_ringparam *ring,
0436              struct kernel_ethtool_ringparam *kernel_ring,
0437              struct netlink_ext_ack *extack)
0438 {
0439     struct netxen_adapter *adapter = netdev_priv(dev);
0440     u16 max_rcv_desc = MAX_RCV_DESCRIPTORS_10G;
0441     u16 max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
0442     u16 num_rxd, num_jumbo_rxd, num_txd;
0443 
0444     if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
0445         return -EOPNOTSUPP;
0446 
0447     if (ring->rx_mini_pending)
0448         return -EOPNOTSUPP;
0449 
0450     if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
0451         max_rcv_desc = MAX_RCV_DESCRIPTORS_1G;
0452         max_jumbo_desc = MAX_JUMBO_RCV_DESCRIPTORS_10G;
0453     }
0454 
0455     num_rxd = netxen_validate_ringparam(ring->rx_pending,
0456             MIN_RCV_DESCRIPTORS, max_rcv_desc, "rx");
0457 
0458     num_jumbo_rxd = netxen_validate_ringparam(ring->rx_jumbo_pending,
0459             MIN_JUMBO_DESCRIPTORS, max_jumbo_desc, "rx jumbo");
0460 
0461     num_txd = netxen_validate_ringparam(ring->tx_pending,
0462             MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
0463 
0464     if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
0465             num_jumbo_rxd == adapter->num_jumbo_rxd)
0466         return 0;
0467 
0468     adapter->num_rxd = num_rxd;
0469     adapter->num_jumbo_rxd = num_jumbo_rxd;
0470     adapter->num_txd = num_txd;
0471 
0472     return netxen_nic_reset_context(adapter);
0473 }
0474 
0475 static void
0476 netxen_nic_get_pauseparam(struct net_device *dev,
0477               struct ethtool_pauseparam *pause)
0478 {
0479     struct netxen_adapter *adapter = netdev_priv(dev);
0480     __u32 val;
0481     int port = adapter->physical_port;
0482 
0483     pause->autoneg = 0;
0484 
0485     if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
0486         if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
0487             return;
0488         /* get flow control settings */
0489         val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
0490         pause->rx_pause = netxen_gb_get_rx_flowctl(val);
0491         val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
0492         switch (port) {
0493         case 0:
0494             pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
0495             break;
0496         case 1:
0497             pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
0498             break;
0499         case 2:
0500             pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
0501             break;
0502         case 3:
0503         default:
0504             pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
0505             break;
0506         }
0507     } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
0508         if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
0509             return;
0510         pause->rx_pause = 1;
0511         val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
0512         if (port == 0)
0513             pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
0514         else
0515             pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
0516     } else {
0517         printk(KERN_ERR"%s: Unknown board type: %x\n",
0518                 netxen_nic_driver_name, adapter->ahw.port_type);
0519     }
0520 }
0521 
0522 static int
0523 netxen_nic_set_pauseparam(struct net_device *dev,
0524               struct ethtool_pauseparam *pause)
0525 {
0526     struct netxen_adapter *adapter = netdev_priv(dev);
0527     __u32 val;
0528     int port = adapter->physical_port;
0529 
0530     /* not supported */
0531     if (pause->autoneg)
0532         return -EINVAL;
0533 
0534     /* read mode */
0535     if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
0536         if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
0537             return -EIO;
0538         /* set flow control */
0539         val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port));
0540 
0541         if (pause->rx_pause)
0542             netxen_gb_rx_flowctl(val);
0543         else
0544             netxen_gb_unset_rx_flowctl(val);
0545 
0546         NXWR32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
0547                 val);
0548         /* set autoneg */
0549         val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
0550         switch (port) {
0551         case 0:
0552             if (pause->tx_pause)
0553                 netxen_gb_unset_gb0_mask(val);
0554             else
0555                 netxen_gb_set_gb0_mask(val);
0556             break;
0557         case 1:
0558             if (pause->tx_pause)
0559                 netxen_gb_unset_gb1_mask(val);
0560             else
0561                 netxen_gb_set_gb1_mask(val);
0562             break;
0563         case 2:
0564             if (pause->tx_pause)
0565                 netxen_gb_unset_gb2_mask(val);
0566             else
0567                 netxen_gb_set_gb2_mask(val);
0568             break;
0569         case 3:
0570         default:
0571             if (pause->tx_pause)
0572                 netxen_gb_unset_gb3_mask(val);
0573             else
0574                 netxen_gb_set_gb3_mask(val);
0575             break;
0576         }
0577         NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
0578     } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
0579         if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
0580             return -EIO;
0581         val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL);
0582         if (port == 0) {
0583             if (pause->tx_pause)
0584                 netxen_xg_unset_xg0_mask(val);
0585             else
0586                 netxen_xg_set_xg0_mask(val);
0587         } else {
0588             if (pause->tx_pause)
0589                 netxen_xg_unset_xg1_mask(val);
0590             else
0591                 netxen_xg_set_xg1_mask(val);
0592         }
0593         NXWR32(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);
0594     } else {
0595         printk(KERN_ERR "%s: Unknown board type: %x\n",
0596                 netxen_nic_driver_name,
0597                 adapter->ahw.port_type);
0598     }
0599     return 0;
0600 }
0601 
0602 static int netxen_nic_reg_test(struct net_device *dev)
0603 {
0604     struct netxen_adapter *adapter = netdev_priv(dev);
0605     u32 data_read, data_written;
0606 
0607     data_read = NXRD32(adapter, NETXEN_PCIX_PH_REG(0));
0608     if ((data_read & 0xffff) != adapter->pdev->vendor)
0609         return 1;
0610 
0611     if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
0612         return 0;
0613 
0614     data_written = (u32)0xa5a5a5a5;
0615 
0616     NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written);
0617     data_read = NXRD32(adapter, CRB_SCRATCHPAD_TEST);
0618     if (data_written != data_read)
0619         return 1;
0620 
0621     return 0;
0622 }
0623 
0624 static int netxen_get_sset_count(struct net_device *dev, int sset)
0625 {
0626     switch (sset) {
0627     case ETH_SS_TEST:
0628         return NETXEN_NIC_TEST_LEN;
0629     case ETH_SS_STATS:
0630         return NETXEN_NIC_STATS_LEN;
0631     default:
0632         return -EOPNOTSUPP;
0633     }
0634 }
0635 
0636 static void
0637 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
0638              u64 *data)
0639 {
0640     memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
0641     if ((data[0] = netxen_nic_reg_test(dev)))
0642         eth_test->flags |= ETH_TEST_FL_FAILED;
0643     /* link test */
0644     if ((data[1] = (u64) netxen_nic_test_link(dev)))
0645         eth_test->flags |= ETH_TEST_FL_FAILED;
0646 }
0647 
0648 static void
0649 netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
0650 {
0651     int index;
0652 
0653     switch (stringset) {
0654     case ETH_SS_TEST:
0655         memcpy(data, *netxen_nic_gstrings_test,
0656                NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN);
0657         break;
0658     case ETH_SS_STATS:
0659         for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
0660             memcpy(data + index * ETH_GSTRING_LEN,
0661                    netxen_nic_gstrings_stats[index].stat_string,
0662                    ETH_GSTRING_LEN);
0663         }
0664         break;
0665     }
0666 }
0667 
0668 static void
0669 netxen_nic_get_ethtool_stats(struct net_device *dev,
0670                  struct ethtool_stats *stats, u64 *data)
0671 {
0672     struct netxen_adapter *adapter = netdev_priv(dev);
0673     int index;
0674 
0675     for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) {
0676         char *p =
0677             (char *)adapter +
0678             netxen_nic_gstrings_stats[index].stat_offset;
0679         data[index] =
0680             (netxen_nic_gstrings_stats[index].sizeof_stat ==
0681              sizeof(u64)) ? *(u64 *) p : *(u32 *) p;
0682     }
0683 }
0684 
0685 static void
0686 netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
0687 {
0688     struct netxen_adapter *adapter = netdev_priv(dev);
0689     u32 wol_cfg = 0;
0690 
0691     wol->supported = 0;
0692     wol->wolopts = 0;
0693 
0694     if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
0695         return;
0696 
0697     wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
0698     if (wol_cfg & (1UL << adapter->portnum))
0699         wol->supported |= WAKE_MAGIC;
0700 
0701     wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
0702     if (wol_cfg & (1UL << adapter->portnum))
0703         wol->wolopts |= WAKE_MAGIC;
0704 }
0705 
0706 static int
0707 netxen_nic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
0708 {
0709     struct netxen_adapter *adapter = netdev_priv(dev);
0710     u32 wol_cfg = 0;
0711 
0712     if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
0713         return -EOPNOTSUPP;
0714 
0715     if (wol->wolopts & ~WAKE_MAGIC)
0716         return -EOPNOTSUPP;
0717 
0718     wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV);
0719     if (!(wol_cfg & (1 << adapter->portnum)))
0720         return -EOPNOTSUPP;
0721 
0722     wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG);
0723     if (wol->wolopts & WAKE_MAGIC)
0724         wol_cfg |= 1UL << adapter->portnum;
0725     else
0726         wol_cfg &= ~(1UL << adapter->portnum);
0727     NXWR32(adapter, NETXEN_WOL_CONFIG, wol_cfg);
0728 
0729     return 0;
0730 }
0731 
0732 /*
0733  * Set the coalescing parameters. Currently only normal is supported.
0734  * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
0735  * firmware coalescing to default.
0736  */
0737 static int netxen_set_intr_coalesce(struct net_device *netdev,
0738                     struct ethtool_coalesce *ethcoal,
0739                     struct kernel_ethtool_coalesce *kernel_coal,
0740                     struct netlink_ext_ack *extack)
0741 {
0742     struct netxen_adapter *adapter = netdev_priv(netdev);
0743 
0744     if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
0745         return -EINVAL;
0746 
0747     if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
0748         return -EINVAL;
0749 
0750     /*
0751     * Return Error if unsupported values or
0752     * unsupported parameters are set.
0753     */
0754     if (ethcoal->rx_coalesce_usecs > 0xffff ||
0755         ethcoal->rx_max_coalesced_frames > 0xffff ||
0756         ethcoal->tx_coalesce_usecs > 0xffff ||
0757         ethcoal->tx_max_coalesced_frames > 0xffff)
0758         return -EINVAL;
0759 
0760     if (!ethcoal->rx_coalesce_usecs ||
0761         !ethcoal->rx_max_coalesced_frames) {
0762         adapter->coal.flags = NETXEN_NIC_INTR_DEFAULT;
0763         adapter->coal.normal.data.rx_time_us =
0764             NETXEN_DEFAULT_INTR_COALESCE_RX_TIME_US;
0765         adapter->coal.normal.data.rx_packets =
0766             NETXEN_DEFAULT_INTR_COALESCE_RX_PACKETS;
0767     } else {
0768         adapter->coal.flags = 0;
0769         adapter->coal.normal.data.rx_time_us =
0770         ethcoal->rx_coalesce_usecs;
0771         adapter->coal.normal.data.rx_packets =
0772         ethcoal->rx_max_coalesced_frames;
0773     }
0774     adapter->coal.normal.data.tx_time_us = ethcoal->tx_coalesce_usecs;
0775     adapter->coal.normal.data.tx_packets =
0776     ethcoal->tx_max_coalesced_frames;
0777 
0778     netxen_config_intr_coalesce(adapter);
0779 
0780     return 0;
0781 }
0782 
0783 static int netxen_get_intr_coalesce(struct net_device *netdev,
0784                     struct ethtool_coalesce *ethcoal,
0785                     struct kernel_ethtool_coalesce *kernel_coal,
0786                     struct netlink_ext_ack *extack)
0787 {
0788     struct netxen_adapter *adapter = netdev_priv(netdev);
0789 
0790     if (!NX_IS_REVISION_P3(adapter->ahw.revision_id))
0791         return -EINVAL;
0792 
0793     if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC)
0794         return -EINVAL;
0795 
0796     ethcoal->rx_coalesce_usecs = adapter->coal.normal.data.rx_time_us;
0797     ethcoal->tx_coalesce_usecs = adapter->coal.normal.data.tx_time_us;
0798     ethcoal->rx_max_coalesced_frames =
0799         adapter->coal.normal.data.rx_packets;
0800     ethcoal->tx_max_coalesced_frames =
0801         adapter->coal.normal.data.tx_packets;
0802 
0803     return 0;
0804 }
0805 
0806 static int
0807 netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
0808 {
0809     struct netxen_adapter *adapter = netdev_priv(netdev);
0810     struct netxen_minidump *mdump = &adapter->mdump;
0811     if (adapter->fw_mdump_rdy)
0812         dump->len = mdump->md_dump_size;
0813     else
0814         dump->len = 0;
0815 
0816     if (!mdump->md_enabled)
0817         dump->flag = ETH_FW_DUMP_DISABLE;
0818     else
0819         dump->flag = mdump->md_capture_mask;
0820 
0821     dump->version = adapter->fw_version;
0822     return 0;
0823 }
0824 
0825 /* Fw dump levels */
0826 static const u32 FW_DUMP_LEVELS[] = { 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
0827 
0828 static int
0829 netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val)
0830 {
0831     int i;
0832     struct netxen_adapter *adapter = netdev_priv(netdev);
0833     struct netxen_minidump *mdump = &adapter->mdump;
0834 
0835     switch (val->flag) {
0836     case NX_FORCE_FW_DUMP_KEY:
0837         if (!mdump->md_enabled) {
0838             netdev_info(netdev, "FW dump not enabled\n");
0839             return 0;
0840         }
0841         if (adapter->fw_mdump_rdy) {
0842             netdev_info(netdev, "Previous dump not cleared, not forcing dump\n");
0843             return 0;
0844         }
0845         netdev_info(netdev, "Forcing a fw dump\n");
0846         nx_dev_request_reset(adapter);
0847         break;
0848     case NX_DISABLE_FW_DUMP:
0849         if (mdump->md_enabled) {
0850             netdev_info(netdev, "Disabling FW Dump\n");
0851             mdump->md_enabled = 0;
0852         }
0853         break;
0854     case NX_ENABLE_FW_DUMP:
0855         if (!mdump->md_enabled) {
0856             netdev_info(netdev, "Enabling FW dump\n");
0857             mdump->md_enabled = 1;
0858         }
0859         break;
0860     case NX_FORCE_FW_RESET:
0861         netdev_info(netdev, "Forcing FW reset\n");
0862         nx_dev_request_reset(adapter);
0863         adapter->flags &= ~NETXEN_FW_RESET_OWNER;
0864         break;
0865     default:
0866         for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) {
0867             if (val->flag == FW_DUMP_LEVELS[i]) {
0868                 mdump->md_capture_mask = val->flag;
0869                 netdev_info(netdev,
0870                     "Driver mask changed to: 0x%x\n",
0871                     mdump->md_capture_mask);
0872                 return 0;
0873             }
0874         }
0875         netdev_info(netdev,
0876             "Invalid dump level: 0x%x\n", val->flag);
0877         return -EINVAL;
0878     }
0879 
0880     return 0;
0881 }
0882 
0883 static int
0884 netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
0885             void *buffer)
0886 {
0887     int i, copy_sz;
0888     u32 *hdr_ptr, *data;
0889     struct netxen_adapter *adapter = netdev_priv(netdev);
0890     struct netxen_minidump *mdump = &adapter->mdump;
0891 
0892 
0893     if (!adapter->fw_mdump_rdy) {
0894         netdev_info(netdev, "Dump not available\n");
0895         return -EINVAL;
0896     }
0897     /* Copy template header first */
0898     copy_sz = mdump->md_template_size;
0899     hdr_ptr = (u32 *) mdump->md_template;
0900     data = buffer;
0901     for (i = 0; i < copy_sz/sizeof(u32); i++)
0902         *data++ = cpu_to_le32(*hdr_ptr++);
0903 
0904     /* Copy captured dump data */
0905     memcpy(buffer + copy_sz,
0906         mdump->md_capture_buff + mdump->md_template_size,
0907             mdump->md_capture_size);
0908     dump->len = copy_sz + mdump->md_capture_size;
0909     dump->flag = mdump->md_capture_mask;
0910 
0911     /* Free dump area once data has been captured */
0912     vfree(mdump->md_capture_buff);
0913     mdump->md_capture_buff = NULL;
0914     adapter->fw_mdump_rdy = 0;
0915     netdev_info(netdev, "extracted the fw dump Successfully\n");
0916     return 0;
0917 }
0918 
0919 const struct ethtool_ops netxen_nic_ethtool_ops = {
0920     .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
0921                      ETHTOOL_COALESCE_MAX_FRAMES,
0922     .get_drvinfo = netxen_nic_get_drvinfo,
0923     .get_regs_len = netxen_nic_get_regs_len,
0924     .get_regs = netxen_nic_get_regs,
0925     .get_link = ethtool_op_get_link,
0926     .get_eeprom_len = netxen_nic_get_eeprom_len,
0927     .get_eeprom = netxen_nic_get_eeprom,
0928     .get_ringparam = netxen_nic_get_ringparam,
0929     .set_ringparam = netxen_nic_set_ringparam,
0930     .get_pauseparam = netxen_nic_get_pauseparam,
0931     .set_pauseparam = netxen_nic_set_pauseparam,
0932     .get_wol = netxen_nic_get_wol,
0933     .set_wol = netxen_nic_set_wol,
0934     .self_test = netxen_nic_diag_test,
0935     .get_strings = netxen_nic_get_strings,
0936     .get_ethtool_stats = netxen_nic_get_ethtool_stats,
0937     .get_sset_count = netxen_get_sset_count,
0938     .get_coalesce = netxen_get_intr_coalesce,
0939     .set_coalesce = netxen_set_intr_coalesce,
0940     .get_dump_flag = netxen_get_dump_flag,
0941     .get_dump_data = netxen_get_dump_data,
0942     .set_dump = netxen_set_dump,
0943     .get_link_ksettings = netxen_nic_get_link_ksettings,
0944     .set_link_ksettings = netxen_nic_set_link_ksettings,
0945 };