net: dsa: allow switches driver to implement get/set EEE
authorFlorian Fainelli <f.fainelli@gmail.com>
Thu, 25 Sep 2014 00:05:21 +0000 (17:05 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 28 Sep 2014 21:14:09 +0000 (17:14 -0400)
Allow switches driver to query and enable/disable EEE on a per-port
basis by implementing the ethtool_{get,set}_eee settings and delegating
these operations to the switch driver.

set_eee() will need to coordinate with the PHY driver to make sure that
EEE is enabled, the link-partner supports it and the auto-negotiation
result is satisfactory.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/dsa.h
net/dsa/slave.c

index 4f664fe0e42ca631e6975542a3f8dc258f08b397..58ad8c6492dba56360b9cad1c81d4061526721c9 100644 (file)
@@ -232,6 +232,15 @@ struct dsa_switch_driver {
                               struct phy_device *phy);
        void    (*port_disable)(struct dsa_switch *ds, int port,
                                struct phy_device *phy);
+
+       /*
+        * EEE setttings
+        */
+       int     (*set_eee)(struct dsa_switch *ds, int port,
+                          struct phy_device *phydev,
+                          struct ethtool_eee *e);
+       int     (*get_eee)(struct dsa_switch *ds, int port,
+                          struct ethtool_eee *e);
 };
 
 void register_switch_driver(struct dsa_switch_driver *type);
index 182d30ae6818cfc392ab781aaa00011f1732d761..36953c84ff2d44e488ba79fd3125cf7df2abdda6 100644 (file)
@@ -342,6 +342,44 @@ static int dsa_slave_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
        return ret;
 }
 
+static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
+{
+       struct dsa_slave_priv *p = netdev_priv(dev);
+       struct dsa_switch *ds = p->parent;
+       int ret;
+
+       if (!ds->drv->set_eee)
+               return -EOPNOTSUPP;
+
+       ret = ds->drv->set_eee(ds, p->port, p->phy, e);
+       if (ret)
+               return ret;
+
+       if (p->phy)
+               ret = phy_ethtool_set_eee(p->phy, e);
+
+       return ret;
+}
+
+static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
+{
+       struct dsa_slave_priv *p = netdev_priv(dev);
+       struct dsa_switch *ds = p->parent;
+       int ret;
+
+       if (!ds->drv->get_eee)
+               return -EOPNOTSUPP;
+
+       ret = ds->drv->get_eee(ds, p->port, e);
+       if (ret)
+               return ret;
+
+       if (p->phy)
+               ret = phy_ethtool_get_eee(p->phy, e);
+
+       return ret;
+}
+
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
        .get_settings           = dsa_slave_get_settings,
        .set_settings           = dsa_slave_set_settings,
@@ -353,6 +391,8 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
        .get_sset_count         = dsa_slave_get_sset_count,
        .set_wol                = dsa_slave_set_wol,
        .get_wol                = dsa_slave_get_wol,
+       .set_eee                = dsa_slave_set_eee,
+       .get_eee                = dsa_slave_get_eee,
 };
 
 static const struct net_device_ops dsa_slave_netdev_ops = {