aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorSreenivasa Honnur <sreenivasa.honnur@neterion.com>2008-01-24 04:45:43 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:03:52 -0500
commitfaa4f7969f3340606f46515560ce193d9bd74ea4 (patch)
tree31bd54a2162dd35767baaeaaf4ae55ada2dd7958 /drivers/net/s2io.c
parentdb0ce50d3792e993a1b24f16fb70153eccf38f33 (diff)
[S2IO]: Support for add/delete/store/restore ethernet addresses
- Support to add/delete/store/restore 64 and 128 Ethernet addresses for Xframe I and Xframe II respectively. Signed-off-by: Sreenivasa Honnur <sreenivasa.honnur@neterion.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r--drivers/net/s2io.c194
1 files changed, 178 insertions, 16 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 67e0a65fc28c..644d71bfb640 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -3375,6 +3375,9 @@ static void s2io_reset(struct s2io_nic * sp)
3375 /* Set swapper to enable I/O register access */ 3375 /* Set swapper to enable I/O register access */
3376 s2io_set_swapper(sp); 3376 s2io_set_swapper(sp);
3377 3377
3378 /* restore mac_addr entries */
3379 do_s2io_restore_unicast_mc(sp);
3380
3378 /* Restore the MSIX table entries from local variables */ 3381 /* Restore the MSIX table entries from local variables */
3379 restore_xmsi_data(sp); 3382 restore_xmsi_data(sp);
3380 3383
@@ -3433,9 +3436,6 @@ static void s2io_reset(struct s2io_nic * sp)
3433 writeq(val64, &bar0->pcc_err_reg); 3436 writeq(val64, &bar0->pcc_err_reg);
3434 } 3437 }
3435 3438
3436 /* restore the previously assigned mac address */
3437 do_s2io_prog_unicast(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr);
3438
3439 sp->device_enabled_once = FALSE; 3439 sp->device_enabled_once = FALSE;
3440} 3440}
3441 3441
@@ -3920,6 +3920,9 @@ hw_init_failed:
3920static int s2io_close(struct net_device *dev) 3920static int s2io_close(struct net_device *dev)
3921{ 3921{
3922 struct s2io_nic *sp = dev->priv; 3922 struct s2io_nic *sp = dev->priv;
3923 struct config_param *config = &sp->config;
3924 u64 tmp64;
3925 int offset;
3923 3926
3924 /* Return if the device is already closed * 3927 /* Return if the device is already closed *
3925 * Can happen when s2io_card_up failed in change_mtu * 3928 * Can happen when s2io_card_up failed in change_mtu *
@@ -3928,6 +3931,14 @@ static int s2io_close(struct net_device *dev)
3928 return 0; 3931 return 0;
3929 3932
3930 netif_stop_queue(dev); 3933 netif_stop_queue(dev);
3934
3935 /* delete all populated mac entries */
3936 for (offset = 1; offset < config->max_mc_addr; offset++) {
3937 tmp64 = do_s2io_read_unicast_mc(sp, offset);
3938 if (tmp64 != S2IO_DISABLE_MAC_ENTRY)
3939 do_s2io_delete_unicast_mc(sp, tmp64);
3940 }
3941
3931 /* Reset card, kill tasklet and free Tx and Rx buffers. */ 3942 /* Reset card, kill tasklet and free Tx and Rx buffers. */
3932 s2io_card_down(sp); 3943 s2io_card_down(sp);
3933 3944
@@ -4728,8 +4739,9 @@ static void s2io_set_multicast(struct net_device *dev)
4728 struct XENA_dev_config __iomem *bar0 = sp->bar0; 4739 struct XENA_dev_config __iomem *bar0 = sp->bar0;
4729 u64 val64 = 0, multi_mac = 0x010203040506ULL, mask = 4740 u64 val64 = 0, multi_mac = 0x010203040506ULL, mask =
4730 0xfeffffffffffULL; 4741 0xfeffffffffffULL;
4731 u64 dis_addr = 0xffffffffffffULL, mac_addr = 0; 4742 u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, mac_addr = 0;
4732 void __iomem *add; 4743 void __iomem *add;
4744 struct config_param *config = &sp->config;
4733 4745
4734 if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) { 4746 if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) {
4735 /* Enable all Multicast addresses */ 4747 /* Enable all Multicast addresses */
@@ -4739,7 +4751,7 @@ static void s2io_set_multicast(struct net_device *dev)
4739 &bar0->rmac_addr_data1_mem); 4751 &bar0->rmac_addr_data1_mem);
4740 val64 = RMAC_ADDR_CMD_MEM_WE | 4752 val64 = RMAC_ADDR_CMD_MEM_WE |
4741 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4753 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
4742 RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET); 4754 RMAC_ADDR_CMD_MEM_OFFSET(config->max_mc_addr - 1);
4743 writeq(val64, &bar0->rmac_addr_cmd_mem); 4755 writeq(val64, &bar0->rmac_addr_cmd_mem);
4744 /* Wait till command completes */ 4756 /* Wait till command completes */
4745 wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, 4757 wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
@@ -4747,7 +4759,7 @@ static void s2io_set_multicast(struct net_device *dev)
4747 S2IO_BIT_RESET); 4759 S2IO_BIT_RESET);
4748 4760
4749 sp->m_cast_flg = 1; 4761 sp->m_cast_flg = 1;
4750 sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET; 4762 sp->all_multi_pos = config->max_mc_addr - 1;
4751 } else if ((dev->flags & IFF_ALLMULTI) && (sp->m_cast_flg)) { 4763 } else if ((dev->flags & IFF_ALLMULTI) && (sp->m_cast_flg)) {
4752 /* Disable all Multicast addresses */ 4764 /* Disable all Multicast addresses */
4753 writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr), 4765 writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr),
@@ -4816,7 +4828,7 @@ static void s2io_set_multicast(struct net_device *dev)
4816 /* Update individual M_CAST address list */ 4828 /* Update individual M_CAST address list */
4817 if ((!sp->m_cast_flg) && dev->mc_count) { 4829 if ((!sp->m_cast_flg) && dev->mc_count) {
4818 if (dev->mc_count > 4830 if (dev->mc_count >
4819 (MAX_ADDRS_SUPPORTED - MAC_MC_ADDR_START_OFFSET - 1)) { 4831 (config->max_mc_addr - config->max_mac_addr)) {
4820 DBG_PRINT(ERR_DBG, "%s: No more Rx filters ", 4832 DBG_PRINT(ERR_DBG, "%s: No more Rx filters ",
4821 dev->name); 4833 dev->name);
4822 DBG_PRINT(ERR_DBG, "can be added, please enable "); 4834 DBG_PRINT(ERR_DBG, "can be added, please enable ");
@@ -4836,7 +4848,7 @@ static void s2io_set_multicast(struct net_device *dev)
4836 val64 = RMAC_ADDR_CMD_MEM_WE | 4848 val64 = RMAC_ADDR_CMD_MEM_WE |
4837 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4849 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
4838 RMAC_ADDR_CMD_MEM_OFFSET 4850 RMAC_ADDR_CMD_MEM_OFFSET
4839 (MAC_MC_ADDR_START_OFFSET + i); 4851 (config->mc_start_offset + i);
4840 writeq(val64, &bar0->rmac_addr_cmd_mem); 4852 writeq(val64, &bar0->rmac_addr_cmd_mem);
4841 4853
4842 /* Wait for command completes */ 4854 /* Wait for command completes */
@@ -4868,7 +4880,7 @@ static void s2io_set_multicast(struct net_device *dev)
4868 val64 = RMAC_ADDR_CMD_MEM_WE | 4880 val64 = RMAC_ADDR_CMD_MEM_WE |
4869 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4881 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
4870 RMAC_ADDR_CMD_MEM_OFFSET 4882 RMAC_ADDR_CMD_MEM_OFFSET
4871 (i + MAC_MC_ADDR_START_OFFSET); 4883 (i + config->mc_start_offset);
4872 writeq(val64, &bar0->rmac_addr_cmd_mem); 4884 writeq(val64, &bar0->rmac_addr_cmd_mem);
4873 4885
4874 /* Wait for command completes */ 4886 /* Wait for command completes */
@@ -4884,8 +4896,78 @@ static void s2io_set_multicast(struct net_device *dev)
4884 } 4896 }
4885} 4897}
4886 4898
4887/* add unicast MAC address to CAM */ 4899/* read from CAM unicast & multicast addresses and store it in
4888static int do_s2io_add_unicast(struct s2io_nic *sp, u64 addr, int off) 4900 * def_mac_addr structure
4901 */
4902void do_s2io_store_unicast_mc(struct s2io_nic *sp)
4903{
4904 int offset;
4905 u64 mac_addr = 0x0;
4906 struct config_param *config = &sp->config;
4907
4908 /* store unicast & multicast mac addresses */
4909 for (offset = 0; offset < config->max_mc_addr; offset++) {
4910 mac_addr = do_s2io_read_unicast_mc(sp, offset);
4911 /* if read fails disable the entry */
4912 if (mac_addr == FAILURE)
4913 mac_addr = S2IO_DISABLE_MAC_ENTRY;
4914 do_s2io_copy_mac_addr(sp, offset, mac_addr);
4915 }
4916}
4917
4918/* restore unicast & multicast MAC to CAM from def_mac_addr structure */
4919static void do_s2io_restore_unicast_mc(struct s2io_nic *sp)
4920{
4921 int offset;
4922 struct config_param *config = &sp->config;
4923 /* restore unicast mac address */
4924 for (offset = 0; offset < config->max_mac_addr; offset++)
4925 do_s2io_prog_unicast(sp->dev,
4926 sp->def_mac_addr[offset].mac_addr);
4927
4928 /* restore multicast mac address */
4929 for (offset = config->mc_start_offset;
4930 offset < config->max_mc_addr; offset++)
4931 do_s2io_add_mc(sp, sp->def_mac_addr[offset].mac_addr);
4932}
4933
4934/* add a multicast MAC address to CAM */
4935static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr)
4936{
4937 int i;
4938 u64 mac_addr = 0;
4939 struct config_param *config = &sp->config;
4940
4941 for (i = 0; i < ETH_ALEN; i++) {
4942 mac_addr <<= 8;
4943 mac_addr |= addr[i];
4944 }
4945 if ((0ULL == mac_addr) || (mac_addr == S2IO_DISABLE_MAC_ENTRY))
4946 return SUCCESS;
4947
4948 /* check if the multicast mac already preset in CAM */
4949 for (i = config->mc_start_offset; i < config->max_mc_addr; i++) {
4950 u64 tmp64;
4951 tmp64 = do_s2io_read_unicast_mc(sp, i);
4952 if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
4953 break;
4954
4955 if (tmp64 == mac_addr)
4956 return SUCCESS;
4957 }
4958 if (i == config->max_mc_addr) {
4959 DBG_PRINT(ERR_DBG,
4960 "CAM full no space left for multicast MAC\n");
4961 return FAILURE;
4962 }
4963 /* Update the internal structure with this new mac address */
4964 do_s2io_copy_mac_addr(sp, i, mac_addr);
4965
4966 return (do_s2io_add_mac(sp, mac_addr, i));
4967}
4968
4969/* add MAC address to CAM */
4970static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int off)
4889{ 4971{
4890 u64 val64; 4972 u64 val64;
4891 struct XENA_dev_config __iomem *bar0 = sp->bar0; 4973 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)
4902 if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, 4984 if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
4903 RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4985 RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
4904 S2IO_BIT_RESET)) { 4986 S2IO_BIT_RESET)) {
4905 DBG_PRINT(INFO_DBG, "add_mac_addr failed\n"); 4987 DBG_PRINT(INFO_DBG, "do_s2io_add_mac failed\n");
4906 return FAILURE; 4988 return FAILURE;
4907 } 4989 }
4908 return SUCCESS; 4990 return SUCCESS;
4909} 4991}
4992/* deletes a specified unicast/multicast mac entry from CAM */
4993static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr)
4994{
4995 int offset;
4996 u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, tmp64;
4997 struct config_param *config = &sp->config;
4998
4999 for (offset = 1;
5000 offset < config->max_mc_addr; offset++) {
5001 tmp64 = do_s2io_read_unicast_mc(sp, offset);
5002 if (tmp64 == addr) {
5003 /* disable the entry by writing 0xffffffffffffULL */
5004 if (do_s2io_add_mac(sp, dis_addr, offset) == FAILURE)
5005 return FAILURE;
5006 /* store the new mac list from CAM */
5007 do_s2io_store_unicast_mc(sp);
5008 return SUCCESS;
5009 }
5010 }
5011 DBG_PRINT(ERR_DBG, "MAC address 0x%llx not found in CAM\n",
5012 (unsigned long long)addr);
5013 return FAILURE;
5014}
5015
5016/* read mac entries from CAM */
5017static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset)
5018{
5019 u64 tmp64 = 0xffffffffffff0000ULL, val64;
5020 struct XENA_dev_config __iomem *bar0 = sp->bar0;
5021
5022 /* read mac addr */
5023 val64 =
5024 RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
5025 RMAC_ADDR_CMD_MEM_OFFSET(offset);
5026 writeq(val64, &bar0->rmac_addr_cmd_mem);
5027
5028 /* Wait till command completes */
5029 if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
5030 RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING,
5031 S2IO_BIT_RESET)) {
5032 DBG_PRINT(INFO_DBG, "do_s2io_read_unicast_mc failed\n");
5033 return FAILURE;
5034 }
5035 tmp64 = readq(&bar0->rmac_addr_data0_mem);
5036 return (tmp64 >> 16);
5037}
4910 5038
4911/** 5039/**
4912 * s2io_set_mac_addr driver entry point 5040 * s2io_set_mac_addr driver entry point
4913 */ 5041 */
5042
4914static int s2io_set_mac_addr(struct net_device *dev, void *p) 5043static int s2io_set_mac_addr(struct net_device *dev, void *p)
4915{ 5044{
4916 struct sockaddr *addr = p; 5045 struct sockaddr *addr = p;
@@ -4923,7 +5052,6 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p)
4923 /* store the MAC address in CAM */ 5052 /* store the MAC address in CAM */
4924 return (do_s2io_prog_unicast(dev, dev->dev_addr)); 5053 return (do_s2io_prog_unicast(dev, dev->dev_addr));
4925} 5054}
4926
4927/** 5055/**
4928 * do_s2io_prog_unicast - Programs the Xframe mac address 5056 * do_s2io_prog_unicast - Programs the Xframe mac address
4929 * @dev : pointer to the device structure. 5057 * @dev : pointer to the device structure.
@@ -4933,11 +5061,14 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p)
4933 * Return value: SUCCESS on success and an appropriate (-)ve integer 5061 * Return value: SUCCESS on success and an appropriate (-)ve integer
4934 * as defined in errno.h file on failure. 5062 * as defined in errno.h file on failure.
4935 */ 5063 */
5064
4936static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr) 5065static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr)
4937{ 5066{
4938 struct s2io_nic *sp = dev->priv; 5067 struct s2io_nic *sp = dev->priv;
4939 register u64 mac_addr = 0, perm_addr = 0; 5068 register u64 mac_addr = 0, perm_addr = 0;
4940 int i; 5069 int i;
5070 u64 tmp64;
5071 struct config_param *config = &sp->config;
4941 5072
4942 /* 5073 /*
4943 * Set the new MAC address as the new unicast filter and reflect this 5074 * 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)
4955 if (mac_addr == perm_addr) 5086 if (mac_addr == perm_addr)
4956 return SUCCESS; 5087 return SUCCESS;
4957 5088
5089 /* check if the mac already preset in CAM */
5090 for (i = 1; i < config->max_mac_addr; i++) {
5091 tmp64 = do_s2io_read_unicast_mc(sp, i);
5092 if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */
5093 break;
5094
5095 if (tmp64 == mac_addr) {
5096 DBG_PRINT(INFO_DBG,
5097 "MAC addr:0x%llx already present in CAM\n",
5098 (unsigned long long)mac_addr);
5099 return SUCCESS;
5100 }
5101 }
5102 if (i == config->max_mac_addr) {
5103 DBG_PRINT(ERR_DBG, "CAM full no space left for Unicast MAC\n");
5104 return FAILURE;
5105 }
4958 /* Update the internal structure with this new mac address */ 5106 /* Update the internal structure with this new mac address */
4959 do_s2io_copy_mac_addr(sp, 0, mac_addr); 5107 do_s2io_copy_mac_addr(sp, i, mac_addr);
4960 return (do_s2io_add_unicast(sp, mac_addr, 0)); 5108 return (do_s2io_add_mac(sp, mac_addr, i));
4961} 5109}
4962 5110
4963/** 5111/**
@@ -7651,7 +7799,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
7651 */ 7799 */
7652 bar0 = sp->bar0; 7800 bar0 = sp->bar0;
7653 val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 7801 val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
7654 RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET); 7802 RMAC_ADDR_CMD_MEM_OFFSET(0 + S2IO_MAC_ADDR_START_OFFSET);
7655 writeq(val64, &bar0->rmac_addr_cmd_mem); 7803 writeq(val64, &bar0->rmac_addr_cmd_mem);
7656 wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, 7804 wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
7657 RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET); 7805 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)
7671 memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); 7819 memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN);
7672 memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); 7820 memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
7673 7821
7822 /* initialize number of multicast & unicast MAC entries variables */
7823 if (sp->device_type == XFRAME_I_DEVICE) {
7824 config->max_mc_addr = S2IO_XENA_MAX_MC_ADDRESSES;
7825 config->max_mac_addr = S2IO_XENA_MAX_MAC_ADDRESSES;
7826 config->mc_start_offset = S2IO_XENA_MC_ADDR_START_OFFSET;
7827 } else if (sp->device_type == XFRAME_II_DEVICE) {
7828 config->max_mc_addr = S2IO_HERC_MAX_MC_ADDRESSES;
7829 config->max_mac_addr = S2IO_HERC_MAX_MAC_ADDRESSES;
7830 config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET;
7831 }
7832
7833 /* store mac addresses from CAM to s2io_nic structure */
7834 do_s2io_store_unicast_mc(sp);
7835
7674 /* Store the values of the MSIX table in the s2io_nic structure */ 7836 /* Store the values of the MSIX table in the s2io_nic structure */
7675 store_xmsi_data(sp); 7837 store_xmsi_data(sp);
7676 /* reset Nic and bring it to known state */ 7838 /* reset Nic and bring it to known state */