diff options
| author | Steve French <sfrench@us.ibm.com> | 2007-07-18 20:38:57 -0400 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2007-07-18 20:38:57 -0400 |
| commit | 1ff8392c32a2645d2665ca779ecb91bb29361c13 (patch) | |
| tree | 860b95e9a499ade4060848740fc6ce1fbb4e4e8d /net/bluetooth | |
| parent | 70b315b0dd3879cb3ab8aadffb14f10b2d19b9c3 (diff) | |
| parent | 5bae7ac9feba925fd0099057f6b23d7be80b7b41 (diff) | |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
fs/cifs/export.c
Diffstat (limited to 'net/bluetooth')
| -rw-r--r-- | net/bluetooth/bnep/core.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/cmtp/core.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/hci_conn.c | 51 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 100 | ||||
| -rw-r--r-- | net/bluetooth/hci_event.c | 29 | ||||
| -rw-r--r-- | net/bluetooth/hidp/core.c | 20 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/core.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/tty.c | 34 |
8 files changed, 182 insertions, 58 deletions
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 1c8f4a0c5f43..1f78c3e336d8 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/signal.h> | 36 | #include <linux/signal.h> |
| 37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 38 | #include <linux/wait.h> | 38 | #include <linux/wait.h> |
| 39 | #include <linux/freezer.h> | ||
| 39 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
| 40 | #include <linux/net.h> | 41 | #include <linux/net.h> |
| 41 | #include <net/sock.h> | 42 | #include <net/sock.h> |
| @@ -474,7 +475,6 @@ static int bnep_session(void *arg) | |||
| 474 | 475 | ||
| 475 | daemonize("kbnepd %s", dev->name); | 476 | daemonize("kbnepd %s", dev->name); |
| 476 | set_user_nice(current, -15); | 477 | set_user_nice(current, -15); |
| 477 | current->flags |= PF_NOFREEZE; | ||
| 478 | 478 | ||
| 479 | init_waitqueue_entry(&wait, current); | 479 | init_waitqueue_entry(&wait, current); |
| 480 | add_wait_queue(sk->sk_sleep, &wait); | 480 | add_wait_queue(sk->sk_sleep, &wait); |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 66bef1ccee2a..ca60a4517fd3 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/poll.h> | 30 | #include <linux/poll.h> |
| 31 | #include <linux/fcntl.h> | 31 | #include <linux/fcntl.h> |
| 32 | #include <linux/freezer.h> | ||
| 32 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
| 33 | #include <linux/socket.h> | 34 | #include <linux/socket.h> |
| 34 | #include <linux/ioctl.h> | 35 | #include <linux/ioctl.h> |
| @@ -287,7 +288,6 @@ static int cmtp_session(void *arg) | |||
| 287 | 288 | ||
| 288 | daemonize("kcmtpd_ctr_%d", session->num); | 289 | daemonize("kcmtpd_ctr_%d", session->num); |
| 289 | set_user_nice(current, -15); | 290 | set_user_nice(current, -15); |
| 290 | current->flags |= PF_NOFREEZE; | ||
| 291 | 291 | ||
| 292 | init_waitqueue_entry(&wait, current); | 292 | init_waitqueue_entry(&wait, current); |
| 293 | add_wait_queue(sk->sk_sleep, &wait); | 293 | add_wait_queue(sk->sk_sleep, &wait); |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 63980bd6b5f2..5fdfc9a67d39 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
| @@ -123,8 +123,8 @@ void hci_add_sco(struct hci_conn *conn, __u16 handle) | |||
| 123 | conn->state = BT_CONNECT; | 123 | conn->state = BT_CONNECT; |
| 124 | conn->out = 1; | 124 | conn->out = 1; |
| 125 | 125 | ||
| 126 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | ||
| 127 | cp.handle = cpu_to_le16(handle); | 126 | cp.handle = cpu_to_le16(handle); |
| 127 | cp.pkt_type = cpu_to_le16(hdev->pkt_type & SCO_PTYPE_MASK); | ||
| 128 | 128 | ||
| 129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); | 129 | hci_send_cmd(hdev, OGF_LINK_CTL, OCF_ADD_SCO, sizeof(cp), &cp); |
| 130 | } | 130 | } |
| @@ -220,19 +220,19 @@ int hci_conn_del(struct hci_conn *conn) | |||
| 220 | 220 | ||
| 221 | del_timer(&conn->disc_timer); | 221 | del_timer(&conn->disc_timer); |
| 222 | 222 | ||
| 223 | if (conn->type == SCO_LINK) { | 223 | if (conn->type == ACL_LINK) { |
| 224 | struct hci_conn *acl = conn->link; | ||
| 225 | if (acl) { | ||
| 226 | acl->link = NULL; | ||
| 227 | hci_conn_put(acl); | ||
| 228 | } | ||
| 229 | } else { | ||
| 230 | struct hci_conn *sco = conn->link; | 224 | struct hci_conn *sco = conn->link; |
| 231 | if (sco) | 225 | if (sco) |
| 232 | sco->link = NULL; | 226 | sco->link = NULL; |
| 233 | 227 | ||
| 234 | /* Unacked frames */ | 228 | /* Unacked frames */ |
| 235 | hdev->acl_cnt += conn->sent; | 229 | hdev->acl_cnt += conn->sent; |
| 230 | } else { | ||
| 231 | struct hci_conn *acl = conn->link; | ||
| 232 | if (acl) { | ||
| 233 | acl->link = NULL; | ||
| 234 | hci_conn_put(acl); | ||
| 235 | } | ||
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | tasklet_disable(&hdev->tx_task); | 238 | tasklet_disable(&hdev->tx_task); |
| @@ -297,9 +297,10 @@ EXPORT_SYMBOL(hci_get_route); | |||
| 297 | 297 | ||
| 298 | /* Create SCO or ACL connection. | 298 | /* Create SCO or ACL connection. |
| 299 | * Device _must_ be locked */ | 299 | * Device _must_ be locked */ |
| 300 | struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | 300 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) |
| 301 | { | 301 | { |
| 302 | struct hci_conn *acl; | 302 | struct hci_conn *acl; |
| 303 | struct hci_conn *sco; | ||
| 303 | 304 | ||
| 304 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 305 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); |
| 305 | 306 | ||
| @@ -313,28 +314,26 @@ struct hci_conn * hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
| 313 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) | 314 | if (acl->state == BT_OPEN || acl->state == BT_CLOSED) |
| 314 | hci_acl_connect(acl); | 315 | hci_acl_connect(acl); |
| 315 | 316 | ||
| 316 | if (type == SCO_LINK) { | 317 | if (type == ACL_LINK) |
| 317 | struct hci_conn *sco; | 318 | return acl; |
| 318 | 319 | ||
| 319 | if (!(sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst))) { | 320 | if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { |
| 320 | if (!(sco = hci_conn_add(hdev, SCO_LINK, dst))) { | 321 | if (!(sco = hci_conn_add(hdev, type, dst))) { |
| 321 | hci_conn_put(acl); | 322 | hci_conn_put(acl); |
| 322 | return NULL; | 323 | return NULL; |
| 323 | } | ||
| 324 | } | 324 | } |
| 325 | acl->link = sco; | 325 | } |
| 326 | sco->link = acl; | ||
| 327 | 326 | ||
| 328 | hci_conn_hold(sco); | 327 | acl->link = sco; |
| 328 | sco->link = acl; | ||
| 329 | 329 | ||
| 330 | if (acl->state == BT_CONNECTED && | 330 | hci_conn_hold(sco); |
| 331 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) | ||
| 332 | hci_add_sco(sco, acl->handle); | ||
| 333 | 331 | ||
| 334 | return sco; | 332 | if (acl->state == BT_CONNECTED && |
| 335 | } else { | 333 | (sco->state == BT_OPEN || sco->state == BT_CLOSED)) |
| 336 | return acl; | 334 | hci_add_sco(sco, acl->handle); |
| 337 | } | 335 | |
| 336 | return sco; | ||
| 338 | } | 337 | } |
| 339 | EXPORT_SYMBOL(hci_connect); | 338 | EXPORT_SYMBOL(hci_connect); |
| 340 | 339 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aa4b56a8c3ea..f6d867e0179f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -826,7 +826,7 @@ EXPORT_SYMBOL(hci_free_dev); | |||
| 826 | int hci_register_dev(struct hci_dev *hdev) | 826 | int hci_register_dev(struct hci_dev *hdev) |
| 827 | { | 827 | { |
| 828 | struct list_head *head = &hci_dev_list, *p; | 828 | struct list_head *head = &hci_dev_list, *p; |
| 829 | int id = 0; | 829 | int i, id = 0; |
| 830 | 830 | ||
| 831 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); | 831 | BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); |
| 832 | 832 | ||
| @@ -851,6 +851,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
| 851 | 851 | ||
| 852 | hdev->flags = 0; | 852 | hdev->flags = 0; |
| 853 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); | 853 | hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); |
| 854 | hdev->esco_type = (ESCO_HV1); | ||
| 854 | hdev->link_mode = (HCI_LM_ACCEPT); | 855 | hdev->link_mode = (HCI_LM_ACCEPT); |
| 855 | 856 | ||
| 856 | hdev->idle_timeout = 0; | 857 | hdev->idle_timeout = 0; |
| @@ -865,6 +866,9 @@ int hci_register_dev(struct hci_dev *hdev) | |||
| 865 | skb_queue_head_init(&hdev->cmd_q); | 866 | skb_queue_head_init(&hdev->cmd_q); |
| 866 | skb_queue_head_init(&hdev->raw_q); | 867 | skb_queue_head_init(&hdev->raw_q); |
| 867 | 868 | ||
| 869 | for (i = 0; i < 3; i++) | ||
| 870 | hdev->reassembly[i] = NULL; | ||
| 871 | |||
| 868 | init_waitqueue_head(&hdev->req_wait_q); | 872 | init_waitqueue_head(&hdev->req_wait_q); |
| 869 | init_MUTEX(&hdev->req_lock); | 873 | init_MUTEX(&hdev->req_lock); |
| 870 | 874 | ||
| @@ -889,6 +893,8 @@ EXPORT_SYMBOL(hci_register_dev); | |||
| 889 | /* Unregister HCI device */ | 893 | /* Unregister HCI device */ |
| 890 | int hci_unregister_dev(struct hci_dev *hdev) | 894 | int hci_unregister_dev(struct hci_dev *hdev) |
| 891 | { | 895 | { |
| 896 | int i; | ||
| 897 | |||
| 892 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); | 898 | BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); |
| 893 | 899 | ||
| 894 | hci_unregister_sysfs(hdev); | 900 | hci_unregister_sysfs(hdev); |
| @@ -899,9 +905,13 @@ int hci_unregister_dev(struct hci_dev *hdev) | |||
| 899 | 905 | ||
| 900 | hci_dev_do_close(hdev); | 906 | hci_dev_do_close(hdev); |
| 901 | 907 | ||
| 908 | for (i = 0; i < 3; i++) | ||
| 909 | kfree_skb(hdev->reassembly[i]); | ||
| 910 | |||
| 902 | hci_notify(hdev, HCI_DEV_UNREG); | 911 | hci_notify(hdev, HCI_DEV_UNREG); |
| 903 | 912 | ||
| 904 | __hci_dev_put(hdev); | 913 | __hci_dev_put(hdev); |
| 914 | |||
| 905 | return 0; | 915 | return 0; |
| 906 | } | 916 | } |
| 907 | EXPORT_SYMBOL(hci_unregister_dev); | 917 | EXPORT_SYMBOL(hci_unregister_dev); |
| @@ -922,6 +932,90 @@ int hci_resume_dev(struct hci_dev *hdev) | |||
| 922 | } | 932 | } |
| 923 | EXPORT_SYMBOL(hci_resume_dev); | 933 | EXPORT_SYMBOL(hci_resume_dev); |
| 924 | 934 | ||
| 935 | /* Receive packet type fragment */ | ||
| 936 | #define __reassembly(hdev, type) ((hdev)->reassembly[(type) - 2]) | ||
| 937 | |||
| 938 | int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) | ||
| 939 | { | ||
| 940 | if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) | ||
| 941 | return -EILSEQ; | ||
| 942 | |||
| 943 | while (count) { | ||
| 944 | struct sk_buff *skb = __reassembly(hdev, type); | ||
| 945 | struct { int expect; } *scb; | ||
| 946 | int len = 0; | ||
| 947 | |||
| 948 | if (!skb) { | ||
| 949 | /* Start of the frame */ | ||
| 950 | |||
| 951 | switch (type) { | ||
| 952 | case HCI_EVENT_PKT: | ||
| 953 | if (count >= HCI_EVENT_HDR_SIZE) { | ||
| 954 | struct hci_event_hdr *h = data; | ||
| 955 | len = HCI_EVENT_HDR_SIZE + h->plen; | ||
| 956 | } else | ||
| 957 | return -EILSEQ; | ||
| 958 | break; | ||
| 959 | |||
| 960 | case HCI_ACLDATA_PKT: | ||
| 961 | if (count >= HCI_ACL_HDR_SIZE) { | ||
| 962 | struct hci_acl_hdr *h = data; | ||
| 963 | len = HCI_ACL_HDR_SIZE + __le16_to_cpu(h->dlen); | ||
| 964 | } else | ||
| 965 | return -EILSEQ; | ||
| 966 | break; | ||
| 967 | |||
| 968 | case HCI_SCODATA_PKT: | ||
| 969 | if (count >= HCI_SCO_HDR_SIZE) { | ||
| 970 | struct hci_sco_hdr *h = data; | ||
| 971 | len = HCI_SCO_HDR_SIZE + h->dlen; | ||
| 972 | } else | ||
| 973 | return -EILSEQ; | ||
| 974 | break; | ||
| 975 | } | ||
| 976 | |||
| 977 | skb = bt_skb_alloc(len, GFP_ATOMIC); | ||
| 978 | if (!skb) { | ||
| 979 | BT_ERR("%s no memory for packet", hdev->name); | ||
| 980 | return -ENOMEM; | ||
| 981 | } | ||
| 982 | |||
| 983 | skb->dev = (void *) hdev; | ||
| 984 | bt_cb(skb)->pkt_type = type; | ||
| 985 | |||
| 986 | __reassembly(hdev, type) = skb; | ||
| 987 | |||
| 988 | scb = (void *) skb->cb; | ||
| 989 | scb->expect = len; | ||
| 990 | } else { | ||
| 991 | /* Continuation */ | ||
| 992 | |||
| 993 | scb = (void *) skb->cb; | ||
| 994 | len = scb->expect; | ||
| 995 | } | ||
| 996 | |||
| 997 | len = min(len, count); | ||
| 998 | |||
| 999 | memcpy(skb_put(skb, len), data, len); | ||
| 1000 | |||
| 1001 | scb->expect -= len; | ||
| 1002 | |||
| 1003 | if (scb->expect == 0) { | ||
| 1004 | /* Complete frame */ | ||
| 1005 | |||
| 1006 | __reassembly(hdev, type) = NULL; | ||
| 1007 | |||
| 1008 | bt_cb(skb)->pkt_type = type; | ||
| 1009 | hci_recv_frame(skb); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | count -= len; data += len; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | return 0; | ||
| 1016 | } | ||
| 1017 | EXPORT_SYMBOL(hci_recv_fragment); | ||
| 1018 | |||
| 925 | /* ---- Interface to upper protocols ---- */ | 1019 | /* ---- Interface to upper protocols ---- */ |
| 926 | 1020 | ||
| 927 | /* Register/Unregister protocols. | 1021 | /* Register/Unregister protocols. |
| @@ -1029,7 +1123,7 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 ogf, __u16 ocf, __u32 plen, void *p | |||
| 1029 | 1123 | ||
| 1030 | skb = bt_skb_alloc(len, GFP_ATOMIC); | 1124 | skb = bt_skb_alloc(len, GFP_ATOMIC); |
| 1031 | if (!skb) { | 1125 | if (!skb) { |
| 1032 | BT_ERR("%s Can't allocate memory for HCI command", hdev->name); | 1126 | BT_ERR("%s no memory for command", hdev->name); |
| 1033 | return -ENOMEM; | 1127 | return -ENOMEM; |
| 1034 | } | 1128 | } |
| 1035 | 1129 | ||
| @@ -1161,7 +1255,7 @@ EXPORT_SYMBOL(hci_send_sco); | |||
| 1161 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) | 1255 | static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int *quote) |
| 1162 | { | 1256 | { |
| 1163 | struct hci_conn_hash *h = &hdev->conn_hash; | 1257 | struct hci_conn_hash *h = &hdev->conn_hash; |
| 1164 | struct hci_conn *conn = NULL; | 1258 | struct hci_conn *conn = NULL; |
| 1165 | int num = 0, min = ~0; | 1259 | int num = 0, min = ~0; |
| 1166 | struct list_head *p; | 1260 | struct list_head *p; |
| 1167 | 1261 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 447ba7131220..4baea1e38652 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -350,11 +350,24 @@ static void hci_cc_info_param(struct hci_dev *hdev, __u16 ocf, struct sk_buff *s | |||
| 350 | if (hdev->features[0] & LMP_5SLOT) | 350 | if (hdev->features[0] & LMP_5SLOT) |
| 351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); | 351 | hdev->pkt_type |= (HCI_DM5 | HCI_DH5); |
| 352 | 352 | ||
| 353 | if (hdev->features[1] & LMP_HV2) | 353 | if (hdev->features[1] & LMP_HV2) { |
| 354 | hdev->pkt_type |= (HCI_HV2); | 354 | hdev->pkt_type |= (HCI_HV2); |
| 355 | hdev->esco_type |= (ESCO_HV2); | ||
| 356 | } | ||
| 357 | |||
| 358 | if (hdev->features[1] & LMP_HV3) { | ||
| 359 | hdev->pkt_type |= (HCI_HV3); | ||
| 360 | hdev->esco_type |= (ESCO_HV3); | ||
| 361 | } | ||
| 355 | 362 | ||
| 356 | if (hdev->features[1] & LMP_HV3) | 363 | if (hdev->features[3] & LMP_ESCO) |
| 357 | hdev->pkt_type |= (HCI_HV3); | 364 | hdev->esco_type |= (ESCO_EV3); |
| 365 | |||
| 366 | if (hdev->features[4] & LMP_EV4) | ||
| 367 | hdev->esco_type |= (ESCO_EV4); | ||
| 368 | |||
| 369 | if (hdev->features[4] & LMP_EV5) | ||
| 370 | hdev->esco_type |= (ESCO_EV5); | ||
| 358 | 371 | ||
| 359 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, | 372 | BT_DBG("%s: features 0x%x 0x%x 0x%x", hdev->name, |
| 360 | lf->features[0], lf->features[1], lf->features[2]); | 373 | lf->features[0], lf->features[1], lf->features[2]); |
| @@ -881,12 +894,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
| 881 | if (conn) { | 894 | if (conn) { |
| 882 | conn->sent -= count; | 895 | conn->sent -= count; |
| 883 | 896 | ||
| 884 | if (conn->type == SCO_LINK) { | 897 | if (conn->type == ACL_LINK) { |
| 885 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
| 886 | hdev->sco_cnt = hdev->sco_pkts; | ||
| 887 | } else { | ||
| 888 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | 898 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) |
| 889 | hdev->acl_cnt = hdev->acl_pkts; | 899 | hdev->acl_cnt = hdev->acl_pkts; |
| 900 | } else { | ||
| 901 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | ||
| 902 | hdev->sco_cnt = hdev->sco_pkts; | ||
| 890 | } | 903 | } |
| 891 | } | 904 | } |
| 892 | } | 905 | } |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ceadfcf457c1..64d89ca28847 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/sched.h> | 28 | #include <linux/sched.h> |
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/poll.h> | 30 | #include <linux/poll.h> |
| 31 | #include <linux/freezer.h> | ||
| 31 | #include <linux/fcntl.h> | 32 | #include <linux/fcntl.h> |
| 32 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
| 33 | #include <linux/socket.h> | 34 | #include <linux/socket.h> |
| @@ -547,7 +548,6 @@ static int hidp_session(void *arg) | |||
| 547 | 548 | ||
| 548 | daemonize("khidpd_%04x%04x", vendor, product); | 549 | daemonize("khidpd_%04x%04x", vendor, product); |
| 549 | set_user_nice(current, -15); | 550 | set_user_nice(current, -15); |
| 550 | current->flags |= PF_NOFREEZE; | ||
| 551 | 551 | ||
| 552 | init_waitqueue_entry(&ctrl_wait, current); | 552 | init_waitqueue_entry(&ctrl_wait, current); |
| 553 | init_waitqueue_entry(&intr_wait, current); | 553 | init_waitqueue_entry(&intr_wait, current); |
| @@ -581,15 +581,6 @@ static int hidp_session(void *arg) | |||
| 581 | 581 | ||
| 582 | hidp_del_timer(session); | 582 | hidp_del_timer(session); |
| 583 | 583 | ||
| 584 | fput(session->intr_sock->file); | ||
| 585 | |||
| 586 | wait_event_timeout(*(ctrl_sk->sk_sleep), | ||
| 587 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); | ||
| 588 | |||
| 589 | fput(session->ctrl_sock->file); | ||
| 590 | |||
| 591 | __hidp_unlink_session(session); | ||
| 592 | |||
| 593 | if (session->input) { | 584 | if (session->input) { |
| 594 | input_unregister_device(session->input); | 585 | input_unregister_device(session->input); |
| 595 | session->input = NULL; | 586 | session->input = NULL; |
| @@ -601,6 +592,15 @@ static int hidp_session(void *arg) | |||
| 601 | hid_free_device(session->hid); | 592 | hid_free_device(session->hid); |
| 602 | } | 593 | } |
| 603 | 594 | ||
| 595 | fput(session->intr_sock->file); | ||
| 596 | |||
| 597 | wait_event_timeout(*(ctrl_sk->sk_sleep), | ||
| 598 | (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); | ||
| 599 | |||
| 600 | fput(session->ctrl_sock->file); | ||
| 601 | |||
| 602 | __hidp_unlink_session(session); | ||
| 603 | |||
| 604 | up_write(&hidp_session_sem); | 604 | up_write(&hidp_session_sem); |
| 605 | 605 | ||
| 606 | kfree(session); | 606 | kfree(session); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 52e04df323ea..bb7220770f2c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
| 34 | #include <linux/signal.h> | 34 | #include <linux/signal.h> |
| 35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 36 | #include <linux/freezer.h> | ||
| 36 | #include <linux/wait.h> | 37 | #include <linux/wait.h> |
| 37 | #include <linux/device.h> | 38 | #include <linux/device.h> |
| 38 | #include <linux/net.h> | 39 | #include <linux/net.h> |
| @@ -1940,7 +1941,6 @@ static int rfcomm_run(void *unused) | |||
| 1940 | 1941 | ||
| 1941 | daemonize("krfcommd"); | 1942 | daemonize("krfcommd"); |
| 1942 | set_user_nice(current, -10); | 1943 | set_user_nice(current, -10); |
| 1943 | current->flags |= PF_NOFREEZE; | ||
| 1944 | 1944 | ||
| 1945 | BT_DBG(""); | 1945 | BT_DBG(""); |
| 1946 | 1946 | ||
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index b2b1cceb102a..23ba61a13bdd 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
| @@ -95,6 +95,10 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) | |||
| 95 | 95 | ||
| 96 | BT_DBG("dev %p dlc %p", dev, dlc); | 96 | BT_DBG("dev %p dlc %p", dev, dlc); |
| 97 | 97 | ||
| 98 | write_lock_bh(&rfcomm_dev_lock); | ||
| 99 | list_del_init(&dev->list); | ||
| 100 | write_unlock_bh(&rfcomm_dev_lock); | ||
| 101 | |||
| 98 | rfcomm_dlc_lock(dlc); | 102 | rfcomm_dlc_lock(dlc); |
| 99 | /* Detach DLC if it's owned by this dev */ | 103 | /* Detach DLC if it's owned by this dev */ |
| 100 | if (dlc->owner == dev) | 104 | if (dlc->owner == dev) |
| @@ -156,8 +160,13 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) | |||
| 156 | read_lock(&rfcomm_dev_lock); | 160 | read_lock(&rfcomm_dev_lock); |
| 157 | 161 | ||
| 158 | dev = __rfcomm_dev_get(id); | 162 | dev = __rfcomm_dev_get(id); |
| 159 | if (dev) | 163 | |
| 160 | rfcomm_dev_hold(dev); | 164 | if (dev) { |
| 165 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
| 166 | dev = NULL; | ||
| 167 | else | ||
| 168 | rfcomm_dev_hold(dev); | ||
| 169 | } | ||
| 161 | 170 | ||
| 162 | read_unlock(&rfcomm_dev_lock); | 171 | read_unlock(&rfcomm_dev_lock); |
| 163 | 172 | ||
| @@ -265,6 +274,12 @@ out: | |||
| 265 | 274 | ||
| 266 | dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); | 275 | dev->tty_dev = tty_register_device(rfcomm_tty_driver, dev->id, NULL); |
| 267 | 276 | ||
| 277 | if (IS_ERR(dev->tty_dev)) { | ||
| 278 | list_del(&dev->list); | ||
| 279 | kfree(dev); | ||
| 280 | return PTR_ERR(dev->tty_dev); | ||
| 281 | } | ||
| 282 | |||
| 268 | return dev->id; | 283 | return dev->id; |
| 269 | } | 284 | } |
| 270 | 285 | ||
| @@ -272,10 +287,7 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) | |||
| 272 | { | 287 | { |
| 273 | BT_DBG("dev %p", dev); | 288 | BT_DBG("dev %p", dev); |
| 274 | 289 | ||
| 275 | write_lock_bh(&rfcomm_dev_lock); | 290 | set_bit(RFCOMM_TTY_RELEASED, &dev->flags); |
| 276 | list_del_init(&dev->list); | ||
| 277 | write_unlock_bh(&rfcomm_dev_lock); | ||
| 278 | |||
| 279 | rfcomm_dev_put(dev); | 291 | rfcomm_dev_put(dev); |
| 280 | } | 292 | } |
| 281 | 293 | ||
| @@ -329,7 +341,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) | |||
| 329 | if (copy_from_user(&req, arg, sizeof(req))) | 341 | if (copy_from_user(&req, arg, sizeof(req))) |
| 330 | return -EFAULT; | 342 | return -EFAULT; |
| 331 | 343 | ||
| 332 | BT_DBG("sk %p dev_id %id flags 0x%x", sk, req.dev_id, req.flags); | 344 | BT_DBG("sk %p dev_id %d flags 0x%x", sk, req.dev_id, req.flags); |
| 333 | 345 | ||
| 334 | if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) | 346 | if (req.flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) |
| 335 | return -EPERM; | 347 | return -EPERM; |
| @@ -370,7 +382,7 @@ static int rfcomm_release_dev(void __user *arg) | |||
| 370 | if (copy_from_user(&req, arg, sizeof(req))) | 382 | if (copy_from_user(&req, arg, sizeof(req))) |
| 371 | return -EFAULT; | 383 | return -EFAULT; |
| 372 | 384 | ||
| 373 | BT_DBG("dev_id %id flags 0x%x", req.dev_id, req.flags); | 385 | BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); |
| 374 | 386 | ||
| 375 | if (!(dev = rfcomm_dev_get(req.dev_id))) | 387 | if (!(dev = rfcomm_dev_get(req.dev_id))) |
| 376 | return -ENODEV; | 388 | return -ENODEV; |
| @@ -383,6 +395,10 @@ static int rfcomm_release_dev(void __user *arg) | |||
| 383 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) | 395 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) |
| 384 | rfcomm_dlc_close(dev->dlc, 0); | 396 | rfcomm_dlc_close(dev->dlc, 0); |
| 385 | 397 | ||
| 398 | /* Shut down TTY synchronously before freeing rfcomm_dev */ | ||
| 399 | if (dev->tty) | ||
| 400 | tty_vhangup(dev->tty); | ||
| 401 | |||
| 386 | rfcomm_dev_del(dev); | 402 | rfcomm_dev_del(dev); |
| 387 | rfcomm_dev_put(dev); | 403 | rfcomm_dev_put(dev); |
| 388 | return 0; | 404 | return 0; |
| @@ -415,6 +431,8 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
| 415 | 431 | ||
| 416 | list_for_each(p, &rfcomm_dev_list) { | 432 | list_for_each(p, &rfcomm_dev_list) { |
| 417 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); | 433 | struct rfcomm_dev *dev = list_entry(p, struct rfcomm_dev, list); |
| 434 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
| 435 | continue; | ||
| 418 | (di + n)->id = dev->id; | 436 | (di + n)->id = dev->id; |
| 419 | (di + n)->flags = dev->flags; | 437 | (di + n)->flags = dev->flags; |
| 420 | (di + n)->state = dev->dlc->state; | 438 | (di + n)->state = dev->dlc->state; |
