Patchwork net dsa: add per port phy address mapping

login
register
mail settings
Submitter Rodolfo Giometti
Date Oct. 15, 2012, 1:33 p.m.
Message ID <1350308008-17189-1-git-send-email-giometti@linux.it>
Download mbox | patch
Permalink /patch/191565/
State Deferred
Delegated to: David Miller
Headers show

Comments

Rodolfo Giometti - Oct. 15, 2012, 1:33 p.m.
In some circumstances ports' phy addresses must be remapped in a custom
manner (i.e. when phys have multiple MDIO addresses).

Compatibility with old behaviour is kept by using a special flag named
"port_phy_remap" which must be set to 1 in order to enable remapping
defined into "port_phy_addr" array.

Signed-off-by: Rodolfo Giometti <giometti@linux.it>
---
 include/net/dsa.h  |   11 +++++++++++
 net/dsa/dsa.c      |    3 ++-
 net/dsa/dsa_priv.h |    3 ++-
 net/dsa/slave.c    |   25 +++++++++++++++----------
 4 files changed, 30 insertions(+), 12 deletions(-)
Lennert Buytenhek - Oct. 16, 2012, 8:02 a.m.
On Mon, Oct 15, 2012 at 03:33:25PM +0200, Rodolfo Giometti wrote:

> In some circumstances ports' phy addresses must be remapped in a custom
> manner (i.e. when phys have multiple MDIO addresses).

Can you give an example of when this is needed (i.e. on which
switch chips)?
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 7828ebf..ff07a86 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -36,6 +36,17 @@  struct dsa_chip_data {
 	char		*port_names[DSA_MAX_PORTS];
 
 	/*
+	 * The MDIO address of the phy connected to each port.
+	 * Set port_phy_remap = 1 in order to activate the remap otherwise
+	 * is assumed that phy on port0 has address 0x0, phy on port1 has
+	 * address 0x1 and so on...
+	 * Note that for ports marked as "cpu" or "dsa" these fields are
+	 * ignored.
+	 */
+	unsigned long	port_phy_remap:1;
+	int		port_phy_addr[DSA_MAX_PORTS];
+
+	/*
 	 * An array (with nr_chips elements) of which element [a]
 	 * indicates which port on this switch should be used to
 	 * send packets to that are destined for switch a.  Can be
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 88e7c2f..a7f6fa2 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -175,7 +175,8 @@  dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 		if (!(ds->phys_port_mask & (1 << i)))
 			continue;
 
-		slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i]);
+		slave_dev = dsa_slave_create(ds, parent, i, pd->port_names[i],
+				pd->port_phy_remap ? pd->port_phy_addr[i] : i);
 		if (slave_dev == NULL) {
 			printk(KERN_ERR "%s[%d]: can't create dsa "
 			       "slave device for port %d(%s)\n",
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index d4cf5cc..7bf1876 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -42,7 +42,8 @@  extern char dsa_driver_version[];
 void dsa_slave_mii_bus_init(struct dsa_switch *ds);
 struct net_device *dsa_slave_create(struct dsa_switch *ds,
 				    struct device *parent,
-				    int port, char *name);
+				    int port, char *name,
+				    int phy_addr);
 
 /* tag_dsa.c */
 netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index e32083d..4286964 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -19,20 +19,25 @@  static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
 {
 	struct dsa_switch *ds = bus->priv;
 
-	if (ds->phys_port_mask & (1 << addr))
-		return ds->drv->phy_read(ds, addr, reg);
-
-	return 0xffff;
+	/*
+	 * if port_phy_remap is not enabled when can use old sanity check:
+	 *
+	 *	if (ds->phys_port_mask & (1 << port))
+	 *
+	 * but if port_phy_remap is enabled we should find port<-->addr
+	 * mapping by looking into port_phy_addr array... that why I dropped
+	 * any sanity checks here (real kernel programmers should know what
+	 * they do! ;) - Rodolfo Giometti
+	 */
+	return ds->drv->phy_read(ds, addr, reg);
 }
 
 static int dsa_slave_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
 {
 	struct dsa_switch *ds = bus->priv;
 
-	if (ds->phys_port_mask & (1 << addr))
-		return ds->drv->phy_write(ds, addr, reg, val);
-
-	return 0;
+	/* See comment in function dsa_slave_phy_read() above */
+	return ds->drv->phy_write(ds, addr, reg, val);
 }
 
 void dsa_slave_mii_bus_init(struct dsa_switch *ds)
@@ -333,7 +338,7 @@  static const struct net_device_ops trailer_netdev_ops = {
 /* slave device setup *******************************************************/
 struct net_device *
 dsa_slave_create(struct dsa_switch *ds, struct device *parent,
-		 int port, char *name)
+		 int port, char *name, int phy_addr)
 {
 	struct net_device *master = ds->dst->master_netdev;
 	struct net_device *slave_dev;
@@ -377,7 +382,7 @@  dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	p->dev = slave_dev;
 	p->parent = ds;
 	p->port = port;
-	p->phy = ds->slave_mii_bus->phy_map[port];
+	p->phy = ds->slave_mii_bus->phy_map[phy_addr];
 
 	ret = register_netdev(slave_dev);
 	if (ret) {