Staging: batman-adv: Unify sysfs file names with their bat_priv atomics
[firefly-linux-kernel-4.4.55.git] / drivers / staging / batman-adv / hard-interface.c
index 80cfa866958504692a45b2c6aaf29e936dc97d72..ff0ac98250014f5ef4848e15f72ca76787056972 100644 (file)
 /* protect update critical side of if_list - but not the content */
 static DEFINE_SPINLOCK(if_list_lock);
 
+static void hardif_free_rcu(struct rcu_head *rcu)
+{
+       struct batman_if *batman_if;
+
+       batman_if = container_of(rcu, struct batman_if, rcu);
+       dev_put(batman_if->net_dev);
+       kref_put(&batman_if->refcount, hardif_free_ref);
+}
+
 struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
 {
        struct batman_if *batman_if;
@@ -50,7 +59,7 @@ struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
 
 out:
        if (batman_if)
-               hardif_hold(batman_if);
+               kref_get(&batman_if->refcount);
 
        rcu_read_unlock();
        return batman_if;
@@ -100,7 +109,7 @@ static struct batman_if *get_active_batman_if(struct net_device *soft_iface)
 
 out:
        if (batman_if)
-               hardif_hold(batman_if);
+               kref_get(&batman_if->refcount);
 
        rcu_read_unlock();
        return batman_if;
@@ -125,13 +134,13 @@ static void set_primary_if(struct bat_priv *bat_priv,
        struct batman_if *old_if;
 
        if (batman_if)
-               hardif_hold(batman_if);
+               kref_get(&batman_if->refcount);
 
        old_if = bat_priv->primary_if;
        bat_priv->primary_if = batman_if;
 
        if (old_if)
-               hardif_put(old_if);
+               kref_put(&old_if->refcount, hardif_free_ref);
 
        if (!bat_priv->primary_if)
                return;
@@ -165,7 +174,7 @@ static void update_mac_addresses(struct batman_if *batman_if)
               batman_if->net_dev->dev_addr, ETH_ALEN);
 }
 
-static void check_known_mac_addr(uint8_t *addr)
+static void check_known_mac_addr(struct net_device *net_dev)
 {
        struct batman_if *batman_if;
 
@@ -175,11 +184,16 @@ static void check_known_mac_addr(uint8_t *addr)
                    (batman_if->if_status != IF_TO_BE_ACTIVATED))
                        continue;
 
-               if (!compare_orig(batman_if->net_dev->dev_addr, addr))
+               if (batman_if->net_dev == net_dev)
+                       continue;
+
+               if (!compare_orig(batman_if->net_dev->dev_addr,
+                                 net_dev->dev_addr))
                        continue;
 
                pr_warning("The newly added mac address (%pM) already exists "
-                          "on: %s\n", addr, batman_if->net_dev->name);
+                          "on: %s\n", net_dev->dev_addr,
+                          batman_if->net_dev->name);
                pr_warning("It is strongly recommended to keep mac addresses "
                           "unique to avoid problems!\n");
        }
@@ -194,7 +208,7 @@ int hardif_min_mtu(struct net_device *soft_iface)
         * (have MTU > 1500 + BAT_HEADER_LEN) */
        int min_mtu = ETH_DATA_LEN;
 
-       if (atomic_read(&bat_priv->frag_enabled))
+       if (atomic_read(&bat_priv->fragmentation))
                goto out;
 
        rcu_read_lock();
@@ -310,7 +324,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
        batman_if->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN);
        batman_if->batman_adv_ptype.func = batman_skb_recv;
        batman_if->batman_adv_ptype.dev = batman_if->net_dev;
-       hardif_hold(batman_if);
+       kref_get(&batman_if->refcount);
        dev_add_pack(&batman_if->batman_adv_ptype);
 
        atomic_set(&batman_if->seqno, 1);
@@ -318,7 +332,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
        bat_info(batman_if->soft_iface, "Adding interface: %s\n",
                 batman_if->net_dev->name);
 
