Bluetooth: Use RCU to manipulate chan_list

Instead of using tasklet_disable() to prevent acess to the channel use, we
can use RCU and improve the performance of our code.

Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index e6d8a22..b044676 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -960,9 +960,7 @@
 	chan->conn = conn;
 	skb_queue_head_init(&chan->data_q);
 
-	tasklet_disable(&hdev->tx_task);
-	list_add(&conn->chan_list, &chan->list);
-	tasklet_enable(&hdev->tx_task);
+	list_add_rcu(&chan->list, &conn->chan_list);
 
 	return chan;
 }
@@ -974,9 +972,9 @@
 
 	BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
 
-	tasklet_disable(&hdev->tx_task);
-	list_del(&chan->list);
-	tasklet_enable(&hdev->tx_task);
+	list_del_rcu(&chan->list);
+
+	synchronize_rcu();
 
 	skb_queue_purge(&chan->data_q);
 	kfree(chan);
@@ -986,10 +984,10 @@
 
 void hci_chan_list_flush(struct hci_conn *conn)
 {
-	struct hci_chan *chan, *tmp;
+	struct hci_chan *chan;
 
 	BT_DBG("conn %p", conn);
 
-	list_for_each_entry_safe(chan, tmp, &conn->chan_list, list)
+	list_for_each_entry_rcu(chan, &conn->chan_list, list)
 		hci_chan_del(chan);
 }