diff options
Diffstat (limited to 'net/bluetooth/rfcomm/sock.c')
| -rw-r--r-- | net/bluetooth/rfcomm/sock.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 4b5968dda673..194b3a04cfd3 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
| @@ -40,6 +40,8 @@ | |||
| 40 | #include <linux/skbuff.h> | 40 | #include <linux/skbuff.h> |
| 41 | #include <linux/list.h> | 41 | #include <linux/list.h> |
| 42 | #include <linux/device.h> | 42 | #include <linux/device.h> |
| 43 | #include <linux/debugfs.h> | ||
| 44 | #include <linux/seq_file.h> | ||
| 43 | #include <net/sock.h> | 45 | #include <net/sock.h> |
| 44 | 46 | ||
| 45 | #include <asm/system.h> | 47 | #include <asm/system.h> |
| @@ -80,11 +82,14 @@ static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb) | |||
| 80 | static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) | 82 | static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) |
| 81 | { | 83 | { |
| 82 | struct sock *sk = d->owner, *parent; | 84 | struct sock *sk = d->owner, *parent; |
| 85 | unsigned long flags; | ||
| 86 | |||
| 83 | if (!sk) | 87 | if (!sk) |
| 84 | return; | 88 | return; |
| 85 | 89 | ||
| 86 | BT_DBG("dlc %p state %ld err %d", d, d->state, err); | 90 | BT_DBG("dlc %p state %ld err %d", d, d->state, err); |
| 87 | 91 | ||
| 92 | local_irq_save(flags); | ||
| 88 | bh_lock_sock(sk); | 93 | bh_lock_sock(sk); |
| 89 | 94 | ||
| 90 | if (err) | 95 | if (err) |
| @@ -106,6 +111,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) | |||
| 106 | } | 111 | } |
| 107 | 112 | ||
| 108 | bh_unlock_sock(sk); | 113 | bh_unlock_sock(sk); |
| 114 | local_irq_restore(flags); | ||
| 109 | 115 | ||
| 110 | if (parent && sock_flag(sk, SOCK_ZAPPED)) { | 116 | if (parent && sock_flag(sk, SOCK_ZAPPED)) { |
| 111 | /* We have to drop DLC lock here, otherwise | 117 | /* We have to drop DLC lock here, otherwise |
| @@ -395,7 +401,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a | |||
| 395 | 401 | ||
| 396 | BT_DBG("sk %p", sk); | 402 | BT_DBG("sk %p", sk); |
| 397 | 403 | ||
| 398 | if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc)) | 404 | if (alen < sizeof(struct sockaddr_rc) || |
| 405 | addr->sa_family != AF_BLUETOOTH) | ||
| 399 | return -EINVAL; | 406 | return -EINVAL; |
| 400 | 407 | ||
| 401 | lock_sock(sk); | 408 | lock_sock(sk); |
| @@ -500,7 +507,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
| 500 | BT_DBG("sk %p timeo %ld", sk, timeo); | 507 | BT_DBG("sk %p timeo %ld", sk, timeo); |
| 501 | 508 | ||
| 502 | /* Wait for an incoming connection. (wake-one). */ | 509 | /* Wait for an incoming connection. (wake-one). */ |
| 503 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 510 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 504 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { | 511 | while (!(nsk = bt_accept_dequeue(sk, newsock))) { |
| 505 | set_current_state(TASK_INTERRUPTIBLE); | 512 | set_current_state(TASK_INTERRUPTIBLE); |
| 506 | if (!timeo) { | 513 | if (!timeo) { |
| @@ -523,7 +530,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f | |||
| 523 | } | 530 | } |
| 524 | } | 531 | } |
| 525 | set_current_state(TASK_RUNNING); | 532 | set_current_state(TASK_RUNNING); |
| 526 | remove_wait_queue(sk->sk_sleep, &wait); | 533 | remove_wait_queue(sk_sleep(sk), &wait); |
| 527 | 534 | ||
| 528 | if (err) | 535 | if (err) |
| 529 | goto done; | 536 | goto done; |
| @@ -618,7 +625,7 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | |||
| 618 | { | 625 | { |
| 619 | DECLARE_WAITQUEUE(wait, current); | 626 | DECLARE_WAITQUEUE(wait, current); |
| 620 | 627 | ||
| 621 | add_wait_queue(sk->sk_sleep, &wait); | 628 | add_wait_queue(sk_sleep(sk), &wait); |
| 622 | for (;;) { | 629 | for (;;) { |
| 623 | set_current_state(TASK_INTERRUPTIBLE); | 630 | set_current_state(TASK_INTERRUPTIBLE); |
| 624 | 631 | ||
| @@ -637,7 +644,7 @@ static long rfcomm_sock_data_wait(struct sock *sk, long timeo) | |||
| 637 | } | 644 | } |
| 638 | 645 | ||
| 639 | __set_current_state(TASK_RUNNING); | 646 | __set_current_state(TASK_RUNNING); |
| 640 | remove_wait_queue(sk->sk_sleep, &wait); | 647 | remove_wait_queue(sk_sleep(sk), &wait); |
| 641 | return timeo; | 648 | return timeo; |
| 642 | } | 649 | } |
| 643 | 650 | ||
| @@ -1061,26 +1068,38 @@ done: | |||
| 1061 | return result; | 1068 | return result; |
| 1062 | } | 1069 | } |
| 1063 | 1070 | ||
| 1064 | static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf) | 1071 | static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) |
| 1065 | { | 1072 | { |
| 1066 | struct sock *sk; | 1073 | struct sock *sk; |
| 1067 | struct hlist_node *node; | 1074 | struct hlist_node *node; |
| 1068 | char *str = buf; | ||
| 1069 | 1075 | ||
| 1070 | read_lock_bh(&rfcomm_sk_list.lock); | 1076 | read_lock_bh(&rfcomm_sk_list.lock); |
| 1071 | 1077 | ||
| 1072 | sk_for_each(sk, node, &rfcomm_sk_list.head) { | 1078 | sk_for_each(sk, node, &rfcomm_sk_list.head) { |
| 1073 | str += sprintf(str, "%s %s %d %d\n", | 1079 | seq_printf(f, "%s %s %d %d\n", |
| 1074 | batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), | 1080 | batostr(&bt_sk(sk)->src), |
| 1081 | batostr(&bt_sk(sk)->dst), | ||
| 1075 | sk->sk_state, rfcomm_pi(sk)->channel); | 1082 | sk->sk_state, rfcomm_pi(sk)->channel); |
| 1076 | } | 1083 | } |
| 1077 | 1084 | ||
| 1078 | read_unlock_bh(&rfcomm_sk_list.lock); | 1085 | read_unlock_bh(&rfcomm_sk_list.lock); |
| 1079 | 1086 | ||
| 1080 | return (str - buf); | 1087 | return 0; |
| 1088 | } | ||
| 1089 | |||
| 1090 | static int rfcomm_sock_debugfs_open(struct inode *inode, struct file *file) | ||
| 1091 | { | ||
| 1092 | return single_open(file, rfcomm_sock_debugfs_show, inode->i_private); | ||
| 1081 | } | 1093 | } |
| 1082 | 1094 | ||
| 1083 | static CLASS_ATTR(rfcomm, S_IRUGO, rfcomm_sock_sysfs_show, NULL); | 1095 | static const struct file_operations rfcomm_sock_debugfs_fops = { |
| 1096 | .open = rfcomm_sock_debugfs_open, | ||
| 1097 | .read = seq_read, | ||
| 1098 | .llseek = seq_lseek, | ||
| 1099 | .release = single_release, | ||
| 1100 | }; | ||
| 1101 | |||
| 1102 | static struct dentry *rfcomm_sock_debugfs; | ||
| 1084 | 1103 | ||
| 1085 | static const struct proto_ops rfcomm_sock_ops = { | 1104 | static const struct proto_ops rfcomm_sock_ops = { |
| 1086 | .family = PF_BLUETOOTH, | 1105 | .family = PF_BLUETOOTH, |
| @@ -1120,8 +1139,12 @@ int __init rfcomm_init_sockets(void) | |||
| 1120 | if (err < 0) | 1139 | if (err < 0) |
| 1121 | goto error; | 1140 | goto error; |
| 1122 | 1141 | ||
| 1123 | if (class_create_file(bt_class, &class_attr_rfcomm) < 0) | 1142 | if (bt_debugfs) { |
| 1124 | BT_ERR("Failed to create RFCOMM info file"); | 1143 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, |
| 1144 | bt_debugfs, NULL, &rfcomm_sock_debugfs_fops); | ||
| 1145 | if (!rfcomm_sock_debugfs) | ||
| 1146 | BT_ERR("Failed to create RFCOMM debug file"); | ||
| 1147 | } | ||
| 1125 | 1148 | ||
| 1126 | BT_INFO("RFCOMM socket layer initialized"); | 1149 | BT_INFO("RFCOMM socket layer initialized"); |
| 1127 | 1150 | ||
| @@ -1133,9 +1156,9 @@ error: | |||
| 1133 | return err; | 1156 | return err; |
| 1134 | } | 1157 | } |
| 1135 | 1158 | ||
| 1136 | void rfcomm_cleanup_sockets(void) | 1159 | void __exit rfcomm_cleanup_sockets(void) |
| 1137 | { | 1160 | { |
| 1138 | class_remove_file(bt_class, &class_attr_rfcomm); | 1161 | debugfs_remove(rfcomm_sock_debugfs); |
| 1139 | 1162 | ||
| 1140 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) | 1163 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) |
| 1141 | BT_ERR("RFCOMM socket layer unregistration failed"); | 1164 | BT_ERR("RFCOMM socket layer unregistration failed"); |
