diff options
author | Sven Eckelmann <sven.eckelmann@gmx.de> | 2010-11-22 00:56:01 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-29 11:09:13 -0800 |
commit | 7a18deb7b03e4112af5add8498889f9b2b36d59f (patch) | |
tree | 5981a5f191de7268371120a2b700bfcf8aa33809 /drivers/staging/batman-adv/originator.c | |
parent | bd204952cf161404eae0aa6478fb1b4c586ac678 (diff) |
Staging: batman-adv: Limit spin_locks to spin_lock_bh
spin_lock_irqsave disables the IRQs and stores them inside the flags
provided by the caller. This is needed to protect a bottom half handler
or a user context critical section from being interrupted by an
interrupt handler which also tries to acquire the spinlock and locks
forever.
The linux device drivers will receive the packets inside an interrupt
handler and the network infrastructure will process them inside bottom
half. Thus batman-adv will only run in user context and bottom half
handlers. We can conclude that batman-adv doesn't share its own
spinlocks with real interrupt handlers.
This makes it possible to exchange the quite complex spin_lock_irqsave
with spin_lock_bh which only stops bottom halves from running on the
current cpu, but allows interrupt handlers to take over to keep the
interrupt latency low.
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/batman-adv/originator.c')
-rw-r--r-- | drivers/staging/batman-adv/originator.c | 37 |
1 files changed, 15 insertions, 22 deletions
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index a4b7d377d941..8bef4681bf82 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c @@ -40,22 +40,21 @@ static void start_purge_timer(struct bat_priv *bat_priv) int originator_init(struct bat_priv *bat_priv) { - unsigned long flags; if (bat_priv->orig_hash) return 1; - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + spin_lock_bh(&bat_priv->orig_hash_lock); bat_priv->orig_hash = hash_new(128); if (!bat_priv->orig_hash) goto err; - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); start_purge_timer(bat_priv); return 1; err: - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); return 0; } @@ -108,17 +107,15 @@ static void free_orig_node(void *data, void *arg) void originator_free(struct bat_priv *bat_priv) { - unsigned long flags; - if (!bat_priv->orig_hash) return; cancel_delayed_work_sync(&bat_priv->orig_work); - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + spin_lock_bh(&bat_priv->orig_hash_lock); hash_delete(bat_priv->orig_hash, free_orig_node, bat_priv); bat_priv->orig_hash = NULL; - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); } /* this function finds or creates an originator entry for the given @@ -273,9 +270,8 @@ static void _purge_orig(struct bat_priv *bat_priv) HASHIT(hashit); struct element_t *bucket; struct orig_node *orig_node; - unsigned long flags; - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + spin_lock_bh(&bat_priv->orig_hash_lock); /* for all origins... */ while (hash_iterate(bat_priv->orig_hash, &hashit)) { @@ -292,7 +288,7 @@ static void _purge_orig(struct bat_priv *bat_priv) frag_list_free(&orig_node->frag_list); } - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); softif_neigh_purge(bat_priv); } @@ -324,7 +320,6 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) int batman_count = 0; int last_seen_secs; int last_seen_msecs; - unsigned long flags; if ((!bat_priv->primary_if) || (bat_priv->primary_if->if_status != IF_ACTIVE)) { @@ -346,7 +341,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops"); - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + spin_lock_bh(&bat_priv->orig_hash_lock); while (hash_iterate(bat_priv->orig_hash, &hashit)) { bucket = hlist_entry(hashit.walk, struct element_t, hlist); @@ -377,7 +372,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) batman_count++; } - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); if ((batman_count == 0)) seq_printf(seq, "No batman nodes in range ...\n"); @@ -419,13 +414,12 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) { struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct orig_node *orig_node; - unsigned long flags; HASHIT(hashit); struct element_t *bucket; /* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + spin_lock_bh(&bat_priv->orig_hash_lock); while (hash_iterate(bat_priv->orig_hash, &hashit)) { bucket = hlist_entry(hashit.walk, struct element_t, hlist); @@ -435,11 +429,11 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num) goto err; } - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); return 0; err: - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); return -ENOMEM; } @@ -500,14 +494,13 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface); struct batman_if *batman_if_tmp; struct orig_node *orig_node; - unsigned long flags; HASHIT(hashit); struct element_t *bucket; int ret; /* resize all orig nodes because orig_node->bcast_own(_sum) depend on * if_num */ - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); + spin_lock_bh(&bat_priv->orig_hash_lock); while (hash_iterate(bat_priv->orig_hash, &hashit)) { bucket = hlist_entry(hashit.walk, struct element_t, hlist); @@ -538,10 +531,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num) rcu_read_unlock(); batman_if->if_num = -1; - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); return 0; err: - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); + spin_unlock_bh(&bat_priv->orig_hash_lock); return -ENOMEM; } |