X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fstaging%2Fbatman-adv%2Fhard-interface.c;h=ff0ac98250014f5ef4848e15f72ca76787056972;hb=641ee3f8f4375bde4e216aacd26d286a34efed61;hp=80cfa866958504692a45b2c6aaf29e936dc97d72;hpb=4b4a2700f462102569b407102c60d3b9cf4432a0;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 80cfa8669585..ff0ac9825001 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c @@ -36,6 +36,15 @@ /* 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; }