diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 911704571b9c..230697aac94b 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -443,7 +443,7 @@ fs3270_open(struct inode *inode, struct file *filp) tty_kref_put(tty); return -ENODEV; } - minor = tty->index + RAW3270_FIRSTMINOR; + minor = tty->index; tty_kref_put(tty); } mutex_lock(&fs3270_mutex); @@ -524,6 +524,25 @@ static const struct file_operations fs3270_fops = { .llseek = no_llseek, }; +void fs3270_create_cb(int minor) +{ + __register_chrdev(IBM_FS3270_MAJOR, minor, 1, "tub", &fs3270_fops); + device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, minor), + NULL, "3270/tub%d", minor); +} + +void fs3270_destroy_cb(int minor) +{ + device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, minor)); + __unregister_chrdev(IBM_FS3270_MAJOR, minor, 1, "tub"); +} + +struct raw3270_notifier fs3270_notifier = +{ + .create = fs3270_create_cb, + .destroy = fs3270_destroy_cb, +}; + /* * 3270 fullscreen driver initialization. */ @@ -532,16 +551,20 @@ fs3270_init(void) { int rc; - rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); + rc = __register_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270", &fs3270_fops); if (rc) return rc; + device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, 0), + NULL, "3270/tub"); + raw3270_register_notifier(&fs3270_notifier); return 0; } static void __exit fs3270_exit(void) { - unregister_chrdev(IBM_FS3270_MAJOR, "fs3270"); + raw3270_unregister_notifier(&fs3270_notifier); + __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270"); } MODULE_LICENSE("GPL"); diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 9a6c140c5f07..72f69fda9d01 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -28,7 +28,7 @@ #include #include -static struct class *class3270; +struct class *class3270; /* The main 3270 data structure. */ struct raw3270 { @@ -46,8 +46,6 @@ struct raw3270 { struct timer_list timer; /* Device timer. */ unsigned char *ascebc; /* ascii -> ebcdic table */ - struct device *clttydev; /* 3270-class tty device ptr */ - struct device *cltubdev; /* 3270-class tub device ptr */ struct raw3270_request init_request; unsigned char init_data[256]; @@ -1072,10 +1070,6 @@ raw3270_delete_device(struct raw3270 *rp) /* Remove from device chain. */ mutex_lock(&raw3270_mutex); - if (rp->clttydev && !IS_ERR(rp->clttydev)) - device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor)); - if (rp->cltubdev && !IS_ERR(rp->cltubdev)) - device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, rp->minor)); list_del_init(&rp->list); mutex_unlock(&raw3270_mutex); @@ -1139,75 +1133,34 @@ static struct attribute_group raw3270_attr_group = { static int raw3270_create_attributes(struct raw3270 *rp) { - int rc; - - rc = sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); - if (rc) - goto out; - - rp->clttydev = device_create(class3270, &rp->cdev->dev, - MKDEV(IBM_TTY3270_MAJOR, rp->minor), NULL, - "tty%s", dev_name(&rp->cdev->dev)); - if (IS_ERR(rp->clttydev)) { - rc = PTR_ERR(rp->clttydev); - goto out_ttydev; - } - - rp->cltubdev = device_create(class3270, &rp->cdev->dev, - MKDEV(IBM_FS3270_MAJOR, rp->minor), NULL, - "tub%s", dev_name(&rp->cdev->dev)); - if (!IS_ERR(rp->cltubdev)) - goto out; - - rc = PTR_ERR(rp->cltubdev); - device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor)); - -out_ttydev: - sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group); -out: - return rc; + return sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); } /* * Notifier for device addition/removal */ -struct raw3270_notifier { - struct list_head list; - void (*notifier)(int, int); -}; - static LIST_HEAD(raw3270_notifier); -int raw3270_register_notifier(void (*notifier)(int, int)) +int raw3270_register_notifier(struct raw3270_notifier *notifier) { - struct raw3270_notifier *np; struct raw3270 *rp; - np = kmalloc(sizeof(struct raw3270_notifier), GFP_KERNEL); - if (!np) - return -ENOMEM; - np->notifier = notifier; mutex_lock(&raw3270_mutex); - list_add_tail(&np->list, &raw3270_notifier); - list_for_each_entry(rp, &raw3270_devices, list) { - get_device(&rp->cdev->dev); - notifier(rp->minor, 1); - } + list_add_tail(¬ifier->list, &raw3270_notifier); + list_for_each_entry(rp, &raw3270_devices, list) + notifier->create(rp->minor); mutex_unlock(&raw3270_mutex); return 0; } -void raw3270_unregister_notifier(void (*notifier)(int, int)) +void raw3270_unregister_notifier(struct raw3270_notifier *notifier) { - struct raw3270_notifier *np; + struct raw3270 *rp; mutex_lock(&raw3270_mutex); - list_for_each_entry(np, &raw3270_notifier, list) - if (np->notifier == notifier) { - list_del(&np->list); - kfree(np); - break; - } + list_for_each_entry(rp, &raw3270_devices, list) + notifier->destroy(rp->minor); + list_del(¬ifier->list); mutex_unlock(&raw3270_mutex); } @@ -1217,8 +1170,8 @@ void raw3270_unregister_notifier(void (*notifier)(int, int)) static int raw3270_set_online (struct ccw_device *cdev) { - struct raw3270 *rp; struct raw3270_notifier *np; + struct raw3270 *rp; int rc; rp = raw3270_create_device(cdev); @@ -1239,7 +1192,7 @@ raw3270_set_online (struct ccw_device *cdev) set_bit(RAW3270_FLAGS_READY, &rp->flags); mutex_lock(&raw3270_mutex); list_for_each_entry(np, &raw3270_notifier, list) - np->notifier(rp->minor, 1); + np->create(rp->minor); mutex_unlock(&raw3270_mutex); return 0; @@ -1290,7 +1243,7 @@ raw3270_remove (struct ccw_device *cdev) mutex_lock(&raw3270_mutex); list_for_each_entry(np, &raw3270_notifier, list) - np->notifier(rp->minor, 0); + np->destroy(rp->minor); mutex_unlock(&raw3270_mutex); /* Reset 3270 device. */ @@ -1434,6 +1387,7 @@ MODULE_LICENSE("GPL"); module_init(raw3270_init); module_exit(raw3270_exit); +EXPORT_SYMBOL(class3270); EXPORT_SYMBOL(raw3270_request_alloc); EXPORT_SYMBOL(raw3270_request_free); EXPORT_SYMBOL(raw3270_request_reset); diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h index ed34eb2199cc..a4c79d043cd3 100644 --- a/drivers/s390/char/raw3270.h +++ b/drivers/s390/char/raw3270.h @@ -91,6 +91,7 @@ struct raw3270_iocb { struct raw3270; struct raw3270_view; +extern struct class *class3270; /* 3270 CCW request */ struct raw3270_request { @@ -192,8 +193,14 @@ struct raw3270 *raw3270_setup_console(struct ccw_device *cdev); void raw3270_wait_cons_dev(struct raw3270 *); /* Notifier for device addition/removal */ -int raw3270_register_notifier(void (*notifier)(int, int)); -void raw3270_unregister_notifier(void (*notifier)(int, int)); +struct raw3270_notifier { + struct list_head list; + void (*create)(int minor); + void (*destroy)(int minor); +}; + +int raw3270_register_notifier(struct raw3270_notifier *); +void raw3270_unregister_notifier(struct raw3270_notifier *); void raw3270_pm_unfreeze(struct raw3270_view *); /* diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 5e4b6fc49ae3..48767e6bab9d 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -829,9 +829,8 @@ tty3270_del_views(void) { int i; - for (i = 0; i < tty3270_max_index; i++) { - struct raw3270_view *view = - raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR); + for (i = RAW3270_FIRSTMINOR; i <= tty3270_max_index; i++) { + struct raw3270_view *view = raw3270_find_view(&tty3270_fn, i); if (!IS_ERR(view)) raw3270_del_view(view); } @@ -855,8 +854,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) int i, rc; /* Check if the tty3270 is already there. */ - view = raw3270_find_view(&tty3270_fn, - tty->index + RAW3270_FIRSTMINOR); + view = raw3270_find_view(&tty3270_fn, tty->index); if (!IS_ERR(view)) { tp = container_of(view, struct tty3270, view); tty->driver_data = tp; @@ -868,8 +866,8 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) tp->inattr = TF_INPUT; return tty_port_install(&tp->port, driver, tty); } - if (tty3270_max_index < tty->index + 1) - tty3270_max_index = tty->index + 1; + if (tty3270_max_index < tty->index) + tty3270_max_index = tty->index; /* Quick exit if there is no device for tty->index. */ if (PTR_ERR(view) == -ENODEV) @@ -880,8 +878,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty) if (IS_ERR(tp)) return PTR_ERR(tp); - rc = raw3270_add_view(&tp->view, &tty3270_fn, - tty->index + RAW3270_FIRSTMINOR); + rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index); if (rc) { tty3270_free_view(tp); return rc; @@ -1788,6 +1785,22 @@ static const struct tty_operations tty3270_ops = { .set_termios = tty3270_set_termios }; +void tty3270_create_cb(int minor) +{ + tty_register_device(tty3270_driver, minor, NULL); +} + +void tty3270_destroy_cb(int minor) +{ + tty_unregister_device(tty3270_driver, minor); +} + +struct raw3270_notifier tty3270_notifier = +{ + .create = tty3270_create_cb, + .destroy = tty3270_destroy_cb, +}; + /* * 3270 tty registration code called from tty_init(). * Most kernel services (incl. kmalloc) are available at this poimt. @@ -1797,23 +1810,25 @@ static int __init tty3270_init(void) struct tty_driver *driver; int ret; - driver = alloc_tty_driver(RAW3270_MAXDEVS); - if (!driver) - return -ENOMEM; + driver = tty_alloc_driver(RAW3270_MAXDEVS, + TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV | + TTY_DRIVER_RESET_TERMIOS); + if (IS_ERR(driver)) + return PTR_ERR(driver); /* * Initialize the tty_driver structure * Entries in tty3270_driver that are NOT initialized: * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc */ - driver->driver_name = "ttyTUB"; - driver->name = "ttyTUB"; + driver->driver_name = "tty3270"; + driver->name = "3270/tty"; driver->major = IBM_TTY3270_MAJOR; - driver->minor_start = RAW3270_FIRSTMINOR; + driver->minor_start = 0; driver->type = TTY_DRIVER_TYPE_SYSTEM; driver->subtype = SYSTEM_TYPE_TTY; driver->init_termios = tty_std_termios; - driver->flags = TTY_DRIVER_RESET_TERMIOS; tty_set_operations(driver, &tty3270_ops); ret = tty_register_driver(driver); if (ret) { @@ -1821,6 +1836,7 @@ static int __init tty3270_init(void) return ret; } tty3270_driver = driver; + raw3270_register_notifier(&tty3270_notifier); return 0; } @@ -1829,6 +1845,7 @@ tty3270_exit(void) { struct tty_driver *driver; + raw3270_unregister_notifier(&tty3270_notifier); driver = tty3270_driver; tty3270_driver = NULL; tty_unregister_driver(driver);