Browse Source

net: dsa: allow drivers to do link adjustment

Whenever libphy determines that the link status of a given PHY/port has
changed, allow to call into the switch driver link adjustment callback
so proper actions can be taken care of by the switch driver upon link
notification.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Florian Fainelli 11 years ago
parent
commit
ec9436baed
2 changed files with 11 additions and 0 deletions
  1. 7 0
      include/net/dsa.h
  2. 4 0
      net/dsa/slave.c

+ 7 - 0
include/net/dsa.h

@@ -16,6 +16,7 @@
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of.h>
+#include <linux/phy.h>
 
 
 #define DSA_MAX_SWITCHES	4
 #define DSA_MAX_SWITCHES	4
 #define DSA_MAX_PORTS		12
 #define DSA_MAX_PORTS		12
@@ -181,6 +182,12 @@ struct dsa_switch_driver {
 	 */
 	 */
 	void	(*poll_link)(struct dsa_switch *ds);
 	void	(*poll_link)(struct dsa_switch *ds);
 
 
+	/*
+	 * Link state adjustment (called from libphy)
+	 */
+	void	(*adjust_link)(struct dsa_switch *ds, int port,
+				struct phy_device *phydev);
+
 	/*
 	/*
 	 * ethtool hardware statistics.
 	 * ethtool hardware statistics.
 	 */
 	 */

+ 4 - 0
net/dsa/slave.c

@@ -333,6 +333,7 @@ static const struct dsa_device_ops notag_netdev_ops = {
 static void dsa_slave_adjust_link(struct net_device *dev)
 static void dsa_slave_adjust_link(struct net_device *dev)
 {
 {
 	struct dsa_slave_priv *p = netdev_priv(dev);
 	struct dsa_slave_priv *p = netdev_priv(dev);
+	struct dsa_switch *ds = p->parent;
 	unsigned int status_changed = 0;
 	unsigned int status_changed = 0;
 
 
 	if (p->old_link != p->phy->link) {
 	if (p->old_link != p->phy->link) {
@@ -350,6 +351,9 @@ static void dsa_slave_adjust_link(struct net_device *dev)
 		p->old_pause = p->phy->pause;
 		p->old_pause = p->phy->pause;
 	}
 	}
 
 
+	if (ds->drv->adjust_link && status_changed)
+		ds->drv->adjust_link(ds, p->port, p->phy);
+
 	if (status_changed)
 	if (status_changed)
 		phy_print_status(p->phy);
 		phy_print_status(p->phy);
 }
 }