spin_unlock_bh(&dsaf_dev->tcam_lock);
 }
 
+/**
+ * hns_dsaf_tcam_uc_cfg_vague - INT
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @address,
+ * @ptbl_tcam_data,
+ */
+static void hns_dsaf_tcam_uc_cfg_vague(struct dsaf_device *dsaf_dev,
+                                      u32 address,
+                                      struct dsaf_tbl_tcam_data *tcam_data,
+                                      struct dsaf_tbl_tcam_data *tcam_mask,
+                                      struct dsaf_tbl_tcam_ucast_cfg *tcam_uc)
+{
+       spin_lock_bh(&dsaf_dev->tcam_lock);
+       hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+       hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, tcam_data);
+       hns_dsaf_tbl_tcam_ucast_cfg(dsaf_dev, tcam_uc);
+       hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+       hns_dsaf_tbl_tcam_data_ucast_pul(dsaf_dev);
+
+       /*Restore Match Data*/
+       tcam_mask->tbl_tcam_data_high = 0xffffffff;
+       tcam_mask->tbl_tcam_data_low = 0xffffffff;
+       hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+
+       spin_unlock_bh(&dsaf_dev->tcam_lock);
+}
+
+/**
+ * hns_dsaf_tcam_mc_cfg_vague - INT
+ * @dsaf_dev: dsa fabric device struct pointer
+ * @address,
+ * @ptbl_tcam_data,
+ * @ptbl_tcam_mask
+ * @ptbl_tcam_mcast
+ */
+static void hns_dsaf_tcam_mc_cfg_vague(struct dsaf_device *dsaf_dev,
+                                      u32 address,
+                                      struct dsaf_tbl_tcam_data *tcam_data,
+                                      struct dsaf_tbl_tcam_data *tcam_mask,
+                                      struct dsaf_tbl_tcam_mcast_cfg *tcam_mc)
+{
+       spin_lock_bh(&dsaf_dev->tcam_lock);
+       hns_dsaf_tbl_tcam_addr_cfg(dsaf_dev, address);
+       hns_dsaf_tbl_tcam_data_cfg(dsaf_dev, tcam_data);
+       hns_dsaf_tbl_tcam_mcast_cfg(dsaf_dev, tcam_mc);
+       hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+       hns_dsaf_tbl_tcam_data_mcast_pul(dsaf_dev);
+
+       /*Restore Match Data*/
+       tcam_mask->tbl_tcam_data_high = 0xffffffff;
+       tcam_mask->tbl_tcam_data_low = 0xffffffff;
+       hns_dsaf_tbl_tcam_match_cfg(dsaf_dev, tcam_mask);
+
+       spin_unlock_bh(&dsaf_dev->tcam_lock);
+}
+
 /**
  * hns_dsaf_tcam_mc_invld - INT
  * @dsaf_id: dsa fabric id
        return DSAF_INVALID_ENTRY_IDX;
 }
 
+/**
+ * hns_dsaf_find_empty_mac_entry_reverse
+ * search dsa fabric soft empty-entry from the end
+ * @dsaf_dev: dsa fabric device struct pointer
+ */
+static u16 hns_dsaf_find_empty_mac_entry_reverse(struct dsaf_device *dsaf_dev)
+{
+       struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+       struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+       int i;
+
+       soft_mac_entry = priv->soft_mac_tbl + (DSAF_TCAM_SUM - 1);
+       for (i = (DSAF_TCAM_SUM - 1); i > 0; i--) {
+               /* search all entry from end to start.*/
+               if (soft_mac_entry->index == DSAF_INVALID_ENTRY_IDX)
+                       return i;
+               soft_mac_entry--;
+       }
+       return DSAF_INVALID_ENTRY_IDX;
+}
+
 /**
  * hns_dsaf_set_mac_key - set mac key
  * @dsaf_dev: dsa fabric device struct pointer
        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)
+static void set_promisc_tcam_enable(struct dsaf_device *dsaf_dev, u32 port)
 {
+       struct dsaf_tbl_tcam_ucast_cfg tbl_tcam_ucast = {0, 1, 0, 0, 0x80};
+       struct dsaf_tbl_tcam_data tbl_tcam_data_mc = {0x01000000, port};
+       struct dsaf_tbl_tcam_data tbl_tcam_mask_uc = {0x01000000, 0xf};
+       struct dsaf_tbl_tcam_mcast_cfg tbl_tcam_mcast = {0, 0, {0} };
        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};
+       struct dsaf_tbl_tcam_data tbl_tcam_data_uc = {0, port};
+       struct dsaf_drv_mac_single_dest_entry mask_entry;
+       struct dsaf_drv_tbl_tcam_key temp_key, mask_key;
+       struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+       u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+       struct dsaf_drv_tbl_tcam_key mac_key;
+       struct hns_mac_cb *mac_cb;
+       u8 addr[ETH_ALEN] = {0};
+       u8 port_num;
+       u16 mskid;
 
-       if ((AE_IS_VER1(dsaf_dev->dsaf_ver)) || HNS_DSAF_IS_DEBUG(dsaf_dev))
+       /* promisc use vague table match with vlanid = 0 & macaddr = 0 */
+       hns_dsaf_set_mac_key(dsaf_dev, &mac_key, 0x00, port, addr);
+       entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+       if (entry_index != DSAF_INVALID_ENTRY_IDX)
                return;
 
