forked from mirrors/linux
		
	net: dsa: rework switch parsing
When parsing a switch, we have to identify to which tree it belongs and parse its ports. Provide two functions to separate the OF and platform data specific paths. Also use the of_property_read_variable_u32_array function to parse the OF member array instead of calling of_property_read_u32_index twice. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									0eefe2c173
								
							
						
					
					
						commit
						975e6e3221
					
				
					 1 changed files with 58 additions and 59 deletions
				
			
		
							
								
								
									
										117
									
								
								net/dsa/dsa2.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								net/dsa/dsa2.c
									
									
									
									
									
								
							| 
						 | 
					@ -617,7 +617,8 @@ static int dsa_port_parse_of(struct dsa_port *dp, struct device_node *dn)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dsa_parse_ports_of(struct device_node *dn, struct dsa_switch *ds)
 | 
					static int dsa_switch_parse_ports_of(struct dsa_switch *ds,
 | 
				
			||||||
 | 
									     struct device_node *dn)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct device_node *ports, *port;
 | 
						struct device_node *ports, *port;
 | 
				
			||||||
	struct dsa_port *dp;
 | 
						struct dsa_port *dp;
 | 
				
			||||||
| 
						 | 
					@ -648,6 +649,39 @@ static int dsa_parse_ports_of(struct device_node *dn, struct dsa_switch *ds)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dsa_switch_parse_member_of(struct dsa_switch *ds,
 | 
				
			||||||
 | 
									      struct device_node *dn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						u32 m[2] = { 0, 0 };
 | 
				
			||||||
 | 
						int sz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Don't error out if this optional property isn't found */
 | 
				
			||||||
 | 
						sz = of_property_read_variable_u32_array(dn, "dsa,member", m, 2, 2);
 | 
				
			||||||
 | 
						if (sz < 0 && sz != -EINVAL)
 | 
				
			||||||
 | 
							return sz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ds->index = m[1];
 | 
				
			||||||
 | 
						if (ds->index >= DSA_MAX_SWITCHES)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ds->dst = dsa_tree_touch(m[0]);
 | 
				
			||||||
 | 
						if (!ds->dst)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int dsa_switch_parse_of(struct dsa_switch *ds, struct device_node *dn)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = dsa_switch_parse_member_of(ds, dn);
 | 
				
			||||||
 | 
						if (err)
 | 
				
			||||||
 | 
							return err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dsa_switch_parse_ports_of(ds, dn);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dsa_port_parse(struct dsa_port *dp, const char *name,
 | 
					static int dsa_port_parse(struct dsa_port *dp, const char *name,
 | 
				
			||||||
			  struct device *dev)
 | 
								  struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -673,7 +707,8 @@ static int dsa_port_parse(struct dsa_port *dp, const char *name,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dsa_parse_ports(struct dsa_chip_data *cd, struct dsa_switch *ds)
 | 
					static int dsa_switch_parse_ports(struct dsa_switch *ds,
 | 
				
			||||||
 | 
									  struct dsa_chip_data *cd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	bool valid_name_found = false;
 | 
						bool valid_name_found = false;
 | 
				
			||||||
	struct dsa_port *dp;
 | 
						struct dsa_port *dp;
 | 
				
			||||||
| 
						 | 
					@ -703,40 +738,19 @@ static int dsa_parse_ports(struct dsa_chip_data *cd, struct dsa_switch *ds)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int dsa_parse_member_dn(struct device_node *np, u32 *tree, u32 *index)
 | 
					static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err;
 | 
						ds->cd = cd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*tree = *index = 0;
 | 
						/* We don't support interconnected switches nor multiple trees via
 | 
				
			||||||
 | 
						 * platform data, so this is the unique switch of the tree.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						ds->index = 0;
 | 
				
			||||||
 | 
						ds->dst = dsa_tree_touch(0);
 | 
				
			||||||
 | 
						if (!ds->dst)
 | 
				
			||||||
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = of_property_read_u32_index(np, "dsa,member", 0, tree);
 | 
						return dsa_switch_parse_ports(ds, cd);
 | 
				
			||||||
	if (err) {
 | 
					 | 
				
			||||||
		/* Does not exist, but it is optional */
 | 
					 | 
				
			||||||
		if (err == -EINVAL)
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = of_property_read_u32_index(np, "dsa,member", 1, index);
 | 
					 | 
				
			||||||
	if (err)
 | 
					 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (*index >= DSA_MAX_SWITCHES)
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int dsa_parse_member(struct dsa_chip_data *pd, u32 *tree, u32 *index)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!pd)
 | 
					 | 
				
			||||||
		return -ENODEV;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* We do not support complex trees with dsa_chip_data */
 | 
					 | 
				
			||||||
	*tree = 0;
 | 
					 | 
				
			||||||
	*index = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int _dsa_register_switch(struct dsa_switch *ds)
 | 
					static int _dsa_register_switch(struct dsa_switch *ds)
 | 
				
			||||||
| 
						 | 
					@ -744,36 +758,21 @@ static int _dsa_register_switch(struct dsa_switch *ds)
 | 
				
			||||||
	struct dsa_chip_data *pdata = ds->dev->platform_data;
 | 
						struct dsa_chip_data *pdata = ds->dev->platform_data;
 | 
				
			||||||
	struct device_node *np = ds->dev->of_node;
 | 
						struct device_node *np = ds->dev->of_node;
 | 
				
			||||||
	struct dsa_switch_tree *dst;
 | 
						struct dsa_switch_tree *dst;
 | 
				
			||||||
	u32 tree, index;
 | 
						unsigned int index;
 | 
				
			||||||
	int i, err;
 | 
						int i, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (np) {
 | 
						if (np)
 | 
				
			||||||
		err = dsa_parse_member_dn(np, &tree, &index);
 | 
							err = dsa_switch_parse_of(ds, np);
 | 
				
			||||||
		if (err)
 | 
						else if (pdata)
 | 
				
			||||||
			return err;
 | 
							err = dsa_switch_parse(ds, pdata);
 | 
				
			||||||
	} else {
 | 
						else
 | 
				
			||||||
		err = dsa_parse_member(pdata, &tree, &index);
 | 
							err = -ENODEV;
 | 
				
			||||||
		if (err)
 | 
					 | 
				
			||||||
			return err;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dst = dsa_tree_touch(tree);
 | 
						if (err)
 | 
				
			||||||
	if (!dst)
 | 
							return err;
 | 
				
			||||||
		return -ENOMEM;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ds->dst = dst;
 | 
						index = ds->index;
 | 
				
			||||||
	ds->index = index;
 | 
						dst = ds->dst;
 | 
				
			||||||
	ds->cd = pdata;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (np) {
 | 
					 | 
				
			||||||
		err = dsa_parse_ports_of(np, ds);
 | 
					 | 
				
			||||||
		if (err)
 | 
					 | 
				
			||||||
			return err;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		err = dsa_parse_ports(pdata, ds);
 | 
					 | 
				
			||||||
		if (err)
 | 
					 | 
				
			||||||
			return err;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Initialize the routing table */
 | 
						/* Initialize the routing table */
 | 
				
			||||||
	for (i = 0; i < DSA_MAX_SWITCHES; ++i)
 | 
						for (i = 0; i < DSA_MAX_SWITCHES; ++i)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue