]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/s2io.c
drivers/net/wan: Add missing "space"
[linux-2.6-omap-h63xx.git] / drivers / net / s2io.c
index 9d80f1cf73acbbe70a9eb8df62ef6a9c2f6be871..644d71bfb6408fbfe59501b6f751defb9143a8a3 100644 (file)
@@ -84,7 +84,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.26.10"
+#define DRV_VERSION "2.0.26.17"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -335,10 +335,9 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
        {"mc_err_cnt"}
 };
 
-#define S2IO_XENA_STAT_LEN sizeof(ethtool_xena_stats_keys)/ ETH_GSTRING_LEN
-#define S2IO_ENHANCED_STAT_LEN sizeof(ethtool_enhanced_stats_keys)/ \
-                                       ETH_GSTRING_LEN
-#define S2IO_DRIVER_STAT_LEN sizeof(ethtool_driver_stats_keys)/ ETH_GSTRING_LEN
+#define S2IO_XENA_STAT_LEN     ARRAY_SIZE(ethtool_xena_stats_keys)
+#define S2IO_ENHANCED_STAT_LEN ARRAY_SIZE(ethtool_enhanced_stats_keys)
+#define S2IO_DRIVER_STAT_LEN   ARRAY_SIZE(ethtool_driver_stats_keys)
 
 #define XFRAME_I_STAT_LEN (S2IO_XENA_STAT_LEN + S2IO_DRIVER_STAT_LEN )
 #define XFRAME_II_STAT_LEN (XFRAME_I_STAT_LEN + S2IO_ENHANCED_STAT_LEN )
@@ -346,7 +345,7 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
 #define XFRAME_I_STAT_STRINGS_LEN ( XFRAME_I_STAT_LEN * ETH_GSTRING_LEN )
 #define XFRAME_II_STAT_STRINGS_LEN ( XFRAME_II_STAT_LEN * ETH_GSTRING_LEN )
 
-#define S2IO_TEST_LEN  sizeof(s2io_gstrings) / ETH_GSTRING_LEN
+#define S2IO_TEST_LEN  ARRAY_SIZE(s2io_gstrings)
 #define S2IO_STRINGS_LEN       S2IO_TEST_LEN * ETH_GSTRING_LEN
 
 #define S2IO_TIMER_CONF(timer, handle, arg, exp)               \
@@ -2704,9 +2703,6 @@ static int s2io_poll(struct napi_struct *napi, int budget)
        struct XENA_dev_config __iomem *bar0 = nic->bar0;
        int i;
 
-       if (!is_s2io_card_up(nic))
-               return 0;
-
        mac_control = &nic->mac_control;
        config = &nic->config;
 
@@ -3379,6 +3375,9 @@ static void s2io_reset(struct s2io_nic * sp)
        /* Set swapper to enable I/O register access */
        s2io_set_swapper(sp);
 
+       /* restore mac_addr entries */
+       do_s2io_restore_unicast_mc(sp);
+
        /* Restore the MSIX table entries from local variables */
        restore_xmsi_data(sp);
 
@@ -3437,9 +3436,6 @@ static void s2io_reset(struct s2io_nic * sp)
                writeq(val64, &bar0->pcc_err_reg);
        }
 
-       /* restore the previously assigned mac address */
-       do_s2io_prog_unicast(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr);
-
        sp->device_enabled_once = FALSE;
 }
 
@@ -3851,8 +3847,6 @@ static int s2io_open(struct net_device *dev)
        netif_carrier_off(dev);
        sp->last_link_state = 0;
 
