aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGustavo F. Padovan <padovan@profusion.mobi>2011-12-14 12:08:48 -0500
committerGustavo F. Padovan <padovan@profusion.mobi>2011-12-18 14:07:56 -0500
commit8192edef03f9b47f1cc1120724db525e63e218f3 (patch)
tree5eac8bda79aefa69b41b9914d256aac4431e3c44
parentd01b2ff4e6496bc48a1917b6340e13263f871a15 (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.c14
-rw-r--r--net/bluetooth/hci_core.c12
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
987void hci_chan_list_flush(struct hci_conn *conn) 985void 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 }