From 0d861d8b8edd139a9b291cb262d08dec8dc3922d Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Sat, 1 May 2010 16:15:35 -0300 Subject: Bluetooth: Make hci_send_sco() void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It also removes an unneeded check for the MTU. The check is done before on sco_send_frame() Signed-off-by: Gustavo F. Padovan Reviewed-by: João Paulo Rechi Vita Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/net/bluetooth/hci_core.h') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ce3c99e5fa25..9830a88f487e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -637,7 +637,7 @@ int hci_unregister_notifier(struct notifier_block *nb); int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); -int hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); +void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); -- cgit v1.2.3 From 9a9c6a34416b3743c09c00f3d6708d9df3c21629 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Sat, 1 May 2010 16:15:43 -0300 Subject: Bluetooth: Make hci_send_acl() void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hci_send_acl can't fail, so we can make it void. This patch changes that and all the funcions that use hci_send_acl(). That change exposed a bug on sending connectionless data. We were not reporting the lenght send back to the user space. Signed-off-by: Gustavo F. Padovan Reviewed-by: João Paulo Rechi Vita Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 4 +-- net/bluetooth/l2cap.c | 73 +++++++++++++++------------------------- 3 files changed, 30 insertions(+), 49 deletions(-) (limited to 'include/net/bluetooth/hci_core.h') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9830a88f487e..4511df2a0d7f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -636,7 +636,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); -int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); +void hci_send_acl(struct hci_conn *conn, 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/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 1c9aef97f519..904f1e8a7a3b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1260,7 +1260,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) hdr->dlen = cpu_to_le16(len); } -int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) +void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) { struct hci_dev *hdev = conn->hdev; struct sk_buff *list; @@ -1303,7 +1303,7 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) tasklet_schedule(&hdev->tx_task); - return 0; + return; } EXPORT_SYMBOL(hci_send_acl); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 6b08f4d7c873..7e74d5be16e3 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -330,19 +330,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn) return id; } -static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) +static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) { struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); BT_DBG("code 0x%2.2x", code); if (!skb) - return -ENOMEM; + return; - return hci_send_acl(conn->hcon, skb, 0); + hci_send_acl(conn->hcon, skb, 0); } -static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) { struct sk_buff *skb; struct l2cap_hdr *lh; @@ -369,7 +369,7 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) skb = bt_skb_alloc(count, GFP_ATOMIC); if (!skb) - return -ENOMEM; + return; lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE); @@ -381,10 +381,10 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control) put_unaligned_le16(fcs, skb_put(skb, 2)); } - return hci_send_acl(pi->conn->hcon, skb, 0); + hci_send_acl(pi->conn->hcon, skb, 0); } -static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) +static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) { if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) control |= L2CAP_SUPER_RCV_NOT_READY; @@ -393,7 +393,7 @@ static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control) control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT; - return l2cap_send_sframe(pi, control); + l2cap_send_sframe(pi, control); } static void l2cap_do_start(struct sock *sk) @@ -1289,18 +1289,13 @@ static void l2cap_drop_acked_frames(struct sock *sk) return; } -static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb) +static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb) { struct l2cap_pinfo *pi = l2cap_pi(sk); - int err; BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len); - err = hci_send_acl(pi->conn->hcon, skb, 0); - if (err < 0) - kfree_skb(skb); - - return err; + hci_send_acl(pi->conn->hcon, skb, 0); } static int l2cap_streaming_send(struct sock *sk) @@ -1308,7 +1303,6 @@ static int l2cap_streaming_send(struct sock *sk) struct sk_buff *skb, *tx_skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - int err; while ((skb = sk->sk_send_head)) { tx_skb = skb_clone(skb, GFP_ATOMIC); @@ -1322,11 +1316,7 @@ static int l2cap_streaming_send(struct sock *sk) put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } - err = l2cap_do_send(sk, tx_skb); - if (err < 0) { - l2cap_send_disconn_req(pi->conn, sk); - return err; - } + l2cap_do_send(sk, tx_skb); pi->next_tx_seq = (pi->next_tx_seq + 1) % 64; @@ -1346,7 +1336,6 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) struct l2cap_pinfo *pi = l2cap_pi(sk); struct sk_buff *skb, *tx_skb; u16 control, fcs; - int err; skb = skb_peek(TX_QUEUE(sk)); do { @@ -1375,11 +1364,7 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq) put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2); } - err = l2cap_do_send(sk, tx_skb); - if (err < 0) { - l2cap_send_disconn_req(pi->conn, sk); - return err; - } + l2cap_do_send(sk, tx_skb); break; } while(1); return 0; @@ -1390,7 +1375,7 @@ static int l2cap_ertm_send(struct sock *sk) struct sk_buff *skb, *tx_skb; struct l2cap_pinfo *pi = l2cap_pi(sk); u16 control, fcs; - int err, nsent = 0; + int nsent = 0; if (pi->conn_state & L2CAP_CONN_WAIT_F) return 0; @@ -1423,11 +1408,8 @@ static int l2cap_ertm_send(struct sock *sk) put_unaligned_le16(fcs, skb->data + tx_skb->len - 2); } - err = l2cap_do_send(sk, tx_skb); - if (err < 0) { - l2cap_send_disconn_req(pi->conn, sk); - return err; - } + l2cap_do_send(sk, tx_skb); + __mod_retrans_timer(); bt_cb(skb)->tx_seq = pi->next_tx_seq; @@ -1447,7 +1429,7 @@ static int l2cap_ertm_send(struct sock *sk) return nsent; } -static int l2cap_send_ack(struct l2cap_pinfo *pi) +static void l2cap_send_ack(struct l2cap_pinfo *pi) { struct sock *sk = (struct sock *)pi; u16 control = 0; @@ -1456,15 +1438,15 @@ static int l2cap_send_ack(struct l2cap_pinfo *pi) if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) { control |= L2CAP_SUPER_RCV_NOT_READY; - return l2cap_send_sframe(pi, control); + l2cap_send_sframe(pi, control); + return; } else if (l2cap_ertm_send(sk) == 0) { control |= L2CAP_SUPER_RCV_READY; - return l2cap_send_sframe(pi, control); + l2cap_send_sframe(pi, control); } - return 0; } -static int l2cap_send_srejtail(struct sock *sk) +static void l2cap_send_srejtail(struct sock *sk) { struct srej_list *tail; u16 control; @@ -1476,8 +1458,6 @@ static int l2cap_send_srejtail(struct sock *sk) control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT; l2cap_send_sframe(l2cap_pi(sk), control); - - return 0; } static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb) @@ -1687,10 +1667,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms /* Connectionless channel */ if (sk->sk_type == SOCK_DGRAM) { skb = l2cap_create_connless_pdu(sk, msg, len); - if (IS_ERR(skb)) + if (IS_ERR(skb)) { err = PTR_ERR(skb); - else - err = l2cap_do_send(sk, skb); + } else { + l2cap_do_send(sk, skb); + err = len; + } goto done; } @@ -1709,9 +1691,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms goto done; } - err = l2cap_do_send(sk, skb); - if (!err) - err = len; + l2cap_do_send(sk, skb); + err = len; break; case L2CAP_MODE_ERTM: -- cgit v1.2.3 From f48fd9c8cd746fdb055a97249a209c77dca0f710 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Mar 2010 15:20:04 +0100 Subject: Bluetooth: Create per controller workqueue Instead of having a global workqueue for all controllers, it makes more sense to have a workqueue per controller. Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 14 ++++++++++++++ net/bluetooth/hci_sysfs.c | 16 +++------------- 3 files changed, 19 insertions(+), 13 deletions(-) (limited to 'include/net/bluetooth/hci_core.h') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4511df2a0d7f..e42f6ed5421c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -107,6 +107,8 @@ struct hci_dev { unsigned long acl_last_tx; unsigned long sco_last_tx; + struct workqueue_struct *workqueue; + struct tasklet_struct cmd_task; struct tasklet_struct rx_task; struct tasklet_struct tx_task; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 904f1e8a7a3b..5e83f8e0877a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -928,6 +929,10 @@ int hci_register_dev(struct hci_dev *hdev) write_unlock_bh(&hci_dev_list_lock); + hdev->workqueue = create_singlethread_workqueue(hdev->name); + if (!hdev->workqueue) + goto nomem; + hci_register_sysfs(hdev); hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, @@ -942,6 +947,13 @@ int hci_register_dev(struct hci_dev *hdev) hci_notify(hdev, HCI_DEV_REG); return id; + +nomem: + write_lock_bh(&hci_dev_list_lock); + list_del(&hdev->list); + write_unlock_bh(&hci_dev_list_lock); + + return -ENOMEM; } EXPORT_SYMBOL(hci_register_dev); @@ -970,6 +982,8 @@ int hci_unregister_dev(struct hci_dev *hdev) hci_unregister_sysfs(hdev); + destroy_workqueue(hdev->workqueue); + __hci_dev_put(hdev); return 0; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 0e8e1a59856c..a978449ab04d 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -14,8 +14,6 @@ static struct class *bt_class; struct dentry *bt_debugfs = NULL; EXPORT_SYMBOL_GPL(bt_debugfs); -static struct workqueue_struct *bt_workq; - static inline char *link_typetostr(int type) { switch (type) { @@ -161,14 +159,14 @@ void hci_conn_add_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - queue_work(bt_workq, &conn->work_add); + queue_work(conn->hdev->workqueue, &conn->work_add); } void hci_conn_del_sysfs(struct hci_conn *conn) { BT_DBG("conn %p", conn); - queue_work(bt_workq, &conn->work_del); + queue_work(conn->hdev->workqueue, &conn->work_del); } static inline char *host_bustostr(int bus) @@ -487,17 +485,11 @@ void hci_unregister_sysfs(struct hci_dev *hdev) int __init bt_sysfs_init(void) { - bt_workq = create_singlethread_workqueue("bluetooth"); - if (!bt_workq) - return -ENOMEM; - bt_debugfs = debugfs_create_dir("bluetooth", NULL); bt_class = class_create(THIS_MODULE, "bluetooth"); - if (IS_ERR(bt_class)) { - destroy_workqueue(bt_workq); + if (IS_ERR(bt_class)) return PTR_ERR(bt_class); - } return 0; } @@ -507,6 +499,4 @@ void bt_sysfs_cleanup(void) class_destroy(bt_class); debugfs_remove_recursive(bt_debugfs); - - destroy_workqueue(bt_workq); } -- cgit v1.2.3