X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fisdn%2Fcapi%2Fcapi.c;h=173c899a1fb40cb9eca8ff5b02844a95519b2527;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=3429d57e297eef21284108506a0584d91e5ea339;hpb=48ed9e9ed158dedf557fbe4b9e8b09f109e2a79a;p=linux-2.6.git diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3429d57e2..173c899a1 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -57,20 +58,20 @@ MODULE_LICENSE("GPL"); /* -------- driver information -------------------------------------- */ -static struct class_simple *capi_class; +static struct class *capi_class; -int capi_major = 68; /* allocated */ +static int capi_major = 68; /* allocated */ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #define CAPINC_NR_PORTS 32 #define CAPINC_MAX_PORTS 256 -int capi_ttymajor = 191; -int capi_ttyminors = CAPINC_NR_PORTS; +static int capi_ttymajor = 191; +static int capi_ttyminors = CAPINC_NR_PORTS; #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -MODULE_PARM(capi_major, "i"); +module_param_named(major, capi_major, uint, 0); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -MODULE_PARM(capi_ttymajor, "i"); -MODULE_PARM(capi_ttyminors, "i"); +module_param_named(ttymajor, capi_ttymajor, uint, 0); +module_param_named(ttyminors, capi_ttyminors, uint, 0); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ /* -------- defines ------------------------------------------------- */ @@ -142,11 +143,11 @@ struct capidev { /* -------- global variables ---------------------------------------- */ -static rwlock_t capidev_list_lock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(capidev_list_lock); static LIST_HEAD(capidev_list); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -static rwlock_t capiminor_list_lock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(capiminor_list_lock); static LIST_HEAD(capiminor_list); #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -267,7 +268,7 @@ static void capiminor_free(struct capiminor *mp) kfree(mp); } -struct capiminor *capiminor_find(unsigned int minor) +static struct capiminor *capiminor_find(unsigned int minor) { struct list_head *l; struct capiminor *p = NULL; @@ -436,51 +437,61 @@ static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) struct sk_buff *nskb; int datalen; u16 errcode, datahandle; - + struct tty_ldisc *ld; + datalen = skb->len - CAPIMSG_LEN(skb->data); - if (mp->tty) { - if (mp->tty->ldisc.receive_buf == 0) { - printk(KERN_ERR "capi: ldisc has no receive_buf function\n"); - return -1; - } - if (mp->ttyinstop) { + if (mp->tty == NULL) + { +#ifdef _DEBUG_DATAFLOW + printk(KERN_DEBUG "capi: currently no receiver\n"); +#endif + return -1; + } + + ld = tty_ldisc_ref(mp->tty); + if (ld == NULL) + return -1; + if (ld->receive_buf == NULL) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: recv tty throttled\n"); + printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n"); #endif - return -1; - } - if (mp->tty->ldisc.receive_room && - mp->tty->ldisc.receive_room(mp->tty) < datalen) { + goto bad; + } + if (mp->ttyinstop) { #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: no room in tty\n"); + printk(KERN_DEBUG "capi: recv tty throttled\n"); #endif - return -1; - } - if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) { - printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); - return -1; - } - datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); - errcode = capi20_put_message(mp->ap, nskb); - if (errcode != CAPI_NOERROR) { - printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", - errcode); - kfree_skb(nskb); - return -1; - } - (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", - datahandle, skb->len); + goto bad; + } + if (mp->tty->receive_room < datalen) { +#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) + printk(KERN_DEBUG "capi: no room in tty\n"); #endif - mp->tty->ldisc.receive_buf(mp->tty, skb->data, NULL, skb->len); - kfree_skb(skb); - return 0; - + goto bad; + } + if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) { + printk(KERN_ERR "capi: gen_data_b3_resp failed\n"); + goto bad; } + datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4); + errcode = capi20_put_message(mp->ap, nskb); + if (errcode != CAPI_NOERROR) { + printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n", + errcode); + kfree_skb(nskb); + goto bad; + } + (void)skb_pull(skb, CAPIMSG_LEN(skb->data)); #ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: currently no receiver\n"); + printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n", + datahandle, skb->len); #endif + ld->receive_buf(mp->tty, skb->data, NULL, skb->len); + kfree_skb(skb); + tty_ldisc_deref(ld); + return 0; +bad: + tty_ldisc_deref(ld); return -1; } @@ -614,6 +625,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { + datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); #ifdef _DEBUG_DATAFLOW printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", @@ -633,10 +645,8 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) #endif kfree_skb(skb); (void)capiminor_del_ack(mp, datahandle); - if (mp->tty) { - if (mp->tty->ldisc.write_wakeup) - mp->tty->ldisc.write_wakeup(mp->tty); - } + if (mp->tty) + tty_wakeup(mp->tty); (void)handle_minor_send(mp); } else { @@ -1034,16 +1044,14 @@ static void capinc_tty_close(struct tty_struct * tty, struct file * file) #endif } -static int capinc_tty_write(struct tty_struct * tty, int from_user, +static int capinc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct capiminor *mp = (struct capiminor *)tty->driver_data; struct sk_buff *skb; - int retval; #ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write(from_user=%d,count=%d)\n", - from_user, count); + printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count); #endif if (!mp || !mp->nccip) { @@ -1067,18 +1075,7 @@ static int capinc_tty_write(struct tty_struct * tty, int from_user, } skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); - if (from_user) { - retval = copy_from_user(skb_put(skb, count), buf, count); - if (retval) { - kfree_skb(skb); -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: copy_from_user=%d\n", retval); -#endif - return -EFAULT; - } - } else { - memcpy(skb_put(skb, count), buf, count); - } + memcpy(skb_put(skb, count), buf, count); skb_queue_tail(&mp->outqueue, skb); mp->outbytes += skb->len; @@ -1168,7 +1165,7 @@ static int capinc_tty_write_room(struct tty_struct *tty) return room; } -int capinc_tty_chars_in_buffer(struct tty_struct *tty) +static int capinc_tty_chars_in_buffer(struct tty_struct *tty) { struct capiminor *mp = (struct capiminor *)tty->driver_data; if (!mp || !mp->nccip) { @@ -1488,6 +1485,7 @@ static int __init capi_init(void) { char *p; char *compileinfo; + int major_ret; if ((p = strchr(revision, ':')) != 0 && p[1]) { strlcpy(rev, p + 2, sizeof(rev)); @@ -1496,25 +1494,25 @@ static int __init capi_init(void) } else strcpy(rev, "1.0"); - if (register_chrdev(capi_major, "capi20", &capi_fops)) { + 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); - return -EIO; + return major_ret; } - - capi_class = class_simple_create(THIS_MODULE, "capi"); + capi_class = class_create(THIS_MODULE, "capi"); if (IS_ERR(capi_class)) { unregister_chrdev(capi_major, "capi20"); return PTR_ERR(capi_class); } - class_simple_device_add(capi_class, MKDEV(capi_major, 0), NULL, "capi"); + 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_simple_device_remove(MKDEV(capi_major, 0)); - class_simple_destroy(capi_class); + class_device_destroy(capi_class, MKDEV(capi_major, 0)); + class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); return -ENOMEM; } @@ -1541,8 +1539,8 @@ static void __exit capi_exit(void) { proc_exit(); - class_simple_device_remove(MKDEV(capi_major, 0)); - class_simple_destroy(capi_class); + class_device_destroy(capi_class, MKDEV(capi_major, 0)); + class_destroy(capi_class); unregister_chrdev(capi_major, "capi20"); devfs_remove("isdn/capi20");