aboutsummaryrefslogtreecommitdiff
path: root/net/bluetooth
diff options
context:
space:
mode:
authorJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 12:06:44 -0600
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 12:06:44 -0600
commit0bd2af46839ad6262d25714a6ec0365db9d6b98f (patch)
treedcced72d230d69fd0c5816ac6dd03ab84799a93e /net/bluetooth
parente138a5d2356729b8752e88520cc1525fae9794ac (diff)
parentf26b90440cd74c78fe10c9bd5160809704a9627c (diff)
Merge ../scsi-rc-fixes-2.6
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/af_bluetooth.c38
-rw-r--r--net/bluetooth/bnep/core.c4
-rw-r--r--net/bluetooth/bnep/sock.c69
-rw-r--r--net/bluetooth/cmtp/sock.c35
-rw-r--r--net/bluetooth/hci_conn.c6
-rw-r--r--net/bluetooth/hci_event.c34
-rw-r--r--net/bluetooth/hci_sock.c13
-rw-r--r--net/bluetooth/hci_sysfs.c21
-rw-r--r--net/bluetooth/hidp/core.c14
-rw-r--r--net/bluetooth/hidp/sock.c80
-rw-r--r--net/bluetooth/l2cap.c16
-rw-r--r--net/bluetooth/rfcomm/core.c3
-rw-r--r--net/bluetooth/rfcomm/sock.c6
-rw-r--r--net/bluetooth/rfcomm/tty.c7
-rw-r--r--net/bluetooth/sco.c6
15 files changed, 278 insertions, 74 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 305a099b747..67df99e2e5c 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -48,41 +48,56 @@
#define BT_DBG(D...)
#endif
-#define VERSION "2.10"
+#define VERSION "2.11"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
+static DEFINE_RWLOCK(bt_proto_lock);
int bt_sock_register(int proto, struct net_proto_family *ops)
{
+ int err = 0;
+
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
+ write_lock(&bt_proto_lock);
+
if (bt_proto[proto])
- return -EEXIST;
+ err = -EEXIST;
+ else
+ bt_proto[proto] = ops;
- bt_proto[proto] = ops;
- return 0;
+ write_unlock(&bt_proto_lock);
+
+ return err;
}
EXPORT_SYMBOL(bt_sock_register);
int bt_sock_unregister(int proto)
{
+ int err = 0;
+
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
+ write_lock(&bt_proto_lock);
+
if (!bt_proto[proto])
- return -ENOENT;
+ err = -ENOENT;
+ else
+ bt_proto[proto] = NULL;
- bt_proto[proto] = NULL;
- return 0;
+ write_unlock(&bt_proto_lock);
+
+ return err;
}
EXPORT_SYMBOL(bt_sock_unregister);
static int bt_sock_create(struct socket *sock, int proto)
{
- int err = 0;
+ int err;
if (proto < 0 || proto >= BT_MAX_PROTO)
return -EINVAL;
@@ -92,11 +107,18 @@ static int bt_sock_create(struct socket *sock, int proto)
request_module("bt-proto-%d", proto);
}
#endif
+
err = -EPROTONOSUPPORT;
+
+ read_lock(&bt_proto_lock);
+
if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
err = bt_proto[proto]->create(sock, proto);
module_put(bt_proto[proto]->owner);
}
+
+ read_unlock(&bt_proto_lock);
+
return err;
}
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 2312d050eee..4d3424c2421 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -528,12 +528,10 @@ static struct device *bnep_get_device(struct bnep_session *session)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
- if (!conn)
- return NULL;
hci_dev_put(hdev);
- return &conn->dev;
+ return conn ? &conn->dev : NULL;
}
int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 28c55835422..5563db1bf52 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -43,6 +43,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
+#include <linux/compat.h>
#include <net/sock.h>
#include <asm/system.h>
@@ -146,24 +147,56 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return 0;
}
+#ifdef CONFIG_COMPAT
+static int bnep_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == BNEPGETCONNLIST) {
+ struct bnep_connlist_req cl;
+ uint32_t uci;
+ int err;
+
+ if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+ get_user(uci, (u32 __user *) (arg + 4)))
+ return -EFAULT;
+
+ cl.ci = compat_ptr(uci);
+
+ if (cl.cnum <= 0)
+ return -EINVAL;
+
+ err = bnep_get_connlist(&cl);
+
+ if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+ err = -EFAULT;
+
+ return err;
+ }
+
+ return bnep_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
static const struct proto_ops bnep_sock_ops = {
- .family = PF_BLUETOOTH,
- .owner = THIS_MODULE,
- .release = bnep_sock_release,
- .ioctl = bnep_sock_ioctl,
- .bind = sock_no_bind,
- .getname = sock_no_getname,
- .sendmsg = sock_no_sendmsg,
- .recvmsg = sock_no_recvmsg,
- .poll = sock_no_poll,
- .listen = sock_no_listen,
- .shutdown = sock_no_shutdown,
- .setsockopt = sock_no_setsockopt,
- .getsockopt = sock_no_getsockopt,
- .connect = sock_no_connect,
- .socketpair = sock_no_socketpair,
- .accept = sock_no_accept,
- .mmap = sock_no_mmap
+ .family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
+ .release = bnep_sock_release,
+ .ioctl = bnep_sock_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = bnep_sock_compat_ioctl,
+#endif
+ .bind = sock_no_bind,
+ .getname = sock_no_getname,
+ .sendmsg = sock_no_sendmsg,
+ .recvmsg = sock_no_recvmsg,
+ .poll = sock_no_poll,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .setsockopt = sock_no_setsockopt,
+ .getsockopt = sock_no_getsockopt,
+ .connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = sock_no_accept,
+ .mmap = sock_no_mmap
};
static struct proto bnep_proto = {
@@ -181,7 +214,7 @@ static int bnep_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c
index 10ad7fd91d8..53295d33dc5 100644
--- a/net/bluetooth/cmtp/sock.c
+++ b/net/bluetooth/cmtp/sock.c
@@ -34,6 +34,7 @@
#include <linux/socket.h>
#include <linux/ioctl.h>
#include <linux/file.h>
+#include <linux/compat.h>
#include <net/sock.h>
#include <linux/isdn/capilli.h>
@@ -137,11 +138,43 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+static int cmtp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == CMTPGETCONNLIST) {
+ struct cmtp_connlist_req cl;
+ uint32_t uci;
+ int err;
+
+ if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+ get_user(uci, (u32 __user *) (arg + 4)))
+ return -EFAULT;
+
+ cl.ci = compat_ptr(uci);
+
+ if (cl.cnum <= 0)
+ return -EINVAL;
+
+ err = cmtp_get_connlist(&cl);
+
+ if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+ err = -EFAULT;
+
+ return err;
+ }
+
+ return cmtp_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
static const struct proto_ops cmtp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = cmtp_sock_release,
.ioctl = cmtp_sock_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = cmtp_sock_compat_ioctl,
+#endif
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
@@ -172,7 +205,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 90e3a285a17..6cd5711fa28 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -51,7 +51,7 @@
#define BT_DBG(D...)
#endif
-static void hci_acl_connect(struct hci_conn *conn)
+void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct inquiry_entry *ie;
@@ -63,6 +63,8 @@ static void hci_acl_connect(struct hci_conn *conn)
conn->out = 1;
conn->link_mode = HCI_LM_MASTER;
+ conn->attempt++;
+
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
@@ -80,7 +82,7 @@ static void hci_acl_connect(struct hci_conn *conn)
cp.role_switch = 0x01;
else
cp.role_switch = 0x00;
-
+
hci_send_cmd(hdev, OGF_LINK_CTL, OCF_CREATE_CONN, sizeof(cp), &cp);
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d43d0c89097..bb94e6da223 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -57,6 +57,7 @@
static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb)
{
__u8 status;
+ struct hci_conn *pend;
BT_DBG("%s ocf 0x%x", hdev->name, ocf);
@@ -71,6 +72,15 @@ static void hci_cc_link_ctl(struct hci_dev *hdev, __u16 ocf, struct sk_buff *skb
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, status);
}
+
+ hci_dev_lock(hdev);
+
+ pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (pend)
+ hci_acl_connect(pend);
+
+ hci_dev_unlock(hdev);
+
break;
default:
@@ -414,9 +424,12 @@ static inline void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
if (status) {
if (conn && conn->state == BT_CONNECT) {
- conn->state = BT_CLOSED;
- hci_proto_connect_cfm(conn, status);
- hci_conn_del(conn);
+ if (status != 0x0c || conn->attempt > 2) {
+ conn->state = BT_CLOSED;
+ hci_proto_connect_cfm(conn, status);
+ hci_conn_del(conn);
+ } else
+ conn->state = BT_CONNECT2;
}
} else {
if (!conn) {
@@ -562,11 +575,20 @@ static void hci_cs_info_param(struct hci_dev *hdev, __u16 ocf, __u8 status)
static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
+ struct hci_conn *pend;
BT_DBG("%s status %d", hdev->name, status);
clear_bit(HCI_INQUIRY, &hdev->flags);
hci_req_complete(hdev, status);
+
+ hci_dev_lock(hdev);
+
+ pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (pend)
+ hci_acl_connect(pend);
+
+ hci_dev_unlock(hdev);
}
/* Inquiry Result */
@@ -728,7 +750,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_conn_complete *ev = (struct hci_ev_conn_complete *) skb->data;
- struct hci_conn *conn;
+ struct hci_conn *conn, *pend;
BT_DBG("%s", hdev->name);
@@ -801,6 +823,10 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (ev->status)
hci_conn_del(conn);
+ pend = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+ if (pend)
+ hci_acl_connect(pend);
+
hci_dev_unlock(hdev);
}
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 1a35d343e08..711a085eca5 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -120,10 +120,13 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (!hci_test_bit(evt, &flt->event_mask))
continue;
- if (flt->opcode && ((evt == HCI_EV_CMD_COMPLETE &&
- flt->opcode != *(__u16 *)(skb->data + 3)) ||
- (evt == HCI_EV_CMD_STATUS &&
- flt->opcode != *(__u16 *)(skb->data + 4))))
+ if (flt->opcode &&
+ ((evt == HCI_EV_CMD_COMPLETE &&
+ flt->opcode !=
+ get_unaligned((__u16 *)(skb->data + 3))) ||
+ (evt == HCI_EV_CMD_STATUS &&
+ flt->opcode !=
+ get_unaligned((__u16 *)(skb->data + 4)))))
continue;
}
@@ -618,7 +621,7 @@ static int hci_sock_create(struct socket *sock, int protocol)
sock->ops = &hci_sock_ops;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 989b22d9042..3eeeb7a86e7 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -242,10 +242,14 @@ static void add_conn(void *data)
struct hci_conn *conn = data;
int i;
- device_register(&conn->dev);
+ if (device_register(&conn->dev) < 0) {
+ BT_ERR("Failed to register connection device");
+ return;
+ }
for (i = 0; conn_attrs[i]; i++)
- device_create_file(&conn->dev, conn_attrs[i]);
+ if (device_create_file(&conn->dev, conn_attrs[i]) < 0)
+ BT_ERR("Failed to create connection attribute");
}
void hci_conn_add_sysfs(struct hci_conn *conn)
@@ -255,7 +259,9 @@ void hci_conn_add_sysfs(struct hci_conn *conn)
BT_DBG("conn %p", conn);
- conn->dev.parent = &hdev->dev;
+ conn->dev.bus = &bt_bus;
+ conn->dev.parent = &hdev->dev;
+
conn->dev.release = bt_release;
snprintf(conn->dev.bus_id, BUS_ID_SIZE,
@@ -295,11 +301,7 @@ int hci_register_sysfs(struct hci_dev *hdev)
BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type);
dev->class = bt_class;
-
- if (hdev->parent)
- dev->parent = hdev->parent;
- else
- dev->parent = &bt_platform->dev;
+ dev->parent = hdev->parent;
strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE);
@@ -312,7 +314,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
return err;
for (i = 0; bt_attrs[i]; i++)
- device_create_file(dev, bt_attrs[i]);
+ if (device_create_file(dev, bt_attrs[i]) < 0)
+ BT_ERR("Failed to create device attribute");
return 0;
}
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 03b5dadb495..66782010f82 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -507,14 +507,12 @@ static int hidp_session(void *arg)
hidp_del_timer(session);
- if (intr_sk->sk_state != BT_CONNECTED)
- wait_event_timeout(*(ctrl_sk->sk_sleep), (ctrl_sk->sk_state == BT_CLOSED), HZ);
-
- fput(session->ctrl_sock->file);
+ fput(session->intr_sock->file);
- wait_event_timeout(*(intr_sk->sk_sleep), (intr_sk->sk_state == BT_CLOSED), HZ);
+ wait_event_timeout(*(ctrl_sk->sk_sleep),
+ (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
- fput(session->intr_sock->file);
+ fput(session->ctrl_sock->file);
__hidp_unlink_session(session);
@@ -541,12 +539,10 @@ static struct device *hidp_get_device(struct hidp_session *session)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
- if (!conn)
- return NULL;
hci_dev_put(hdev);
- return &conn->dev;
+ return conn ? &conn->dev : NULL;
}
static inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c
index 099646e4e2e..407fba43c1b 100644
--- a/net/bluetooth/hidp/sock.c
+++ b/net/bluetooth/hidp/sock.c
@@ -35,6 +35,7 @@
#include <linux/ioctl.h>
#include <linux/file.h>
#include <linux/init.h>
+#include <linux/compat.h>
#include <net/sock.h>
#include "hidp.h"
@@ -143,11 +144,88 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
return -EINVAL;
}
+#ifdef CONFIG_COMPAT
+struct compat_hidp_connadd_req {
+ int ctrl_sock; // Connected control socket
+ int intr_sock; // Connteted interrupt socket
+ __u16 parser;
+ __u16 rd_size;
+ compat_uptr_t rd_data;
+ __u8 country;
+ __u8 subclass;
+ __u16 vendor;
+ __u16 product;
+ __u16 version;
+ __u32 flags;
+ __u32 idle_to;
+ char name[128];
+};
+
+static int hidp_sock_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+ if (cmd == HIDPGETCONNLIST) {
+ struct hidp_connlist_req cl;
+ uint32_t uci;
+ int err;
+
+ if (get_user(cl.cnum, (uint32_t __user *) arg) ||
+ get_user(uci, (u32 __user *) (arg + 4)))
+ return -EFAULT;
+
+ cl.ci = compat_ptr(uci);
+
+ if (cl.cnum <= 0)
+ return -EINVAL;
+
+ err = hidp_get_connlist(&cl);
+
+ if (!err && put_user(cl.cnum, (uint32_t __user *) arg))
+ err = -EFAULT;
+
+ return err;
+ } else if (cmd == HIDPCONNADD) {
+ struct compat_hidp_connadd_req ca;
+ struct hidp_connadd_req __user *uca;
+
+ uca = compat_alloc_user_space(sizeof(*uca));
+
+ if (copy_from_user(&ca, (void *) arg, sizeof(ca)))
+ return -EFAULT;
+
+ if (put_user(ca.ctrl_sock, &uca->ctrl_sock) ||
+ put_user(ca.intr_sock, &uca->intr_sock) ||
+ put_user(ca.parser, &uca->parser) ||
+ put_user(ca.rd_size, &uca->parser) ||
+ put_user(compat_ptr(ca.rd_data), &uca->rd_data) ||
+ put_user(ca.country, &uca->country) ||
+ put_user(ca.subclass, &uca->subclass) ||
+ put_user(ca.vendor, &uca->vendor) ||
+ put_user(ca.product, &uca->product) ||
+ put_user(ca.version, &uca->version) ||
+ put_user(ca.flags, &uca->flags) ||
+ put_user(ca.idle_to, &uca->idle_to) ||
+ copy_to_user(&uca->name[0], &ca.name[0], 128))
+ return -EFAULT;
+
+ arg = (unsigned long) uca;
+
+ /* Fall through. We don't actually write back any _changes_
+ to the structure anyway, so there's no need to copy back
+ into the original compat version */
+ }
+
+ return hidp_sock_ioctl(sock, cmd, arg);
+}
+#endif
+
static const struct proto_ops hidp_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.release = hidp_sock_release,
.ioctl = hidp_sock_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = hidp_sock_compat_ioctl,
+#endif
.bind = sock_no_bind,
.getname = sock_no_getname,
.sendmsg = sock_no_sendmsg,
@@ -178,7 +256,7 @@ static int hidp_sock_create(struct socket *sock, int protocol)
if (sock->type != SOCK_RAW)
return -ESOCKTNOSUPPORT;
- sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
+ sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
if (!sk)
return -ENOMEM;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index d56f60b392a..bbf78e6a7bc 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -559,7 +559,7 @@ static int l2cap_sock_create(struct socket *sock, int protocol)
sock->ops = &l2cap_sock_ops;
- sk = l2cap_sock_alloc(sock, protocol, GFP_KERNEL);
+ sk = l2cap_sock_alloc(sock, protocol, GFP_ATOMIC);
if (!sk)
return -ENOMEM;
@@ -1353,12 +1353,12 @@ static inline int l2cap_conf_output(struct sock *sk, void **ptr)
/* Configure output options and let the other side know
* which ones we don't like. */
- if (pi->conf_mtu < pi->omtu) {
- l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ if (pi->conf_mtu < pi->omtu)
result = L2CAP_CONF_UNACCEPT;
- } else {
+ else
pi->omtu = pi->conf_mtu;
- }
+
+ l2cap_add_conf_opt(ptr, L2CAP_CONF_MTU, 2, pi->omtu);
BT_DBG("sk %p result %d", sk, result);
return result;
@@ -1533,6 +1533,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid)))
return -ENOENT;
+ if (sk->sk_state == BT_DISCONN)
+ goto unlock;
+
l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req));
if (flags & 0x0001) {
@@ -2216,7 +2219,8 @@ static int __init l2cap_init(void)
goto error;
}
- class_create_file(bt_class, &class_attr_l2cap);
+ if (class_create_file(bt_class, &class_attr_l2cap) < 0)
+ BT_ERR("Failed to create L2CAP info file");
BT_INFO("L2CAP ver %s", VERSION);
BT_INFO("L2CAP socket layer initialized");
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 468df3b953f..ddc4e9d5963 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2058,7 +2058,8 @@ static int __init rfcomm_init(void)
kernel_thread(rfcomm_run, NULL, CLONE_KERNEL);
- class_create_file(bt_class, &class_attr_rfcomm_dlc);
+ if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
+ BT_ERR("Failed to create RFCOMM info file");
rfcomm_init_sockets();
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 220fee04e7f..544d65b7baa 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -336,7 +336,8 @@ static int rfcomm_sock_create(struct socket *sock, int protocol)
sock->ops = &rfcomm_sock_ops;
- if (!(sk = rfcomm_sock_alloc(sock, protocol, GFP_KERNEL)))
+ sk = rfcomm_sock_alloc(sock, protocol, GFP_ATOMIC);
+ if (!sk)
return -ENOMEM;
rfcomm_sock_init(sk, NULL);
@@ -944,7 +945,8 @@ int __init rfcomm_init_sockets(void)
if (err < 0)
goto error;
- class_create_file(bt_class, &class_attr_rfcomm);
+ if (class_create_file(bt_class, &class_attr_rfcomm) < 0)
+ BT_ERR("Failed to create RFCOMM info file");
BT_INFO("RFCOMM socket layer initialized");
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 1958ad1b854..1fb5d42f37a 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -172,12 +172,10 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
return NULL;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
- if (!conn)
- return NULL;
hci_dev_put(hdev);
- return &conn->dev;
+ return conn ? &conn->dev : NULL;
}
static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
@@ -767,6 +765,9 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct termios *old)
BT_DBG("tty %p termios %p", tty, old);
+ if (!dev || !dev->dlc || !dev->dlc->session)
+ return;
+
/* Handle turning off CRTSCTS */
if ((old->c_cflag & CRTSCTS) && !(new->c_cflag & CRTSCTS))
BT_DBG("Turning off CRTSCTS unsupported");
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 7714a2ec385..5d13d4f3175 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -452,7 +452,8 @@ static int sco_sock_create(struct socket *sock, int protocol)
sock->ops = &sco_sock_ops;
- if (!(sk = sco_sock_alloc(sock, protocol, GFP_KERNEL)))
+ sk = sco_sock_alloc(sock, protocol, GFP_ATOMIC);
+ if (!sk)
return -ENOMEM;
sco_sock_init(sk, NULL);
@@ -967,7 +968,8 @@ static int __init sco_init(void)
goto error;
}
- class_create_file(bt_class, &class_attr_sco);
+ if (class_create_file(bt_class, &class_attr_sco) < 0)
+ BT_ERR("Failed to create SCO info file");
BT_INFO("SCO (Voice Link) ver %s", VERSION);
BT_INFO("SCO socket layer initialized");