]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: atlantic: implement AQC113 L2/L3/L4 RX filter ops
authorSukhdeep Singh <sukhdeeps@marvell.com>
Wed, 10 Jun 2026 11:54:43 +0000 (17:24 +0530)
committerJakub Kicinski <kuba@kernel.org>
Mon, 15 Jun 2026 22:38:43 +0000 (15:38 -0700)
Implement complete RX filter management for AQC113 hardware:

- Add tag-based ethertype filter policy (hw_atl2_filter_tag_get/put)
  that allocates and releases ART tags for L2 ethertype filters.

- Add L3/L4 filter sharing via serialized usage counters in
  hw_atl2_l3_filter/hw_atl2_l4_filter, managed through
  hw_atl2_rxf_l3_get/put and hw_atl2_rxf_l4_get/put.

- Implement L3 (IPv4/IPv6 source/destination address and protocol)
  filter find, get (program HW and increment refcount), and put
  (decrement refcount and clear HW when last user releases).

- Implement L4 (TCP/UDP/SCTP source/destination port) filter management
  with the same find/get/put pattern.

- Add combined L3L4 filter configuration (hw_atl2_new_fl3l4_configure)
  that translates legacy aq_rx_filter_l3l4 commands into AQC113 separate
  L3+L4 filter programming with Action Resolver Table (ART) entries.

- Add L2 ethertype filter set/clear (hw_atl2_hw_fl2_set/clear) with
  tag-based ART integration.

- Wire .hw_filter_l2_set, .hw_filter_l2_clear, .hw_filter_l3l4_set
  into hw_atl2_ops.

Signed-off-by: Sukhdeep Singh <sukhdeeps@marvell.com>
Link: https://patch.msgid.link/20260610115448.272-8-sukhdeeps@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c

index ec5b2a03fd6f4a2fa1e521788292f0b205bb676c..f48b7953274dd5fd5a0988a663ae15ead98b6b46 100644 (file)
@@ -87,6 +87,38 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc116c = {
                          AQ_NIC_RATE_10M,
 };
 
+/* Find tag with the same action or new free tag
+ *  top - top inclusive tag value
+ *  action - action for ActionResolverTable
+ */
+static int hw_atl2_filter_tag_get(struct hw_atl2_tag_policy *tags,
+                                 int top, u16 action)
+{
+       int i;
+
+       for (i = 1; i <= top; i++)
+               if (tags[i].usage > 0 && tags[i].action == action) {
+                       tags[i].usage++;
+                       return i;
+               }
+
+       for (i = 1; i <= top; i++)
+               if (tags[i].usage == 0) {
+                       tags[i].usage = 1;
+                       tags[i].action = action;
+                       return i;
+               }
+
+       return -ENOSPC;
+}
+
+static void hw_atl2_filter_tag_put(struct hw_atl2_tag_policy *tags,
+                                  int tag)
+{
+       if (tags[tag].usage > 0)
+               tags[tag].usage--;
+}
+
 static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self)
 {
        return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL2_FW_SM_ACT_RSLVR);
@@ -816,6 +848,489 @@ static struct aq_stats_s *hw_atl2_utils_get_hw_stats(struct aq_hw_s *self)
        return &self->curr_stats;
 }
 