-       napi_enable(&sp->napi);
-
        if (sp->config.intr_type == MSI_X) {
                int ret = s2io_enable_msi_x(sp);
 
@@ -3895,7 +3889,6 @@ static int s2io_open(struct net_device *dev)
        return 0;
 
 hw_init_failed:
-       napi_disable(&sp->napi);
        if (sp->config.intr_type == MSI_X) {
                if (sp->entries) {
                        kfree(sp->entries);
@@ -3927,6 +3920,9 @@ hw_init_failed:
 static int s2io_close(struct net_device *dev)
 {
        struct s2io_nic *sp = dev->priv;
+       struct config_param *config = &sp->config;
+       u64 tmp64;
+       int offset;
 
        /* Return if the device is already closed               *
        *  Can happen when s2io_card_up failed in change_mtu    *
@@ -3935,7 +3931,14 @@ static int s2io_close(struct net_device *dev)
                return 0;
 
        netif_stop_queue(dev);
-       napi_disable(&sp->napi);
+
+       /* delete all populated mac entries */
+       for (offset = 1; offset < config->max_mc_addr; offset++) {
+               tmp64 = do_s2io_read_unicast_mc(sp, offset);
+               if (tmp64 != S2IO_DISABLE_MAC_ENTRY)
+                       do_s2io_delete_unicast_mc(sp, tmp64);
+       }
+
        /* Reset card, kill tasklet and free Tx and Rx buffers. */
        s2io_card_down(sp);
 
@@ -4736,8 +4739,9 @@ static void s2io_set_multicast(struct net_device *dev)
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
        u64 val64 = 0, multi_mac = 0x010203040506ULL, mask =
            0xfeffffffffffULL;
-       u64 dis_addr = 0xffffffffffffULL, mac_addr = 0;
+       u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, mac_addr = 0;
        void __iomem *add;
+       struct config_param *config = &sp->config;
 
        if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) {
                /*  Enable all Multicast addresses */
@@ -4747,7 +4751,7 @@ static void s2io_set_multicast(struct net_device *dev)
                       &bar0->rmac_addr_data1_mem);
                val64 = RMAC_ADDR_CMD_MEM_WE |
                    RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-                   RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
+                   RMAC_ADDR_CMD_MEM_OFFSET(config->max_mc_addr - 1);
                writeq(val64, &bar0->rmac_addr_cmd_mem);
                /* Wait till command completes */
                wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
@@ -4755,7 +4759,7 @@ static void s2io_set_multicast(struct net_device *dev)
                                        S2IO_BIT_RESET);
 
                sp->m_cast_flg = 1;
-               sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
+               sp->all_multi_pos = config->max_mc_addr - 1;
        } else if ((dev->flags & IFF_ALLMULTI) && (sp->m_cast_flg)) {
                /*  Disable all Multicast addresses */
                writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
@@ -4824,7 +4828,7 @@ static void s2io_set_multicast(struct net_device *dev)
        /*  Update individual M_CAST address list */
        if ((!sp->m_cast_flg) && dev->mc_count) {
                if (dev->mc_count >
-                   (MAX_ADDRS_SUPPORTED - MAC_MC_ADDR_START_OFFSET - 1)) {
+                   (config->max_mc_addr - config->max_mac_addr)) {
                        DBG_PRINT(ERR_DBG, "%s: No more Rx filters ",
                                  dev->name);
                        DBG_PRINT(ERR_DBG, "can be added, please enable ");
@@ -4844,7 +4848,7 @@ static void s2io_set_multicast(struct net_device *dev)
                        val64 = RMAC_ADDR_CMD_MEM_WE |
                            RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
                            RMAC_ADDR_CMD_MEM_OFFSET
-                           (MAC_MC_ADDR_START_OFFSET + i);
+                           (config->mc_start_offset + i);
                        writeq(val64, &bar0->rmac_addr_cmd_mem);
 
                        /* Wait for command completes */
@@ -4876,7 +4880,7 @@ static void s2io_set_multicast(struct net_device *dev)
                        val64 = RMAC_ADDR_CMD_MEM_WE |
                            RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
                            RMAC_ADDR_CMD_MEM_OFFSET
-                           (i + MAC_MC_ADDR_START_OFFSET);
+                           (i + config->mc_start_offset);
                        writeq(val64, &bar0->rmac_addr_cmd_mem);
 
                        /* Wait for command completes */
@@ -4892,8 +4896,78 @@ static void s2io_set_multicast(struct net_device *dev)
        }
 }
 
-/* add unicast MAC address to CAM */
-static int do_s2io_add_unicast(struct s2io_nic *sp, u64 addr, int off)
+/* read from CAM unicast & multicast addresses and store it in
+ * def_mac_addr structure
+ */
+void do_s2io_store_unicast_mc(struct s2io_nic *sp)
+{
+       int offset;
+       u64 mac_addr = 0x0;
+       struct config_param *config = &sp->config;
+
+       /* store unicast & multicast mac addresses */
+       for (offset = 0; offset < config->max_mc_addr; offset++) {
+               mac_addr = do_s2io_read_unicast_mc(sp, offset);
+               /* if read fails disable the entry */
+               if (mac_addr == FAILURE)
+                       mac_addr = S2IO_DISABLE_MAC_ENTRY;
+               do_s2io_copy_mac_addr(sp, offset, mac_addr);
+       }
+}
+
+/* restore unicast & multicast MAC to CAM from def_mac_addr structure */
+static void do_s2io_restore_unicast_mc(struct s2io_nic *sp)
+{
+       int offset;
+       struct config_param *config = &sp->config;
+       /* restore unicast mac address */
+       for (offset = 0; offset < config->max_mac_addr; offset++)
+               do_s2io_prog_unicast(sp->dev,
+                       sp->def_mac_addr[offset].mac_addr);
+
+       /* restore multicast mac address */
+       for (offset = config->mc_start_offset;
+               offset < config->max_mc_addr; offset++)
+               do_s2io_add_mc(sp, sp->def_mac_addr[offset].mac_addr);
+}
+
+/* add a multicast MAC address to CAM */
+static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr)
+{
+       int i;
+       u64 mac_addr = 0;
+       struct config_param *config = &sp->config;
+
+       for (i = 0; i < ETH_ALEN; i++) {
+               mac_addr <<= 8;
+               mac_addr |= addr[i];
+       }
+       if ((0ULL == mac_addr) || (mac_addr == S2IO_DISABLE_MAC_ENTRY))
+               return SUCCESS;
+
+       /* check if the multicast mac already preset in CAM */
+       for (i = config->mc_start_offset; i < config->max_mc_addr; i++) {
+               u64 tmp64;
+               tmp64 = do_s2io_read_unicast_mc(sp, i);
+               if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
+                       break;
+
+               if (tmp64 == mac_addr)
+                       return SUCCESS;
+       }
+       if (i == config->max_mc_addr) {
+               DBG_PRINT(ERR_DBG,
+                       "CAM full no space left for multicast MAC\n");
+               return FAILURE;
+       }
+       /* Update the internal structure with this new mac address */
+       do_s2io_copy_mac_addr(sp, i, mac_addr);
+
+       return (do_s2io_add_mac(sp, mac_addr, i));
+}
+
+/* add MAC address to CAM */
+static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int off)
 {
        u64 val64;
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -4910,15 +4984,62 @@ static int do_s2io_add_unicast(struct s2io_nic *sp, u64 addr, int off)
        if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
                RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
                S2IO_BIT_RESET)) {
-               DBG_PRINT(INFO_DBG, "add_mac_addr failed\n");
+               DBG_PRINT(INFO_DBG, "do_s2io_add_mac failed\n");
                return FAILURE;
        }
        return SUCCESS;
 }