-       if (atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu <
+       if (atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu <
                ETH_DATA_LEN + BAT_HEADER_LEN)
                bat_info(batman_if->soft_iface,
                        "The MTU of interface %s is too small (%i) to handle "
@@ -329,7 +343,7 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
                        batman_if->net_dev->name, batman_if->net_dev->mtu,
                        ETH_DATA_LEN + BAT_HEADER_LEN);
 
-       if (!atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu <
+       if (!atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu <
                ETH_DATA_LEN + BAT_HEADER_LEN)
                bat_info(batman_if->soft_iface,
                        "The MTU of interface %s is too small (%i) to handle "
@@ -369,7 +383,7 @@ void hardif_disable_interface(struct batman_if *batman_if)
        bat_info(batman_if->soft_iface, "Removing interface: %s\n",
                 batman_if->net_dev->name);
        dev_remove_pack(&batman_if->batman_adv_ptype);
-       hardif_put(batman_if);
+       kref_put(&batman_if->refcount, hardif_free_ref);
 
        bat_priv->num_ifaces--;
        orig_hash_del_if(batman_if, bat_priv->num_ifaces);
@@ -381,7 +395,7 @@ void hardif_disable_interface(struct batman_if *batman_if)
                set_primary_if(bat_priv, new_if);
 
                if (new_if)
-                       hardif_put(new_if);
+                       kref_put(&new_if->refcount, hardif_free_ref);
        }
 
        kfree(batman_if->packet_buff);
@@ -427,17 +441,16 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
        batman_if->soft_iface = NULL;
        batman_if->if_status = IF_NOT_IN_USE;
        INIT_LIST_HEAD(&batman_if->list);
-       atomic_set(&batman_if->refcnt, 0);
-       hardif_hold(batman_if);
+       kref_init(&batman_if->refcount);
 
-       check_known_mac_addr(batman_if->net_dev->dev_addr);
+       check_known_mac_addr(batman_if->net_dev);
 
        spin_lock(&if_list_lock);
        list_add_tail_rcu(&batman_if->list, &if_list);
        spin_unlock(&if_list_lock);
 
        /* extra reference for return */
-       hardif_hold(batman_if);
+       kref_get(&batman_if->refcount);
        return batman_if;
 
 free_if:
@@ -458,24 +471,28 @@ static void hardif_remove_interface(struct batman_if *batman_if)
                return;
 
        batman_if->if_status = IF_TO_BE_REMOVED;
-
-       /* caller must take if_list_lock */
-       list_del_rcu(&batman_if->list);
-       synchronize_rcu();
        sysfs_del_hardif(&batman_if->hardif_obj);
-       hardif_put(batman_if);
+       call_rcu(&batman_if->rcu, hardif_free_rcu);
 }
 
 void hardif_remove_interfaces(void)
 {
        struct batman_if *batman_if, *batman_if_tmp;
+       struct list_head if_queue;
+
+       INIT_LIST_HEAD(&if_queue);
 
-       rtnl_lock();
        spin_lock(&if_list_lock);
        list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) {
-               hardif_remove_interface(batman_if);
+               list_del_rcu(&batman_if->list);
+               list_add_tail(&batman_if->list, &if_queue);
        }
        spin_unlock(&if_list_lock);
+
+       rtnl_lock();
+       list_for_each_entry_safe(batman_if, batman_if_tmp, &if_queue, list) {
+               hardif_remove_interface(batman_if);
+       }
        rtnl_unlock();
 }
 
@@ -502,20 +519,20 @@ static int hard_if_event(struct notifier_block *this,
                break;
        case NETDEV_UNREGISTER:
                spin_lock(&if_list_lock);
-               hardif_remove_interface(batman_if);
+               list_del_rcu(&batman_if->list);
                spin_unlock(&if_list_lock);
+
+               hardif_remove_interface(batman_if);
                break;
        case NETDEV_CHANGEMTU:
                if (batman_if->soft_iface)
                        update_min_mtu(batman_if->soft_iface);
                break;
        case NETDEV_CHANGEADDR:
-               if (batman_if->if_status == IF_NOT_IN_USE) {
-                       hardif_put(batman_if);
-                       goto out;
-               }
+               if (batman_if->if_status == IF_NOT_IN_USE)
+                       goto hardif_put;
 
-               check_known_mac_addr(batman_if->net_dev->dev_addr);
+               check_known_mac_addr(batman_if->net_dev);
                update_mac_addresses(batman_if);
 
                bat_priv = netdev_priv(batman_if->soft_iface);
@@ -525,8 +542,9 @@ static int hard_if_event(struct notifier_block *this,
        default:
                break;
        };
-       hardif_put(batman_if);
 
+hardif_put:
+       kref_put(&batman_if->refcount, hardif_free_ref);
 out:
        return NOTIFY_DONE;
 }