]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/hsr/hsr_device.c
net/hsr: Operstate handling cleanup.
[karo-tx-linux.git] / net / hsr / hsr_device.c
index 4e5d92a8f0796d77fa13ef0930ca01c200a77183..8936b3c2bb843eb86b488c1e7f4a4fc1e8c63f68 100644 (file)
@@ -46,31 +46,36 @@ static void __hsr_set_operstate(struct net_device *dev, int transition)
        }
 }
 
-void hsr_set_operstate(struct net_device *hsr_dev, struct net_device *slave1,
-                      struct net_device *slave2)
+static void hsr_set_operstate(struct net_device *hsr_dev, bool has_carrier)
 {
        if (!is_admin_up(hsr_dev)) {
                __hsr_set_operstate(hsr_dev, IF_OPER_DOWN);
                return;
        }
 
-       if (is_slave_up(slave1) || is_slave_up(slave2))
+       if (has_carrier)
                __hsr_set_operstate(hsr_dev, IF_OPER_UP);
        else
                __hsr_set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN);
 }
 
-void hsr_set_carrier(struct net_device *hsr_dev, struct net_device *slave1,
-                    struct net_device *slave2)
+static bool hsr_check_carrier(struct hsr_priv *hsr)
 {
-       if (is_slave_up(slave1) || is_slave_up(slave2))
-               netif_carrier_on(hsr_dev);
+       bool has_carrier;
+
+       has_carrier = (is_slave_up(hsr->slave[0]) || is_slave_up(hsr->slave[1]));
+
+       if (has_carrier)
+               netif_carrier_on(hsr->dev);
        else
-               netif_carrier_off(hsr_dev);
+               netif_carrier_off(hsr->dev);
+
+       return has_carrier;
 }
 
 
-void hsr_check_announce(struct net_device *hsr_dev, int old_operstate)
+static void hsr_check_announce(struct net_device *hsr_dev,
+                              unsigned char old_operstate)
 {
        struct hsr_priv *hsr;
 
@@ -89,6 +94,20 @@ void hsr_check_announce(struct net_device *hsr_dev, int old_operstate)
                del_timer(&hsr->announce_timer);
 }
 
+void hsr_check_carrier_and_operstate(struct hsr_priv *hsr)
+{
+       unsigned char old_operstate;
+       bool has_carrier;
+
+       /* netif_stacked_transfer_operstate() cannot be used here since
+        * it doesn't set IF_OPER_LOWERLAYERDOWN (?)
+        */
+       old_operstate = hsr->dev->operstate;
+       has_carrier = hsr_check_carrier(hsr);
+       hsr_set_operstate(hsr->dev, has_carrier);
+       hsr_check_announce(hsr->dev, old_operstate);
+}
+
 
 int hsr_get_max_mtu(struct hsr_priv *hsr)
 {
@@ -429,7 +448,8 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
 
        hsr = netdev_priv(hsr_dev);
 
-       del_timer(&hsr->announce_timer);
+       del_timer_sync(&hsr->prune_timer);
+       del_timer_sync(&hsr->announce_timer);
        unregister_hsr_master(hsr);    /* calls list_del_rcu on hsr */
        restore_slaves(hsr_dev);
        call_rcu(&hsr->rcu_head, reclaim_hsr_dev);   /* reclaim hsr */
@@ -523,6 +543,10 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
        hsr->announce_timer.function = hsr_announce;
        hsr->announce_timer.data = (unsigned long) hsr;
 
+       init_timer(&hsr->prune_timer);
+       hsr->prune_timer.function = hsr_prune_nodes;
+       hsr->prune_timer.data = (unsigned long) hsr;
+
        ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr);
        hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec;
 
@@ -596,6 +620,9 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
        if (res)
                goto fail;
 
+       hsr->prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD);
+       add_timer(&hsr->prune_timer);
+
        register_hsr_master(hsr);
 
        return 0;