From: Wei Fang Replace the struct ipft_entry_data pointer in struct netc_port with a plain u32 entry ID (ipft_hf_eid), using NTMP_NULL_ENTRY_ID as the sentinel value. The ipft_entry_data allocation is now freed immediately inside netc_port_add_host_flood_rule() after the hardware entry is committed, so no heap memory survives beyond that function. As a result, netc_free_host_flood_rules() is no longer needed and can be removed. Signed-off-by: Wei Fang --- drivers/net/dsa/netc/netc_main.c | 63 ++++++++++++------------------ drivers/net/dsa/netc/netc_switch.h | 2 +- 2 files changed, 25 insertions(+), 40 deletions(-) diff --git a/drivers/net/dsa/netc/netc_main.c b/drivers/net/dsa/netc/netc_main.c index 77077352c1a5..d326a00104e1 100644 --- a/drivers/net/dsa/netc/netc_main.c +++ b/drivers/net/dsa/netc/netc_main.c @@ -286,6 +286,12 @@ static int netc_init_all_ports(struct netc_switch *priv) dev_err(dev, "Failed to create MDIO bus\n"); return err; } + + /* The ipft_hf_eid is initialized to an invalid entry + * ID because the host flood rule (IPFT entry) has not + * been created. + */ + np->ipft_hf_eid = NTMP_NULL_ENTRY_ID; } } @@ -938,30 +944,12 @@ static void netc_destroy_all_lists(struct netc_switch *priv) mutex_destroy(&priv->vft_lock); } -static void netc_free_host_flood_rules(struct netc_switch *priv) -{ - struct dsa_port *dp; - - dsa_switch_for_each_user_port(dp, priv->ds) { - struct netc_port *np = priv->ports[dp->index]; - - /* No need to clear the hardware IPFT entry. Because PCIe - * FLR will be performed when the switch is re-registered, - * it will reset hardware state. So only need to free the - * memory to avoid memory leak. - */ - kfree(np->host_flood); - np->host_flood = NULL; - } -} - static void netc_teardown(struct dsa_switch *ds) { struct netc_switch *priv = ds->priv; disable_delayed_work_sync(&priv->fdbt_ageing_work); netc_destroy_all_lists(priv); - netc_free_host_flood_rules(priv); netc_free_ntmp_user(priv); } @@ -1759,37 +1747,36 @@ static int netc_port_add_host_flood_rule(struct netc_port *np, cfge->cfg = cpu_to_le32(cfg); err = ntmp_ipft_add_entry(&priv->ntmp, host_flood); - if (err) { - kfree(host_flood); - return err; - } + if (err) + goto free_host_flood; np->uc = uc; np->mc = mc; - np->host_flood = host_flood; + np->ipft_hf_eid = host_flood->entry_id; /* Enable ingress port filter table lookup */ netc_port_wr(np, NETC_PIPFCR, PIPFCR_EN); - return 0; +free_host_flood: + kfree(host_flood); + + return err; } -static void netc_port_remove_host_flood(struct netc_port *np, - struct ipft_entry_data *host_flood) +static void netc_port_remove_host_flood(struct netc_port *np, u32 entry_id) { struct netc_switch *priv = np->switch_priv; bool disable_host_flood = false; - if (!host_flood) + if (entry_id == NTMP_NULL_ENTRY_ID) return; - if (np->host_flood == host_flood) + if (np->ipft_hf_eid == entry_id) disable_host_flood = true; - ntmp_ipft_delete_entry(&priv->ntmp, host_flood->entry_id); - kfree(host_flood); + ntmp_ipft_delete_entry(&priv->ntmp, entry_id); if (disable_host_flood) { - np->host_flood = NULL; + np->ipft_hf_eid = NTMP_NULL_ENTRY_ID; np->uc = false; np->mc = false; netc_port_wr(np, NETC_PIPFCR, 0); @@ -1800,7 +1787,7 @@ static void netc_port_set_host_flood(struct dsa_switch *ds, int port, bool uc, bool mc) { struct netc_port *np = NETC_PORT(ds, port); - struct ipft_entry_data *old_host_flood; + u32 old_entry_id; /* Do not add host flood rule to ingress port filter table when * the port has joined a bridge. Otherwise, the ingress frames @@ -1808,7 +1795,7 @@ static void netc_port_set_host_flood(struct dsa_switch *ds, int port, * will be redirected directly to the CPU port. */ if (dsa_port_bridge_dev_get(np->dp)) { - netc_port_remove_host_flood(np, np->host_flood); + netc_port_remove_host_flood(np, np->ipft_hf_eid); return; } @@ -1818,20 +1805,18 @@ static void netc_port_set_host_flood(struct dsa_switch *ds, int port, /* IPFT does not support in-place updates to the KEYE element, * we need to add a new entry and then delete the old one. So - * save the old entry first. + * save the old entry ID first. */ - old_host_flood = np->host_flood; - np->host_flood = NULL; + old_entry_id = np->ipft_hf_eid; if (netc_port_add_host_flood_rule(np, uc, mc)) { - np->host_flood = old_host_flood; dev_err(ds->dev, "Failed to add host flood rule on port %d\n", port); return; } /* Remove the old host flood entry */ - netc_port_remove_host_flood(np, old_host_flood); + netc_port_remove_host_flood(np, old_entry_id); } static int netc_single_vlan_aware_bridge(struct dsa_switch *ds, @@ -2020,7 +2005,7 @@ static int netc_port_bridge_join(struct dsa_switch *ds, int port, netc_port_set_pvid(np, vlan_unaware_pvid); out: - netc_port_remove_host_flood(np, np->host_flood); + netc_port_remove_host_flood(np, np->ipft_hf_eid); if (atomic_inc_return(&priv->br_cnt) == 1) schedule_delayed_work(&priv->fdbt_ageing_work, diff --git a/drivers/net/dsa/netc/netc_switch.h b/drivers/net/dsa/netc/netc_switch.h index 305f2a92e2f9..fd36ec2d0e90 100644 --- a/drivers/net/dsa/netc/netc_switch.h +++ b/drivers/net/dsa/netc/netc_switch.h @@ -84,7 +84,7 @@ struct netc_port { u16 uc:1; u16 mc:1; u16 pvid; - struct ipft_entry_data *host_flood; + u32 ipft_hf_eid; }; struct netc_switch_regs { -- 2.34.1