Re: [PATCH net-next 6/9] net: atlantic: implement AQC113 L2/L3/L4 RX filter management filter management management

From: Vadim Fedorenko

Date: Wed May 06 2026 - 18:43:43 EST


On 06/05/2026 14:57, sukhdeeps@xxxxxxxxxxx wrote:
From: Sukhdeep Singh <sukhdeeps@xxxxxxxxxxx>

Implement complete RX filter management for AQC113 hardware:

- Add tag-based filter policy with reference-counted sharing, allowing
multiple filter rules to share the same L3 or L4 hardware filter
when their match criteria are identical.
- 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 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 with tag-based ART integration.
- Add MAC address setup using firmware-provided L2 filter base index.

Update hardware initialization:
- Use firmware-reported ART section base and count instead of
hardcoded 0xFFFF section enable.
- Enable L3 v6/v4 select mode for simultaneous IPv4/IPv6 filtering.
- Initialize L3L4 filter indices to -1 on reset.

Wire up hw_filter_l2_set, hw_filter_l2_clear, hw_filter_l3l4_set,
hw_set_mac_address, hw_get_version, and hw_get_regs in hw_atl2_ops.

Signed-off-by: Sukhdeep Singh <sukhdeeps@xxxxxxxxxxx>
---
.../net/ethernet/aquantia/atlantic/aq_hw.h | 2 +
.../aquantia/atlantic/hw_atl2/hw_atl2.c | 582 +++++++++++++++++-
2 files changed, 580 insertions(+), 4 deletions(-)

[...]

@@ -380,6 +422,9 @@ static void hw_atl2_hw_init_new_rx_filters(struct aq_hw_s *self)
{
u8 *prio_tc_map = self->aq_nic_cfg->prio_tc_map;
struct hw_atl2_priv *priv = self->priv;
+ u32 art_first_sec, art_last_sec;
+ u32 art_sections;
+ u32 art_mask = 0;

no need to init variable which is overwritten later ...

u16 action;
u8 index;
int i;
@@ -394,9 +439,14 @@ static void hw_atl2_hw_init_new_rx_filters(struct aq_hw_s *self)
* REC entry is used for further processing. If multiple entries match,
* the lowest REC entry, Action field will be selected.
*/
- hw_atl2_rpf_act_rslvr_section_en_set(self, 0xFFFF);
+ art_last_sec = priv->art_base_index / 8 + priv->art_count / 8;
+ art_first_sec = priv->art_base_index / 8;
+ art_mask = (BIT(art_last_sec) - 1) - (BIT(art_first_sec) - 1);

... here

+ art_sections = hw_atl2_rpf_act_rslvr_section_en_get(self) | art_mask;
+ hw_atl2_rpf_act_rslvr_section_en_set(self, art_sections);
+ hw_atl2_rpf_l3_v6_v4_select_set(self, 1);
hw_atl2_rpfl2_uc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC,
- HW_ATL2_MAC_UC);
+ priv->l2_filters_base_index);
hw_atl2_rpfl2_bc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC);
/* FW reserves the beginning of ART, thus all driver entries must
@@ -530,6 +580,35 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self)
return aq_hw_err_from_flags(self);
}
+static int hw_atl2_hw_mac_addr_set(struct aq_hw_s *self, const u8 *mac_addr)
+{
+ struct hw_atl2_priv *priv = self->priv;
+ u32 location = priv->l2_filters_base_index;
+ unsigned int h = 0U;
+ unsigned int l = 0U;
+ int err = 0;

here again, h, l and err are not used with init values.

+
+ if (!mac_addr) {
+ err = -EINVAL;
+ goto err_exit;
+ }
+ h = (mac_addr[0] << 8) | (mac_addr[1]);
+ l = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
+ (mac_addr[4] << 8) | mac_addr[5];
+
+ hw_atl_rpfl2_uc_flr_en_set(self, 0U, location);
+ hw_atl_rpfl2unicast_dest_addresslsw_set(self, l, location);
+ hw_atl_rpfl2unicast_dest_addressmsw_set(self, h, location);
+ hw_atl_rpfl2unicast_flr_act_set(self, 1U, location);
+ hw_atl2_rpfl2_uc_flr_tag_set(self, HW_ATL2_RPF_TAG_BASE_UC, location);
+ hw_atl_rpfl2_uc_flr_en_set(self, 1U, location);
+
+ err = aq_hw_err_from_flags(self);
+
+err_exit:
+ return err;
+}
+
static int hw_atl2_hw_init(struct aq_hw_s *self, const u8 *mac_addr)
{
static u32 aq_hw_atl2_igcr_table_[4][2] = {

[...]