diff options
Diffstat (limited to 'net/bluetooth/sco.c')
| -rw-r--r-- | net/bluetooth/sco.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index dd8f6ec57dce..d0927d1fdada 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
| @@ -38,6 +38,8 @@ | |||
| 38 | #include <linux/socket.h> | 38 | #include <linux/socket.h> |
| 39 | #include <linux/skbuff.h> | 39 | #include <linux/skbuff.h> |
| 40 | #include <linux/device.h> | 40 | #include <linux/device.h> |
| 41 | #include <linux/debugfs.h> | ||
| 42 | #include <linux/seq_file.h> | ||
| 41 | #include <linux/list.h> | 43 | #include <linux/list.h> |
| 42 | #include <net/sock.h> | 44 | #include <net/sock.h> |
| 43 | 45 | ||
| @@ -163,11 +165,11 @@ static inline int sco_chan_add(struct sco_conn *conn, struct sock *sk, struct so | |||
| 163 | int err = 0; | 165 | int err = 0; |
| 164 | 166 | ||
| 165 | sco_conn_lock(conn); | 167 | sco_conn_lock(conn); |
| 166 | if (conn->sk) { | 168 | if (conn->sk) |
| 167 | err = -EBUSY; | 169 | err = -EBUSY; |
| 168 | } else { | 170 | else |
| 169 | __sco_chan_add(conn, sk, parent); | 171 | __sco_chan_add(conn, sk, parent); |
| 170 | } | 172 | |
| 171 | sco_conn_unlock(conn); | 173 | sco_conn_unlock(conn); |
| 172 | return err; | 174 | return err; |
| 173 | } | 175 | } |
| @@ -239,22 +241,19 @@ static inline int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | |||
| 239 | BT_DBG("sk %p len %d", sk, len); | 241 | BT_DBG("sk %p len %d", sk, len); |
| 240 | 242 | ||
| 241 | count = min_t(unsigned int, conn->mtu, len); | 243 | count = min_t(unsigned int, conn->mtu, len); |
| 242 | if (!(skb = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err))) | 244 | skb = bt_skb_send_alloc(sk, count, |
| 245 | msg->msg_flags & MSG_DONTWAIT, &err); | ||
| 246 | if (!skb) | ||
| 243 | return err; | 247 | return err; |
| 244 | 248 | ||
| 245 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { | 249 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) { |
| 246 | err = -EFAULT; | 250 | kfree_skb(skb); |
| 247 | goto fail; | 251 | return -EFAULT; |
| 248 | } | 252 | } |
| 249 | 253 | ||
| 250 | if ((err = hci_send_sco(conn->hcon, skb)) < 0) | 254 | hci_send_sco(conn->hcon, skb); |
| 251 | return err; | ||
| 252 | 255 | ||
| 253 | return count; | 256 | return count; |
| 254 | |||
| 255 | fail: | ||
| 256 | kfree_skb(skb); | ||
| 257 | return err; | ||
| 258 | } | 257 | } |
| 259 | 258 | ||
| 260 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | 259 | static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) |
| @@ -274,7 +273,6 @@ static inline void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | |||
| 274 | 273 | ||
| 275 | drop: | 274 | drop: |
| 276 | kfree_skb(skb); | 275 | kfree_skb(skb); |
| 277 | return; | ||
| 278 | } | 276 | } |
| 279 | 277 | ||
| 280 | /* -------- Socket interface ---------- */ | 278 | /* -------- Socket interface ---------- */ |
| @@ -497,7 +495,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen | |||
| 497 | 495 | ||
| 498 | BT_DBG("sk %p", sk); | 496 | BT_DBG("sk %p", sk); |
| 499 | 497 | ||
| 500 | if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_sco)) | 498 | if (alen < sizeof(struct sockaddr_sco) || |
| 499 | addr->sa_family != AF_BLUETOOTH) | ||
| 501 | return -EINVAL; | 500 | return -EINVAL; |
| 502 | 501 | ||
| 503 | if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) | 502 | if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) |
| @@ -564,7 +563,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag | |||
| 564 | BT_DBG("sk %p timeo %ld", sk, timeo); | 563 | BT_DBG("sk %p timeo %ld", sk, timeo); |
| 565 | 564 | ||
| 566 | /* Wait for an incoming connection. (wake-one). */ | 565 | /* Wait for an incoming connection. (wake-one). */ |
| 567 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 566 | add_wait_queue_exclusive(sk_sleep(sk), &wait); |
| 568 | while (!(ch = bt_accept_dequeue(sk, newsock))) { | 567 | while (!(ch = bt_accept_dequeue(sk, newsock))) { |
| 569 | set_current_state(TASK_INTERRUPTIBLE); | 568 | set_current_state(TASK_INTERRUPTIBLE); |
| 570 | if (!timeo) { | 569 | if (!timeo) { |
| @@ -587,7 +586,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag | |||
| 587 | } | 586 | } |
| 588 | } | 587 | } |
| 589 | set_current_state(TASK_RUNNING); | 588 | set_current_state(TASK_RUNNING); |
| 590 | remove_wait_queue(sk->sk_sleep, &wait); | 589 | remove_wait_queue(sk_sleep(sk), &wait); |
| 591 | 590 | ||
| 592 | if (err) | 591 | if (err) |
| 593 | goto done; | 592 | goto done; |
| @@ -623,7 +622,7 @@ static int sco_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
| 623 | struct msghdr *msg, size_t len) | 622 | struct msghdr *msg, size_t len) |
| 624 | { | 623 | { |
| 625 | struct sock *sk = sock->sk; | 624 | struct sock *sk = sock->sk; |
| 626 | int err = 0; | 625 | int err; |
| 627 | 626 | ||
| 628 | BT_DBG("sock %p, sk %p", sock, sk); | 627 | BT_DBG("sock %p, sk %p", sock, sk); |
| 629 | 628 | ||
| @@ -848,7 +847,8 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
| 848 | 847 | ||
| 849 | bh_lock_sock(parent); | 848 | bh_lock_sock(parent); |
| 850 | 849 | ||
| 851 | sk = sco_sock_alloc(sock_net(parent), NULL, BTPROTO_SCO, GFP_ATOMIC); | 850 | sk = sco_sock_alloc(sock_net(parent), NULL, |
| 851 | BTPROTO_SCO, GFP_ATOMIC); | ||
| 852 | if (!sk) { | 852 | if (!sk) { |
| 853 | bh_unlock_sock(parent); | 853 | bh_unlock_sock(parent); |
| 854 | goto done; | 854 | goto done; |
| @@ -953,26 +953,36 @@ drop: | |||
| 953 | return 0; | 953 | return 0; |
| 954 | } | 954 | } |
| 955 | 955 | ||
| 956 | static ssize_t sco_sysfs_show(struct class *dev, char *buf) | 956 | static int sco_debugfs_show(struct seq_file *f, void *p) |
| 957 | { | 957 | { |
| 958 | struct sock *sk; | 958 | struct sock *sk; |
| 959 | struct hlist_node *node; | 959 | struct hlist_node *node; |
| 960 | char *str = buf; | ||
| 961 | 960 | ||
| 962 | read_lock_bh(&sco_sk_list.lock); | 961 | read_lock_bh(&sco_sk_list.lock); |
| 963 | 962 | ||
| 964 | sk_for_each(sk, node, &sco_sk_list.head) { | 963 | sk_for_each(sk, node, &sco_sk_list.head) { |
| 965 | str += sprintf(str, "%s %s %d\n", | 964 | seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), |
| 966 | batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), | 965 | batostr(&bt_sk(sk)->dst), sk->sk_state); |
| 967 | sk->sk_state); | ||
| 968 | } | 966 | } |
| 969 | 967 | ||
| 970 | read_unlock_bh(&sco_sk_list.lock); | 968 | read_unlock_bh(&sco_sk_list.lock); |
| 971 | 969 | ||
| 972 | return (str - buf); | 970 | return 0; |
| 973 | } | 971 | } |
| 974 | 972 | ||
| 975 | static CLASS_ATTR(sco, S_IRUGO, sco_sysfs_show, NULL); | 973 | static int sco_debugfs_open(struct inode *inode, struct file *file) |
| 974 | { | ||
| 975 | return single_open(file, sco_debugfs_show, inode->i_private); | ||
| 976 | } | ||
| 977 | |||
| 978 | static const struct file_operations sco_debugfs_fops = { | ||
| 979 | .open = sco_debugfs_open, | ||
| 980 | .read = seq_read, | ||
| 981 | .llseek = seq_lseek, | ||
| 982 | .release = single_release, | ||
| 983 | }; | ||
| 984 | |||
| 985 | static struct dentry *sco_debugfs; | ||
| 976 | 986 | ||
| 977 | static const struct proto_ops sco_sock_ops = { | 987 | static const struct proto_ops sco_sock_ops = { |
| 978 | .family = PF_BLUETOOTH, | 988 | .family = PF_BLUETOOTH, |
| @@ -1030,8 +1040,12 @@ static int __init sco_init(void) | |||
| 1030 | goto error; | 1040 | goto error; |
| 1031 | } | 1041 | } |
| 1032 | 1042 | ||
| 1033 | if (class_create_file(bt_class, &class_attr_sco) < 0) | 1043 | if (bt_debugfs) { |
| 1034 | BT_ERR("Failed to create SCO info file"); | 1044 | sco_debugfs = debugfs_create_file("sco", 0444, |
| 1045 | bt_debugfs, NULL, &sco_debugfs_fops); | ||
| 1046 | if (!sco_debugfs) | ||
| 1047 | BT_ERR("Failed to create SCO debug file"); | ||
| 1048 | } | ||
| 1035 | 1049 | ||
| 1036 | BT_INFO("SCO (Voice Link) ver %s", VERSION); | 1050 | BT_INFO("SCO (Voice Link) ver %s", VERSION); |
| 1037 | BT_INFO("SCO socket layer initialized"); | 1051 | BT_INFO("SCO socket layer initialized"); |
| @@ -1045,7 +1059,7 @@ error: | |||
| 1045 | 1059 | ||
| 1046 | static void __exit sco_exit(void) | 1060 | static void __exit sco_exit(void) |
| 1047 | { | 1061 | { |
| 1048 | class_remove_file(bt_class, &class_attr_sco); | 1062 | debugfs_remove(sco_debugfs); |
| 1049 | 1063 | ||
| 1050 | if (bt_sock_unregister(BTPROTO_SCO) < 0) | 1064 | if (bt_sock_unregister(BTPROTO_SCO) < 0) |
| 1051 | BT_ERR("SCO socket unregistration failed"); | 1065 | BT_ERR("SCO socket unregistration failed"); |
