Pull ec into release branch
[pandora-kernel.git] / drivers / net / netxen / netxen_nic_ethtool.c
index c381d77..ee1b5a2 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <linux/pci.h>
 #include <asm/io.h>
@@ -81,8 +82,7 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
 #define NETXEN_NIC_STATS_LEN   ARRAY_SIZE(netxen_nic_gstrings_stats)
 
 static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
-       "Register_Test_offline", "EEPROM_Test_offline",
-       "Interrupt_Test_offline", "Loopback_Test_offline",
+       "Register_Test_on_offline",
        "Link_Test_on_offline"
 };
 
@@ -94,17 +94,7 @@ static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = {
 
 static int netxen_nic_get_eeprom_len(struct net_device *dev)
 {
-       struct netxen_port *port = netdev_priv(dev);
-       struct netxen_adapter *adapter = port->adapter;
-       int n;
-
-       if ((netxen_rom_fast_read(adapter, 0, &n) == 0)
-           && (n & NETXEN_ROM_ROUNDUP)) {
-               n &= ~NETXEN_ROM_ROUNDUP;
-               if (n < NETXEN_MAX_EEPROM_LEN)
-                       return n;
-       }
-       return 0;
+       return FLASH_TOTAL_SIZE;
 }
 
 static void
@@ -403,19 +393,12 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
        }
 }
 
-static void
-netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
-{
-       wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
-       /* options can be added depending upon the mode */
-       wol->wolopts = 0;
-}
-
-static u32 netxen_nic_get_link(struct net_device *dev)
+static u32 netxen_nic_test_link(struct net_device *dev)
 {
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
        __u32 status;
+       int val;
 
        /* read which mode */
        if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
@@ -424,11 +407,13 @@ static u32 netxen_nic_get_link(struct net_device *dev)
                                         NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
                                         &status) != 0)
                        return -EIO;
-               else
-                       return (netxen_get_phy_link(status));
+               else {
+                       val = netxen_get_phy_link(status);
+                       return !val;
+               }
        } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
-               int val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
-               return val == XG_LINK_UP;
+               val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+               return (val == XG_LINK_UP) ? 0 : 1;
        }
        return -EIO;
 }
@@ -440,18 +425,94 @@ netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        struct netxen_port *port = netdev_priv(dev);
        struct netxen_adapter *adapter = port->adapter;
        int offset;
+       int ret;
 
        if (eeprom->len == 0)
                return -EINVAL;
 
        eeprom->magic = (port->pdev)->vendor | ((port->pdev)->device << 16);
-       for (offset = 0; offset < eeprom->len; offset++)
-               if (netxen_rom_fast_read
-                   (adapter, (8 * offset) + 8, (int *)eeprom->data) == -1)
-                       return -EIO;
+       offset = eeprom->offset;
+
+       ret = netxen_rom_fast_read_words(adapter, offset, bytes, 
+                                               eeprom->len);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
+static int
+netxen_nic_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+                       u8 * bytes)
+{
+       struct netxen_port *port = netdev_priv(dev);
+       struct netxen_adapter *adapter = port->adapter;
+       int offset = eeprom->offset;
+       static int flash_start;
+       static int ready_to_flash;
+       int ret;
+
+       if (flash_start == 0) {
+               netxen_halt_pegs(adapter);
+               ret = netxen_flash_unlock(adapter);
+               if (ret < 0) {
+                       printk(KERN_ERR "%s: Flash unlock failed.\n",
+                               netxen_nic_driver_name);
+                       return ret;
+               }
+               printk(KERN_INFO "%s: flash unlocked. \n", 
+                       netxen_nic_driver_name);
+               last_schedule_time = jiffies;
+               ret = netxen_flash_erase_secondary(adapter);
+               if (ret != FLASH_SUCCESS) {
+                       printk(KERN_ERR "%s: Flash erase failed.\n", 
+                               netxen_nic_driver_name);
+                       return ret;
+               }
+               printk(KERN_INFO "%s: secondary flash erased successfully.\n", 
+                       netxen_nic_driver_name);
+               flash_start = 1;
+               return 0;
+       }
+
+       if (offset == BOOTLD_START) {
+               ret = netxen_flash_erase_primary(adapter);
+               if (ret != FLASH_SUCCESS) {
+                       printk(KERN_ERR "%s: Flash erase failed.\n", 
+                               netxen_nic_driver_name);
+                       return ret;
+               }
+
+               ret = netxen_rom_se(adapter, USER_START);
+               if (ret != FLASH_SUCCESS)
+                       return ret;
+               ret = netxen_rom_se(adapter, FIXED_START);
+               if (ret != FLASH_SUCCESS)
+                       return ret;
+
+               printk(KERN_INFO "%s: primary flash erased successfully\n", 
+                       netxen_nic_driver_name);
+
+               ret = netxen_backup_crbinit(adapter);
+               if (ret != FLASH_SUCCESS) {
+                       printk(KERN_ERR "%s: CRBinit backup failed.\n", 
+                               netxen_nic_driver_name);
+                       return ret;
+               }
+               printk(KERN_INFO "%s: CRBinit backup done.\n", 
+                       netxen_nic_driver_name);
+               ready_to_flash = 1;
+       }
+
+       if (!ready_to_flash) {
+               printk(KERN_ERR "%s: Invalid write sequence, returning...\n",
+                       netxen_nic_driver_name);
+               return -EINVAL;
+       }
+
+       return netxen_rom_fast_write_words(adapter, offset, bytes, eeprom->len);
+}
+
 static void
 netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
 {
@@ -540,100 +601,21 @@ netxen_nic_set_pauseparam(struct net_device *dev,
 
 static int netxen_nic_reg_test(struct net_device *dev)
 {
-       struct netxen_port *port = netdev_priv(dev);
-       struct netxen_adapter *adapter = port->adapter;
-       u32 data_read, data_written, save;
-       __u32 mode;
-
-       /* 
-        * first test the "Read Only" registers by writing which mode
-        */
-       netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
-       if (netxen_get_niu_enable_ge(mode)) {   /* GB Mode */
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
-                                  &data_read);
-
-               save = data_read;
-               if (data_read)
-                       data_written = data_read & NETXEN_NIC_INVALID_DATA;
-               else
-                       data_written = NETXEN_NIC_INVALID_DATA;
-               netxen_nic_write_w0(adapter,
-                                   NETXEN_NIU_GB_MII_MGMT_STATUS(port->
-                                                                 portnum),
-                                   data_written);
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum),
-                                  &data_read);
-
-               if (data_written == data_read) {
-                       netxen_nic_write_w0(adapter,
-                                           NETXEN_NIU_GB_MII_MGMT_STATUS(port->
-                                                                         portnum),
-                                           save);
-
-                       return 0;
-               }
-
-               /* netxen_niu_gb_mii_mgmt_indicators is read only */
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
-                                                                  portnum),
-                                  &data_read);
-
-               save = data_read;
-               if (data_read)
-                       data_written = data_read & NETXEN_NIC_INVALID_DATA;
-               else
-                       data_written = NETXEN_NIC_INVALID_DATA;
-               netxen_nic_write_w0(adapter,
-                                   NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
-                                                                   portnum),
-                                   data_written);
-
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_MII_MGMT_INDICATE(port->
-                                                                  portnum),
-                                  &data_read);
-
-               if (data_written == data_read) {
-                       netxen_nic_write_w0(adapter,
-                                           NETXEN_NIU_GB_MII_MGMT_INDICATE
-                                           (port->portnum), save);
-                       return 0;
-               }
+       struct netxen_adapter *adapter = netdev_priv(dev);
+       u32 data_read, data_written;
 
