mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
net: atlantic: fix AQC113 HW init: ART, L2 filter slot, MAC address
Fix initialization issues in hw_atl2 to correctly support AQC113: - hw_atl2_hw_reset: replace unconditional priv memset with selective field clears so that l3l4_filters[].l3_index and l4_index can be initialized to -1 (not allocated) rather than 0; 0 is a valid filter index and would incorrectly appear as an occupied slot after a reset. - hw_atl2_hw_init_new_rx_filters: use firmware-reported ART section base and count (clamped to 16) instead of hardcoded 0xFFFF mask; enable simultaneous IPv4/IPv6 L3 filter mode (rpf_l3_v6_v4_select); tag the UC MAC slot using firmware-supplied l2_filters_base_index instead of hardcoded HW_ATL2_MAC_UC. - hw_atl2_hw_init_rx_path: enable only the firmware-assigned MAC slot (priv->l2_filters_base_index) instead of always slot 0. - Add hw_atl2_hw_mac_addr_set() that programs the MAC address into the firmware-assigned L2 filter slot. Wire into hw_atl2_ops replacing the A1 hw_atl_b0_hw_mac_addr_set; call it from hw_init. - Wire .hw_get_regs into hw_atl2_ops. Signed-off-by: Sukhdeep Singh <sukhdeeps@marvell.com> Link: https://patch.msgid.link/20260610115448.272-7-sukhdeeps@marvell.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
4428d3b994
commit
6c1ca112a6
|
|
@ -11,6 +11,7 @@
|
|||
#include "hw_atl/hw_atl_utils.h"
|
||||
#include "hw_atl/hw_atl_llh.h"
|
||||
#include "hw_atl/hw_atl_llh_internal.h"
|
||||
#include "hw_atl2.h"
|
||||
#include "hw_atl2_utils.h"
|
||||
#include "hw_atl2_llh.h"
|
||||
#include "hw_atl2_internal.h"
|
||||
|
|
@ -95,12 +96,21 @@ static int hw_atl2_hw_reset(struct aq_hw_s *self)
|
|||
{
|
||||
struct hw_atl2_priv *priv = self->priv;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
err = hw_atl2_utils_soft_reset(self);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
memset(&priv->last_stats, 0, sizeof(priv->last_stats));
|
||||
memset(priv->l3_v4_filters, 0, sizeof(priv->l3_v4_filters));
|
||||
memset(priv->l3_v6_filters, 0, sizeof(priv->l3_v6_filters));
|
||||
memset(priv->l4_filters, 0, sizeof(priv->l4_filters));
|
||||
memset(priv->etype_policy, 0, sizeof(priv->etype_policy));
|
||||
for (i = 0; i < HW_ATL2_RPF_L3L4_FILTERS; i++) {
|
||||
priv->l3l4_filters[i].l3_index = -1;
|
||||
priv->l3l4_filters[i].l4_index = -1;
|
||||
}
|
||||
|
||||
self->aq_fw_ops->set_state(self, MPI_RESET);
|
||||
|
||||
|
|
@ -380,6 +390,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;
|
||||
u16 action;
|
||||
u8 index;
|
||||
int i;
|
||||
|
|
@ -394,9 +407,20 @@ 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 = min_t(u32,
|
||||
priv->art_base_index / 8 + priv->art_count / 8,
|
||||
16U);
|
||||
art_first_sec = min_t(u32, priv->art_base_index / 8, 16U);
|
||||
art_mask = (BIT(art_last_sec) - 1) - (BIT(art_first_sec) - 1);
|
||||
if (!art_mask) {
|
||||
/* ART base index is out of range, enabling all sections */
|
||||
art_mask = 0xFFFF;
|
||||
}
|
||||
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
|
||||
|
|
@ -484,6 +508,7 @@ static int hw_atl2_act_rslvr_table_set(struct aq_hw_s *self, u8 location,
|
|||
static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self)
|
||||
{
|
||||
struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
|
||||
struct hw_atl2_priv *priv = self->priv;
|
||||
int i;
|
||||
|
||||
/* Rx TC/RSS number config */
|
||||
|
|
@ -499,7 +524,9 @@ static int hw_atl2_hw_init_rx_path(struct aq_hw_s *self)
|
|||
|
||||
/* Multicast filters */
|
||||
for (i = HW_ATL2_MAC_MAX; i--;) {
|
||||
hw_atl_rpfl2_uc_flr_en_set(self, (i == 0U) ? 1U : 0U, i);
|
||||
hw_atl_rpfl2_uc_flr_en_set(self,
|
||||
(i == priv->l2_filters_base_index) ?
|
||||
1U : 0U, i);
|
||||
hw_atl_rpfl2unicast_flr_act_set(self, 1U, i);
|
||||
}
|
||||
|
||||
|
|
@ -530,6 +557,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;
|
||||
unsigned int l;
|
||||
int err;
|
||||
|
||||
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] = {
|
||||
|
|
@ -547,7 +603,7 @@ static int hw_atl2_hw_init(struct aq_hw_s *self, const u8 *mac_addr)
|
|||
hw_atl2_hw_init_tx_path(self);
|
||||
hw_atl2_hw_init_rx_path(self);
|
||||
|
||||
hw_atl_b0_hw_mac_addr_set(self, mac_addr);
|
||||
hw_atl2_hw_mac_addr_set(self, mac_addr);
|
||||
|
||||
self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk);
|
||||
self->aq_fw_ops->set_state(self, MPI_INIT);
|
||||
|
|
@ -619,6 +675,8 @@ static int hw_atl2_hw_multicast_list_set(struct aq_hw_s *self,
|
|||
[ETH_ALEN],
|
||||
u32 count)
|
||||
{
|
||||
struct hw_atl2_priv *priv = self->priv;
|
||||
u32 base_location = priv->l2_filters_base_index + 1;
|
||||
struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
|
||||
int err = 0;
|
||||
|
||||
|
|
@ -634,18 +692,18 @@ static int hw_atl2_hw_multicast_list_set(struct aq_hw_s *self,
|
|||
u32 l = (ar_mac[i][2] << 24) | (ar_mac[i][3] << 16) |
|
||||
(ar_mac[i][4] << 8) | ar_mac[i][5];
|
||||
|
||||
hw_atl_rpfl2_uc_flr_en_set(self, 0U, HW_ATL2_MAC_MIN + i);
|
||||
hw_atl_rpfl2_uc_flr_en_set(self, 0U, base_location + i);
|
||||
|
||||
hw_atl_rpfl2unicast_dest_addresslsw_set(self, l,
|
||||
HW_ATL2_MAC_MIN + i);
|
||||
base_location + i);
|
||||
|
||||
hw_atl_rpfl2unicast_dest_addressmsw_set(self, h,
|
||||
HW_ATL2_MAC_MIN + i);
|
||||
base_location + i);
|
||||
|
||||
hw_atl2_rpfl2_uc_flr_tag_set(self, 1, HW_ATL2_MAC_MIN + i);
|
||||
hw_atl2_rpfl2_uc_flr_tag_set(self, 1, base_location + i);
|
||||
|
||||
hw_atl_rpfl2_uc_flr_en_set(self, (cfg->is_mc_list_enabled),
|
||||
HW_ATL2_MAC_MIN + i);
|
||||
base_location + i);
|
||||
}
|
||||
|
||||
err = aq_hw_err_from_flags(self);
|
||||
|
|
@ -816,7 +874,7 @@ static int hw_atl2_hw_vlan_ctrl(struct aq_hw_s *self, bool enable)
|
|||
const struct aq_hw_ops hw_atl2_ops = {
|
||||
.hw_soft_reset = hw_atl2_utils_soft_reset,
|
||||
.hw_prepare = hw_atl2_utils_initfw,
|
||||
.hw_set_mac_address = hw_atl_b0_hw_mac_addr_set,
|
||||
.hw_set_mac_address = hw_atl2_hw_mac_addr_set,
|
||||
.hw_init = hw_atl2_hw_init,
|
||||
.hw_reset = hw_atl2_hw_reset,
|
||||
.hw_start = hw_atl_b0_hw_start,
|
||||
|
|
@ -846,6 +904,7 @@ const struct aq_hw_ops hw_atl2_ops = {
|
|||
.hw_rss_set = hw_atl2_hw_rss_set,
|
||||
.hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set,
|
||||
.hw_tc_rate_limit_set = hw_atl2_hw_init_tx_tc_rate_limit,
|
||||
.hw_get_regs = hw_atl2_utils_hw_get_regs,
|
||||
.hw_get_hw_stats = hw_atl2_utils_get_hw_stats,
|
||||
.hw_get_fw_version = hw_atl2_utils_get_fw_version,
|
||||
.hw_set_offload = hw_atl_b0_hw_offload_set,
|
||||
|
|
|
|||
|
|
@ -626,6 +626,8 @@ int hw_atl2_utils_get_filter_caps(struct aq_hw_s *self)
|
|||
if (priv->art_count == 0)
|
||||
priv->art_count = HW_ATL2_ART_TOTAL_ENTRIES;
|
||||
priv->l2_filters_base_index = filter_caps.l2_filters_base_index;
|
||||
if (priv->l2_filters_base_index >= HW_ATL2_MAC_MAX)
|
||||
priv->l2_filters_base_index = HW_ATL2_MAC_UC;
|
||||
priv->l2_filter_count = filter_caps.l2_filter_count;
|
||||
priv->etype_filter_base_index = filter_caps.ethertype_filter_base_index;
|
||||
priv->etype_filter_count = filter_caps.ethertype_filter_count;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user