Commit 3ff468ef authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski

net: mscc: ocelot: remove struct ocelot_mm_state :: lock

Unfortunately, the workarounds for the hardware bugs make it pointless
to keep fine-grained locking for the MAC Merge state of each port.

Our vsc9959_cut_through_fwd() implementation requires
ocelot->fwd_domain_lock to be held, in order to serialize with changes
to the bridging domains and to port speed changes (which affect which
ports can be cut-through). Simultaneously, the traffic classes which can
be cut-through cannot be preemptible at the same time, and this will
depend on the MAC Merge layer state (which changes from threaded
interrupt context).

Since vsc9959_cut_through_fwd() would have to hold the mm->lock of all
ports for a correct and race-free implementation with respect to
ocelot_mm_irq(), in practice it means that any time a port's mm->lock is
held, it would potentially block holders of ocelot->fwd_domain_lock.

In the interest of simple locking rules, make all MAC Merge layer state
changes (and preemptible traffic class changes) be serialized by the
ocelot->fwd_domain_lock.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 15f93f46
...@@ -56,8 +56,6 @@ static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port) ...@@ -56,8 +56,6 @@ static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
enum ethtool_mm_verify_status verify_status; enum ethtool_mm_verify_status verify_status;
u32 val; u32 val;
mutex_lock(&mm->lock);
val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS); val = ocelot_port_readl(ocelot_port, DEV_MM_STATUS);
verify_status = ocelot_mm_verify_status(val); verify_status = ocelot_mm_verify_status(val);
...@@ -88,16 +86,18 @@ static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port) ...@@ -88,16 +86,18 @@ static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
} }
ocelot_port_writel(ocelot_port, val, DEV_MM_STATUS); ocelot_port_writel(ocelot_port, val, DEV_MM_STATUS);
mutex_unlock(&mm->lock);
} }
void ocelot_mm_irq(struct ocelot *ocelot) void ocelot_mm_irq(struct ocelot *ocelot)
{ {
int port; int port;
mutex_lock(&ocelot->fwd_domain_lock);
for (port = 0; port < ocelot->num_phys_ports; port++) for (port = 0; port < ocelot->num_phys_ports; port++)
ocelot_mm_update_port_status(ocelot, port); ocelot_mm_update_port_status(ocelot, port);
mutex_unlock(&ocelot->fwd_domain_lock);
} }
EXPORT_SYMBOL_GPL(ocelot_mm_irq); EXPORT_SYMBOL_GPL(ocelot_mm_irq);
...@@ -107,14 +107,11 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port, ...@@ -107,14 +107,11 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port,
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
u32 mm_enable = 0, verify_disable = 0, add_frag_size; u32 mm_enable = 0, verify_disable = 0, add_frag_size;
struct ocelot_mm_state *mm;
int err; int err;
if (!ocelot->mm_supported) if (!ocelot->mm_supported)
return -EOPNOTSUPP; return -EOPNOTSUPP;
mm = &ocelot->mm[port];
err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size, err = ethtool_mm_frag_size_min_to_add(cfg->tx_min_frag_size,
&add_frag_size, extack); &add_frag_size, extack);
if (err) if (err)
...@@ -129,7 +126,7 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port, ...@@ -129,7 +126,7 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port,
if (!cfg->verify_enabled) if (!cfg->verify_enabled)
verify_disable = DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS; verify_disable = DEV_MM_CONFIG_VERIF_CONFIG_PRM_VERIFY_DIS;
mutex_lock(&mm->lock); mutex_lock(&ocelot->fwd_domain_lock);
ocelot_port_rmwl(ocelot_port, mm_enable, ocelot_port_rmwl(ocelot_port, mm_enable,
DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA | DEV_MM_CONFIG_ENABLE_CONFIG_MM_TX_ENA |
...@@ -148,7 +145,7 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port, ...@@ -148,7 +145,7 @@ int ocelot_port_set_mm(struct ocelot *ocelot, int port,
QSYS_PREEMPTION_CFG, QSYS_PREEMPTION_CFG,
port); port);
mutex_unlock(&mm->lock); mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
} }
...@@ -166,7 +163,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port, ...@@ -166,7 +163,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port,
mm = &ocelot->mm[port]; mm = &ocelot->mm[port];
mutex_lock(&mm->lock); mutex_lock(&ocelot->fwd_domain_lock);
val = ocelot_port_readl(ocelot_port, DEV_MM_ENABLE_CONFIG); val = ocelot_port_readl(ocelot_port, DEV_MM_ENABLE_CONFIG);
state->pmac_enabled = !!(val & DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA); state->pmac_enabled = !!(val & DEV_MM_CONFIG_ENABLE_CONFIG_MM_RX_ENA);
...@@ -185,7 +182,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port, ...@@ -185,7 +182,7 @@ int ocelot_port_get_mm(struct ocelot *ocelot, int port,
state->verify_status = mm->verify_status; state->verify_status = mm->verify_status;
state->tx_active = mm->tx_active; state->tx_active = mm->tx_active;
mutex_unlock(&mm->lock); mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
} }
...@@ -209,7 +206,6 @@ int ocelot_mm_init(struct ocelot *ocelot) ...@@ -209,7 +206,6 @@ int ocelot_mm_init(struct ocelot *ocelot)
u32 val; u32 val;
mm = &ocelot->mm[port]; mm = &ocelot->mm[port];
mutex_init(&mm->lock);
ocelot_port = ocelot->ports[port]; ocelot_port = ocelot->ports[port];
/* Update initial status variable for the /* Update initial status variable for the
......
...@@ -744,7 +744,6 @@ struct ocelot_mirror { ...@@ -744,7 +744,6 @@ struct ocelot_mirror {
}; };
struct ocelot_mm_state { struct ocelot_mm_state {
struct mutex lock;
enum ethtool_mm_verify_status verify_status; enum ethtool_mm_verify_status verify_status;
bool tx_active; bool tx_active;
}; };
......
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