summaryrefslogtreecommitdiff
path: root/drivers/staging/batman-adv/routing.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/routing.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/routing.c')
-rw-r--r--drivers/staging/batman-adv/routing.c49
1 files changed, 21 insertions, 28 deletions
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
index 77e5d1411c99..1536963dd69f 100644
--- a/drivers/staging/batman-adv/routing.c
+++ b/drivers/staging/batman-adv/routing.c
@@ -41,9 +41,8 @@ void slide_own_bcast_window(struct batman_if *batman_if)
struct element_t *bucket;
struct orig_node *orig_node;
TYPE_OF_WORD *word;
- unsigned long flags;
- 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);
@@ -55,7 +54,7 @@ void slide_own_bcast_window(struct batman_if *batman_if)
bit_packet_count(word);
}
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
}
static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node,
@@ -749,7 +748,6 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
{
struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
struct ethhdr *ethhdr;
- unsigned long flags;
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, sizeof(struct batman_packet))))
@@ -775,12 +773,12 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
ethhdr = (struct ethhdr *)skb_mac_header(skb);
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
+ spin_lock_bh(&bat_priv->orig_hash_lock);
receive_aggr_bat_packet(ethhdr,
skb->data,
skb_headlen(skb),
batman_if);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
kfree_skb(skb);
return NET_RX_SUCCESS;
@@ -794,7 +792,6 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
struct ethhdr *ethhdr;
struct batman_if *batman_if;
int ret;
- unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
icmp_packet = (struct icmp_packet_rr *)skb->data;
@@ -811,7 +808,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
/* answer echo request (ping) */
/* get routing information */
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
+ spin_lock_bh(&bat_priv->orig_hash_lock);
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
compare_orig, choose_orig,
icmp_packet->orig));
@@ -824,7 +821,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
* copy the required data before sending */
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -843,7 +840,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv,
ret = NET_RX_SUCCESS;
} else
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return ret;
}
@@ -856,7 +853,6 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
struct ethhdr *ethhdr;
struct batman_if *batman_if;
int ret;
- unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
icmp_packet = (struct icmp_packet *)skb->data;
@@ -874,7 +870,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
return NET_RX_DROP;
/* get routing information */
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
+ spin_lock_bh(&bat_priv->orig_hash_lock);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
icmp_packet->orig));
@@ -887,7 +883,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
* copy the required data before sending */
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -906,7 +902,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
ret = NET_RX_SUCCESS;
} else
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return ret;
}
@@ -921,7 +917,6 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
struct batman_if *batman_if;
int hdr_size = sizeof(struct icmp_packet);
int ret;
- unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
/**
@@ -969,7 +964,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
ret = NET_RX_DROP;
/* get routing information */
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
+ spin_lock_bh(&bat_priv->orig_hash_lock);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
icmp_packet->dst));
@@ -981,7 +976,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
* copy the required data before sending */
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -998,7 +993,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
ret = NET_RX_SUCCESS;
} else
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return ret;
}
@@ -1131,7 +1126,6 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
struct neigh_node *router;
struct batman_if *batman_if;
uint8_t dstaddr[ETH_ALEN];
- unsigned long flags;
struct unicast_packet *unicast_packet;
struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
int ret;
@@ -1148,7 +1142,7 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
}
/* get routing information */
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
+ spin_lock_bh(&bat_priv->orig_hash_lock);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
unicast_packet->dest));
@@ -1156,7 +1150,7 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
router = find_router(bat_priv, orig_node, recv_if);
if (!router) {
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return NET_RX_DROP;
}
@@ -1166,7 +1160,7 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
batman_if = router->if_incoming;
memcpy(dstaddr, router->addr, ETH_ALEN);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
/* create a copy of the skb, if needed, to modify it. */
if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
@@ -1266,7 +1260,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
struct ethhdr *ethhdr;
int hdr_size = sizeof(struct bcast_packet);
int32_t seq_diff;
- unsigned long flags;
/* drop packet if it has not necessary minimum size */
if (unlikely(!pskb_may_pull(skb, hdr_size)))
@@ -1295,13 +1288,13 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
if (bcast_packet->ttl < 2)
return NET_RX_DROP;
- spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
+ spin_lock_bh(&bat_priv->orig_hash_lock);
orig_node = ((struct orig_node *)
hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
bcast_packet->orig));
if (orig_node == NULL) {
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return NET_RX_DROP;
}
@@ -1309,7 +1302,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
if (get_bit_status(orig_node->bcast_bits,
orig_node->last_bcast_seqno,
ntohl(bcast_packet->seqno))) {
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return NET_RX_DROP;
}
@@ -1318,7 +1311,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
/* check whether the packet is old and the host just restarted. */
if (window_protected(bat_priv, seq_diff,
&orig_node->bcast_seqno_reset)) {
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
return NET_RX_DROP;
}
@@ -1327,7 +1320,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
- spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
+ spin_unlock_bh(&bat_priv->orig_hash_lock);
/* rebroadcast packet */
add_bcast_packet_to_list(bat_priv, skb);