Skip to content

Commit

Permalink
Bluetooth: Use RCU to manipulate chan_list
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Gustavo F. Padovan committed Dec 18, 2011
1 parent d01b2ff commit 8192ede
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 10 deletions.
14 changes: 6 additions & 8 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -960,9 +960,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn)
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;
}
Expand All @@ -974,9 +972,9 @@ int hci_chan_del(struct hci_chan *chan)

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);
Expand All @@ -986,10 +984,10 @@ int hci_chan_del(struct hci_chan *chan)

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);
}
12 changes: 10 additions & 2 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2135,7 +2135,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,

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;

if (skb_queue_empty(&tmp->data_q))
Expand All @@ -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)
break;
}
Expand Down Expand Up @@ -2207,7 +2211,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)

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;

if (chan->sent) {
Expand All @@ -2228,6 +2234,8 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
skb->priority);
}

rcu_read_unlock();

if (hci_conn_num(hdev, type) == num)
break;
}
Expand Down

0 comments on commit 8192ede

Please sign in to comment.