* [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible
@ 2011-11-01 8:58 Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 2/7] Bluetooth: set skbuffer priority based on L2CAP socket priority Luiz Augusto von Dentz
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:58 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
When all items in the list have the same type there is no much of a point
to use list_for_each except if you want to use the list pointer itself.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/bnep/core.c | 13 +++--------
net/bluetooth/cmtp/core.c | 13 +++--------
net/bluetooth/hci_conn.c | 14 +++---------
net/bluetooth/hci_core.c | 46 +++++++++++-------------------------------
net/bluetooth/hci_sysfs.c | 18 +++-------------
net/bluetooth/hidp/core.c | 1 +
net/bluetooth/mgmt.c | 32 +++++++++--------------------
net/bluetooth/rfcomm/core.c | 14 ++++--------
net/bluetooth/rfcomm/tty.c | 20 ++++++------------
9 files changed, 51 insertions(+), 120 deletions(-)
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 91bcd3a..a6cd856 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -65,15 +65,13 @@ static DECLARE_RWSEM(bnep_session_sem);
static struct bnep_session *__bnep_get_session(u8 *dst)
{
struct bnep_session *s;
- struct list_head *p;
BT_DBG("");
- list_for_each(p, &bnep_session_list) {
- s = list_entry(p, struct bnep_session, list);
+ list_for_each_entry(s, &bnep_session_list, list)
if (!compare_ether_addr(dst, s->eh.h_source))
return s;
- }
+
return NULL;
}
@@ -667,17 +665,14 @@ static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
int bnep_get_connlist(struct bnep_connlist_req *req)
{
- struct list_head *p;
+ struct bnep_session *s;
int err = 0, n = 0;
down_read(&bnep_session_sem);
- list_for_each(p, &bnep_session_list) {
- struct bnep_session *s;
+ list_for_each_entry(s, &bnep_session_list, list) {
struct bnep_conninfo ci;
- s = list_entry(p, struct bnep_session, list);
-
__bnep_copy_ci(&ci, s);
if (copy_to_user(req->ci, &ci, sizeof(ci))) {
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 7d00ddf..9e8940b 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -53,15 +53,13 @@ static LIST_HEAD(cmtp_session_list);
static struct cmtp_session *__cmtp_get_session(bdaddr_t *bdaddr)
{
struct cmtp_session *session;
- struct list_head *p;
BT_DBG("");
- list_for_each(p, &cmtp_session_list) {
- session = list_entry(p, struct cmtp_session, list);
+ list_for_each_entry(session, &cmtp_session_list, list)
if (!bacmp(bdaddr, &session->bdaddr))
return session;
- }
+
return NULL;
}
@@ -431,19 +429,16 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)
int cmtp_get_connlist(struct cmtp_connlist_req *req)
{
- struct list_head *p;
+ struct cmtp_session *session;
int err = 0, n = 0;
BT_DBG("");
down_read(&cmtp_session_sem);
- list_for_each(p, &cmtp_session_list) {
- struct cmtp_session *session;
+ list_for_each_entry(session, &cmtp_session_list, list) {
struct cmtp_conninfo ci;
- session = list_entry(p, struct cmtp_session, list);
-
__cmtp_copy_session(session, &ci);
if (copy_to_user(req->ci, &ci, sizeof(ci))) {
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index c1c597e..6e98ff3 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -453,16 +453,13 @@ int hci_conn_del(struct hci_conn *conn)
struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
{
int use_src = bacmp(src, BDADDR_ANY);
- struct hci_dev *hdev = NULL;
- struct list_head *p;
+ struct hci_dev *hdev = NULL, *d;
BT_DBG("%s -> %s", batostr(src), batostr(dst));
read_lock_bh(&hci_dev_list_lock);
- list_for_each(p, &hci_dev_list) {
- struct hci_dev *d = list_entry(p, struct hci_dev, list);
-
+ list_for_each_entry(d, &hci_dev_list, list) {
if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags))
continue;
@@ -855,10 +852,10 @@ EXPORT_SYMBOL(hci_conn_put_device);
int hci_get_conn_list(void __user *arg)
{
+ register struct hci_conn *c;
struct hci_conn_list_req req, *cl;
struct hci_conn_info *ci;
struct hci_dev *hdev;
- struct list_head *p;
int n = 0, size, err;
if (copy_from_user(&req, arg, sizeof(req)))
@@ -882,10 +879,7 @@ int hci_get_conn_list(void __user *arg)
ci = cl->conn_info;
hci_dev_lock_bh(hdev);
- list_for_each(p, &hdev->conn_hash.list) {
- register struct hci_conn *c;
- c = list_entry(p, struct hci_conn, list);
-
+ list_for_each_entry(c, &hdev->conn_hash.list, list) {
bacpy(&(ci + n)->bdaddr, &c->dst);
(ci + n)->handle = c->handle;
(ci + n)->type = c->type;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index fdcbf8f..412082d 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -319,8 +319,7 @@ static void hci_linkpol_req(struct hci_dev *hdev, unsigned long opt)
* Device is held on return. */
struct hci_dev *hci_dev_get(int index)
{
- struct hci_dev *hdev = NULL;
- struct list_head *p;
+ struct hci_dev *hdev = NULL, *d;
BT_DBG("%d", index);
@@ -328,8 +327,7 @@ struct hci_dev *hci_dev_get(int index)
return NULL;
read_lock(&hci_dev_list_lock);
- list_for_each(p, &hci_dev_list) {
- struct hci_dev *d = list_entry(p, struct hci_dev, list);
+ list_for_each_entry(d, &hci_dev_list, list) {
if (d->id == index) {
hdev = hci_dev_hold(d);
break;
@@ -794,9 +792,9 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
int hci_get_dev_list(void __user *arg)
{
+ struct hci_dev *hdev;
struct hci_dev_list_req *dl;
struct hci_dev_req *dr;
- struct list_head *p;
int n = 0, size, err;
__u16 dev_num;
@@ -815,11 +813,7 @@ int hci_get_dev_list(void __user *arg)
dr = dl->dev_req;
read_lock_bh(&hci_dev_list_lock);
- list_for_each(p, &hci_dev_list) {
- struct hci_dev *hdev;
-
- hdev = list_entry(p, struct hci_dev, list);
-
+ list_for_each_entry(hdev, &hci_dev_list, list) {
hci_del_off_timer(hdev);
if (!test_bit(HCI_MGMT, &hdev->flags))
@@ -1008,16 +1002,11 @@ int hci_link_keys_clear(struct hci_dev *hdev)
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
- struct list_head *p;
-
- list_for_each(p, &hdev->link_keys) {
- struct link_key *k;
-
- k = list_entry(p, struct link_key, list);
+ struct link_key *k;
+ list_for_each_entry(k, &hdev->link_keys, list)
if (bacmp(bdaddr, &k->bdaddr) == 0)
return k;
- }
return NULL;
}
@@ -1280,16 +1269,11 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr)
{
- struct list_head *p;
-
- list_for_each(p, &hdev->blacklist) {
- struct bdaddr_list *b;
-
- b = list_entry(p, struct bdaddr_list, list);
+ struct bdaddr_list *b;
+ list_for_each_entry(b, &hdev->blacklist, list)
if (bacmp(bdaddr, &b->bdaddr) == 0)
return b;
- }
return NULL;
}
@@ -2033,16 +2017,12 @@ EXPORT_SYMBOL(hci_send_sco);
static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct hci_conn *conn = NULL;
+ struct hci_conn *conn = NULL, *c;
int num = 0, min = ~0;
- struct list_head *p;
/* We don't have to lock device here. Connections are always
* added and removed with TX task disabled. */
- list_for_each(p, &h->list) {
- struct hci_conn *c;
- c = list_entry(p, struct hci_conn, list);
-
+ list_for_each_entry(c, &h->list, list) {
if (c->type != type || skb_queue_empty(&c->data_q))
continue;
@@ -2091,14 +2071,12 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct list_head *p;
- struct hci_conn *c;
+ struct hci_conn *c;
BT_ERR("%s link tx timeout", hdev->name);
/* Kill stalled connections */
- list_for_each(p, &h->list) {
- c = list_entry(p, struct hci_conn, list);
+ list_for_each_entry(c, &h->list, list) {
if (c->type == type && c->sent) {
BT_ERR("%s killing stalled connection %s",
hdev->name, batostr(&c->dst));
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 1f9f876..f8e6aa3 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -435,17 +435,12 @@ static const struct file_operations inquiry_cache_fops = {
static int blacklist_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
- struct list_head *l;
+ struct bdaddr_list *b;
hci_dev_lock_bh(hdev);
- list_for_each(l, &hdev->blacklist) {
- struct bdaddr_list *b;
-
- b = list_entry(l, struct bdaddr_list, list);
-
+ list_for_each_entry(b, &hdev->blacklist, list)
seq_printf(f, "%s\n", batostr(&b->bdaddr));
- }
hci_dev_unlock_bh(hdev);
@@ -484,17 +479,12 @@ static void print_bt_uuid(struct seq_file *f, u8 *uuid)
static int uuids_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
- struct list_head *l;
+ struct bt_uuid *uuid;
hci_dev_lock_bh(hdev);
- list_for_each(l, &hdev->uuids) {
- struct bt_uuid *uuid;
-
- uuid = list_entry(l, struct bt_uuid, list);
-
+ list_for_each_entry(uuid, &hdev->uuids, list)
print_bt_uuid(f, uuid->uuid);
- }
hci_dev_unlock_bh(hdev);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 217ef47..2efd6cc 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -88,6 +88,7 @@ static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
if (!bacmp(bdaddr, &session->bdaddr))
return session;
}
+
return NULL;
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 9ffd7c3..7809aa9 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -123,6 +123,7 @@ static int read_index_list(struct sock *sk)
{
struct mgmt_rp_read_index_list *rp;
struct list_head *p;
+ struct hci_dev *d;
size_t rp_len;
u16 count;
int i, err;
@@ -146,9 +147,7 @@ static int read_index_list(struct sock *sk)
put_unaligned_le16(count, &rp->num_controllers);
i = 0;
- list_for_each(p, &hci_dev_list) {
- struct hci_dev *d = list_entry(p, struct hci_dev, list);
-
+ list_for_each_entry(d, &hci_dev_list, list) {
hci_del_off_timer(d);
set_bit(HCI_MGMT, &d->flags);
@@ -277,13 +276,9 @@ static void mgmt_pending_foreach(u16 opcode, int index,
static struct pending_cmd *mgmt_pending_find(u16 opcode, int index)
{
- struct list_head *p;
-
- list_for_each(p, &cmd_list) {
- struct pending_cmd *cmd;
-
- cmd = list_entry(p, struct pending_cmd, list);
+ struct pending_cmd *cmd;
+ list_for_each_entry(cmd, &cmd_list, list) {
if (cmd->opcode != opcode)
continue;
@@ -592,7 +587,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
u16 eir_len = 0;
u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)];
int i, truncated = 0;
- struct list_head *p;
+ struct bt_uuid *uuid;
size_t name_len;
name_len = strlen(hdev->dev_name);
@@ -617,8 +612,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data)
memset(uuid16_list, 0, sizeof(uuid16_list));
/* Group all UUID16 types */
- list_for_each(p, &hdev->uuids) {
- struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
+ list_for_each_entry(uuid, &hdev->uuids, list) {
u16 uuid16;
uuid16 = get_uuid16(uuid->uuid);
@@ -1069,6 +1063,7 @@ static int get_connections(struct sock *sk, u16 index)
{
struct mgmt_rp_get_connections *rp;
struct hci_dev *hdev;
+ struct hci_conn *c;
struct list_head *p;
size_t rp_len;
u16 count;
@@ -1097,11 +1092,8 @@ static int get_connections(struct sock *sk, u16 index)
put_unaligned_le16(count, &rp->conn_count);
i = 0;
- list_for_each(p, &hdev->conn_hash.list) {
- struct hci_conn *c = list_entry(p, struct hci_conn, list);
-
+ list_for_each_entry(c, &hdev->conn_hash.list, list)
bacpy(&rp->conn[i++], &c->dst);
- }
err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
@@ -1270,13 +1262,9 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
- struct list_head *p;
-
- list_for_each(p, &cmd_list) {
- struct pending_cmd *cmd;
-
- cmd = list_entry(p, struct pending_cmd, list);
+ struct pending_cmd *cmd;
+ list_for_each_entry(cmd, &cmd_list, list) {
if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
continue;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 38b618c..3d35eba 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -377,13 +377,11 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d)
static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
{
struct rfcomm_dlc *d;
- struct list_head *p;
- list_for_each(p, &s->dlcs) {
- d = list_entry(p, struct rfcomm_dlc, list);
+ list_for_each_entry(d, &s->dlcs, list)
if (d->dlci == dlci)
return d;
- }
+
return NULL;
}
@@ -2115,15 +2113,13 @@ static struct hci_cb rfcomm_cb = {
static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x)
{
struct rfcomm_session *s;
- struct list_head *pp, *p;
rfcomm_lock();
- list_for_each(p, &session_list) {
- s = list_entry(p, struct rfcomm_session, list);
- list_for_each(pp, &s->dlcs) {
+ list_for_each_entry(s, &session_list, list) {
+ struct rfcomm_dlc *d;
+ list_for_each_entry(d, &s->dlcs, list) {
struct sock *sk = s->sock->sk;
- struct rfcomm_dlc *d = list_entry(pp, struct rfcomm_dlc, list);
seq_printf(f, "%s %s %ld %d %d %d %d\n",
batostr(&bt_sk(sk)->src),
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index c258796..f6b2197 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -133,13 +133,10 @@ static inline void rfcomm_dev_put(struct rfcomm_dev *dev)
static struct rfcomm_dev *__rfcomm_dev_get(int id)
{
struct rfcomm_dev *dev;
- struct list_head *p;
- list_for_each(p, &rfcomm_dev_list) {
- dev = list_entry(p, struct rfcomm_dev, list);
+ list_for_each_entry(dev, &rfcomm_dev_list, list)
if (dev->id == id)
return dev;
- }
return NULL;
}
@@ -197,7 +194,7 @@ static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL);
static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
{
- struct rfcomm_dev *dev;
+ struct rfcomm_dev *dev, *entry;
struct list_head *head = &rfcomm_dev_list, *p;
int err = 0;
@@ -212,8 +209,8 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
if (req->dev_id < 0) {
dev->id = 0;
- list_for_each(p, &rfcomm_dev_list) {
- if (list_entry(p, struct rfcomm_dev, list)->id != dev->id)
+ list_for_each_entry(entry, &rfcomm_dev_list, list) {
+ if (entry->id != dev->id)
break;
dev->id++;
@@ -222,9 +219,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
} else {
dev->id = req->dev_id;
- list_for_each(p, &rfcomm_dev_list) {
- struct rfcomm_dev *entry = list_entry(p, struct rfcomm_dev, list);
-
+ list_for_each_entry(entry, &rfcomm_dev_list, list) {
if (entry->id == dev->id) {
err = -EADDRINUSE;
goto out;
@@ -455,9 +450,9 @@ static int rfcomm_release_dev(void __user *arg)
static int rfcomm_get_dev_list(void __user *arg)
{
+ struct rfcomm_dev *dev;
struct rfcomm_dev_list_req *dl;
struct rfcomm_dev_info *di;
- struct list_head *p;
int n = 0, size, err;
u16 dev_num;
@@ -479,8 +474,7 @@ static int rfcomm_get_dev_list(void __user *arg)
read_lock_bh(&rfcomm_dev_lock);
- list_for_each(p, &rfcomm_dev_list) {
- struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list);
+ list_for_each_entry(dev, &rfcomm_dev_list, list) {
if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags))
continue;
(di + n)->id = dev->id;
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/7] Bluetooth: set skbuffer priority based on L2CAP socket priority
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
@ 2011-11-01 8:58 ` Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 3/7] Bluetooth: make use sk_priority to priritize RFCOMM packets Luiz Augusto von Dentz
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:58 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This uses SO_PRIORITY to set the skbuffer priority field
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
include/net/bluetooth/hci_core.h | 3 +++
include/net/bluetooth/l2cap.h | 3 ++-
net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++-------
net/bluetooth/l2cap_sock.c | 2 +-
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 119b795..5d5fba9 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -32,6 +32,9 @@
#define HCI_PROTO_L2CAP 0
#define HCI_PROTO_SCO 1
+/* HCI priority */
+#define HCI_PRIO_MAX 7
+
/* HCI Core structures */
struct inquiry_data {
bdaddr_t bdaddr;
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index fddc82a..ed38c08 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -744,7 +744,8 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk);
void l2cap_chan_close(struct l2cap_chan *chan, int reason);
void l2cap_chan_destroy(struct l2cap_chan *chan);
int l2cap_chan_connect(struct l2cap_chan *chan);
-int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
+ u32 priority);
void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
#endif /* __L2CAP_H */
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index bda6da7..2db7d9d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -564,6 +564,7 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
flags = ACL_START;
bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
+ skb->priority = HCI_PRIO_MAX;
hci_send_acl(conn->hcon, skb, flags);
}
@@ -1265,7 +1266,8 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
struct hci_conn *hcon = chan->conn->hcon;
u16 flags;
- BT_DBG("chan %p, skb %p len %d", chan, skb, skb->len);
+ BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
+ skb->priority);
if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
lmp_no_flush_capable(hcon->hdev))
@@ -1483,6 +1485,8 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
return -EFAULT;
+ (*frag)->priority = skb->priority;
+
sent += count;
len -= count;
@@ -1492,7 +1496,9 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in
return sent;
}
-static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
+static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan,
+ struct msghdr *msg, size_t len,
+ u32 priority)
{
struct sock *sk = chan->sk;
struct l2cap_conn *conn = chan->conn;
@@ -1500,7 +1506,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct
int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE;
struct l2cap_hdr *lh;
- BT_DBG("sk %p len %d", sk, (int)len);
+ BT_DBG("sk %p len %d priority %u", sk, (int)len, priority);
count = min_t(unsigned int, (conn->mtu - hlen), len);
skb = bt_skb_send_alloc(sk, count + hlen,
@@ -1508,6 +1514,8 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct
if (!skb)
return ERR_PTR(err);
+ skb->priority = priority;
+
/* Create L2CAP header */
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->cid = cpu_to_le16(chan->dcid);
@@ -1522,7 +1530,9 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct
return skb;
}
-static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
+static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan,
+ struct msghdr *msg, size_t len,
+ u32 priority)
{
struct sock *sk = chan->sk;
struct l2cap_conn *conn = chan->conn;
@@ -1538,6 +1548,8 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct ms
if (!skb)
return ERR_PTR(err);
+ skb->priority = priority;
+
/* Create L2CAP header */
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->cid = cpu_to_le16(chan->dcid);
@@ -1651,7 +1663,8 @@ static int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, si
return size;
}
-int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len,
+ u32 priority)
{
struct sk_buff *skb;
u32 control;
@@ -1659,7 +1672,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
/* Connectionless channel */
if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
- skb = l2cap_create_connless_pdu(chan, msg, len);
+ skb = l2cap_create_connless_pdu(chan, msg, len, priority);
if (IS_ERR(skb))
return PTR_ERR(skb);
@@ -1674,7 +1687,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
return -EMSGSIZE;
/* Create a basic PDU */
- skb = l2cap_create_basic_pdu(chan, msg, len);
+ skb = l2cap_create_basic_pdu(chan, msg, len, priority);
if (IS_ERR(skb))
return PTR_ERR(skb);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 836d12e..646aefc 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -721,7 +721,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
return -ENOTCONN;
}
- err = l2cap_chan_send(chan, msg, len);
+ err = l2cap_chan_send(chan, msg, len, sk->sk_priority);
release_sock(sk);
return err;
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/7] Bluetooth: make use sk_priority to priritize RFCOMM packets
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 2/7] Bluetooth: set skbuffer priority based on L2CAP socket priority Luiz Augusto von Dentz
@ 2011-11-01 8:58 ` Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 4/7] Bluetooth: prioritizing data over HCI Luiz Augusto von Dentz
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:58 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/rfcomm/core.c | 51 +++++++++++++++++++++++++++++-------------
net/bluetooth/rfcomm/sock.c | 2 +
2 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 3d35eba..24bf961 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -65,7 +65,8 @@ static DEFINE_MUTEX(rfcomm_mutex);
static LIST_HEAD(session_list);
-static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len);
+static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len,
+ u32 priority);
static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci);
static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci);
static int rfcomm_queue_disc(struct rfcomm_dlc *d);
@@ -747,19 +748,34 @@ void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *d
}
/* ---- RFCOMM frame sending ---- */
-static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len)
+static int rfcomm_send_frame(struct rfcomm_session *s, u8 *data, int len,
+ u32 priority)
{
struct socket *sock = s->sock;
+ struct sock *sk = sock->sk;
struct kvec iv = { data, len };
struct msghdr msg;
- BT_DBG("session %p len %d", s, len);
+ BT_DBG("session %p len %d priority %u", s, len, priority);
+
+ if (sk->sk_priority != priority) {
+ lock_sock(sk);
+ sk->sk_priority = priority;
+ release_sock(sk);
+ }
memset(&msg, 0, sizeof(msg));
return kernel_sendmsg(sock, &msg, &iv, 1, len);
}
+static int rfcomm_send_cmd(struct rfcomm_session *s, struct rfcomm_cmd *cmd)
+{
+ BT_DBG("%p cmd %u", s, cmd->ctrl);
+
+ return rfcomm_send_frame(s, (void *) cmd, sizeof(*cmd), HCI_PRIO_MAX);
+}
+
static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci)
{
struct rfcomm_cmd cmd;
@@ -771,7 +787,7 @@ static int rfcomm_send_sabm(struct rfcomm_session *s, u8 dlci)
cmd.len = __len8(0);
cmd.fcs = __fcs2((u8 *) &cmd);
- return rfcomm_send_frame(s, (void *) &cmd, sizeof(cmd));
+ return rfcomm_send_cmd(s, &cmd);
}
static int rfcomm_send_ua(struct rfcomm_session *s, u8 dlci)
@@ -785,7 +801,7 @@ static int rfcomm_send_ua(struct rfcomm_session *s, u8 dlci)
cmd.len = __len8(0);
cmd.fcs = __fcs2((u8 *) &cmd);
- return rfcomm_send_frame(s, (void *) &cmd, sizeof(cmd));
+ return rfcomm_send_cmd(s, &cmd);
}
static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci)
@@ -799,7 +815,7 @@ static int rfcomm_send_disc(struct rfcomm_session *s, u8 dlci)
cmd.len = __len8(0);
cmd.fcs = __fcs2((u8 *) &cmd);
- return rfcomm_send_frame(s, (void *) &cmd, sizeof(cmd));
+ return rfcomm_send_cmd(s, &cmd);
}
static int rfcomm_queue_disc(struct rfcomm_dlc *d)
@@ -813,6 +829,8 @@ static int rfcomm_queue_disc(struct rfcomm_dlc *d)
if (!skb)
return -ENOMEM;
+ skb->priority = HCI_PRIO_MAX;
+
cmd = (void *) __skb_put(skb, sizeof(*cmd));
cmd->addr = d->addr;
cmd->ctrl = __ctrl(RFCOMM_DISC, 1);
@@ -835,7 +853,7 @@ static int rfcomm_send_dm(struct rfcomm_session *s, u8 dlci)
cmd.len = __len8(0);
cmd.fcs = __fcs2((u8 *) &cmd);
- return rfcomm_send_frame(s, (void *) &cmd, sizeof(cmd));
+ return rfcomm_send_cmd(s, &cmd);
}
static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
@@ -860,7 +878,7 @@ static int rfcomm_send_nsc(struct rfcomm_session *s, int cr, u8 type)
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d)
@@ -902,7 +920,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
@@ -940,7 +958,7 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
@@ -967,7 +985,7 @@ static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig)
@@ -994,7 +1012,7 @@ static int rfcomm_send_msc(struct rfcomm_session *s, int cr, u8 dlci, u8 v24_sig
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
@@ -1016,7 +1034,7 @@ static int rfcomm_send_fcoff(struct rfcomm_session *s, int cr)
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
@@ -1038,7 +1056,7 @@ static int rfcomm_send_fcon(struct rfcomm_session *s, int cr)
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static int rfcomm_send_test(struct rfcomm_session *s, int cr, u8 *pattern, int len)
@@ -1089,7 +1107,7 @@ static int rfcomm_send_credits(struct rfcomm_session *s, u8 addr, u8 credits)
*ptr = __fcs(buf); ptr++;
- return rfcomm_send_frame(s, buf, ptr - buf);
+ return rfcomm_send_frame(s, buf, ptr - buf, HCI_PRIO_MAX);
}
static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
@@ -1767,7 +1785,8 @@ static inline int rfcomm_process_tx(struct rfcomm_dlc *d)
return skb_queue_len(&d->tx_queue);
while (d->tx_credits && (skb = skb_dequeue(&d->tx_queue))) {
- err = rfcomm_send_frame(d->session, skb->data, skb->len);
+ err = rfcomm_send_frame(d->session, skb->data, skb->len,
+ skb->priority);
if (err < 0) {
skb_queue_head(&d->tx_queue, skb);
break;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 482722b..40988e2 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -597,6 +597,8 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
break;
}
+ skb->priority = sk->sk_priority;
+
err = rfcomm_dlc_send(d, skb);
if (err < 0) {
kfree_skb(skb);
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/7] Bluetooth: prioritizing data over HCI
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 2/7] Bluetooth: set skbuffer priority based on L2CAP socket priority Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 3/7] Bluetooth: make use sk_priority to priritize RFCOMM packets Luiz Augusto von Dentz
@ 2011-11-01 8:58 ` Luiz Augusto von Dentz
2011-11-01 16:41 ` Gustavo Padovan
2011-11-01 16:42 ` Gustavo Padovan
2011-11-01 8:59 ` [PATCH 5/7] Bluetooth: handle priority change within quote Luiz Augusto von Dentz
` (3 subsequent siblings)
6 siblings, 2 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:58 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
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>
---
include/net/bluetooth/hci_core.h | 42 ++++++++++
include/net/bluetooth/l2cap.h | 1 +
net/bluetooth/hci_conn.c | 59 ++++++++++++++
net/bluetooth/hci_core.c | 159 ++++++++++++++++++++++++++++++++------
net/bluetooth/l2cap_core.c | 18 ++++-
5 files changed, 252 insertions(+), 27 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5d5fba9..1efad6b 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -67,6 +67,12 @@ struct hci_conn_hash {
unsigned int le_num;
};
+struct hci_chan_hash {
+ struct list_head list;
+ spinlock_t lock;
+ unsigned int num;
+};
+
struct bdaddr_list {
struct list_head list;
bdaddr_t bdaddr;
@@ -287,6 +293,7 @@ struct hci_conn {
unsigned int sent;
struct sk_buff_head data_q;
+ struct hci_chan_hash chan_hash;
struct timer_list disc_timer;
struct timer_list idle_timer;
@@ -309,6 +316,14 @@ struct hci_conn {
void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
};
+struct hci_chan {
+ struct list_head list;
+
+ struct hci_conn *conn;
+ struct sk_buff_head data_q;
+ unsigned int sent;
+};
+
extern struct hci_proto *hci_proto[];
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
@@ -469,6 +484,28 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
return NULL;
}
+static inline void hci_chan_hash_init(struct hci_conn *c)
+{
+ struct hci_chan_hash *h = &c->chan_hash;
+ INIT_LIST_HEAD(&h->list);
+ spin_lock_init(&h->lock);
+ h->num = 0;
+}
+
+static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan)
+{
+ struct hci_chan_hash *h = &c->chan_hash;
+ list_add(&chan->list, &h->list);
+ h->num++;
+}
+
+static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan)
+{
+ struct hci_chan_hash *h = &c->chan_hash;
+ list_del(&chan->list);
+ h->num--;
+}
+
void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
@@ -480,6 +517,10 @@ int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
+struct hci_chan *hci_chan_create(struct hci_conn *conn);
+int hci_chan_del(struct hci_chan *chan);
+void hci_chan_hash_flush(struct hci_conn *conn);
+
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
@@ -850,6 +891,7 @@ int hci_unregister_notifier(struct notifier_block *nb);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+void hci_chan_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index ed38c08..c7aa766 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -450,6 +450,7 @@ struct l2cap_ops {
struct l2cap_conn {
struct hci_conn *hcon;
+ struct hci_chan *hchan;
bdaddr_t *dst;
bdaddr_t *src;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 6e98ff3..fb66597 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -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,58 @@ 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 list_head *p;
+
+ BT_DBG("conn %p", conn);
+ p = h->list.next;
+ while (p != &h->list) {
+ struct hci_chan *chan;
+
+ chan = list_entry(p, struct hci_chan, list);
+ p = p->next;
+
+ hci_chan_del(chan);
+ }
+}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 412082d..6dbc36a1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1939,23 +1939,18 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
hdr->dlen = cpu_to_le16(len);
}
-void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
+static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue,
+ struct sk_buff *skb, __u16 flags)
{
struct hci_dev *hdev = conn->hdev;
struct sk_buff *list;
- BT_DBG("%s conn %p flags 0x%x", hdev->name, conn, flags);
-
- skb->dev = (void *) hdev;
- bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
- hci_add_acl_hdr(skb, conn->handle, flags);
-
list = skb_shinfo(skb)->frag_list;
if (!list) {
/* Non fragmented */
BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
- skb_queue_tail(&conn->data_q, skb);
+ skb_queue_tail(queue, skb);
} else {
/* Fragmented */
BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
@@ -1963,9 +1958,9 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
skb_shinfo(skb)->frag_list = NULL;
/* Queue all fragments atomically */
- spin_lock_bh(&conn->data_q.lock);
+ spin_lock_bh(&queue->lock);
- __skb_queue_tail(&conn->data_q, skb);
+ __skb_queue_tail(queue, skb);
flags &= ~ACL_START;
flags |= ACL_CONT;
@@ -1978,16 +1973,46 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
- __skb_queue_tail(&conn->data_q, skb);
+ __skb_queue_tail(queue, skb);
} while (list);
- spin_unlock_bh(&conn->data_q.lock);
+ spin_unlock_bh(&queue->lock);
}
+}
+
+void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("%s conn %p flags 0x%x", hdev->name, conn, flags);
+
+ skb->dev = (void *) hdev;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+ hci_add_acl_hdr(skb, conn->handle, flags);
+
+ hci_queue_acl(conn, &conn->data_q, skb, flags);
tasklet_schedule(&hdev->tx_task);
}
EXPORT_SYMBOL(hci_send_acl);
+void hci_chan_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)
+{
+ struct hci_conn *conn = chan->conn;
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("%s chan %p flags 0x%x", hdev->name, chan, flags);
+
+ skb->dev = (void *) hdev;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+ hci_add_acl_hdr(skb, conn->handle, flags);
+
+ hci_queue_acl(conn, &chan->data_q, skb, flags);
+
+ tasklet_schedule(&hdev->tx_task);
+}
+EXPORT_SYMBOL(hci_chan_send_acl);
+
/* Send SCO data */
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)
{
@@ -2085,11 +2110,90 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
}
}
-static inline void hci_sched_acl(struct hci_dev *hdev)
+static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
+ int *quote)
{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_chan *chan = NULL;
+ int num = 0, min = ~0, cur_prio = 0;
struct hci_conn *conn;
+ int cnt, q, conn_num = 0;
+
+ BT_DBG("%s", hdev->name);
+
+ list_for_each_entry(conn, &h->list, list) {
+ struct hci_chan_hash *ch;
+ struct hci_chan *tmp;
+
+ if (conn->type != type)
+ continue;
+
+ if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
+ continue;
+
+ conn_num++;
+
+ ch = &conn->chan_hash;
+
+ list_for_each_entry(tmp, &ch->list, list) {
+ struct sk_buff *skb;
+
+ if (skb_queue_empty(&tmp->data_q))
+ continue;
+
+ skb = skb_peek(&tmp->data_q);
+ if (skb->priority < cur_prio)
+ continue;
+
+ if (skb->priority > cur_prio) {
+ num = 0;
+ min = ~0;
+ cur_prio = skb->priority;
+ }
+
+ num++;
+
+ if (conn->sent < min) {
+ min = conn->sent;
+ chan = tmp;
+ }
+ }
+
+ if (hci_conn_num(hdev, type) == conn_num)
+ break;
+ }
+
+ if (!chan)
+ return NULL;
+
+ switch (chan->conn->type) {
+ case ACL_LINK:
+ cnt = hdev->acl_cnt;
+ break;
+ case SCO_LINK:
+ case ESCO_LINK:
+ cnt = hdev->sco_cnt;
+ break;
+ case LE_LINK:
+ cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
+ break;
+ default:
+ cnt = 0;
+ BT_ERR("Unknown link type");
+ }
+
+ q = cnt / num;
+ *quote = q ? q : 1;
+ BT_DBG("chan %p quote %d", chan, *quote);
+ return chan;
+}
+
+static inline void hci_sched_acl(struct hci_dev *hdev)
+{
+ struct hci_chan *chan;
struct sk_buff *skb;
int quote;
+ unsigned int cnt;
BT_DBG("%s", hdev->name);
@@ -2103,17 +2207,23 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
hci_link_tx_to(hdev, ACL_LINK);
}
- while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, "e))) {
- while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
- BT_DBG("skb %p len %d", skb, skb->len);
+ cnt = hdev->acl_cnt;
+
+ while (hdev->acl_cnt &&
+ (chan = hci_chan_sent(hdev, ACL_LINK, "e))) {
+ while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
+ BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
+ skb->len, skb->priority);
- hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
+ hci_conn_enter_active_mode(chan->conn,
+ bt_cb(skb)->force_active);
hci_send_frame(skb);
hdev->acl_last_tx = jiffies;
hdev->acl_cnt--;
- conn->sent++;
+ chan->sent++;
+ chan->conn->sent++;
}
}
}
@@ -2167,7 +2277,7 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
static inline void hci_sched_le(struct hci_dev *hdev)
{
- struct hci_conn *conn;
+ struct hci_chan *chan;
struct sk_buff *skb;
int quote, cnt;
@@ -2185,17 +2295,20 @@ static inline void hci_sched_le(struct hci_dev *hdev)
}
cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
- while (cnt && (conn = hci_low_sent(hdev, LE_LINK, "e))) {
- while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
- BT_DBG("skb %p len %d", skb, skb->len);
+ while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) {
+ while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
+ BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
+ skb->len, skb->priority);
hci_send_frame(skb);
hdev->le_last_tx = jiffies;
cnt--;
- conn->sent++;
+ chan->sent++;
+ chan->conn->sent++;
}
}
+
if (hdev->le_pkts)
hdev->le_cnt = cnt;
else
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2db7d9d..fa404c4 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -566,7 +566,7 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
skb->priority = HCI_PRIO_MAX;
- hci_send_acl(conn->hcon, skb, flags);
+ hci_chan_send_acl(conn->hchan, skb, flags);
}
static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control)
@@ -1002,6 +1002,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
chan->ops->close(chan->data);
}
+ hci_chan_del(conn->hchan);
+
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
del_timer_sync(&conn->info_timer);
@@ -1024,18 +1026,26 @@ static void security_timeout(unsigned long arg)
static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
{
struct l2cap_conn *conn = hcon->l2cap_data;
+ struct hci_chan *hchan;
if (conn || status)
return conn;
+ hchan = hci_chan_create(hcon);
+ if (!hchan)
+ return NULL;
+
conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
- if (!conn)
+ if (!conn) {
+ hci_chan_del(hchan);
return NULL;
+ }
hcon->l2cap_data = conn;
conn->hcon = hcon;
+ conn->hchan = hchan;
- BT_DBG("hcon %p conn %p", hcon, conn);
+ BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
conn->mtu = hcon->hdev->le_mtu;
@@ -1276,7 +1286,7 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
flags = ACL_START;
bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags);
- hci_send_acl(hcon, skb, flags);
+ hci_chan_send_acl(chan->conn->hchan, skb, flags);
}
static void l2cap_streaming_send(struct l2cap_chan *chan)
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/7] Bluetooth: handle priority change within quote
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
` (2 preceding siblings ...)
2011-11-01 8:58 ` [PATCH 4/7] Bluetooth: prioritizing data over HCI Luiz Augusto von Dentz
@ 2011-11-01 8:59 ` Luiz Augusto von Dentz
2011-11-01 8:59 ` [PATCH 6/7] Bluetooth: recalculate priorities when channels are starving Luiz Augusto von Dentz
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:59 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
The quote is calculated based on the first buffer in the queue so if the
priority changes to something lower than the priority of the first skb
the quote needs to be recalculated.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/hci_core.c | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6dbc36a1..4ecf652 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2211,10 +2211,17 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
while (hdev->acl_cnt &&
(chan = hci_chan_sent(hdev, ACL_LINK, "e))) {
- while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
+ u32 priority = (skb_peek(&chan->data_q))->priority;
+ while (quote-- && (skb = skb_peek(&chan->data_q))) {
BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
skb->len, skb->priority);
+ /* Stop if priority has changed */
+ if (skb->priority < priority)
+ break;
+
+ skb = skb_dequeue(&chan->data_q);
+
hci_conn_enter_active_mode(chan->conn,
bt_cb(skb)->force_active);
@@ -2296,10 +2303,17 @@ static inline void hci_sched_le(struct hci_dev *hdev)
cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) {
- while (quote-- && (skb = skb_dequeue(&chan->data_q))) {
+ u32 priority = (skb_peek(&chan->data_q))->priority;
+ while (quote-- && (skb = skb_peek(&chan->data_q))) {
BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
skb->len, skb->priority);
+ /* Stop if priority has changed */
+ if (skb->priority < priority)
+ break;
+
+ skb = skb_dequeue(&chan->data_q);
+
hci_send_frame(skb);
hdev->le_last_tx = jiffies;
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/7] Bluetooth: recalculate priorities when channels are starving
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
` (3 preceding siblings ...)
2011-11-01 8:59 ` [PATCH 5/7] Bluetooth: handle priority change within quote Luiz Augusto von Dentz
@ 2011-11-01 8:59 ` Luiz Augusto von Dentz
2011-11-01 8:59 ` [PATCH 7/7] Bluetooth: use buffer priority to mark URB_ISO_ASAP flag Luiz Augusto von Dentz
2011-11-01 16:45 ` [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Gustavo Padovan
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:59 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
To avoid starvation the priority is recalculated so that the starving
channels are promoted to HCI_PRIO_MAX - 1 (6).
HCI_PRIO_MAX (7) is considered special, because it requires CAP_NET_ADMIN
capability which can be used to provide more guaranties, so it is not used
when promoting.
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
net/bluetooth/hci_core.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 55 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 4ecf652..14f7d73 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2188,6 +2188,53 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type,
return chan;
}
+static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct hci_conn *conn;
+ int num = 0;
+
+ BT_DBG("%s", hdev->name);
+
+ list_for_each_entry(conn, &h->list, list) {
+ struct hci_chan_hash *ch;
+ struct hci_chan *chan;
+
+ if (conn->type != type)
+ continue;
+
+ if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
+ continue;
+
+ num++;
+
+ ch = &conn->chan_hash;
+ list_for_each_entry(chan, &ch->list, list) {
+ struct sk_buff *skb;
+
+ if (chan->sent) {
+ chan->sent = 0;
+ continue;
+ }
+
+ if (skb_queue_empty(&chan->data_q))
+ continue;
+
+ skb = skb_peek(&chan->data_q);
+ if (skb->priority >= HCI_PRIO_MAX - 1)
+ continue;
+
+ skb->priority = HCI_PRIO_MAX - 1;
+
+ BT_DBG("chan %p skb %p promoted to %d", chan, skb,
+ skb->priority);
+ }
+
+ if (hci_conn_num(hdev, type) == num)
+ break;
+ }
+}
+
static inline void hci_sched_acl(struct hci_dev *hdev)
{
struct hci_chan *chan;
@@ -2233,6 +2280,9 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
chan->conn->sent++;
}
}
+
+ if (cnt != hdev->acl_cnt)
+ hci_prio_recalculate(hdev, ACL_LINK);
}
/* Schedule SCO */
@@ -2286,7 +2336,7 @@ static inline void hci_sched_le(struct hci_dev *hdev)
{
struct hci_chan *chan;
struct sk_buff *skb;
- int quote, cnt;
+ int quote, cnt, tmp;
BT_DBG("%s", hdev->name);
@@ -2302,6 +2352,7 @@ static inline void hci_sched_le(struct hci_dev *hdev)
}
cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
+ tmp = cnt;
while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, "e))) {
u32 priority = (skb_peek(&chan->data_q))->priority;
while (quote-- && (skb = skb_peek(&chan->data_q))) {
@@ -2327,6 +2378,9 @@ static inline void hci_sched_le(struct hci_dev *hdev)
hdev->le_cnt = cnt;
else
hdev->acl_cnt = cnt;
+
+ if (cnt != tmp)
+ hci_prio_recalculate(hdev, LE_LINK);
}
static void hci_tx_task(unsigned long arg)
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/7] Bluetooth: use buffer priority to mark URB_ISO_ASAP flag
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
` (4 preceding siblings ...)
2011-11-01 8:59 ` [PATCH 6/7] Bluetooth: recalculate priorities when channels are starving Luiz Augusto von Dentz
@ 2011-11-01 8:59 ` Luiz Augusto von Dentz
2011-11-01 16:45 ` [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Gustavo Padovan
6 siblings, 0 replies; 10+ messages in thread
From: Luiz Augusto von Dentz @ 2011-11-01 8:59 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
drivers/bluetooth/btusb.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index abfc4ee..9db2476 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -727,6 +727,9 @@ static int btusb_send_frame(struct sk_buff *skb)
usb_fill_bulk_urb(urb, data->udev, pipe,
skb->data, skb->len, btusb_tx_complete, skb);
+ if (skb->priority >= HCI_PRIO_MAX - 1)
+ urb->transfer_flags = URB_ISO_ASAP;
+
hdev->stat.acl_tx++;
break;
--
1.7.6.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 4/7] Bluetooth: prioritizing data over HCI
2011-11-01 8:58 ` [PATCH 4/7] Bluetooth: prioritizing data over HCI Luiz Augusto von Dentz
@ 2011-11-01 16:41 ` Gustavo Padovan
2011-11-01 16:42 ` Gustavo Padovan
1 sibling, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2011-11-01 16:41 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
* Luiz Augusto von Dentz <luiz.dentz@gmail.com> [2011-11-01 10:58:59 +0200]:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> 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>
> ---
> include/net/bluetooth/hci_core.h | 42 ++++++++++
> include/net/bluetooth/l2cap.h | 1 +
> net/bluetooth/hci_conn.c | 59 ++++++++++++++
> net/bluetooth/hci_core.c | 159 ++++++++++++++++++++++++++++++++------
> net/bluetooth/l2cap_core.c | 18 ++++-
> 5 files changed, 252 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 5d5fba9..1efad6b 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -67,6 +67,12 @@ struct hci_conn_hash {
> unsigned int le_num;
> };
>
> +struct hci_chan_hash {
> + struct list_head list;
> + spinlock_t lock;
> + unsigned int num;
> +};
> +
> struct bdaddr_list {
> struct list_head list;
> bdaddr_t bdaddr;
> @@ -287,6 +293,7 @@ struct hci_conn {
> unsigned int sent;
>
> struct sk_buff_head data_q;
> + struct hci_chan_hash chan_hash;
>
> struct timer_list disc_timer;
> struct timer_list idle_timer;
> @@ -309,6 +316,14 @@ struct hci_conn {
> void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
> };
>
> +struct hci_chan {
> + struct list_head list;
> +
> + struct hci_conn *conn;
> + struct sk_buff_head data_q;
> + unsigned int sent;
> +};
> +
> extern struct hci_proto *hci_proto[];
> extern struct list_head hci_dev_list;
> extern struct list_head hci_cb_list;
> @@ -469,6 +484,28 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
> return NULL;
> }
>
> +static inline void hci_chan_hash_init(struct hci_conn *c)
> +{
> + struct hci_chan_hash *h = &c->chan_hash;
> + INIT_LIST_HEAD(&h->list);
> + spin_lock_init(&h->lock);
> + h->num = 0;
> +}
> +
> +static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan)
> +{
> + struct hci_chan_hash *h = &c->chan_hash;
> + list_add(&chan->list, &h->list);
> + h->num++;
> +}
> +
> +static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan)
> +{
> + struct hci_chan_hash *h = &c->chan_hash;
> + list_del(&chan->list);
> + h->num--;
> +}
> +
> void hci_acl_connect(struct hci_conn *conn);
> void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
> void hci_add_sco(struct hci_conn *conn, __u16 handle);
> @@ -480,6 +517,10 @@ int hci_conn_del(struct hci_conn *conn);
> void hci_conn_hash_flush(struct hci_dev *hdev);
> void hci_conn_check_pending(struct hci_dev *hdev);
>
> +struct hci_chan *hci_chan_create(struct hci_conn *conn);
> +int hci_chan_del(struct hci_chan *chan);
> +void hci_chan_hash_flush(struct hci_conn *conn);
> +
> struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
> __u8 sec_level, __u8 auth_type);
> int hci_conn_check_link_mode(struct hci_conn *conn);
> @@ -850,6 +891,7 @@ int hci_unregister_notifier(struct notifier_block *nb);
>
> int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
> void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
> +void hci_chan_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
Your patch left only one user of hci_send_acl in l2cap_core.c:
l2cap_send_sframe(). I don't see a reason to for this so let's fix this here
and make all of them use the same sending function. Actually is a better idea
to first covert l2cap_send_sframe() to use l2cap_do_send().
And let's not change the function name here, hci_send_acl() is a good name.
Gustavo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 4/7] Bluetooth: prioritizing data over HCI
2011-11-01 8:58 ` [PATCH 4/7] Bluetooth: prioritizing data over HCI Luiz Augusto von Dentz
2011-11-01 16:41 ` Gustavo Padovan
@ 2011-11-01 16:42 ` Gustavo Padovan
1 sibling, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2011-11-01 16:42 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
* Luiz Augusto von Dentz <luiz.dentz@gmail.com> [2011-11-01 10:58:59 +0200]:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> 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>
> ---
> include/net/bluetooth/hci_core.h | 42 ++++++++++
> include/net/bluetooth/l2cap.h | 1 +
> net/bluetooth/hci_conn.c | 59 ++++++++++++++
> net/bluetooth/hci_core.c | 159 ++++++++++++++++++++++++++++++++------
> net/bluetooth/l2cap_core.c | 18 ++++-
> 5 files changed, 252 insertions(+), 27 deletions(-)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index 5d5fba9..1efad6b 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -67,6 +67,12 @@ struct hci_conn_hash {
> unsigned int le_num;
> };
>
> +struct hci_chan_hash {
> + struct list_head list;
> + spinlock_t lock;
> + unsigned int num;
> +};
> +
> struct bdaddr_list {
> struct list_head list;
> bdaddr_t bdaddr;
> @@ -287,6 +293,7 @@ struct hci_conn {
> unsigned int sent;
>
> struct sk_buff_head data_q;
> + struct hci_chan_hash chan_hash;
>
> struct timer_list disc_timer;
> struct timer_list idle_timer;
> @@ -309,6 +316,14 @@ struct hci_conn {
> void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
> };
>
> +struct hci_chan {
> + struct list_head list;
> +
> + struct hci_conn *conn;
> + struct sk_buff_head data_q;
> + unsigned int sent;
> +};
> +
> extern struct hci_proto *hci_proto[];
> extern struct list_head hci_dev_list;
> extern struct list_head hci_cb_list;
> @@ -469,6 +484,28 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
> return NULL;
> }
>
> +static inline void hci_chan_hash_init(struct hci_conn *c)
> +{
> + struct hci_chan_hash *h = &c->chan_hash;
> + INIT_LIST_HEAD(&h->list);
> + spin_lock_init(&h->lock);
> + h->num = 0;
> +}
> +
> +static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan)
> +{
> + struct hci_chan_hash *h = &c->chan_hash;
> + list_add(&chan->list, &h->list);
> + h->num++;
> +}
> +
> +static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan)
> +{
> + struct hci_chan_hash *h = &c->chan_hash;
> + list_del(&chan->list);
> + h->num--;
> +}
> +
> void hci_acl_connect(struct hci_conn *conn);
> void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
> void hci_add_sco(struct hci_conn *conn, __u16 handle);
> @@ -480,6 +517,10 @@ int hci_conn_del(struct hci_conn *conn);
> void hci_conn_hash_flush(struct hci_dev *hdev);
> void hci_conn_check_pending(struct hci_dev *hdev);
>
> +struct hci_chan *hci_chan_create(struct hci_conn *conn);
> +int hci_chan_del(struct hci_chan *chan);
> +void hci_chan_hash_flush(struct hci_conn *conn);
> +
> struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
> __u8 sec_level, __u8 auth_type);
> int hci_conn_check_link_mode(struct hci_conn *conn);
> @@ -850,6 +891,7 @@ int hci_unregister_notifier(struct notifier_block *nb);
>
> int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
> void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
> +void hci_chan_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
> void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
>
> void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> index ed38c08..c7aa766 100644
> --- a/include/net/bluetooth/l2cap.h
> +++ b/include/net/bluetooth/l2cap.h
> @@ -450,6 +450,7 @@ struct l2cap_ops {
>
> struct l2cap_conn {
> struct hci_conn *hcon;
> + struct hci_chan *hchan;
>
> bdaddr_t *dst;
> bdaddr_t *src;
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 6e98ff3..fb66597 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -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,58 @@ 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 list_head *p;
> +
> + BT_DBG("conn %p", conn);
> + p = h->list.next;
> + while (p != &h->list) {
> + struct hci_chan *chan;
> +
> + chan = list_entry(p, struct hci_chan, list);
> + p = p->next;
> +
> + hci_chan_del(chan);
> + }
Can't this be list_for_each_entry_safe()?
Gustavo
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
` (5 preceding siblings ...)
2011-11-01 8:59 ` [PATCH 7/7] Bluetooth: use buffer priority to mark URB_ISO_ASAP flag Luiz Augusto von Dentz
@ 2011-11-01 16:45 ` Gustavo Padovan
6 siblings, 0 replies; 10+ messages in thread
From: Gustavo Padovan @ 2011-11-01 16:45 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
* Luiz Augusto von Dentz <luiz.dentz@gmail.com> [2011-11-01 10:58:56 +0200]:
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> When all items in the list have the same type there is no much of a point
> to use list_for_each except if you want to use the list pointer itself.
>
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
> net/bluetooth/bnep/core.c | 13 +++--------
> net/bluetooth/cmtp/core.c | 13 +++--------
> net/bluetooth/hci_conn.c | 14 +++---------
> net/bluetooth/hci_core.c | 46 +++++++++++-------------------------------
> net/bluetooth/hci_sysfs.c | 18 +++-------------
> net/bluetooth/hidp/core.c | 1 +
> net/bluetooth/mgmt.c | 32 +++++++++--------------------
> net/bluetooth/rfcomm/core.c | 14 ++++--------
> net/bluetooth/rfcomm/tty.c | 20 ++++++------------
> 9 files changed, 51 insertions(+), 120 deletions(-)
Applied, thanks.
Gustavo
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-11-01 16:45 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-01 8:58 [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 2/7] Bluetooth: set skbuffer priority based on L2CAP socket priority Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 3/7] Bluetooth: make use sk_priority to priritize RFCOMM packets Luiz Augusto von Dentz
2011-11-01 8:58 ` [PATCH 4/7] Bluetooth: prioritizing data over HCI Luiz Augusto von Dentz
2011-11-01 16:41 ` Gustavo Padovan
2011-11-01 16:42 ` Gustavo Padovan
2011-11-01 8:59 ` [PATCH 5/7] Bluetooth: handle priority change within quote Luiz Augusto von Dentz
2011-11-01 8:59 ` [PATCH 6/7] Bluetooth: recalculate priorities when channels are starving Luiz Augusto von Dentz
2011-11-01 8:59 ` [PATCH 7/7] Bluetooth: use buffer priority to mark URB_ISO_ASAP flag Luiz Augusto von Dentz
2011-11-01 16:45 ` [PATCH 1/7] bluetooth: replace list_for_each with list_for_each_entry whenever possible Gustavo Padovan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).