Commit d9d15a66 authored by David S. Miller's avatar David S. Miller

Merge branch 'sja1105-sja1110-prep'

Vladimir Oltean says:

====================
SJA1105 DSA driver preparation for new switch introduction (SJA1110)

This series contains refactoring patches which are necessary before the
support for the new NXP SJA1110 switch can be introduced in this driver.

As far as this series is concerned, here is the list of major changes
introduced with the SJA1110:
- 11 ports vs 5
- port 0 goes to the internal microcontroller, so it is unused as far as
  DSA is concerned
- the Clock Generation Unit does not need any configuration for
  setting up the PLLs for MII/RMII/RGMII
- the L2 Policing Table contains multicast policers too, not just
  broadcast and per-traffic class. These must be minimally initialized.
- more frame buffers
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents feeb3712 1bf658ee
......@@ -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.
*/
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
* 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 @@ static int sja1105_notify_crosschip_switches(struct sja1105_private *priv)
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;
......
......@@ -7,8 +7,6 @@
#include <linux/packing.h>
#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,
......@@ -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",
};
......@@ -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
}
......
......@@ -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,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment