Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
[linux-2.6-microblaze.git] / net / dsa / slave.c
index 8157be7..99673f6 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "dsa_priv.h"
 
-static bool dsa_slave_dev_check(struct net_device *dev);
+static bool dsa_slave_dev_check(const struct net_device *dev);
 
 /* slave mii_bus handling ***************************************************/
 static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
@@ -311,7 +311,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
 
 static int dsa_slave_port_obj_add(struct net_device *dev,
                                  const struct switchdev_obj *obj,
-                                 struct switchdev_trans *trans)
+                                 struct switchdev_trans *trans,
+                                 struct netlink_ext_ack *extack)
 {
        struct dsa_port *dp = dsa_slave_to_port(dev);
        int err;
@@ -323,6 +324,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
 
        switch (obj->id) {
        case SWITCHDEV_OBJ_ID_PORT_MDB:
+               if (obj->orig_dev != dev)
+                       return -EOPNOTSUPP;
                err = dsa_port_mdb_add(dp, SWITCHDEV_OBJ_PORT_MDB(obj), trans);
                break;
        case SWITCHDEV_OBJ_ID_HOST_MDB:
@@ -333,6 +336,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
                                       trans);
                break;
        case SWITCHDEV_OBJ_ID_PORT_VLAN:
+               if (obj->orig_dev != dev)
+                       return -EOPNOTSUPP;
                err = dsa_port_vlan_add(dp, SWITCHDEV_OBJ_PORT_VLAN(obj),
                                        trans);
                break;
@@ -352,6 +357,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
 
        switch (obj->id) {
        case SWITCHDEV_OBJ_ID_PORT_MDB:
+               if (obj->orig_dev != dev)
+                       return -EOPNOTSUPP;
                err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
                break;
        case SWITCHDEV_OBJ_ID_HOST_MDB:
@@ -361,6 +368,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
                err = dsa_port_mdb_del(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj));
                break;
        case SWITCHDEV_OBJ_ID_PORT_VLAN:
+               if (obj->orig_dev != dev)
+                       return -EOPNOTSUPP;
                err = dsa_port_vlan_del(dp, SWITCHDEV_OBJ_PORT_VLAN(obj));
                break;
        default:
@@ -423,6 +432,8 @@ static void dsa_skb_tx_timestamp(struct dsa_slave_priv *p,
        if (!clone)
                return;
 
+       DSA_SKB_CB(skb)->clone = clone;
+
        if (ds->ops->port_txtstamp(ds, p->dp->index, clone, type))
                return;
 
@@ -460,6 +471,7 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
        u64_stats_update_end(&s->syncp);
 
        DSA_SKB_CB(skb)->deferred_xmit = false;
+       DSA_SKB_CB(skb)->clone = NULL;
 
        /* Identify PTP protocol packets, clone them, and pass them to the
         * switch driver
@@ -1160,98 +1172,6 @@ static struct device_type dsa_type = {
        .name   = "dsa",
 };
 
-static void dsa_slave_phylink_validate(struct net_device *dev,
-                                      unsigned long *supported,
-                                      struct phylink_link_state *state)
-{
-       struct dsa_port *dp = dsa_slave_to_port(dev);
-       struct dsa_switch *ds = dp->ds;
-
-       if (!ds->ops->phylink_validate)
-               return;
-
-       ds->ops->phylink_validate(ds, dp->index, supported, state);
-}
-
-static int dsa_slave_phylink_mac_link_state(struct net_device *dev,
-                                           struct phylink_link_state *state)
-{
-       struct dsa_port *dp = dsa_slave_to_port(dev);
-       struct dsa_switch *ds = dp->ds;
-
-       /* Only called for SGMII and 802.3z */
-       if (!ds->ops->phylink_mac_link_state)
-               return -EOPNOTSUPP;
-
-       return ds->ops->phylink_mac_link_state(ds, dp->index, state);
-}
-
-static void dsa_slave_phylink_mac_config(struct net_device *dev,
-                                        unsigned int mode,
-                                        const struct phylink_link_state *state)
-{
-       struct dsa_port *dp = dsa_slave_to_port(dev);
-       struct dsa_switch *ds = dp->ds;
-
-       if (!ds->ops->phylink_mac_config)
-               return;
-
-       ds->ops->phylink_mac_config(ds, dp->index, mode, state);
-}
-
-static void dsa_slave_phylink_mac_an_restart(struct net_device *dev)
-{
-       struct dsa_port *dp = dsa_slave_to_port(dev);
-       struct dsa_switch *ds = dp->ds;
-
-       if (!ds->ops->phylink_mac_an_restart)
-               return;
-
-       ds->ops->phylink_mac_an_restart(ds, dp->index);
-}
-
-static void dsa_slave_phylink_mac_link_down(struct net_device *dev,
-                                           unsigned int mode,
-                                           phy_interface_t interface)
-{
-       struct dsa_port *dp = dsa_slave_to_port(dev);
-       struct dsa_switch *ds = dp->ds;
-
-       if (!ds->ops->phylink_mac_link_down) {
-               if (ds->ops->adjust_link && dev->phydev)
-                       ds->ops->adjust_link(ds, dp->index, dev->phydev);
-               return;
-       }
-
-       ds->ops->phylink_mac_link_down(ds, dp->index, mode, interface);
-}
-
-static void dsa_slave_phylink_mac_link_up(struct net_device *dev,
-                                         unsigned int mode,
-                                         phy_interface_t interface,
-                                         struct phy_device *phydev)
-{
-       struct dsa_port *dp = dsa_slave_to_port(dev);
-       struct dsa_switch *ds = dp->ds;
-
-       if (!ds->ops->phylink_mac_link_up) {
-               if (ds->ops->adjust_link && dev->phydev)
-                       ds->ops->adjust_link(ds, dp->index, dev->phydev);
-               return;
-       }
-
-       ds->ops->phylink_mac_link_up(ds, dp->index, mode, interface, phydev);
-}
-
-static const struct phylink_mac_ops dsa_slave_phylink_mac_ops = {
-       .validate = dsa_slave_phylink_validate,
-       .mac_link_state = dsa_slave_phylink_mac_link_state,
-       .mac_config = dsa_slave_phylink_mac_config,
-       .mac_an_restart = dsa_slave_phylink_mac_an_restart,
-       .mac_link_down = dsa_slave_phylink_mac_link_down,
-       .mac_link_up = dsa_slave_phylink_mac_link_up,
-};
-
 void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up)
 {
        const struct dsa_port *dp = dsa_to_port(ds, port);
@@ -1299,8 +1219,11 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
        if (mode < 0)
                mode = PHY_INTERFACE_MODE_NA;
 
-       dp->pl = phylink_create(slave_dev, of_fwnode_handle(port_dn), mode,
-                               &dsa_slave_phylink_mac_ops);
+       dp->pl_config.dev = &slave_dev->dev;
+       dp->pl_config.type = PHYLINK_NETDEV;
+
+       dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode,
+                               &dsa_port_phylink_mac_ops);
        if (IS_ERR(dp->pl)) {
                netdev_err(slave_dev,
                           "error creating PHYLINK: %ld\n", PTR_ERR(dp->pl));
@@ -1494,7 +1417,7 @@ void dsa_slave_destroy(struct net_device *slave_dev)
        free_netdev(slave_dev);
 }
 
