From 1b0f14b6c218238de8e1e3ebb06a4efad58043b5 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 13 Apr 2021 16:24:44 +0300 Subject: [PATCH] dpaa2-switch: create a central dpaa2_switch_acl_tbl structure Introduce a new structure - dpaa2_switch_acl_tbl - to hold all data related to an ACL table: number of rules added, ACL table id, etc. This will be used more in the next patches when adding support for sharing an ACL table between ports. Signed-off-by: Ioana Ciornei Signed-off-by: David S. Miller --- .../net/ethernet/freescale/dpaa2/dpaa2-switch.c | 44 ++++++++++++++++++---- .../net/ethernet/freescale/dpaa2/dpaa2-switch.h | 10 ++++- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c index 80efc81..351ee8f 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c @@ -40,6 +40,17 @@ static struct dpaa2_switch_fdb *dpaa2_switch_fdb_get_unused(struct ethsw_core *e return NULL; } +static struct dpaa2_switch_acl_tbl * +dpaa2_switch_acl_tbl_get_unused(struct ethsw_core *ethsw) +{ + int i; + + for (i = 0; i < ethsw->sw_attr.num_ifs; i++) + if (!ethsw->acls[i].in_use) + return ðsw->acls[i]; + return NULL; +} + static u16 dpaa2_switch_port_set_fdb(struct ethsw_port_priv *port_priv, struct net_device *bridge_dev) { @@ -2689,7 +2700,7 @@ static int dpaa2_switch_port_trap_mac_addr(struct ethsw_port_priv *port_priv, acl_h = &acl_key.match; acl_m = &acl_key.mask; - if (port_priv->acl_num_rules >= DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES) { + if (port_priv->acl_tbl->num_rules >= DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES) { netdev_err(netdev, "ACL full\n"); return -ENOMEM; } @@ -2707,7 +2718,7 @@ static int dpaa2_switch_port_trap_mac_addr(struct ethsw_port_priv *port_priv, dpsw_acl_prepare_entry_cfg(&acl_key, cmd_buff); memset(&acl_entry_cfg, 0, sizeof(acl_entry_cfg)); - acl_entry_cfg.precedence = port_priv->acl_num_rules; + acl_entry_cfg.precedence = port_priv->acl_tbl->num_rules; acl_entry_cfg.result.action = DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF; acl_entry_cfg.key_iova = dma_map_single(dev, cmd_buff, DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, @@ -2719,7 +2730,7 @@ static int dpaa2_switch_port_trap_mac_addr(struct ethsw_port_priv *port_priv, err = dpsw_acl_add_entry(port_priv->ethsw_data->mc_io, 0, port_priv->ethsw_data->dpsw_handle, - port_priv->acl_tbl, &acl_entry_cfg); + port_priv->acl_tbl->id, &acl_entry_cfg); dma_unmap_single(dev, acl_entry_cfg.key_iova, sizeof(cmd_buff), DMA_TO_DEVICE); @@ -2728,7 +2739,7 @@ static int dpaa2_switch_port_trap_mac_addr(struct ethsw_port_priv *port_priv, return err; } - port_priv->acl_num_rules++; + port_priv->acl_tbl->num_rules++; return 0; } @@ -2743,12 +2754,13 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) }; struct net_device *netdev = port_priv->netdev; struct ethsw_core *ethsw = port_priv->ethsw_data; + struct dpaa2_switch_acl_tbl *acl_tbl; struct dpsw_fdb_cfg fdb_cfg = {0}; struct dpsw_acl_if_cfg acl_if_cfg; struct dpsw_if_attr dpsw_if_attr; struct dpaa2_switch_fdb *fdb; struct dpsw_acl_cfg acl_cfg; - u16 fdb_id; + u16 fdb_id, acl_tbl_id; int err; /* Get the Tx queue for this specific port */ @@ -2792,7 +2804,7 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) /* Create an ACL table to be used by this switch port */ acl_cfg.max_entries = DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES; err = dpsw_acl_add(ethsw->mc_io, 0, ethsw->dpsw_handle, - &port_priv->acl_tbl, &acl_cfg); + &acl_tbl_id, &acl_cfg); if (err) { netdev_err(netdev, "dpsw_acl_add err %d\n", err); return err; @@ -2801,13 +2813,19 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port) acl_if_cfg.if_id[0] = port_priv->idx; acl_if_cfg.num_ifs = 1; err = dpsw_acl_add_if(ethsw->mc_io, 0, ethsw->dpsw_handle, - port_priv->acl_tbl, &acl_if_cfg); + acl_tbl_id, &acl_if_cfg); if (err) { netdev_err(netdev, "dpsw_acl_add_if err %d\n", err); dpsw_acl_remove(ethsw->mc_io, 0, ethsw->dpsw_handle, - port_priv->acl_tbl); + acl_tbl_id); } + acl_tbl = dpaa2_switch_acl_tbl_get_unused(ethsw); + acl_tbl->id = acl_tbl_id; + acl_tbl->in_use = true; + acl_tbl->num_rules = 0; + port_priv->acl_tbl = acl_tbl; + err = dpaa2_switch_port_trap_mac_addr(port_priv, stpa); if (err) return err; @@ -2858,6 +2876,7 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev) } kfree(ethsw->fdbs); + kfree(ethsw->acls); kfree(ethsw->ports); dpaa2_switch_takedown(sw_dev); @@ -2983,6 +3002,13 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev) goto err_free_ports; } + ethsw->acls = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->acls), + GFP_KERNEL); + if (!ethsw->acls) { + err = -ENOMEM; + goto err_free_fdbs; + } + for (i = 0; i < ethsw->sw_attr.num_ifs; i++) { err = dpaa2_switch_probe_port(ethsw, i); if (err) @@ -3031,6 +3057,8 @@ err_stop: err_free_netdev: for (i--; i >= 0; i--) free_netdev(ethsw->ports[i]->netdev); + kfree(ethsw->acls); +err_free_fdbs: kfree(ethsw->fdbs); err_free_ports: kfree(ethsw->ports); diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h index 0ae1d27..a2c0ff2 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h @@ -101,6 +101,12 @@ struct dpaa2_switch_fdb { bool in_use; }; +struct dpaa2_switch_acl_tbl { + u16 id; + u8 num_rules; + bool in_use; +}; + /* Per port private data */ struct ethsw_port_priv { struct net_device *netdev; @@ -118,8 +124,7 @@ struct ethsw_port_priv { bool ucast_flood; bool learn_ena; - u16 acl_tbl; - u8 acl_num_rules; + struct dpaa2_switch_acl_tbl *acl_tbl; }; /* Switch data */ @@ -145,6 +150,7 @@ struct ethsw_core { int napi_users; struct dpaa2_switch_fdb *fdbs; + struct dpaa2_switch_acl_tbl *acls; }; static inline bool dpaa2_switch_supports_cpu_traffic(struct ethsw_core *ethsw) -- 2.7.4