Merge tag 'vfio-v4.8-rc1' of git://github.com/awilliam/linux-vfio
[deliverable/linux.git] / net / dsa / slave.c
index 15a4922618952b4c0de337e4253642e772d2fffe..fc91967452253b54c4c692f77d67ba9b08e59e74 100644 (file)
@@ -49,7 +49,8 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds)
        ds->slave_mii_bus->name = "dsa slave smi";
        ds->slave_mii_bus->read = dsa_slave_phy_read;
        ds->slave_mii_bus->write = dsa_slave_phy_write;
-       snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d", ds->index);
+       snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d.%d",
+                ds->dst->tree, ds->index);
        ds->slave_mii_bus->parent = ds->dev;
        ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
 }
@@ -332,6 +333,44 @@ static int dsa_slave_vlan_filtering(struct net_device *dev,
        return 0;
 }
 
+static int dsa_fastest_ageing_time(struct dsa_switch *ds,
+                                  unsigned int ageing_time)
+{
+       int i;
+
+       for (i = 0; i < DSA_MAX_PORTS; ++i) {
+               struct dsa_port *dp = &ds->ports[i];
+
+               if (dp && dp->ageing_time && dp->ageing_time < ageing_time)
+                       ageing_time = dp->ageing_time;
+       }
+
+       return ageing_time;
+}
+
+static int dsa_slave_ageing_time(struct net_device *dev,
+                                const struct switchdev_attr *attr,
+                                struct switchdev_trans *trans)
+{
+       struct dsa_slave_priv *p = netdev_priv(dev);
+       struct dsa_switch *ds = p->parent;
+       unsigned long ageing_jiffies = clock_t_to_jiffies(attr->u.ageing_time);
+       unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies);
+
+       /* bridge skips -EOPNOTSUPP, so skip the prepare phase */
+       if (switchdev_trans_ph_prepare(trans))
+               return 0;
+
+       /* Keep the fastest ageing time in case of multiple bridges */
+       ds->ports[p->port].ageing_time = ageing_time;
+       ageing_time = dsa_fastest_ageing_time(ds, ageing_time);
+
+       if (ds->drv->set_ageing_time)
+               return ds->drv->set_ageing_time(ds, ageing_time);
+
+       return 0;
+}
+
 static int dsa_slave_port_attr_set(struct net_device *dev,
                                   const struct switchdev_attr *attr,
                                   struct switchdev_trans *trans)
@@ -345,6 +384,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
        case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
                ret = dsa_slave_vlan_filtering(dev, attr, trans);
                break;
+       case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
+               ret = dsa_slave_ageing_time(dev, attr, trans);
+               break;
        default:
                ret = -EOPNOTSUPP;
                break;
@@ -864,6 +906,13 @@ static void dsa_slave_poll_controller(struct net_device *dev)
 }
 #endif
 
+void dsa_cpu_port_ethtool_init(struct ethtool_ops *ops)
+{
+       ops->get_sset_count = dsa_cpu_port_get_sset_count;
+       ops->get_ethtool_stats = dsa_cpu_port_get_ethtool_stats;
+       ops->get_strings = dsa_cpu_port_get_strings;
+}
+
 static const struct ethtool_ops dsa_slave_ethtool_ops = {
        .get_settings           = dsa_slave_get_settings,
        .set_settings           = dsa_slave_set_settings,
@@ -884,8 +933,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = {
        .get_eee                = dsa_slave_get_eee,
 };
 
-static struct ethtool_ops dsa_cpu_port_ethtool_ops;
-
 static const struct net_device_ops dsa_slave_netdev_ops = {
        .ndo_open               = dsa_slave_open,
        .ndo_stop               = dsa_slave_close,
@@ -1118,19 +1165,6 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 
        slave_dev->features = master->vlan_features;
        slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
-       if (master->ethtool_ops != &dsa_cpu_port_ethtool_ops) {
-               memcpy(&dst->master_ethtool_ops, master->ethtool_ops,
-                      sizeof(struct ethtool_ops));
-               memcpy(&dsa_cpu_port_ethtool_ops, &dst->master_ethtool_ops,
-                      sizeof(struct ethtool_ops));
-               dsa_cpu_port_ethtool_ops.get_sset_count =
-                                       dsa_cpu_port_get_sset_count;
-               dsa_cpu_port_ethtool_ops.get_ethtool_stats =
-                                       dsa_cpu_port_get_ethtool_stats;
-               dsa_cpu_port_ethtool_ops.get_strings =
-                                       dsa_cpu_port_get_strings;
-               master->ethtool_ops = &dsa_cpu_port_ethtool_ops;
-       }
        eth_hw_addr_inherit(slave_dev, master);
        slave_dev->priv_flags |= IFF_NO_QUEUE;
        slave_dev->netdev_ops = &dsa_slave_netdev_ops;
This page took 0.025806 seconds and 5 git commands to generate.