Commit 009d30f1 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski

net: mscc: ocelot: extend ocelot->fwd_domain_lock to cover ocelot->tas_lock

In a future commit we will have to call vsc9959_tas_guard_bands_update()
from ocelot_port_update_active_preemptible_tcs(), and that will be
impossible due to the AB/BA locking dependencies between
ocelot->tas_lock and ocelot->fwd_domain_lock.

Just like we did in commit 3ff468ef ("net: mscc: ocelot: remove
struct ocelot_mm_state :: lock"), the only solution is to expand the
scope of ocelot->fwd_domain_lock for it to also serialize changes made
to the Time-Aware Shaper, because those will have to result in a
recalculation of cut-through TCs, which is something that depends on the
forwarding domain.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Message-ID: <20230705104422.49025-2-vladimir.oltean@nxp.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ceb20a3c
...@@ -1790,12 +1790,12 @@ static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu) ...@@ -1790,12 +1790,12 @@ static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
ocelot_port_set_maxlen(ocelot, port, new_mtu); ocelot_port_set_maxlen(ocelot, port, new_mtu);
mutex_lock(&ocelot->tas_lock); mutex_lock(&ocelot->fwd_domain_lock);
if (ocelot_port->taprio && felix->info->tas_guard_bands_update) if (ocelot_port->taprio && felix->info->tas_guard_bands_update)
felix->info->tas_guard_bands_update(ocelot, port); felix->info->tas_guard_bands_update(ocelot, port);
mutex_unlock(&ocelot->tas_lock); mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
} }
......
...@@ -1217,7 +1217,7 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) ...@@ -1217,7 +1217,7 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
u8 tas_speed; u8 tas_speed;
int tc; int tc;
lockdep_assert_held(&ocelot->tas_lock); lockdep_assert_held(&ocelot->fwd_domain_lock);
taprio = ocelot_port->taprio; taprio = ocelot_port->taprio;
...@@ -1259,8 +1259,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) ...@@ -1259,8 +1259,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
vsc9959_tas_min_gate_lengths(taprio, min_gate_len); vsc9959_tas_min_gate_lengths(taprio, min_gate_len);
mutex_lock(&ocelot->fwd_domain_lock);
for (tc = 0; tc < OCELOT_NUM_TC; tc++) { for (tc = 0; tc < OCELOT_NUM_TC; tc++) {
u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc); u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc);
u64 remaining_gate_len_ps; u64 remaining_gate_len_ps;
...@@ -1323,8 +1321,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port) ...@@ -1323,8 +1321,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port); ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port);
ocelot->ops->cut_through_fwd(ocelot); ocelot->ops->cut_through_fwd(ocelot);
mutex_unlock(&ocelot->fwd_domain_lock);
} }
static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
...@@ -1351,7 +1347,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, ...@@ -1351,7 +1347,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
break; break;
} }
mutex_lock(&ocelot->tas_lock); mutex_lock(&ocelot->fwd_domain_lock);
ocelot_rmw_rix(ocelot, ocelot_rmw_rix(ocelot,
QSYS_TAG_CONFIG_LINK_SPEED(tas_speed), QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
...@@ -1361,7 +1357,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port, ...@@ -1361,7 +1357,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
if (ocelot_port->taprio) if (ocelot_port->taprio)
vsc9959_tas_guard_bands_update(ocelot, port); vsc9959_tas_guard_bands_update(ocelot, port);
mutex_unlock(&ocelot->tas_lock); mutex_unlock(&ocelot->fwd_domain_lock);
} }
static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time, static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
...@@ -1409,7 +1405,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1409,7 +1405,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
int ret, i; int ret, i;
u32 val; u32 val;
mutex_lock(&ocelot->tas_lock); mutex_lock(&ocelot->fwd_domain_lock);
if (taprio->cmd == TAPRIO_CMD_DESTROY) { if (taprio->cmd == TAPRIO_CMD_DESTROY) {
ocelot_port_mqprio(ocelot, port, &taprio->mqprio); ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
...@@ -1421,7 +1417,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1421,7 +1417,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
vsc9959_tas_guard_bands_update(ocelot, port); vsc9959_tas_guard_bands_update(ocelot, port);
mutex_unlock(&ocelot->tas_lock); mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
} else if (taprio->cmd != TAPRIO_CMD_REPLACE) { } else if (taprio->cmd != TAPRIO_CMD_REPLACE) {
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
...@@ -1504,7 +1500,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1504,7 +1500,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
ocelot_port->taprio = taprio_offload_get(taprio); ocelot_port->taprio = taprio_offload_get(taprio);
vsc9959_tas_guard_bands_update(ocelot, port); vsc9959_tas_guard_bands_update(ocelot, port);
mutex_unlock(&ocelot->tas_lock); mutex_unlock(&ocelot->fwd_domain_lock);
return 0; return 0;
...@@ -1512,7 +1508,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, ...@@ -1512,7 +1508,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
taprio->mqprio.qopt.num_tc = 0; taprio->mqprio.qopt.num_tc = 0;
ocelot_port_mqprio(ocelot, port, &taprio->mqprio); ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
err_unlock: err_unlock:
mutex_unlock(&ocelot->tas_lock); mutex_unlock(&ocelot->fwd_domain_lock);
return ret; return ret;
} }
...@@ -1525,7 +1521,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) ...@@ -1525,7 +1521,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
int port; int port;
u32 val; u32 val;
mutex_lock(&ocelot->tas_lock); 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_port = ocelot->ports[port]; ocelot_port = ocelot->ports[port];
...@@ -1563,7 +1559,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot) ...@@ -1563,7 +1559,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
QSYS_TAG_CONFIG_ENABLE, QSYS_TAG_CONFIG_ENABLE,
QSYS_TAG_CONFIG, port); QSYS_TAG_CONFIG, port);
} }
mutex_unlock(&ocelot->tas_lock); mutex_unlock(&ocelot->fwd_domain_lock);
} }
static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port, static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
...@@ -1634,6 +1630,18 @@ static int vsc9959_qos_query_caps(struct tc_query_caps_base *base) ...@@ -1634,6 +1630,18 @@ static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)
} }
} }
static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port,
struct tc_mqprio_qopt_offload *mqprio)
{
int ret;
mutex_lock(&ocelot->fwd_domain_lock);
ret = ocelot_port_mqprio(ocelot, port, mqprio);
mutex_unlock(&ocelot->fwd_domain_lock);
return ret;
}
static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type, enum tc_setup_type type,
void *type_data) void *type_data)
...@@ -1646,7 +1654,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port, ...@@ -1646,7 +1654,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
case TC_SETUP_QDISC_TAPRIO: case TC_SETUP_QDISC_TAPRIO:
return vsc9959_qos_port_tas_set(ocelot, port, type_data); return vsc9959_qos_port_tas_set(ocelot, port, type_data);
case TC_SETUP_QDISC_MQPRIO: case TC_SETUP_QDISC_MQPRIO:
return ocelot_port_mqprio(ocelot, port, type_data); return vsc9959_qos_port_mqprio(ocelot, port, type_data);
case TC_SETUP_QDISC_CBS: case TC_SETUP_QDISC_CBS:
return vsc9959_qos_port_cbs_set(ds, port, type_data); return vsc9959_qos_port_cbs_set(ds, port, type_data);
default: default:
......
...@@ -2927,7 +2927,6 @@ int ocelot_init(struct ocelot *ocelot) ...@@ -2927,7 +2927,6 @@ int ocelot_init(struct ocelot *ocelot)
mutex_init(&ocelot->mact_lock); mutex_init(&ocelot->mact_lock);
mutex_init(&ocelot->fwd_domain_lock); mutex_init(&ocelot->fwd_domain_lock);
mutex_init(&ocelot->tas_lock);
spin_lock_init(&ocelot->ptp_clock_lock); spin_lock_init(&ocelot->ptp_clock_lock);
spin_lock_init(&ocelot->ts_id_lock); spin_lock_init(&ocelot->ts_id_lock);
......
...@@ -89,17 +89,14 @@ void ocelot_port_change_fp(struct ocelot *ocelot, int port, ...@@ -89,17 +89,14 @@ void ocelot_port_change_fp(struct ocelot *ocelot, int port,
{ {
struct ocelot_mm_state *mm = &ocelot->mm[port]; struct ocelot_mm_state *mm = &ocelot->mm[port];
mutex_lock(&ocelot->fwd_domain_lock); lockdep_assert_held(&ocelot->fwd_domain_lock);
if (mm->preemptible_tcs == preemptible_tcs) if (mm->preemptible_tcs == preemptible_tcs)
goto out_unlock; return;
mm->preemptible_tcs = preemptible_tcs; mm->preemptible_tcs = preemptible_tcs;
ocelot_port_update_active_preemptible_tcs(ocelot, port); ocelot_port_update_active_preemptible_tcs(ocelot, port);
out_unlock:
mutex_unlock(&ocelot->fwd_domain_lock);
} }
static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port) static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
......
...@@ -863,12 +863,12 @@ struct ocelot { ...@@ -863,12 +863,12 @@ struct ocelot {
struct mutex stat_view_lock; struct mutex stat_view_lock;
/* Lock for serializing access to the MAC table */ /* Lock for serializing access to the MAC table */
struct mutex mact_lock; struct mutex mact_lock;
/* Lock for serializing forwarding domain changes */ /* Lock for serializing forwarding domain changes, including the
* configuration of the Time-Aware Shaper, MAC Merge layer and
* cut-through forwarding, on which it depends
*/
struct mutex fwd_domain_lock; struct mutex fwd_domain_lock;
/* Lock for serializing Time-Aware Shaper changes */
struct mutex tas_lock;
struct workqueue_struct *owq; struct workqueue_struct *owq;
u8 ptp:1; u8 ptp:1;
......
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