mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: dsa: list DSA links in the fabric
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>
This commit is contained in:
		
							parent
							
								
									5c26c1d6df
								
							
						
					
					
						commit
						c5f51765a1
					
				
					 3 changed files with 72 additions and 6 deletions
				
			
		| 
						 | 
					@ -1143,6 +1143,7 @@ static int mv88e6xxx_pri_setup(struct mv88e6xxx_chip *chip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
 | 
					static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dsa_switch *ds = chip->ds;
 | 
				
			||||||
	int target, port;
 | 
						int target, port;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1151,10 +1152,9 @@ static int mv88e6xxx_devmap_setup(struct mv88e6xxx_chip *chip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Initialize the routing port to the 32 possible target devices */
 | 
						/* Initialize the routing port to the 32 possible target devices */
 | 
				
			||||||
	for (target = 0; target < 32; target++) {
 | 
						for (target = 0; target < 32; target++) {
 | 
				
			||||||
 | 
							port = dsa_routing_port(ds, target);
 | 
				
			||||||
 | 
							if (port == ds->num_ports)
 | 
				
			||||||
			port = 0x1f;
 | 
								port = 0x1f;
 | 
				
			||||||
		if (target < DSA_MAX_SWITCHES)
 | 
					 | 
				
			||||||
			if (chip->ds->rtable[target] != DSA_RTABLE_NONE)
 | 
					 | 
				
			||||||
				port = chip->ds->rtable[target];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
 | 
							err = mv88e6xxx_g2_device_mapping_write(chip, target, port);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,6 +123,9 @@ struct dsa_switch_tree {
 | 
				
			||||||
	/* List of switch ports */
 | 
						/* List of switch ports */
 | 
				
			||||||
	struct list_head ports;
 | 
						struct list_head ports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* List of DSA links composing the routing table */
 | 
				
			||||||
 | 
						struct list_head rtable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Data for the individual switch chips.
 | 
						 * Data for the individual switch chips.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -214,6 +217,17 @@ struct dsa_port {
 | 
				
			||||||
	bool setup;
 | 
						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 {
 | 
					struct dsa_switch {
 | 
				
			||||||
	bool setup;
 | 
						bool setup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,6 +338,19 @@ static inline u32 dsa_user_ports(struct dsa_switch *ds)
 | 
				
			||||||
	return mask;
 | 
						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 */
 | 
					/* Return the local port used to reach an arbitrary switch port */
 | 
				
			||||||
static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
 | 
					static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
 | 
				
			||||||
					    int port)
 | 
										    int port)
 | 
				
			||||||
| 
						 | 
					@ -331,7 +358,7 @@ static inline unsigned int dsa_towards_port(struct dsa_switch *ds, int device,
 | 
				
			||||||
	if (device == ds->index)
 | 
						if (device == ds->index)
 | 
				
			||||||
		return port;
 | 
							return port;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return ds->rtable[device];
 | 
							return dsa_routing_port(ds, device);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return the local port used to reach the dedicated CPU port */
 | 
					/* Return the local port used to reach the dedicated CPU port */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,8 @@ static struct dsa_switch_tree *dsa_tree_alloc(int index)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dst->index = index;
 | 
						dst->index = index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						INIT_LIST_HEAD(&dst->rtable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&dst->ports);
 | 
						INIT_LIST_HEAD(&dst->ports);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INIT_LIST_HEAD(&dst->list);
 | 
						INIT_LIST_HEAD(&dst->list);
 | 
				
			||||||
| 
						 | 
					@ -122,6 +124,31 @@ static struct dsa_port *dsa_tree_find_port_by_node(struct dsa_switch_tree *dst,
 | 
				
			||||||
	return NULL;
 | 
						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)
 | 
					static bool dsa_port_setup_routing_table(struct dsa_port *dp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct dsa_switch *ds = dp->ds;
 | 
						struct dsa_switch *ds = dp->ds;
 | 
				
			||||||
| 
						 | 
					@ -129,6 +156,7 @@ static bool dsa_port_setup_routing_table(struct dsa_port *dp)
 | 
				
			||||||
	struct device_node *dn = dp->dn;
 | 
						struct device_node *dn = dp->dn;
 | 
				
			||||||
	struct of_phandle_iterator it;
 | 
						struct of_phandle_iterator it;
 | 
				
			||||||
	struct dsa_port *link_dp;
 | 
						struct dsa_port *link_dp;
 | 
				
			||||||
 | 
						struct dsa_link *dl;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	of_for_each_phandle(&it, err, dn, "link", NULL, 0) {
 | 
						of_for_each_phandle(&it, err, dn, "link", NULL, 0) {
 | 
				
			||||||
| 
						 | 
					@ -138,7 +166,11 @@ static bool dsa_port_setup_routing_table(struct dsa_port *dp)
 | 
				
			||||||
			return false;
 | 
								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;
 | 
						return true;
 | 
				
			||||||
| 
						 | 
					@ -544,6 +576,8 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void dsa_tree_teardown(struct dsa_switch_tree *dst)
 | 
					static void dsa_tree_teardown(struct dsa_switch_tree *dst)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct dsa_link *dl, *next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dst->setup)
 | 
						if (!dst->setup)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -553,6 +587,11 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dsa_tree_teardown_default_cpu(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);
 | 
						pr_info("DSA: tree %d torn down\n", dst->index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dst->setup = false;
 | 
						dst->setup = false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue