*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/moduleparam.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/isdn/capiutil.h>
#include <linux/isdn/capicmd.h>
#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
struct capiminor;
-struct datahandle_queue {
- struct list_head list;
- u16 datahandle;
-};
-
struct capiminor {
struct list_head list;
struct capincci *nccip;
int outbytes;
/* transmit path */
- struct list_head ackqueue;
+ struct datahandle_queue {
+ struct datahandle_queue *next;
+ u16 datahandle;
+ } *ackqueue;
int nack;
- spinlock_t ackqlock;
+
};
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
{
- struct datahandle_queue *n;
- unsigned long flags;
+ struct datahandle_queue *n, **pp;
n = kmalloc(sizeof(*n), GFP_ATOMIC);
- if (unlikely(!n)) {
- printk(KERN_ERR "capi: alloc datahandle failed\n");
- return -1;
+ if (!n) {
+ printk(KERN_ERR "capi: alloc datahandle failed\n");
+ return -1;
}
+ n->next = NULL;
n->datahandle = datahandle;
- INIT_LIST_HEAD(&n->list);
- spin_lock_irqsave(&mp->ackqlock, flags);
- list_add_tail(&n->list, &mp->ackqueue);
+ for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ;
+ *pp = n;
mp->nack++;
- spin_unlock_irqrestore(&mp->ackqlock, flags);
return 0;
}
static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
{
- struct datahandle_queue *p, *tmp;
- unsigned long flags;
+ struct datahandle_queue **pp, *p;
- spin_lock_irqsave(&mp->ackqlock, flags);
- list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
- if (p->datahandle == datahandle) {
- list_del(&p->list);
+ for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) {
+ if ((*pp)->datahandle == datahandle) {
+ p = *pp;
+ *pp = (*pp)->next;
kfree(p);
mp->nack--;
- spin_unlock_irqrestore(&mp->ackqlock, flags);
return 0;
}
}
- spin_unlock_irqrestore(&mp->ackqlock, flags);
return -1;
}
static void capiminor_del_all_ack(struct capiminor *mp)
{
- struct datahandle_queue *p, *tmp;
- unsigned long flags;
+ struct datahandle_queue **pp, *p;
- spin_lock_irqsave(&mp->ackqlock, flags);
- list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
- list_del(&p->list);
+ pp = &mp->ackqueue;
+ while (*pp) {
+ p = *pp;
+ *pp = (*pp)->next;
kfree(p);
mp->nack--;
}
- spin_unlock_irqrestore(&mp->ackqlock, flags);
}
mp->ncci = ncci;
mp->msgid = 0;
atomic_set(&mp->ttyopencount,0);
- INIT_LIST_HEAD(&mp->ackqueue);
- spin_lock_init(&mp->ackqlock);
skb_queue_head_init(&mp->inqueue);
skb_queue_head_init(&mp->outqueue);
drv->owner = THIS_MODULE;
drv->driver_name = "capi_nc";
+ drv->devfs_name = "capi/";
drv->name = "capi";
drv->major = capi_ttymajor;
drv->minor_start = 0;
}
class_device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
+ devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
+ "isdn/capi20");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) {
class_device_destroy(capi_class, MKDEV(capi_major, 0));
class_destroy(capi_class);
unregister_chrdev(capi_major, "capi20");
+ devfs_remove("isdn/capi20");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
capinc_tty_exit();