]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: airoha: Fix PPE table access in airoha_ppe_debugfs_foe_show()
authorLorenzo Bianconi <lorenzo@kernel.org>
Thu, 31 Jul 2025 10:29:08 +0000 (12:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Aug 2025 14:39:25 +0000 (16:39 +0200)
[ Upstream commit 38358fa3cc8e16c6862a3e5c5c233f9f652e3a6d ]

In order to avoid any possible race we need to hold the ppe_lock
spinlock accessing the hw PPE table. airoha_ppe_foe_get_entry routine is
always executed holding ppe_lock except in airoha_ppe_debugfs_foe_show
routine. Fix the problem introducing airoha_ppe_foe_get_entry_locked
routine.

Fixes: 3fe15c640f380 ("net: airoha: Introduce PPE debugfs support")
Reviewed-by: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250731-airoha_ppe_foe_get_entry_locked-v2-1-50efbd8c0fd6@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/airoha/airoha_ppe.c

index 0e217acfc5ef748453b020e5713ace1910abc4a8..7832fe8fc2021dc713063f41fe5f23bc1ea8daf0 100644 (file)
@@ -498,9 +498,11 @@ static void airoha_ppe_foe_flow_stats_update(struct airoha_ppe *ppe,
                FIELD_PREP(AIROHA_FOE_IB2_NBQ, nbq);
 }
 
-struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
-                                                 u32 hash)
+static struct airoha_foe_entry *
+airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash)
 {
+       lockdep_assert_held(&ppe_lock);
+
        if (hash < PPE_SRAM_NUM_ENTRIES) {
                u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry);
                struct airoha_eth *eth = ppe->eth;
@@ -527,6 +529,18 @@ struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
        return ppe->foe + hash * sizeof(struct airoha_foe_entry);
 }
 
+struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
+                                                 u32 hash)
+{
+       struct airoha_foe_entry *hwe;
+
+       spin_lock_bh(&ppe_lock);
+       hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
+       spin_unlock_bh(&ppe_lock);
+
+       return hwe;
+}
+
 static bool airoha_ppe_foe_compare_entry(struct airoha_flow_table_entry *e,
                                         struct airoha_foe_entry *hwe)
 {
@@ -641,7 +655,7 @@ airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe,
        struct airoha_flow_table_entry *f;
        int type;
 
-       hwe_p = airoha_ppe_foe_get_entry(ppe, hash);
+       hwe_p = airoha_ppe_foe_get_entry_locked(ppe, hash);
        if (!hwe_p)
                return -EINVAL;
 
@@ -693,7 +707,7 @@ static void airoha_ppe_foe_insert_entry(struct airoha_ppe *ppe,
 
        spin_lock_bh(&ppe_lock);
 
-       hwe = airoha_ppe_foe_get_entry(ppe, hash);
+       hwe = airoha_ppe_foe_get_entry_locked(ppe, hash);
        if (!hwe)
                goto unlock;
 
@@ -808,7 +822,7 @@ airoha_ppe_foe_flow_l2_entry_update(struct airoha_ppe *ppe,
                u32 ib1, state;
                int idle;
 
-               hwe = airoha_ppe_foe_get_entry(ppe, iter->hash);
+               hwe = airoha_ppe_foe_get_entry_locked(ppe, iter->hash);
                if (!hwe)
                        continue;
 
@@ -845,7 +859,7 @@ static void airoha_ppe_foe_flow_entry_update(struct airoha_ppe *ppe,
        if (e->hash == 0xffff)
                goto unlock;
 
-       hwe_p = airoha_ppe_foe_get_entry(ppe, e->hash);
+       hwe_p = airoha_ppe_foe_get_entry_locked(ppe, e->hash);
        if (!hwe_p)
                goto unlock;