-static bool dsa_slave_dev_check(struct net_device *dev)
+static bool dsa_slave_dev_check(const struct net_device *dev)
 {
        return dev->netdev_ops == &dsa_slave_netdev_ops;
 }
@@ -1565,19 +1488,6 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
        return NOTIFY_DONE;
 }
 
-static int
-dsa_slave_switchdev_port_attr_set_event(struct net_device *netdev,
-               struct switchdev_notifier_port_attr_info *port_attr_info)
-{
-       int err;
-
-       err = dsa_slave_port_attr_set(netdev, port_attr_info->attr,
-                                     port_attr_info->trans);
-
-       port_attr_info->handled = true;
-       return notifier_from_errno(err);
-}
-
 struct dsa_switchdev_event_work {
        struct work_struct work;
        struct switchdev_notifier_fdb_info fdb_info;
@@ -1652,13 +1562,18 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
 {
        struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
        struct dsa_switchdev_event_work *switchdev_work;
+       int err;
+
+       if (event == SWITCHDEV_PORT_ATTR_SET) {
+               err = switchdev_handle_port_attr_set(dev, ptr,
+                                                    dsa_slave_dev_check,
+                                                    dsa_slave_port_attr_set);
+               return notifier_from_errno(err);
+       }
 
        if (!dsa_slave_dev_check(dev))
                return NOTIFY_DONE;
 
-       if (event == SWITCHDEV_PORT_ATTR_SET)
-               return dsa_slave_switchdev_port_attr_set_event(dev, ptr);
-
        switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
        if (!switchdev_work)
                return NOTIFY_BAD;
@@ -1688,41 +1603,28 @@ err_fdb_work_init:
        return NOTIFY_BAD;
 }
 
-static int
-dsa_slave_switchdev_port_obj_event(unsigned long event,
-                       struct net_device *netdev,
-                       struct switchdev_notifier_port_obj_info *port_obj_info)
-{
-       int err = -EOPNOTSUPP;
-
-       switch (event) {
-       case SWITCHDEV_PORT_OBJ_ADD:
-               err = dsa_slave_port_obj_add(netdev, port_obj_info->obj,
-                                            port_obj_info->trans);
-               break;
-       case SWITCHDEV_PORT_OBJ_DEL:
-               err = dsa_slave_port_obj_del(netdev, port_obj_info->obj);
-               break;
-       }
-
-       port_obj_info->handled = true;
-       return notifier_from_errno(err);
-}
-
 static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
                                              unsigned long event, void *ptr)
 {
        struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
-
-       if (!dsa_slave_dev_check(dev))
-               return NOTIFY_DONE;
+       int err;
 
        switch (event) {
-       case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
+       case SWITCHDEV_PORT_OBJ_ADD:
+               err = switchdev_handle_port_obj_add(dev, ptr,
+                                                   dsa_slave_dev_check,
+                                                   dsa_slave_port_obj_add);
+               return notifier_from_errno(err);
        case SWITCHDEV_PORT_OBJ_DEL:
-               return dsa_slave_switchdev_port_obj_event(event, dev, ptr);
+               err = switchdev_handle_port_obj_del(dev, ptr,
+                                                   dsa_slave_dev_check,
+                                                   dsa_slave_port_obj_del);
+               return notifier_from_errno(err);
        case SWITCHDEV_PORT_ATTR_SET:
-               return dsa_slave_switchdev_port_attr_set_event(dev, ptr);
+               err = switchdev_handle_port_attr_set(dev, ptr,
+                                                    dsa_slave_dev_check,
+                                                    dsa_slave_port_attr_set);
+               return notifier_from_errno(err);
        }
 
        return NOTIFY_DONE;