From 542043e91df452ed09f382d8c41cdf3788f31b5e Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:13 +0300 Subject: net: dsa: sja1105: parameterize the number of ports The sja1105 driver will gain support for the next-gen SJA1110 switch, which is very similar except for the fact it has more than 5 ports. So we need to replace the hardcoded SJA1105_NUM_PORTS in this driver with ds->num_ports. This patch is as mechanical as possible (save for the fact that ds->num_ports is not an integer constant expression). Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_clocking.c | 3 +- drivers/net/dsa/sja1105/sja1105_flower.c | 9 +++-- drivers/net/dsa/sja1105/sja1105_main.c | 61 ++++++++++++++++++------------ drivers/net/dsa/sja1105/sja1105_spi.c | 4 +- drivers/net/dsa/sja1105/sja1105_tas.c | 14 ++++--- 5 files changed, 53 insertions(+), 38 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c index 2a9b8a6a5306..f54b4d03a002 100644 --- a/drivers/net/dsa/sja1105/sja1105_clocking.c +++ b/drivers/net/dsa/sja1105/sja1105_clocking.c @@ -721,9 +721,10 @@ int sja1105_clocking_setup_port(struct sja1105_private *priv, int port) int sja1105_clocking_setup(struct sja1105_private *priv) { + struct dsa_switch *ds = priv->ds; int port, rc; - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { rc = sja1105_clocking_setup_port(priv, port); if (rc < 0) return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_flower.c b/drivers/net/dsa/sja1105/sja1105_flower.c index 973761132fc3..77c54126b3fc 100644 --- a/drivers/net/dsa/sja1105/sja1105_flower.c +++ b/drivers/net/dsa/sja1105/sja1105_flower.c @@ -35,6 +35,7 @@ static int sja1105_setup_bcast_policer(struct sja1105_private *priv, { struct sja1105_rule *rule = sja1105_rule_find(priv, cookie); struct sja1105_l2_policing_entry *policing; + struct dsa_switch *ds = priv->ds; bool new_rule = false; unsigned long p; int rc; @@ -59,7 +60,7 @@ static int sja1105_setup_bcast_policer(struct sja1105_private *priv, policing = priv->static_config.tables[BLK_IDX_L2_POLICING].entries; - if (policing[(SJA1105_NUM_PORTS * SJA1105_NUM_TC) + port].sharindx != port) { + if (policing[(ds->num_ports * SJA1105_NUM_TC) + port].sharindx != port) { NL_SET_ERR_MSG_MOD(extack, "Port already has a broadcast policer"); rc = -EEXIST; @@ -72,7 +73,7 @@ static int sja1105_setup_bcast_policer(struct sja1105_private *priv, * point to the newly allocated policer */ for_each_set_bit(p, &rule->port_mask, SJA1105_NUM_PORTS) { - int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + p; + int bcast = (ds->num_ports * SJA1105_NUM_TC) + p; policing[bcast].sharindx = rule->bcast_pol.sharindx; } @@ -435,7 +436,7 @@ int sja1105_cls_flower_del(struct dsa_switch *ds, int port, policing = priv->static_config.tables[BLK_IDX_L2_POLICING].entries; if (rule->type == SJA1105_RULE_BCAST_POLICER) { - int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + port; + int bcast = (ds->num_ports * SJA1105_NUM_TC) + port; old_sharindx = policing[bcast].sharindx; policing[bcast].sharindx = port; @@ -486,7 +487,7 @@ void sja1105_flower_setup(struct dsa_switch *ds) INIT_LIST_HEAD(&priv->flow_block.rules); - for (port = 0; port < SJA1105_NUM_PORTS; port++) + for (port = 0; port < ds->num_ports; port++) priv->flow_block.l2_policer_used[port] = true; } diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 802314e90e64..ed98bb51596a 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -106,6 +106,7 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv) .ingress = false, }; struct sja1105_mac_config_entry *mac; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; int i; @@ -117,16 +118,16 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_NUM_PORTS, + table->entries = kcalloc(ds->num_ports, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_NUM_PORTS; + table->entry_count = ds->num_ports; mac = table->entries; - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { mac[i] = default_mac; if (i == dsa_upstream_port(priv->ds, i)) { /* STP doesn't get called for CPU port, so we need to @@ -161,6 +162,7 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv, { struct device *dev = &priv->spidev->dev; struct sja1105_xmii_params_entry *mii; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; int i; @@ -182,7 +184,7 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv, mii = table->entries; - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { if (dsa_is_unused_port(priv->ds, i)) continue; @@ -265,8 +267,6 @@ static int sja1105_init_static_fdb(struct sja1105_private *priv) static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) { - struct sja1105_table *table; - u64 max_fdb_entries = SJA1105_MAX_L2_LOOKUP_COUNT / SJA1105_NUM_PORTS; struct sja1105_l2_lookup_params_entry default_l2_lookup_params = { /* Learned FDB entries are forgotten after 300 seconds */ .maxage = SJA1105_AGEING_TIME_MS(300000), @@ -274,8 +274,6 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) .dyn_tbsz = SJA1105ET_FDB_BIN_SIZE, /* And the P/Q/R/S equivalent setting: */ .start_dynspc = 0, - .maxaddrp = {max_fdb_entries, max_fdb_entries, max_fdb_entries, - max_fdb_entries, max_fdb_entries, }, /* 2^8 + 2^5 + 2^3 + 2^2 + 2^1 + 1 in Koopman notation */ .poly = 0x97, /* This selects between Independent VLAN Learning (IVL) and @@ -299,6 +297,15 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) .owr_dyn = true, .drpnolearn = true, }; + struct dsa_switch *ds = priv->ds; + struct sja1105_table *table; + u64 max_fdb_entries; + int port; + + max_fdb_entries = SJA1105_MAX_L2_LOOKUP_COUNT / ds->num_ports; + + for (port = 0; port < ds->num_ports; port++) + default_l2_lookup_params.maxaddrp[port] = max_fdb_entries; table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS]; @@ -388,6 +395,7 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv) static int sja1105_init_l2_forwarding(struct sja1105_private *priv) { struct sja1105_l2_forwarding_entry *l2fwd; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; int i, j; @@ -408,7 +416,7 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) l2fwd = table->entries; /* First 5 entries define the forwarding rules */ - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { unsigned int upstream = dsa_upstream_port(priv->ds, i); for (j = 0; j < SJA1105_NUM_TC; j++) @@ -436,8 +444,8 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) * Create a one-to-one mapping. */ for (i = 0; i < SJA1105_NUM_TC; i++) - for (j = 0; j < SJA1105_NUM_PORTS; j++) - l2fwd[SJA1105_NUM_PORTS + i].vlan_pmap[j] = i; + for (j = 0; j < ds->num_ports; j++) + l2fwd[ds->num_ports + i].vlan_pmap[j] = i; return 0; } @@ -533,7 +541,7 @@ static int sja1105_init_general_params(struct sja1105_private *priv) */ .host_port = dsa_upstream_port(priv->ds, 0), /* Default to an invalid value */ - .mirr_port = SJA1105_NUM_PORTS, + .mirr_port = priv->ds->num_ports, /* Link-local traffic received on casc_port will be forwarded * to host_port without embedding the source port and device ID * info in the destination MAC address (presumably because it @@ -541,7 +549,7 @@ static int sja1105_init_general_params(struct sja1105_private *priv) * that). Default to an invalid port (to disable the feature) * and overwrite this if we find any DSA (cascaded) ports. */ - .casc_port = SJA1105_NUM_PORTS, + .casc_port = priv->ds->num_ports, /* No TTEthernet */ .vllupformat = SJA1105_VL_FORMAT_PSFP, .vlmarker = 0, @@ -662,6 +670,7 @@ static int sja1105_init_avb_params(struct sja1105_private *priv) static int sja1105_init_l2_policing(struct sja1105_private *priv) { struct sja1105_l2_policing_entry *policing; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; int port, tc; @@ -683,8 +692,8 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv) policing = table->entries; /* Setup shared indices for the matchall policers */ - for (port = 0; port < SJA1105_NUM_PORTS; port++) { - int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + port; + for (port = 0; port < ds->num_ports; port++) { + int bcast = (ds->num_ports * SJA1105_NUM_TC) + port; for (tc = 0; tc < SJA1105_NUM_TC; tc++) policing[port * SJA1105_NUM_TC + tc].sharindx = port; @@ -693,7 +702,7 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv) } /* Setup the matchall policer parameters */ - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { int mtu = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN; if (dsa_is_cpu_port(priv->ds, port)) @@ -759,9 +768,10 @@ static int sja1105_static_config_load(struct sja1105_private *priv, static int sja1105_parse_rgmii_delays(struct sja1105_private *priv, const struct sja1105_dt_port *ports) { + struct dsa_switch *ds = priv->ds; int i; - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { if (ports[i].role == XMII_MAC) continue; @@ -1636,7 +1646,7 @@ static int sja1105_bridge_member(struct dsa_switch *ds, int port, l2_fwd = priv->static_config.tables[BLK_IDX_L2_FORWARDING].entries; - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { /* Add this port to the forwarding matrix of the * other ports in the same bridge, and viceversa. */ @@ -1852,7 +1862,7 @@ int sja1105_static_config_reload(struct sja1105_private *priv, * switch wants to see in the static config in order to allow us to * change it through the dynamic interface later. */ - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { speed_mbps[i] = sja1105_speed[mac[i].speed]; mac[i].speed = SJA1105_SPEED_AUTO; } @@ -1904,7 +1914,7 @@ out_unlock_ptp: if (rc < 0) goto out; - for (i = 0; i < SJA1105_NUM_PORTS; i++) { + for (i = 0; i < ds->num_ports; i++) { rc = sja1105_adjust_port_config(priv, i, speed_mbps[i]); if (rc < 0) goto out; @@ -3022,7 +3032,7 @@ static void sja1105_teardown(struct dsa_switch *ds) struct sja1105_bridge_vlan *v, *n; int port; - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { struct sja1105_port *sp = &priv->ports[port]; if (!dsa_is_user_port(ds, port)) @@ -3225,6 +3235,7 @@ static int sja1105_mirror_apply(struct sja1105_private *priv, int from, int to, { struct sja1105_general_params_entry *general_params; struct sja1105_mac_config_entry *mac; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; bool already_enabled; u64 new_mirr_port; @@ -3235,7 +3246,7 @@ static int sja1105_mirror_apply(struct sja1105_private *priv, int from, int to, mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; - already_enabled = (general_params->mirr_port != SJA1105_NUM_PORTS); + already_enabled = (general_params->mirr_port != ds->num_ports); if (already_enabled && enabled && general_params->mirr_port != to) { dev_err(priv->ds->dev, "Delete mirroring rules towards port %llu first\n", @@ -3249,7 +3260,7 @@ static int sja1105_mirror_apply(struct sja1105_private *priv, int from, int to, int port; /* Anybody still referencing mirr_port? */ - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { if (mac[port].ing_mirr || mac[port].egr_mirr) { keep = true; break; @@ -3257,7 +3268,7 @@ static int sja1105_mirror_apply(struct sja1105_private *priv, int from, int to, } /* Unset already_enabled for next time */ if (!keep) - new_mirr_port = SJA1105_NUM_PORTS; + new_mirr_port = ds->num_ports; } if (new_mirr_port != general_params->mirr_port) { general_params->mirr_port = new_mirr_port; @@ -3679,7 +3690,7 @@ static int sja1105_probe(struct spi_device *spi) } /* Connections between dsa_port and sja1105_port */ - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { struct sja1105_port *sp = &priv->ports[port]; struct dsa_port *dp = dsa_to_port(ds, port); struct net_device *slave; diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index df3a780e9dcc..f22340e77fd5 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -309,10 +309,10 @@ int static_config_buf_prepare_for_upload(struct sja1105_private *priv, int sja1105_static_config_upload(struct sja1105_private *priv) { - unsigned long port_bitmap = GENMASK_ULL(SJA1105_NUM_PORTS - 1, 0); struct sja1105_static_config *config = &priv->static_config; const struct sja1105_regs *regs = priv->info->regs; struct device *dev = &priv->spidev->dev; + struct dsa_switch *ds = priv->ds; struct sja1105_status status; int rc, retries = RETRIES; u8 *config_buf; @@ -333,7 +333,7 @@ int sja1105_static_config_upload(struct sja1105_private *priv) * Tx on all ports and waiting for current packet to drain. * Otherwise, the PHY will see an unterminated Ethernet packet. */ - rc = sja1105_inhibit_tx(priv, port_bitmap, true); + rc = sja1105_inhibit_tx(priv, GENMASK_ULL(ds->num_ports - 1, 0), true); if (rc < 0) { dev_err(dev, "Failed to inhibit Tx on ports\n"); rc = -ENXIO; diff --git a/drivers/net/dsa/sja1105/sja1105_tas.c b/drivers/net/dsa/sja1105/sja1105_tas.c index 31d8acff1f01..e6153848a950 100644 --- a/drivers/net/dsa/sja1105/sja1105_tas.c +++ b/drivers/net/dsa/sja1105/sja1105_tas.c @@ -27,7 +27,7 @@ static int sja1105_tas_set_runtime_params(struct sja1105_private *priv) tas_data->enabled = false; - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { const struct tc_taprio_qopt_offload *offload; offload = tas_data->offload[port]; @@ -164,6 +164,7 @@ int sja1105_init_scheduling(struct sja1105_private *priv) struct sja1105_tas_data *tas_data = &priv->tas_data; struct sja1105_gating_config *gating_cfg = &tas_data->gating_cfg; struct sja1105_schedule_entry *schedule; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; int schedule_start_idx; s64 entry_point_delta; @@ -207,7 +208,7 @@ int sja1105_init_scheduling(struct sja1105_private *priv) } /* Figure out the dimensioning of the problem */ - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { if (tas_data->offload[port]) { num_entries += tas_data->offload[port]->num_entries; num_cycles++; @@ -269,7 +270,7 @@ int sja1105_init_scheduling(struct sja1105_private *priv) schedule_entry_points_params->clksrc = SJA1105_TAS_CLKSRC_PTP; schedule_entry_points_params->actsubsch = num_cycles - 1; - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { const struct tc_taprio_qopt_offload *offload; /* Relative base time */ s64 rbt; @@ -468,6 +469,7 @@ bool sja1105_gating_check_conflicts(struct sja1105_private *priv, int port, struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg; size_t num_entries = gating_cfg->num_entries; struct tc_taprio_qopt_offload *dummy; + struct dsa_switch *ds = priv->ds; struct sja1105_gate_entry *e; bool conflict; int i = 0; @@ -491,7 +493,7 @@ bool sja1105_gating_check_conflicts(struct sja1105_private *priv, int port, if (port != -1) { conflict = sja1105_tas_check_conflicts(priv, port, dummy); } else { - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { conflict = sja1105_tas_check_conflicts(priv, port, dummy); if (conflict) @@ -554,7 +556,7 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, } } - for (other_port = 0; other_port < SJA1105_NUM_PORTS; other_port++) { + for (other_port = 0; other_port < ds->num_ports; other_port++) { if (other_port == port) continue; @@ -885,7 +887,7 @@ void sja1105_tas_teardown(struct dsa_switch *ds) cancel_work_sync(&priv->tas_data.tas_work); - for (port = 0; port < SJA1105_NUM_PORTS; port++) { + for (port = 0; port < ds->num_ports; port++) { offload = priv->tas_data.offload[port]; if (!offload) continue; -- cgit v1.2.3 From f238fef1b3de2fac2d09d925ebc75aacf5e27fd1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:14 +0300 Subject: net: dsa: sja1105: avoid some work for unused ports Do not put unused ports in the forwarding domain, and do not allocate FDB entries for dynamic address learning for them. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_main.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index ed98bb51596a..2f162765d9f3 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -298,14 +298,22 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) .drpnolearn = true, }; struct dsa_switch *ds = priv->ds; + int port, num_used_ports = 0; struct sja1105_table *table; u64 max_fdb_entries; - int port; - - max_fdb_entries = SJA1105_MAX_L2_LOOKUP_COUNT / ds->num_ports; for (port = 0; port < ds->num_ports; port++) + if (!dsa_is_unused_port(ds, port)) + num_used_ports++; + + max_fdb_entries = SJA1105_MAX_L2_LOOKUP_COUNT / num_used_ports; + + for (port = 0; port < ds->num_ports; port++) { + if (dsa_is_unused_port(ds, port)) + continue; + default_l2_lookup_params.maxaddrp[port] = max_fdb_entries; + } table = &priv->static_config.tables[BLK_IDX_L2_LOOKUP_PARAMS]; @@ -419,6 +427,9 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) for (i = 0; i < ds->num_ports; i++) { unsigned int upstream = dsa_upstream_port(priv->ds, i); + if (dsa_is_unused_port(ds, i)) + continue; + for (j = 0; j < SJA1105_NUM_TC; j++) l2fwd[i].vlan_pmap[j] = j; @@ -440,12 +451,18 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) l2fwd[upstream].bc_domain |= BIT(i); l2fwd[upstream].fl_domain |= BIT(i); } + /* Next 8 entries define VLAN PCP mapping from ingress to egress. * Create a one-to-one mapping. */ - for (i = 0; i < SJA1105_NUM_TC; i++) - for (j = 0; j < ds->num_ports; j++) + for (i = 0; i < SJA1105_NUM_TC; i++) { + for (j = 0; j < ds->num_ports; j++) { + if (dsa_is_unused_port(ds, j)) + continue; + l2fwd[ds->num_ports + i].vlan_pmap[j] = i; + } + } return 0; } -- cgit v1.2.3 From 82760d7f2ea63829d6ab0f3de7ec98b93132c8ee Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:15 +0300 Subject: net: dsa: sja1105: dimension the data structures for a larger port count Introduce a SJA1105_MAX_NUM_PORTS macro which at the moment is equal to SJA1105_NUM_PORTS (5). With the introduction of SJA1110, these structures will need to hold information for up to 11 ports. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105.h | 33 ++++++++++++++++---------------- drivers/net/dsa/sja1105/sja1105_flower.c | 4 ++-- drivers/net/dsa/sja1105/sja1105_main.c | 8 ++++---- drivers/net/dsa/sja1105/sja1105_tas.h | 2 +- drivers/net/dsa/sja1105/sja1105_vl.c | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 10fc6b54f9f6..3737a3b38863 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -14,6 +14,7 @@ #include "sja1105_static_config.h" #define SJA1105_NUM_PORTS 5 +#define SJA1105_MAX_NUM_PORTS SJA1105_NUM_PORTS #define SJA1105_NUM_TC 8 #define SJA1105ET_FDB_BIN_SIZE 4 /* The hardware value is in multiples of 10 ms. @@ -57,19 +58,19 @@ struct sja1105_regs { u64 ptpclkcorp; u64 ptpsyncts; u64 ptpschtm; - u64 ptpegr_ts[SJA1105_NUM_PORTS]; - u64 pad_mii_tx[SJA1105_NUM_PORTS]; - u64 pad_mii_rx[SJA1105_NUM_PORTS]; - u64 pad_mii_id[SJA1105_NUM_PORTS]; - u64 cgu_idiv[SJA1105_NUM_PORTS]; - u64 mii_tx_clk[SJA1105_NUM_PORTS]; - u64 mii_rx_clk[SJA1105_NUM_PORTS]; - u64 mii_ext_tx_clk[SJA1105_NUM_PORTS]; - u64 mii_ext_rx_clk[SJA1105_NUM_PORTS]; - u64 rgmii_tx_clk[SJA1105_NUM_PORTS]; - u64 rmii_ref_clk[SJA1105_NUM_PORTS]; - u64 rmii_ext_tx_clk[SJA1105_NUM_PORTS]; - u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_NUM_PORTS]; + u64 ptpegr_ts[SJA1105_MAX_NUM_PORTS]; + u64 pad_mii_tx[SJA1105_MAX_NUM_PORTS]; + u64 pad_mii_rx[SJA1105_MAX_NUM_PORTS]; + u64 pad_mii_id[SJA1105_MAX_NUM_PORTS]; + u64 cgu_idiv[SJA1105_MAX_NUM_PORTS]; + u64 mii_tx_clk[SJA1105_MAX_NUM_PORTS]; + u64 mii_rx_clk[SJA1105_MAX_NUM_PORTS]; + u64 mii_ext_tx_clk[SJA1105_MAX_NUM_PORTS]; + u64 mii_ext_rx_clk[SJA1105_MAX_NUM_PORTS]; + u64 rgmii_tx_clk[SJA1105_MAX_NUM_PORTS]; + u64 rmii_ref_clk[SJA1105_MAX_NUM_PORTS]; + u64 rmii_ext_tx_clk[SJA1105_MAX_NUM_PORTS]; + u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS]; }; struct sja1105_info { @@ -206,8 +207,8 @@ enum sja1105_vlan_state { struct sja1105_private { struct sja1105_static_config static_config; - bool rgmii_rx_delay[SJA1105_NUM_PORTS]; - bool rgmii_tx_delay[SJA1105_NUM_PORTS]; + bool rgmii_rx_delay[SJA1105_MAX_NUM_PORTS]; + bool rgmii_tx_delay[SJA1105_MAX_NUM_PORTS]; bool best_effort_vlan_filtering; unsigned long learn_ena; unsigned long ucast_egress_floods; @@ -220,7 +221,7 @@ struct sja1105_private { struct list_head dsa_8021q_vlans; struct list_head bridge_vlans; struct sja1105_flow_block flow_block; - struct sja1105_port ports[SJA1105_NUM_PORTS]; + struct sja1105_port ports[SJA1105_MAX_NUM_PORTS]; /* Serializes transmission of management frames so that * the switch doesn't confuse them with one another. */ diff --git a/drivers/net/dsa/sja1105/sja1105_flower.c b/drivers/net/dsa/sja1105/sja1105_flower.c index 77c54126b3fc..6c10ffa968ce 100644 --- a/drivers/net/dsa/sja1105/sja1105_flower.c +++ b/drivers/net/dsa/sja1105/sja1105_flower.c @@ -72,7 +72,7 @@ static int sja1105_setup_bcast_policer(struct sja1105_private *priv, /* Make the broadcast policers of all ports attached to this block * point to the newly allocated policer */ - for_each_set_bit(p, &rule->port_mask, SJA1105_NUM_PORTS) { + for_each_set_bit(p, &rule->port_mask, SJA1105_MAX_NUM_PORTS) { int bcast = (ds->num_ports * SJA1105_NUM_TC) + p; policing[bcast].sharindx = rule->bcast_pol.sharindx; @@ -144,7 +144,7 @@ static int sja1105_setup_tc_policer(struct sja1105_private *priv, /* Make the policers for traffic class @tc of all ports attached to * this block point to the newly allocated policer */ - for_each_set_bit(p, &rule->port_mask, SJA1105_NUM_PORTS) { + for_each_set_bit(p, &rule->port_mask, SJA1105_MAX_NUM_PORTS) { int index = (p * SJA1105_NUM_TC) + tc; policing[index].sharindx = rule->tc_pol.sharindx; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 2f162765d9f3..76fc730b341d 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1861,8 +1861,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv, { struct ptp_system_timestamp ptp_sts_before; struct ptp_system_timestamp ptp_sts_after; + int speed_mbps[SJA1105_MAX_NUM_PORTS]; struct sja1105_mac_config_entry *mac; - int speed_mbps[SJA1105_NUM_PORTS]; struct dsa_switch *ds = priv->ds; s64 t1, t2, t3, t4; s64 t12, t34; @@ -2639,7 +2639,7 @@ out: static int sja1105_build_vlan_table(struct sja1105_private *priv, bool notify) { - u16 subvlan_map[SJA1105_NUM_PORTS][DSA_8021Q_N_SUBVLAN]; + u16 subvlan_map[SJA1105_MAX_NUM_PORTS][DSA_8021Q_N_SUBVLAN]; struct sja1105_retagging_entry *new_retagging; struct sja1105_vlan_lookup_entry *new_vlan; struct sja1105_table *table; @@ -2975,7 +2975,7 @@ static const struct dsa_8021q_ops sja1105_dsa_8021q_ops = { */ static int sja1105_setup(struct dsa_switch *ds) { - struct sja1105_dt_port ports[SJA1105_NUM_PORTS]; + struct sja1105_dt_port ports[SJA1105_MAX_NUM_PORTS]; struct sja1105_private *priv = ds->priv; int rc; @@ -3668,7 +3668,7 @@ static int sja1105_probe(struct spi_device *spi) return -ENOMEM; ds->dev = dev; - ds->num_ports = SJA1105_NUM_PORTS; + ds->num_ports = SJA1105_MAX_NUM_PORTS; ds->ops = &sja1105_switch_ops; ds->priv = priv; priv->ds = ds; diff --git a/drivers/net/dsa/sja1105/sja1105_tas.h b/drivers/net/dsa/sja1105/sja1105_tas.h index 0c173ff51751..c05bd07e8221 100644 --- a/drivers/net/dsa/sja1105/sja1105_tas.h +++ b/drivers/net/dsa/sja1105/sja1105_tas.h @@ -39,7 +39,7 @@ struct sja1105_gating_config { }; struct sja1105_tas_data { - struct tc_taprio_qopt_offload *offload[SJA1105_NUM_PORTS]; + struct tc_taprio_qopt_offload *offload[SJA1105_MAX_NUM_PORTS]; struct sja1105_gating_config gating_cfg; enum sja1105_tas_state state; enum sja1105_ptp_op last_op; diff --git a/drivers/net/dsa/sja1105/sja1105_vl.c b/drivers/net/dsa/sja1105/sja1105_vl.c index ffc4042b4502..f6e13e6c6a18 100644 --- a/drivers/net/dsa/sja1105/sja1105_vl.c +++ b/drivers/net/dsa/sja1105/sja1105_vl.c @@ -386,7 +386,7 @@ static int sja1105_init_virtual_links(struct sja1105_private *priv, if (rule->type != SJA1105_RULE_VL) continue; - for_each_set_bit(port, &rule->port_mask, SJA1105_NUM_PORTS) { + for_each_set_bit(port, &rule->port_mask, SJA1105_MAX_NUM_PORTS) { vl_lookup[k].format = SJA1105_VL_FORMAT_PSFP; vl_lookup[k].port = port; vl_lookup[k].macaddr = rule->key.vl.dmac; -- cgit v1.2.3 From df2a81a35ebb507d8d614d993d3b55425d73ffee Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:16 +0300 Subject: net: dsa: sja1105: don't assign the host port using dsa_upstream_port() If @port is unused, then dsa_upstream_port(ds, port) returns @port, which means we cannot assume the CPU port can be retrieved this way. The sja1105 switches support a single CPU port, so just iterate over the switch ports and stop at the first CPU port we see. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_main.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 76fc730b341d..409e059b87e3 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -556,7 +556,7 @@ static int sja1105_init_general_params(struct sja1105_private *priv) * receieved on host_port itself would be dropped, except * by installing a temporary 'management route' */ - .host_port = dsa_upstream_port(priv->ds, 0), + .host_port = priv->ds->num_ports, /* Default to an invalid value */ .mirr_port = priv->ds->num_ports, /* Link-local traffic received on casc_port will be forwarded @@ -579,7 +579,16 @@ static int sja1105_init_general_params(struct sja1105_private *priv) .tpid = ETH_P_SJA1105, .tpid2 = ETH_P_SJA1105, }; + struct dsa_switch *ds = priv->ds; struct sja1105_table *table; + int port; + + for (port = 0; port < ds->num_ports; port++) { + if (dsa_is_cpu_port(ds, port)) { + default_general_params.host_port = port; + break; + } + } table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; -- cgit v1.2.3 From c50376783f23ffd2dd8833c2069e52ba08e82917 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:17 +0300 Subject: net: dsa: sja1105: skip CGU configuration if it's unnecessary There are two distinct code paths which enter sja1105_clocking.c, one through sja1105_clocking_setup() and the other through sja1105_clocking_setup_port(): sja1105_static_config_reload sja1105_setup | | | +------------------+ | | v v sja1105_clocking_setup sja1105_adjust_port_config | | v | sja1105_clocking_setup_port <------------------+ As opposed to SJA1105, the SJA1110 does not need any configuration of the Clock Generation Unit in order for xMII ports to work. Just RGMII internal delays need to be configured, and that is done inside sja1105_clocking_setup_port for the RGMII ports. So this patch introduces the concept of a "reserved address", which the CGU configuration functions from sja1105_clocking.c must check before proceeding to do anything. The SJA1110 will have reserved addresses for the CGU PLLs for MII/RMII/RGMII. Additionally, make sja1105_clocking_setup() a function pointer so it can be overridden by the SJA1110. Even though nothing port-related needs to be done in the CGU, there are some operations such as disabling the watchdog clock which are unique to the SJA1110. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105.h | 1 + drivers/net/dsa/sja1105/sja1105_clocking.c | 33 +++++++++++++++++++++++++ drivers/net/dsa/sja1105/sja1105_main.c | 4 +-- drivers/net/dsa/sja1105/sja1105_spi.c | 6 +++++ drivers/net/dsa/sja1105/sja1105_static_config.h | 2 ++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 3737a3b38863..47cad24e6af0 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -109,6 +109,7 @@ struct sja1105_info { const unsigned char *addr, u16 vid); void (*ptp_cmd_packing)(u8 *buf, struct sja1105_ptp_cmd *cmd, enum packing_op op); + int (*clocking_setup)(struct sja1105_private *priv); const char *name; }; diff --git a/drivers/net/dsa/sja1105/sja1105_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c index f54b4d03a002..4697ac064abc 100644 --- a/drivers/net/dsa/sja1105/sja1105_clocking.c +++ b/drivers/net/dsa/sja1105/sja1105_clocking.c @@ -110,6 +110,9 @@ static int sja1105_cgu_idiv_config(struct sja1105_private *priv, int port, struct sja1105_cgu_idiv idiv; u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; + if (regs->cgu_idiv[port] == SJA1105_RSV_ADDR) + return 0; + if (enabled && factor != 1 && factor != 10) { dev_err(dev, "idiv factor must be 1 or 10\n"); return -ERANGE; @@ -159,6 +162,9 @@ static int sja1105_cgu_mii_tx_clk_config(struct sja1105_private *priv, u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; int clksrc; + if (regs->mii_tx_clk[port] == SJA1105_RSV_ADDR) + return 0; + if (role == XMII_MAC) clksrc = mac_clk_sources[port]; else @@ -188,6 +194,9 @@ sja1105_cgu_mii_rx_clk_config(struct sja1105_private *priv, int port) CLKSRC_MII4_RX_CLK, }; + if (regs->mii_rx_clk[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload for packed_buf */ mii_rx_clk.clksrc = clk_sources[port]; mii_rx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */ @@ -212,6 +221,9 @@ sja1105_cgu_mii_ext_tx_clk_config(struct sja1105_private *priv, int port) CLKSRC_IDIV4, }; + if (regs->mii_ext_tx_clk[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload for packed_buf */ mii_ext_tx_clk.clksrc = clk_sources[port]; mii_ext_tx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */ @@ -236,6 +248,9 @@ sja1105_cgu_mii_ext_rx_clk_config(struct sja1105_private *priv, int port) CLKSRC_IDIV4, }; + if (regs->mii_ext_rx_clk[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload for packed_buf */ mii_ext_rx_clk.clksrc = clk_sources[port]; mii_ext_rx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */ @@ -320,6 +335,9 @@ static int sja1105_cgu_rgmii_tx_clk_config(struct sja1105_private *priv, u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; int clksrc; + if (regs->rgmii_tx_clk[port] == SJA1105_RSV_ADDR) + return 0; + if (speed == SJA1105_SPEED_1000MBPS) { clksrc = CLKSRC_PLL0; } else { @@ -368,6 +386,9 @@ static int sja1105_rgmii_cfg_pad_tx_config(struct sja1105_private *priv, struct sja1105_cfg_pad_mii pad_mii_tx = {0}; u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; + if (regs->pad_mii_tx[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload */ pad_mii_tx.d32_os = 3; /* TXD[3:2] output stage: */ /* high noise/high speed */ @@ -394,6 +415,9 @@ static int sja1105_cfg_pad_rx_config(struct sja1105_private *priv, int port) struct sja1105_cfg_pad_mii pad_mii_rx = {0}; u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; + if (regs->pad_mii_rx[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload */ pad_mii_rx.d32_ih = 0; /* RXD[3:2] input stage hysteresis: */ /* non-Schmitt (default) */ @@ -572,6 +596,9 @@ static int sja1105_cgu_rmii_ref_clk_config(struct sja1105_private *priv, CLKSRC_MII4_TX_CLK, }; + if (regs->rmii_ref_clk[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload for packed_buf */ ref_clk.clksrc = clk_sources[port]; ref_clk.autoblock = 1; /* Autoblock clk while changing clksrc */ @@ -589,6 +616,9 @@ sja1105_cgu_rmii_ext_tx_clk_config(struct sja1105_private *priv, int port) struct sja1105_cgu_mii_ctrl ext_tx_clk; u8 packed_buf[SJA1105_SIZE_CGU_CMD] = {0}; + if (regs->rmii_ext_tx_clk[port] == SJA1105_RSV_ADDR) + return 0; + /* Payload for packed_buf */ ext_tx_clk.clksrc = CLKSRC_PLL1; ext_tx_clk.autoblock = 1; /* Autoblock clk while changing clksrc */ @@ -607,6 +637,9 @@ static int sja1105_cgu_rmii_pll_config(struct sja1105_private *priv) struct device *dev = priv->ds->dev; int rc; + if (regs->rmii_pll1 == SJA1105_RSV_ADDR) + return 0; + /* PLL1 must be enabled and output 50 Mhz. * This is done by writing first 0x0A010941 to * the PLL_1_C register and then deasserting diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 409e059b87e3..be48e45079f2 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1936,7 +1936,7 @@ out_unlock_ptp: * For these interfaces there is no dynamic configuration * needed, since PLLs have same settings at all speeds. */ - rc = sja1105_clocking_setup(priv); + rc = priv->info->clocking_setup(priv); if (rc < 0) goto out; @@ -3015,7 +3015,7 @@ static int sja1105_setup(struct dsa_switch *ds) return rc; } /* Configure the CGU (PHY link modes and speeds) */ - rc = sja1105_clocking_setup(priv); + rc = priv->info->clocking_setup(priv); if (rc < 0) { dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc); return rc; diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index f22340e77fd5..c08aa6fbd85d 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -489,6 +489,7 @@ const struct sja1105_info sja1105e_info = { .fdb_add_cmd = sja1105et_fdb_add, .fdb_del_cmd = sja1105et_fdb_del, .ptp_cmd_packing = sja1105et_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105et_regs, .name = "SJA1105E", }; @@ -507,6 +508,7 @@ const struct sja1105_info sja1105t_info = { .fdb_add_cmd = sja1105et_fdb_add, .fdb_del_cmd = sja1105et_fdb_del, .ptp_cmd_packing = sja1105et_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105et_regs, .name = "SJA1105T", }; @@ -526,6 +528,7 @@ const struct sja1105_info sja1105p_info = { .fdb_add_cmd = sja1105pqrs_fdb_add, .fdb_del_cmd = sja1105pqrs_fdb_del, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105pqrs_regs, .name = "SJA1105P", }; @@ -545,6 +548,7 @@ const struct sja1105_info sja1105q_info = { .fdb_add_cmd = sja1105pqrs_fdb_add, .fdb_del_cmd = sja1105pqrs_fdb_del, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105pqrs_regs, .name = "SJA1105Q", }; @@ -564,6 +568,7 @@ const struct sja1105_info sja1105r_info = { .fdb_add_cmd = sja1105pqrs_fdb_add, .fdb_del_cmd = sja1105pqrs_fdb_del, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105pqrs_regs, .name = "SJA1105R", }; @@ -584,5 +589,6 @@ const struct sja1105_info sja1105s_info = { .fdb_add_cmd = sja1105pqrs_fdb_add, .fdb_del_cmd = sja1105pqrs_fdb_del, .ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .name = "SJA1105S", }; diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index 779eb6840f05..9bc783a2bbea 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -129,6 +129,8 @@ enum sja1105_blk_idx { #define SJA1105R_PART_NO 0x9A86 #define SJA1105S_PART_NO 0x9A87 +#define SJA1105_RSV_ADDR 0xffffffffffffffffull + struct sja1105_schedule_entry { u64 winstindex; u64 winend; -- cgit v1.2.3 From fd6f2c257b0bc0c656e88dcc2c6fc7ce180fb2de Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:18 +0300 Subject: net: dsa: sja1105: dynamically choose the number of static config table entries Due to the fact that the port count is different, some static config tables have a different number of elements in SJA1105 compared to SJA1110. Such an example is the L2 Policing table, which has 45 entries in SJA1105 (one per port x traffic class, and one broadcast policer per port) and 110 entries in SJA1110 (one per port x traffic class, one broadcast and one multicast policer per port). Similarly, the MAC Configuration Table, the L2 Forwarding table, all have a different number of elements simply because the port count is different, and although this can be accounted for by looking at ds->ports, the policing table can't because of the presence of the extra multicast policers. The common denominator for the static config initializers for these tables is that they must set up all the entries within that table. So the simplest way to account for these differences in a uniform manner is to look at struct sja1105_table_ops::max_entry_count. For the sake of uniformity, this patch makes that change also for tables whose number of elements did not change in SJA1110, like the xMII Mode Parameters, the L2 Lookup Parameters, General Parameters, AVB Parameters (all of these are singleton tables with a single entry). Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_main.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index be48e45079f2..cd9359722e5f 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -118,12 +118,12 @@ static int sja1105_init_mac_settings(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(ds->num_ports, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = ds->num_ports; + table->entry_count = table->ops->max_entry_count; mac = table->entries; @@ -174,13 +174,13 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv, table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_XMII_PARAMS_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; /* Override table based on PHYLINK DT bindings */ - table->entry_count = SJA1105_MAX_XMII_PARAMS_COUNT; + table->entry_count = table->ops->max_entry_count; mii = table->entries; @@ -322,12 +322,12 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_MAX_L2_LOOKUP_PARAMS_COUNT; + table->entry_count = table->ops->max_entry_count; /* This table only has a single entry */ ((struct sja1105_l2_lookup_params_entry *)table->entries)[0] = @@ -414,12 +414,12 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_L2_FORWARDING_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_MAX_L2_FORWARDING_COUNT; + table->entry_count = table->ops->max_entry_count; l2fwd = table->entries; @@ -484,12 +484,12 @@ static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_MAX_L2_FORWARDING_PARAMS_COUNT; + table->entry_count = table->ops->max_entry_count; /* This table only has a single entry */ ((struct sja1105_l2_forwarding_params_entry *)table->entries)[0] = @@ -597,12 +597,12 @@ static int sja1105_init_general_params(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_GENERAL_PARAMS_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_MAX_GENERAL_PARAMS_COUNT; + table->entry_count = table->ops->max_entry_count; /* This table only has a single entry */ ((struct sja1105_general_params_entry *)table->entries)[0] = @@ -624,12 +624,12 @@ static int sja1105_init_avb_params(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_AVB_PARAMS_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_MAX_AVB_PARAMS_COUNT; + table->entry_count = table->ops->max_entry_count; avb = table->entries; @@ -708,12 +708,12 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv) table->entry_count = 0; } - table->entries = kcalloc(SJA1105_MAX_L2_POLICING_COUNT, + table->entries = kcalloc(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_MAX_L2_POLICING_COUNT; + table->entry_count = table->ops->max_entry_count; policing = table->entries; -- cgit v1.2.3 From f78a2517cf73fb0de68012ba2f42c9ad65d2aa14 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:19 +0300 Subject: net: dsa: sja1105: use sja1105_xfer_u32 for the reset procedure Using sja1105_xfer_buf results in a higher overhead and is harder to read. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_spi.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index c08aa6fbd85d..79ba86096a4b 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -7,8 +7,6 @@ #include #include "sja1105.h" -#define SJA1105_SIZE_RESET_CMD 4 - struct sja1105_chunk { u8 *buf; size_t len; @@ -179,28 +177,20 @@ static int sja1105et_reset_cmd(struct dsa_switch *ds) { struct sja1105_private *priv = ds->priv; const struct sja1105_regs *regs = priv->info->regs; - u8 packed_buf[SJA1105_SIZE_RESET_CMD] = {0}; - const int size = SJA1105_SIZE_RESET_CMD; - u64 cold_rst = 1; - - sja1105_pack(packed_buf, &cold_rst, 3, 3, size); + u32 cold_reset = BIT(3); - return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf, - SJA1105_SIZE_RESET_CMD); + /* Cold reset */ + return sja1105_xfer_u32(priv, SPI_WRITE, regs->rgu, &cold_reset, NULL); } static int sja1105pqrs_reset_cmd(struct dsa_switch *ds) { struct sja1105_private *priv = ds->priv; const struct sja1105_regs *regs = priv->info->regs; - u8 packed_buf[SJA1105_SIZE_RESET_CMD] = {0}; - const int size = SJA1105_SIZE_RESET_CMD; - u64 cold_rst = 1; - - sja1105_pack(packed_buf, &cold_rst, 2, 2, size); + u32 cold_reset = BIT(2); - return sja1105_xfer_buf(priv, SPI_WRITE, regs->rgu, packed_buf, - SJA1105_SIZE_RESET_CMD); + /* Cold reset */ + return sja1105_xfer_u32(priv, SPI_WRITE, regs->rgu, &cold_reset, NULL); } int sja1105_inhibit_tx(const struct sja1105_private *priv, -- cgit v1.2.3 From 38fbe91f2287c696f290d9115901aa435f7166a8 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:20 +0300 Subject: net: dsa: sja1105: configure the multicast policers, if present The SJA1110 policer array is similar in layout with SJA1105, except it contains one multicast policer per port at the end. Detect the presence of multicast policers based on the maximum number of supported L2 Policing Table entries, and make those policers have a shared index equal to the port's default policer. Letting the user configure these policers is not supported at the moment. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index cd9359722e5f..c391ab00e003 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -719,12 +719,16 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv) /* Setup shared indices for the matchall policers */ for (port = 0; port < ds->num_ports; port++) { + int mcast = (ds->num_ports * (SJA1105_NUM_TC + 1)) + port; int bcast = (ds->num_ports * SJA1105_NUM_TC) + port; for (tc = 0; tc < SJA1105_NUM_TC; tc++) policing[port * SJA1105_NUM_TC + tc].sharindx = port; policing[bcast].sharindx = port; + /* Only SJA1110 has multicast policers */ + if (mcast <= table->ops->max_entry_count) + policing[mcast].sharindx = port; } /* Setup the matchall policer parameters */ -- cgit v1.2.3 From 1bf658eefe38cc26801b5861bbb6dbf3259ba8c1 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Mon, 24 May 2021 16:14:21 +0300 Subject: net: dsa: sja1105: allow the frame buffer size to be customized The shared frame buffer of the SJA1110 is larger than that of SJA1105, which is natural due to the fact that there are more ports. Introduce yet another property in struct sja1105_info which encodes the maximum number of 128 byte blocks that can be used for frame buffers. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/sja1105/sja1105.h | 1 + drivers/net/dsa/sja1105/sja1105_main.c | 21 +++++++++------------ drivers/net/dsa/sja1105/sja1105_spi.c | 9 ++++++++- drivers/net/dsa/sja1105/sja1105_static_config.c | 13 ++++++------- drivers/net/dsa/sja1105/sja1105_static_config.h | 5 +++-- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 47cad24e6af0..2ec03917feb3 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -90,6 +90,7 @@ struct sja1105_info { */ int ptpegr_ts_bytes; int num_cbs_shapers; + int max_frame_mem; const struct sja1105_dynamic_table_ops *dyn_ops; const struct sja1105_table_ops *static_ops; const struct sja1105_regs *regs; diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index c391ab00e003..a105e174b3af 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -469,12 +469,7 @@ static int sja1105_init_l2_forwarding(struct sja1105_private *priv) static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) { - struct sja1105_l2_forwarding_params_entry default_l2fwd_params = { - /* Disallow dynamic reconfiguration of vlan_pmap */ - .max_dynp = 0, - /* Use a single memory partition for all ingress queues */ - .part_spc = { SJA1105_MAX_FRAME_MEMORY, 0, 0, 0, 0, 0, 0, 0 }, - }; + struct sja1105_l2_forwarding_params_entry *l2fwd_params; struct sja1105_table *table; table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; @@ -492,8 +487,12 @@ static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv) table->entry_count = table->ops->max_entry_count; /* This table only has a single entry */ - ((struct sja1105_l2_forwarding_params_entry *)table->entries)[0] = - default_l2fwd_params; + l2fwd_params = table->entries; + + /* Disallow dynamic reconfiguration of vlan_pmap */ + l2fwd_params->max_dynp = 0; + /* Use a single memory partition for all ingress queues */ + l2fwd_params->part_spc[0] = priv->info->max_frame_mem; return 0; } @@ -502,16 +501,14 @@ void sja1105_frame_memory_partitioning(struct sja1105_private *priv) { struct sja1105_l2_forwarding_params_entry *l2_fwd_params; struct sja1105_vl_forwarding_params_entry *vl_fwd_params; + int max_mem = priv->info->max_frame_mem; struct sja1105_table *table; - int max_mem; /* VLAN retagging is implemented using a loopback port that consumes * frame buffers. That leaves less for us. */ if (priv->vlan_state == SJA1105_VLAN_BEST_EFFORT) - max_mem = SJA1105_MAX_FRAME_MEMORY_RETAGGING; - else - max_mem = SJA1105_MAX_FRAME_MEMORY; + max_mem -= SJA1105_FRAME_MEMORY_RETAGGING_OVERHEAD; table = &priv->static_config.tables[BLK_IDX_L2_FORWARDING_PARAMS]; l2_fwd_params = table->entries; diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 79ba86096a4b..d0bc6cf90bfd 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -271,7 +271,8 @@ int static_config_buf_prepare_for_upload(struct sja1105_private *priv, char *final_header_ptr; int crc_len; - valid = sja1105_static_config_check_valid(config); + valid = sja1105_static_config_check_valid(config, + priv->info->max_frame_mem); if (valid != SJA1105_CONFIG_OK) { dev_err(&priv->spidev->dev, sja1105_static_config_error_msg[valid]); @@ -474,6 +475,7 @@ const struct sja1105_info sja1105e_info = { .can_limit_mcast_flood = false, .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, + .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, .num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT, .reset_cmd = sja1105et_reset_cmd, .fdb_add_cmd = sja1105et_fdb_add, @@ -493,6 +495,7 @@ const struct sja1105_info sja1105t_info = { .can_limit_mcast_flood = false, .ptp_ts_bits = 24, .ptpegr_ts_bytes = 4, + .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, .num_cbs_shapers = SJA1105ET_MAX_CBS_COUNT, .reset_cmd = sja1105et_reset_cmd, .fdb_add_cmd = sja1105et_fdb_add, @@ -512,6 +515,7 @@ const struct sja1105_info sja1105p_info = { .can_limit_mcast_flood = true, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -532,6 +536,7 @@ const struct sja1105_info sja1105q_info = { .can_limit_mcast_flood = true, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -552,6 +557,7 @@ const struct sja1105_info sja1105r_info = { .can_limit_mcast_flood = true, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, @@ -573,6 +579,7 @@ const struct sja1105_info sja1105s_info = { .can_limit_mcast_flood = true, .ptp_ts_bits = 32, .ptpegr_ts_bytes = 8, + .max_frame_mem = SJA1105_MAX_FRAME_MEMORY, .num_cbs_shapers = SJA1105PQRS_MAX_CBS_COUNT, .setup_rgmii_delay = sja1105pqrs_setup_rgmii_delay, .reset_cmd = sja1105pqrs_reset_cmd, diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c index a8efb7fac395..33f91ecbe07b 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.c +++ b/drivers/net/dsa/sja1105/sja1105_static_config.c @@ -657,11 +657,11 @@ const char *sja1105_static_config_error_msg[] = { }; static sja1105_config_valid_t -static_config_check_memory_size(const struct sja1105_table *tables) +static_config_check_memory_size(const struct sja1105_table *tables, int max_mem) { const struct sja1105_l2_forwarding_params_entry *l2_fwd_params; const struct sja1105_vl_forwarding_params_entry *vl_fwd_params; - int i, max_mem, mem = 0; + int i, mem = 0; l2_fwd_params = tables[BLK_IDX_L2_FORWARDING_PARAMS].entries; @@ -675,9 +675,7 @@ static_config_check_memory_size(const struct sja1105_table *tables) } if (tables[BLK_IDX_RETAGGING].entry_count) - max_mem = SJA1105_MAX_FRAME_MEMORY_RETAGGING; - else - max_mem = SJA1105_MAX_FRAME_MEMORY; + max_mem -= SJA1105_FRAME_MEMORY_RETAGGING_OVERHEAD; if (mem > max_mem) return SJA1105_OVERCOMMITTED_FRAME_MEMORY; @@ -686,7 +684,8 @@ static_config_check_memory_size(const struct sja1105_table *tables) } sja1105_config_valid_t -sja1105_static_config_check_valid(const struct sja1105_static_config *config) +sja1105_static_config_check_valid(const struct sja1105_static_config *config, + int max_mem) { const struct sja1105_table *tables = config->tables; #define IS_FULL(blk_idx) \ @@ -754,7 +753,7 @@ sja1105_static_config_check_valid(const struct sja1105_static_config *config) if (!IS_FULL(BLK_IDX_XMII_PARAMS)) return SJA1105_MISSING_XMII_TABLE; - return static_config_check_memory_size(tables); + return static_config_check_memory_size(tables, max_mem); #undef IS_FULL } diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index 9bc783a2bbea..4ddb06bd8e92 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -115,7 +115,7 @@ enum sja1105_blk_idx { #define SJA1105PQRS_MAX_CBS_COUNT 16 #define SJA1105_MAX_FRAME_MEMORY 929 -#define SJA1105_MAX_FRAME_MEMORY_RETAGGING 910 +#define SJA1105_FRAME_MEMORY_RETAGGING_OVERHEAD 19 #define SJA1105_VL_FRAME_MEMORY 100 #define SJA1105E_DEVICE_ID 0x9C00000Cull @@ -416,7 +416,8 @@ typedef enum { extern const char *sja1105_static_config_error_msg[]; sja1105_config_valid_t -sja1105_static_config_check_valid(const struct sja1105_static_config *config); +sja1105_static_config_check_valid(const struct sja1105_static_config *config, + int max_mem); void sja1105_static_config_pack(void *buf, struct sja1105_static_config *config); int sja1105_static_config_init(struct sja1105_static_config *config, -- cgit v1.2.3