diff options
Diffstat (limited to 'net')
35 files changed, 696 insertions, 65 deletions
diff --git a/net/Kconfig b/net/Kconfig index 5b22278..caeacd1 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -225,6 +225,8 @@ source "net/ieee80211/Kconfig" endmenu +source "net/rfkill/Kconfig" + endif # if NET endmenu # Networking diff --git a/net/Makefile b/net/Makefile index 9fdb60c..34e5b2d 100644 --- a/net/Makefile +++ b/net/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_IEEE80211) += ieee80211/ obj-$(CONFIG_TIPC) += tipc/ obj-$(CONFIG_NETLABEL) += netlabel/ obj-$(CONFIG_IUCV) += iucv/ +obj-$(CONFIG_RFKILL) += rfkill/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index f6a92a0..fbdfb12 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1844,7 +1844,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { .sendpage = sock_no_sendpage, }; -#include <linux/smp_lock.h> SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK); static struct notifier_block ddp_notifier = { diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 6ded952..429e13a 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -23,7 +23,6 @@ #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> -#include <linux/smp_lock.h> #include <linux/sockios.h> #include <linux/net.h> #include <net/ax25.h> diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index ab2db55..1c8f4a0 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -37,7 +37,6 @@ #include <linux/init.h> #include <linux/wait.h> #include <linux/errno.h> -#include <linux/smp_lock.h> #include <linux/net.h> #include <net/sock.h> diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 832b5f4..bfc9a35 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -499,6 +499,15 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, char break; case HCI_FILTER: + { + struct hci_filter *f = &hci_pi(sk)->filter; + + uf.type_mask = f->type_mask; + uf.opcode = f->opcode; + uf.event_mask[0] = *((u32 *) f->event_mask + 0); + uf.event_mask[1] = *((u32 *) f->event_mask + 1); + } + len = min_t(unsigned int, len, sizeof(uf)); if (copy_from_user(&uf, optval, len)) { err = -EFAULT; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 801d687..2583540 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -305,7 +305,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; + dev->bus = &bt_bus; dev->parent = hdev->parent; strlcpy(dev->bus_id, hdev->name, BUS_ID_SIZE); @@ -322,6 +322,10 @@ int hci_register_sysfs(struct hci_dev *hdev) if (device_create_file(dev, bt_attrs[i]) < 0) BT_ERR("Failed to create device attribute"); + if (sysfs_create_link(&bt_class->subsys.kobj, + &dev->kobj, kobject_name(&dev->kobj)) < 0) + BT_ERR("Failed to create class symlink"); + return 0; } @@ -329,6 +333,9 @@ void hci_unregister_sysfs(struct hci_dev *hdev) { BT_DBG("%p name %s type %d", hdev, hdev->name, hdev->type); + sysfs_remove_link(&bt_class->subsys.kobj, + kobject_name(&hdev->dev.kobj)); + device_del(&hdev->dev); } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index a586787..a59b1fb 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -954,11 +954,17 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch switch (optname) { case L2CAP_OPTIONS: + opts.imtu = l2cap_pi(sk)->imtu; + opts.omtu = l2cap_pi(sk)->omtu; + opts.flush_to = l2cap_pi(sk)->flush_to; + opts.mode = 0x00; + len = min_t(unsigned int, sizeof(opts), optlen); if (copy_from_user((char *) &opts, optval, len)) { err = -EFAULT; break; } + l2cap_pi(sk)->imtu = opts.imtu; l2cap_pi(sk)->omtu = opts.omtu; break; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index fe7df90..52e04df 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -622,7 +622,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst bacpy(&addr.l2_bdaddr, src); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = 0; - *err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr)); + *err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (*err < 0) goto failed; @@ -643,7 +643,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst bacpy(&addr.l2_bdaddr, dst); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = htobs(RFCOMM_PSM); - *err = sock->ops->connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); + *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); if (*err == 0 || *err == -EINPROGRESS) return s; @@ -1058,6 +1058,12 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) case BT_DISCONN: d->state = BT_CLOSED; __rfcomm_dlc_close(d, 0); + + if (list_empty(&s->dlcs)) { + s->state = BT_DISCONN; + rfcomm_send_disc(s, 0); + } + break; } } else { @@ -1067,6 +1073,10 @@ static int rfcomm_recv_ua(struct rfcomm_session *s, u8 dlci) s->state = BT_CONNECTED; rfcomm_process_connect(s); break; + + case BT_DISCONN: + rfcomm_session_put(s); + break; } } return 0; @@ -1757,19 +1767,12 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) BT_DBG("session %p", s); - if (sock_create_lite(PF_BLUETOOTH, sock->type, BTPROTO_L2CAP, &nsock)) + err = kernel_accept(sock, &nsock, O_NONBLOCK); + if (err < 0) return; - nsock->ops = sock->ops; - __module_get(nsock->ops->owner); - err = sock->ops->accept(sock, nsock, O_NONBLOCK); - if (err < 0) { - sock_release(nsock); - return; - } - /* Set our callbacks */ nsock->sk->sk_data_ready = rfcomm_l2data_ready; nsock->sk->sk_state_change = rfcomm_l2state_change; @@ -1885,7 +1888,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) bacpy(&addr.l2_bdaddr, ba); addr.l2_family = AF_BLUETOOTH; addr.l2_psm = htobs(RFCOMM_PSM); - err = sock->ops->bind(sock, (struct sockaddr *) &addr, sizeof(addr)); + err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { BT_ERR("Bind failed %d", err); goto failed; @@ -1898,7 +1901,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) release_sock(sk); /* Start listening on the socket */ - err = sock->ops->listen(sock, 10); + err = kernel_listen(sock, 10); if (err) { BT_ERR("Listen failed %d", err); goto failed; diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 9a7a44f..b2b1cce 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -517,9 +517,10 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) if (dlc->state == BT_CLOSED) { if (!dev->tty) { if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { - rfcomm_dev_hold(dev); - rfcomm_dev_del(dev); + if (rfcomm_dev_get(dev->id) == NULL) + return; + rfcomm_dev_del(dev); /* We have to drop DLC lock here, otherwise rfcomm_dev_put() will dead lock if it's the last reference. */ @@ -974,8 +975,12 @@ static void rfcomm_tty_hangup(struct tty_struct *tty) rfcomm_tty_flush_buffer(tty); - if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) + if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { + if (rfcomm_dev_get(dev->id) == NULL) + return; rfcomm_dev_del(dev); + rfcomm_dev_put(dev); + } } static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused) diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index ebb0861..0e035d6 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -13,7 +13,6 @@ * 2 of the License, or (at your option) any later version. */ #include <linux/kernel.h> -#include <linux/smp_lock.h> #include "br_private.h" #include "br_private_stp.h" diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 3e246b3..a786e78 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -14,7 +14,6 @@ */ #include <linux/kernel.h> -#include <linux/smp_lock.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 030aa79..24e0ca4 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/times.h> -#include <linux/smp_lock.h> #include "br_private.h" #include "br_private_stp.h" diff --git a/net/core/dev.c b/net/core/dev.c index f27d4ab..4317c1b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2377,9 +2377,9 @@ static int __init dev_proc_init(void) out: return rc; out_softnet: - proc_net_remove("softnet_stat"); -out_dev2: proc_net_remove("ptype"); +out_dev2: + proc_net_remove("softnet_stat"); out_dev: proc_net_remove("dev"); goto out; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b316435..758dafe 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -9,7 +9,6 @@ * Copyright (C) 2002 Red Hat, Inc. */ -#include <linux/smp_lock.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/string.h> diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b92a322..9cd3a1c 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -117,7 +117,6 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/kernel.h> -#include <linux/smp_lock.h> #include <linux/mutex.h> #include <linux/sched.h> #include <linux/slab.h> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 16aae8e..041fba3 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -92,7 +92,6 @@ #include <asm/uaccess.h> #include <asm/system.h> -#include <linux/smp_lock.h> #include <linux/inet.h> #include <linux/igmp.h> #include <linux/inetdevice.h> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8b124ea..bd4c295 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -252,7 +252,6 @@ #include <linux/fcntl.h> #include <linux/poll.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/fs.h> #include <linux/random.h> #include <linux/bootmem.h> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 0faacf9..53232dd 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -40,7 +40,6 @@ #include <linux/compiler.h> #include <linux/module.h> -#include <linux/smp_lock.h> /* People can turn this off for buggy TCP's found in printers etc. */ int sysctl_tcp_retrans_collapse __read_mostly = 1; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 18cb928..6dd3772 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -42,7 +42,6 @@ #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/icmpv6.h> -#include <linux/smp_lock.h> #include <linux/netfilter_ipv6.h> #include <net/ip.h> diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index da07e9a..bbe99f8 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -198,7 +198,7 @@ config IP6_NF_RAW and OUTPUT chains. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. endmenu diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 392f8bc..15419dd 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1961,7 +1961,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { .sendpage = sock_no_sendpage, }; -#include <linux/smp_lock.h> SOCKOPS_WRAP(ipx_dgram, PF_IPX); static struct packet_type ipx_8023_packet_type = { diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 06c97c6..dcd7e32 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -2538,7 +2538,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { }; #endif /* CONFIG_IRDA_ULTRA */ -#include <linux/smp_lock.h> SOCKOPS_WRAP(irda_stream, PF_IRDA); SOCKOPS_WRAP(irda_seqpacket, PF_IRDA); SOCKOPS_WRAP(irda_dgram, PF_IRDA); diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c558f32..ea6211c 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -100,7 +100,7 @@ config NF_CT_PROTO_SCTP tracking code will be able to do state tracking on SCTP connections. If you want to compile it as a module, say M here and read - Documentation/modules.txt. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NF_CONNTRACK_AMANDA tristate "Amanda backup protocol support" @@ -279,8 +279,8 @@ config NETFILTER_XT_TARGET_CONNMARK affects the connection mark value rather than the packet mark value. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. The module will be called - ipt_CONNMARK.o. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. The module will be called + ipt_CONNMARK.ko. If unsure, say `N'. config NETFILTER_XT_TARGET_DSCP tristate '"DSCP" target support' @@ -341,7 +341,7 @@ config NETFILTER_XT_TARGET_NOTRACK no protocol helpers for the selected packets). If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_TARGET_SECMARK tristate '"SECMARK" target support' @@ -397,7 +397,7 @@ config NETFILTER_XT_MATCH_COMMENT comments in your iptables ruleset. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_MATCH_CONNBYTES tristate '"connbytes" per-connection counter match support' @@ -409,7 +409,7 @@ config NETFILTER_XT_MATCH_CONNBYTES number of bytes and/or packets for each direction within a connection. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_MATCH_CONNMARK tristate '"connmark" connection mark match support' @@ -421,8 +421,8 @@ config NETFILTER_XT_MATCH_CONNMARK connection mark value previously set for the session by `CONNMARK'. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. The module will be called - ipt_connmark.o. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. The module will be called + ipt_connmark.ko. If unsure, say `N'. config NETFILTER_XT_MATCH_CONNTRACK tristate '"conntrack" connection tracking match support' @@ -446,7 +446,7 @@ config NETFILTER_XT_MATCH_DCCP and DCCP flags. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_MATCH_DSCP tristate '"DSCP" match support' @@ -565,7 +565,7 @@ config NETFILTER_XT_MATCH_QUOTA byte counter. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_MATCH_REALM tristate '"realm" match support' @@ -579,7 +579,7 @@ config NETFILTER_XT_MATCH_REALM in tc world. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_MATCH_SCTP tristate '"sctp" protocol match support (EXPERIMENTAL)' @@ -590,7 +590,7 @@ config NETFILTER_XT_MATCH_SCTP and SCTP chunk types. If you want to compile it as a module, say M here and read - <file:Documentation/modules.txt>. If unsure, say `N'. + <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. config NETFILTER_XT_MATCH_STATE tristate '"state" match support' diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 507828d..1f15821 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -45,7 +45,6 @@ #include <linux/rtnetlink.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> -#include <linux/smp_lock.h> #include <linux/notifier.h> #include <linux/security.h> #include <linux/jhash.h> diff --git a/net/rfkill/Kconfig b/net/rfkill/Kconfig new file mode 100644 index 0000000..8b31759 --- /dev/null +++ b/net/rfkill/Kconfig @@ -0,0 +1,24 @@ +# +# RF switch subsystem configuration +# +menuconfig RFKILL + tristate "RF switch subsystem support" + help + Say Y here if you want to have control over RF switches + found on many WiFi, Bluetooth and IRDA cards. + + To compile this driver as a module, choose M here: the + module will be called rfkill. + +config RFKILL_INPUT + tristate "Input layer to RF switch connector" + depends on RFKILL && INPUT + help + Say Y here if you want kernel automatically toggle state + of RF switches on and off when user presses appropriate + button or a key on the keyboard. Without this module you + need a some kind of userspace application to control + state of the switches. + + To compile this driver as a module, choose M here: the + module will be called rfkill-input. diff --git a/net/rfkill/Makefile b/net/rfkill/Makefile new file mode 100644 index 0000000..b38c430 --- /dev/null +++ b/net/rfkill/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the RF switch subsystem. +# + +obj-$(CONFIG_RFKILL) += rfkill.o +obj-$(CONFIG_RFKILL_INPUT) += rfkill-input.o diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c new file mode 100644 index 0000000..e5c840c --- /dev/null +++ b/net/rfkill/rfkill-input.c @@ -0,0 +1,174 @@ +/* + * Input layer to RF Kill interface connector + * + * Copyright (c) 2007 Dmitry Torokhov + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/input.h> +#include <linux/slab.h> +#include <linux/workqueue.h> +#include <linux/init.h> +#include <linux/rfkill.h> + +MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); +MODULE_DESCRIPTION("Input layer to RF switch connector"); +MODULE_LICENSE("GPL"); + +struct rfkill_task { + struct work_struct work; + enum rfkill_type type; + struct mutex mutex; /* ensures that task is serialized */ + spinlock_t lock; /* for accessing last and desired state */ + unsigned long last; /* last schedule */ + enum rfkill_state desired_state; /* on/off */ + enum rfkill_state current_state; /* on/off */ +}; + +static void rfkill_task_handler(struct work_struct *work) +{ + struct rfkill_task *task = container_of(work, struct rfkill_task, work); + enum rfkill_state state; + + mutex_lock(&task->mutex); + + /* + * Use temp variable to fetch desired state to keep it + * consistent even if rfkill_schedule_toggle() runs in + * another thread or interrupts us. + */ + state = task->desired_state; + + if (state != task->current_state) { + rfkill_switch_all(task->type, state); + task->current_state = state; + } + + mutex_unlock(&task->mutex); +} + +static void rfkill_schedule_toggle(struct rfkill_task *task) +{ + unsigned int flags; + + spin_lock_irqsave(&task->lock, flags); + + if (time_after(jiffies, task->last + msecs_to_jiffies(200))) { + task->desired_state = !task->desired_state; + task->last = jiffies; + schedule_work(&task->work); + } + + spin_unlock_irqrestore(&task->lock, flags); +} + +#define DEFINE_RFKILL_TASK(n, t) \ + struct rfkill_task n = { \ + .work = __WORK_INITIALIZER(n.work, \ + rfkill_task_handler), \ + .type = t, \ + .mutex = __MUTEX_INITIALIZER(n.mutex), \ + .lock = __SPIN_LOCK_UNLOCKED(n.lock), \ + .desired_state = RFKILL_STATE_ON, \ + .current_state = RFKILL_STATE_ON, \ + } + +static DEFINE_RFKILL_TASK(rfkill_wlan, RFKILL_TYPE_WLAN); +static DEFINE_RFKILL_TASK(rfkill_bt, RFKILL_TYPE_BLUETOOTH); + +static void rfkill_event(struct input_handle *handle, unsigned int type, + unsigned int code, int down) +{ + if (type == EV_KEY && down == 1) { + switch (code) { + case KEY_WLAN: + rfkill_schedule_toggle(&rfkill_wlan); + break; + case KEY_BLUETOOTH: + rfkill_schedule_toggle(&rfkill_bt); + break; + default: + break; + } + } +} + +static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "rfkill"; + + error = input_register_handle(handle); + if (error) + goto err_free_handle; + + error = input_open_device(handle); + if (error) + goto err_unregister_handle; + + return 0; + + err_unregister_handle: + input_unregister_handle(handle); + err_free_handle: + kfree(handle); + return error; +} + +static void rfkill_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id rfkill_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT(EV_KEY) }, + .keybit = { [LONG(KEY_WLAN)] = BIT(KEY_WLAN) }, + }, + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT(EV_KEY) }, + .keybit = { [LONG(KEY_BLUETOOTH)] = BIT(KEY_BLUETOOTH) }, + }, + { } +}; + +static struct input_handler rfkill_handler = { + .event = rfkill_event, + .connect = rfkill_connect, + .disconnect = rfkill_disconnect, + .name = "rfkill", + .id_table = rfkill_ids, +}; + +static int __init rfkill_handler_init(void) +{ + return input_register_handler(&rfkill_handler); +} + +static void __exit rfkill_handler_exit(void) +{ + input_unregister_handler(&rfkill_handler); + flush_scheduled_work(); +} + +module_init(rfkill_handler_init); +module_exit(rfkill_handler_exit); diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c new file mode 100644 index 0000000..a973603 --- /dev/null +++ b/net/rfkill/rfkill.c @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2006 Ivo van Doorn + * Copyright (C) 2007 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/workqueue.h> +#include <linux/capability.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/rfkill.h> + +MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>"); +MODULE_VERSION("1.0"); +MODULE_DESCRIPTION("RF switch support"); +MODULE_LICENSE("GPL"); + +static LIST_HEAD(rfkill_list); /* list of registered rf switches */ +static DEFINE_MUTEX(rfkill_mutex); + +static enum rfkill_state rfkill_states[RFKILL_TYPE_MAX]; + +static int rfkill_toggle_radio(struct rfkill *rfkill, + enum rfkill_state state) +{ + int retval; + + retval = mutex_lock_interruptible(&rfkill->mutex); + if (retval) + return retval; + + if (state != rfkill->state) { + retval = rfkill->toggle_radio(rfkill->data, state); + if (!retval) + rfkill->state = state; + } + + mutex_unlock(&rfkill->mutex); + return retval; +} + +/** + * rfkill_switch_all - Toggle state of all switches of given type + * @type: type of interfaces to be affeceted + * @state: the new state + * + * This function toggles state of all switches of given type unless + * a specific switch is claimed by userspace in which case it is + * left alone. + */ + +void rfkill_switch_all(enum rfkill_type type, enum rfkill_state state) +{ + struct rfkill *rfkill; + + mutex_lock(&rfkill_mutex); + + rfkill_states[type] = state; + + list_for_each_entry(rfkill, &rfkill_list, node) { + if (!rfkill->user_claim) + rfkill_toggle_radio(rfkill, state); + } + + mutex_unlock(&rfkill_mutex); +} +EXPORT_SYMBOL(rfkill_switch_all); + +static ssize_t rfkill_name_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + + return sprintf(buf, "%s\n", rfkill->name); +} + +static ssize_t rfkill_type_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + const char *type; + + switch (rfkill->type) { + case RFKILL_TYPE_WLAN: + type = "wlan"; + break; + case RFKILL_TYPE_BLUETOOTH: + type = "bluetooth"; + break; + case RFKILL_TYPE_IRDA: + type = "irda"; + break; + default: + BUG(); + } + + return sprintf(buf, "%s\n", type); +} + +static ssize_t rfkill_state_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + + return sprintf(buf, "%d\n", rfkill->state); +} + +static ssize_t rfkill_state_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rfkill *rfkill = to_rfkill(dev); + unsigned int state = simple_strtoul(buf, NULL, 0); + int error; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + error = rfkill_toggle_radio(rfkill, + state ? RFKILL_STATE_ON : RFKILL_STATE_OFF); + if (error) + return error; + + return count; +} + +static ssize_t rfkill_claim_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct rfkill *rfkill = to_rfkill(dev); + + return sprintf(buf, "%d", rfkill->user_claim); +} + +static ssize_t rfkill_claim_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct rfkill *rfkill = to_rfkill(dev); + bool claim = !!simple_strtoul(buf, NULL, 0); + int error; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + /* + * Take the global lock to make sure the kernel is not in + * the middle of rfkill_switch_all + */ + error = mutex_lock_interruptible(&rfkill_mutex); + if (error) + return error; + + if (rfkill->user_claim != claim) { + if (!claim) + rfkill_toggle_radio(rfkill, + rfkill_states[rfkill->type]); + rfkill->user_claim = claim; + } + + mutex_unlock(&rfkill_mutex); + + return count; +} + +static struct device_attribute rfkill_dev_attrs[] = { + __ATTR(name, S_IRUGO, rfkill_name_show, NULL), + __ATTR(type, S_IRUGO, rfkill_type_show, NULL), + __ATTR(state, S_IRUGO, rfkill_state_show, rfkill_state_store), + __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), + __ATTR_NULL +}; + +static void rfkill_release(struct device *dev) +{ + struct rfkill *rfkill = to_rfkill(dev); + + kfree(rfkill); + module_put(THIS_MODULE); +} + +#ifdef CONFIG_PM +static int rfkill_suspend(struct device *dev, pm_message_t state) +{ + struct rfkill *rfkill = to_rfkill(dev); + + if (dev->power.power_state.event != state.event) { + if (state.event == PM_EVENT_SUSPEND) { + mutex_lock(&rfkill->mutex); + + if (rfkill->state == RFKILL_STATE_ON) + rfkill->toggle_radio(rfkill->data, + RFKILL_STATE_OFF); + + mutex_unlock(&rfkill->mutex); + } + + dev->power.power_state = state; + } + + return 0; +} + +static int rfkill_resume(struct device *dev) +{ + struct rfkill *rfkill = to_rfkill(dev); + + if (dev->power.power_state.event != PM_EVENT_ON) { + mutex_lock(&rfkill->mutex); + + if (rfkill->state == RFKILL_STATE_ON) + rfkill->toggle_radio(rfkill->data, RFKILL_STATE_ON); + + mutex_unlock(&rfkill->mutex); + } + + dev->power.power_state = PMSG_ON; + return 0; +} +#else +#define rfkill_suspend NULL +#define rfkill_resume NULL +#endif + +static struct class rfkill_class = { + .name = "rfkill", + .dev_release = rfkill_release, + .dev_attrs = rfkill_dev_attrs, + .suspend = rfkill_suspend, + .resume = rfkill_resume, +}; + +static int rfkill_add_switch(struct rfkill *rfkill) +{ + int retval; + + retval = mutex_lock_interruptible(&rfkill_mutex); + if (retval) + return retval; + + retval = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type]); + if (retval) + goto out; + + list_add_tail(&rfkill->node, &rfkill_list); + + out: + mutex_unlock(&rfkill_mutex); + return retval; +} + +static void rfkill_remove_switch(struct rfkill *rfkill) +{ + mutex_lock(&rfkill_mutex); + list_del_init(&rfkill->node); + rfkill_toggle_radio(rfkill, RFKILL_STATE_OFF); + mutex_unlock(&rfkill_mutex); +} + +/** + * rfkill_allocate - allocate memory for rfkill structure. + * @parent: device that has rf switch on it + * @type: type of the switch (wlan, bluetooth, irda) + * + * This function should be called by the network driver when it needs + * rfkill structure. Once the structure is allocated the driver shoud + * finish its initialization by setting name, private data, enable_radio + * and disable_radio methods and then register it with rfkill_register(). + * NOTE: If registration fails the structure shoudl be freed by calling + * rfkill_free() otherwise rfkill_unregister() should be used. + */ +struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type) +{ + struct rfkill *rfkill; + struct device *dev; + + rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL); + if (rfkill) + return NULL; + + mutex_init(&rfkill->mutex); + INIT_LIST_HEAD(&rfkill->node); + rfkill->type = type; + + dev = &rfkill->dev; + dev->class = &rfkill_class; + dev->parent = parent; + device_initialize(dev); + + __module_get(THIS_MODULE); + + return rfkill; +} +EXPORT_SYMBOL(rfkill_allocate); + +/** + * rfkill_free - Mark rfkill structure for deletion + * @rfkill: rfkill structure to be destroyed + * + * Decrements reference count of rfkill structure so it is destoryed. + * Note that rfkill_free() should _not_ be called after rfkill_unregister(). + */ +void rfkill_free(struct rfkill *rfkill) +{ + if (rfkill) + put_device(&rfkill->dev); +} +EXPORT_SYMBOL(rfkill_free); + +/** + * rfkill_register - Register a rfkill structure. + * @rfkill: rfkill structure to be registered + * + * This function should be called by the network driver when the rfkill + * structure needs to be registered. Immediately from registration the + * switch driver should be able to service calls to toggle_radio. + */ +int rfkill_register(struct rfkill *rfkill) +{ + static atomic_t rfkill_no = ATOMIC_INIT(0); + struct device *dev = &rfkill->dev; + int error; + + if (!rfkill->toggle_radio) + return -EINVAL; + + error = rfkill_add_switch(rfkill); + if (error) + return error; + + snprintf(dev->bus_id, sizeof(dev->bus_id), + "rfkill%ld", (long)atomic_inc_return(&rfkill_no) - 1); + + error = device_add(dev); + if (error) { + rfkill_remove_switch(rfkill); + return error; + } + + return 0; +} +EXPORT_SYMBOL(rfkill_register); + +/** + * rfkill_unregister - Uegister a rfkill structure. + * @rfkill: rfkill structure to be unregistered + * + * This function should be called by the network driver during device + * teardown to destroy rfkill structure. Note that rfkill_free() should + * _not_ be called after rfkill_unregister(). + */ +void rfkill_unregister(struct rfkill *rfkill) +{ + device_del(&rfkill->dev); + rfkill_remove_switch(rfkill); + put_device(&rfkill->dev); +} +EXPORT_SYMBOL(rfkill_unregister); + +/* + * Rfkill module initialization/deinitialization. + */ +static int __init rfkill_init(void) +{ + int error; + int i; + + for (i = 0; i < ARRAY_SIZE(rfkill_states); i++) + rfkill_states[i] = RFKILL_STATE_ON; + + error = class_register(&rfkill_class); + if (error) { + printk(KERN_ERR "rfkill: unable to register rfkill class\n"); + return error; + } + + return 0; +} + +static void __exit rfkill_exit(void) +{ + class_unregister(&rfkill_class); +} + +module_init(rfkill_init); +module_exit(rfkill_exit); diff --git a/net/socket.c b/net/socket.c index 1ad62c0..98a8f67 100644 --- a/net/socket.c +++ b/net/socket.c @@ -261,8 +261,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct socket_alloc *ei = (struct socket_alloc *)foo; - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) - == SLAB_CTOR_CONSTRUCTOR) + if (flags & SLAB_CTOR_CONSTRUCTOR) inode_init_once(&ei->vfs_inode); } @@ -314,8 +313,19 @@ static int sockfs_delete_dentry(struct dentry *dentry) dentry->d_flags |= DCACHE_UNHASHED; return 0; } + +/* + * sockfs_dname() is called from d_path(). + */ +static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen) +{ + return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", + dentry->d_inode->i_ino); +} + static struct dentry_operations sockfs_dentry_operations = { .d_delete = sockfs_delete_dentry, + .d_dname = sockfs_dname, }; /* @@ -355,14 +365,9 @@ static int sock_alloc_fd(struct file **filep) static int sock_attach_fd(struct socket *sock, struct file *file) { - struct qstr this; - char name[32]; - - this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); - this.name = name; - this.hash = 0; + struct qstr name = { .name = "" }; - file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); + file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); if (unlikely(!file->f_path.dentry)) return -ENOMEM; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9b9ea50..ad39b47 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -828,8 +828,7 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct rpc_inode *rpci = (struct rpc_inode *) foo; - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == - SLAB_CTOR_CONSTRUCTOR) { + if (flags & SLAB_CTOR_CONSTRUCTOR) { inode_init_once(&rpci->vfs_inode); rpci->private = NULL; rpci->nreaders = 0; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 4a53e94..9901451 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -763,9 +763,9 @@ void *rpc_malloc(struct rpc_task *task, size_t size) else buf = kmalloc(size, gfp); *buf = size; - dprintk("RPC: %5u allocated buffer of size %u at %p\n", + dprintk("RPC: %5u allocated buffer of size %zu at %p\n", task->tk_pid, size, buf); - return (void *) ++buf; + return ++buf; } /** @@ -775,14 +775,14 @@ void *rpc_malloc(struct rpc_task *task, size_t size) */ void rpc_free(void *buffer) { - size_t size, *buf = (size_t *) buffer; + size_t size, *buf = buffer; if (!buffer) return; size = *buf; buf--; - dprintk("RPC: freeing buffer of size %u at %p\n", + dprintk("RPC: freeing buffer of size %zu at %p\n", size, buf); if (size <= RPC_BUFFER_MAXSIZE) mempool_free(buf, rpc_buffer_mempool); diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig index 3891cc0..f9e367d 100644 --- a/net/tipc/Kconfig +++ b/net/tipc/Kconfig @@ -18,7 +18,7 @@ config TIPC This protocol support is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called tipc. If you want to compile it - as a module, say M here and read <file:Documentation/modules.txt>. + as a module, say M here and read <file:Documentation/kbuild/modules.txt>. If in doubt, say N. diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index aec8cf1..fc12ba5 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -111,7 +111,6 @@ #include <net/scm.h> #include <linux/init.h> #include <linux/poll.h> -#include <linux/smp_lock.h> #include <linux/rtnetlink.h> #include <linux/mount.h> #include <net/checksum.h> diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 0d6002fc..479927c 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1605,7 +1605,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { .sendpage = sock_no_sendpage, }; -#include <linux/smp_lock.h> SOCKOPS_WRAP(x25_proto, AF_X25); static struct packet_type x25_packet_type = { |