From 8035ded466049ca2fe8c04564a0fa00f222abe3f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 1 Nov 2011 10:58:56 +0200 Subject: Bluetooth: replace list_for_each with list_for_each_entry whenever possible 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 Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c1c597e3e198..6e98ff3da2a4 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; -- cgit v1.2.3 From 73d80deb7bdf0171f22e76dc2429c1f99eff90e2 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 2 Nov 2011 15:52:01 +0200 Subject: 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 Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 43 +++++++++++- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/hci_conn.c | 53 +++++++++++++++ net/bluetooth/hci_core.c | 143 ++++++++++++++++++++++++++++++++------- net/bluetooth/l2cap_core.c | 63 +++++++++-------- net/bluetooth/smp.c | 3 +- 6 files changed, 251 insertions(+), 55 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5a9db9a4b439..f97792c972f3 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); @@ -849,7 +890,7 @@ int hci_register_notifier(struct notifier_block *nb); 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_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 c10bf1db0abb..6ae9492ec564 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -451,6 +451,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 6e98ff3da2a4..e545376379c5 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,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); +} diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index f2ec434971f6..631327dc7fed 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1937,23 +1937,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); @@ -1961,9 +1956,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; @@ -1976,11 +1971,25 @@ 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_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); } @@ -2083,11 +2092,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); @@ -2101,17 +2189,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; - hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active); + 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(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++; } } } @@ -2165,7 +2259,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; @@ -2183,17 +2277,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 ac2c41ada0fe..15751fa5e914 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -566,7 +566,25 @@ 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_send_acl(conn->hchan, skb, flags); +} + +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 priority %u", chan, skb, skb->len, + skb->priority); + + if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && + lmp_no_flush_capable(hcon->hdev)) + flags = ACL_START_NO_FLUSH; + else + flags = ACL_START; + + bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); + hci_send_acl(chan->conn->hchan, skb, flags); } static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) @@ -575,7 +593,6 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) struct l2cap_hdr *lh; struct l2cap_conn *conn = chan->conn; int count, hlen; - u8 flags; if (chan->state != BT_CONNECTED) return; @@ -615,14 +632,8 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u32 control) put_unaligned_le16(fcs, skb_put(skb, L2CAP_FCS_SIZE)); } - if (lmp_no_flush_capable(conn->hcon->hdev)) - flags = ACL_START_NO_FLUSH; - else - flags = ACL_START; - - bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); - - hci_send_acl(chan->conn->hcon, skb, flags); + skb->priority = HCI_PRIO_MAX; + l2cap_do_send(chan, skb); } static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u32 control) @@ -1002,6 +1013,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 +1037,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; @@ -1261,24 +1282,6 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan) __clear_retrans_timer(chan); } -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 priority %u", chan, skb, skb->len, - skb->priority); - - if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && - lmp_no_flush_capable(hcon->hdev)) - flags = ACL_START_NO_FLUSH; - else - flags = ACL_START; - - bt_cb(skb)->force_active = test_bit(FLAG_FORCE_ACTIVE, &chan->flags); - hci_send_acl(hcon, skb, flags); -} - static void l2cap_streaming_send(struct l2cap_chan *chan) { struct sk_buff *skb; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 759b63572641..94e94ca35384 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -181,7 +181,8 @@ static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data) if (!skb) return; - hci_send_acl(conn->hcon, skb, 0); + skb->priority = HCI_PRIO_MAX; + hci_send_acl(conn->hchan, skb, 0); mod_timer(&conn->security_timer, jiffies + msecs_to_jiffies(SMP_TIMEOUT)); -- cgit v1.2.3 From 9f5a0d7bf079e9e26771ad13ff1c2cb3adf80963 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 7 Nov 2011 14:20:25 +0200 Subject: Bluetooth: Define HCI reasons instead of magic number Use HCI error reasons instead of magic numbers. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 7 +++++++ include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_conn.c | 2 +- net/bluetooth/hci_event.c | 4 ++-- net/bluetooth/l2cap_core.c | 8 ++++---- 5 files changed, 15 insertions(+), 8 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index c5fcd13b9edf..139ce2aa6eee 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -264,6 +264,13 @@ enum { #define HCI_LK_SMP_IRK 0x82 #define HCI_LK_SMP_CSRK 0x83 +/* ---- HCI Error Codes ---- */ +#define HCI_ERROR_AUTH_FAILURE 0x05 +#define HCI_ERROR_REJ_BAD_ADDR 0x0f +#define HCI_ERROR_REMOTE_USER_TERM 0x13 +#define HCI_ERROR_LOCAL_HOST_TERM 0x16 +#define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 + /* ----- HCI Commands ---- */ #define HCI_OP_NOP 0x0000 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f97792c972f3..006a7699abac 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -730,7 +730,7 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) static inline int hci_proto_disconn_ind(struct hci_conn *conn) { register struct hci_proto *hp; - int reason = 0x13; + int reason = HCI_ERROR_REMOTE_USER_TERM; hp = hci_proto[HCI_PROTO_L2CAP]; if (hp && hp->disconn_ind) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e545376379c5..ac943676f78d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -820,7 +820,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev) c->state = BT_CLOSED; - hci_proto_disconn_cfm(c, 0x16); + hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); hci_conn_del(c); } } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8c81a75381fb..9dc54db693a3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1559,7 +1559,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk struct hci_cp_reject_conn_req cp; bacpy(&cp.bdaddr, &ev->bdaddr); - cp.reason = 0x0f; + cp.reason = HCI_ERROR_REJ_BAD_ADDR; hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); } } @@ -2646,7 +2646,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff struct hci_cp_io_capability_neg_reply cp; bacpy(&cp.bdaddr, &ev->bdaddr); - cp.reason = 0x18; /* Pairing not allowed */ + cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, sizeof(cp), &cp); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index fe5666e15298..a50610b8a00c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -313,7 +313,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, chan->psm, chan->dcid); - conn->disc_reason = 0x13; + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; chan->conn = conn; @@ -1082,7 +1082,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) setup_timer(&conn->info_timer, l2cap_info_timeout, (unsigned long) conn); - conn->disc_reason = 0x13; + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; return conn; } @@ -2535,7 +2535,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd /* Check if the ACL is secure enough (if not SDP) */ if (psm != cpu_to_le16(0x0001) && !hci_conn_check_link_mode(conn->hcon)) { - conn->disc_reason = 0x05; + conn->disc_reason = HCI_ERROR_AUTH_FAILURE; result = L2CAP_CR_SEC_BLOCK; goto response; } @@ -4411,7 +4411,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon) BT_DBG("hcon %p", hcon); if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn) - return 0x13; + return HCI_ERROR_REMOTE_USER_TERM; return conn->disc_reason; } -- cgit v1.2.3 From d095c1ebd43a43c1d78055ff111f464b04f8624e Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 1 Dec 2011 14:33:27 +0200 Subject: Bluetooth: Remove magic bluetooth version numbers Use bluetooth names instead of BT SIG assigned numbers Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/bluetooth.h | 5 +++++ net/bluetooth/hci_conn.c | 2 +- net/bluetooth/hci_event.c | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 38cd3dab7f1d..97264fc8feeb 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -36,6 +36,11 @@ #define PF_BLUETOOTH AF_BLUETOOTH #endif +/* Bluetooth versions */ +#define BLUETOOTH_VER_1_1 1 +#define BLUETOOTH_VER_1_2 2 +#define BLUETOOTH_VER_2_0 3 + /* Reserv for core and drivers use */ #define BT_SKB_RESERVE 8 diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index de0b93e45980..b328ac611ccd 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -123,7 +123,7 @@ static void hci_acl_connect_cancel(struct hci_conn *conn) BT_DBG("%p", conn); - if (conn->hdev->hci_ver < 2) + if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2) return; bacpy(&cp.bdaddr, &conn->dst); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e3f7a8192446..a3e83aa92ecd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -500,7 +500,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) /* CSR 1.1 dongles does not accept any bitfield so don't try to set * any event mask for pre 1.2 devices */ - if (hdev->lmp_ver <= 1) + if (hdev->lmp_ver <= BLUETOOTH_VER_1_1) return; events[4] |= 0x01; /* Flow Specification Complete */ @@ -564,7 +564,7 @@ static void hci_setup(struct hci_dev *hdev) { hci_setup_event_mask(hdev); - if (hdev->hci_ver > 1) + if (hdev->hci_ver > BLUETOOTH_VER_1_1) hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); if (hdev->features[6] & LMP_SIMPLE_PAIR) { @@ -1558,7 +1558,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s } /* Set packet type for incoming connection */ - if (!conn->out && hdev->hci_ver < 3) { + if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) { struct hci_cp_change_conn_ptype cp; cp.handle = ev->handle; cp.pkt_type = cpu_to_le16(conn->pkt_type); -- cgit v1.2.3 From 2c33c06a8fd2f784ca763ad150d5d63c3c49946e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 14 Dec 2011 13:02:51 -0200 Subject: Bluetooth: remove struct hci_chan_hash Only the list member of the struct was used, so we now fold it into hci_conn. Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 33 ++------------------------------- net/bluetooth/hci_conn.c | 13 ++++++------- net/bluetooth/hci_core.c | 9 ++------- 3 files changed, 10 insertions(+), 45 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e34cd71a586e..fb2cce2b633f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -67,12 +67,6 @@ 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; @@ -301,7 +295,7 @@ struct hci_conn { unsigned int sent; struct sk_buff_head data_q; - struct hci_chan_hash chan_hash; + struct list_head chan_list; struct timer_list disc_timer; struct timer_list idle_timer; @@ -390,7 +384,6 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; INIT_LIST_HEAD(&h->list); - spin_lock_init(&h->lock); h->acl_num = 0; h->sco_num = 0; } @@ -492,28 +485,6 @@ 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); @@ -527,7 +498,7 @@ 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); +void hci_chan_list_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); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b328ac611ccd..1a076941829b 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -374,7 +374,7 @@ 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); + INIT_LIST_HEAD(&conn->chan_list);; setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); @@ -434,7 +434,7 @@ int hci_conn_del(struct hci_conn *conn) tasklet_disable(&hdev->tx_task); - hci_chan_hash_flush(conn); + hci_chan_list_flush(conn); hci_conn_hash_del(hdev, conn); if (hdev->notify) @@ -970,7 +970,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) skb_queue_head_init(&chan->data_q); tasklet_disable(&hdev->tx_task); - hci_chan_hash_add(conn, chan); + list_add(&conn->chan_list, &chan->list); tasklet_enable(&hdev->tx_task); return chan; @@ -984,7 +984,7 @@ int hci_chan_del(struct hci_chan *chan) BT_DBG("%s conn %p chan %p", hdev->name, conn, chan); tasklet_disable(&hdev->tx_task); - hci_chan_hash_del(conn, chan); + list_del(&chan->list); tasklet_enable(&hdev->tx_task); skb_queue_purge(&chan->data_q); @@ -993,13 +993,12 @@ int hci_chan_del(struct hci_chan *chan) return 0; } -void hci_chan_hash_flush(struct hci_conn *conn) +void hci_chan_list_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) + list_for_each_entry_safe(chan, tmp, &conn->chan_list, list) hci_chan_del(chan); } diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ce3727ecc0c4..700d0abdf2b1 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2125,7 +2125,6 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, 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) @@ -2136,9 +2135,7 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, conn_num++; - ch = &conn->chan_hash; - - list_for_each_entry(tmp, &ch->list, list) { + list_for_each_entry(tmp, &conn->chan_list, list) { struct sk_buff *skb; if (skb_queue_empty(&tmp->data_q)) @@ -2200,7 +2197,6 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) 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) @@ -2211,8 +2207,7 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) num++; - ch = &conn->chan_hash; - list_for_each_entry(chan, &ch->list, list) { + list_for_each_entry(chan, &conn->chan_list, list) { struct sk_buff *skb; if (chan->sent) { -- cgit v1.2.3 From 3e9c40a6f72a4ee7a978204cac00f91ad08bbe9b Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 14 Dec 2011 22:52:31 -0200 Subject: Bluetooth: Use list_for_each_entry in hci_conn_hash_flush() Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1a076941829b..dfe807fb7e79 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -807,17 +807,11 @@ void hci_conn_enter_sniff_mode(struct hci_conn *conn) void hci_conn_hash_flush(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; - struct list_head *p; + struct hci_conn *c; BT_DBG("hdev %s", hdev->name); - p = h->list.next; - while (p != &h->list) { - struct hci_conn *c; - - c = list_entry(p, struct hci_conn, list); - p = p->next; - + list_for_each_entry(c, &h->list, list) { c->state = BT_CLOSED; hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); -- cgit v1.2.3 From 416dc94baa4a0de6904707d17522f7eae7778c8e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 7 Dec 2011 13:24:33 -0200 Subject: Bluetooth: make hci_conn_enter_sniff_mode static It isn't used outside hci_conn.c Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_conn.c | 72 ++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 37 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 8e33c66eac73..6a1ac2c2489c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -509,7 +509,6 @@ int hci_conn_change_link_key(struct hci_conn *conn); int hci_conn_switch_role(struct hci_conn *conn, __u8 role); void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); -void hci_conn_enter_sniff_mode(struct hci_conn *conn); void hci_conn_hold_device(struct hci_conn *conn); void hci_conn_put_device(struct hci_conn *conn); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index dfe807fb7e79..3131a99dd5f6 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -311,6 +311,42 @@ static void hci_conn_timeout(unsigned long arg) hci_dev_unlock(hdev); } +/* Enter sniff mode */ +static void hci_conn_enter_sniff_mode(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + + BT_DBG("conn %p mode %d", conn, conn->mode); + + if (test_bit(HCI_RAW, &hdev->flags)) + return; + + if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) + return; + + if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) + return; + + if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { + struct hci_cp_sniff_subrate cp; + cp.handle = cpu_to_le16(conn->handle); + cp.max_latency = cpu_to_le16(0); + cp.min_remote_timeout = cpu_to_le16(0); + cp.min_local_timeout = cpu_to_le16(0); + hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); + } + + if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { + struct hci_cp_sniff_mode cp; + cp.handle = cpu_to_le16(conn->handle); + cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); + cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); + cp.attempt = cpu_to_le16(4); + cp.timeout = cpu_to_le16(1); + hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); + } +} + static void hci_conn_idle(unsigned long arg) { struct hci_conn *conn = (void *) arg; @@ -767,42 +803,6 @@ timer: jiffies + msecs_to_jiffies(hdev->idle_timeout)); } -/* Enter sniff mode */ -void hci_conn_enter_sniff_mode(struct hci_conn *conn) -{ - struct hci_dev *hdev = conn->hdev; - - BT_DBG("conn %p mode %d", conn, conn->mode); - - if (test_bit(HCI_RAW, &hdev->flags)) - return; - - if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) - return; - - if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) - return; - - if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { - struct hci_cp_sniff_subrate cp; - cp.handle = cpu_to_le16(conn->handle); - cp.max_latency = cpu_to_le16(0); - cp.min_remote_timeout = cpu_to_le16(0); - cp.min_local_timeout = cpu_to_le16(0); - hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); - } - - if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { - struct hci_cp_sniff_mode cp; - cp.handle = cpu_to_le16(conn->handle); - cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); - cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); - cp.attempt = cpu_to_le16(4); - cp.timeout = cpu_to_le16(1); - hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); - } -} - /* Drop all connection on the device */ void hci_conn_hash_flush(struct hci_dev *hdev) { -- cgit v1.2.3 From 09fd0de5bd8f8ef3317e5365f92f1a13dcd89aa9 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 17 Jun 2011 13:03:21 -0300 Subject: Bluetooth: Replace spin_lock by mutex in hci_dev Now we run everything in HCI in process context, so it's a better idea use mutex instead spin_lock. The macro remains hci_dev_lock() (and I got rid of hci_dev_lock_bh()), of course. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 8 ++- net/bluetooth/hci_conn.c | 12 ++--- net/bluetooth/hci_core.c | 38 +++++++------- net/bluetooth/hci_sock.c | 8 +-- net/bluetooth/hci_sysfs.c | 20 ++++---- net/bluetooth/hidp/core.c | 4 +- net/bluetooth/l2cap_core.c | 4 +- net/bluetooth/mgmt.c | 104 +++++++++++++++++++-------------------- net/bluetooth/sco.c | 4 +- 9 files changed, 100 insertions(+), 102 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1e28be45c4f2..e7dbe597a4bb 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -117,7 +117,7 @@ struct adv_entry { #define NUM_REASSEMBLY 4 struct hci_dev { struct list_head list; - spinlock_t lock; + struct mutex lock; atomic_t refcnt; char name[8]; @@ -566,10 +566,8 @@ static inline struct hci_dev *hci_dev_hold(struct hci_dev *d) return NULL; } -#define hci_dev_lock(d) spin_lock(&d->lock) -#define hci_dev_unlock(d) spin_unlock(&d->lock) -#define hci_dev_lock_bh(d) spin_lock_bh(&d->lock) -#define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock) +#define hci_dev_lock(d) mutex_lock(&d->lock) +#define hci_dev_unlock(d) mutex_unlock(&d->lock) struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3131a99dd5f6..d45783de5e2a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -876,7 +876,7 @@ int hci_get_conn_list(void __user *arg) ci = cl->conn_info; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); list_for_each_entry(c, &hdev->conn_hash.list, list) { bacpy(&(ci + n)->bdaddr, &c->dst); (ci + n)->handle = c->handle; @@ -887,7 +887,7 @@ int hci_get_conn_list(void __user *arg) if (++n >= req.conn_num) break; } - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); cl->dev_id = hdev->id; cl->conn_num = n; @@ -911,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr); if (conn) { bacpy(&ci.bdaddr, &conn->dst); @@ -921,7 +921,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) ci.state = conn->state; ci.link_mode = conn->link_mode; } - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); if (!conn) return -ENOENT; @@ -937,11 +937,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr); if (conn) req.type = conn->auth_type; - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); if (!conn) return -ENOENT; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4f15722c56dc..ec1019178f80 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -433,14 +433,14 @@ int hci_inquiry(void __user *arg) if (!hdev) return -ENODEV; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || inquiry_cache_empty(hdev) || ir.flags & IREQ_CACHE_FLUSH) { inquiry_cache_flush(hdev); do_inquiry = 1; } - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); timeo = ir.length * msecs_to_jiffies(2000); @@ -462,9 +462,9 @@ int hci_inquiry(void __user *arg) goto done; } - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); ir.num_rsp = inquiry_cache_dump(hdev, max_rsp, buf); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); BT_DBG("num_rsp %d", ir.num_rsp); @@ -541,9 +541,9 @@ int hci_dev_open(__u16 dev) set_bit(HCI_UP, &hdev->flags); hci_notify(hdev, HCI_DEV_UP); if (!test_bit(HCI_SETUP, &hdev->flags)) { - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); mgmt_powered(hdev, 1); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); } } else { /* Init failed, cleanup */ @@ -597,10 +597,10 @@ static int hci_dev_do_close(struct hci_dev *hdev) if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) cancel_delayed_work(&hdev->power_off); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); inquiry_cache_flush(hdev); hci_conn_hash_flush(hdev); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_notify(hdev, HCI_DEV_DOWN); @@ -636,9 +636,9 @@ static int hci_dev_do_close(struct hci_dev *hdev) * and no tasks are scheduled. */ hdev->close(hdev); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); mgmt_powered(hdev, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); /* Clear flags */ hdev->flags = 0; @@ -681,10 +681,10 @@ int hci_dev_reset(__u16 dev) skb_queue_purge(&hdev->rx_q); skb_queue_purge(&hdev->cmd_q); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); inquiry_cache_flush(hdev); hci_conn_hash_flush(hdev); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); if (hdev->flush) hdev->flush(hdev); @@ -967,13 +967,13 @@ static void hci_discov_off(struct work_struct *work) BT_DBG("%s", hdev->name); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan); hdev->discov_timeout = 0; - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); } int hci_uuids_clear(struct hci_dev *hdev) @@ -1443,7 +1443,7 @@ int hci_register_dev(struct hci_dev *hdev) list_add_tail(&hdev->list, head); atomic_set(&hdev->refcnt, 1); - spin_lock_init(&hdev->lock); + mutex_init(&hdev->lock); hdev->flags = 0; hdev->dev_flags = 0; @@ -1558,9 +1558,9 @@ void hci_unregister_dev(struct hci_dev *hdev) if (!test_bit(HCI_INIT, &hdev->flags) && !test_bit(HCI_SETUP, &hdev->flags)) { - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); mgmt_index_removed(hdev); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); } /* mgmt_index_removed should take care of emptying the @@ -1580,13 +1580,13 @@ void hci_unregister_dev(struct hci_dev *hdev) destroy_workqueue(hdev->workqueue); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hci_blacklist_clear(hdev); hci_uuids_clear(hdev); hci_link_keys_clear(hdev); hci_remote_oob_data_clear(hdev); hci_adv_entries_clear(hdev); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); __hci_dev_put(hdev); } diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f6afe3d76a66..399be345ea22 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -188,11 +188,11 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) return -EFAULT; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_blacklist_add(hdev, &bdaddr); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return err; } @@ -205,11 +205,11 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&bdaddr, arg, sizeof(bdaddr))) return -EFAULT; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_blacklist_del(hdev, &bdaddr); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return err; } diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index f8e6aa386cef..c3c1ec871d46 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -402,7 +402,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p) struct inquiry_cache *cache = &hdev->inq_cache; struct inquiry_entry *e; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); for (e = cache->list; e; e = e->next) { struct inquiry_data *data = &e->data; @@ -415,7 +415,7 @@ static int inquiry_cache_show(struct seq_file *f, void *p) data->rssi, data->ssp_mode, e->timestamp); } - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return 0; } @@ -437,12 +437,12 @@ static int blacklist_show(struct seq_file *f, void *p) struct hci_dev *hdev = f->private; struct bdaddr_list *b; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); list_for_each_entry(b, &hdev->blacklist, list) seq_printf(f, "%s\n", batostr(&b->bdaddr)); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return 0; } @@ -481,12 +481,12 @@ static int uuids_show(struct seq_file *f, void *p) struct hci_dev *hdev = f->private; struct bt_uuid *uuid; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); list_for_each_entry(uuid, &hdev->uuids, list) print_bt_uuid(f, uuid->uuid); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return 0; } @@ -507,11 +507,11 @@ static int auto_accept_delay_set(void *data, u64 val) { struct hci_dev *hdev = data; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hdev->auto_accept_delay = val; - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return 0; } @@ -520,11 +520,11 @@ static int auto_accept_delay_get(void *data, u64 *val) { struct hci_dev *hdev = data; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); *val = hdev->auto_accept_delay; - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); return 0; } diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 3c2d888925d7..d478be11d562 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -795,11 +795,11 @@ static struct hci_conn *hidp_get_connection(struct hidp_session *session) if (!hdev) return NULL; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (conn) hci_conn_hold_device(conn); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 014fdec17113..0369a9bf60c6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1171,7 +1171,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) if (!hdev) return -EHOSTUNREACH; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); auth_type = l2cap_get_auth_type(chan); @@ -1214,7 +1214,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan) err = 0; done: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7a23f211d602..ad4817c9ef2f 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -257,7 +257,7 @@ static int read_controller_info(struct sock *sk, u16 index) if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) cancel_delayed_work_sync(&hdev->power_off); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); set_bit(HCI_MGMT, &hdev->flags); @@ -286,7 +286,7 @@ static int read_controller_info(struct sock *sk, u16 index) memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp)); @@ -394,7 +394,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) return cmd_status(sk, index, MGMT_OP_SET_POWERED, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); up = test_bit(HCI_UP, &hdev->flags); if ((cp->val && up) || (!cp->val && !up)) { @@ -422,7 +422,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) err = 0; failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; } @@ -449,7 +449,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, @@ -492,7 +492,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, hdev->discov_timeout = get_unaligned_le16(&cp->timeout); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -520,7 +520,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, @@ -557,7 +557,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -612,7 +612,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (cp->val) set_bit(HCI_PAIRABLE, &hdev->flags); @@ -628,7 +628,7 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -827,7 +827,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) return cmd_status(sk, index, MGMT_OP_ADD_UUID, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC); if (!uuid) { @@ -851,7 +851,7 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -878,7 +878,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { err = hci_uuids_clear(hdev); @@ -914,7 +914,7 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0); unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -940,7 +940,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hdev->major_class = cp->major; hdev->minor_class = cp->minor; @@ -950,7 +950,7 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, if (err == 0) err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -974,7 +974,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); BT_DBG("hci%u enable %d", index, cp->enable); @@ -995,7 +995,7 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, -err); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1034,7 +1034,7 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys, key_count); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hci_link_keys_clear(hdev); @@ -1054,7 +1054,7 @@ static int load_link_keys(struct sock *sk, u16 index, unsigned char *data, cmd_complete(sk, index, MGMT_OP_LOAD_LINK_KEYS, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return 0; @@ -1082,7 +1082,7 @@ static int remove_keys(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_REMOVE_KEYS, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); memset(&rp, 0, sizeof(rp)); bacpy(&rp.bdaddr, &cp->bdaddr); @@ -1123,7 +1123,7 @@ unlock: if (err < 0) err = cmd_complete(sk, index, MGMT_OP_REMOVE_KEYS, &rp, sizeof(rp)); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1151,7 +1151,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) return cmd_status(sk, index, MGMT_OP_DISCONNECT, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_DISCONNECT, @@ -1189,7 +1189,7 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1231,7 +1231,7 @@ static int get_connections(struct sock *sk, u16 index) return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); count = 0; list_for_each(p, &hdev->conn_hash.list) { @@ -1263,7 +1263,7 @@ static int get_connections(struct sock *sk, u16 index) unlock: kfree(rp); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; } @@ -1311,7 +1311,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, @@ -1354,7 +1354,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1380,7 +1380,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, @@ -1391,7 +1391,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, err = send_pin_code_neg_reply(sk, index, hdev, cp); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1416,14 +1416,14 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); hdev->io_capability = cp->io_capability; BT_DBG("%s IO capability set to 0x%02x", hdev->name, hdev->io_capability); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0); @@ -1504,7 +1504,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); sec_level = BT_SECURITY_MEDIUM; if (cp->io_cap == 0x03) @@ -1561,7 +1561,7 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) err = 0; unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1580,7 +1580,7 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr, return cmd_status(sk, index, mgmt_op, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, mgmt_op, MGMT_STATUS_NOT_POWERED); @@ -1631,7 +1631,7 @@ static int user_pairing_resp(struct sock *sk, u16 index, bdaddr_t *bdaddr, mgmt_pending_remove(cmd); done: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1719,7 +1719,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_SET_LOCAL_NAME, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len); if (!cmd) { @@ -1734,7 +1734,7 @@ static int set_local_name(struct sock *sk, u16 index, unsigned char *data, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1753,7 +1753,7 @@ static int read_local_oob_data(struct sock *sk, u16 index) return cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_READ_LOCAL_OOB_DATA, @@ -1784,7 +1784,7 @@ static int read_local_oob_data(struct sock *sk, u16 index) mgmt_pending_remove(cmd); unlock: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1808,7 +1808,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_add_remote_oob_data(hdev, &cp->bdaddr, cp->hash, cp->randomizer); @@ -1819,7 +1819,7 @@ static int add_remote_oob_data(struct sock *sk, u16 index, unsigned char *data, err = cmd_complete(sk, index, MGMT_OP_ADD_REMOTE_OOB_DATA, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1843,7 +1843,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, return cmd_status(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_remove_remote_oob_data(hdev, &cp->bdaddr); if (err < 0) @@ -1853,7 +1853,7 @@ static int remove_remote_oob_data(struct sock *sk, u16 index, err = cmd_complete(sk, index, MGMT_OP_REMOVE_REMOTE_OOB_DATA, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1878,7 +1878,7 @@ static int start_discovery(struct sock *sk, u16 index, return cmd_status(sk, index, MGMT_OP_START_DISCOVERY, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (!test_bit(HCI_UP, &hdev->flags)) { err = cmd_status(sk, index, MGMT_OP_START_DISCOVERY, @@ -1897,7 +1897,7 @@ static int start_discovery(struct sock *sk, u16 index, mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1916,7 +1916,7 @@ static int stop_discovery(struct sock *sk, u16 index) return cmd_status(sk, index, MGMT_OP_STOP_DISCOVERY, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0); if (!cmd) { @@ -1929,7 +1929,7 @@ static int stop_discovery(struct sock *sk, u16 index) mgmt_pending_remove(cmd); failed: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1953,7 +1953,7 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_blacklist_add(hdev, &cp->bdaddr); if (err < 0) @@ -1963,7 +1963,7 @@ static int block_device(struct sock *sk, u16 index, unsigned char *data, err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; @@ -1987,7 +1987,7 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, MGMT_STATUS_INVALID_PARAMS); - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); err = hci_blacklist_del(hdev, &cp->bdaddr); @@ -1998,7 +1998,7 @@ static int unblock_device(struct sock *sk, u16 index, unsigned char *data, err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE, NULL, 0); - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index a324b009e34b..725e10d487f2 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -189,7 +189,7 @@ static int sco_connect(struct sock *sk) if (!hdev) return -EHOSTUNREACH; - hci_dev_lock_bh(hdev); + hci_dev_lock(hdev); if (lmp_esco_capable(hdev) && !disable_esco) type = ESCO_LINK; @@ -225,7 +225,7 @@ static int sco_connect(struct sock *sk) } done: - hci_dev_unlock_bh(hdev); + hci_dev_unlock(hdev); hci_dev_put(hdev); return err; } -- cgit v1.2.3 From 19c40e3bcaf2d969f5d4ee85bbe1330b54d36d9c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 17 Jun 2011 13:03:21 -0300 Subject: Bluetooth: Use delayed_work for connection timeout Bluetooth rx task runs now in a workqueue, so it a good approach run any timer that share locking with process context code also in a workqueue. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 8 +++++--- net/bluetooth/hci_conn.c | 9 +++++---- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e7dbe597a4bb..d91590850429 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -297,7 +297,7 @@ struct hci_conn { struct sk_buff_head data_q; struct list_head chan_list; - struct timer_list disc_timer; + struct delayed_work disc_work; struct timer_list idle_timer; struct timer_list auto_accept_timer; @@ -517,7 +517,7 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { atomic_inc(&conn->refcnt); - del_timer(&conn->disc_timer); + cancel_delayed_work_sync(&conn->disc_work); } static inline void hci_conn_put(struct hci_conn *conn) @@ -536,7 +536,9 @@ static inline void hci_conn_put(struct hci_conn *conn) } else { timeo = msecs_to_jiffies(10); } - mod_timer(&conn->disc_timer, jiffies + timeo); + cancel_delayed_work_sync(&conn->disc_work); + queue_delayed_work(conn->hdev->workqueue, + &conn->disc_work, jiffies + timeo); } } diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index d45783de5e2a..7d88a6142092 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -275,9 +275,10 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) } } -static void hci_conn_timeout(unsigned long arg) +static void hci_conn_timeout(struct work_struct *work) { - struct hci_conn *conn = (void *) arg; + struct hci_conn *conn = container_of(work, struct hci_conn, + disc_work.work); struct hci_dev *hdev = conn->hdev; __u8 reason; @@ -412,7 +413,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) INIT_LIST_HEAD(&conn->chan_list);; - setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); + INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, (unsigned long) conn); @@ -444,7 +445,7 @@ int hci_conn_del(struct hci_conn *conn) del_timer(&conn->idle_timer); - del_timer(&conn->disc_timer); + cancel_delayed_work_sync(&conn->disc_work); del_timer(&conn->auto_accept_timer); -- cgit v1.2.3 From b9cc553f12d14b692d0fcb607d28db783da68139 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 17 Jun 2011 12:58:41 -0300 Subject: Bluetooth: hci_conn_auto_accept() doesn't need locking It doesn't really touch any sensitive information about hdev. So no need to lock here. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7d88a6142092..e6d8a220b5d9 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -362,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg) struct hci_conn *conn = (void *) arg; struct hci_dev *hdev = conn->hdev; - hci_dev_lock(hdev); - hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), &conn->dst); - - hci_dev_unlock(hdev); } struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) -- cgit v1.2.3 From 8192edef03f9b47f1cc1120724db525e63e218f3 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 14 Dec 2011 15:08:48 -0200 Subject: 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 Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 14 ++++++-------- net/bluetooth/hci_core.c | 12 ++++++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) (limited to 'net/bluetooth/hci_conn.c') 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) 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; } @@ -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); @@ -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); } 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, 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)) @@ -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; } @@ -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) { @@ -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; } -- cgit v1.2.3 From bf4c63252490ba78fb833cc7acf1a5b1900c970f Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 14 Dec 2011 22:54:12 -0200 Subject: Bluetooth: convert conn hash to RCU Handling hci_conn_hash with RCU make us avoid some locking and disable tasklets. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 45 +++++++++++++++++++++++++++------------- net/bluetooth/hci_conn.c | 19 ++++++++--------- net/bluetooth/hci_core.c | 34 +++++++++++++++++++----------- 3 files changed, 62 insertions(+), 36 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 14b200b08d84..e83243318924 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -392,7 +392,7 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev) static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; - list_add(&c->list, &h->list); + list_add_rcu(&c->list, &h->list); switch (c->type) { case ACL_LINK: h->acl_num++; @@ -410,7 +410,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; - list_del(&c->list); + + list_del_rcu(&c->list); + synchronize_rcu(); + switch (c->type) { case ACL_LINK: h->acl_num--; @@ -445,14 +448,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, __u16 handle) { struct hci_conn_hash *h = &hdev->conn_hash; - struct list_head *p; struct hci_conn *c; - list_for_each(p, &h->list) { - c = list_entry(p, struct hci_conn, list); - if (c->handle == handle) + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { + if (c->handle == handle) { + rcu_read_unlock(); return c; + } } + rcu_read_unlock(); + return NULL; } @@ -460,14 +467,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, __u8 type, bdaddr_t *ba) { struct hci_conn_hash *h = &hdev->conn_hash; - struct list_head *p; struct hci_conn *c; - list_for_each(p, &h->list) { - c = list_entry(p, struct hci_conn, list); - if (c->type == type && !bacmp(&c->dst, ba)) + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { + if (c->type == type && !bacmp(&c->dst, ba)) { + rcu_read_unlock(); return c; + } } + + rcu_read_unlock(); + return NULL; } @@ -475,14 +487,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, __u8 type, __u16 state) { struct hci_conn_hash *h = &hdev->conn_hash; - struct list_head *p; struct hci_conn *c; - list_for_each(p, &h->list) { - c = list_entry(p, struct hci_conn, list); - if (c->type == type && c->state == state) + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { + if (c->type == type && c->state == state) { + rcu_read_unlock(); return c; + } } + + rcu_read_unlock(); + return NULL; } diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b04467674a13..5e9e193ac71e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -418,18 +418,17 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_dev_hold(hdev); - tasklet_disable(&hdev->tx_task); - hci_conn_hash_add(hdev, conn); - if (hdev->notify) + if (hdev->notify) { + tasklet_disable(&hdev->tx_task); hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); + tasklet_enable(&hdev->tx_task); + } atomic_set(&conn->devref, 0); hci_conn_init_sysfs(conn); - tasklet_enable(&hdev->tx_task); - return conn; } @@ -465,15 +464,15 @@ int hci_conn_del(struct hci_conn *conn) } } - tasklet_disable(&hdev->tx_task); hci_chan_list_flush(conn); hci_conn_hash_del(hdev, conn); - if (hdev->notify) + if (hdev->notify) { + tasklet_disable(&hdev->tx_task); hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); - - tasklet_enable(&hdev->tx_task); + tasklet_enable(&hdev->tx_task); + } skb_queue_purge(&conn->data_q); @@ -808,7 +807,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev) BT_DBG("hdev %s", hdev->name); - list_for_each_entry(c, &h->list, list) { + list_for_each_entry_rcu(c, &h->list, list) { c->state = BT_CLOSED; hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2c4f32f44569..de923ee60093 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2050,7 +2050,10 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int /* We don't have to lock device here. Connections are always * added and removed with TX task disabled. */ - list_for_each_entry(c, &h->list, list) { + + rcu_read_lock(); + + list_for_each_entry_rcu(c, &h->list, list) { if (c->type != type || skb_queue_empty(&c->data_q)) continue; @@ -2068,6 +2071,8 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int break; } + rcu_read_unlock(); + if (conn) { int cnt, q; @@ -2103,14 +2108,18 @@ static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type) BT_ERR("%s link tx timeout", hdev->name); + rcu_read_lock(); + /* Kill stalled connections */ - list_for_each_entry(c, &h->list, list) { + list_for_each_entry_rcu(c, &h->list, list) { if (c->type == type && c->sent) { BT_ERR("%s killing stalled connection %s", hdev->name, batostr(&c->dst)); hci_acl_disconn(c, 0x13); } } + + rcu_read_unlock(); } static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, @@ -2124,7 +2133,9 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, BT_DBG("%s", hdev->name); - list_for_each_entry(conn, &h->list, list) { + rcu_read_lock(); + + list_for_each_entry_rcu(conn, &h->list, list) { struct hci_chan *tmp; if (conn->type != type) @@ -2135,8 +2146,6 @@ static inline struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, conn_num++; - rcu_read_lock(); - list_for_each_entry_rcu(tmp, &conn->chan_list, list) { struct sk_buff *skb; @@ -2161,12 +2170,12 @@ 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; } + rcu_read_unlock(); + if (!chan) return NULL; @@ -2200,7 +2209,9 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) BT_DBG("%s", hdev->name); - list_for_each_entry(conn, &h->list, list) { + rcu_read_lock(); + + list_for_each_entry_rcu(conn, &h->list, list) { struct hci_chan *chan; if (conn->type != type) @@ -2211,8 +2222,6 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) num++; - rcu_read_lock(); - list_for_each_entry_rcu(chan, &conn->chan_list, list) { struct sk_buff *skb; @@ -2234,11 +2243,12 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type) skb->priority); } - rcu_read_unlock(); - if (hci_conn_num(hdev, type) == num) break; } + + rcu_read_unlock(); + } static inline void hci_sched_acl(struct hci_dev *hdev) -- cgit v1.2.3 From 3c54711c4fd103edf2044ab60726939f1de02b0c Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 14 Dec 2011 22:58:44 -0200 Subject: Bluetooth: Don't disable tasklets to call hdev->notify() It's pointless, we aren't protecting anything since btusb_notify() schedules a work to run, then all it operation happens without protection. If protection is really needed here, we will fix it further. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 10 ++-------- net/bluetooth/hci_event.c | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5e9e193ac71e..385cccbcafe0 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -419,11 +419,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_dev_hold(hdev); hci_conn_hash_add(hdev, conn); - if (hdev->notify) { - tasklet_disable(&hdev->tx_task); + if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); - tasklet_enable(&hdev->tx_task); - } atomic_set(&conn->devref, 0); @@ -468,11 +465,8 @@ int hci_conn_del(struct hci_conn *conn) hci_chan_list_flush(conn); hci_conn_hash_del(hdev, conn); - if (hdev->notify) { - tasklet_disable(&hdev->tx_task); + if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); - tasklet_enable(&hdev->tx_task); - } skb_queue_purge(&conn->data_q); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0a9501f17366..93ecb2dfa177 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -378,11 +378,8 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s voice setting 0x%04x", hdev->name, setting); - if (hdev->notify) { - tasklet_disable(&hdev->tx_task); + if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); - tasklet_enable(&hdev->tx_task); - } } static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) @@ -409,11 +406,8 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb BT_DBG("%s voice setting 0x%04x", hdev->name, setting); - if (hdev->notify) { - tasklet_disable(&hdev->tx_task); + if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); - tasklet_enable(&hdev->tx_task); - } } static void hci_cc_host_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) -- cgit v1.2.3 From d7660918fce210f421cc58c060ca3de71e4ffd37 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Sun, 18 Dec 2011 22:33:30 -0200 Subject: Revert "Bluetooth: Revert: Fix L2CAP connection establishment" This reverts commit 4dff523a913197e3314c7b0d08734ab037709093. It was reported that this patch cause issues when trying to connect to legacy devices so reverting it. Reported-by: David Fries Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e0af7237cd92..c1c597e3e198 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -673,7 +673,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) goto encrypt; auth: - if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) + if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; if (!hci_conn_auth(conn, sec_level, auth_type)) -- cgit v1.2.3 From f20d09d5f7093e5dc5f231c65835e2d04739bd5e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 22 Dec 2011 16:30:27 -0200 Subject: Bluetooth: remove *_bh usage from hci_dev_list and hci_cb_list They don't need to disable interrupts anymore, we only run in process context now. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci_core.h | 16 ++++++++-------- net/bluetooth/hci_conn.c | 4 ++-- net/bluetooth/hci_core.c | 24 ++++++++++++------------ 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'net/bluetooth/hci_conn.c') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 37d7cb8be480..5e2e98458496 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -801,13 +801,13 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; - read_lock_bh(&hci_cb_list_lock); + read_lock(&hci_cb_list_lock); list_for_each(p, &hci_cb_list) { struct hci_cb *cb = list_entry(p, struct hci_cb, list); if (cb->security_cfm) cb->security_cfm(conn, status, encrypt); } - read_unlock_bh(&hci_cb_list_lock); + read_unlock(&hci_cb_list_lock); } static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, @@ -823,26 +823,26 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, hci_proto_encrypt_cfm(conn, status, encrypt); - read_lock_bh(&hci_cb_list_lock); + read_lock(&hci_cb_list_lock); list_for_each(p, &hci_cb_list) { struct hci_cb *cb = list_entry(p, struct hci_cb, list); if (cb->security_cfm) cb->security_cfm(conn, status, encrypt); } - read_unlock_bh(&hci_cb_list_lock); + read_unlock(&hci_cb_list_lock); } static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) { struct list_head *p; - read_lock_bh(&hci_cb_list_lock); + read_lock(&hci_cb_list_lock); list_for_each(p, &hci_cb_list) { struct hci_cb *cb = list_entry(p, struct hci_cb, list); if (cb->key_change_cfm) cb->key_change_cfm(conn, status); } - read_unlock_bh(&hci_cb_list_lock); + read_unlock(&hci_cb_list_lock); } static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, @@ -850,13 +850,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, { struct list_head *p; - read_lock_bh(&hci_cb_list_lock); + read_lock(&hci_cb_list_lock); list_for_each(p, &hci_cb_list) { struct hci_cb *cb = list_entry(p, struct hci_cb, list); if (cb->role_switch_cfm) cb->role_switch_cfm(conn, status, role); } - read_unlock_bh(&hci_cb_list_lock); + read_unlock(&hci_cb_list_lock); } int hci_register_cb(struct hci_cb *hcb); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 401d8ea266aa..3db432473ad5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -487,7 +487,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) BT_DBG("%s -> %s", batostr(src), batostr(dst)); - read_lock_bh(&hci_dev_list_lock); + read_lock(&hci_dev_list_lock); list_for_each_entry(d, &hci_dev_list, list) { if (!test_bit(HCI_UP, &d->flags) || test_bit(HCI_RAW, &d->flags)) @@ -512,7 +512,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) if (hdev) hdev = hci_dev_hold(hdev); - read_unlock_bh(&hci_dev_list_lock); + read_unlock(&hci_dev_list_lock); return hdev; } EXPORT_SYMBOL(hci_get_route); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 22c8331cd0d5..4f0ff01dc680 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -844,7 +844,7 @@ int hci_get_dev_list(void __user *arg) dr = dl->dev_req; - read_lock_bh(&hci_dev_list_lock); + read_lock(&hci_dev_list_lock); list_for_each_entry(hdev, &hci_dev_list, list) { if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->flags)) cancel_delayed_work(&hdev->power_off); @@ -858,7 +858,7 @@ int hci_get_dev_list(void __user *arg) if (++n >= dev_num) break; } - read_unlock_bh(&hci_dev_list_lock); + read_unlock(&hci_dev_list_lock); dl->dev_num = n; size = sizeof(*dl) + n * sizeof(*dr); @@ -1458,7 +1458,7 @@ int hci_register_dev(struct hci_dev *hdev) */ id = (hdev->dev_type == HCI_BREDR) ? 0 : 1; - write_lock_bh(&hci_dev_list_lock); + write_lock(&hci_dev_list_lock); /* Find first available device id */ list_for_each(p, &hci_dev_list) { @@ -1528,7 +1528,7 @@ int hci_register_dev(struct hci_dev *hdev) atomic_set(&hdev->promisc, 0); - write_unlock_bh(&hci_dev_list_lock); + write_unlock(&hci_dev_list_lock); hdev->workqueue = alloc_workqueue(hdev->name, WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); @@ -1561,9 +1561,9 @@ int hci_register_dev(struct hci_dev *hdev) err_wqueue: destroy_workqueue(hdev->workqueue); err: - write_lock_bh(&hci_dev_list_lock); + write_lock(&hci_dev_list_lock); list_del(&hdev->list); - write_unlock_bh(&hci_dev_list_lock); + write_unlock(&hci_dev_list_lock); return error; } @@ -1576,9 +1576,9 @@ void hci_unregister_dev(struct hci_dev *hdev) BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); - write_lock_bh(&hci_dev_list_lock); + write_lock(&hci_dev_list_lock); list_del(&hdev->list); - write_unlock_bh(&hci_dev_list_lock); + write_unlock(&hci_dev_list_lock); hci_dev_do_close(hdev); @@ -1830,9 +1830,9 @@ int hci_register_cb(struct hci_cb *cb) { BT_DBG("%p name %s", cb, cb->name); - write_lock_bh(&hci_cb_list_lock); + write_lock(&hci_cb_list_lock); list_add(&cb->list, &hci_cb_list); - write_unlock_bh(&hci_cb_list_lock); + write_unlock(&hci_cb_list_lock); return 0; } @@ -1842,9 +1842,9 @@ int hci_unregister_cb(struct hci_cb *cb) { BT_DBG("%p name %s", cb, cb->name); - write_lock_bh(&hci_cb_list_lock); + write_lock(&hci_cb_list_lock); list_del(&cb->list); - write_unlock_bh(&hci_cb_list_lock); + write_unlock(&hci_cb_list_lock); return 0; } -- cgit v1.2.3 From 18daf1644e634bae951a6e3d4d19d89170209762 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 13 Jan 2012 15:11:30 +0100 Subject: Bluetooth: Fix l2cap conn failures for ssp devices Commit 330605423c fixed l2cap conn establishment for non-ssp remote devices by not setting HCI_CONN_ENCRYPT_PEND every time conn security is tested (which was always returning failure on any subsequent security checks). However, this broke l2cap conn establishment for ssp remote devices when an ACL link was already established at SDP-level security. This fix ensures that encryption must be pending whenever authentication is also pending. Signed-off-by: Peter Hurley Tested-by: Daniel Wagner Acked-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/bluetooth/hci_conn.c') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3db432473ad5..07bc69ed9498 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -635,6 +635,10 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->pend)) { struct hci_cp_auth_requested cp; + + /* encrypt must be pending if auth is also pending */ + set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend); + cp.handle = cpu_to_le16(conn->handle); hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); -- cgit v1.2.3