-               /* netxen_niu_gb_interface_status is read only */
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_INTERFACE_STATUS(port->
-                                                                 portnum),
-                                  &data_read);
-
-               save = data_read;
-               if (data_read)
-                       data_written = data_read & NETXEN_NIC_INVALID_DATA;
-               else
-                       data_written = NETXEN_NIC_INVALID_DATA;
-               netxen_nic_write_w0(adapter,
-                                   NETXEN_NIU_GB_INTERFACE_STATUS(port->
-                                                                  portnum),
-                                   data_written);
+       netxen_nic_read_w0(adapter, NETXEN_PCIX_PH_REG(0), &data_read);
+       if ((data_read & 0xffff) != PHAN_VENDOR_ID)
+       return 1;
 
-               netxen_nic_read_w0(adapter,
-                                  NETXEN_NIU_GB_INTERFACE_STATUS(port->
-                                                                 portnum),
-                                  &data_read);
+       data_written = (u32)0xa5a5a5a5;
 
-               if (data_written == data_read) {
-                       netxen_nic_write_w0(adapter,
-                                           NETXEN_NIU_GB_INTERFACE_STATUS
-                                           (port->portnum), save);
+       netxen_nic_reg_write(adapter, CRB_SCRATCHPAD_TEST, data_written);
+       data_read = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_SCRATCHPAD_TEST));
+       if (data_written != data_read)
+               return 1;
 
-                       return 0;
-               }
-       }                       /* GB Mode */
-       return 1;
+       return 0;
 }
 
 static int netxen_nic_diag_test_count(struct net_device *dev)
@@ -647,26 +629,20 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 {
        if (eth_test->flags == ETH_TEST_FL_OFFLINE) {   /* offline tests */
                /* link test */
-               if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+               if ((data[1] = (u64) netxen_nic_test_link(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               if (netif_running(dev))
-                       dev->stop(dev);
-
                /* register tests */
-               if (!(data[0] = netxen_nic_reg_test(dev)))
+               if ((data[0] = netxen_nic_reg_test(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
-               /* other tests pass as of now */
-               data[1] = data[2] = data[3] = 1;
-               if (netif_running(dev))
-                       dev->open(dev);
        } else {                /* online tests */
-               /* link test */
-               if (!(data[4] = (u64) netxen_nic_get_link(dev)))
+               /* register tests */
+               if((data[0] = netxen_nic_reg_test(dev)))
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               /* other tests pass by default */
-               data[0] = data[1] = data[2] = data[3] = 1;
+               /* link test */
+               if ((data[1] = (u64) netxen_nic_test_link(dev)))
+                       eth_test->flags |= ETH_TEST_FL_FAILED;
        }
 }
 
@@ -717,10 +693,10 @@ struct ethtool_ops netxen_nic_ethtool_ops = {
        .get_drvinfo = netxen_nic_get_drvinfo,
        .get_regs_len = netxen_nic_get_regs_len,
        .get_regs = netxen_nic_get_regs,
-       .get_wol = netxen_nic_get_wol,
-       .get_link = netxen_nic_get_link,
+       .get_link = ethtool_op_get_link,
        .get_eeprom_len = netxen_nic_get_eeprom_len,
        .get_eeprom = netxen_nic_get_eeprom,
+       .set_eeprom = netxen_nic_set_eeprom,
        .get_ringparam = netxen_nic_get_ringparam,
        .get_pauseparam = netxen_nic_get_pauseparam,
        .set_pauseparam = netxen_nic_set_pauseparam,