Commit 7a18deb7 authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Greg Kroah-Hartman

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: default avatarSven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent bd204952
......@@ -104,7 +104,6 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
{
struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
struct forw_packet *forw_packet_aggr;
unsigned long flags;
unsigned char *skb_buff;
/* own packet should always be scheduled */
......@@ -156,9 +155,9 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
forw_packet_aggr->direct_link_flags |= 1;
/* add new packet to packet list */
spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
hlist_add_head(&forw_packet_aggr->list, &bat_priv->forw_bat_list);
spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
/* start timer for this packet */
INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
......@@ -201,10 +200,9 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
struct batman_packet *batman_packet =
(struct batman_packet *)packet_buff;
bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0;
unsigned long flags;
/* find position for the packet in the forward queue */
spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
/* own packets are not to be aggregated */
if ((atomic_read(&bat_priv->aggregated_ogms)) && (!own_packet)) {
hlist_for_each_entry(forw_packet_pos, tmp_node,
......@@ -225,7 +223,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
* suitable aggregation packet found */
if (forw_packet_aggr == NULL) {
/* the following section can run without the lock */
spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
/**
* if we could not aggregate this packet with one of the others
......@@ -243,7 +241,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
aggregate(forw_packet_aggr,
packet_buff, packet_len,
direct_link);
spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
}
}
......
......@@ -54,12 +54,11 @@ static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
va_list args;
static char debug_log_buf[256];
char *p;
unsigned long flags;
if (!debug_log)
return 0;
spin_lock_irqsave(&debug_log->lock, flags);
spin_lock_bh(&debug_log->lock);
va_start(args, fmt);
printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf),
fmt, args);
......@@ -68,7 +67,7 @@ static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
for (p = debug_log_buf; *p != 0; p++)
emit_log_char(debug_log, *p);
spin_unlock_irqrestore(&debug_log->lock, flags);
spin_unlock_bh(&debug_log->lock);
wake_up(&debug_log->queue_wait);
......@@ -110,7 +109,6 @@ static ssize_t log_read(struct file *file, char __user *buf,
struct debug_log *debug_log = bat_priv->debug_log;
int error, i = 0;
char c;
unsigned long flags;
if ((file->f_flags & O_NONBLOCK) &&
!(debug_log->log_end - debug_log->log_start))
......@@ -131,7 +129,7 @@ static ssize_t log_read(struct file *file, char __user *buf,
if (error)
return error;
spin_lock_irqsave(&debug_log->lock, flags);
spin_lock_bh(&debug_log->lock);
while ((!error) && (i < count) &&
(debug_log->log_start != debug_log->log_end)) {
......@@ -139,18 +137,18 @@ static ssize_t log_read(struct file *file, char __user *buf,
debug_log->log_start++;
spin_unlock_irqrestore(&debug_log->lock, flags);
spin_unlock_bh(&debug_log->lock);
error = __put_user(c, buf);
spin_lock_irqsave(&debug_log->lock, flags);
spin_lock_bh(&debug_log->lock);
buf++;
i++;
}
spin_unlock_irqrestore(&debug_log->lock, flags);
spin_unlock_bh(&debug_log->lock);
if (!error)
return i;
......
......@@ -85,9 +85,8 @@ static int bat_socket_release(struct inode *inode, struct file *file)
struct socket_client *socket_client = file->private_data;
struct socket_packet *socket_packet;
struct list_head *list_pos, *list_pos_tmp;
unsigned long flags;
spin_lock_irqsave(&socket_client->lock, flags);
spin_lock_bh(&socket_client->lock);
/* for all packets in the queue ... */
list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) {
......@@ -99,7 +98,7 @@ static int bat_socket_release(struct inode *inode, struct file *file)
}
socket_client_hash[socket_client->index] = NULL;
spin_unlock_irqrestore(&socket_client->lock, flags);
spin_unlock_bh(&socket_client->lock);
kfree(socket_client);
dec_module_count();
......@@ -114,7 +113,6 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf,
struct socket_packet *socket_packet;
size_t packet_len;
int error;
unsigned long flags;
if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0))
return -EAGAIN;
......@@ -131,14 +129,14 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf,
if (error)
return error;
spin_lock_irqsave(&socket_client->lock, flags);
spin_lock_bh(&socket_client->lock);
socket_packet = list_first_entry(&socket_client->queue_list,
struct socket_packet, list);
list_del(&socket_packet->list);
socket_client->queue_len--;
spin_unlock_irqrestore(&socket_client->lock, flags);
spin_unlock_bh(&socket_client->lock);
error = __copy_to_user(buf, &socket_packet->icmp_packet,
socket_packet->icmp_len);
......@@ -164,7 +162,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
struct batman_if *batman_if;
size_t packet_len = sizeof(struct icmp_packet);
uint8_t dstaddr[ETH_ALEN];
unsigned long flags;
if (len < sizeof(struct icmp_packet)) {
bat_dbg(DBG_BATMAN, bat_priv,
......@@ -224,7 +221,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
goto dst_unreach;
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));
......@@ -238,7 +235,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
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);
if (!batman_if)
goto dst_unreach;
......@@ -258,7 +255,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
goto out;
unlock:
spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
spin_unlock_bh(&bat_priv->orig_hash_lock);
dst_unreach:
icmp_packet->msg_type = DESTINATION_UNREACHABLE;
bat_socket_add_packet(socket_client, icmp_packet, packet_len);
......@@ -313,7 +310,6 @@ static void bat_socket_add_packet(struct socket_client *socket_client,
size_t icmp_len)
{
struct socket_packet *socket_packet;
unsigned long flags;
socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC);
......@@ -324,12 +320,12 @@ static void bat_socket_add_packet(struct socket_client *socket_client,
memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len);
socket_packet->icmp_len = icmp_len;
spin_lock_irqsave(&socket_client->lock, flags);
spin_lock_bh(&socket_client->lock);
/* while waiting for the lock the socket_client could have been
* deleted */
if (!socket_client_hash[icmp_packet->uid]) {
spin_unlock_irqrestore(&socket_client->lock, flags);
spin_unlock_bh(&socket_client->lock);
kfree(socket_packet);
return;
}
......@@ -346,7 +342,7 @@ static void bat_socket_add_packet(struct socket_client *socket_client,
socket_client->queue_len--;
}
spin_unlock_irqrestore(&socket_client->lock, flags);
spin_unlock_bh(&socket_client->lock);
wake_up(&socket_client->queue_wait);
}
......
......@@ -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;
}
......@@ -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);
......
......@@ -367,13 +367,12 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv,
struct forw_packet *forw_packet,
unsigned long send_time)
{
unsigned long flags;
INIT_HLIST_NODE(&forw_packet->list);
/* add new packet to packet list */
spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
hlist_add_head(&forw_packet->list, &bat_priv->forw_bcast_list);
spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
/* start timer for this packet */
INIT_DELAYED_WORK(&forw_packet->delayed_work,
......@@ -443,14 +442,13 @@ static void send_outstanding_bcast_packet(struct work_struct *work)
container_of(work, struct delayed_work, work);
struct forw_packet *forw_packet =
container_of(delayed_work, struct forw_packet, delayed_work);
unsigned long flags;
struct sk_buff *skb1;
struct net_device *soft_iface = forw_packet->if_incoming->soft_iface;
struct bat_priv *bat_priv = netdev_priv(soft_iface);
spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
hlist_del(&forw_packet->list);
spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING)
goto out;
......@@ -488,13 +486,12 @@ void send_outstanding_bat_packet(struct work_struct *work)
container_of(work, struct delayed_work, work);
struct forw_packet *forw_packet =
container_of(delayed_work, struct forw_packet, delayed_work);
unsigned long flags;
struct bat_priv *bat_priv;
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
hlist_del(&forw_packet->list);
spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
if (atomic_read(&bat_priv->mesh_state) == MESH_DEACTIVATING)
goto out;
......@@ -522,7 +519,6 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
{
struct forw_packet *forw_packet;
struct hlist_node *tmp_node, *safe_tmp_node;
unsigned long flags;
if (batman_if)
bat_dbg(DBG_BATMAN, bat_priv,
......@@ -533,7 +529,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
"purge_outstanding_packets()\n");
/* free bcast list */
spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&bat_priv->forw_bcast_list, list) {
......@@ -545,19 +541,19 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
(forw_packet->if_incoming != batman_if))
continue;
spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
/**
* send_outstanding_bcast_packet() will lock the list to
* delete the item from the list
*/
cancel_delayed_work_sync(&forw_packet->delayed_work);
spin_lock_irqsave(&bat_priv->forw_bcast_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
}
spin_unlock_irqrestore(&bat_priv->forw_bcast_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
/* free batman packet list */
spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&bat_priv->forw_bat_list, list) {
......@@ -569,14 +565,14 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
(forw_packet->if_incoming != batman_if))
continue;
spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
/**
* send_outstanding_bat_packet() will lock the list to
* delete the item from the list
*/
cancel_delayed_work_sync(&forw_packet->delayed_work);
spin_lock_irqsave(&bat_priv->forw_bat_list_lock, flags);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
}
spin_unlock_irqrestore(&bat_priv->forw_bat_list_lock, flags);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
}
......@@ -97,9 +97,8 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
{
struct softif_neigh *softif_neigh, *softif_neigh_tmp;
struct hlist_node *node, *node_tmp;
unsigned long flags;
spin_lock_irqsave(&bat_priv->softif_neigh_lock, flags);
spin_lock_bh(&bat_priv->softif_neigh_lock);
hlist_for_each_entry_safe(softif_neigh, node, node_tmp,
&bat_priv->softif_neigh_list, list) {
......@@ -125,7 +124,7 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
}
spin_unlock_irqrestore(&bat_priv->softif_neigh_lock, flags);
spin_unlock_bh(&bat_priv->softif_neigh_lock);
}
static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
......@@ -133,7 +132,6 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
{
struct softif_neigh *softif_neigh;
struct hlist_node *node;
unsigned long flags;
rcu_read_lock();
hlist_for_each_entry_rcu(softif_neigh, node,
......@@ -158,9 +156,9 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
kref_init(&softif_neigh->refcount);
INIT_HLIST_NODE(&softif_neigh->list);
spin_lock_irqsave(&bat_priv->softif_neigh_lock, flags);
spin_lock_bh(&bat_priv->softif_neigh_lock);
hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
spin_unlock_irqrestore(&bat_priv->softif_neigh_lock, flags);
spin_unlock_bh(&bat_priv->softif_neigh_lock);
found:
kref_get(&softif_neigh->refcount);
......
......@@ -59,15 +59,14 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
struct hna_local_entry *hna_local_entry;
struct hna_global_entry *hna_global_entry;
struct hashtable_t *swaphash;
unsigned long flags;
int required_bytes;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
hna_local_entry =
((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash,
compare_orig, choose_orig,
addr));
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
if (hna_local_entry) {
hna_local_entry->last_seen = jiffies;
......@@ -107,7 +106,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
else
hna_local_entry->never_purge = 0;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
hash_add(bat_priv->hna_local_hash, compare_orig, choose_orig,
hna_local_entry);
......@@ -125,10 +124,10 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
bat_priv->hna_local_hash = swaphash;
}
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
/* remove address from global hash if present */
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
hna_global_entry = ((struct hna_global_entry *)
hash_find(bat_priv->hna_global_hash,
......@@ -138,7 +137,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
_hna_global_del_orig(bat_priv, hna_global_entry,
"local hna received");
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
}
int hna_local_fill_buffer(struct bat_priv *bat_priv,
......@@ -148,9 +147,8 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv,
struct element_t *bucket;
HASHIT(hashit);
int i = 0;
unsigned long flags;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
......@@ -168,7 +166,7 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv,
if (i == bat_priv->num_local_hna)
atomic_set(&bat_priv->hna_local_changed, 0);
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
return i;
}
......@@ -180,7 +178,6 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
HASHIT(hashit);
HASHIT(hashit_count);
struct element_t *bucket;
unsigned long flags;
size_t buf_size, pos;
char *buff;
......@@ -194,7 +191,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
"announced via HNA:\n",
net_dev->name);
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
......@@ -203,7 +200,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
return -ENOMEM;
}
buff[0] = '\0';
......@@ -217,7 +214,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
hna_local_entry->addr);
}
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
seq_printf(seq, "%s", buff);
kfree(buff);
......@@ -249,9 +246,8 @@ void hna_local_remove(struct bat_priv *bat_priv,
uint8_t *addr, char *message)
{
struct hna_local_entry *hna_local_entry;
unsigned long flags;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
hna_local_entry = (struct hna_local_entry *)
hash_find(bat_priv->hna_local_hash, compare_orig, choose_orig,
......@@ -259,7 +255,7 @@ void hna_local_remove(struct bat_priv *bat_priv,
if (hna_local_entry)
hna_local_del(bat_priv, hna_local_entry, message);
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
}
static void hna_local_purge(struct work_struct *work)
......@@ -271,10 +267,9 @@ static void hna_local_purge(struct work_struct *work)
struct hna_local_entry *hna_local_entry;
HASHIT(hashit);
struct element_t *bucket;
unsigned long flags;
unsigned long timeout;
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
while (hash_iterate(bat_priv->hna_local_hash, &hashit)) {
bucket = hlist_entry(hashit.walk, struct element_t, hlist);
......@@ -288,7 +283,7 @@ static void hna_local_purge(struct work_struct *work)
"address timed out");
}
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
hna_local_start_timer(bat_priv);
}
......@@ -323,11 +318,10 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
struct hna_local_entry *hna_local_entry;
struct hashtable_t *swaphash;
int hna_buff_count = 0;
unsigned long flags;
unsigned char *hna_ptr;
while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) {
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
hna_global_entry = (struct hna_global_entry *)
......@@ -335,8 +329,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
choose_orig, hna_ptr);
if (!hna_global_entry) {
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock,
flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
hna_global_entry =
kmalloc(sizeof(struct hna_global_entry),
......@@ -352,17 +345,17 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
"%pM (via %pM)\n",
hna_global_entry->addr, orig_node->orig);
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
hash_add(bat_priv->hna_global_hash, compare_orig,
choose_orig, hna_global_entry);
}
hna_global_entry->orig_node = orig_node;
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
/* remove address from local hash if present */
spin_lock_irqsave(&bat_priv->hna_lhash_lock, flags);
spin_lock_bh(&bat_priv->hna_lhash_lock);
hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
hna_local_entry = (struct hna_local_entry *)
......@@ -373,7 +366,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
hna_local_del(bat_priv, hna_local_entry,
"global hna received");
spin_unlock_irqrestore(&bat_priv->hna_lhash_lock, flags);
spin_unlock_bh(&bat_priv->hna_lhash_lock);
hna_buff_count++;
}
......@@ -390,7 +383,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
}
}
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
if (bat_priv->hna_global_hash->elements * 4 >
bat_priv->hna_global_hash->size) {
......@@ -403,7 +396,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
bat_priv->hna_global_hash = swaphash;
}
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
}
int hna_global_seq_print_text(struct seq_file *seq, void *offset)
......@@ -414,7 +407,6 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
HASHIT(hashit);
HASHIT(hashit_count);
struct element_t *bucket;
unsigned long flags;
size_t buf_size, pos;
char *buff;
......@@ -427,7 +419,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
net_dev->name);
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
......@@ -436,7 +428,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
return -ENOMEM;
}
buff[0] = '\0';
......@@ -451,7 +443,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
hna_global_entry->orig_node->orig);
}
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
seq_printf(seq, "%s", buff);
kfree(buff);
......@@ -477,13 +469,12 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
{
struct hna_global_entry *hna_global_entry;
int hna_buff_count = 0;
unsigned long flags;
unsigned char *hna_ptr;
if (orig_node->hna_buff_len == 0)
return;
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
......@@ -499,7 +490,7 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
hna_buff_count++;
}
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
orig_node->hna_buff_len = 0;
kfree(orig_node->hna_buff);
......@@ -523,13 +514,12 @@ void hna_global_free(struct bat_priv *bat_priv)
struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
{
struct hna_global_entry *hna_global_entry;
unsigned long flags;
spin_lock_irqsave(&bat_priv->hna_ghash_lock, flags);
spin_lock_bh(&bat_priv->hna_ghash_lock);
hna_global_entry = (struct hna_global_entry *)
hash_find(bat_priv->hna_global_hash,
compare_orig, choose_orig, addr);
spin_unlock_irqrestore(&bat_priv->hna_ghash_lock, flags);
spin_unlock_bh(&bat_priv->hna_ghash_lock);
if (!hna_global_entry)
return NULL;
......
......@@ -170,7 +170,6 @@ void frag_list_free(struct list_head *head)
int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
struct sk_buff **new_skb)
{
unsigned long flags;
struct orig_node *orig_node;
struct frag_packet_list_entry *tmp_frag_entry;
int ret = NET_RX_DROP;
......@@ -178,7 +177,7 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
(struct unicast_frag_packet *)skb->data;
*new_skb = NULL;
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->orig));
......@@ -211,7 +210,7 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
if (*new_skb)
ret = NET_RX_SUCCESS;
out:
spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
spin_unlock_bh(&bat_priv->orig_hash_lock);
return ret;
}
......@@ -279,9 +278,8 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
struct neigh_node *router;
int data_len = skb->len;
uint8_t dstaddr[6];
unsigned long flags;
spin_lock_irqsave(&bat_priv->orig_hash_lock, flags);
spin_lock_bh(&bat_priv->orig_hash_lock);
/* get routing information */
orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
......@@ -304,7 +302,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
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);
if (batman_if->if_status != IF_ACTIVE)
goto dropped;
......@@ -334,7 +332,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
return 0;
unlock:
spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);
spin_unlock_bh(&bat_priv->orig_hash_lock);
dropped:
kfree_skb(skb);
return 1;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment