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 | |
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>
-rw-r--r-- | net/bluetooth/hci_conn.c | 14 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 12 |
2 files changed, 16 insertions, 10 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 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 36763aa59ea1..2c4f32f44569 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2135,7 +2135,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, | |||
2135 | 2135 | ||
2136 | conn_num++; | 2136 | conn_num++; |
2137 | 2137 | ||
2138 | list_for_each_entry(tmp, &conn->chan_list, list) { | 2138 | rcu_read_lock(); |
2139 | |||
2140 | list_for_each_entry_rcu(tmp, &conn->chan_list, list) { | ||
2139 | struct sk_buff *skb; | 2141 | struct sk_buff *skb; |
2140 | 2142 | ||
2141 | if (skb_queue_empty(&tmp->data_q)) | 2143 | if (skb_queue_empty(&tmp->data_q)) |
@@ -2159,6 +2161,8 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, | |||
2159 | } | 2161 | } |
2160 | } | 2162 | } |
2161 | 2163 | ||
2164 | rcu_read_unlock(); | ||
2165 | |||
2162 | if (hci_conn_num(hdev, type) == conn_num) | 2166 | if (hci_conn_num(hdev, type) == conn_num) |
2163 | break; | 2167 | break; |
2164 | } | 2168 | } |
@@ -2207,7 +2211,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) | |||
2207 | 2211 | ||
2208 | num++; | 2212 | num++; |
2209 | 2213 | ||
2210 | list_for_each_entry(chan, &conn->chan_list, list) { | 2214 | rcu_read_lock(); |
2215 | |||
2216 | list_for_each_entry_rcu(chan, &conn->chan_list, list) { | ||
2211 | struct sk_buff *skb; | 2217 | struct sk_buff *skb; |
2212 | 2218 | ||
2213 | if (chan->sent) { | 2219 | if (chan->sent) { |
@@ -2228,6 +2234,8 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) | |||
2228 | skb->priority); | 2234 | skb->priority); |
2229 | } | 2235 | } |
2230 | 2236 | ||
2237 | rcu_read_unlock(); | ||
2238 | |||
2231 | if (hci_conn_num(hdev, type) == num) | 2239 | if (hci_conn_num(hdev, type) == num) |
2232 | break; | 2240 | break; |
2233 | } | 2241 | } |