Commit 8192edef authored by Gustavo F. Padovan's avatar Gustavo F. Padovan

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: default avatarMarcel Holtmann <marcel@holtmann.org>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent d01b2ff4
...@@ -960,9 +960,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) ...@@ -960,9 +960,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
chan->conn = conn; chan->conn = conn;
skb_queue_head_init(&chan->data_q); skb_queue_head_init(&chan->data_q);
tasklet_disable(&hdev->tx_task); list_add_rcu(&chan->list, &conn->chan_list);
list_add(&conn->chan_list, &chan->list);
tasklet_enable(&hdev->tx_task);
return chan; return chan;
} }
...@@ -974,9 +972,9 @@ int hci_chan_del(struct hci_chan *chan) ...@@ -974,9 +972,9 @@ int hci_chan_del(struct hci_chan *chan)
BT_DBG("%s conn %p chan %p", hdev->name, conn, chan); BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
tasklet_disable(&hdev->tx_task); list_del_rcu(&chan->list);
list_del(&chan->list);
tasklet_enable(&hdev->tx_task); synchronize_rcu();
skb_queue_purge(&chan->data_q); skb_queue_purge(&chan->data_q);
kfree(chan); kfree(chan);
...@@ -986,10 +984,10 @@ int hci_chan_del(struct hci_chan *chan) ...@@ -986,10 +984,10 @@ int hci_chan_del(struct hci_chan *chan)
void hci_chan_list_flush(struct hci_conn *conn) void hci_chan_list_flush(struct hci_conn *conn)
{ {
struct hci_chan *chan, *tmp; struct hci_chan *chan;
BT_DBG("conn %p", conn); 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); hci_chan_del(chan);
} }
...@@ -2135,7 +2135,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, ...@@ -2135,7 +2135,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
conn_num++; conn_num++;
list_for_each_entry(tmp, &conn->chan_list, list) { rcu_read_lock();
list_for_each_entry_rcu(tmp, &conn->chan_list, list) {
struct sk_buff *skb; struct sk_buff *skb;
if (skb_queue_empty(&tmp->data_q)) 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,6 +2161,8 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
} }
} }
rcu_read_unlock();
if (hci_conn_num(hdev, type) == conn_num) if (hci_conn_num(hdev, type) == conn_num)
break; break;
} }
...@@ -2207,7 +2211,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) ...@@ -2207,7 +2211,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
num++; num++;
list_for_each_entry(chan, &conn->chan_list, list) { rcu_read_lock();
list_for_each_entry_rcu(chan, &conn->chan_list, list) {
struct sk_buff *skb; struct sk_buff *skb;
if (chan->sent) { if (chan->sent) {
...@@ -2228,6 +2234,8 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) ...@@ -2228,6 +2234,8 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
skb->priority); skb->priority);
} }
rcu_read_unlock();
if (hci_conn_num(hdev, type) == num) if (hci_conn_num(hdev, type) == num)
break; break;
} }
......
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