From 2267e86d4765f8ddaf5944d17e3b425b51a1a051 Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Thu, 25 Sep 2003 07:11:27 -0700 Subject: [PATCH] [ATM]: [ioctl][2/8] Add registration functions (from levon@movementarian.org) --- include/linux/atmdev.h | 22 ++++++++++++++++++++++ net/atm/ioctl.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h index 0bf8106530b97..d4617e465c60d 100644 --- a/include/linux/atmdev.h +++ b/include/linux/atmdev.h @@ -445,6 +445,28 @@ int atm_pcr_goal(struct atm_trafprm *tp); void vcc_release_async(struct atm_vcc *vcc, int reply); +struct atm_ioctl { + struct module *owner; + /* A module reference is kept if appropriate over this call. + * Return -ENOIOCTLCMD if you don't handle it. */ + int (*ioctl)(struct socket *, unsigned int cmd, unsigned long arg); + struct list_head list; +}; + +/** + * register_atm_ioctl - register handler for ioctl operations + * + * Special (non-device) handlers of ioctl's should + * register here. If you're a normal device, you should + * set .ioctl in your atmdev_ops instead. + */ +void register_atm_ioctl(struct atm_ioctl *); + +/** + * deregister_atm_ioctl - remove the ioctl handler + */ +void deregister_atm_ioctl(struct atm_ioctl *); + #endif /* __KERNEL__ */ #endif diff --git a/net/atm/ioctl.c b/net/atm/ioctl.c index 3ae335f4a5dbe..f654b35c7e6c9 100644 --- a/net/atm/ioctl.c +++ b/net/atm/ioctl.c @@ -1,6 +1,7 @@ -/* net/atm/common.c - ATM sockets (common part for PVC and SVC) */ +/* ATM ioctl handling */ /* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ +/* 2003 John Levon */ #include @@ -18,7 +19,7 @@ #ifdef CONFIG_ATM_CLIP #include /* for clip_create */ #endif -#include "resources.h" /* atm_find_dev */ +#include "resources.h" #include "signaling.h" /* for WAITING and sigd_attach */ #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) @@ -153,11 +154,32 @@ EXPORT_SYMBOL(br2684_ioctl_set); #endif #endif +static DECLARE_MUTEX(ioctl_mutex); +static LIST_HEAD(ioctl_list); + + +void register_atm_ioctl(struct atm_ioctl *ioctl) +{ + down(&ioctl_mutex); + list_add_tail(&ioctl->list, &ioctl_list); + up(&ioctl_mutex); +} + +void deregister_atm_ioctl(struct atm_ioctl *ioctl) +{ + down(&ioctl_mutex); + list_del(&ioctl->list); + up(&ioctl_mutex); +} + +EXPORT_SYMBOL(register_atm_ioctl); +EXPORT_SYMBOL(deregister_atm_ioctl); int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct atm_vcc *vcc; int error; + struct list_head * pos; vcc = ATM_SD(sock); switch (cmd) { @@ -396,6 +418,22 @@ int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) break; } error = -ENOIOCTLCMD; + + down(&ioctl_mutex); + list_for_each(pos, &ioctl_list) { + struct atm_ioctl * ic = list_entry(pos, struct atm_ioctl, list); + if (try_module_get(ic->owner)) { + error = ic->ioctl(sock, cmd, arg); + module_put(ic->owner); + if (error != -ENOIOCTLCMD) + break; + } + } + up(&ioctl_mutex); + + if (error != -ENOIOCTLCMD) + goto done; + #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE) down(&pppoatm_ioctl_mutex); if (pppoatm_ioctl_hook) -- 2.53.0