diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index a04f8463ac7e..847e9e6df08b 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -53,6 +53,8 @@ #define SOL_SCO 17 #define SOL_RFCOMM 18 +#define BT_DEFER_SETUP 7 + #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg) #define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg) #define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg) @@ -108,6 +110,7 @@ struct bt_sock { bdaddr_t dst; struct list_head accept_q; struct sock *parent; + u32 defer_setup; }; struct bt_sock_list { diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 744ed3f07ef3..7c0031ff8cfb 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -217,7 +217,8 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) continue; } - if (sk->sk_state == BT_CONNECTED || !newsock) { + if (sk->sk_state == BT_CONNECTED || !newsock || + bt_sk(parent)->defer_setup) { bt_accept_unlink(sk); if (newsock) sock_graft(sk, newsock); @@ -232,7 +233,7 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) EXPORT_SYMBOL(bt_accept_dequeue); int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t len, int flags) + struct msghdr *msg, size_t len, int flags) { int noblock = flags & MSG_DONTWAIT; struct sock *sk = sock->sk; @@ -275,6 +276,9 @@ static inline unsigned int bt_accept_poll(struct sock *parent) struct list_head *p, *n; struct sock *sk; + if (bt_sk(parent)->defer_setup) + return POLLIN | POLLRDNORM; + list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); if (sk->sk_state == BT_CONNECTED)