+/* deletes a specified unicast/multicast mac entry from CAM */
+static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr)
+{
+       int offset;
+       u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, tmp64;
+       struct config_param *config = &sp->config;
+
+       for (offset = 1;
+               offset < config->max_mc_addr; offset++) {
+               tmp64 = do_s2io_read_unicast_mc(sp, offset);
+               if (tmp64 == addr) {
+                       /* disable the entry by writing  0xffffffffffffULL */
+                       if (do_s2io_add_mac(sp, dis_addr, offset) ==  FAILURE)
+                               return FAILURE;
+                       /* store the new mac list from CAM */
+                       do_s2io_store_unicast_mc(sp);
+                       return SUCCESS;
+               }
+       }
+       DBG_PRINT(ERR_DBG, "MAC address 0x%llx not found in CAM\n",
+                       (unsigned long long)addr);
+       return FAILURE;
+}
+
+/* read mac entries from CAM */
+static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset)
+{
+       u64 tmp64 = 0xffffffffffff0000ULL, val64;
+       struct XENA_dev_config __iomem *bar0 = sp->bar0;
+
+       /* read mac addr */
+       val64 =
+               RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
+               RMAC_ADDR_CMD_MEM_OFFSET(offset);
+       writeq(val64, &bar0->rmac_addr_cmd_mem);
+
+       /* Wait till command completes */
+       if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+               RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
+               S2IO_BIT_RESET)) {
+               DBG_PRINT(INFO_DBG, "do_s2io_read_unicast_mc failed\n");
+               return FAILURE;
+       }
+       tmp64 = readq(&bar0->rmac_addr_data0_mem);
+       return (tmp64 >> 16);
+}
 
 /**
  * s2io_set_mac_addr driver entry point
  */
