Bluetooth: prioritizing data over HCI

This implement priority based scheduler using skbuffer priority set via
SO_PRIORITY socket option.

It introduces hci_chan_hash (list of HCI Channel/hci_chan) per connection,
each item in this list refer to a L2CAP connection and it is used to
queue the data for transmission.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
This commit is contained in:
Luiz Augusto von Dentz
2011-11-02 15:52:01 +02:00
committed by Gustavo F. Padovan
parent 3c32fa93e5
commit 73d80deb7b
6 changed files with 252 additions and 56 deletions

View File

@@ -374,6 +374,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
skb_queue_head_init(&conn->data_q);
hci_chan_hash_init(conn);
setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn);
setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn);
setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept,
@@ -432,6 +434,8 @@ int hci_conn_del(struct hci_conn *conn)
tasklet_disable(&hdev->tx_task);
hci_chan_hash_flush(conn);
hci_conn_hash_del(hdev, conn);
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
@@ -950,3 +954,52 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
}
struct hci_chan *hci_chan_create(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct hci_chan *chan;
BT_DBG("%s conn %p", hdev->name, conn);
chan = kzalloc(sizeof(struct hci_chan), GFP_ATOMIC);
if (!chan)
return NULL;
chan->conn = conn;
skb_queue_head_init(&chan->data_q);
tasklet_disable(&hdev->tx_task);
hci_chan_hash_add(conn, chan);
tasklet_enable(&hdev->tx_task);
return chan;
}
int hci_chan_del(struct hci_chan *chan)
{
struct hci_conn *conn = chan->conn;
struct hci_dev *hdev = conn->hdev;
BT_DBG("%s conn %p chan %p", hdev->name, conn, chan);
tasklet_disable(&hdev->tx_task);
hci_chan_hash_del(conn, chan);
tasklet_enable(&hdev->tx_task);
skb_queue_purge(&chan->data_q);
kfree(chan);
return 0;
}
void hci_chan_hash_flush(struct hci_conn *conn)
{
struct hci_chan_hash *h = &conn->chan_hash;
struct hci_chan *chan, *tmp;
BT_DBG("conn %p", conn);
list_for_each_entry_safe(chan, tmp, &h->list, list)
hci_chan_del(chan);
}