X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fbluetooth%2Faf_bluetooth.c;h=67df99e2e5c82b2a4fc72e28dc748a33209fcd55;hb=refs%2Fheads%2Fvserver;hp=74b70f70e07771751aec410df42c6012091f481b;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 74b70f70e..67df99e2e 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -22,27 +22,19 @@ SOFTWARE IS DISCLAIMED. */ -/* - * Bluetooth address family and sockets. - * - * $Id: af_bluetooth.c,v 1.3 2002/04/17 17:37:15 maxk Exp $ - */ -#define VERSION "2.4" - -#include +/* Bluetooth address family and sockets. */ + #include #include #include #include #include -#include #include #include #include #include #include -#include #include #if defined(CONFIG_KMOD) @@ -53,46 +45,61 @@ #ifndef CONFIG_BT_SOCK_DEBUG #undef BT_DBG -#define BT_DBG( A... ) +#define BT_DBG(D...) #endif -struct proc_dir_entry *proc_bt; +#define VERSION "2.11" /* Bluetooth sockets */ -#define BT_MAX_PROTO 6 +#define BT_MAX_PROTO 8 static struct net_proto_family *bt_proto[BT_MAX_PROTO]; - -static kmem_cache_t *bt_sock_cache; +static DEFINE_RWLOCK(bt_proto_lock); int bt_sock_register(int proto, struct net_proto_family *ops) { - if (proto >= BT_MAX_PROTO) + 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) { - if (proto >= BT_MAX_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 >= BT_MAX_PROTO) + if (proto < 0 || proto >= BT_MAX_PROTO) return -EINVAL; #if defined(CONFIG_KMOD) @@ -100,41 +107,19 @@ 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); } - return err; -} -struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio) -{ - struct sock *sk; - void *pi; - - sk = sk_alloc(PF_BLUETOOTH, prio, sizeof(struct bt_sock), bt_sock_cache); - if (!sk) - return NULL; - - if (pi_size) { - pi = kmalloc(pi_size, prio); - if (!pi) { - sk_free(sk); - return NULL; - } - memset(pi, 0, pi_size); - sk->sk_protinfo = pi; - } + read_unlock(&bt_proto_lock); - sock_init_data(sock, sk); - INIT_LIST_HEAD(&bt_sk(sk)->accept_q); - - sk->sk_zapped = 0; - sk->sk_protocol = proto; - sk->sk_state = BT_OPEN; - - return sk; + return err; } void bt_sock_link(struct bt_sock_list *l, struct sock *sk) @@ -143,6 +128,7 @@ void bt_sock_link(struct bt_sock_list *l, struct sock *sk) sk_add_node(sk, &l->head); write_unlock_bh(&l->lock); } +EXPORT_SYMBOL(bt_sock_link); void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk) { @@ -150,6 +136,7 @@ void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk) sk_del_node_init(sk); write_unlock_bh(&l->lock); } +EXPORT_SYMBOL(bt_sock_unlink); void bt_accept_enqueue(struct sock *parent, struct sock *sk) { @@ -160,8 +147,9 @@ void bt_accept_enqueue(struct sock *parent, struct sock *sk) bt_sk(sk)->parent = parent; parent->sk_ack_backlog++; } +EXPORT_SYMBOL(bt_accept_enqueue); -static void bt_accept_unlink(struct sock *sk) +void bt_accept_unlink(struct sock *sk) { BT_DBG("sk %p state %d", sk, sk->sk_state); @@ -170,24 +158,27 @@ static void bt_accept_unlink(struct sock *sk) bt_sk(sk)->parent = NULL; sock_put(sk); } +EXPORT_SYMBOL(bt_accept_unlink); struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) { struct list_head *p, *n; struct sock *sk; - + BT_DBG("parent %p", parent); list_for_each_safe(p, n, &bt_sk(parent)->accept_q) { sk = (struct sock *) list_entry(p, struct bt_sock, accept_q); - + lock_sock(sk); + + /* FIXME: Is this check still needed */ if (sk->sk_state == BT_CLOSED) { release_sock(sk); bt_accept_unlink(sk); continue; } - + if (sk->sk_state == BT_CONNECTED || !newsock) { bt_accept_unlink(sk); if (newsock) @@ -195,10 +186,12 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock) release_sock(sk); return sk; } + release_sock(sk); } return NULL; } +EXPORT_SYMBOL(bt_accept_dequeue); int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) @@ -235,6 +228,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, return err ? : copied; } +EXPORT_SYMBOL(bt_sock_recvmsg); static inline unsigned int bt_accept_poll(struct sock *parent) { @@ -265,6 +259,9 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) mask |= POLLERR; + if (sk->sk_shutdown & RCV_SHUTDOWN) + mask |= POLLRDHUP; + if (sk->sk_shutdown == SHUTDOWN_MASK) mask |= POLLHUP; @@ -287,6 +284,7 @@ unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *w return mask; } +EXPORT_SYMBOL(bt_sock_poll); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) { @@ -300,7 +298,7 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) set_current_state(TASK_INTERRUPTIBLE); if (!timeo) { - err = -EAGAIN; + err = -EINPROGRESS; break; } @@ -313,52 +311,40 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) timeo = schedule_timeout(timeo); lock_sock(sk); - if (sk->sk_err) { - err = sock_error(sk); + err = sock_error(sk); + if (err) break; - } } set_current_state(TASK_RUNNING); remove_wait_queue(sk->sk_sleep, &wait); return err; } +EXPORT_SYMBOL(bt_sock_wait_state); static struct net_proto_family bt_sock_family_ops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, .family = PF_BLUETOOTH, .create = bt_sock_create, }; -extern int hci_sock_init(void); -extern int hci_sock_cleanup(void); - -extern int bt_sysfs_init(void); -extern int bt_sysfs_cleanup(void); - static int __init bt_init(void) { + int err; + BT_INFO("Core ver %s", VERSION); - proc_bt = proc_mkdir("bluetooth", NULL); - if (proc_bt) - proc_bt->owner = THIS_MODULE; - - /* Init socket cache */ - bt_sock_cache = kmem_cache_create("bt_sock", - sizeof(struct bt_sock), 0, - SLAB_HWCACHE_ALIGN, 0, 0); - - if (!bt_sock_cache) { - BT_ERR("Socket cache creation failed"); - return -ENOMEM; + err = bt_sysfs_init(); + if (err < 0) + return err; + + err = sock_register(&bt_sock_family_ops); + if (err < 0) { + bt_sysfs_cleanup(); + return err; } - - sock_register(&bt_sock_family_ops); BT_INFO("HCI device and connection manager initialized"); - bt_sysfs_init(); - hci_sock_init(); return 0; @@ -368,12 +354,9 @@ static void __exit bt_exit(void) { hci_sock_cleanup(); - bt_sysfs_cleanup(); - sock_unregister(PF_BLUETOOTH); - kmem_cache_destroy(bt_sock_cache); - remove_proc_entry("bluetooth", NULL); + bt_sysfs_cleanup(); } subsys_initcall(bt_init);