-       /* find the tcam entry index for promisc */
-       entry_index = dsaf_promisc_tcam_entry(port);
-
-       memset(&tbl_tcam_data, 0, sizeof(tbl_tcam_data));
-       memset(&tbl_tcam_mask, 0, sizeof(tbl_tcam_mask));
-
-       /* config key mask */
-       if (enable) {
-               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],
-                            DSAF_SERVICE_NW_NUM, true);
-               mac_data.tbl_mcast_item_vld = true;     /* item_vld bit */
+       /* put promisc tcam entry in the end. */
+       /* 1. set promisc unicast vague tcam entry. */
+       entry_index = hns_dsaf_find_empty_mac_entry_reverse(dsaf_dev);
+       if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+               dev_err(dsaf_dev->dev,
+                       "enable uc promisc failed (port:%#x)\n",
+                       port);
+               return;
+       }
+
+       mac_cb = dsaf_dev->mac_cb[port];
+       (void)hns_mac_get_inner_port_num(mac_cb, 0, &port_num);
+       tbl_tcam_ucast.tbl_ucast_out_port = port_num;
+
+       /* config uc vague table */
+       hns_dsaf_tcam_uc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_uc,
+                                  &tbl_tcam_mask_uc, &tbl_tcam_ucast);
+
+       /* update software entry */
+       soft_mac_entry = priv->soft_mac_tbl;
+       soft_mac_entry += entry_index;
+       soft_mac_entry->index = entry_index;
+       soft_mac_entry->tcam_key.high.val = mac_key.high.val;
+       soft_mac_entry->tcam_key.low.val = mac_key.low.val;
+       /* step back to the START for mc. */
+       soft_mac_entry = priv->soft_mac_tbl;
+
+       /* 2. set promisc multicast vague tcam entry. */
+       entry_index = hns_dsaf_find_empty_mac_entry_reverse(dsaf_dev);
+       if (entry_index == DSAF_INVALID_ENTRY_IDX) {
+               dev_err(dsaf_dev->dev,
+                       "enable mc promisc failed (port:%#x)\n",
+                       port);
+               return;
+       }
+
+       memset(&mask_entry, 0x0, sizeof(mask_entry));
+       memset(&mask_key, 0x0, sizeof(mask_key));
+       memset(&temp_key, 0x0, sizeof(temp_key));
+       mask_entry.addr[0] = 0x01;
+       hns_dsaf_set_mac_key(dsaf_dev, &mask_key, mask_entry.in_vlan_id,
+                            port, mask_entry.addr);
+       tbl_tcam_mcast.tbl_mcast_item_vld = 1;
+       tbl_tcam_mcast.tbl_mcast_old_en = 0;
+
+       if (port < DSAF_SERVICE_NW_NUM) {
+               mskid = port;
+       } else if (port >= DSAF_BASE_INNER_PORT_NUM) {
+               mskid = port - DSAF_BASE_INNER_PORT_NUM + DSAF_SERVICE_NW_NUM;
        } else {
-               mac_data.tbl_mcast_item_vld = false;    /* item_vld bit */
+               dev_err(dsaf_dev->dev, "%s,pnum(%d)error,key(%#x:%#x)\n",
+                       dsaf_dev->ae_dev.name, port,
+                       mask_key.high.val, mask_key.low.val);
+               return;
        }
 
