Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Sreenivasa Honnur and committed by
David S. Miller
faa4f796 db0ce50d

+201 -23
+11 -5
drivers/net/s2io-regs.h
··· 723 723 u64 rmac_cfg_key; 724 724 #define RMAC_CFG_KEY(val) vBIT(val,0,16) 725 725 726 - #define MAX_MAC_ADDRESSES 16 727 - #define MAX_MC_ADDRESSES 32 /* Multicast addresses */ 728 - #define MAC_MAC_ADDR_START_OFFSET 0 729 - #define MAC_MC_ADDR_START_OFFSET 16 730 - #define MAC_MC_ALL_MC_ADDR_OFFSET 63 /* enables all multicast pkts */ 726 + #define S2IO_MAC_ADDR_START_OFFSET 0 727 + 728 + #define S2IO_XENA_MAX_MC_ADDRESSES 64 /* multicast addresses */ 729 + #define S2IO_HERC_MAX_MC_ADDRESSES 256 730 + 731 + #define S2IO_XENA_MAX_MAC_ADDRESSES 16 732 + #define S2IO_HERC_MAX_MAC_ADDRESSES 64 733 + 734 + #define S2IO_XENA_MC_ADDR_START_OFFSET 16 735 + #define S2IO_HERC_MC_ADDR_START_OFFSET 64 736 + 731 737 u64 rmac_addr_cmd_mem; 732 738 #define RMAC_ADDR_CMD_MEM_WE s2BIT(7) 733 739 #define RMAC_ADDR_CMD_MEM_RD 0
+178 -16
drivers/net/s2io.c
··· 3375 3375 /* Set swapper to enable I/O register access */ 3376 3376 s2io_set_swapper(sp); 3377 3377 3378 + /* restore mac_addr entries */ 3379 + do_s2io_restore_unicast_mc(sp); 3380 + 3378 3381 /* Restore the MSIX table entries from local variables */ 3379 3382 restore_xmsi_data(sp); 3380 3383 ··· 3435 3432 val64 = readq(&bar0->pcc_err_reg); 3436 3433 writeq(val64, &bar0->pcc_err_reg); 3437 3434 } 3438 - 3439 - /* restore the previously assigned mac address */ 3440 - do_s2io_prog_unicast(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr); 3441 3435 3442 3436 sp->device_enabled_once = FALSE; 3443 3437 } ··· 3920 3920 static int s2io_close(struct net_device *dev) 3921 3921 { 3922 3922 struct s2io_nic *sp = dev->priv; 3923 + struct config_param *config = &sp->config; 3924 + u64 tmp64; 3925 + int offset; 3923 3926 3924 3927 /* Return if the device is already closed * 3925 3928 * Can happen when s2io_card_up failed in change_mtu * ··· 3931 3928 return 0; 3932 3929 3933 3930 netif_stop_queue(dev); 3931 + 3932 + /* delete all populated mac entries */ 3933 + for (offset = 1; offset < config->max_mc_addr; offset++) { 3934 + tmp64 = do_s2io_read_unicast_mc(sp, offset); 3935 + if (tmp64 != S2IO_DISABLE_MAC_ENTRY) 3936 + do_s2io_delete_unicast_mc(sp, tmp64); 3937 + } 3938 + 3934 3939 /* Reset card, kill tasklet and free Tx and Rx buffers. */ 3935 3940 s2io_card_down(sp); 3936 3941 ··· 4739 4728 struct XENA_dev_config __iomem *bar0 = sp->bar0; 4740 4729 u64 val64 = 0, multi_mac = 0x010203040506ULL, mask = 4741 4730 0xfeffffffffffULL; 4742 - u64 dis_addr = 0xffffffffffffULL, mac_addr = 0; 4731 + u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, mac_addr = 0; 4743 4732 void __iomem *add; 4733 + struct config_param *config = &sp->config; 4744 4734 4745 4735 if ((dev->flags & IFF_ALLMULTI) && (!sp->m_cast_flg)) { 4746 4736 /* Enable all Multicast addresses */ ··· 4751 4739 &bar0->rmac_addr_data1_mem); 4752 4740 val64 = RMAC_ADDR_CMD_MEM_WE | 4753 4741 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4754 - RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET); 4742 + RMAC_ADDR_CMD_MEM_OFFSET(config->max_mc_addr - 1); 4755 4743 writeq(val64, &bar0->rmac_addr_cmd_mem); 4756 4744 /* Wait till command completes */ 4757 4745 wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, ··· 4759 4747 S2IO_BIT_RESET); 4760 4748 4761 4749 sp->m_cast_flg = 1; 4762 - sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET; 4750 + sp->all_multi_pos = config->max_mc_addr - 1; 4763 4751 } else if ((dev->flags & IFF_ALLMULTI) && (sp->m_cast_flg)) { 4764 4752 /* Disable all Multicast addresses */ 4765 4753 writeq(RMAC_ADDR_DATA0_MEM_ADDR(dis_addr), ··· 4828 4816 /* Update individual M_CAST address list */ 4829 4817 if ((!sp->m_cast_flg) && dev->mc_count) { 4830 4818 if (dev->mc_count > 4831 - (MAX_ADDRS_SUPPORTED - MAC_MC_ADDR_START_OFFSET - 1)) { 4819 + (config->max_mc_addr - config->max_mac_addr)) { 4832 4820 DBG_PRINT(ERR_DBG, "%s: No more Rx filters ", 4833 4821 dev->name); 4834 4822 DBG_PRINT(ERR_DBG, "can be added, please enable "); ··· 4848 4836 val64 = RMAC_ADDR_CMD_MEM_WE | 4849 4837 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4850 4838 RMAC_ADDR_CMD_MEM_OFFSET 4851 - (MAC_MC_ADDR_START_OFFSET + i); 4839 + (config->mc_start_offset + i); 4852 4840 writeq(val64, &bar0->rmac_addr_cmd_mem); 4853 4841 4854 4842 /* Wait for command completes */ ··· 4880 4868 val64 = RMAC_ADDR_CMD_MEM_WE | 4881 4869 RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4882 4870 RMAC_ADDR_CMD_MEM_OFFSET 4883 - (i + MAC_MC_ADDR_START_OFFSET); 4871 + (i + config->mc_start_offset); 4884 4872 writeq(val64, &bar0->rmac_addr_cmd_mem); 4885 4873 4886 4874 /* Wait for command completes */ ··· 4896 4884 } 4897 4885 } 4898 4886 4899 - /* add unicast MAC address to CAM */ 4900 - static int do_s2io_add_unicast(struct s2io_nic *sp, u64 addr, int off) 4887 + /* read from CAM unicast & multicast addresses and store it in 4888 + * def_mac_addr structure 4889 + */ 4890 + void do_s2io_store_unicast_mc(struct s2io_nic *sp) 4891 + { 4892 + int offset; 4893 + u64 mac_addr = 0x0; 4894 + struct config_param *config = &sp->config; 4895 + 4896 + /* store unicast & multicast mac addresses */ 4897 + for (offset = 0; offset < config->max_mc_addr; offset++) { 4898 + mac_addr = do_s2io_read_unicast_mc(sp, offset); 4899 + /* if read fails disable the entry */ 4900 + if (mac_addr == FAILURE) 4901 + mac_addr = S2IO_DISABLE_MAC_ENTRY; 4902 + do_s2io_copy_mac_addr(sp, offset, mac_addr); 4903 + } 4904 + } 4905 + 4906 + /* restore unicast & multicast MAC to CAM from def_mac_addr structure */ 4907 + static void do_s2io_restore_unicast_mc(struct s2io_nic *sp) 4908 + { 4909 + int offset; 4910 + struct config_param *config = &sp->config; 4911 + /* restore unicast mac address */ 4912 + for (offset = 0; offset < config->max_mac_addr; offset++) 4913 + do_s2io_prog_unicast(sp->dev, 4914 + sp->def_mac_addr[offset].mac_addr); 4915 + 4916 + /* restore multicast mac address */ 4917 + for (offset = config->mc_start_offset; 4918 + offset < config->max_mc_addr; offset++) 4919 + do_s2io_add_mc(sp, sp->def_mac_addr[offset].mac_addr); 4920 + } 4921 + 4922 + /* add a multicast MAC address to CAM */ 4923 + static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr) 4924 + { 4925 + int i; 4926 + u64 mac_addr = 0; 4927 + struct config_param *config = &sp->config; 4928 + 4929 + for (i = 0; i < ETH_ALEN; i++) { 4930 + mac_addr <<= 8; 4931 + mac_addr |= addr[i]; 4932 + } 4933 + if ((0ULL == mac_addr) || (mac_addr == S2IO_DISABLE_MAC_ENTRY)) 4934 + return SUCCESS; 4935 + 4936 + /* check if the multicast mac already preset in CAM */ 4937 + for (i = config->mc_start_offset; i < config->max_mc_addr; i++) { 4938 + u64 tmp64; 4939 + tmp64 = do_s2io_read_unicast_mc(sp, i); 4940 + if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */ 4941 + break; 4942 + 4943 + if (tmp64 == mac_addr) 4944 + return SUCCESS; 4945 + } 4946 + if (i == config->max_mc_addr) { 4947 + DBG_PRINT(ERR_DBG, 4948 + "CAM full no space left for multicast MAC\n"); 4949 + return FAILURE; 4950 + } 4951 + /* Update the internal structure with this new mac address */ 4952 + do_s2io_copy_mac_addr(sp, i, mac_addr); 4953 + 4954 + return (do_s2io_add_mac(sp, mac_addr, i)); 4955 + } 4956 + 4957 + /* add MAC address to CAM */ 4958 + static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int off) 4901 4959 { 4902 4960 u64 val64; 4903 4961 struct XENA_dev_config __iomem *bar0 = sp->bar0; ··· 4984 4902 if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, 4985 4903 RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4986 4904 S2IO_BIT_RESET)) { 4987 - DBG_PRINT(INFO_DBG, "add_mac_addr failed\n"); 4905 + DBG_PRINT(INFO_DBG, "do_s2io_add_mac failed\n"); 4988 4906 return FAILURE; 4989 4907 } 4990 4908 return SUCCESS; 4909 + } 4910 + /* deletes a specified unicast/multicast mac entry from CAM */ 4911 + static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr) 4912 + { 4913 + int offset; 4914 + u64 dis_addr = S2IO_DISABLE_MAC_ENTRY, tmp64; 4915 + struct config_param *config = &sp->config; 4916 + 4917 + for (offset = 1; 4918 + offset < config->max_mc_addr; offset++) { 4919 + tmp64 = do_s2io_read_unicast_mc(sp, offset); 4920 + if (tmp64 == addr) { 4921 + /* disable the entry by writing 0xffffffffffffULL */ 4922 + if (do_s2io_add_mac(sp, dis_addr, offset) == FAILURE) 4923 + return FAILURE; 4924 + /* store the new mac list from CAM */ 4925 + do_s2io_store_unicast_mc(sp); 4926 + return SUCCESS; 4927 + } 4928 + } 4929 + DBG_PRINT(ERR_DBG, "MAC address 0x%llx not found in CAM\n", 4930 + (unsigned long long)addr); 4931 + return FAILURE; 4932 + } 4933 + 4934 + /* read mac entries from CAM */ 4935 + static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset) 4936 + { 4937 + u64 tmp64 = 0xffffffffffff0000ULL, val64; 4938 + struct XENA_dev_config __iomem *bar0 = sp->bar0; 4939 + 4940 + /* read mac addr */ 4941 + val64 = 4942 + RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 4943 + RMAC_ADDR_CMD_MEM_OFFSET(offset); 4944 + writeq(val64, &bar0->rmac_addr_cmd_mem); 4945 + 4946 + /* Wait till command completes */ 4947 + if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, 4948 + RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, 4949 + S2IO_BIT_RESET)) { 4950 + DBG_PRINT(INFO_DBG, "do_s2io_read_unicast_mc failed\n"); 4951 + return FAILURE; 4952 + } 4953 + tmp64 = readq(&bar0->rmac_addr_data0_mem); 4954 + return (tmp64 >> 16); 4991 4955 } 4992 4956 4993 4957 /** 4994 4958 * s2io_set_mac_addr driver entry point 4995 4959 */ 4960 + 4996 4961 static int s2io_set_mac_addr(struct net_device *dev, void *p) 4997 4962 { 4998 4963 struct sockaddr *addr = p; ··· 5052 4923 /* store the MAC address in CAM */ 5053 4924 return (do_s2io_prog_unicast(dev, dev->dev_addr)); 5054 4925 } 5055 - 5056 4926 /** 5057 4927 * do_s2io_prog_unicast - Programs the Xframe mac address 5058 4928 * @dev : pointer to the device structure. ··· 5061 4933 * Return value: SUCCESS on success and an appropriate (-)ve integer 5062 4934 * as defined in errno.h file on failure. 5063 4935 */ 4936 + 5064 4937 static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr) 5065 4938 { 5066 4939 struct s2io_nic *sp = dev->priv; 5067 4940 register u64 mac_addr = 0, perm_addr = 0; 5068 4941 int i; 4942 + u64 tmp64; 4943 + struct config_param *config = &sp->config; 5069 4944 5070 4945 /* 5071 4946 * Set the new MAC address as the new unicast filter and reflect this ··· 5086 4955 if (mac_addr == perm_addr) 5087 4956 return SUCCESS; 5088 4957 4958 + /* check if the mac already preset in CAM */ 4959 + for (i = 1; i < config->max_mac_addr; i++) { 4960 + tmp64 = do_s2io_read_unicast_mc(sp, i); 4961 + if (tmp64 == S2IO_DISABLE_MAC_ENTRY) /* CAM entry is empty */ 4962 + break; 4963 + 4964 + if (tmp64 == mac_addr) { 4965 + DBG_PRINT(INFO_DBG, 4966 + "MAC addr:0x%llx already present in CAM\n", 4967 + (unsigned long long)mac_addr); 4968 + return SUCCESS; 4969 + } 4970 + } 4971 + if (i == config->max_mac_addr) { 4972 + DBG_PRINT(ERR_DBG, "CAM full no space left for Unicast MAC\n"); 4973 + return FAILURE; 4974 + } 5089 4975 /* Update the internal structure with this new mac address */ 5090 - do_s2io_copy_mac_addr(sp, 0, mac_addr); 5091 - return (do_s2io_add_unicast(sp, mac_addr, 0)); 4976 + do_s2io_copy_mac_addr(sp, i, mac_addr); 4977 + return (do_s2io_add_mac(sp, mac_addr, i)); 5092 4978 } 5093 4979 5094 4980 /** ··· 7799 7651 */ 7800 7652 bar0 = sp->bar0; 7801 7653 val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | 7802 - RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET); 7654 + RMAC_ADDR_CMD_MEM_OFFSET(0 + S2IO_MAC_ADDR_START_OFFSET); 7803 7655 writeq(val64, &bar0->rmac_addr_cmd_mem); 7804 7656 wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, 7805 7657 RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET); ··· 7818 7670 dev->addr_len = ETH_ALEN; 7819 7671 memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); 7820 7672 memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); 7673 + 7674 + /* initialize number of multicast & unicast MAC entries variables */ 7675 + if (sp->device_type == XFRAME_I_DEVICE) { 7676 + config->max_mc_addr = S2IO_XENA_MAX_MC_ADDRESSES; 7677 + config->max_mac_addr = S2IO_XENA_MAX_MAC_ADDRESSES; 7678 + config->mc_start_offset = S2IO_XENA_MC_ADDR_START_OFFSET; 7679 + } else if (sp->device_type == XFRAME_II_DEVICE) { 7680 + config->max_mc_addr = S2IO_HERC_MAX_MC_ADDRESSES; 7681 + config->max_mac_addr = S2IO_HERC_MAX_MAC_ADDRESSES; 7682 + config->mc_start_offset = S2IO_HERC_MC_ADDR_START_OFFSET; 7683 + } 7684 + 7685 + /* store mac addresses from CAM to s2io_nic structure */ 7686 + do_s2io_store_unicast_mc(sp); 7821 7687 7822 7688 /* Store the values of the MSIX table in the s2io_nic structure */ 7823 7689 store_xmsi_data(sp);
+12 -2
drivers/net/s2io.h
··· 31 31 #define SUCCESS 0 32 32 #define FAILURE -1 33 33 #define S2IO_MINUS_ONE 0xFFFFFFFFFFFFFFFFULL 34 + #define S2IO_DISABLE_MAC_ENTRY 0xFFFFFFFFFFFFULL 34 35 #define S2IO_MAX_PCI_CONFIG_SPACE_REINIT 100 35 36 #define S2IO_BIT_RESET 1 36 37 #define S2IO_BIT_SET 2 ··· 459 458 #define MAX_MTU_JUMBO (MAX_PYLD_JUMBO+18) 460 459 #define MAX_MTU_JUMBO_VLAN (MAX_PYLD_JUMBO+22) 461 460 u16 bus_speed; 461 + int max_mc_addr; /* xena=64 herc=256 */ 462 + int max_mac_addr; /* xena=16 herc=64 */ 463 + int mc_start_offset; /* xena=16 herc=64 */ 462 464 }; 463 465 464 466 /* Structure representing MAC Addrs */ ··· 830 826 #define MAX_MAC_SUPPORTED 16 831 827 #define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED 832 828 833 - struct mac_addr def_mac_addr[MAX_MAC_SUPPORTED]; 829 + struct mac_addr def_mac_addr[256]; 834 830 835 831 struct net_device_stats stats; 836 832 int high_dma_flag; ··· 857 853 #define MAX_ADDRS_SUPPORTED 64 858 854 u16 usr_addr_count; 859 855 u16 mc_addr_count; 860 - struct usr_addr usr_addrs[MAX_ADDRS_SUPPORTED]; 856 + struct usr_addr usr_addrs[256]; 861 857 862 858 u16 m_cast_flg; 863 859 u16 all_multi_pos; ··· 1070 1066 static void s2io_rem_isr(struct s2io_nic * sp); 1071 1067 1072 1068 static void restore_xmsi_data(struct s2io_nic *nic); 1069 + static void do_s2io_store_unicast_mc(struct s2io_nic *sp); 1070 + static void do_s2io_restore_unicast_mc(struct s2io_nic *sp); 1071 + static u64 do_s2io_read_unicast_mc(struct s2io_nic *sp, int offset); 1072 + static int do_s2io_add_mc(struct s2io_nic *sp, u8 *addr); 1073 + static int do_s2io_add_mac(struct s2io_nic *sp, u64 addr, int offset); 1074 + static int do_s2io_delete_unicast_mc(struct s2io_nic *sp, u64 addr); 1073 1075 1074 1076 static int 1075 1077 s2io_club_tcp_session(u8 *buffer, u8 **tcp, u32 *tcp_len, struct lro **lro,