+
 static int s2io_set_mac_addr(struct net_device *dev, void *p)
 {
        struct sockaddr *addr = p;
@@ -4931,7 +5052,6 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p)
        /* store the MAC address in CAM */
        return (do_s2io_prog_unicast(dev, dev->dev_addr));
 }
-
 /**
  *  do_s2io_prog_unicast - Programs the Xframe mac address
  *  @dev : pointer to the device structure.
@@ -4941,11 +5061,14 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p)
  *  Return value: SUCCESS on success and an appropriate (-)ve integer
  *  as defined in errno.h file on failure.
  */
+
 static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr)
 {
        struct s2io_nic *sp = dev->priv;
        register u64 mac_addr = 0, perm_addr = 0;
        int i;
+       u64 tmp64;
+       struct config_param *config = &sp->config;
 
        /*
        * Set the new MAC address as the new unicast filter and reflect this
@@ -4963,9 +5086,26 @@ static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr)
        if (mac_addr == perm_addr)
                return SUCCESS;
 
+       /* check if the mac already preset in CAM */
+       for (i = 1; i < config->max_mac_addr; i++) {
+               tmp64 = do_s2io_read_unicast_mc(sp, i);
+               if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
+                       break;
+
+               if (tmp64 == mac_addr) {
+                       DBG_PRINT(INFO_DBG,
+                       "MAC addr:0x%llx already present in CAM\n",
+                       (unsigned long long)mac_addr);
+                       return SUCCESS;
+               }
+       }
+       if (i == config->max_mac_addr) {
+               DBG_PRINT(ERR_DBG, "CAM full no space left for Unicast MAC\n");
+               return FAILURE;
+       }
        /* Update the internal structure with this new mac address */
-       do_s2io_copy_mac_addr(sp, 0, mac_addr);
-       return (do_s2io_add_unicast(sp, mac_addr, 0));
+       do_s2io_copy_mac_addr(sp, i, mac_addr);
+       return (do_s2io_add_mac(sp, mac_addr, i));
 }
 
 /**
@@ -6799,6 +6939,8 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
        struct XENA_dev_config __iomem *bar0 = sp->bar0;
        unsigned long flags;
        register u64 val64 = 0;
+       struct config_param *config;
+       config = &sp->config;
 
        if (!is_s2io_card_up(sp))
                return;
@@ -6810,6 +6952,10 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
        }
        clear_bit(__S2IO_STATE_CARD_UP, &sp->state);
 
+       /* Disable napi */
+       if (config->napi)
+               napi_disable(&sp->napi);
+
        /* disable Tx and Rx traffic on the NIC */
        if (do_io)
                stop_nic(sp);
@@ -6903,6 +7049,11 @@ static int s2io_card_up(struct s2io_nic * sp)
                DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i,
                          atomic_read(&sp->rx_bufs_left[i]));
        }
+
+       /* Initialise napi */
+       if (config->napi)
+               napi_enable(&sp->napi);
+
        /* Maintain the state prior to the open */
        if (sp->promisc_flg)
                sp->promisc_flg = 0;
@@ -7648,7 +7799,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
         */
        bar0 = sp->bar0;
        val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
-           RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
+           RMAC_ADDR_CMD_MEM_OFFSET(0 + S2IO_MAC_ADDR_START_OFFSET);
        writeq(val64, &bar0->rmac_addr_cmd_mem);
        wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
                      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET);
@@ -7668,6 +7819,20 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
        memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
        memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
 
+       /* initialize number of multicast & unicast MAC entries variables */
+       if (sp->device_type == XFRAME_I_DEVICE) {
+               config->max_mc_addr = S2IO_XENA_MAX_MC_ADDRESSES;
+               config->max_mac_addr = S2IO_XENA_MAX_MAC_ADDRESSES;
+               config->mc_start_offset = S2IO_XENA_MC_ADDR_START_OFFSET;
+       } else if (sp->device_type == XFRAME_II_DEVICE) {
+               config->max_mc_addr = S2IO_HERC_MAX_MC_ADDRESSES;
+               config->max_mac_addr = S2IO_HERC_MAX_MAC_ADDRESSES;
+               config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
+       }
+
+       /* store mac addresses from CAM to s2io_nic structure */
+       do_s2io_store_unicast_mc(sp);
+
         /* Store the values of the MSIX table in the s2io_nic structure */
        store_xmsi_data(sp);
        /* reset Nic and bring it to known state */