mac802154: cleanup in rx path
[cascardo/linux.git] / net / hsr / hsr_main.c
index 5f9cd7f..779d28b 100644 (file)
 #include "hsr_device.h"
 #include "hsr_netlink.h"
 #include "hsr_framereg.h"
-
-
-/* List of all registered virtual HSR devices */
-static LIST_HEAD(hsr_list);
-
-void register_hsr_master(struct hsr_priv *hsr)
-{
-       list_add_tail_rcu(&hsr->hsr_list, &hsr_list);
-}
-
-void unregister_hsr_master(struct hsr_priv *hsr)
-{
-       struct hsr_priv *hsr_it;
-
-       list_for_each_entry(hsr_it, &hsr_list, hsr_list)
-               if (hsr_it == hsr) {
-                       list_del_rcu(&hsr_it->hsr_list);
-                       return;
-               }
-}
-
-bool is_hsr_slave(struct net_device *dev)
-{
-       struct hsr_priv *hsr_it;
-
-       list_for_each_entry_rcu(hsr_it, &hsr_list, hsr_list) {
-               if (dev == hsr_it->slave[0])
-                       return true;
-               if (dev == hsr_it->slave[1])
-                       return true;
-       }
-
-       return false;
-}
-
-/* If dev is a HSR slave device, return the virtual master device. Return NULL
- * otherwise.
- */
-struct hsr_priv *get_hsr_master(struct net_device *dev)
-{
-       struct hsr_priv *hsr;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(hsr, &hsr_list, hsr_list)
-               if ((dev == hsr->slave[0]) ||
-                   (dev == hsr->slave[1])) {
-                       rcu_read_unlock();
-                       return hsr;
-               }
-
-       rcu_read_unlock();
-       return NULL;
-}
-
-/* If dev is a HSR slave device, return the other slave device. Return NULL
- * otherwise.
- */
-struct net_device *get_other_slave(struct hsr_priv *hsr,
-                                  struct net_device *dev)
-{
-       if (dev == hsr->slave[0])
-               return hsr->slave[1];
-       if (dev == hsr->slave[1])
-               return hsr->slave[0];
-
-       return NULL;
-}
+#include "hsr_slave.h"
 
 
 static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
                             void *ptr)
 {
-       struct net_device *slave, *other_slave;
+       struct net_device *dev;
+       struct hsr_port *port, *master;
        struct hsr_priv *hsr;
-       int old_operstate;
        int mtu_max;
        int res;
-       struct net_device *dev;
 
        dev = netdev_notifier_info_to_dev(ptr);
-
-       hsr = get_hsr_master(dev);
-       if (hsr) {
-               /* dev is a slave device */
-               slave = dev;
-               other_slave = get_other_slave(hsr, slave);
-       } else {
+       port = hsr_port_get_rtnl(dev);
+       if (port == NULL) {
                if (!is_hsr_master(dev))
-                       return NOTIFY_DONE;
+                       return NOTIFY_DONE;     /* Not an HSR device */
                hsr = netdev_priv(dev);
-               slave = hsr->slave[0];
-               other_slave = hsr->slave[1];
+               port = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
+       } else {
+               hsr = port->hsr;
        }
 
        switch (event) {
        case NETDEV_UP:         /* Administrative state DOWN */
        case NETDEV_DOWN:       /* Administrative state UP */
        case NETDEV_CHANGE:     /* Link (carrier) state changes */
-               old_operstate = hsr->dev->operstate;
-               hsr_set_carrier(hsr->dev, slave, other_slave);
-               /* netif_stacked_transfer_operstate() cannot be used here since
-                * it doesn't set IF_OPER_LOWERLAYERDOWN (?)
-                */
-               hsr_set_operstate(hsr->dev, slave, other_slave);
-               hsr_check_announce(hsr->dev, old_operstate);
+               hsr_check_carrier_and_operstate(hsr);
                break;
        case NETDEV_CHANGEADDR:
-
-               /* This should not happen since there's no ndo_set_mac_address()
-                * for HSR devices - i.e. not supported.
-                */
-               if (dev == hsr->dev)
+               if (port->type == HSR_PT_MASTER) {
+                       /* This should not happen since there's no
+                        * ndo_set_mac_address() for HSR devices - i.e. not
+                        * supported.
+                        */
                        break;
+               }
+
+               master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
 
-               if (dev == hsr->slave[0])
-                       ether_addr_copy(hsr->dev->dev_addr,
-                                       hsr->slave[0]->dev_addr);
+               if (port->type == HSR_PT_SLAVE_A) {
+                       ether_addr_copy(master->dev->dev_addr, dev->dev_addr);
+                       call_netdevice_notifiers(NETDEV_CHANGEADDR, master->dev);
+               }
 
                /* Make sure we recognize frames from ourselves in hsr_rcv() */
+               port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
                res = hsr_create_self_node(&hsr->self_node_db,
-                                          hsr->dev->dev_addr,
-                                          hsr->slave[1] ?
-                                               hsr->slave[1]->dev_addr :
-                                               hsr->dev->dev_addr);
+                                          master->dev->dev_addr,
+                                          port ?
+                                               port->dev->dev_addr :
+                                               master->dev->dev_addr);
                if (res)
-                       netdev_warn(hsr->dev,
+                       netdev_warn(master->dev,
                                    "Could not update HSR node address.\n");
-
-               if (dev == hsr->slave[0])
-                       call_netdevice_notifiers(NETDEV_CHANGEADDR, hsr->dev);
                break;
        case NETDEV_CHANGEMTU:
-               if (dev == hsr->dev)
+               if (port->type == HSR_PT_MASTER)
                        break; /* Handled in ndo_change_mtu() */
-               mtu_max = hsr_get_max_mtu(hsr);
-               if (hsr->dev->mtu > mtu_max)
-                       dev_set_mtu(hsr->dev, mtu_max);
+               mtu_max = hsr_get_max_mtu(port->hsr);
+               master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER);
+               master->dev->mtu = mtu_max;
                break;
        case NETDEV_UNREGISTER:
-               if (dev == hsr->slave[0])
-                       hsr->slave[0] = NULL;
-               if (dev == hsr->slave[1])
-                       hsr->slave[1] = NULL;
-
-               /* There should really be a way to set a new slave device... */
-
+               hsr_del_port(port);
                break;
        case NETDEV_PRE_TYPE_CHANGE:
                /* HSR works only on Ethernet devices. Refuse slave to change
@@ -175,6 +94,16 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
 }
 
 
+struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt)
+{
+       struct hsr_port *port;
+
+       hsr_for_each_port(hsr, port)
+               if (port->type == pt)
+                       return port;
+       return NULL;
+}
+
 static struct notifier_block hsr_nb = {
        .notifier_call = hsr_netdev_notify,     /* Slave event notifications */
 };