summaryrefslogtreecommitdiff
path: root/drivers/staging/batman-adv/originator.c
diff options
context:
space:
mode:
authorSven Eckelmann <sven.eckelmann@gmx.de>2010-11-22 00:56:01 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2010-11-29 11:09:13 -0800
commit7a18deb7b03e4112af5add8498889f9b2b36d59f (patch)
tree5981a5f191de7268371120a2b700bfcf8aa33809 /drivers/staging/batman-adv/originator.c
parentbd204952cf161404eae0aa6478fb1b4c586ac678 (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.c37
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;
}