+static bool hw_atl2_rxf_l3_is_equal(struct hw_atl2_l3_filter *f1,
+                                   struct hw_atl2_l3_filter *f2)
+{
+       if (f1->cmd != f2->cmd)
+               return false;
+
+       if (f1->cmd & HW_ATL2_RPF_L3_CMD_SA_EN)
+               if (f1->srcip[0] != f2->srcip[0])
+                       return false;
+
+       if (f1->cmd & HW_ATL2_RPF_L3_CMD_DA_EN)
+               if (f1->dstip[0] != f2->dstip[0])
+                       return false;
+
+       if (f1->cmd & (HW_ATL2_RPF_L3_CMD_PROTO_EN |
+                      HW_ATL2_RPF_L3_V6_CMD_PROTO_EN))
+               if (f1->proto != f2->proto)
+                       return false;
+
+       if (f1->cmd & HW_ATL2_RPF_L3_V6_CMD_SA_EN)
+               if (memcmp(f1->srcip, f2->srcip, 16))
+                       return false;
+
+       if (f1->cmd & HW_ATL2_RPF_L3_V6_CMD_DA_EN)
+               if (memcmp(f1->dstip, f2->dstip, 16))
+                       return false;
+
+       return true;
+}
+
+static int hw_atl2_new_fl3l4_find_l3(struct aq_hw_s *self,
+                                    struct hw_atl2_l3_filter *l3)
+{
+       struct hw_atl2_priv *priv = self->priv;
+       struct hw_atl2_l3_filter *l3_filters;
+       int i, first, last;
+
+       if (l3->cmd & HW_ATL2_RPF_L3_V6_CMD_EN) {
+               l3_filters = priv->l3_v6_filters;
+               first = priv->l3_v6_filter_base_index;
+               last = priv->l3_v6_filter_base_index +
+                      priv->l3_v6_filter_count;
+       } else {
+               l3_filters = priv->l3_v4_filters;
+               first = priv->l3_v4_filter_base_index;
+               last = priv->l3_v4_filter_base_index +
+                      priv->l3_v4_filter_count;
+       }
+       for (i = first; i < last; i++) {
+               if (hw_atl2_rxf_l3_is_equal(&l3_filters[i], l3))
+                       return i;
+       }
+
+       for (i = first; i < last; i++) {
+               u32 l3_enable_mask = HW_ATL2_RPF_L3_CMD_EN |
+                                    HW_ATL2_RPF_L3_V6_CMD_EN;
+
+               if (!(l3_filters[i].cmd & l3_enable_mask))
+                       return i;
+       }
+
+       return -ENOSPC;
+}
+
+static void hw_atl2_rxf_l3_get(struct aq_hw_s *self,
+                              struct hw_atl2_l3_filter *l3, int idx,
+                              const struct hw_atl2_l3_filter *_l3)
+{
+       int i;
+
+       l3->usage++;
+       if (l3->usage == 1) {
+               l3->cmd = _l3->cmd;
+               for (i = 0; i < 4; i++) {
+                       l3->srcip[i] = _l3->srcip[i];
+                       l3->dstip[i] = _l3->dstip[i];
+               }
+               l3->proto = _l3->proto;
+
+               if (l3->cmd & HW_ATL2_RPF_L3_CMD_EN) {
+                       hw_atl2_rpf_l3_v4_cmd_set(self, l3->cmd, idx);
+                       hw_atl2_rpf_l3_v4_tag_set(self, idx + 1, idx);
+                       hw_atl2_rpf_l3_v4_dest_addr_set(self,
+                                                       idx,
+                                                       l3->dstip[0]);
+                       hw_atl2_rpf_l3_v4_src_addr_set(self,
+                                                      idx,
+                                                      l3->srcip[0]);
+               } else {
+                       hw_atl2_rpf_l3_v6_cmd_set(self, l3->cmd, idx);
+                       hw_atl2_rpf_l3_v6_tag_set(self, idx + 1, idx);
+                       hw_atl2_rpf_l3_v6_dest_addr_set(self,
+                                                       idx,
+                                                       l3->dstip);
+                       hw_atl2_rpf_l3_v6_src_addr_set(self,
+                                                      idx,
+                                                      l3->srcip);
+               }
+       }
+}
+
+static void hw_atl2_rxf_l3_put(struct aq_hw_s *self,
+                              struct hw_atl2_l3_filter *l3, int idx)
+{
+       if (l3->usage)
+               l3->usage--;
+
+       if (!l3->usage) {
+               if (l3->cmd & HW_ATL2_RPF_L3_V6_CMD_EN)
+                       hw_atl2_rpf_l3_v6_cmd_set(self, 0, idx);
+               else
+                       hw_atl2_rpf_l3_v4_cmd_set(self, 0, idx);
+               l3->cmd = 0;
+       }
+}
+
+static bool hw_atl2_rxf_l4_is_equal(struct hw_atl2_l4_filter *f1,
+                                   struct hw_atl2_l4_filter *f2)
+{
+       if (f1->cmd != f2->cmd)
+               return false;
+
+       if (f1->cmd & HW_ATL2_RPF_L4_CMD_SP_EN)
+               if (f1->sport != f2->sport)
+                       return false;
+
+       if (f1->cmd & HW_ATL2_RPF_L4_CMD_DP_EN)
+               if (f1->dport != f2->dport)
+                       return false;
+
+       return true;
+}
+
+static int hw_atl2_new_fl3l4_find_l4(struct aq_hw_s *self,
+                                    struct hw_atl2_l4_filter *l4)
+{
+       struct hw_atl2_priv *priv = self->priv;
+       int i, first, last;
+
+       first = priv->l4_filter_base_index;
+       last = priv->l4_filter_base_index + priv->l4_filter_count;
+
+       for (i = first; i < last; i++)
+               if (hw_atl2_rxf_l4_is_equal(&priv->l4_filters[i], l4))
+                       return i;
+
+       for (i = first; i < last; i++)
+               if ((priv->l4_filters[i].cmd & HW_ATL2_RPF_L4_CMD_EN) == 0)
+                       return i;
+
+       return -ENOSPC;
+}
+
+static void hw_atl2_rxf_l4_put(struct aq_hw_s *self,
+                              struct hw_atl2_l4_filter *l4, int idx)
+{
+       if (l4->usage)
+               l4->usage--;
+
+       if (!l4->usage) {
+               l4->cmd = 0;
+               hw_atl2_rpf_l4_cmd_set(self, l4->cmd, idx);
+       }
+}
+
+static void hw_atl2_rxf_l4_get(struct aq_hw_s *self,
+                              struct hw_atl2_l4_filter *l4, int idx,
+                              const struct hw_atl2_l4_filter *_l4)
+{
+       l4->usage++;
+       if (l4->usage == 1) {
+               l4->cmd = _l4->cmd;
+               l4->sport = _l4->sport;
+               l4->dport = _l4->dport;
+
+               hw_atl2_rpf_l4_cmd_set(self, l4->cmd, idx);
+               hw_atl2_rpf_l4_tag_set(self, idx + 1, idx);
+               hw_atl_rpf_l4_spd_set(self, l4->sport, idx);
+               hw_atl_rpf_l4_dpd_set(self, l4->dport, idx);
+       }
+}
+
+static int hw_atl2_new_fl3l4_configure(struct aq_hw_s *self,
+                                      struct aq_rx_filter_l3l4 *data)
+{
+       struct hw_atl2_priv *priv = self->priv;
+       s8 old_l3_index = priv->l3l4_filters[data->location].l3_index;
+       s8 old_l4_index = priv->l3l4_filters[data->location].l4_index;
+       u8 old_ipv6 = priv->l3l4_filters[data->location].ipv6;
+       struct hw_atl2_l3_filter *l3_filters;
+       struct hw_atl2_l3_filter l3;
+       struct hw_atl2_l4_filter l4;
+       s8 l3_idx = -1;
+       s8 l4_idx = -1;
+
+       if (!(data->cmd & HW_ATL_RX_ENABLE_FLTR_L3L4))
+               return 0;
+
+       memset(&l3, 0, sizeof(l3));
+       memset(&l4, 0, sizeof(l4));
+
+       /* convert legacy filter to new */
+       if (data->cmd & HW_ATL_RX_ENABLE_CMP_PROT_L4) {
+               l3.cmd |= data->is_ipv6 ? HW_ATL2_RPF_L3_V6_CMD_PROTO_EN :
+                                         HW_ATL2_RPF_L3_CMD_PROTO_EN;
+               l3.cmd |= data->is_ipv6 ? HW_ATL2_RPF_L3_V6_CMD_EN :
+                                         HW_ATL2_RPF_L3_CMD_EN;
+               switch (data->cmd & 0x7) {
+               case HW_ATL_RX_TCP:
+                       l3.cmd |= IPPROTO_TCP << (data->is_ipv6 ? 0x18 : 8);
+                       break;
+               case HW_ATL_RX_UDP:
+                       l3.cmd |= IPPROTO_UDP << (data->is_ipv6 ? 0x18 : 8);
+                       break;
+               case HW_ATL_RX_SCTP:
+                       l3.cmd |= IPPROTO_SCTP << (data->is_ipv6 ? 0x18 : 8);
+                       break;
+               case HW_ATL_RX_ICMP:
+                       l3.cmd |= IPPROTO_ICMP << (data->is_ipv6 ? 0x18 : 8);
+                       break;
+               }
+       }
+
+       if (data->cmd & HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3) {
+               if (data->is_ipv6) {
+                       l3.cmd |= HW_ATL2_RPF_L3_V6_CMD_SA_EN |
+                                 HW_ATL2_RPF_L3_V6_CMD_EN;
+                       memcpy(l3.srcip, data->ip_src, sizeof(l3.srcip));
+               } else {
+                       l3.cmd |= HW_ATL2_RPF_L3_CMD_SA_EN |
+                                 HW_ATL2_RPF_L3_CMD_EN;
+                       l3.srcip[0] = data->ip_src[0];
+               }
+       }
+       if (data->cmd & HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3) {
+               if (data->is_ipv6) {
+                       l3.cmd |= HW_ATL2_RPF_L3_V6_CMD_DA_EN |
+                                 HW_ATL2_RPF_L3_V6_CMD_EN;
+                       memcpy(l3.dstip, data->ip_dst, sizeof(l3.dstip));
+               } else {
+                       l3.cmd |= HW_ATL2_RPF_L3_CMD_DA_EN |
+                                 HW_ATL2_RPF_L3_CMD_EN;
+                       l3.dstip[0] = data->ip_dst[0];
+               }
+       }
+
+       if (data->cmd & HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4) {
+               l4.cmd |= HW_ATL2_RPF_L4_CMD_DP_EN | HW_ATL2_RPF_L4_CMD_EN;
+               l4.dport = data->p_dst;
+       }
+       if (data->cmd & HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4) {
+               l4.cmd |= HW_ATL2_RPF_L4_CMD_SP_EN | HW_ATL2_RPF_L4_CMD_EN;
+               l4.sport = data->p_src;
+       }
+
+       /* find L3 and L4 filters */
+       if (l3.cmd & (HW_ATL2_RPF_L3_CMD_EN | HW_ATL2_RPF_L3_V6_CMD_EN)) {
+               l3_idx = hw_atl2_new_fl3l4_find_l3(self, &l3);
+               if (l3_idx < 0)
+                       return l3_idx;
+
+               if (l3.cmd & HW_ATL2_RPF_L3_V6_CMD_EN)
+                       l3_filters = priv->l3_v6_filters;
+               else
+                       l3_filters = priv->l3_v4_filters;
+
+               if (priv->l3l4_filters[data->location].l3_index != l3_idx ||
+                   old_ipv6 != !!(l3.cmd & HW_ATL2_RPF_L3_V6_CMD_EN))
+                       hw_atl2_rxf_l3_get(self, &l3_filters[l3_idx],
+                                          l3_idx, &l3);
+       }
+
+       if (old_l3_index != -1) {
+               if (old_ipv6)
+                       l3_filters = priv->l3_v6_filters;
+               else
+                       l3_filters = priv->l3_v4_filters;
+
+               if (!(hw_atl2_rxf_l3_is_equal(&l3,
+                                             &l3_filters[old_l3_index]))) {
+                       hw_atl2_rxf_l3_put(self,
+                                          &l3_filters[old_l3_index],
+                                          old_l3_index);
+               }
+       }
+       if (l3.cmd & HW_ATL2_RPF_L3_V6_CMD_EN)
+               priv->l3l4_filters[data->location].ipv6 = 1;
+       else
+               priv->l3l4_filters[data->location].ipv6 = 0;
+       priv->l3l4_filters[data->location].l3_index = l3_idx;
+
+       if (l4.cmd & HW_ATL2_RPF_L4_CMD_EN) {
+               l4_idx = hw_atl2_new_fl3l4_find_l4(self, &l4);
+               if (l4_idx < 0)
+                       return l4_idx;
+
+               if (priv->l3l4_filters[data->location].l4_index != l4_idx)
+                       hw_atl2_rxf_l4_get(self, &priv->l4_filters[l4_idx],
+                                          l4_idx, &l4);
+       }
+
+       if (old_l4_index != -1) {
+               if (!(hw_atl2_rxf_l4_is_equal(&priv->l4_filters[old_l4_index],
+                                             &l4))) {
+                       hw_atl2_rxf_l4_put(self,
+                                          &priv->l4_filters[old_l4_index],
+                                          old_l4_index);
+               }
+       }
+       priv->l3l4_filters[data->location].l4_index = l4_idx;
+
+       return 0;
+}
+
+static int hw_atl2_hw_fl3l4_set(struct aq_hw_s *self,
+                               struct aq_rx_filter_l3l4 *data)
+{
+       struct hw_atl2_priv *priv = self->priv;
+       struct hw_atl2_l3_filter *l3_filters;
+       struct hw_atl2_l3_filter *l3 = NULL;
+       struct hw_atl2_l4_filter *l4 = NULL;
+       u8 location = data->location;
+       u32 req_tag = 0;
+       u16 action = 0;
+       int l3_index;
+       int l4_index;
+       u32 mask = 0;
+       u8 index;
+       u8 ipv6;
+       int res;
+
+       res = hw_atl2_new_fl3l4_configure(self, data);
+       if (res)
+               return res;
+
+       l3_index = priv->l3l4_filters[location].l3_index;
+       l4_index = priv->l3l4_filters[location].l4_index;
+       ipv6 = priv->l3l4_filters[location].ipv6;
+       if (ipv6)
+               l3_filters = priv->l3_v6_filters;
+       else
+               l3_filters = priv->l3_v4_filters;
+
+       if (!(data->cmd & HW_ATL_RX_ENABLE_FLTR_L3L4)) {
+               if (l3_index > -1)
+                       hw_atl2_rxf_l3_put(self, &l3_filters[l3_index],
+                                          l3_index);
+
+               if (l4_index > -1)
+                       hw_atl2_rxf_l4_put(self, &priv->l4_filters[l4_index],
+                                          l4_index);
+
+               priv->l3l4_filters[location].l3_index = -1;
+               priv->l3l4_filters[location].l4_index = -1;
+               index = priv->art_base_index + HW_ATL2_RPF_L3L4_USER_INDEX +
+                       location;
+               hw_atl2_act_rslvr_table_set(self, index, 0, 0,
+                                           HW_ATL2_ACTION_DISABLE);
+
+               return 0;
+       }
+
+       if (l3_index != -1)
+               l3 = &l3_filters[l3_index];
+       if (l4_index != -1)
+               l4 = &priv->l4_filters[l4_index];
+
+       if (l4 && (l4->cmd & HW_ATL2_RPF_L4_CMD_EN)) {
+               req_tag |= (l4_index + 1) << HW_ATL2_RPF_TAG_L4_OFFSET;
+               mask |= HW_ATL2_RPF_TAG_L4_MASK;
+       }
+
+       if (l3) {
+               if (l3->cmd & HW_ATL2_RPF_L3_V6_CMD_EN) {
+                       req_tag |= (l3_index + 1) <<
+                                  HW_ATL2_RPF_TAG_L3_V6_OFFSET;
+                       mask |= HW_ATL2_RPF_TAG_L3_V6_MASK;
+               } else {
+                       req_tag |= (l3_index + 1) <<
+                                  HW_ATL2_RPF_TAG_L3_V4_OFFSET;
+                       mask |= HW_ATL2_RPF_TAG_L3_V4_MASK;
+               }
+       }
+
+       if (data->cmd & (HW_ATL_RX_HOST << HW_ATL2_RPF_L3_L4_ACTF_SHIFT))
+               action = HW_ATL2_ACTION_ASSIGN_QUEUE((data->cmd  &
+                                                     HW_ATL2_RPF_L3_L4_RXQF_MSK) >>
+                                                    HW_ATL2_RPF_L3_L4_RXQF_SHIFT);
+       else
+               action = HW_ATL2_ACTION_DROP;
+
+       index = priv->art_base_index + HW_ATL2_RPF_L3L4_USER_INDEX + location;
+       hw_atl2_act_rslvr_table_set(self, index, req_tag, mask, action);
+       return 0;
+}
+
+static int hw_atl2_hw_fl2_set(struct aq_hw_s *self,
+                             struct aq_rx_filter_l2 *data)
+{
+       struct hw_atl2_priv *priv = self->priv;
+       u32 mask = HW_ATL2_RPF_TAG_ET_MASK;
+       u32 req_tag = 0;
+       u16 action = 0;
+       u32 location;
+       u8 index;
+       int tag;
+
+       location = priv->etype_filter_base_index + data->location;
+
+       hw_atl_rpf_etht_flr_set(self, data->ethertype, location);
+       hw_atl_rpf_etht_user_priority_en_set(self,
+                                            !!data->user_priority_en,
+                                            location);
+       if (data->user_priority_en) {
+               hw_atl_rpf_etht_user_priority_set(self,
+                                                 data->user_priority,
+                                                 location);
+               req_tag |= data->user_priority << HW_ATL2_RPF_TAG_PCP_OFFSET;
+               mask |= HW_ATL2_RPF_TAG_PCP_MASK;
+       }
+
+       if (data->queue < 0) {
+               hw_atl_rpf_etht_flr_act_set(self, 0U, location);
+               hw_atl_rpf_etht_rx_queue_en_set(self, 0U, location);
+               action = HW_ATL2_ACTION_DROP;
+       } else {
+               hw_atl_rpf_etht_flr_act_set(self, 1U, location);
+               hw_atl_rpf_etht_rx_queue_en_set(self, 1U, location);
+               hw_atl_rpf_etht_rx_queue_set(self, data->queue, location);
+               action = HW_ATL2_ACTION_ASSIGN_QUEUE(data->queue);
+       }
+
+       tag = hw_atl2_filter_tag_get(priv->etype_policy,
+                                    priv->etype_filter_tag_top,
+                                    action);
+
+       if (tag < 0)
+               return -ENOSPC;
+
+       req_tag |= tag << HW_ATL2_RPF_TAG_ET_OFFSET;
+       hw_atl2_rpf_etht_flr_tag_set(self, tag, location);
+       index = priv->art_base_index + HW_ATL2_RPF_ET_PCP_USER_INDEX +
+               data->location;
+       hw_atl2_act_rslvr_table_set(self, index, req_tag, mask, action);
+
+       hw_atl_rpf_etht_flr_en_set(self, 1U, location);
+
+       return aq_hw_err_from_flags(self);
+}
+
+static int hw_atl2_hw_fl2_clear(struct aq_hw_s *self,
+                               struct aq_rx_filter_l2 *data)
+{
+       struct hw_atl2_priv *priv = self->priv;
+       u32 location;
+       u8 index;
+       u32 tag;
+
+       location = priv->etype_filter_base_index + data->location;
+       hw_atl_rpf_etht_flr_en_set(self, 0U, location);
+       hw_atl_rpf_etht_flr_set(self, 0U, location);
+       hw_atl_rpf_etht_user_priority_en_set(self, 0U, location);
+
+       index = priv->art_base_index + HW_ATL2_RPF_ET_PCP_USER_INDEX +
+               data->location;
+       hw_atl2_act_rslvr_table_set(self, index, 0, 0,
+                                   HW_ATL2_ACTION_DISABLE);
+       tag = hw_atl2_rpf_etht_flr_tag_get(self, location);
+       hw_atl2_filter_tag_put(priv->etype_policy, tag);
+
+       return aq_hw_err_from_flags(self);
+}
+
+/*
+ * Set VLAN filter table
+ * Configure VLAN filter table to accept (and assign the queue) traffic
+ * for the particular vlan ids.
+ * Note: use this function under vlan promisc mode not to lost the traffic
+ *
+ * param - aq_hw_s
+ * param - aq_rx_filter_vlan VLAN filter configuration
+ * return 0 - OK, <0 - error
+ */
 static int hw_atl2_hw_vlan_set(struct aq_hw_s *self,
                               struct aq_rx_filter_vlan *aq_vlans)
 {
@@ -897,6 +1412,9 @@ const struct aq_hw_ops hw_atl2_ops = {
        .hw_ring_rx_init             = hw_atl2_hw_ring_rx_init,
        .hw_ring_tx_init             = hw_atl2_hw_ring_tx_init,
        .hw_packet_filter_set        = hw_atl2_hw_packet_filter_set,
+       .hw_filter_l2_set            = hw_atl2_hw_fl2_set,
+       .hw_filter_l2_clear          = hw_atl2_hw_fl2_clear,
+       .hw_filter_l3l4_set          = hw_atl2_hw_fl3l4_set,
        .hw_filter_vlan_set          = hw_atl2_hw_vlan_set,
        .hw_filter_vlan_ctrl         = hw_atl2_hw_vlan_ctrl,
        .hw_multicast_list_set       = hw_atl2_hw_multicast_list_set,