diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index 10fc6b54f9f6..2ec03917feb3 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 { @@ -89,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; @@ -108,6 +110,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; }; @@ -206,8 +209,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 +223,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_clocking.c b/drivers/net/dsa/sja1105/sja1105_clocking.c index 2a9b8a6a5306..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 @@ -721,9 +754,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..6c10ffa968ce 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; @@ -71,8 +72,8 @@ 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) { - int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + p; + 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; } @@ -143,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; @@ -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..a105e174b3af 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(table->ops->max_entry_count, table->ops->unpacked_entry_size, GFP_KERNEL); if (!table->entries) return -ENOMEM; - table->entry_count = SJA1105_NUM_PORTS; + table->entry_count = table->ops->max_entry_count; 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; @@ -172,17 +174,17 @@ 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; - 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,23 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv) .owr_dyn = true, .drpnolearn = true, }; + struct dsa_switch *ds = priv->ds; + int port, num_used_ports = 0; + struct sja1105_table *table; + u64 max_fdb_entries; + + 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]; @@ -307,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] = @@ -388,6 +403,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; @@ -398,19 +414,22 @@ 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; /* 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); + if (dsa_is_unused_port(ds, i)) + continue; + for (j = 0; j < SJA1105_NUM_TC; j++) l2fwd[i].vlan_pmap[j] = j; @@ -432,24 +451,25 @@ 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 < SJA1105_NUM_PORTS; j++) - l2fwd[SJA1105_NUM_PORTS + i].vlan_pmap[j] = i; + 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; } 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]; @@ -459,16 +479,20 @@ 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] = - 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; } @@ -477,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; @@ -531,9 +553,9 @@ 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 = 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 +563,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, @@ -554,7 +576,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]; @@ -563,12 +594,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] = @@ -590,12 +621,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; @@ -662,6 +693,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; @@ -673,27 +705,31 @@ 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; /* 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 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 */ - 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 +795,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 +1673,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. */ @@ -1834,8 +1871,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; @@ -1852,7 +1889,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; } @@ -1900,11 +1937,11 @@ 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; - 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; @@ -2612,7 +2649,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; @@ -2948,7 +2985,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; @@ -2979,7 +3016,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; @@ -3022,7 +3059,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 +3262,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 +3273,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 +3287,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 +3295,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; @@ -3640,7 +3678,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; @@ -3679,7 +3717,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..d0bc6cf90bfd 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; + u32 cold_reset = BIT(3); - sja1105_pack(packed_buf, &cold_rst, 3, 3, size); - - 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; + u32 cold_reset = BIT(2); - sja1105_pack(packed_buf, &cold_rst, 2, 2, size); - - 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, @@ -281,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]); @@ -309,10 +300,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 +324,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; @@ -484,11 +475,13 @@ 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, .fdb_del_cmd = sja1105et_fdb_del, .ptp_cmd_packing = sja1105et_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105et_regs, .name = "SJA1105E", }; @@ -502,11 +495,13 @@ 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, .fdb_del_cmd = sja1105et_fdb_del, .ptp_cmd_packing = sja1105et_ptp_cmd_packing, + .clocking_setup = sja1105_clocking_setup, .regs = &sja1105et_regs, .name = "SJA1105T", }; @@ -520,12 +515,14 @@ 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, .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", }; @@ -539,12 +536,14 @@ 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, .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", }; @@ -558,12 +557,14 @@ 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, .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", }; @@ -578,11 +579,13 @@ 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, .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.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 779eb6840f05..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 @@ -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; @@ -414,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, 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; 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;