|
@@ -3375,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);
|
|
|
|
|
@@ -3433,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;
|
|
|
}
|
|
|
|
|
@@ -3920,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 *
|
|
@@ -3928,6 +3931,14 @@ static int s2io_close(struct net_device *dev)
|
|
|
return 0;
|
|
|
|
|
|
netif_stop_queue(dev);
|
|
|
+
|
|
|
+ /* 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);
|
|
|
|
|
@@ -4728,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 */
|
|
@@ -4739,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,
|
|
@@ -4747,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),
|
|
@@ -4816,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 ");
|
|
@@ -4836,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 */
|
|
@@ -4868,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 */
|
|
@@ -4884,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;
|
|
@@ -4902,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;
|
|
@@ -4923,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.
|
|
@@ -4933,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
|
|
@@ -4955,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));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -7651,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);
|
|
@@ -7671,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 */
|