Skip to content

Commit

Permalink
net: dsa: list DSA links in the fabric
Browse files Browse the repository at this point in the history
Implement a new list of DSA links in the switch fabric itself, to
provide an alterative to the ds->rtable static arrays.

At the same time, provide a new dsa_routing_port() helper to abstract
the usage of ds->rtable in drivers. If there's no port to reach a
given device, return the first invalid port, ds->num_ports. This avoids
potential signedness errors or the need to define special values.

Signed-off-by: Vivien Didelot <vivien.didelot@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
  • Loading branch information
vivien authored and rehsack committed Jan 21, 2021
1 parent 8d23606 commit 27f0edf
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
8 changes: 4 additions & 4 deletions drivers/net/dsa/mv88e6xxx/chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,7 @@ static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip)

static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
{
struct dsa_switch *ds = chip->ds;
int target, port;
int err;

Expand All @@ -1151,10 +1152,9 @@ static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)

/* Initialize the routing port to the 32 possible target devices */
for (target = 0; target < 32; target++) {
port = 0x1f;
if (target < DSA_MAX_SWITCHES)
if (chip->ds->rtable[target] != DSA_RTABLE_NONE)
port = chip->ds->rtable[target];
port = dsa_routing_port(ds, target);
if (port == ds->num_ports)
port = 0x1f;

err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
if (err)
Expand Down
29 changes: 28 additions & 1 deletion include/net/dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ struct dsa_switch_tree {
/* List of switch ports */
struct list_head ports;

/* List of DSA links composing the routing table */
struct list_head rtable;

/*
* Data for the individual switch chips.
*/
Expand Down Expand Up @@ -225,6 +228,17 @@ struct dsa_port {
bool setup;
};

/* TODO: ideally DSA ports would have a single dp->link_dp member,
* and no dst->rtable nor this struct dsa_link would be needed,
* but this would require some more complex tree walking,
* so keep it stupid at the moment and list them all.
*/
struct dsa_link {
struct dsa_port *dp;
struct dsa_port *link_dp;
struct list_head list;
};

struct dsa_switch {
bool setup;

Expand Down Expand Up @@ -341,14 +355,27 @@ static inline u32 dsa_user_ports(struct dsa_switch *ds)
return mask;
}

/* Return the local port used to reach an arbitrary switch device */
static inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device)
{
struct dsa_switch_tree *dst = ds->dst;
struct dsa_link *dl;

list_for_each_entry(dl, &dst->rtable, list)
if (dl->dp->ds == ds && dl->link_dp->ds->index == device)
return dl->dp->index;

return ds->num_ports;
}

/* Return the local port used to reach an arbitrary switch port */
static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
int port)
{
if (device == ds->index)
return port;
else
return ds->rtable[device];
return dsa_routing_port(ds, device);
}

/* Return the local port used to reach the dedicated CPU port */
Expand Down
41 changes: 40 additions & 1 deletion net/dsa/dsa2.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index)

dst->index = index;

INIT_LIST_HEAD(&dst->rtable);

INIT_LIST_HEAD(&dst->ports);

INIT_LIST_HEAD(&dst->list);
Expand Down Expand Up @@ -122,13 +124,39 @@ static struct dsa_port *dsa_tree_find_port_by_node(struct dsa_switch_tree *dst,
return NULL;
}

struct dsa_link *dsa_link_touch(struct dsa_port *dp, struct dsa_port *link_dp)
{
struct dsa_switch *ds = dp->ds;
struct dsa_switch_tree *dst;
struct dsa_link *dl;

dst = ds->dst;

list_for_each_entry(dl, &dst->rtable, list)
if (dl->dp == dp && dl->link_dp == link_dp)
return dl;

dl = kzalloc(sizeof(*dl), GFP_KERNEL);
if (!dl)
return NULL;

dl->dp = dp;
dl->link_dp = link_dp;

INIT_LIST_HEAD(&dl->list);
list_add_tail(&dl->list, &dst->rtable);

return dl;
}

static bool dsa_port_setup_routing_table(struct dsa_port *dp)
{
struct dsa_switch *ds = dp->ds;
struct dsa_switch_tree *dst = ds->dst;
struct device_node *dn = dp->dn;
struct of_phandle_iterator it;
struct dsa_port *link_dp;
struct dsa_link *dl;
int err;

of_for_each_phandle(&it, err, dn, "link", NULL, 0) {
Expand All @@ -138,7 +166,11 @@ static bool dsa_port_setup_routing_table(struct dsa_port *dp)
return false;
}

ds->rtable[link_dp->ds->index] = dp->index;
dl = dsa_link_touch(dp, link_dp);
if (!dl) {
of_node_put(it.node);
return false;
}
}

return true;
Expand Down Expand Up @@ -548,6 +580,8 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)

static void dsa_tree_teardown(struct dsa_switch_tree *dst)
{
struct dsa_link *dl, *next;

if (!dst->setup)
return;

Expand All @@ -557,6 +591,11 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst)

dsa_tree_teardown_default_cpu(dst);

list_for_each_entry_safe(dl, next, &dst->rtable, list) {
list_del(&dl->list);
kfree(dl);
}

pr_info("DSA: tree %d torn down\n", dst->index);

dst->setup = false;
Expand Down

0 comments on commit 27f0edf

Please sign in to comment.