diff options
Diffstat (limited to 'drivers/isdn')
25 files changed, 281 insertions, 996 deletions
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile index 63baf27a2c79..d14334f4007e 100644 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -3,6 +3,6 @@ # Object files in subdirectories -obj-$(CONFIG_ISDN_CAPI) += capi/ +obj-$(CONFIG_BT_CMTP) += capi/ obj-$(CONFIG_MISDN) += mISDN/ obj-$(CONFIG_ISDN) += hardware/ diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig index 573fea5500ce..cc408ad9aafb 100644 --- a/drivers/isdn/capi/Kconfig +++ b/drivers/isdn/capi/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -menuconfig ISDN_CAPI - tristate "CAPI 2.0 subsystem" +config ISDN_CAPI + def_bool ISDN && BT help This provides CAPI (the Common ISDN Application Programming Interface) Version 2.0, a standard making it easy for programs to @@ -15,42 +15,18 @@ menuconfig ISDN_CAPI See CONFIG_BT_CMTP for the last remaining regular driver in the kernel that uses the CAPI subsystem. -if ISDN_CAPI - config CAPI_TRACE - bool "CAPI trace support" - default y + def_bool BT_CMTP help If you say Y here, the kernelcapi driver can make verbose traces of CAPI messages. This feature can be enabled/disabled via IOCTL for every controller (default disabled). - This will increase the size of the kernelcapi module by 20 KB. - If unsure, say Y. - -config ISDN_CAPI_CAPI20 - tristate "CAPI2.0 /dev/capi20 support" - help - This option will provide the CAPI 2.0 interface to userspace - applications via /dev/capi20. Applications should use the - standardized libcapi20 to access this functionality. You should say - Y/M here. config ISDN_CAPI_MIDDLEWARE - bool "CAPI2.0 Middleware support" - depends on ISDN_CAPI_CAPI20 && TTY + def_bool BT_CMTP && TTY help This option will enhance the capabilities of the /dev/capi20 interface. It will provide a means of moving a data connection, established via the usual /dev/capi20 interface to a special tty device. If you want to use pppd with pppdcapiplugin to dial up to your ISP, say Y here. - -config ISDN_CAPI_CAPIDRV_VERBOSE - bool "Verbose reason code reporting" - depends on ISDN_CAPI_CAPIDRV - help - If you say Y here, the capidrv interface will give verbose reasons - for disconnecting. This will increase the size of the kernel by 7 KB. - If unsure, say N. - -endif diff --git a/drivers/isdn/capi/Makefile b/drivers/isdn/capi/Makefile index d299f3e75f89..352217ebabd8 100644 --- a/drivers/isdn/capi/Makefile +++ b/drivers/isdn/capi/Makefile @@ -1,17 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -# Makefile for the CAPI subsystem. +# Makefile for the CAPI subsystem used by BT_CMTP -# Ordering constraints: kernelcapi.o first - -# Each configuration option enables a list of files. - -obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o -obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o -obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o - -# Multipart objects. - -kernelcapi-y := kcapi.o capiutil.o capilib.o -kernelcapi-$(CONFIG_PROC_FS) += kcapi_proc.o - -ccflags-y += -I$(srctree)/$(src)/../include -I$(srctree)/$(src)/../include/uapi +obj-$(CONFIG_BT_CMTP) += kernelcapi.o +kernelcapi-y := kcapi.o capiutil.o capi.o kcapi_proc.o diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3c3ad42f22bf..85767f52fe3c 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -39,7 +39,9 @@ #include <linux/isdn/capiutil.h> #include <linux/isdn/capicmd.h> -MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); +#include "kcapi.h" + +MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer and /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -688,6 +690,9 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos if (!cdev->ap.applid) return -ENODEV; + if (count < CAPIMSG_BASELEN) + return -EINVAL; + skb = alloc_skb(count, GFP_USER); if (!skb) return -ENOMEM; @@ -698,7 +703,8 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos } mlen = CAPIMSG_LEN(skb->data); if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) { + if (count < CAPI_DATA_B3_REQ_LEN || + (size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) { kfree_skb(skb); return -EINVAL; } @@ -711,6 +717,10 @@ capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos CAPIMSG_SETAPPID(skb->data, cdev->ap.applid); if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) { + if (count < CAPI_DISCONNECT_B3_RESP_LEN) { + kfree_skb(skb); + return -EINVAL; + } mutex_lock(&cdev->lock); capincci_free(cdev, CAPIMSG_NCCI(skb->data)); mutex_unlock(&cdev->lock); @@ -736,7 +746,7 @@ capi_poll(struct file *file, poll_table *wait) poll_wait(file, &(cdev->recvwait), wait); mask = EPOLLOUT | EPOLLWRNORM; - if (!skb_queue_empty(&cdev->recvqueue)) + if (!skb_queue_empty_lockless(&cdev->recvqueue)) mask |= EPOLLIN | EPOLLRDNORM; return mask; } @@ -942,6 +952,34 @@ capi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } +#ifdef CONFIG_COMPAT +static long +capi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret; + + if (cmd == CAPI_MANUFACTURER_CMD) { + struct { + compat_ulong_t cmd; + compat_uptr_t data; + } mcmd32; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user(&mcmd32, compat_ptr(arg), sizeof(mcmd32))) + return -EFAULT; + + mutex_lock(&capi_mutex); + ret = capi20_manufacturer(mcmd32.cmd, compat_ptr(mcmd32.data)); + mutex_unlock(&capi_mutex); + + return ret; + } + + return capi_unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + static int capi_open(struct inode *inode, struct file *file) { struct capidev *cdev; @@ -988,6 +1026,9 @@ static const struct file_operations capi_fops = .write = capi_write, .poll = capi_poll, .unlocked_ioctl = capi_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = capi_compat_ioctl, +#endif .open = capi_open, .release = capi_release, }; @@ -1373,15 +1414,22 @@ static int __init capi_init(void) { const char *compileinfo; int major_ret; + int ret; + + ret = kcapi_init(); + if (ret) + return ret; major_ret = register_chrdev(capi_major, "capi20", &capi_fops); if (major_ret < 0) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); + kcapi_exit(); return major_ret; } capi_class = class_create(THIS_MODULE, "capi"); if (IS_ERR(capi_class)) { unregister_chrdev(capi_major, "capi20"); + kcapi_exit(); return PTR_ERR(capi_class); } @@ -1391,6 +1439,7 @@ static int __init capi_init(void) device_destroy(capi_class, MKDEV(capi_major, 0)); class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); + kcapi_exit(); return -ENOMEM; } @@ -1416,6 +1465,8 @@ static void __exit capi_exit(void) unregister_chrdev(capi_major, "capi20"); capinc_tty_exit(); + + kcapi_exit(); } module_init(capi_init); diff --git a/drivers/isdn/capi/capilib.c b/drivers/isdn/capi/capilib.c deleted file mode 100644 index a39ad3796bba..000000000000 --- a/drivers/isdn/capi/capilib.c +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/isdn/capilli.h> - -#define DBG(format, arg...) do { \ - printk(KERN_DEBUG "%s: " format "\n" , __func__ , ## arg); \ - } while (0) - -struct capilib_msgidqueue { - struct capilib_msgidqueue *next; - u16 msgid; -}; - -struct capilib_ncci { - struct list_head list; - u16 applid; - u32 ncci; - u32 winsize; - int nmsg; - struct capilib_msgidqueue *msgidqueue; - struct capilib_msgidqueue *msgidlast; - struct capilib_msgidqueue *msgidfree; - struct capilib_msgidqueue msgidpool[CAPI_MAXDATAWINDOW]; -}; - -// --------------------------------------------------------------------------- -// NCCI Handling - -static inline void mq_init(struct capilib_ncci *np) -{ - u_int i; - np->msgidqueue = NULL; - np->msgidlast = NULL; - np->nmsg = 0; - memset(np->msgidpool, 0, sizeof(np->msgidpool)); - np->msgidfree = &np->msgidpool[0]; - for (i = 1; i < np->winsize; i++) { - np->msgidpool[i].next = np->msgidfree; - np->msgidfree = &np->msgidpool[i]; - } -} - -static inline int mq_enqueue(struct capilib_ncci *np, u16 msgid) -{ - struct capilib_msgidqueue *mq; - if ((mq = np->msgidfree) == NULL) - return 0; - np->msgidfree = mq->next; - mq->msgid = msgid; - mq->next = NULL; - if (np->msgidlast) - np->msgidlast->next = mq; - np->msgidlast = mq; - if (!np->msgidqueue) - np->msgidqueue = mq; - np->nmsg++; - return 1; -} - -static inline int mq_dequeue(struct capilib_ncci *np, u16 msgid) -{ - struct capilib_msgidqueue **pp; - for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->msgid == msgid) { - struct capilib_msgidqueue *mq = *pp; - *pp = mq->next; - if (mq == np->msgidlast) - np->msgidlast = NULL; - mq->next = np->msgidfree; - np->msgidfree = mq; - np->nmsg--; - return 1; - } - } - return 0; -} - -void capilib_new_ncci(struct list_head *head, u16 applid, u32 ncci, u32 winsize) -{ - struct capilib_ncci *np; - - np = kmalloc(sizeof(*np), GFP_ATOMIC); - if (!np) { - printk(KERN_WARNING "capilib_new_ncci: no memory.\n"); - return; - } - if (winsize > CAPI_MAXDATAWINDOW) { - printk(KERN_ERR "capi_new_ncci: winsize %d too big\n", - winsize); - winsize = CAPI_MAXDATAWINDOW; - } - np->applid = applid; - np->ncci = ncci; - np->winsize = winsize; - mq_init(np); - list_add_tail(&np->list, head); - DBG("kcapi: appl %d ncci 0x%x up", applid, ncci); -} - -EXPORT_SYMBOL(capilib_new_ncci); - -void capilib_free_ncci(struct list_head *head, u16 applid, u32 ncci) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", applid, ncci); - list_del(&np->list); - kfree(np); - return; - } - printk(KERN_ERR "capilib_free_ncci: ncci 0x%x not found\n", ncci); -} - -EXPORT_SYMBOL(capilib_free_ncci); - -void capilib_release_appl(struct list_head *head, u16 applid) -{ - struct list_head *l, *n; - struct capilib_ncci *np; - - list_for_each_safe(l, n, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", applid, np->ncci); - list_del(&np->list); - kfree(np); - } -} - -EXPORT_SYMBOL(capilib_release_appl); - -void capilib_release(struct list_head *head) -{ - struct list_head *l, *n; - struct capilib_ncci *np; - - list_for_each_safe(l, n, head) { - np = list_entry(l, struct capilib_ncci, list); - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down\n", np->applid, np->ncci); - list_del(&np->list); - kfree(np); - } -} - -EXPORT_SYMBOL(capilib_release); - -u16 capilib_data_b3_req(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - - if (mq_enqueue(np, msgid) == 0) - return CAPI_SENDQUEUEFULL; - - return CAPI_NOERROR; - } - printk(KERN_ERR "capilib_data_b3_req: ncci 0x%x not found\n", ncci); - return CAPI_NOERROR; -} - -EXPORT_SYMBOL(capilib_data_b3_req); - -void capilib_data_b3_conf(struct list_head *head, u16 applid, u32 ncci, u16 msgid) -{ - struct list_head *l; - struct capilib_ncci *np; - - list_for_each(l, head) { - np = list_entry(l, struct capilib_ncci, list); - if (np->applid != applid) - continue; - if (np->ncci != ncci) - continue; - - if (mq_dequeue(np, msgid) == 0) { - printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n", - msgid, ncci); - } - return; - } - printk(KERN_ERR "capilib_data_b3_conf: ncci 0x%x not found\n", ncci); -} - -EXPORT_SYMBOL(capilib_data_b3_conf); diff --git a/drivers/isdn/capi/capiutil.c b/drivers/isdn/capi/capiutil.c index 9846d82eb097..f26bf3c66d7e 100644 --- a/drivers/isdn/capi/capiutil.c +++ b/drivers/isdn/capi/capiutil.c @@ -20,6 +20,8 @@ #include <linux/isdn/capiutil.h> #include <linux/slab.h> +#include "kcapi.h" + /* from CAPI2.0 DDK AVM Berlin GmbH */ typedef struct { @@ -245,190 +247,6 @@ static void jumpcstruct(_cmsg *cmsg) } } } -/*-------------------------------------------------------*/ -static void pars_2_message(_cmsg *cmsg) -{ - - for (; TYP != _CEND; cmsg->p++) { - switch (TYP) { - case _CBYTE: - byteTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - if (*(u8 **) OFF == NULL) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - } else if (**(_cstruct *) OFF != 0xff) { - structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF); - cmsg->l += 1 + **(_cstruct *) OFF; - } else { - _cstruct s = *(_cstruct *) OFF; - structTLcpy(cmsg->m + cmsg->l, s, 3 + *(u16 *) (s + 1)); - cmsg->l += 3 + *(u16 *) (s + 1); - } - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (*(_cmstruct *) OFF == CAPI_DEFAULT) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - jumpcstruct(cmsg); - } -/*----- Metastruktur wird composed -----*/ - else { - unsigned _l = cmsg->l; - unsigned _ls; - cmsg->l++; - cmsg->p++; - pars_2_message(cmsg); - _ls = cmsg->l - _l - 1; - if (_ls < 255) - (cmsg->m + _l)[0] = (u8) _ls; - else { - structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls); - (cmsg->m + _l)[0] = 0xff; - wordTLcpy(cmsg->m + _l + 1, &_ls); - } - } - break; - } - } -} - -/** - * capi_cmsg2message() - assemble CAPI 2.0 message from _cmsg structure - * @cmsg: _cmsg structure - * @msg: buffer for assembled message - * - * Return value: 0 for success - */ - -unsigned capi_cmsg2message(_cmsg *cmsg, u8 *msg) -{ - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand); - if (!cmsg->par) - return 1; /* invalid command/subcommand */ - - pars_2_message(cmsg); - - wordTLcpy(msg + 0, &cmsg->l); - byteTLcpy(cmsg->m + 4, &cmsg->Command); - byteTLcpy(cmsg->m + 5, &cmsg->Subcommand); - wordTLcpy(cmsg->m + 2, &cmsg->ApplId); - wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/*-------------------------------------------------------*/ -static void message_2_pars(_cmsg *cmsg) -{ - for (; TYP != _CEND; cmsg->p++) { - - switch (TYP) { - case _CBYTE: - byteTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - *(u8 **) OFF = cmsg->m + cmsg->l; - - if (cmsg->m[cmsg->l] != 0xff) - cmsg->l += 1 + cmsg->m[cmsg->l]; - else - cmsg->l += 3 + *(u16 *) (cmsg->m + cmsg->l + 1); - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (cmsg->m[cmsg->l] == '\0') { - *(_cmstruct *) OFF = CAPI_DEFAULT; - cmsg->l++; - jumpcstruct(cmsg); - } else { - unsigned _l = cmsg->l; - *(_cmstruct *) OFF = CAPI_COMPOSE; - cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; - cmsg->p++; - message_2_pars(cmsg); - } - break; - } - } -} - -/** - * capi_message2cmsg() - disassemble CAPI 2.0 message into _cmsg structure - * @cmsg: _cmsg structure - * @msg: buffer for assembled message - * - * Return value: 0 for success - */ - -unsigned capi_message2cmsg(_cmsg *cmsg, u8 *msg) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - byteTRcpy(cmsg->m + 4, &cmsg->Command); - byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); - cmsg->par = capi_cmd2par(cmsg->Command, cmsg->Subcommand); - if (!cmsg->par) - return 1; /* invalid command/subcommand */ - - message_2_pars(cmsg); - - wordTRcpy(msg + 0, &cmsg->l); - wordTRcpy(cmsg->m + 2, &cmsg->ApplId); - wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/** - * capi_cmsg_header() - initialize header part of _cmsg structure - * @cmsg: _cmsg structure - * @_ApplId: ApplID field value - * @_Command: Command field value - * @_Subcommand: Subcommand field value - * @_Messagenumber: Message Number field value - * @_Controller: Controller/PLCI/NCCI field value - * - * Return value: 0 for success - */ - -unsigned capi_cmsg_header(_cmsg *cmsg, u16 _ApplId, - u8 _Command, u8 _Subcommand, - u16 _Messagenumber, u32 _Controller) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->ApplId = _ApplId; - cmsg->Command = _Command; - cmsg->Subcommand = _Subcommand; - cmsg->Messagenumber = _Messagenumber; - cmsg->adr.adrController = _Controller; - return 0; -} /*-------------------------------------------------------*/ @@ -561,8 +379,6 @@ static char *pnames[] = /*2f */ "Useruserdata" }; - - #include <stdarg.h> /*-------------------------------------------------------*/ @@ -800,37 +616,6 @@ _cdebbuf *capi_message2str(u8 *msg) return cdb; } -/** - * capi_cmsg2str() - format _cmsg structure for printing - * @cmsg: _cmsg structure - * - * Allocates a CAPI debug buffer and fills it with a printable representation - * of the CAPI 2.0 message stored in @cmsg by a previous call to - * capi_cmsg2message() or capi_message2cmsg(). - * Return value: allocated debug buffer, NULL on error - * The returned buffer should be freed by a call to cdebbuf_free() after use. - */ - -_cdebbuf *capi_cmsg2str(_cmsg *cmsg) -{ - _cdebbuf *cdb; - - if (!cmsg->m) - return NULL; /* no message */ - cdb = cdebbuf_alloc(); - if (!cdb) - return NULL; - cmsg->l = 8; - cmsg->p = 0; - cdb = bufprint(cdb, "%s ID=%03d #0x%04x LEN=%04d\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - ((u16 *) cmsg->m)[1], - ((u16 *) cmsg->m)[3], - ((u16 *) cmsg->m)[0]); - cdb = protocol_message_2_pars(cdb, cmsg, 1); - return cdb; -} - int __init cdebug_init(void) { g_cmsg = kmalloc(sizeof(_cmsg), GFP_KERNEL); @@ -854,7 +639,7 @@ int __init cdebug_init(void) return 0; } -void __exit cdebug_exit(void) +void cdebug_exit(void) { if (g_debbuf) kfree(g_debbuf->buf); @@ -885,16 +670,8 @@ int __init cdebug_init(void) return 0; } -void __exit cdebug_exit(void) +void cdebug_exit(void) { } #endif - -EXPORT_SYMBOL(cdebbuf_free); -EXPORT_SYMBOL(capi_cmsg2message); -EXPORT_SYMBOL(capi_message2cmsg); -EXPORT_SYMBOL(capi_cmsg_header); -EXPORT_SYMBOL(capi_cmd2str); -EXPORT_SYMBOL(capi_cmsg2str); -EXPORT_SYMBOL(capi_message2str); diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index a4ceb61c5b60..7168778fbbe1 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c @@ -10,8 +10,6 @@ * */ -#define AVMB1_COMPAT - #include "kcapi.h" #include <linux/module.h> #include <linux/mm.h> @@ -31,18 +29,12 @@ #include <linux/uaccess.h> #include <linux/isdn/capicmd.h> #include <linux/isdn/capiutil.h> -#ifdef AVMB1_COMPAT -#include <linux/b1lli.h> -#endif #include <linux/mutex.h> #include <linux/rcupdate.h> static int showcapimsgs = 0; static struct workqueue_struct *kcapi_wq; -MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer"); -MODULE_AUTHOR("Carsten Paeth"); -MODULE_LICENSE("GPL"); module_param(showcapimsgs, uint, 0); /* ------------------------------------------------------------- */ @@ -61,9 +53,6 @@ static char capi_manufakturer[64] = "AVM Berlin"; #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) -LIST_HEAD(capi_drivers); -DEFINE_MUTEX(capi_drivers_lock); - struct capi_ctr *capi_controller[CAPI_MAXCONTR]; DEFINE_MUTEX(capi_controller_lock); @@ -71,8 +60,6 @@ struct capi20_appl *capi_applications[CAPI_MAXAPPL]; static int ncontrollers; -static BLOCKING_NOTIFIER_HEAD(ctr_notifier_list); - /* -------- controller ref counting -------------------------------------- */ static inline struct capi_ctr * @@ -200,8 +187,6 @@ static void notify_up(u32 contr) if (ap) register_appl(ctr, applid, &ap->rparam); } - - wake_up_interruptible_all(&ctr->state_wait_queue); } else printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr); @@ -229,8 +214,6 @@ static void ctr_down(struct capi_ctr *ctr, int new_state) if (ap) capi_ctr_put(ctr); } - - wake_up_interruptible_all(&ctr->state_wait_queue); } static void notify_down(u32 contr) @@ -251,36 +234,23 @@ static void notify_down(u32 contr) mutex_unlock(&capi_controller_lock); } -static int -notify_handler(struct notifier_block *nb, unsigned long val, void *v) +static void do_notify_work(struct work_struct *work) { - u32 contr = (long)v; + struct capictr_event *event = + container_of(work, struct capictr_event, work); - switch (val) { + switch (event->type) { case CAPICTR_UP: - notify_up(contr); + notify_up(event->controller); break; case CAPICTR_DOWN: - notify_down(contr); + notify_down(event->controller); break; } - return NOTIFY_OK; -} -static void do_notify_work(struct work_struct *work) -{ - struct capictr_event *event = - container_of(work, struct capictr_event, work); - - blocking_notifier_call_chain(&ctr_notifier_list, event->type, - (void *)(long)event->controller); kfree(event); } -/* - * The notifier will result in adding/deleteing of devices. Devices can - * only removed in user process, not in bh. - */ static int notify_push(unsigned int event_type, u32 controller) { struct capictr_event *event = kmalloc(sizeof(*event), GFP_ATOMIC); @@ -296,18 +266,6 @@ static int notify_push(unsigned int event_type, u32 controller) return 0; } -int register_capictr_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&ctr_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(register_capictr_notifier); - -int unregister_capictr_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&ctr_notifier_list, nb); -} -EXPORT_SYMBOL_GPL(unregister_capictr_notifier); - /* -------- Receiver ------------------------------------------ */ static void recv_handler(struct work_struct *work) @@ -454,48 +412,6 @@ void capi_ctr_down(struct capi_ctr *ctr) EXPORT_SYMBOL(capi_ctr_down); -/** - * capi_ctr_suspend_output() - suspend controller - * @ctr: controller descriptor structure. - * - * Called by hardware driver to stop data flow. - * - * Note: The caller is responsible for synchronizing concurrent state changes - * as well as invocations of capi_ctr_handle_message. - */ - -void capi_ctr_suspend_output(struct capi_ctr *ctr) -{ - if (!ctr->blocked) { - printk(KERN_DEBUG "kcapi: controller [%03d] suspend\n", - ctr->cnr); - ctr->blocked = 1; - } -} - -EXPORT_SYMBOL(capi_ctr_suspend_output); - -/** - * capi_ctr_resume_output() - resume controller - * @ctr: controller descriptor structure. - * - * Called by hardware driver to resume data flow. - * - * Note: The caller is responsible for synchronizing concurrent state changes - * as well as invocations of capi_ctr_handle_message. - */ - -void capi_ctr_resume_output(struct capi_ctr *ctr) -{ - if (ctr->blocked) { - printk(KERN_DEBUG "kcapi: controller [%03d] resumed\n", - ctr->cnr); - ctr->blocked = 0; - } -} - -EXPORT_SYMBOL(capi_ctr_resume_output); - /* ------------------------------------------------------------- */ /** @@ -531,7 +447,6 @@ int attach_capi_ctr(struct capi_ctr *ctr) ctr->state = CAPI_CTR_DETECTED; ctr->blocked = 0; ctr->traceflag = showcapimsgs; - init_waitqueue_head(&ctr->state_wait_queue); sprintf(ctr->procfn, "capi/controllers/%d", ctr->cnr); ctr->procent = proc_create_single_data(ctr->procfn, 0, NULL, @@ -586,38 +501,6 @@ unlock_out: EXPORT_SYMBOL(detach_capi_ctr); -/** - * register_capi_driver() - register CAPI driver - * @driver: driver descriptor structure. - * - * Called by hardware driver to register itself with the CAPI subsystem. - */ - -void register_capi_driver(struct capi_driver *driver) -{ - mutex_lock(&capi_drivers_lock); - list_add_tail(&driver->list, &capi_drivers); - mutex_unlock(&capi_drivers_lock); -} - -EXPORT_SYMBOL(register_capi_driver); - -/** - * unregister_capi_driver() - unregister CAPI driver - * @driver: driver descriptor structure. - * - * Called by hardware driver to unregister itself from the CAPI subsystem. - */ - -void unregister_capi_driver(struct capi_driver *driver) -{ - mutex_lock(&capi_drivers_lock); - list_del(&driver->list); - mutex_unlock(&capi_drivers_lock); -} - -EXPORT_SYMBOL(unregister_capi_driver); - /* ------------------------------------------------------------- */ /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ @@ -648,8 +531,6 @@ u16 capi20_isinstalled(void) return ret; } -EXPORT_SYMBOL(capi20_isinstalled); - /** * capi20_register() - CAPI 2.0 operation CAPI_REGISTER * @ap: CAPI application descriptor structure. @@ -711,8 +592,6 @@ u16 capi20_register(struct capi20_appl *ap) return CAPI_NOERROR; } -EXPORT_SYMBOL(capi20_register); - /** * capi20_release() - CAPI 2.0 operation CAPI_RELEASE * @ap: CAPI application descriptor structure. @@ -755,8 +634,6 @@ u16 capi20_release(struct capi20_appl *ap) return CAPI_NOERROR; } -EXPORT_SYMBOL(capi20_release); - /** * capi20_put_message() - CAPI 2.0 operation CAPI_PUT_MESSAGE * @ap: CAPI application descriptor structure. @@ -834,8 +711,6 @@ u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb) return ctr->send_message(ctr, skb); } -EXPORT_SYMBOL(capi20_put_message); - /** * capi20_get_manufacturer() - CAPI 2.0 operation CAPI_GET_MANUFACTURER * @contr: controller number. @@ -869,8 +744,6 @@ u16 capi20_get_manufacturer(u32 contr, u8 *buf) return ret; } -EXPORT_SYMBOL(capi20_get_manufacturer); - /** * capi20_get_version() - CAPI 2.0 operation CAPI_GET_VERSION * @contr: controller number. @@ -904,8 +777,6 @@ u16 capi20_get_version(u32 contr, struct capi_version *verp) return ret; } -EXPORT_SYMBOL(capi20_get_version); - /** * capi20_get_serial() - CAPI 2.0 operation CAPI_GET_SERIAL_NUMBER * @contr: controller number. @@ -939,8 +810,6 @@ u16 capi20_get_serial(u32 contr, u8 *serial) return ret; } -EXPORT_SYMBOL(capi20_get_serial); - /** * capi20_get_profile() - CAPI 2.0 operation CAPI_GET_PROFILE * @contr: controller number. @@ -974,209 +843,6 @@ u16 capi20_get_profile(u32 contr, struct capi_profile *profp) return ret; } -EXPORT_SYMBOL(capi20_get_profile); - -/* Must be called with capi_controller_lock held. */ -static int wait_on_ctr_state(struct capi_ctr *ctr, unsigned int state) -{ - DEFINE_WAIT(wait); - int retval = 0; - - ctr = capi_ctr_get(ctr); - if (!ctr) - return -ESRCH; - - for (;;) { - prepare_to_wait(&ctr->state_wait_queue, &wait, - TASK_INTERRUPTIBLE); - - if (ctr->state == state) - break; - if (ctr->state == CAPI_CTR_DETACHED) { - retval = -ESRCH; - break; - } - if (signal_pending(current)) { - retval = -EINTR; - break; - } - - mutex_unlock(&capi_controller_lock); - schedule(); - mutex_lock(&capi_controller_lock); - } - finish_wait(&ctr->state_wait_queue, &wait); - - capi_ctr_put(ctr); - - return retval; -} - -#ifdef AVMB1_COMPAT -static int old_capi_manufacturer(unsigned int cmd, void __user *data) -{ - avmb1_loadandconfigdef ldef; - avmb1_extcarddef cdef; - avmb1_resetdef rdef; - capicardparams cparams; - struct capi_ctr *ctr; - struct capi_driver *driver = NULL; - capiloaddata ldata; - struct list_head *l; - int retval; - - switch (cmd) { - case AVMB1_ADDCARD: - case AVMB1_ADDCARD_WITH_TYPE: - if (cmd == AVMB1_ADDCARD) { - if ((retval = copy_from_user(&cdef, data, - sizeof(avmb1_carddef)))) - return -EFAULT; - cdef.cardtype = AVM_CARDTYPE_B1; - cdef.cardnr = 0; - } else { - if ((retval = copy_from_user(&cdef, data, - sizeof(avmb1_extcarddef)))) - return -EFAULT; - } - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.cardnr = cdef.cardnr; - - mutex_lock(&capi_drivers_lock); - - switch (cdef.cardtype) { - case AVM_CARDTYPE_B1: - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, "b1isa") == 0) - break; - } - break; - case AVM_CARDTYPE_T1: - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, "t1isa") == 0) - break; - } - break; - default: - driver = NULL; - break; - } - if (!driver) { - printk(KERN_ERR "kcapi: driver not loaded.\n"); - retval = -EIO; - } else if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver has no add card function.\n"); - retval = -EIO; - } else - retval = driver->add_card(driver, &cparams); - - mutex_unlock(&capi_drivers_lock); - return retval; - - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - - if (cmd == AVMB1_LOAD) { - if (copy_from_user(&ldef, data, - sizeof(avmb1_loaddef))) - return -EFAULT; - ldef.t4config.len = 0; - ldef.t4config.data = NULL; - } else { - if (copy_from_user(&ldef, data, - sizeof(avmb1_loadandconfigdef))) - return -EFAULT; - } - - mutex_lock(&capi_controller_lock); - - ctr = get_capi_ctr_by_nr(ldef.contr); - if (!ctr) { - retval = -EINVAL; - goto load_unlock_out; - } - - if (ctr->load_firmware == NULL) { - printk(KERN_DEBUG "kcapi: load: no load function\n"); - retval = -ESRCH; - goto load_unlock_out; - } - - if (ldef.t4file.len <= 0) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - retval = -EINVAL; - goto load_unlock_out; - } - if (ldef.t4file.data == NULL) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - retval = -EINVAL; - goto load_unlock_out; - } - - ldata.firmware.user = 1; - ldata.firmware.data = ldef.t4file.data; - ldata.firmware.len = ldef.t4file.len; - ldata.configuration.user = 1; - ldata.configuration.data = ldef.t4config.data; - ldata.configuration.len = ldef.t4config.len; - - if (ctr->state != CAPI_CTR_DETECTED) { - printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - retval = -EBUSY; - goto load_unlock_out; - } - ctr->state = CAPI_CTR_LOADING; - - retval = ctr->load_firmware(ctr, &ldata); - if (retval) { - ctr->state = CAPI_CTR_DETECTED; - goto load_unlock_out; - } - - retval = wait_on_ctr_state(ctr, CAPI_CTR_RUNNING); - - load_unlock_out: - mutex_unlock(&capi_controller_lock); - return retval; - - case AVMB1_RESETCARD: - if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef))) - return -EFAULT; - - retval = 0; - - mutex_lock(&capi_controller_lock); - - ctr = get_capi_ctr_by_nr(rdef.contr); - if (!ctr) { - retval = -ESRCH; - goto reset_unlock_out; - } - - if (ctr->state == CAPI_CTR_DETECTED) - goto reset_unlock_out; - - if (ctr->reset_ctr == NULL) { - printk(KERN_DEBUG "kcapi: reset: no reset function\n"); - retval = -ESRCH; - goto reset_unlock_out; - } - - ctr->reset_ctr(ctr); - - retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); - - reset_unlock_out: - mutex_unlock(&capi_controller_lock); - return retval; - } - return -EINVAL; -} -#endif - /** * capi20_manufacturer() - CAPI 2.0 operation CAPI_MANUFACTURER * @cmd: command. @@ -1192,14 +858,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) int retval; switch (cmd) { -#ifdef AVMB1_COMPAT - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - case AVMB1_RESETCARD: - case AVMB1_GET_CARDINFO: - case AVMB1_REMOVECARD: - return old_capi_manufacturer(cmd, data); -#endif case KCAPI_CMD_TRACE: { kcapi_flagdef fdef; @@ -1222,43 +880,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) return retval; } - case KCAPI_CMD_ADDCARD: - { - struct list_head *l; - struct capi_driver *driver = NULL; - capicardparams cparams; - kcapi_carddef cdef; - - if ((retval = copy_from_user(&cdef, data, sizeof(cdef)))) - return -EFAULT; - - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.membase = cdef.membase; - cparams.cardnr = cdef.cardnr; - cparams.cardtype = 0; - cdef.driver[sizeof(cdef.driver) - 1] = 0; - - mutex_lock(&capi_drivers_lock); - - list_for_each(l, &capi_drivers) { - driver = list_entry(l, struct capi_driver, list); - if (strcmp(driver->name, cdef.driver) == 0) - break; - } - if (driver == NULL) { - printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", - cdef.driver); - retval = -ESRCH; - } else if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); - retval = -EIO; - } else - retval = driver->add_card(driver, &cparams); - - mutex_unlock(&capi_drivers_lock); - return retval; - } default: printk(KERN_ERR "kcapi: manufacturer command %lu unknown.\n", @@ -1269,8 +890,6 @@ int capi20_manufacturer(unsigned long cmd, void __user *data) return -EINVAL; } -EXPORT_SYMBOL(capi20_manufacturer); - /* ------------------------------------------------------------- */ /* -------- Init & Cleanup ------------------------------------- */ /* ------------------------------------------------------------- */ @@ -1279,12 +898,7 @@ EXPORT_SYMBOL(capi20_manufacturer); * init / exit functions */ -static struct notifier_block capictr_nb = { - .notifier_call = notify_handler, - .priority = INT_MAX, -}; - -static int __init kcapi_init(void) +int __init kcapi_init(void) { int err; @@ -1292,11 +906,8 @@ static int __init kcapi_init(void) if (!kcapi_wq) return -ENOMEM; - register_capictr_notifier(&capictr_nb); - err = cdebug_init(); if (err) { - unregister_capictr_notifier(&capictr_nb); destroy_workqueue(kcapi_wq); return err; } @@ -1305,14 +916,10 @@ static int __init kcapi_init(void) return 0; } -static void __exit kcapi_exit(void) +void kcapi_exit(void) { kcapi_proc_exit(); - unregister_capictr_notifier(&capictr_nb); cdebug_exit(); destroy_workqueue(kcapi_wq); } - -module_init(kcapi_init); -module_exit(kcapi_exit); diff --git a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h index 6d439f9a76b2..479623e1db2a 100644 --- a/drivers/isdn/capi/kcapi.h +++ b/drivers/isdn/capi/kcapi.h @@ -30,22 +30,153 @@ enum { CAPI_CTR_RUNNING = 3, }; -extern struct list_head capi_drivers; -extern struct mutex capi_drivers_lock; - extern struct capi_ctr *capi_controller[CAPI_MAXCONTR]; extern struct mutex capi_controller_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; -#ifdef CONFIG_PROC_FS - void kcapi_proc_init(void); void kcapi_proc_exit(void); -#else +struct capi20_appl { + u16 applid; + capi_register_params rparam; + void (*recv_message)(struct capi20_appl *ap, struct sk_buff *skb); + void *private; -static inline void kcapi_proc_init(void) { }; -static inline void kcapi_proc_exit(void) { }; + /* internal to kernelcapi.o */ + unsigned long nrecvctlpkt; + unsigned long nrecvdatapkt; + unsigned long nsentctlpkt; + unsigned long nsentdatapkt; + struct mutex recv_mtx; + struct sk_buff_head recv_queue; + struct work_struct recv_work; + int release_in_progress; +}; -#endif +u16 capi20_isinstalled(void); +u16 capi20_register(struct capi20_appl *ap); +u16 capi20_release(struct capi20_appl *ap); +u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb); +u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]); +u16 capi20_get_version(u32 contr, struct capi_version *verp); +u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN]); +u16 capi20_get_profile(u32 contr, struct capi_profile *profp); +int capi20_manufacturer(unsigned long cmd, void __user *data); + +#define CAPICTR_UP 0 +#define CAPICTR_DOWN 1 + +int kcapi_init(void); +void kcapi_exit(void); + +/*----- basic-type definitions -----*/ + +typedef __u8 *_cstruct; + +typedef enum { + CAPI_COMPOSE, + CAPI_DEFAULT +} _cmstruct; + +/* + The _cmsg structure contains all possible CAPI 2.0 parameter. + All parameters are stored here first. The function CAPI_CMSG_2_MESSAGE + assembles the parameter and builds CAPI2.0 conform messages. + CAPI_MESSAGE_2_CMSG disassembles CAPI 2.0 messages and stores the + parameter in the _cmsg structure + */ + +typedef struct { + /* Header */ + __u16 ApplId; + __u8 Command; + __u8 Subcommand; + __u16 Messagenumber; + + /* Parameter */ + union { + __u32 adrController; + __u32 adrPLCI; + __u32 adrNCCI; + } adr; + + _cmstruct AdditionalInfo; + _cstruct B1configuration; + __u16 B1protocol; + _cstruct B2configuration; + __u16 B2protocol; + _cstruct B3configuration; + __u16 B3protocol; + _cstruct BC; + _cstruct BChannelinformation; + _cmstruct BProtocol; + _cstruct CalledPartyNumber; + _cstruct CalledPartySubaddress; + _cstruct CallingPartyNumber; + _cstruct CallingPartySubaddress; + __u32 CIPmask; + __u32 CIPmask2; + __u16 CIPValue; + __u32 Class; + _cstruct ConnectedNumber; + _cstruct ConnectedSubaddress; + __u32 Data; + __u16 DataHandle; + __u16 DataLength; + _cstruct FacilityConfirmationParameter; + _cstruct Facilitydataarray; + _cstruct FacilityIndicationParameter; + _cstruct FacilityRequestParameter; + __u16 FacilitySelector; + __u16 Flags; + __u32 Function; + _cstruct HLC; + __u16 Info; + _cstruct InfoElement; + __u32 InfoMask; + __u16 InfoNumber; + _cstruct Keypadfacility; + _cstruct LLC; + _cstruct ManuData; + __u32 ManuID; + _cstruct NCPI; + __u16 Reason; + __u16 Reason_B3; + __u16 Reject; + _cstruct Useruserdata; + + /* intern */ + unsigned l, p; + unsigned char *par; + __u8 *m; + + /* buffer to construct message */ + __u8 buf[180]; + +} _cmsg; + +/*-----------------------------------------------------------------------*/ + +/* + * Debugging / Tracing functions + */ + +char *capi_cmd2str(__u8 cmd, __u8 subcmd); + +typedef struct { + u_char *buf; + u_char *p; + size_t size; + size_t pos; +} _cdebbuf; + +#define CDEBUG_SIZE 1024 +#define CDEBUG_GSIZE 4096 + +void cdebbuf_free(_cdebbuf *cdb); +int cdebug_init(void); +void cdebug_exit(void); + +_cdebbuf *capi_message2str(__u8 *msg); diff --git a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c index c94bd12c0f7c..b5ed4ea145cb 100644 --- a/drivers/isdn/capi/kcapi_proc.c +++ b/drivers/isdn/capi/kcapi_proc.c @@ -192,37 +192,15 @@ static const struct seq_operations seq_applstats_ops = { // --------------------------------------------------------------------------- -static void *capi_driver_start(struct seq_file *seq, loff_t *pos) - __acquires(&capi_drivers_lock) +/* /proc/capi/drivers is always empty */ +static ssize_t empty_read(struct file *file, char __user *buf, + size_t size, loff_t *off) { - mutex_lock(&capi_drivers_lock); - return seq_list_start(&capi_drivers, *pos); -} - -static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) -{ - return seq_list_next(v, &capi_drivers, pos); -} - -static void capi_driver_stop(struct seq_file *seq, void *v) - __releases(&capi_drivers_lock) -{ - mutex_unlock(&capi_drivers_lock); -} - -static int capi_driver_show(struct seq_file *seq, void *v) -{ - struct capi_driver *drv = list_entry(v, struct capi_driver, list); - - seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); return 0; } -static const struct seq_operations seq_capi_driver_ops = { - .start = capi_driver_start, - .next = capi_driver_next, - .stop = capi_driver_stop, - .show = capi_driver_show, +static const struct proc_ops empty_proc_ops = { + .proc_read = empty_read, }; // --------------------------------------------------------------------------- @@ -236,10 +214,10 @@ kcapi_proc_init(void) proc_create_seq("capi/contrstats", 0, NULL, &seq_contrstats_ops); proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops); proc_create_seq("capi/applstats", 0, NULL, &seq_applstats_ops); - proc_create_seq("capi/driver", 0, NULL, &seq_capi_driver_ops); + proc_create("capi/driver", 0, NULL, &empty_proc_ops); } -void __exit +void kcapi_proc_exit(void) { remove_proc_entry("capi/driver", NULL); diff --git a/drivers/isdn/hardware/mISDN/Kconfig b/drivers/isdn/hardware/mISDN/Kconfig index 304f50c08da2..078eeadf707a 100644 --- a/drivers/isdn/hardware/mISDN/Kconfig +++ b/drivers/isdn/hardware/mISDN/Kconfig @@ -10,7 +10,7 @@ config MISDN_HFCPCI depends on PCI help Enable support for cards with Cologne Chip AG's - HFC PCI chip. + HFC PCI chip. config MISDN_HFCMULTI tristate "Support for HFC multiport cards (HFC-4S/8S/E1)" diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index 81f2b183acc8..ecc1ef6c386d 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -402,8 +402,8 @@ hdlc_empty_fifo(struct bchannel *bch, int count) } else { cnt = bchannel_get_rxbuf(bch, count); if (cnt < 0) { - pr_warning("%s.B%d: No bufferspace for %d bytes\n", - fc->name, bch->nr, count); + pr_warn("%s.B%d: No bufferspace for %d bytes\n", + fc->name, bch->nr, count); return; } p = skb_put(bch->rx_skb, count); @@ -509,8 +509,7 @@ HDLC_irq_xpr(struct bchannel *bch) if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) { hdlc_fill_fifo(bch); } else { - if (bch->tx_skb) - dev_kfree_skb(bch->tx_skb); + dev_kfree_skb(bch->tx_skb); if (get_next_bframe(bch)) { hdlc_fill_fifo(bch); test_and_clear_bit(FLG_TX_EMPTY, &bch->Flags); @@ -539,8 +538,8 @@ HDLC_irq(struct bchannel *bch, u32 stat) } if (stat & HDLC_INT_RPR) { if (stat & HDLC_STAT_RDO) { - pr_warning("%s: ch%d stat %x RDO\n", - fc->name, bch->nr, stat); + pr_warn("%s: ch%d stat %x RDO\n", + fc->name, bch->nr, stat); hdlc->ctrl.sr.xml = 0; hdlc->ctrl.sr.cmd |= HDLC_CMD_RRS; write_ctrl(bch, 1); @@ -562,8 +561,8 @@ HDLC_irq(struct bchannel *bch, u32 stat) HDLC_STAT_CRCVFR) { recv_Bchannel(bch, 0, false); } else { - pr_warning("%s: got invalid frame\n", - fc->name); + pr_warn("%s: got invalid frame\n", + fc->name); skb_trim(bch->rx_skb, 0); } } @@ -575,8 +574,8 @@ handle_tx: * restart transmitting the whole frame on HDLC * in transparent mode we send the next data */ - pr_warning("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr, - stat, bch->tx_skb ? "tx_skb" : "no tx_skb"); + pr_warn("%s: ch%d stat %x XDU %s\n", fc->name, bch->nr, + stat, bch->tx_skb ? "tx_skb" : "no tx_skb"); if (bch->tx_skb && bch->tx_skb->len) { if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) bch->tx_idx = 0; diff --git a/drivers/isdn/hardware/mISDN/hfcmulti.c b/drivers/isdn/hardware/mISDN/hfcmulti.c index 86669ec8b977..7013a3f08429 100644 --- a/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -2248,8 +2248,8 @@ next_frame: if (bch) { maxlen = bchannel_get_rxbuf(bch, Zsize); if (maxlen < 0) { - pr_warning("card%d.B%d: No bufferspace for %d bytes\n", - hc->id + 1, bch->nr, Zsize); + pr_warn("card%d.B%d: No bufferspace for %d bytes\n", + hc->id + 1, bch->nr, Zsize); return; } sp = &bch->rx_skb; @@ -2260,8 +2260,8 @@ next_frame: if (*sp == NULL) { *sp = mI_alloc_skb(maxlen, GFP_ATOMIC); if (*sp == NULL) { - pr_warning("card%d: No mem for dch rx_skb\n", - hc->id + 1); + pr_warn("card%d: No mem for dch rx_skb\n", + hc->id + 1); return; } } diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 4a069582fc6b..abdf787c1a71 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -566,8 +566,7 @@ hfcpci_empty_fifo_trans(struct bchannel *bch, struct bzfifo *rxbz, } maxlen = bchannel_get_rxbuf(bch, fcnt_rx); if (maxlen < 0) { - pr_warning("B%d: No bufferspace for %d bytes\n", - bch->nr, fcnt_rx); + pr_warn("B%d: No bufferspace for %d bytes\n", bch->nr, fcnt_rx); } else { ptr = skb_put(bch->rx_skb, fcnt_rx); if (le16_to_cpu(*z2r) + fcnt_rx <= B_FIFO_SIZE + B_SUB_VAL) @@ -1119,8 +1118,7 @@ tx_birq(struct bchannel *bch) if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len) hfcpci_fill_fifo(bch); else { - if (bch->tx_skb) - dev_kfree_skb(bch->tx_skb); + dev_kfree_skb(bch->tx_skb); if (get_next_bframe(bch)) hfcpci_fill_fifo(bch); } @@ -1132,8 +1130,7 @@ tx_dirq(struct dchannel *dch) if (dch->tx_skb && dch->tx_idx < dch->tx_skb->len) hfcpci_fill_dfifo(dch->hw); else { - if (dch->tx_skb) - dev_kfree_skb(dch->tx_skb); + dev_kfree_skb(dch->tx_skb); if (get_next_dframe(dch)) hfcpci_fill_dfifo(dch->hw); } diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 008a74a1ed44..621364bb6b12 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -841,8 +841,8 @@ hfcsusb_rx_frame(struct usb_fifo *fifo, __u8 *data, unsigned int len, if (maxlen < 0) { if (rx_skb) skb_trim(rx_skb, 0); - pr_warning("%s.B%d: No bufferspace for %d bytes\n", - hw->name, fifo->bch->nr, len); + pr_warn("%s.B%d: No bufferspace for %d bytes\n", + hw->name, fifo->bch->nr, len); spin_unlock_irqrestore(&hw->lock, flags); return; } diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.h b/drivers/isdn/hardware/mISDN/hfcsusb.h index e4fa2a2824af..7e2bc5068019 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.h +++ b/drivers/isdn/hardware/mISDN/hfcsusb.h @@ -173,8 +173,8 @@ symbolic(struct hfcusb_symbolic_list list[], const int num) /* - * List of all supported enpoints configiration sets, used to find the - * best matching endpoint configuration within a devices' USB descriptor. + * List of all supported endpoint configuration sets, used to find the + * best matching endpoint configuration within a device's USB descriptor. * We need at least 3 RX endpoints, and 3 TX endpoints, either * INT-in and ISO-out, or ISO-in and ISO-out) * with 4 RX endpoints even E-Channel logging is possible diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index f915399d75ca..ec475087fbf9 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -190,8 +190,7 @@ isac_rme_irq(struct isac_hw *isac) #endif } WriteISAC(isac, ISAC_CMDR, 0x80); - if (isac->dch.rx_skb) - dev_kfree_skb(isac->dch.rx_skb); + dev_kfree_skb(isac->dch.rx_skb); isac->dch.rx_skb = NULL; } else { count = ReadISAC(isac, ISAC_RBCL) & 0x1f; @@ -210,8 +209,7 @@ isac_xpr_irq(struct isac_hw *isac) if (isac->dch.tx_skb && isac->dch.tx_idx < isac->dch.tx_skb->len) { isac_fill_fifo(isac); } else { - if (isac->dch.tx_skb) - dev_kfree_skb(isac->dch.tx_skb); + dev_kfree_skb(isac->dch.tx_skb); if (get_next_dframe(&isac->dch)) isac_fill_fifo(isac); } @@ -464,8 +462,7 @@ isacsx_rme_irq(struct isac_hw *isac) isac->dch.err_crc++; #endif WriteISAC(isac, ISACX_CMDRD, ISACX_CMDRD_RMC); - if (isac->dch.rx_skb) - dev_kfree_skb(isac->dch.rx_skb); + dev_kfree_skb(isac->dch.rx_skb); isac->dch.rx_skb = NULL; } else { count = ReadISAC(isac, ISACX_RBCLD) & 0x1f; @@ -939,8 +936,8 @@ hscx_empty_fifo(struct hscx_hw *hscx, u8 count) hscx_cmdr(hscx, 0x80); /* RMC */ if (hscx->bch.rx_skb) skb_trim(hscx->bch.rx_skb, 0); - pr_warning("%s.B%d: No bufferspace for %d bytes\n", - hscx->ip->name, hscx->bch.nr, count); + pr_warn("%s.B%d: No bufferspace for %d bytes\n", + hscx->ip->name, hscx->bch.nr, count); return; } p = skb_put(hscx->bch.rx_skb, count); @@ -1012,8 +1009,7 @@ hscx_xpr(struct hscx_hw *hx) if (hx->bch.tx_skb && hx->bch.tx_idx < hx->bch.tx_skb->len) { hscx_fill_fifo(hx); } else { - if (hx->bch.tx_skb) - dev_kfree_skb(hx->bch.tx_skb); + dev_kfree_skb(hx->bch.tx_skb); if (get_next_bframe(&hx->bch)) { hscx_fill_fifo(hx); test_and_clear_bit(FLG_TX_EMPTY, &hx->bch.Flags); diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index fd5c52f37802..e325e87c0593 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -27,7 +27,6 @@ MODULE_VERSION(ISAR_REV); #define DEBUG_HW_FIRMWARE_FIFO 0x10000 -static const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; static const u8 faxmodulation[] = {3, 24, 48, 72, 73, 74, 96, 97, 98, 121, 122, 145, 146}; #define FAXMODCNT 13 @@ -222,7 +221,7 @@ load_firmware(struct isar_hw *isar, const u8 *buf, int size) goto reterror; } if (!poll_mbox(isar, 1000)) { - pr_warning("ISAR poll_mbox dkey failed\n"); + pr_warn("ISAR poll_mbox dkey failed\n"); ret = -ETIME; goto reterror; } @@ -432,8 +431,8 @@ isar_rcv_frame(struct isar_ch *ch) case ISDN_P_B_MODEM_ASYNC: maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); if (maxlen < 0) { - pr_warning("%s.B%d: No bufferspace for %d bytes\n", - ch->is->name, ch->bch.nr, ch->is->clsb); + pr_warn("%s.B%d: No bufferspace for %d bytes\n", + ch->is->name, ch->bch.nr, ch->is->clsb); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } @@ -443,8 +442,8 @@ isar_rcv_frame(struct isar_ch *ch) case ISDN_P_B_HDLC: maxlen = bchannel_get_rxbuf(&ch->bch, ch->is->clsb); if (maxlen < 0) { - pr_warning("%s.B%d: No bufferspace for %d bytes\n", - ch->is->name, ch->bch.nr, ch->is->clsb); + pr_warn("%s.B%d: No bufferspace for %d bytes\n", + ch->is->name, ch->bch.nr, ch->is->clsb); ch->is->write_reg(ch->is->hw, ISAR_IIA, 0); break; } @@ -690,8 +689,7 @@ send_next(struct isar_ch *ch) } } } - if (ch->bch.tx_skb) - dev_kfree_skb(ch->bch.tx_skb); + dev_kfree_skb(ch->bch.tx_skb); if (get_next_bframe(&ch->bch)) { isar_fill_fifo(ch); test_and_clear_bit(FLG_TX_EMPTY, &ch->bch.Flags); diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c index 4e30affd1a7c..6aae97e827b7 100644 --- a/drivers/isdn/hardware/mISDN/netjet.c +++ b/drivers/isdn/hardware/mISDN/netjet.c @@ -380,8 +380,8 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt) stat = bchannel_get_rxbuf(&bc->bch, cnt); /* only transparent use the count here, HDLC overun is detected later */ if (stat == -ENOMEM) { - pr_warning("%s.B%d: No memory for %d bytes\n", - card->name, bc->bch.nr, cnt); + pr_warn("%s.B%d: No memory for %d bytes\n", + card->name, bc->bch.nr, cnt); return; } if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) @@ -420,8 +420,8 @@ read_dma(struct tiger_ch *bc, u32 idx, int cnt) recv_Bchannel(&bc->bch, 0, false); stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen); if (stat < 0) { - pr_warning("%s.B%d: No memory for %d bytes\n", - card->name, bc->bch.nr, cnt); + pr_warn("%s.B%d: No memory for %d bytes\n", + card->name, bc->bch.nr, cnt); return; } } else if (stat == -HDLC_CRC_ERROR) { @@ -605,8 +605,7 @@ bc_next_frame(struct tiger_ch *bc) if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) { fill_dma(bc); } else { - if (bc->bch.tx_skb) - dev_kfree_skb(bc->bch.tx_skb); + dev_kfree_skb(bc->bch.tx_skb); if (get_next_bframe(&bc->bch)) { fill_dma(bc); test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags); diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c index 2402608dc98d..f3b8db7b48fe 100644 --- a/drivers/isdn/hardware/mISDN/w6692.c +++ b/drivers/isdn/hardware/mISDN/w6692.c @@ -356,8 +356,7 @@ handle_rxD(struct w6692_hw *card) { card->dch.err_rx++; #endif } - if (card->dch.rx_skb) - dev_kfree_skb(card->dch.rx_skb); + dev_kfree_skb(card->dch.rx_skb); card->dch.rx_skb = NULL; WriteW6692(card, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); } else { @@ -376,8 +375,7 @@ handle_txD(struct w6692_hw *card) { if (card->dch.tx_skb && card->dch.tx_idx < card->dch.tx_skb->len) { W6692_fill_Dfifo(card); } else { - if (card->dch.tx_skb) - dev_kfree_skb(card->dch.tx_skb); + dev_kfree_skb(card->dch.tx_skb); if (get_next_dframe(&card->dch)) W6692_fill_Dfifo(card); } @@ -468,8 +466,8 @@ W6692_empty_Bfifo(struct w6692_ch *wch, int count) WriteW6692B(wch, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); if (wch->bch.rx_skb) skb_trim(wch->bch.rx_skb, 0); - pr_warning("%s.B%d: No bufferspace for %d bytes\n", - card->name, wch->bch.nr, count); + pr_warn("%s.B%d: No bufferspace for %d bytes\n", + card->name, wch->bch.nr, count); return; } ptr = skb_put(wch->bch.rx_skb, count); @@ -636,8 +634,7 @@ send_next(struct w6692_ch *wch) if (wch->bch.tx_skb && wch->bch.tx_idx < wch->bch.tx_skb->len) { W6692_fill_Bfifo(wch); } else { - if (wch->bch.tx_skb) - dev_kfree_skb(wch->bch.tx_skb); + dev_kfree_skb(wch->bch.tx_skb); if (get_next_bframe(&wch->bch)) { W6692_fill_Bfifo(wch); test_and_clear_bit(FLG_TX_EMPTY, &wch->bch.Flags); @@ -732,8 +729,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch) wch->bch.nr, star); } if (star & W_B_STAR_XDOW) { - pr_warning("%s: B%d XDOW proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); + pr_warn("%s: B%d XDOW proto=%x\n", card->name, + wch->bch.nr, wch->bch.state); #ifdef ERROR_STATISTIC wch->bch.err_xdu++; #endif @@ -750,8 +747,8 @@ W6692B_interrupt(struct w6692_hw *card, int ch) return; /* handle XDOW only once */ } if (stat & W_B_EXI_XDUN) { - pr_warning("%s: B%d XDUN proto=%x\n", card->name, - wch->bch.nr, wch->bch.state); + pr_warn("%s: B%d XDUN proto=%x\n", card->name, + wch->bch.nr, wch->bch.state); #ifdef ERROR_STATISTIC wch->bch.err_xdu++; #endif diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c index f378173bcf6f..8c93af06ed02 100644 --- a/drivers/isdn/mISDN/hwchannel.c +++ b/drivers/isdn/mISDN/hwchannel.c @@ -474,8 +474,8 @@ bchannel_get_rxbuf(struct bchannel *bch, int reqlen) if (bch->rx_skb) { len = skb_tailroom(bch->rx_skb); if (len < reqlen) { - pr_warning("B%d no space for %d (only %d) bytes\n", - bch->nr, reqlen, len); + pr_warn("B%d no space for %d (only %d) bytes\n", + bch->nr, reqlen, len); if (test_bit(FLG_TRANSPARENT, &bch->Flags)) { /* send what we have now and try a new buffer */ recv_Bchannel(bch, 0, true); @@ -508,8 +508,7 @@ bchannel_get_rxbuf(struct bchannel *bch, int reqlen) } bch->rx_skb = mI_alloc_skb(len, GFP_ATOMIC); if (!bch->rx_skb) { - pr_warning("B%d receive no memory for %d bytes\n", - bch->nr, len); + pr_warn("B%d receive no memory for %d bytes\n", bch->nr, len); len = -ENOMEM; } return len; diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 447f241467bd..b57dcb834594 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -1254,8 +1254,7 @@ release_card(struct l1oip *hc) mISDN_freebchannel(hc->chan[ch].bch); kfree(hc->chan[ch].bch); #ifdef REORDER_DEBUG - if (hc->chan[ch].disorder_skb) - dev_kfree_skb(hc->chan[ch].disorder_skb); + dev_kfree_skb(hc->chan[ch].disorder_skb); #endif } } diff --git a/drivers/isdn/mISDN/layer2.c b/drivers/isdn/mISDN/layer2.c index 68a481516729..5bf7fcb282c4 100644 --- a/drivers/isdn/mISDN/layer2.c +++ b/drivers/isdn/mISDN/layer2.c @@ -900,8 +900,7 @@ l2_disconnect(struct FsmInst *fi, int event, void *arg) send_uframe(l2, NULL, DISC | 0x10, CMD); mISDN_FsmDelTimer(&l2->t203, 1); restart_t200(l2, 2); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static void @@ -1722,8 +1721,7 @@ l2_set_own_busy(struct FsmInst *fi, int event, void *arg) enquiry_cr(l2, RNR, RSP, 0); test_and_clear_bit(FLG_ACK_PEND, &l2->flag); } - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static void @@ -1736,8 +1734,7 @@ l2_clear_own_busy(struct FsmInst *fi, int event, void *arg) enquiry_cr(l2, RR, RSP, 0); test_and_clear_bit(FLG_ACK_PEND, &l2->flag); } - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static void diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index c6ba37df4b9d..dff4132b3702 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -754,6 +754,8 @@ base_sock_create(struct net *net, struct socket *sock, int protocol, int kern) if (sock->type != SOCK_RAW) return -ESOCKTNOSUPPORT; + if (!capable(CAP_NET_RAW)) + return -EPERM; sk = sk_alloc(net, PF_ISDN, GFP_KERNEL, &mISDN_proto, kern); if (!sk) diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index fa2237e7bcf8..27aa32914425 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c @@ -75,8 +75,7 @@ send_socklist(struct mISDN_sock_list *sl, struct sk_buff *skb) cskb = NULL; } read_unlock(&sl->lock); - if (cskb) - dev_kfree_skb(cskb); + dev_kfree_skb(cskb); } static void @@ -134,8 +133,7 @@ send_layer2(struct mISDNstack *st, struct sk_buff *skb) } out: mutex_unlock(&st->lmutex); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(skb); } static inline int diff --git a/drivers/isdn/mISDN/tei.c b/drivers/isdn/mISDN/tei.c index a4fa594e1caf..59d28cb19738 100644 --- a/drivers/isdn/mISDN/tei.c +++ b/drivers/isdn/mISDN/tei.c @@ -1328,10 +1328,8 @@ mgr_bcast(struct mISDNchannel *ch, struct sk_buff *skb) } out: read_unlock_irqrestore(&mgr->lock, flags); - if (cskb) - dev_kfree_skb(cskb); - if (skb) - dev_kfree_skb(skb); + dev_kfree_skb(cskb); + dev_kfree_skb(skb); return 0; } |