diff options
author | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-14 12:08:48 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-12-18 14:07:56 -0500 |
commit | 8192edef03f9b47f1cc1120724db525e63e218f3 (patch) | |
tree | 5eac8bda79aefa69b41b9914d256aac4431e3c44 /net/bluetooth/hci_conn.c | |
parent | d01b2ff4e6496bc48a1917b6340e13263f871a15 (diff) |
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>
Diffstat (limited to 'net/bluetooth/hci_conn.c')
-rw-r--r-- | net/bluetooth/hci_conn.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e6d8a220b5d9..b04467674a13 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -960,9 +960,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) | |||
960 | chan->conn = conn; | 960 | chan->conn = conn; |
961 | skb_queue_head_init(&chan->data_q); | 961 | skb_queue_head_init(&chan->data_q); |
962 | 962 | ||
963 | tasklet_disable(&hdev->tx_task); | 963 | list_add_rcu(&chan->list, &conn->chan_list); |
964 | list_add(&conn->chan_list, &chan->list); | ||
965 | tasklet_enable(&hdev->tx_task); | ||
966 | 964 | ||
967 | return chan; | 965 | return chan; |
968 | } | 966 | } |
@@ -974,9 +972,9 @@ int hci_chan_del(struct hci_chan *chan) | |||
974 | 972 | ||
975 | BT_DBG("%s conn %p chan %p", hdev->name, conn, chan); | 973 | BT_DBG("%s conn %p chan %p", hdev->name, conn, chan); |
976 | 974 | ||
977 | tasklet_disable(&hdev->tx_task); | 975 | list_del_rcu(&chan->list); |
978 | list_del(&chan->list); | 976 | |
979 | tasklet_enable(&hdev->tx_task); | 977 | synchronize_rcu(); |
980 | 978 | ||
981 | skb_queue_purge(&chan->data_q); | 979 | skb_queue_purge(&chan->data_q); |
982 | kfree(chan); | 980 | kfree(chan); |
@@ -986,10 +984,10 @@ int hci_chan_del(struct hci_chan *chan) | |||
986 | 984 | ||
987 | void hci_chan_list_flush(struct hci_conn *conn) | 985 | void hci_chan_list_flush(struct hci_conn *conn) |
988 | { | 986 | { |
989 | struct hci_chan *chan, *tmp; | 987 | struct hci_chan *chan; |
990 | 988 | ||
991 | BT_DBG("conn %p", conn); | 989 | BT_DBG("conn %p", conn); |
992 | 990 | ||
993 | list_for_each_entry_safe(chan, tmp, &conn->chan_list, list) | 991 | list_for_each_entry_rcu(chan, &conn->chan_list, list) |
994 | hci_chan_del(chan); | 992 | hci_chan_del(chan); |
995 | } | 993 | } |