Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/3270: introduce device notifier

Add a notifier to create / destroy the device nodes for the tty view
and the fullscreen view. Only device nodes for online devices are
created and the device names will follow the convention as outlined
in Documentation/devices.txt: 3270/tty<x> for the tty nodes,
3270/tub<x> for hte fullscreen nodes and 3270/tub for the fullscreen
control node.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

+83 -82
+26 -3
drivers/s390/char/fs3270.c
··· 443 443 tty_kref_put(tty); 444 444 return -ENODEV; 445 445 } 446 - minor = tty->index + RAW3270_FIRSTMINOR; 446 + minor = tty->index; 447 447 tty_kref_put(tty); 448 448 } 449 449 mutex_lock(&fs3270_mutex); ··· 524 524 .llseek = no_llseek, 525 525 }; 526 526 527 + void fs3270_create_cb(int minor) 528 + { 529 + __register_chrdev(IBM_FS3270_MAJOR, minor, 1, "tub", &fs3270_fops); 530 + device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, minor), 531 + NULL, "3270/tub%d", minor); 532 + } 533 + 534 + void fs3270_destroy_cb(int minor) 535 + { 536 + device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, minor)); 537 + __unregister_chrdev(IBM_FS3270_MAJOR, minor, 1, "tub"); 538 + } 539 + 540 + struct raw3270_notifier fs3270_notifier = 541 + { 542 + .create = fs3270_create_cb, 543 + .destroy = fs3270_destroy_cb, 544 + }; 545 + 527 546 /* 528 547 * 3270 fullscreen driver initialization. 529 548 */ ··· 551 532 { 552 533 int rc; 553 534 554 - rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops); 535 + rc = __register_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270", &fs3270_fops); 555 536 if (rc) 556 537 return rc; 538 + device_create(class3270, NULL, MKDEV(IBM_FS3270_MAJOR, 0), 539 + NULL, "3270/tub"); 540 + raw3270_register_notifier(&fs3270_notifier); 557 541 return 0; 558 542 } 559 543 560 544 static void __exit 561 545 fs3270_exit(void) 562 546 { 563 - unregister_chrdev(IBM_FS3270_MAJOR, "fs3270"); 547 + raw3270_unregister_notifier(&fs3270_notifier); 548 + __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270"); 564 549 } 565 550 566 551 MODULE_LICENSE("GPL");
+15 -61
drivers/s390/char/raw3270.c
··· 28 28 #include <linux/device.h> 29 29 #include <linux/mutex.h> 30 30 31 - static struct class *class3270; 31 + struct class *class3270; 32 32 33 33 /* The main 3270 data structure. */ 34 34 struct raw3270 { ··· 46 46 struct timer_list timer; /* Device timer. */ 47 47 48 48 unsigned char *ascebc; /* ascii -> ebcdic table */ 49 - struct device *clttydev; /* 3270-class tty device ptr */ 50 - struct device *cltubdev; /* 3270-class tub device ptr */ 51 49 52 50 struct raw3270_request init_request; 53 51 unsigned char init_data[256]; ··· 1070 1072 1071 1073 /* Remove from device chain. */ 1072 1074 mutex_lock(&raw3270_mutex); 1073 - if (rp->clttydev && !IS_ERR(rp->clttydev)) 1074 - device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor)); 1075 - if (rp->cltubdev && !IS_ERR(rp->cltubdev)) 1076 - device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, rp->minor)); 1077 1075 list_del_init(&rp->list); 1078 1076 mutex_unlock(&raw3270_mutex); 1079 1077 ··· 1133 1139 1134 1140 static int raw3270_create_attributes(struct raw3270 *rp) 1135 1141 { 1136 - int rc; 1137 - 1138 - rc = sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); 1139 - if (rc) 1140 - goto out; 1141 - 1142 - rp->clttydev = device_create(class3270, &rp->cdev->dev, 1143 - MKDEV(IBM_TTY3270_MAJOR, rp->minor), NULL, 1144 - "tty%s", dev_name(&rp->cdev->dev)); 1145 - if (IS_ERR(rp->clttydev)) { 1146 - rc = PTR_ERR(rp->clttydev); 1147 - goto out_ttydev; 1148 - } 1149 - 1150 - rp->cltubdev = device_create(class3270, &rp->cdev->dev, 1151 - MKDEV(IBM_FS3270_MAJOR, rp->minor), NULL, 1152 - "tub%s", dev_name(&rp->cdev->dev)); 1153 - if (!IS_ERR(rp->cltubdev)) 1154 - goto out; 1155 - 1156 - rc = PTR_ERR(rp->cltubdev); 1157 - device_destroy(class3270, MKDEV(IBM_TTY3270_MAJOR, rp->minor)); 1158 - 1159 - out_ttydev: 1160 - sysfs_remove_group(&rp->cdev->dev.kobj, &raw3270_attr_group); 1161 - out: 1162 - return rc; 1142 + return sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group); 1163 1143 } 1164 1144 1165 1145 /* 1166 1146 * Notifier for device addition/removal 1167 1147 */ 1168 - struct raw3270_notifier { 1169 - struct list_head list; 1170 - void (*notifier)(int, int); 1171 - }; 1172 - 1173 1148 static LIST_HEAD(raw3270_notifier); 1174 1149 1175 - int raw3270_register_notifier(void (*notifier)(int, int)) 1150 + int raw3270_register_notifier(struct raw3270_notifier *notifier) 1176 1151 { 1177 - struct raw3270_notifier *np; 1178 1152 struct raw3270 *rp; 1179 1153 1180 - np = kmalloc(sizeof(struct raw3270_notifier), GFP_KERNEL); 1181 - if (!np) 1182 - return -ENOMEM; 1183 - np->notifier = notifier; 1184 1154 mutex_lock(&raw3270_mutex); 1185 - list_add_tail(&np->list, &raw3270_notifier); 1186 - list_for_each_entry(rp, &raw3270_devices, list) { 1187 - get_device(&rp->cdev->dev); 1188 - notifier(rp->minor, 1); 1189 - } 1155 + list_add_tail(&notifier->list, &raw3270_notifier); 1156 + list_for_each_entry(rp, &raw3270_devices, list) 1157 + notifier->create(rp->minor); 1190 1158 mutex_unlock(&raw3270_mutex); 1191 1159 return 0; 1192 1160 } 1193 1161 1194 - void raw3270_unregister_notifier(void (*notifier)(int, int)) 1162 + void raw3270_unregister_notifier(struct raw3270_notifier *notifier) 1195 1163 { 1196 - struct raw3270_notifier *np; 1164 + struct raw3270 *rp; 1197 1165 1198 1166 mutex_lock(&raw3270_mutex); 1199 - list_for_each_entry(np, &raw3270_notifier, list) 1200 - if (np->notifier == notifier) { 1201 - list_del(&np->list); 1202 - kfree(np); 1203 - break; 1204 - } 1167 + list_for_each_entry(rp, &raw3270_devices, list) 1168 + notifier->destroy(rp->minor); 1169 + list_del(&notifier->list); 1205 1170 mutex_unlock(&raw3270_mutex); 1206 1171 } 1207 1172 ··· 1170 1217 static int 1171 1218 raw3270_set_online (struct ccw_device *cdev) 1172 1219 { 1173 - struct raw3270 *rp; 1174 1220 struct raw3270_notifier *np; 1221 + struct raw3270 *rp; 1175 1222 int rc; 1176 1223 1177 1224 rp = raw3270_create_device(cdev); ··· 1192 1239 set_bit(RAW3270_FLAGS_READY, &rp->flags); 1193 1240 mutex_lock(&raw3270_mutex); 1194 1241 list_for_each_entry(np, &raw3270_notifier, list) 1195 - np->notifier(rp->minor, 1); 1242 + np->create(rp->minor); 1196 1243 mutex_unlock(&raw3270_mutex); 1197 1244 return 0; 1198 1245 ··· 1243 1290 1244 1291 mutex_lock(&raw3270_mutex); 1245 1292 list_for_each_entry(np, &raw3270_notifier, list) 1246 - np->notifier(rp->minor, 0); 1293 + np->destroy(rp->minor); 1247 1294 mutex_unlock(&raw3270_mutex); 1248 1295 1249 1296 /* Reset 3270 device. */ ··· 1387 1434 module_init(raw3270_init); 1388 1435 module_exit(raw3270_exit); 1389 1436 1437 + EXPORT_SYMBOL(class3270); 1390 1438 EXPORT_SYMBOL(raw3270_request_alloc); 1391 1439 EXPORT_SYMBOL(raw3270_request_free); 1392 1440 EXPORT_SYMBOL(raw3270_request_reset);
+9 -2
drivers/s390/char/raw3270.h
··· 91 91 92 92 struct raw3270; 93 93 struct raw3270_view; 94 + extern struct class *class3270; 94 95 95 96 /* 3270 CCW request */ 96 97 struct raw3270_request { ··· 193 192 void raw3270_wait_cons_dev(struct raw3270 *); 194 193 195 194 /* Notifier for device addition/removal */ 196 - int raw3270_register_notifier(void (*notifier)(int, int)); 197 - void raw3270_unregister_notifier(void (*notifier)(int, int)); 195 + struct raw3270_notifier { 196 + struct list_head list; 197 + void (*create)(int minor); 198 + void (*destroy)(int minor); 199 + }; 200 + 201 + int raw3270_register_notifier(struct raw3270_notifier *); 202 + void raw3270_unregister_notifier(struct raw3270_notifier *); 198 203 void raw3270_pm_unfreeze(struct raw3270_view *); 199 204 200 205 /*
+33 -16
drivers/s390/char/tty3270.c
··· 829 829 { 830 830 int i; 831 831 832 - for (i = 0; i < tty3270_max_index; i++) { 833 - struct raw3270_view *view = 834 - raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR); 832 + for (i = RAW3270_FIRSTMINOR; i <= tty3270_max_index; i++) { 833 + struct raw3270_view *view = raw3270_find_view(&tty3270_fn, i); 835 834 if (!IS_ERR(view)) 836 835 raw3270_del_view(view); 837 836 } ··· 854 855 int i, rc; 855 856 856 857 /* Check if the tty3270 is already there. */ 857 - view = raw3270_find_view(&tty3270_fn, 858 - tty->index + RAW3270_FIRSTMINOR); 858 + view = raw3270_find_view(&tty3270_fn, tty->index); 859 859 if (!IS_ERR(view)) { 860 860 tp = container_of(view, struct tty3270, view); 861 861 tty->driver_data = tp; ··· 866 868 tp->inattr = TF_INPUT; 867 869 return tty_port_install(&tp->port, driver, tty); 868 870 } 869 - if (tty3270_max_index < tty->index + 1) 870 - tty3270_max_index = tty->index + 1; 871 + if (tty3270_max_index < tty->index) 872 + tty3270_max_index = tty->index; 871 873 872 874 /* Quick exit if there is no device for tty->index. */ 873 875 if (PTR_ERR(view) == -ENODEV) ··· 878 880 if (IS_ERR(tp)) 879 881 return PTR_ERR(tp); 880 882 881 - rc = raw3270_add_view(&tp->view, &tty3270_fn, 882 - tty->index + RAW3270_FIRSTMINOR); 883 + rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index); 883 884 if (rc) { 884 885 tty3270_free_view(tp); 885 886 return rc; ··· 1785 1788 .set_termios = tty3270_set_termios 1786 1789 }; 1787 1790 1791 + void tty3270_create_cb(int minor) 1792 + { 1793 + tty_register_device(tty3270_driver, minor, NULL); 1794 + } 1795 + 1796 + void tty3270_destroy_cb(int minor) 1797 + { 1798 + tty_unregister_device(tty3270_driver, minor); 1799 + } 1800 + 1801 + struct raw3270_notifier tty3270_notifier = 1802 + { 1803 + .create = tty3270_create_cb, 1804 + .destroy = tty3270_destroy_cb, 1805 + }; 1806 + 1788 1807 /* 1789 1808 * 3270 tty registration code called from tty_init(). 1790 1809 * Most kernel services (incl. kmalloc) are available at this poimt. ··· 1810 1797 struct tty_driver *driver; 1811 1798 int ret; 1812 1799 1813 - driver = alloc_tty_driver(RAW3270_MAXDEVS); 1814 - if (!driver) 1815 - return -ENOMEM; 1800 + driver = tty_alloc_driver(RAW3270_MAXDEVS, 1801 + TTY_DRIVER_REAL_RAW | 1802 + TTY_DRIVER_DYNAMIC_DEV | 1803 + TTY_DRIVER_RESET_TERMIOS); 1804 + if (IS_ERR(driver)) 1805 + return PTR_ERR(driver); 1816 1806 1817 1807 /* 1818 1808 * Initialize the tty_driver structure 1819 1809 * Entries in tty3270_driver that are NOT initialized: 1820 1810 * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc 1821 1811 */ 1822 - driver->driver_name = "ttyTUB"; 1823 - driver->name = "ttyTUB"; 1812 + driver->driver_name = "tty3270"; 1813 + driver->name = "3270/tty"; 1824 1814 driver->major = IBM_TTY3270_MAJOR; 1825 - driver->minor_start = RAW3270_FIRSTMINOR; 1815 + driver->minor_start = 0; 1826 1816 driver->type = TTY_DRIVER_TYPE_SYSTEM; 1827 1817 driver->subtype = SYSTEM_TYPE_TTY; 1828 1818 driver->init_termios = tty_std_termios; 1829 - driver->flags = TTY_DRIVER_RESET_TERMIOS; 1830 1819 tty_set_operations(driver, &tty3270_ops); 1831 1820 ret = tty_register_driver(driver); 1832 1821 if (ret) { ··· 1836 1821 return ret; 1837 1822 } 1838 1823 tty3270_driver = driver; 1824 + raw3270_register_notifier(&tty3270_notifier); 1839 1825 return 0; 1840 1826 } 1841 1827 ··· 1845 1829 { 1846 1830 struct tty_driver *driver; 1847 1831 1832 + raw3270_unregister_notifier(&tty3270_notifier); 1848 1833 driver = tty3270_driver; 1849 1834 tty3270_driver = NULL; 1850 1835 tty_unregister_driver(driver);