From edd9a29829e62d439b327cf189b44151570a604d Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Wed, 9 Nov 2016 18:13:45 +0000 Subject: [PATCH 01/17] Doc: hisi: hns adds mc-mac-mask property Since there is not enough tcam table entries for every vlan and multicast address, HNS needs to add support of fuzzy matching of TCAM tables. Adding the property to mask the bits to be fuzzy matched, so update the bindings document Signed-off-by: Kejian Yan Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../devicetree/bindings/net/hisilicon-hns-dsaf.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt index d4b7f2e49984..abfbeecbcf39 100644 --- a/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt +++ b/Documentation/devicetree/bindings/net/hisilicon-hns-dsaf.txt @@ -45,6 +45,12 @@ Required properties: depends on the hardware user manual. - port-mode-offset: is offset of port mode field for each port in dsaf. Its value depends on the hardware user manual. +- mc-mac-mask: mask of multicast address, determines bit in multicast address + to set: + 1 stands for this bit will be precisely matched, TCAM will check this bit of + MAC address. + 0 stands for this bit will be fuzzy matched, TCAM won't care about this bit + of MAC address. [1] Documentation/devicetree/bindings/net/phy.txt @@ -74,10 +80,12 @@ dsaf0: dsa@c7000000 { reg = 0; phy-handle = <&phy0>; serdes-syscon = <&serdes>; + mc-mac-mask = [ff f0 00 00 00 00]; }; port@1 { reg = 1; serdes-syscon = <&serdes>; + mc-mac-mask = [ff f0 00 00 00 00]; }; }; From 153b1d48707eff876c1e0d72bb1e3dcd99613729 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Wed, 9 Nov 2016 18:13:46 +0000 Subject: [PATCH 02/17] net: hns: add fuzzy match of tcam table for hns Since there is not enough tcam table entries for vlan and multicast address, HNSv2 needs to add support of fuzzy matching of TCAM tables. To add fuzzy match of TCAM, we Add the property to mask the bits to be fuzzy matched Signed-off-by: Kejian Yan Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 16 +- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 8 +- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 140 +++++++++++++----- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 6 +- .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 2 + 5 files changed, 118 insertions(+), 54 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 55cbb6ce733c..2d64f534f25e 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -335,8 +335,7 @@ static void hns_mac_param_get(struct mac_params *param, { param->vaddr = (void *)mac_cb->vaddr; param->mac_mode = hns_get_enet_interface(mac_cb); - memcpy(param->addr, mac_cb->addr_entry_idx[0].addr, - MAC_NUM_OCTETS_PER_ADDR); + ether_addr_copy(param->addr, mac_cb->addr_entry_idx[0].addr); param->mac_id = mac_cb->mac_id; param->dev = mac_cb->dev; } @@ -353,8 +352,7 @@ static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb, { int ret; struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; - u8 addr[MAC_NUM_OCTETS_PER_ADDR] - = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct dsaf_drv_mac_single_dest_entry mac_entry; /* directy return ok in debug network mode */ @@ -389,8 +387,7 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable) int ret; struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; u8 port_num; - u8 addr[MAC_NUM_OCTETS_PER_ADDR] - = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct mac_entry_idx *uc_mac_entry; struct dsaf_drv_mac_single_dest_entry mac_entry; @@ -868,6 +865,13 @@ static int hns_mac_get_info(struct hns_mac_cb *mac_cb) } } + if (fwnode_property_read_u8_array(mac_cb->fw_port, "mc-mac-mask", + mac_cb->mc_mask, ETH_ALEN)) { + dev_warn(mac_cb->dev, + "no mc-mac-mask property, set to default value.\n"); + eth_broadcast_addr(mac_cb->mc_mask); + } + return 0; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index d3a1f72ece0e..1d941d5a7362 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -56,9 +56,6 @@ struct dsaf_device; /*check mac addr multicast*/ #define MAC_IS_MULTICAST(p) ((*((u8 *)((p) + 0)) & 0x01) ? (1) : (0)) -/**< Number of octets (8-bit bytes) in an ethernet address */ -#define MAC_NUM_OCTETS_PER_ADDR 6 - struct mac_priv { void *mac; }; @@ -189,7 +186,7 @@ struct mac_statistics { /*mac para struct ,mac get param from nic or dsaf when initialize*/ struct mac_params { - char addr[MAC_NUM_OCTETS_PER_ADDR]; + char addr[ETH_ALEN]; void *vaddr; /*virtual address*/ struct device *dev; u8 mac_id; @@ -214,7 +211,7 @@ struct mac_info { }; struct mac_entry_idx { - u8 addr[MAC_NUM_OCTETS_PER_ADDR]; + u8 addr[ETH_ALEN]; u16 vlan_id:12; u16 valid:1; u16 qos:3; @@ -317,6 +314,7 @@ struct hns_mac_cb { u8 __iomem *serdes_vaddr; struct regmap *serdes_ctrl; struct regmap *cpld_ctrl; + char mc_mask[ETH_ALEN]; u32 cpld_ctrl_reg; u32 port_rst_off; u32 port_mode_off; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 8ea3d95fa483..64f45ee1ea3d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -591,6 +591,16 @@ static void hns_dsaf_voq_bp_all_thrd_cfg(struct dsaf_device *dsaf_dev) } } +static void hns_dsaf_tbl_tcam_match_cfg( + struct dsaf_device *dsaf_dev, + struct dsaf_tbl_tcam_data *ptbl_tcam_data) +{ + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MATCH_CFG_L_REG, + ptbl_tcam_data->tbl_tcam_data_low); + dsaf_write_dev(dsaf_dev, DSAF_TBL_TCAM_MATCH_CFG_H_REG, + ptbl_tcam_data->tbl_tcam_data_high); +} + /** * hns_dsaf_tbl_tcam_data_cfg - tbl * @dsaf_id: dsa fabric id @@ -894,15 +904,16 @@ static void hns_dsaf_tcam_uc_cfg( } /** - * hns_dsaf_tcam_mc_cfg - INT - * @dsaf_id: dsa fabric id - * @address, - * @ptbl_tcam_data, - * @ptbl_tcam_mcast, + * hns_dsaf_tcam_mc_cfg - cfg the tcam for mc + * @dsaf_dev: dsa fabric device struct pointer + * @address: tcam index + * @ptbl_tcam_data: tcam data struct pointer + * @ptbl_tcam_mcast: tcam mask struct pointer, it must be null for HNSv1 */ static void hns_dsaf_tcam_mc_cfg( struct dsaf_device *dsaf_dev, u32 address, struct dsaf_tbl_tcam_data *ptbl_tcam_data, + struct dsaf_tbl_tcam_data *ptbl_tcam_mask, struct dsaf_tbl_tcam_mcast_cfg *ptbl_tcam_mcast) { spin_lock_bh(&dsaf_dev->tcam_lock); @@ -913,7 +924,11 @@ static void hns_dsaf_tcam_mc_cfg( hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, ptbl_tcam_data); /*Write Tcam Mcast*/ hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, ptbl_tcam_mcast); - /*Write Plus*/ + /* Write Match Data */ + if (ptbl_tcam_mask) + hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, ptbl_tcam_mask); + + /* Write Puls */ hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev); spin_unlock_bh(&dsaf_dev->tcam_lock); @@ -1625,7 +1640,7 @@ int hns_dsaf_set_mac_mc_entry( hns_dsaf_tcam_mc_cfg( dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + (struct dsaf_tbl_tcam_data *)(&mac_key), NULL, &mac_data); /* config software entry */ soft_mac_entry += entry_index; @@ -1636,6 +1651,16 @@ int hns_dsaf_set_mac_mc_entry( return 0; } +static void hns_dsaf_mc_mask_bit_clear(char *dst, const char *src) +{ + u16 *a = (u16 *)dst; + const u16 *b = (const u16 *)src; + + a[0] &= b[0]; + a[1] &= b[1]; + a[2] &= b[2]; +} + /** * hns_dsaf_add_mac_mc_port - add mac mc-port * @dsaf_dev: dsa fabric device struct pointer @@ -1646,11 +1671,14 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, { u16 entry_index = DSAF_INVALID_ENTRY_IDX; struct dsaf_drv_tbl_tcam_key mac_key; + struct dsaf_drv_tbl_tcam_key mask_key; + struct dsaf_tbl_tcam_data *pmask_key = NULL; struct dsaf_tbl_tcam_mcast_cfg mac_data; - struct dsaf_drv_priv *priv = - (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev); struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; - struct dsaf_drv_tbl_tcam_key tmp_mac_key; + struct dsaf_tbl_tcam_data tcam_data; + u8 mc_addr[ETH_ALEN]; + u8 *mc_mask; int mskid; /*chechk mac addr */ @@ -1660,14 +1688,28 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, return -EINVAL; } + ether_addr_copy(mc_addr, mac_entry->addr); + mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask; + if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) { + /* prepare for key data setting */ + hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask); + + /* config key mask */ + hns_dsaf_set_mac_key(dsaf_dev, &mask_key, + 0x0, + 0xff, + mc_mask); + pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key); + } + /*config key */ hns_dsaf_set_mac_key( dsaf_dev, &mac_key, mac_entry->in_vlan_id, - mac_entry->in_port_num, mac_entry->addr); + mac_entry->in_port_num, mc_addr); memset(&mac_data, 0, sizeof(struct dsaf_tbl_tcam_mcast_cfg)); - /*check exist? */ + /* check if the tcam is exist */ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); if (entry_index == DSAF_INVALID_ENTRY_IDX) { /*if hasnot , find a empty*/ @@ -1681,11 +1723,11 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, return -EINVAL; } } else { - /*if exist, add in */ - hns_dsaf_tcam_mc_get( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data); + /* if exist, add in */ + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, + &mac_data); } + /* config hardware entry */ if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) { mskid = mac_entry->port_num; @@ -1708,9 +1750,12 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val, entry_index); - hns_dsaf_tcam_mc_cfg( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + tcam_data.tbl_tcam_data_high = mac_key.high.val; + tcam_data.tbl_tcam_data_low = mac_key.low.val; + + /* config mc entry with mask */ + hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data, + pmask_key, &mac_data); /*config software entry */ soft_mac_entry += entry_index; @@ -1782,15 +1827,18 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, { u16 entry_index = DSAF_INVALID_ENTRY_IDX; struct dsaf_drv_tbl_tcam_key mac_key; - struct dsaf_drv_priv *priv = - (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev); struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; u16 vlan_id; u8 in_port_num; struct dsaf_tbl_tcam_mcast_cfg mac_data; - struct dsaf_drv_tbl_tcam_key tmp_mac_key; + struct dsaf_tbl_tcam_data tcam_data; int mskid; const u8 empty_msk[sizeof(mac_data.tbl_mcast_port_msk)] = {0}; + struct dsaf_drv_tbl_tcam_key mask_key; + struct dsaf_tbl_tcam_data *pmask_key = NULL; + u8 mc_addr[ETH_ALEN]; + u8 *mc_mask; if (!(void *)mac_entry) { dev_err(dsaf_dev->dev, @@ -1798,10 +1846,6 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, return -EINVAL; } - /*get key info*/ - vlan_id = mac_entry->in_vlan_id; - in_port_num = mac_entry->in_port_num; - /*check mac addr */ if (MAC_IS_ALL_ZEROS(mac_entry->addr)) { dev_err(dsaf_dev->dev, "del_port failed, addr %pM!\n", @@ -1809,11 +1853,28 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, return -EINVAL; } - /*config key */ - hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, - mac_entry->addr); + /* always mask vlan_id field */ + ether_addr_copy(mc_addr, mac_entry->addr); + mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask; - /*check is exist? */ + if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) { + /* prepare for key data setting */ + hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask); + + /* config key mask */ + hns_dsaf_set_mac_key(dsaf_dev, &mask_key, 0x00, 0xff, mc_addr); + + pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key); + } + + /* get key info */ + vlan_id = mac_entry->in_vlan_id; + in_port_num = mac_entry->in_port_num; + + /* config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, vlan_id, in_port_num, mc_addr); + + /* check if the tcam entry is exist */ entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); if (entry_index == DSAF_INVALID_ENTRY_IDX) { /*find none */ @@ -1829,10 +1890,8 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val, entry_index); - /*read entry*/ - hns_dsaf_tcam_mc_get( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data); + /* read entry */ + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data); /*del the port*/ if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) { @@ -1857,10 +1916,13 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, /* del soft entry */ soft_mac_entry += entry_index; soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX; - } else { /* not zer, just del port, updata*/ - hns_dsaf_tcam_mc_cfg( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + } else { /* not zero, just del port, update */ + tcam_data.tbl_tcam_data_high = mac_key.high.val; + tcam_data.tbl_tcam_data_low = mac_key.low.val; + + hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, + &tcam_data, + pmask_key, &mac_data); } return 0; @@ -1976,7 +2038,7 @@ int hns_dsaf_get_mac_entry_by_index( struct dsaf_tbl_tcam_mcast_cfg mac_data; struct dsaf_tbl_tcam_ucast_cfg mac_uc_data; - char mac_addr[MAC_NUM_OCTETS_PER_ADDR] = {0}; + char mac_addr[ETH_ALEN] = {0}; if (entry_index >= DSAF_TCAM_SUM) { /* find none, del error */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index c494fc52be74..f832a3203365 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -35,8 +35,6 @@ struct hns_mac_cb; #define DSAF_CFG_READ_CNT 30 -#define MAC_NUM_OCTETS_PER_ADDR 6 - #define DSAF_DUMP_REGS_NUM 504 #define DSAF_STATIC_NUM 28 #define DSAF_V2_STATIC_NUM 44 @@ -165,7 +163,7 @@ enum dsaf_mode { /*mac entry, mc or uc entry*/ struct dsaf_drv_mac_single_dest_entry { /* mac addr, match the entry*/ - u8 addr[MAC_NUM_OCTETS_PER_ADDR]; + u8 addr[ETH_ALEN]; u16 in_vlan_id; /* value of VlanId */ /* the vld input port num, dsaf-mode fix 0, */ @@ -179,7 +177,7 @@ struct dsaf_drv_mac_single_dest_entry { /*only mc entry*/ struct dsaf_drv_mac_multi_dest_entry { /* mac addr, match the entry*/ - u8 addr[MAC_NUM_OCTETS_PER_ADDR]; + u8 addr[ETH_ALEN]; u16 in_vlan_id; /* this mac addr output port,*/ /* bit0-bit5 means Port0-Port5(1bit is vld)**/ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 878950a42e6c..6826b28875df 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -297,6 +297,8 @@ #define DSAF_TBL_LKUP_NUM_I_0_REG 0x50C0 #define DSAF_TBL_LKUP_NUM_O_0_REG 0x50E0 #define DSAF_TBL_UCAST_BCAST_MIS_INFO_0_0_REG 0x510C +#define DSAF_TBL_TCAM_MATCH_CFG_H_REG 0x5130 +#define DSAF_TBL_TCAM_MATCH_CFG_L_REG 0x5134 #define DSAF_INODE_FIFO_WL_0_REG 0x6000 #define DSAF_ONODE_FIFO_WL_0_REG 0x6020 From 1f5fa2dd1cfa4c1356e83ff4bdd82561cad95278 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Wed, 9 Nov 2016 18:13:47 +0000 Subject: [PATCH 03/17] net: hns: fix for promisc mode in HNS driver If set promisc mode when there is some traffic, The service nic will cause system halted. We reserve the last 6 tcam entry for the 6 ports. If promisc mode is enabled, we can config the relative tcam as fuzzy matching and set to be valid, or set the tcam to be invalid Signed-off-by: Kejian Yan Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 2 + .../ethernet/hisilicon/hns/hns_dsaf_main.c | 63 +++++++++++++++++-- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 3 + .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 3 + 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 2d64f534f25e..fc90260607a4 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -1085,6 +1085,8 @@ void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en) { struct mac_driver *mac_ctrl_drv = hns_mac_get_drv(mac_cb); + hns_dsaf_set_promisc_tcam(mac_cb->dsaf_dev, mac_cb->mac_id, !!en); + if (mac_ctrl_drv->set_promiscuous) mac_ctrl_drv->set_promiscuous(mac_ctrl_drv, en); } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 64f45ee1ea3d..27214582fddb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -765,7 +765,7 @@ static void hns_dsaf_tbl_tcam_data_ucast_pul( void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en) { - if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) + if (AE_IS_VER1(dsaf_dev->dsaf_ver) && !HNS_DSAF_IS_DEBUG(dsaf_dev)) dsaf_set_dev_bit(dsaf_dev, DSAF_CFG_0_REG, DSAF_CFG_MIX_MODE_S, !!en); } @@ -1384,6 +1384,12 @@ static int hns_dsaf_init(struct dsaf_device *dsaf_dev) if (HNS_DSAF_IS_DEBUG(dsaf_dev)) return 0; + if (AE_IS_VER1(dsaf_dev->dsaf_ver)) + dsaf_dev->tcam_max_num = DSAF_TCAM_SUM; + else + dsaf_dev->tcam_max_num = + DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM; + spin_lock_init(&dsaf_dev->tcam_lock); ret = hns_dsaf_init_hw(dsaf_dev); if (ret) @@ -1439,7 +1445,7 @@ static u16 hns_dsaf_find_soft_mac_entry( u32 i; soft_mac_entry = priv->soft_mac_tbl; - for (i = 0; i < DSAF_TCAM_SUM; i++) { + for (i = 0; i < dsaf_dev->tcam_max_num; i++) { /* invall tab entry */ if ((soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX) && (soft_mac_entry->tcam_key.high.val == mac_key->high.val) && @@ -1464,7 +1470,7 @@ static u16 hns_dsaf_find_empty_mac_entry(struct dsaf_device *dsaf_dev) u32 i; soft_mac_entry = priv->soft_mac_tbl; - for (i = 0; i < DSAF_TCAM_SUM; i++) { + for (i = 0; i < dsaf_dev->tcam_max_num; i++) { /* inv all entry */ if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX) /* return find result --soft index */ @@ -2040,7 +2046,7 @@ int hns_dsaf_get_mac_entry_by_index( struct dsaf_tbl_tcam_ucast_cfg mac_uc_data; char mac_addr[ETH_ALEN] = {0}; - if (entry_index >= DSAF_TCAM_SUM) { + if (entry_index >= dsaf_dev->tcam_max_num) { /* find none, del error */ dev_err(dsaf_dev->dev, "get_uc_entry failed, %s\n", dsaf_dev->ae_dev.name); @@ -2732,6 +2738,55 @@ int hns_dsaf_get_regs_count(void) return DSAF_DUMP_REGS_NUM; } +/* Reserve the last TCAM entry for promisc support */ +#define dsaf_promisc_tcam_entry(port) \ + (DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM + (port)) +void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev, + u32 port, bool enable) +{ + struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + u16 entry_index; + struct dsaf_drv_tbl_tcam_key tbl_tcam_data, tbl_tcam_mask; + struct dsaf_tbl_tcam_mcast_cfg mac_data = {0}; + + if ((AE_IS_VER1(dsaf_dev->dsaf_ver)) || HNS_DSAF_IS_DEBUG(dsaf_dev)) + return; + + /* find the tcam entry index for promisc */ + entry_index = dsaf_promisc_tcam_entry(port); + + /* config key mask */ + if (enable) { + memset(&tbl_tcam_data, 0, sizeof(tbl_tcam_data)); + memset(&tbl_tcam_mask, 0, sizeof(tbl_tcam_mask)); + tbl_tcam_data.low.bits.port = port; + tbl_tcam_mask.low.bits.port = 0xf; /* [3:0]: port id */ + + /* SUB_QID */ + dsaf_set_bit(mac_data.tbl_mcast_port_msk[0], + DSAF_SERVICE_NW_NUM, true); + mac_data.tbl_mcast_item_vld = true; /* item_vld bit */ + } else { + mac_data.tbl_mcast_item_vld = false; /* item_vld bit */ + } + + dev_dbg(dsaf_dev->dev, + "set_promisc_entry, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, tbl_tcam_data.high.val, + tbl_tcam_data.low.val, entry_index); + + /* config promisc entry with mask */ + hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)&tbl_tcam_data, + (struct dsaf_tbl_tcam_data *)&tbl_tcam_mask, + &mac_data); + + /* config software entry */ + soft_mac_entry += entry_index; + soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX; +} + /** * dsaf_probe - probo dsaf dev * @pdev: dasf platform device diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index f832a3203365..2cae6ebf98b8 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -341,6 +341,7 @@ struct dsaf_device { enum hal_dsaf_mode dsaf_en; enum hal_dsaf_tc_mode dsaf_tc_mode; u32 dsaf_ver; + u16 tcam_max_num; /* max TCAM entry for user except promisc */ struct ppe_common_cb *ppe_common[DSAF_COMM_DEV_NUM]; struct rcb_common_cb *rcb_common[DSAF_COMM_DEV_NUM]; @@ -459,6 +460,8 @@ void hns_dsaf_get_strings(int stringset, u8 *data, int port, void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data); int hns_dsaf_get_regs_count(void); void hns_dsaf_set_promisc_mode(struct dsaf_device *dsaf_dev, u32 en); +void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev, + u32 port, bool enable); void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, u32 *en); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 6826b28875df..3eb8b4d6330f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -41,6 +41,9 @@ #define DSAF_SW_PORT_NUM 8 #define DSAF_TOTAL_QUEUE_NUM 129 +/* reserved a tcam entry for each port to support promisc by fuzzy match */ +#define DSAFV2_MAC_FUZZY_TCAM_NUM DSAF_MAX_PORT_NUM + #define DSAF_TCAM_SUM 512 #define DSAF_LINE_SUM (2048 * 14) From 2e7c80577e40f0968840455d7cff613c2ded316b Mon Sep 17 00:00:00 2001 From: Daode Huang Date: Wed, 9 Nov 2016 18:13:48 +0000 Subject: [PATCH 04/17] net: hns: set default mac pause time to 0xffff The default mac pause time set to 0xff which is too short for pausing, this patch change it to the max value 0xffff. Signed-off-by: Daode Huang Reviewed-by: Yisen Zhuang Reviewed-by: lipeng Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index 1d941d5a7362..a9b0cb3874aa 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -31,7 +31,7 @@ struct dsaf_device; #define MAC_MIN_MTU 68 #define MAC_MAX_MTU_DBG MAC_DEFAULT_MTU -#define MAC_DEFAULT_PAUSE_TIME 0xff +#define MAC_DEFAULT_PAUSE_TIME 0xffff #define MAC_GMAC_IDX 0 #define MAC_XGMAC_IDX 1 From da2ef1e5585bc733c4cccee8390259abeb27f0bf Mon Sep 17 00:00:00 2001 From: Daode Huang Date: Wed, 9 Nov 2016 18:13:49 +0000 Subject: [PATCH 05/17] net: hns: bug fix about restart auto-negotiation When set auto-negotiation off and duplex half, if run "ethtool -r ethX" on port with phy, then the port will be failed to work. It should forbid to start auto-negotiation when auto-negotiate is off. This patch add the limited condition. Reported-by: Jinchuang Tian Signed-off-by: Daode Huang Reviewed-by: Yisen Zhuang Reviewed-by: lipeng Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 87d5c94b2810..3ac2183dbd21 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -1178,7 +1178,8 @@ static int hns_nic_nway_reset(struct net_device *netdev) struct phy_device *phy = netdev->phydev; if (netif_running(netdev)) { - if (phy) + /* if autoneg is disabled, don't restart auto-negotiation */ + if (phy && phy->autoneg == AUTONEG_ENABLE) ret = genphy_restart_aneg(phy); } From f165e03b94e80be95d6f2cc21526c81906563046 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:50 +0000 Subject: [PATCH 06/17] net: hns: delete redundant macro definition This patch deletes redundant macro definitions in hns drivers. And change the .h file containing relation to make the layers more clearly Signed-off-by: Qianqian Xie Signed-off-by: Weiwei Deng Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c | 3 --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 2 +- drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 2d0cb609adc3..193248f754a1 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -18,9 +18,6 @@ #include "hns_dsaf_rcb.h" #define AE_NAME_PORT_ID_IDX 6 -#define ETH_STATIC_REG 1 -#define ETH_DUMP_REG 5 -#define ETH_GSTRING_LEN 32 static struct hns_mac_cb *hns_get_mac_cb(struct hnae_handle *handle) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index a9b0cb3874aa..ca7e17520f1d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -407,7 +407,7 @@ struct mac_driver { }; struct mac_stats_string { - char desc[64]; + char desc[ETH_GSTRING_LEN]; unsigned long offset; }; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index 3eb8b4d6330f..f5505e84352f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -314,7 +314,6 @@ #define PPE_COM_INTEN_REG 0x110 #define PPE_COM_RINT_REG 0x114 #define PPE_COM_INTSTS_REG 0x118 -#define PPE_COM_COMMON_CNT_CLR_CE_REG 0x1120 #define PPE_COM_HIS_RX_PKT_QID_DROP_CNT_REG 0x300 #define PPE_COM_HIS_RX_PKT_QID_OK_CNT_REG 0x600 #define PPE_COM_HIS_TX_PKT_QID_ERR_CNT_REG 0x900 From 28b3012400ad349ad633187c7e6e37352a22dd6e Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:51 +0000 Subject: [PATCH 07/17] net: hns: modify ethtool statistics value error This patch modify the gmac_rx_filt_pkt and gmac_rx_octets_total_filt statistics value. The two statistics is inconsistent with register, and just the opposite. Signed-off-by: Qianqian Xie Signed-off-by: Jun He Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c index 1e1eb92998fb..3382441fe7b5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -37,8 +37,8 @@ static const struct mac_stats_string g_gmac_stats_string[] = { {"gmac_rx_very_long_err", MAC_STATS_FIELD_OFF(rx_long_err)}, {"gmac_rx_runt_err", MAC_STATS_FIELD_OFF(rx_minto64)}, {"gmac_rx_short_err", MAC_STATS_FIELD_OFF(rx_under_min)}, - {"gmac_rx_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_bytes)}, - {"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_pkts)}, + {"gmac_rx_filt_pkt", MAC_STATS_FIELD_OFF(rx_filter_pkts)}, + {"gmac_rx_octets_total_filt", MAC_STATS_FIELD_OFF(rx_filter_bytes)}, {"gmac_rx_overrun_cnt", MAC_STATS_FIELD_OFF(rx_fifo_overrun_err)}, {"gmac_rx_length_err", MAC_STATS_FIELD_OFF(rx_len_err)}, {"gmac_rx_fail_comma", MAC_STATS_FIELD_OFF(rx_comma_err)}, From 20b3385aaab5af5127fa957bcfcaf0bd92b61447 Mon Sep 17 00:00:00 2001 From: Daode Huang Date: Wed, 9 Nov 2016 18:13:52 +0000 Subject: [PATCH 08/17] net: hns: fix to intimate the link-status change by adding LF/RF method In current scenario, when the interface is disabled we reset the XGMAC RX/TX functionality. This operation does not affects the PHY layer/SFP and which appears UP to the remote end(this behaviour is unlike GMAC). The result is remote end keeps on sending the packets which gets partly processed by XMAC and dropped. Since these are partly processed these appears as errored packets in the packet counter statistics. This patch fixes this behaviour and adds local-fault and remote-fault functionality which can be used to intimate the remote peer whenever the state of the interface changes. This patch also removes the existing hns_dsaf_xge_core_srst_by_port function which was being used to reset the RX/TX functionality at XGE Core. Reported-by: Jun He Signed-off-by: Daode Huang Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns/hns_dsaf_main.h | 2 - .../ethernet/hisilicon/hns/hns_dsaf_misc.c | 31 -------------- .../net/ethernet/hisilicon/hns/hns_dsaf_reg.h | 7 +++- .../ethernet/hisilicon/hns/hns_dsaf_xgmac.c | 41 +++++++++++++------ .../ethernet/hisilicon/hns/hns_dsaf_xgmac.h | 5 ++- 5 files changed, 37 insertions(+), 49 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 2cae6ebf98b8..7f70f34dc308 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -306,8 +306,6 @@ struct dsaf_misc_op { /* reset series function, it will be reset if the dereset is 0 */ void (*dsaf_reset)(struct dsaf_device *dsaf_dev, bool dereset); void (*xge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset); - void (*xge_core_srst)(struct dsaf_device *dsaf_dev, u32 port, - bool dereset); void (*ge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset); void (*ppe_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset); void (*ppe_comm_srst)(struct dsaf_device *dsaf_dev, bool dereset); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 67accce1d33d..a2c22d084ce9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -23,7 +23,6 @@ enum _dsm_op_index { enum _dsm_rst_type { HNS_DSAF_RESET_FUNC = 0x1, HNS_PPE_RESET_FUNC = 0x2, - HNS_XGE_CORE_RESET_FUNC = 0x3, HNS_XGE_RESET_FUNC = 0x4, HNS_GE_RESET_FUNC = 0x5, HNS_DSAF_CHN_RESET_FUNC = 0x6, @@ -213,26 +212,6 @@ static void hns_dsaf_xge_srst_by_port_acpi(struct dsaf_device *dsaf_dev, HNS_XGE_RESET_FUNC, port, dereset); } -static void hns_dsaf_xge_core_srst_by_port(struct dsaf_device *dsaf_dev, - u32 port, bool dereset) -{ - u32 reg_val = 0; - u32 reg_addr; - - if (port >= DSAF_XGE_NUM) - return; - - reg_val |= XGMAC_TRX_CORE_SRST_M - << dsaf_dev->mac_cb[port]->port_rst_off; - - if (!dereset) - reg_addr = DSAF_SUB_SC_XGE_RESET_REQ_REG; - else - reg_addr = DSAF_SUB_SC_XGE_RESET_DREQ_REG; - - dsaf_write_sub(dsaf_dev, reg_addr, reg_val); -} - /** * hns_dsaf_srst_chns - reset dsaf channels * @dsaf_dev: dsaf device struct pointer @@ -293,14 +272,6 @@ void hns_dsaf_roce_srst_acpi(struct dsaf_device *dsaf_dev, bool dereset) HNS_ROCE_RESET_FUNC, 0, dereset); } -static void -hns_dsaf_xge_core_srst_by_port_acpi(struct dsaf_device *dsaf_dev, - u32 port, bool dereset) -{ - hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC, - HNS_XGE_CORE_RESET_FUNC, port, dereset); -} - static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port, bool dereset) { @@ -597,7 +568,6 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) misc_op->dsaf_reset = hns_dsaf_rst; misc_op->xge_srst = hns_dsaf_xge_srst_by_port; - misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port; misc_op->ge_srst = hns_dsaf_ge_srst_by_port; misc_op->ppe_srst = hns_ppe_srst_by_port; misc_op->ppe_comm_srst = hns_ppe_com_srst; @@ -615,7 +585,6 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev) misc_op->dsaf_reset = hns_dsaf_rst_acpi; misc_op->xge_srst = hns_dsaf_xge_srst_by_port_acpi; - misc_op->xge_core_srst = hns_dsaf_xge_core_srst_by_port_acpi; misc_op->ge_srst = hns_dsaf_ge_srst_by_port_acpi; misc_op->ppe_srst = hns_ppe_srst_by_port_acpi; misc_op->ppe_comm_srst = hns_ppe_com_srst; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index f5505e84352f..87226685f742 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -702,8 +702,6 @@ #define XGMAC_RX_SYMBOLERRPKTS 0x0210 #define XGMAC_RX_FCSERRPKTS 0x0218 -#define XGMAC_TRX_CORE_SRST_M 0x2080 - #define DSAF_SRAM_INIT_OVER_M 0xff #define DSAFV2_SRAM_INIT_OVER_M 0x3ff #define DSAF_SRAM_INIT_OVER_S 0 @@ -982,6 +980,11 @@ #define XGMAC_ENABLE_TX_B 0 #define XGMAC_ENABLE_RX_B 1 +#define XGMAC_UNIDIR_EN_B 0 +#define XGMAC_RF_TX_EN_B 1 +#define XGMAC_LF_RF_INSERT_S 2 +#define XGMAC_LF_RF_INSERT_M (0x3 << XGMAC_LF_RF_INSERT_S) + #define XGMAC_CTL_TX_FCS_B 0 #define XGMAC_CTL_TX_PAD_B 1 #define XGMAC_CTL_TX_PREAMBLE_TRANS_B 3 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c index 8f4f0e8da984..aae830a93050 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.c @@ -107,6 +107,31 @@ static void hns_xgmac_rx_enable(struct mac_driver *drv, u32 value) dsaf_set_dev_bit(drv, XGMAC_MAC_ENABLE_REG, XGMAC_ENABLE_RX_B, !!value); } +/** + * hns_xgmac_tx_lf_rf_insert - insert lf rf control about xgmac + * @mac_drv: mac driver + * @mode: inserf rf or lf + */ +static void hns_xgmac_lf_rf_insert(struct mac_driver *mac_drv, u32 mode) +{ + dsaf_set_dev_field(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG, + XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, mode); +} + +/** + * hns_xgmac__lf_rf_control_init - initial the lf rf control register + * @mac_drv: mac driver + */ +static void hns_xgmac_lf_rf_control_init(struct mac_driver *mac_drv) +{ + u32 val = 0; + + dsaf_set_bit(val, XGMAC_UNIDIR_EN_B, 0); + dsaf_set_bit(val, XGMAC_RF_TX_EN_B, 1); + dsaf_set_field(val, XGMAC_LF_RF_INSERT_M, XGMAC_LF_RF_INSERT_S, 0); + dsaf_write_reg(mac_drv, XGMAC_MAC_TX_LF_RF_CONTROL_REG, val); +} + /** *hns_xgmac_enable - enable xgmac port *@drv: mac driver @@ -115,12 +140,8 @@ static void hns_xgmac_rx_enable(struct mac_driver *drv, u32 value) static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode) { struct mac_driver *drv = (struct mac_driver *)mac_drv; - struct dsaf_device *dsaf_dev - = (struct dsaf_device *)dev_get_drvdata(drv->dev); - u32 port = drv->mac_id; - dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 1); - mdelay(10); + hns_xgmac_lf_rf_insert(drv, HNS_XGMAC_NO_LF_RF_INSERT); /*enable XGE rX/tX */ if (mode == MAC_COMM_MODE_TX) { @@ -143,9 +164,6 @@ static void hns_xgmac_enable(void *mac_drv, enum mac_commom_mode mode) static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode) { struct mac_driver *drv = (struct mac_driver *)mac_drv; - struct dsaf_device *dsaf_dev - = (struct dsaf_device *)dev_get_drvdata(drv->dev); - u32 port = drv->mac_id; if (mode == MAC_COMM_MODE_TX) { hns_xgmac_tx_enable(drv, 0); @@ -155,9 +173,7 @@ static void hns_xgmac_disable(void *mac_drv, enum mac_commom_mode mode) hns_xgmac_tx_enable(drv, 0); hns_xgmac_rx_enable(drv, 0); } - - mdelay(10); - dsaf_dev->misc_op->xge_core_srst(dsaf_dev, port, 0); + hns_xgmac_lf_rf_insert(drv, HNS_XGMAC_LF_INSERT); } /** @@ -203,6 +219,7 @@ static void hns_xgmac_init(void *mac_drv) dsaf_dev->misc_op->xge_srst(dsaf_dev, port, 1); mdelay(100); + hns_xgmac_lf_rf_control_init(drv); hns_xgmac_exc_irq_en(drv, 0); hns_xgmac_pma_fec_enable(drv, 0x0, 0x0); @@ -788,7 +805,7 @@ static int hns_xgmac_get_sset_count(int stringset) */ static int hns_xgmac_get_regs_count(void) { - return ETH_XGMAC_DUMP_NUM; + return HNS_XGMAC_DUMP_NUM; } void *hns_xgmac_config(struct hns_mac_cb *mac_cb, struct mac_params *mac_param) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h index 139f7297c7b4..da6c5343d3e1 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_xgmac.h @@ -10,6 +10,7 @@ #ifndef _HNS_XGMAC_H #define _HNS_XGMAC_H -#define ETH_XGMAC_DUMP_NUM (214) - +#define HNS_XGMAC_DUMP_NUM 214 +#define HNS_XGMAC_NO_LF_RF_INSERT 0x0 +#define HNS_XGMAC_LF_INSERT 0x2 #endif From d30721d459fb73a797f004b0d05e8eab2e7f1944 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:53 +0000 Subject: [PATCH 09/17] net: hns: modify buffer format of cpu data to le64 Hardware ring buffer data is stored in Little-endian. Thus cpu data should be modified to Little-endian. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index e093cbf26c8c..b0f05578c15d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -590,7 +590,7 @@ static inline int hnae_alloc_buffer_attach(struct hnae_ring *ring, int i) if (ret) return ret; - ring->desc[i].addr = (__le64)ring->desc_cb[i].dma; + ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma); return 0; } @@ -621,14 +621,14 @@ static inline void hnae_replace_buffer(struct hnae_ring *ring, int i, bops->unmap_buffer(ring, &ring->desc_cb[i]); ring->desc_cb[i] = *res_cb; - ring->desc[i].addr = (__le64)ring->desc_cb[i].dma; + ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma); ring->desc[i].rx.ipoff_bnum_pid_flag = 0; } static inline void hnae_reuse_buffer(struct hnae_ring *ring, int i) { ring->desc_cb[i].reuse_flag = 0; - ring->desc[i].addr = (__le64)(ring->desc_cb[i].dma + ring->desc[i].addr = cpu_to_le64(ring->desc_cb[i].dma + ring->desc_cb[i].page_offset); ring->desc[i].rx.ipoff_bnum_pid_flag = 0; } From 5483bfcb169cf3e68196bb6f28a43107fb48022c Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:54 +0000 Subject: [PATCH 10/17] net: hns: modify tcam table and set mac key The current definition of dsaf_drv_tbl_tcam_key is only suitable for Little-endian. If data is stored in Big-endian, this may lead to error in data use. Shift operation can make it work normally in both Big-endian and Little-endian. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_main.c | 16 ++++++++++++---- .../net/ethernet/hisilicon/hns/hns_dsaf_main.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 27214582fddb..db23eef1996b 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1509,8 +1509,12 @@ static void hns_dsaf_set_mac_key( mac_key->high.bits.mac_3 = addr[3]; mac_key->low.bits.mac_4 = addr[4]; mac_key->low.bits.mac_5 = addr[5]; - mac_key->low.bits.vlan = vlan_id; - mac_key->low.bits.port = port; + dsaf_set_field(mac_key->low.bits.port_vlan, DSAF_TBL_TCAM_KEY_VLAN_M, + DSAF_TBL_TCAM_KEY_VLAN_S, vlan_id); + dsaf_set_field(mac_key->low.bits.port_vlan, DSAF_TBL_TCAM_KEY_PORT_M, + DSAF_TBL_TCAM_KEY_PORT_S, port); + + mac_key->low.bits.port_vlan = le16_to_cpu(mac_key->low.bits.port_vlan); } /** @@ -2760,8 +2764,12 @@ void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev, if (enable) { memset(&tbl_tcam_data, 0, sizeof(tbl_tcam_data)); memset(&tbl_tcam_mask, 0, sizeof(tbl_tcam_mask)); - tbl_tcam_data.low.bits.port = port; - tbl_tcam_mask.low.bits.port = 0xf; /* [3:0]: port id */ + dsaf_set_field(tbl_tcam_data.low.bits.port_vlan, + DSAF_TBL_TCAM_KEY_PORT_M, + DSAF_TBL_TCAM_KEY_PORT_S, port); + dsaf_set_field(tbl_tcam_mask.low.bits.port_vlan, + DSAF_TBL_TCAM_KEY_PORT_M, + DSAF_TBL_TCAM_KEY_PORT_S, 0xf); /* SUB_QID */ dsaf_set_bit(mac_data.tbl_mcast_port_msk[0], diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 7f70f34dc308..c68555b491ed 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -357,6 +357,11 @@ static inline void *hns_dsaf_dev_priv(const struct dsaf_device *dsaf_dev) return (void *)((u8 *)dsaf_dev + sizeof(*dsaf_dev)); } +#define DSAF_TBL_TCAM_KEY_PORT_S 0 +#define DSAF_TBL_TCAM_KEY_PORT_M (((1ULL << 4) - 1) << 0) +#define DSAF_TBL_TCAM_KEY_VLAN_S 4 +#define DSAF_TBL_TCAM_KEY_VLAN_M (((1ULL << 12) - 1) << 4) + struct dsaf_drv_tbl_tcam_key { union { struct { @@ -370,11 +375,9 @@ struct dsaf_drv_tbl_tcam_key { } high; union { struct { - u32 port:4; /* port id, */ - /* dsaf-mode fixed 0, non-dsaf-mode port id*/ - u32 vlan:12; /* vlan id */ - u32 mac_5:8; - u32 mac_4:8; + u16 port_vlan; + u8 mac_5; + u8 mac_4; } bits; u32 val; From c9c0b37072f5d75ec498539c90ab7113e02c26d6 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:55 +0000 Subject: [PATCH 11/17] net: hns: modify tcam table of mac uc-entry The current definition of mac_uc_entry is only suitable for Little-endian. Thus it needs to modify tcam table of mac uc-entry to support both Little-endian and Big-endian. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_main.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index db23eef1996b..1713f8d835a2 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1532,6 +1532,7 @@ int hns_dsaf_set_mac_uc_entry( struct dsaf_drv_priv *priv = (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + struct dsaf_tbl_tcam_data tcam_data; /* mac addr check */ if (MAC_IS_ALL_ZEROS(mac_entry->addr) || @@ -1573,9 +1574,10 @@ int hns_dsaf_set_mac_uc_entry( /* default config dvc to 0 */ mac_data.tbl_ucast_dvc = 0; mac_data.tbl_ucast_out_port = mac_entry->port_num; - hns_dsaf_tcam_uc_cfg( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&mac_key), &mac_data); + tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val); + tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val); + + hns_dsaf_tcam_uc_cfg(dsaf_dev, entry_index, &tcam_data, &mac_data); /* config software entry */ soft_mac_entry += entry_index; @@ -1950,6 +1952,7 @@ int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev, struct dsaf_drv_tbl_tcam_key mac_key; struct dsaf_tbl_tcam_ucast_cfg mac_data; + struct dsaf_tbl_tcam_data tcam_data; /* check macaddr */ if (MAC_IS_ALL_ZEROS(mac_entry->addr) || @@ -1978,9 +1981,12 @@ int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev, dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val, entry_index); - /*read entry*/ - hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data); + /* read entry */ + hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data, &mac_data); + + mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high); + mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); + mac_entry->port_num = mac_data.tbl_ucast_out_port; return 0; From 39a6c9ebcbc6b6c3f3aefbe5449eb45d78f2034f Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:56 +0000 Subject: [PATCH 12/17] net: hns: modify table index to get mac entry Big-endian is not supported by the current definition of table index to get mac entry. It needs to be modified to support both Little-endian and Big-endian. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 1713f8d835a2..bd6e5b037731 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -2054,6 +2054,7 @@ int hns_dsaf_get_mac_entry_by_index( struct dsaf_tbl_tcam_mcast_cfg mac_data; struct dsaf_tbl_tcam_ucast_cfg mac_uc_data; + struct dsaf_tbl_tcam_data tcam_data; char mac_addr[ETH_ALEN] = {0}; if (entry_index >= dsaf_dev->tcam_max_num) { @@ -2064,8 +2065,10 @@ int hns_dsaf_get_mac_entry_by_index( } /* mc entry, do read opt */ - hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data); + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data); + + mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high); + mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F; @@ -2082,9 +2085,12 @@ int hns_dsaf_get_mac_entry_by_index( /**mc donot do*/ } else { /*is not mc, just uc... */ - hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)&mac_key, + hns_dsaf_tcam_uc_get(dsaf_dev, entry_index, &tcam_data, &mac_uc_data); + + mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high); + mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); + mac_entry->port_mask[0] = (1 << mac_uc_data.tbl_ucast_out_port); } From 928971b6bc95ae13d2d77c2b7b265c379bf0189d Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:57 +0000 Subject: [PATCH 13/17] net: hns: modify tcam table of mac mc-port Little-endian is only supported by current tcam table to add or delete mac mc-port. This patch makes it support both Little-endian and Big-endian. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../net/ethernet/hisilicon/hns/hns_dsaf_main.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index bd6e5b037731..27eb85c1bef4 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1688,6 +1688,7 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, struct dsaf_tbl_tcam_mcast_cfg mac_data; struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev); struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; + struct dsaf_drv_tbl_tcam_key tmp_mac_key; struct dsaf_tbl_tcam_data tcam_data; u8 mc_addr[ETH_ALEN]; u8 *mc_mask; @@ -1738,6 +1739,10 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, /* if exist, add in */ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data); + + tmp_mac_key.high.val = + le32_to_cpu(tcam_data.tbl_tcam_data_high); + tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); } /* config hardware entry */ @@ -1762,8 +1767,8 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val, entry_index); - tcam_data.tbl_tcam_data_high = mac_key.high.val; - tcam_data.tbl_tcam_data_low = mac_key.low.val; + tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val); + tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val); /* config mc entry with mask */ hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data, @@ -1847,7 +1852,7 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, struct dsaf_tbl_tcam_data tcam_data; int mskid; const u8 empty_msk[sizeof(mac_data.tbl_mcast_port_msk)] = {0}; - struct dsaf_drv_tbl_tcam_key mask_key; + struct dsaf_drv_tbl_tcam_key mask_key, tmp_mac_key; struct dsaf_tbl_tcam_data *pmask_key = NULL; u8 mc_addr[ETH_ALEN]; u8 *mc_mask; @@ -1905,6 +1910,9 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, /* read entry */ hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data); + tmp_mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high); + tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); + /*del the port*/ if (mac_entry->port_num < DSAF_SERVICE_NW_NUM) { mskid = mac_entry->port_num; @@ -1929,8 +1937,8 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, soft_mac_entry += entry_index; soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX; } else { /* not zero, just del port, update */ - tcam_data.tbl_tcam_data_high = mac_key.high.val; - tcam_data.tbl_tcam_data_low = mac_key.low.val; + tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val); + tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val); hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data, From 9d189b853cbca36453676d9152239715965c2a86 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:58 +0000 Subject: [PATCH 14/17] net: hns: modify tcam table of mac mc-entry The current definition of mac_mc_entry is only suitable for Little-endian. Thus it needs to modify tcam table of mac mc-entry to support both Little-endian and Big-endian. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns/hns_dsaf_main.c | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 27eb85c1bef4..74ca53d85f5f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1604,6 +1604,7 @@ int hns_dsaf_set_mac_mc_entry( (struct dsaf_drv_priv *)hns_dsaf_dev_priv(dsaf_dev); struct dsaf_drv_soft_mac_tbl *soft_mac_entry = priv->soft_mac_tbl; struct dsaf_drv_tbl_tcam_key tmp_mac_key; + struct dsaf_tbl_tcam_data tcam_data; /* mac addr check */ if (MAC_IS_ALL_ZEROS(mac_entry->addr)) { @@ -1636,9 +1637,12 @@ int hns_dsaf_set_mac_mc_entry( 0, sizeof(mac_data.tbl_mcast_port_msk)); } else { /* config hardware entry */ - hns_dsaf_tcam_mc_get( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&tmp_mac_key), &mac_data); + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, + &mac_data); + + tmp_mac_key.high.val = + le32_to_cpu(tcam_data.tbl_tcam_data_high); + tmp_mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); } mac_data.tbl_mcast_old_en = 0; mac_data.tbl_mcast_item_vld = 1; @@ -1650,9 +1654,11 @@ int hns_dsaf_set_mac_mc_entry( dsaf_dev->ae_dev.name, mac_key.high.val, mac_key.low.val, entry_index); - hns_dsaf_tcam_mc_cfg( - dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)(&mac_key), NULL, &mac_data); + tcam_data.tbl_tcam_data_high = cpu_to_le32(mac_key.high.val); + tcam_data.tbl_tcam_data_low = cpu_to_le32(mac_key.low.val); + + hns_dsaf_tcam_mc_cfg(dsaf_dev, entry_index, &tcam_data, NULL, + &mac_data); /* config software entry */ soft_mac_entry += entry_index; @@ -2012,6 +2018,7 @@ int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev, struct dsaf_drv_tbl_tcam_key mac_key; struct dsaf_tbl_tcam_mcast_cfg mac_data; + struct dsaf_tbl_tcam_data tcam_data; /*check mac addr */ if (MAC_IS_ALL_ZEROS(mac_entry->addr) || @@ -2041,8 +2048,10 @@ int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev, mac_key.low.val, entry_index); /*read entry */ - hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, - (struct dsaf_tbl_tcam_data *)&mac_key, &mac_data); + hns_dsaf_tcam_mc_get(dsaf_dev, entry_index, &tcam_data, &mac_data); + + mac_key.high.val = le32_to_cpu(tcam_data.tbl_tcam_data_high); + mac_key.low.val = le32_to_cpu(tcam_data.tbl_tcam_data_low); mac_entry->port_mask[0] = mac_data.tbl_mcast_port_msk[0] & 0x3F; return 0; From 590457f4ec3d8a7963be95f3fc4ae916ccd67533 Mon Sep 17 00:00:00 2001 From: Qianqian Xie Date: Wed, 9 Nov 2016 18:13:59 +0000 Subject: [PATCH 15/17] net: hns: modify tcam table of mask_key The packets of wrong mac address(only the last bit is different) can be received in Big-endian by current definition of mask_key. Thus it needs to be modified to support Big-endian and ensure Big-endian normal. Signed-off-by: Qianqian Xie Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 74ca53d85f5f..250e4a1d5c79 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1718,6 +1718,10 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, 0x0, 0xff, mc_mask); + + mask_key.high.val = le32_to_cpu(mask_key.high.val); + mask_key.low.val = le32_to_cpu(mask_key.low.val); + pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key); } @@ -1887,6 +1891,9 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, /* config key mask */ hns_dsaf_set_mac_key(dsaf_dev, &mask_key, 0x00, 0xff, mc_addr); + mask_key.high.val = le32_to_cpu(mask_key.high.val); + mask_key.low.val = le32_to_cpu(mask_key.low.val); + pmask_key = (struct dsaf_tbl_tcam_data *)(&mask_key); } From ec2cafe68267d88a6290a734d780d680fee50b4f Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Wed, 9 Nov 2016 18:14:00 +0000 Subject: [PATCH 16/17] net: hns: add multicast tcam table clear There is no clear operation before add a new multicast tcam table, so the tcam table will be overflow when add more entries. Reported-by: Daode Huang Signed-off-by: Kejian Yan Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 3 + .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 11 +++ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 12 +++ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 1 + .../ethernet/hisilicon/hns/hns_dsaf_main.c | 79 +++++++++++++++++++ .../ethernet/hisilicon/hns/hns_dsaf_main.h | 3 + drivers/net/ethernet/hisilicon/hns/hns_enet.c | 4 + 7 files changed, 113 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index b0f05578c15d..55c0334270bb 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -426,6 +426,8 @@ enum hnae_media_type { * get mac address * set_mac_addr() * set mac address + * clr_mc_addr() + * clear mcast tcam table * set_mc_addr() * set multicast mode * set_mtu() @@ -488,6 +490,7 @@ struct hnae_ae_ops { void (*set_promisc_mode)(struct hnae_handle *handle, u32 en); int (*get_mac_addr)(struct hnae_handle *handle, void **p); int (*set_mac_addr)(struct hnae_handle *handle, void *p); + int (*clr_mc_addr)(struct hnae_handle *handle); int (*set_mc_addr)(struct hnae_handle *handle, void *addr); int (*set_mtu)(struct hnae_handle *handle, int new_mtu); void (*set_tso_stats)(struct hnae_handle *handle, int enable); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 193248f754a1..366b25b29ca8 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -232,6 +232,16 @@ static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr) return ret; } +static int hns_ae_clr_multicast(struct hnae_handle *handle) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + if (mac_cb->mac_type != HNAE_PORT_SERVICE) + return 0; + + return hns_mac_clr_multicast(mac_cb, handle->vf_id); +} + static int hns_ae_set_mtu(struct hnae_handle *handle, int new_mtu) { struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); @@ -821,6 +831,7 @@ static struct hnae_ae_ops hns_dsaf_ops = { .set_promisc_mode = hns_ae_set_promisc_mode, .set_mac_addr = hns_ae_set_mac_address, .set_mc_addr = hns_ae_set_multicast_one, + .clr_mc_addr = hns_ae_clr_multicast, .set_mtu = hns_ae_set_mtu, .update_stats = hns_ae_update_stats, .set_tso_stats = hns_ae_set_tso_stats, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index fc90260607a4..266417db2b70 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -330,6 +330,18 @@ int hns_mac_del_mac(struct hns_mac_cb *mac_cb, u32 vfn, char *mac) return 0; } +int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn) +{ + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + u8 port_num; + int ret = hns_mac_get_inner_port_num(mac_cb, vfn, &port_num); + + if (ret) + return ret; + + return hns_dsaf_clr_mac_mc_port(dsaf_dev, mac_cb->mac_id, port_num); +} + static void hns_mac_param_get(struct mac_params *param, struct hns_mac_cb *mac_cb) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index ca7e17520f1d..d8964527a028 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -461,5 +461,6 @@ int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb, void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en); int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, u8 vmid, u8 *port_num); +int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn); #endif /* _HNS_DSAF_MAC_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 250e4a1d5c79..ebecbed20ea2 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -959,6 +959,16 @@ static void hns_dsaf_tcam_mc_invld(struct dsaf_device *dsaf_dev, u32 address) spin_unlock_bh(&dsaf_dev->tcam_lock); } +void hns_dsaf_tcam_addr_get(struct dsaf_drv_tbl_tcam_key *mac_key, u8 *addr) +{ + addr[0] = mac_key->high.bits.mac_0; + addr[1] = mac_key->high.bits.mac_1; + addr[2] = mac_key->high.bits.mac_2; + addr[3] = mac_key->high.bits.mac_3; + addr[4] = mac_key->low.bits.mac_4; + addr[5] = mac_key->low.bits.mac_5; +} + /** * hns_dsaf_tcam_uc_get - INT * @dsaf_id: dsa fabric id @@ -1961,6 +1971,75 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, return 0; } +int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev, u8 mac_id, + u8 port_num) +{ + struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev); + struct dsaf_drv_soft_mac_tbl *soft_mac_entry; + struct dsaf_tbl_tcam_mcast_cfg mac_data; + int ret = 0, i; + + if (HNS_DSAF_IS_DEBUG(dsaf_dev)) + return 0; + + for (i = 0; i < DSAF_TCAM_SUM - DSAFV2_MAC_FUZZY_TCAM_NUM; i++) { + u8 addr[ETH_ALEN]; + u8 port; + + soft_mac_entry = priv->soft_mac_tbl + i; + + hns_dsaf_tcam_addr_get(&soft_mac_entry->tcam_key, addr); + port = dsaf_get_field( + soft_mac_entry->tcam_key.low.bits.port_vlan, + DSAF_TBL_TCAM_KEY_PORT_M, + DSAF_TBL_TCAM_KEY_PORT_S); + /* check valid tcam mc entry */ + if (soft_mac_entry->index != DSAF_INVALID_ENTRY_IDX && + port == mac_id && + is_multicast_ether_addr(addr) && + !is_broadcast_ether_addr(addr)) { + const u32 empty_msk[DSAF_PORT_MSK_NUM] = {0}; + struct dsaf_drv_mac_single_dest_entry mac_entry; + + /* disable receiving of this multicast address for + * the VF. + */ + ether_addr_copy(mac_entry.addr, addr); + mac_entry.in_vlan_id = dsaf_get_field( + soft_mac_entry->tcam_key.low.bits.port_vlan, + DSAF_TBL_TCAM_KEY_VLAN_M, + DSAF_TBL_TCAM_KEY_VLAN_S); + mac_entry.in_port_num = mac_id; + mac_entry.port_num = port_num; + if (hns_dsaf_del_mac_mc_port(dsaf_dev, &mac_entry)) { + ret = -EINVAL; + continue; + } + + /* disable receiving of this multicast address for + * the mac port if all VF are disable + */ + hns_dsaf_tcam_mc_get(dsaf_dev, i, + (struct dsaf_tbl_tcam_data *) + (&soft_mac_entry->tcam_key), + &mac_data); + dsaf_set_bit(mac_data.tbl_mcast_port_msk[mac_id / 32], + mac_id % 32, 0); + if (!memcmp(mac_data.tbl_mcast_port_msk, empty_msk, + sizeof(u32) * DSAF_PORT_MSK_NUM)) { + mac_entry.port_num = mac_id; + if (hns_dsaf_del_mac_mc_port(dsaf_dev, + &mac_entry)) { + ret = -EINVAL; + continue; + } + } + } + } + + return ret; +} + /** * hns_dsaf_get_mac_uc_entry - get mac uc entry * @dsaf_dev: dsa fabric device struct pointer diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index c68555b491ed..901037c49a78 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -468,5 +468,8 @@ void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, u32 *en); int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, u32 en); +int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev, + u8 mac_id, u8 port_num); + #endif /* __HNS_DSAF_MAIN_H__ */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 60831a2ac86b..d22a39e7ddb0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1511,6 +1511,10 @@ void hns_set_multicast_list(struct net_device *ndev) return; } + if (h->dev->ops->clr_mc_addr) + if (h->dev->ops->clr_mc_addr(h)) + netdev_err(ndev, "clear multicast address fail\n"); + if (h->dev->ops->set_mc_addr) { netdev_for_each_mc_addr(ha, ndev) if (h->dev->ops->set_mc_addr(h, ha->addr)) From 66355f52ca95926af0389121f1d3f51d991f0e02 Mon Sep 17 00:00:00 2001 From: Kejian Yan Date: Wed, 9 Nov 2016 18:14:01 +0000 Subject: [PATCH 17/17] net: hns: add the support to add/remove the ucast entry to/from table This patch adds the support to add or remove the unicast entries to the table and remove from the table. Reported-by: Daode Huang Signed-off-by: Kejian Yan Reviewed-by: Yisen Zhuang Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns/hnae.h | 8 +++ .../net/ethernet/hisilicon/hns/hns_ae_adapt.c | 24 +++++++++ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 40 +++++++++++++++ .../net/ethernet/hisilicon/hns/hns_dsaf_mac.h | 4 ++ .../ethernet/hisilicon/hns/hns_dsaf_main.c | 49 +++++++++++++++++++ .../ethernet/hisilicon/hns/hns_dsaf_main.h | 4 ++ drivers/net/ethernet/hisilicon/hns/hns_enet.c | 26 ++++++++++ 7 files changed, 155 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 55c0334270bb..09602f1187f5 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -430,6 +430,10 @@ enum hnae_media_type { * clear mcast tcam table * set_mc_addr() * set multicast mode + * add_uc_addr() + * add ucast address + * rm_uc_addr() + * remove ucast address * set_mtu() * set mtu * update_stats() @@ -490,6 +494,10 @@ struct hnae_ae_ops { void (*set_promisc_mode)(struct hnae_handle *handle, u32 en); int (*get_mac_addr)(struct hnae_handle *handle, void **p); int (*set_mac_addr)(struct hnae_handle *handle, void *p); + int (*add_uc_addr)(struct hnae_handle *handle, + const unsigned char *addr); + int (*rm_uc_addr)(struct hnae_handle *handle, + const unsigned char *addr); int (*clr_mc_addr)(struct hnae_handle *handle); int (*set_mc_addr)(struct hnae_handle *handle, void *addr); int (*set_mtu)(struct hnae_handle *handle, int new_mtu); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 366b25b29ca8..0a9cdf00b31a 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -199,6 +199,28 @@ static int hns_ae_set_mac_address(struct hnae_handle *handle, void *p) return 0; } +static int hns_ae_add_uc_address(struct hnae_handle *handle, + const unsigned char *addr) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + if (mac_cb->mac_type != HNAE_PORT_SERVICE) + return -ENOSPC; + + return hns_mac_add_uc_addr(mac_cb, handle->vf_id, addr); +} + +static int hns_ae_rm_uc_address(struct hnae_handle *handle, + const unsigned char *addr) +{ + struct hns_mac_cb *mac_cb = hns_get_mac_cb(handle); + + if (mac_cb->mac_type != HNAE_PORT_SERVICE) + return -ENOSPC; + + return hns_mac_rm_uc_addr(mac_cb, handle->vf_id, addr); +} + static int hns_ae_set_multicast_one(struct hnae_handle *handle, void *addr) { int ret; @@ -830,6 +852,8 @@ static struct hnae_ae_ops hns_dsaf_ops = { .get_coalesce_range = hns_ae_get_coalesce_range, .set_promisc_mode = hns_ae_set_promisc_mode, .set_mac_addr = hns_ae_set_mac_address, + .add_uc_addr = hns_ae_add_uc_address, + .rm_uc_addr = hns_ae_rm_uc_address, .set_mc_addr = hns_ae_set_multicast_one, .clr_mc_addr = hns_ae_clr_multicast, .set_mtu = hns_ae_set_mtu, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index 266417db2b70..3239d27143b9 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -263,6 +263,46 @@ int hns_mac_change_vf_addr(struct hns_mac_cb *mac_cb, return 0; } +int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id, + const unsigned char *addr) +{ + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + struct dsaf_drv_mac_single_dest_entry mac_entry; + int ret; + + if (HNS_DSAF_IS_DEBUG(dsaf_dev)) + return -ENOSPC; + + memset(&mac_entry, 0, sizeof(mac_entry)); + memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + mac_entry.in_port_num = mac_cb->mac_id; + ret = hns_mac_get_inner_port_num(mac_cb, vf_id, &mac_entry.port_num); + if (ret) + return ret; + + return hns_dsaf_set_mac_uc_entry(dsaf_dev, &mac_entry); +} + +int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id, + const unsigned char *addr) +{ + struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; + struct dsaf_drv_mac_single_dest_entry mac_entry; + int ret; + + if (HNS_DSAF_IS_DEBUG(dsaf_dev)) + return -ENOSPC; + + memset(&mac_entry, 0, sizeof(mac_entry)); + memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + mac_entry.in_port_num = mac_cb->mac_id; + ret = hns_mac_get_inner_port_num(mac_cb, vf_id, &mac_entry.port_num); + if (ret) + return ret; + + return hns_dsaf_rm_mac_addr(dsaf_dev, &mac_entry); +} + int hns_mac_set_multi(struct hns_mac_cb *mac_cb, u32 port_num, char *addr, bool enable) { diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h index d8964527a028..2bb3d1e93c64 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h @@ -461,6 +461,10 @@ int hns_cpld_led_set_id(struct hns_mac_cb *mac_cb, void hns_mac_set_promisc(struct hns_mac_cb *mac_cb, u8 en); int hns_mac_get_inner_port_num(struct hns_mac_cb *mac_cb, u8 vmid, u8 *port_num); +int hns_mac_add_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id, + const unsigned char *addr); +int hns_mac_rm_uc_addr(struct hns_mac_cb *mac_cb, u8 vf_id, + const unsigned char *addr); int hns_mac_clr_multicast(struct hns_mac_cb *mac_cb, int vfn); #endif /* _HNS_DSAF_MAC_H */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index ebecbed20ea2..90dbda792614 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1598,6 +1598,55 @@ int hns_dsaf_set_mac_uc_entry( return 0; } +int hns_dsaf_rm_mac_addr( + struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry) +{ + u16 entry_index = DSAF_INVALID_ENTRY_IDX; + struct dsaf_tbl_tcam_ucast_cfg mac_data; + struct dsaf_drv_tbl_tcam_key mac_key; + + /* mac addr check */ + if (!is_valid_ether_addr(mac_entry->addr)) { + dev_err(dsaf_dev->dev, "rm_uc_addr %s Mac %pM err!\n", + dsaf_dev->ae_dev.name, mac_entry->addr); + return -EINVAL; + } + + /* config key */ + hns_dsaf_set_mac_key(dsaf_dev, &mac_key, mac_entry->in_vlan_id, + mac_entry->in_port_num, mac_entry->addr); + + entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key); + if (entry_index == DSAF_INVALID_ENTRY_IDX) { + /* can not find the tcam entry, return 0 */ + dev_info(dsaf_dev->dev, + "rm_uc_addr no tcam, %s Mac key(%#x:%#x)\n", + dsaf_dev->ae_dev.name, + mac_key.high.val, mac_key.low.val); + return 0; + } + + dev_dbg(dsaf_dev->dev, + "rm_uc_addr, %s Mac key(%#x:%#x) entry_index%d\n", + dsaf_dev->ae_dev.name, mac_key.high.val, + mac_key.low.val, entry_index); + + hns_dsaf_tcam_uc_get( + dsaf_dev, entry_index, + (struct dsaf_tbl_tcam_data *)&mac_key, + &mac_data); + + /* unicast entry not used locally should not clear */ + if (mac_entry->port_num != mac_data.tbl_ucast_out_port) + return -EFAULT; + + return hns_dsaf_del_mac_entry(dsaf_dev, + mac_entry->in_vlan_id, + mac_entry->in_port_num, + mac_entry->addr); +} + /** * hns_dsaf_set_mac_mc_entry - set mac mc-entry * @dsaf_dev: dsa fabric device struct pointer diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h index 901037c49a78..cef6bf46ae93 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h @@ -468,6 +468,10 @@ void hns_dsaf_get_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, u32 *en); int hns_dsaf_set_rx_mac_pause_en(struct dsaf_device *dsaf_dev, int mac_id, u32 en); +int hns_dsaf_rm_mac_addr( + struct dsaf_device *dsaf_dev, + struct dsaf_drv_mac_single_dest_entry *mac_entry); + int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev, u8 mac_id, u8 port_num); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index d22a39e7ddb0..776d81e785d8 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1493,6 +1493,29 @@ static netdev_features_t hns_nic_fix_features( return features; } +static int hns_nic_uc_sync(struct net_device *netdev, const unsigned char *addr) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + + if (h->dev->ops->add_uc_addr) + return h->dev->ops->add_uc_addr(h, addr); + + return 0; +} + +static int hns_nic_uc_unsync(struct net_device *netdev, + const unsigned char *addr) +{ + struct hns_nic_priv *priv = netdev_priv(netdev); + struct hnae_handle *h = priv->ae_handle; + + if (h->dev->ops->rm_uc_addr) + return h->dev->ops->rm_uc_addr(h, addr); + + return 0; +} + /** * nic_set_multicast_list - set mutl mac address * @netdev: net device @@ -1535,6 +1558,9 @@ void hns_nic_set_rx_mode(struct net_device *ndev) } hns_set_multicast_list(ndev); + + if (__dev_uc_sync(ndev, hns_nic_uc_sync, hns_nic_uc_unsync)) + netdev_err(ndev, "sync uc address fail\n"); } struct rtnl_link_stats64 *hns_nic_get_stats64(struct net_device *ndev,