[PATCH] net dsa: add per port phy address mapping

Subsystems: networking [dsa], networking [general], the rest

STALE5110d

7 messages, 2 authors, 2012-10-16 · open the first message on its own page

[PATCH] net dsa: add per port phy address mapping

From: Rodolfo Giometti <hidden>
Date: 2012-10-15 13:54:44

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 <redacted>
---
 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(-)
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) {
-- 
1.7.9.5

[PATCH] net dsa: add new option "master_netdev_autoup"

From: Rodolfo Giometti <hidden>
Date: 2012-10-15 13:54:42

By using this option the user can decide if the master device should
be turned on when one of the slave devices is opened.

This functionality is needed if RootFS over NFS is used throught the
DSA.

Signed-off-by: Rodolfo Giometti <redacted>
---
 include/net/dsa.h |    8 ++++++++
 net/dsa/slave.c   |    7 ++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index ff07a86..bd3c8b8 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -63,6 +63,14 @@ struct dsa_platform_data {
 	struct device	*netdev;
 
 	/*
+	 * Enable the auto-up of the master device when a slave is
+	 * open.
+	 * This functionality is needed if RootFS over NFS is used
+	 * throught the DSA.
+	 */
+	unsigned long	master_netdev_autoup:1;
+
+	/*
 	 * Info structs describing each of the switch chips
 	 * connected via this network interface.
 	 */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 4286964..6e9e4546 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -66,9 +66,14 @@ static int dsa_slave_open(struct net_device *dev)
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
 	struct net_device *master = p->parent->dst->master_netdev;
+	struct dsa_platform_data *pd = p->parent->dst->pd;
 	int err;
 
-	if (!(master->flags & IFF_UP))
+	if (pd->master_netdev_autoup)
+		err = dev_open(master);
+	else
+		err = !(master->flags & IFF_UP);
+	if (err)
 		return -ENETDOWN;
 
 	if (!ether_addr_equal(dev->dev_addr, master->dev_addr)) {
-- 
1.7.9.5

[PATCH] net dsa: add phy's interrupts management

From: Rodolfo Giometti <hidden>
Date: 2012-10-15 13:54:45

Signed-off-by: Rodolfo Giometti <redacted>
---
 net/dsa/slave.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 6e9e4546..817bbbd 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -340,6 +340,11 @@ static const struct net_device_ops trailer_netdev_ops = {
 };
 #endif
 
+static void dsa_slave_handle_link_change(struct net_device *dev)
+{
+	/* nop */
+}
+
 /* slave device setup *******************************************************/
 struct net_device *
 dsa_slave_create(struct dsa_switch *ds, struct device *parent,
@@ -400,8 +405,8 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	netif_carrier_off(slave_dev);
 
 	if (p->phy != NULL) {
-		phy_attach(slave_dev, dev_name(&p->phy->dev),
-			   0, PHY_INTERFACE_MODE_GMII);
+		phy_connect_direct(p->dev, p->phy, dsa_slave_handle_link_change,
+				0, PHY_INTERFACE_MODE_GMII);
 
 		p->phy->autoneg = AUTONEG_ENABLE;
 		p->phy->speed = 0;
-- 
1.7.9.5

[PATCH] net dsa: add TX timestamping support

From: Rodolfo Giometti <hidden>
Date: 2012-10-15 13:54:46

Signed-off-by: Rodolfo Giometti <redacted>
---
 net/dsa/tag_dsa.c     |    8 ++++++++
 net/dsa/tag_edsa.c    |    8 ++++++++
 net/dsa/tag_trailer.c |    8 ++++++++
 3 files changed, 24 insertions(+)
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index cacce1e..20c2959 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -24,6 +24,14 @@ netdev_tx_t dsa_xmit(struct sk_buff *skb, struct net_device *dev)
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
+	/* We should call skb_tx_timestamp() at bottom of this function,
+	 * just before dev_queue_xmit(), but the skb is going to be
+	 * modified by DSA stack so it is going to be NOT recognized
+	 * by the ptp_filter called into function skb_clone_tx_timestamp()
+	 * [see file linux/net/core/timestamping.c].
+	 */
+	skb_tx_timestamp(skb);
+
 	/*
 	 * Convert the outermost 802.1q tag to a DSA tag for tagged
 	 * packets, or insert a DSA tag between the addresses and
diff --git a/net/dsa/tag_edsa.c b/net/dsa/tag_edsa.c
index e70c43c..9138bda 100644
--- a/net/dsa/tag_edsa.c
+++ b/net/dsa/tag_edsa.c
@@ -25,6 +25,14 @@ netdev_tx_t edsa_xmit(struct sk_buff *skb, struct net_device *dev)
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
+	/* We should call skb_tx_timestamp() at bottom of this function,
+	 * just before dev_queue_xmit(), but the skb is going to be
+	 * modified by DSA stack so it is going to be NOT recognized
+	 * by the ptp_filter called into function skb_clone_tx_timestamp()
+	 * [see file linux/net/core/timestamping.c].
+	 */
+	skb_tx_timestamp(skb);
+
 	/*
 	 * Convert the outermost 802.1q tag to a DSA tag and prepend
 	 * a DSA ethertype field is the packet is tagged, or insert
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 94bc260..b92cad2 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -24,6 +24,14 @@ netdev_tx_t trailer_xmit(struct sk_buff *skb, struct net_device *dev)
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
+	/* We should call skb_tx_timestamp() at bottom of this function,
+	 * just before dev_queue_xmit(), but the skb is going to be
+	 * modified by DSA stack so it is going to be NOT recognized
+	 * by the ptp_filter called into function skb_clone_tx_timestamp()
+	 * [see file linux/net/core/timestamping.c].
+	 */
+	skb_tx_timestamp(skb);
+
 	/*
 	 * We have to make sure that the trailer ends up as the very
 	 * last 4 bytes of the packet.  This means that we have to pad
-- 
1.7.9.5

Re: [PATCH] net dsa: add new option "master_netdev_autoup"

From: Lennert Buytenhek <hidden>
Date: 2012-10-16 08:11:35

On Mon, Oct 15, 2012 at 03:33:26PM +0200, Rodolfo Giometti wrote:
By using this option the user can decide if the master device should
be turned on when one of the slave devices is opened.

This functionality is needed if RootFS over NFS is used throught the
DSA.
NAK

Use an initramfs if you want this.

Re: [PATCH] net dsa: add phy's interrupts management

From: Lennert Buytenhek <hidden>
Date: 2012-10-16 08:11:36

On Mon, Oct 15, 2012 at 03:33:28PM +0200, Rodolfo Giometti wrote:
quoted hunk
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 6e9e4546..817bbbd 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -340,6 +340,11 @@ static const struct net_device_ops trailer_netdev_ops = {
 };
 #endif
 
+static void dsa_slave_handle_link_change(struct net_device *dev)
+{
+	/* nop */
+}
+
 /* slave device setup *******************************************************/
 struct net_device *
 dsa_slave_create(struct dsa_switch *ds, struct device *parent,
@@ -400,8 +405,8 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 	netif_carrier_off(slave_dev);
 
 	if (p->phy != NULL) {
-		phy_attach(slave_dev, dev_name(&p->phy->dev),
-			   0, PHY_INTERFACE_MODE_GMII);
+		phy_connect_direct(p->dev, p->phy, dsa_slave_handle_link_change,
+				0, PHY_INTERFACE_MODE_GMII);
 
 		p->phy->autoneg = AUTONEG_ENABLE;
What does this do?

Re: [PATCH] net dsa: add per port phy address mapping

From: Lennert Buytenhek <hidden>
Date: 2012-10-16 08:11:36

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)?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help