mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-22 11:19:33 +07:00
net: dsa: sja1105: move sja1105_compose_gating_subschedule at the top
It turns out that sja1105_compose_gating_subschedule must also be called from sja1105_vl_delete, to recalculate the overall tc-gate configuration. Currently this is not possible without introducing a forward declaration. So move the function at the top of the file, along with its dependencies. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
33fdef24c9
commit
e39109f596
@ -7,6 +7,166 @@
|
||||
|
||||
#define SJA1105_SIZE_VL_STATUS 8
|
||||
|
||||
/* Insert into the global gate list, sorted by gate action time. */
|
||||
static int sja1105_insert_gate_entry(struct sja1105_gating_config *gating_cfg,
|
||||
struct sja1105_rule *rule,
|
||||
u8 gate_state, s64 entry_time,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sja1105_gate_entry *e;
|
||||
int rc;
|
||||
|
||||
e = kzalloc(sizeof(*e), GFP_KERNEL);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
e->rule = rule;
|
||||
e->gate_state = gate_state;
|
||||
e->interval = entry_time;
|
||||
|
||||
if (list_empty(&gating_cfg->entries)) {
|
||||
list_add(&e->list, &gating_cfg->entries);
|
||||
} else {
|
||||
struct sja1105_gate_entry *p;
|
||||
|
||||
list_for_each_entry(p, &gating_cfg->entries, list) {
|
||||
if (p->interval == e->interval) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Gate conflict");
|
||||
rc = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (e->interval < p->interval)
|
||||
break;
|
||||
}
|
||||
list_add(&e->list, p->list.prev);
|
||||
}
|
||||
|
||||
gating_cfg->num_entries++;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(e);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The gate entries contain absolute times in their e->interval field. Convert
|
||||
* that to proper intervals (i.e. "0, 5, 10, 15" to "5, 5, 5, 5").
|
||||
*/
|
||||
static void
|
||||
sja1105_gating_cfg_time_to_interval(struct sja1105_gating_config *gating_cfg,
|
||||
u64 cycle_time)
|
||||
{
|
||||
struct sja1105_gate_entry *last_e;
|
||||
struct sja1105_gate_entry *e;
|
||||
struct list_head *prev;
|
||||
|
||||
list_for_each_entry(e, &gating_cfg->entries, list) {
|
||||
struct sja1105_gate_entry *p;
|
||||
|
||||
prev = e->list.prev;
|
||||
|
||||
if (prev == &gating_cfg->entries)
|
||||
continue;
|
||||
|
||||
p = list_entry(prev, struct sja1105_gate_entry, list);
|
||||
p->interval = e->interval - p->interval;
|
||||
}
|
||||
last_e = list_last_entry(&gating_cfg->entries,
|
||||
struct sja1105_gate_entry, list);
|
||||
if (last_e->list.prev != &gating_cfg->entries)
|
||||
last_e->interval = cycle_time - last_e->interval;
|
||||
}
|
||||
|
||||
static void sja1105_free_gating_config(struct sja1105_gating_config *gating_cfg)
|
||||
{
|
||||
struct sja1105_gate_entry *e, *n;
|
||||
|
||||
list_for_each_entry_safe(e, n, &gating_cfg->entries, list) {
|
||||
list_del(&e->list);
|
||||
kfree(e);
|
||||
}
|
||||
}
|
||||
|
||||
static int sja1105_compose_gating_subschedule(struct sja1105_private *priv,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg;
|
||||
struct sja1105_rule *rule;
|
||||
s64 max_cycle_time = 0;
|
||||
s64 its_base_time = 0;
|
||||
int i, rc = 0;
|
||||
|
||||
list_for_each_entry(rule, &priv->flow_block.rules, list) {
|
||||
if (rule->type != SJA1105_RULE_VL)
|
||||
continue;
|
||||
if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
|
||||
continue;
|
||||
|
||||
if (max_cycle_time < rule->vl.cycle_time) {
|
||||
max_cycle_time = rule->vl.cycle_time;
|
||||
its_base_time = rule->vl.base_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (!max_cycle_time)
|
||||
return 0;
|
||||
|
||||
dev_dbg(priv->ds->dev, "max_cycle_time %lld its_base_time %lld\n",
|
||||
max_cycle_time, its_base_time);
|
||||
|
||||
sja1105_free_gating_config(gating_cfg);
|
||||
|
||||
gating_cfg->base_time = its_base_time;
|
||||
gating_cfg->cycle_time = max_cycle_time;
|
||||
gating_cfg->num_entries = 0;
|
||||
|
||||
list_for_each_entry(rule, &priv->flow_block.rules, list) {
|
||||
s64 time;
|
||||
s64 rbt;
|
||||
|
||||
if (rule->type != SJA1105_RULE_VL)
|
||||
continue;
|
||||
if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
|
||||
continue;
|
||||
|
||||
/* Calculate the difference between this gating schedule's
|
||||
* base time, and the base time of the gating schedule with the
|
||||
* longest cycle time. We call it the relative base time (rbt).
|
||||
*/
|
||||
rbt = future_base_time(rule->vl.base_time, rule->vl.cycle_time,
|
||||
its_base_time);
|
||||
rbt -= its_base_time;
|
||||
|
||||
time = rbt;
|
||||
|
||||
for (i = 0; i < rule->vl.num_entries; i++) {
|
||||
u8 gate_state = rule->vl.entries[i].gate_state;
|
||||
s64 entry_time = time;
|
||||
|
||||
while (entry_time < max_cycle_time) {
|
||||
rc = sja1105_insert_gate_entry(gating_cfg, rule,
|
||||
gate_state,
|
||||
entry_time,
|
||||
extack);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
entry_time += rule->vl.cycle_time;
|
||||
}
|
||||
time += rule->vl.entries[i].interval;
|
||||
}
|
||||
}
|
||||
|
||||
sja1105_gating_cfg_time_to_interval(gating_cfg, max_cycle_time);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
sja1105_free_gating_config(gating_cfg);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The switch flow classification core implements TTEthernet, which 'thinks' in
|
||||
* terms of Virtual Links (VL), a concept borrowed from ARINC 664 part 7.
|
||||
* However it also has one other operating mode (VLLUPFORMAT=0) where it acts
|
||||
@ -397,166 +557,6 @@ int sja1105_vl_delete(struct sja1105_private *priv, int port,
|
||||
return sja1105_static_config_reload(priv, SJA1105_VIRTUAL_LINKS);
|
||||
}
|
||||
|
||||
/* Insert into the global gate list, sorted by gate action time. */
|
||||
static int sja1105_insert_gate_entry(struct sja1105_gating_config *gating_cfg,
|
||||
struct sja1105_rule *rule,
|
||||
u8 gate_state, s64 entry_time,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sja1105_gate_entry *e;
|
||||
int rc;
|
||||
|
||||
e = kzalloc(sizeof(*e), GFP_KERNEL);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
e->rule = rule;
|
||||
e->gate_state = gate_state;
|
||||
e->interval = entry_time;
|
||||
|
||||
if (list_empty(&gating_cfg->entries)) {
|
||||
list_add(&e->list, &gating_cfg->entries);
|
||||
} else {
|
||||
struct sja1105_gate_entry *p;
|
||||
|
||||
list_for_each_entry(p, &gating_cfg->entries, list) {
|
||||
if (p->interval == e->interval) {
|
||||
NL_SET_ERR_MSG_MOD(extack,
|
||||
"Gate conflict");
|
||||
rc = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (e->interval < p->interval)
|
||||
break;
|
||||
}
|
||||
list_add(&e->list, p->list.prev);
|
||||
}
|
||||
|
||||
gating_cfg->num_entries++;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(e);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The gate entries contain absolute times in their e->interval field. Convert
|
||||
* that to proper intervals (i.e. "0, 5, 10, 15" to "5, 5, 5, 5").
|
||||
*/
|
||||
static void
|
||||
sja1105_gating_cfg_time_to_interval(struct sja1105_gating_config *gating_cfg,
|
||||
u64 cycle_time)
|
||||
{
|
||||
struct sja1105_gate_entry *last_e;
|
||||
struct sja1105_gate_entry *e;
|
||||
struct list_head *prev;
|
||||
|
||||
list_for_each_entry(e, &gating_cfg->entries, list) {
|
||||
struct sja1105_gate_entry *p;
|
||||
|
||||
prev = e->list.prev;
|
||||
|
||||
if (prev == &gating_cfg->entries)
|
||||
continue;
|
||||
|
||||
p = list_entry(prev, struct sja1105_gate_entry, list);
|
||||
p->interval = e->interval - p->interval;
|
||||
}
|
||||
last_e = list_last_entry(&gating_cfg->entries,
|
||||
struct sja1105_gate_entry, list);
|
||||
if (last_e->list.prev != &gating_cfg->entries)
|
||||
last_e->interval = cycle_time - last_e->interval;
|
||||
}
|
||||
|
||||
static void sja1105_free_gating_config(struct sja1105_gating_config *gating_cfg)
|
||||
{
|
||||
struct sja1105_gate_entry *e, *n;
|
||||
|
||||
list_for_each_entry_safe(e, n, &gating_cfg->entries, list) {
|
||||
list_del(&e->list);
|
||||
kfree(e);
|
||||
}
|
||||
}
|
||||
|
||||
static int sja1105_compose_gating_subschedule(struct sja1105_private *priv,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg;
|
||||
struct sja1105_rule *rule;
|
||||
s64 max_cycle_time = 0;
|
||||
s64 its_base_time = 0;
|
||||
int i, rc = 0;
|
||||
|
||||
list_for_each_entry(rule, &priv->flow_block.rules, list) {
|
||||
if (rule->type != SJA1105_RULE_VL)
|
||||
continue;
|
||||
if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
|
||||
continue;
|
||||
|
||||
if (max_cycle_time < rule->vl.cycle_time) {
|
||||
max_cycle_time = rule->vl.cycle_time;
|
||||
its_base_time = rule->vl.base_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (!max_cycle_time)
|
||||
return 0;
|
||||
|
||||
dev_dbg(priv->ds->dev, "max_cycle_time %lld its_base_time %lld\n",
|
||||
max_cycle_time, its_base_time);
|
||||
|
||||
sja1105_free_gating_config(gating_cfg);
|
||||
|
||||
gating_cfg->base_time = its_base_time;
|
||||
gating_cfg->cycle_time = max_cycle_time;
|
||||
gating_cfg->num_entries = 0;
|
||||
|
||||
list_for_each_entry(rule, &priv->flow_block.rules, list) {
|
||||
s64 time;
|
||||
s64 rbt;
|
||||
|
||||
if (rule->type != SJA1105_RULE_VL)
|
||||
continue;
|
||||
if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
|
||||
continue;
|
||||
|
||||
/* Calculate the difference between this gating schedule's
|
||||
* base time, and the base time of the gating schedule with the
|
||||
* longest cycle time. We call it the relative base time (rbt).
|
||||
*/
|
||||
rbt = future_base_time(rule->vl.base_time, rule->vl.cycle_time,
|
||||
its_base_time);
|
||||
rbt -= its_base_time;
|
||||
|
||||
time = rbt;
|
||||
|
||||
for (i = 0; i < rule->vl.num_entries; i++) {
|
||||
u8 gate_state = rule->vl.entries[i].gate_state;
|
||||
s64 entry_time = time;
|
||||
|
||||
while (entry_time < max_cycle_time) {
|
||||
rc = sja1105_insert_gate_entry(gating_cfg, rule,
|
||||
gate_state,
|
||||
entry_time,
|
||||
extack);
|
||||
if (rc)
|
||||
goto err;
|
||||
|
||||
entry_time += rule->vl.cycle_time;
|
||||
}
|
||||
time += rule->vl.entries[i].interval;
|
||||
}
|
||||
}
|
||||
|
||||
sja1105_gating_cfg_time_to_interval(gating_cfg, max_cycle_time);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
sja1105_free_gating_config(gating_cfg);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sja1105_vl_gate(struct sja1105_private *priv, int port,
|
||||
struct netlink_ext_ack *extack, unsigned long cookie,
|
||||
struct sja1105_key *key, u32 index, s32 prio,
|
||||
|
Loading…
Reference in New Issue
Block a user