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 b68a7e5173be9279b44fbe5ce4f574b847c832b3..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;
@@ -199,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();
@@ -315,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);
@@ -323,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 "
@@ -334,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 "
@@ -374,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);
@@ -386,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);
@@ -432,8 +441,7 @@ 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);
 
@@ -442,7 +450,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
        spin_unlock(&if_list_lock);
 
        /* extra reference for return */
-       hardif_hold(batman_if);
+       kref_get(&batman_if->refcount);
        return batman_if;
 
 free_if:
@@ -463,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();
 }
 
@@ -507,18 +519,18 @@ 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);
                update_mac_addresses(batman_if);
@@ -530,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;
 }