net: mscc: ocelot: Handle SWITCHDEV_PORT_ATTR_SET
authorFlorian Fainelli <f.fainelli@gmail.com>
Wed, 27 Feb 2019 19:44:29 +0000 (11:44 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 Feb 2019 20:39:56 +0000 (12:39 -0800)
Following patches will change the way we communicate setting a port's
attribute and use notifiers to perform those tasks.

Ocelot does not currently have an atomic notifier registered for
switchdev events, so we need to register one in order to deal with
atomic context SWITCHDEV_PORT_ATTR_SET events.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot.h
drivers/net/ethernet/mscc/ocelot_board.c

index 195306d05bcde98e56f2cf8d2cd2a8ff324d5790..83a678b11757de09b37d1f2211676e551bd111e6 100644 (file)
@@ -1582,6 +1582,28 @@ struct notifier_block ocelot_netdevice_nb __read_mostly = {
 };
 EXPORT_SYMBOL(ocelot_netdevice_nb);
 
+static int ocelot_switchdev_event(struct notifier_block *unused,
+                                 unsigned long event, void *ptr)
+{
+       struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+       int err;
+
+       switch (event) {
+       case SWITCHDEV_PORT_ATTR_SET:
+               err = switchdev_handle_port_attr_set(dev, ptr,
+                                                    ocelot_netdevice_dev_check,
+                                                    ocelot_port_attr_set);
+               return notifier_from_errno(err);
+       }
+
+       return NOTIFY_DONE;
+}
+
+struct notifier_block ocelot_switchdev_nb __read_mostly = {
+       .notifier_call = ocelot_switchdev_event,
+};
+EXPORT_SYMBOL(ocelot_switchdev_nb);
+
 static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
                                           unsigned long event, void *ptr)
 {
@@ -1600,6 +1622,11 @@ static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
                                                    ocelot_netdevice_dev_check,
                                                    ocelot_port_obj_del);
                return notifier_from_errno(err);
+       case SWITCHDEV_PORT_ATTR_SET:
+               err = switchdev_handle_port_attr_set(dev, ptr,
+                                                    ocelot_netdevice_dev_check,
+                                                    ocelot_port_attr_set);
+               return notifier_from_errno(err);
        }
 
        return NOTIFY_DONE;
index 086775f7b52f7201877023a3c516e062c86c6143..ba3b3380b4d08782441f12c9e012ee93c96f6a81 100644 (file)
@@ -499,6 +499,7 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
                      struct phy_device *phy);
 
 extern struct notifier_block ocelot_netdevice_nb;
+extern struct notifier_block ocelot_switchdev_nb;
 extern struct notifier_block ocelot_switchdev_blocking_nb;
 
 #endif
index ca3ea2fbfcd08d47282e7c1b02fee70bc761ca32..2c1121d86edf895f1109ae8f68bc8e0a52ff4b3b 100644 (file)
@@ -329,6 +329,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
        }
 
        register_netdevice_notifier(&ocelot_netdevice_nb);
+       register_switchdev_notifier(&ocelot_switchdev_nb);
        register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
 
        dev_info(&pdev->dev, "Ocelot switch probed\n");
@@ -345,6 +346,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
 
        ocelot_deinit(ocelot);
        unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
+       unregister_switchdev_notifier(&ocelot_switchdev_nb);
        unregister_netdevice_notifier(&ocelot_netdevice_nb);
 
        return 0;