-       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);
+       dsaf_set_bit(tbl_tcam_mcast.tbl_mcast_port_msk[mskid / 32],
+                    mskid % 32, 1);
+       memcpy(&temp_key, &mask_key, sizeof(mask_key));
+       hns_dsaf_tcam_mc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_mc,
+                                  (struct dsaf_tbl_tcam_data *)(&mask_key),
+                                  &tbl_tcam_mcast);
 
-       /* 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);
+       /* update software entry */
+       soft_mac_entry += entry_index;
+       soft_mac_entry->index = entry_index;
+       soft_mac_entry->tcam_key.high.val = temp_key.high.val;
+       soft_mac_entry->tcam_key.low.val = temp_key.low.val;
+}
 
-       /* config software entry */
+static void set_promisc_tcam_disable(struct dsaf_device *dsaf_dev, u32 port)
+{
+       struct dsaf_tbl_tcam_data tbl_tcam_data_mc = {0x01000000, port};
+       struct dsaf_tbl_tcam_ucast_cfg tbl_tcam_ucast = {0, 0, 0, 0, 0};
+       struct dsaf_tbl_tcam_mcast_cfg tbl_tcam_mcast = {0, 0, {0} };
+       struct dsaf_drv_priv *priv = hns_dsaf_dev_priv(dsaf_dev);
+       struct dsaf_tbl_tcam_data tbl_tcam_data_uc = {0, 0};
+       struct dsaf_tbl_tcam_data tbl_tcam_mask = {0, 0};
+       struct dsaf_drv_soft_mac_tbl *soft_mac_entry;
+       u16 entry_index = DSAF_INVALID_ENTRY_IDX;
+       struct dsaf_drv_tbl_tcam_key mac_key;
+       u8 addr[ETH_ALEN] = {0};
+
+       /* 1. delete uc vague tcam entry. */
+       /* promisc use vague table match with vlanid = 0 & macaddr = 0 */
+       hns_dsaf_set_mac_key(dsaf_dev, &mac_key, 0x00, port, addr);
+       entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+
+       if (entry_index == DSAF_INVALID_ENTRY_IDX)
+               return;
+
+       /* config uc vague table */
+       hns_dsaf_tcam_uc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_uc,
+                                  &tbl_tcam_mask, &tbl_tcam_ucast);
+       /* update soft management table. */
+       soft_mac_entry = priv->soft_mac_tbl;
        soft_mac_entry += entry_index;
-       soft_mac_entry->index = enable ? entry_index : DSAF_INVALID_ENTRY_IDX;
+       soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
+       /* step back to the START for mc. */
+       soft_mac_entry = priv->soft_mac_tbl;
+
+       /* 2. delete mc vague tcam entry. */
+       addr[0] = 0x01;
+       memset(&mac_key, 0x0, sizeof(mac_key));
+       hns_dsaf_set_mac_key(dsaf_dev, &mac_key, 0x00, port, addr);
+       entry_index = hns_dsaf_find_soft_mac_entry(dsaf_dev, &mac_key);
+
+       if (entry_index == DSAF_INVALID_ENTRY_IDX)
+               return;
+
+       /* config mc vague table */
+       hns_dsaf_tcam_mc_cfg_vague(dsaf_dev, entry_index, &tbl_tcam_data_mc,
+                                  &tbl_tcam_mask, &tbl_tcam_mcast);
+       /* update soft management table. */
+       soft_mac_entry += entry_index;
+       soft_mac_entry->index = DSAF_INVALID_ENTRY_IDX;
+}
+
+/* Reserve the last TCAM entry for promisc support */
+void hns_dsaf_set_promisc_tcam(struct dsaf_device *dsaf_dev,
+                              u32 port, bool enable)
+{
+       if (enable)
+               set_promisc_tcam_enable(dsaf_dev, port);
+       else
+               set_promisc_tcam_disable(dsaf_dev, port);
 }
 
 int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port)