diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:42:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:43 -0400 |
commit | bf970ee46e0fb363c8df4393229121d54330a98e (patch) | |
tree | 3beb09c369b3459e70689b5f9a35caacf063f116 /drivers/char/tty_io.c | |
parent | 73ec06fc5f5c8e1097a7a4a4ab2d7c6c3a007e81 (diff) |
tty: extract the pty init time special cases
The majority of the remaining init_dev code is pty special cases. We
refactor this code into the driver->install method.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 198 |
1 files changed, 68 insertions, 130 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index b0ad4880c3a8..e881e9ed08de 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -136,8 +136,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ | |||
136 | DEFINE_MUTEX(tty_mutex); | 136 | DEFINE_MUTEX(tty_mutex); |
137 | EXPORT_SYMBOL(tty_mutex); | 137 | EXPORT_SYMBOL(tty_mutex); |
138 | 138 | ||
139 | static void initialize_tty_struct(struct tty_struct *tty); | ||
140 | |||
141 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); | 139 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); |
142 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); | 140 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); |
143 | ssize_t redirected_tty_write(struct file *, const char __user *, | 141 | ssize_t redirected_tty_write(struct file *, const char __user *, |
@@ -166,7 +164,7 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | |||
166 | * Locking: none | 164 | * Locking: none |
167 | */ | 165 | */ |
168 | 166 | ||
169 | static struct tty_struct *alloc_tty_struct(void) | 167 | struct tty_struct *alloc_tty_struct(void) |
170 | { | 168 | { |
171 | return kzalloc(sizeof(struct tty_struct), GFP_KERNEL); | 169 | return kzalloc(sizeof(struct tty_struct), GFP_KERNEL); |
172 | } | 170 | } |
@@ -180,7 +178,7 @@ static struct tty_struct *alloc_tty_struct(void) | |||
180 | * Locking: none. Must be called after tty is definitely unused | 178 | * Locking: none. Must be called after tty is definitely unused |
181 | */ | 179 | */ |
182 | 180 | ||
183 | static inline void free_tty_struct(struct tty_struct *tty) | 181 | void free_tty_struct(struct tty_struct *tty) |
184 | { | 182 | { |
185 | kfree(tty->write_buf); | 183 | kfree(tty->write_buf); |
186 | tty_buffer_free_all(tty); | 184 | tty_buffer_free_all(tty); |
@@ -1227,22 +1225,70 @@ struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, int idx) | |||
1227 | } | 1225 | } |
1228 | 1226 | ||
1229 | /** | 1227 | /** |
1228 | * tty_init_termios - helper for termios setup | ||
1229 | * @tty: the tty to set up | ||
1230 | * | ||
1231 | * Initialise the termios structures for this tty. Thus runs under | ||
1232 | * the tty_mutex currently so we can be relaxed about ordering. | ||
1233 | */ | ||
1234 | |||
1235 | int tty_init_termios(struct tty_struct *tty) | ||
1236 | { | ||
1237 | struct ktermios *tp, *ltp; | ||
1238 | int idx = tty->index; | ||
1239 | |||
1240 | tp = tty->driver->termios[idx]; | ||
1241 | ltp = tty->driver->termios_locked[idx]; | ||
1242 | if (tp == NULL) { | ||
1243 | WARN_ON(ltp != NULL); | ||
1244 | tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1245 | ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1246 | if (tp == NULL || ltp == NULL) { | ||
1247 | kfree(tp); | ||
1248 | kfree(ltp); | ||
1249 | return -ENOMEM; | ||
1250 | } | ||
1251 | memcpy(tp, &tty->driver->init_termios, | ||
1252 | sizeof(struct ktermios)); | ||
1253 | tty->driver->termios[idx] = tp; | ||
1254 | tty->driver->termios_locked[idx] = ltp; | ||
1255 | } | ||
1256 | tty->termios = tp; | ||
1257 | tty->termios_locked = ltp; | ||
1258 | |||
1259 | /* Compatibility until drivers always set this */ | ||
1260 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
1261 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | /** | ||
1230 | * tty_driver_install_tty() - install a tty entry in the driver | 1266 | * tty_driver_install_tty() - install a tty entry in the driver |
1231 | * @driver: the driver for the tty | 1267 | * @driver: the driver for the tty |
1232 | * @tty: the tty | 1268 | * @tty: the tty |
1233 | * | 1269 | * |
1234 | * Install a tty object into the driver tables. The tty->index field | 1270 | * Install a tty object into the driver tables. The tty->index field |
1235 | * will be set by the time this is called. | 1271 | * will be set by the time this is called. This method is responsible |
1272 | * for ensuring any need additional structures are allocated and | ||
1273 | * configured. | ||
1236 | * | 1274 | * |
1237 | * Locking: tty_mutex for now | 1275 | * Locking: tty_mutex for now |
1238 | */ | 1276 | */ |
1239 | static int tty_driver_install_tty(struct tty_driver *driver, | 1277 | static int tty_driver_install_tty(struct tty_driver *driver, |
1240 | struct tty_struct *tty) | 1278 | struct tty_struct *tty) |
1241 | { | 1279 | { |
1280 | int idx = tty->index; | ||
1281 | |||
1242 | if (driver->ops->install) | 1282 | if (driver->ops->install) |
1243 | return driver->ops->install(driver, tty); | 1283 | return driver->ops->install(driver, tty); |
1244 | driver->ttys[tty->index] = tty; | 1284 | |
1245 | return 0; | 1285 | if (tty_init_termios(tty) == 0) { |
1286 | tty_driver_kref_get(driver); | ||
1287 | tty->count++; | ||
1288 | driver->ttys[idx] = tty; | ||
1289 | return 0; | ||
1290 | } | ||
1291 | return -ENOMEM; | ||
1246 | } | 1292 | } |
1247 | 1293 | ||
1248 | /** | 1294 | /** |
@@ -1327,9 +1373,7 @@ static int tty_reopen(struct tty_struct *tty) | |||
1327 | struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | 1373 | struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, |
1328 | int first_ok) | 1374 | int first_ok) |
1329 | { | 1375 | { |
1330 | struct tty_struct *tty, *o_tty; | 1376 | struct tty_struct *tty; |
1331 | struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; | ||
1332 | struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; | ||
1333 | int retval; | 1377 | int retval; |
1334 | 1378 | ||
1335 | /* check whether we're reopening an existing tty */ | 1379 | /* check whether we're reopening an existing tty */ |
@@ -1361,118 +1405,17 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1361 | if (!try_module_get(driver->owner)) | 1405 | if (!try_module_get(driver->owner)) |
1362 | return ERR_PTR(-ENODEV); | 1406 | return ERR_PTR(-ENODEV); |
1363 | 1407 | ||
1364 | o_tty = NULL; | ||
1365 | tp = o_tp = NULL; | ||
1366 | ltp = o_ltp = NULL; | ||
1367 | |||
1368 | tty = alloc_tty_struct(); | 1408 | tty = alloc_tty_struct(); |
1369 | if (!tty) | 1409 | if (!tty) |
1370 | goto fail_no_mem; | 1410 | goto fail_no_mem; |
1371 | initialize_tty_struct(tty); | 1411 | initialize_tty_struct(tty, driver, idx); |
1372 | tty->driver = driver; | ||
1373 | tty->ops = driver->ops; | ||
1374 | tty->index = idx; | ||
1375 | tty_line_name(driver, idx, tty->name); | ||
1376 | |||
1377 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | ||
1378 | tp_loc = &tty->termios; | ||
1379 | ltp_loc = &tty->termios_locked; | ||
1380 | } else { | ||
1381 | tp_loc = &driver->termios[idx]; | ||
1382 | ltp_loc = &driver->termios_locked[idx]; | ||
1383 | } | ||
1384 | |||
1385 | if (!*tp_loc) { | ||
1386 | tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1387 | if (!tp) | ||
1388 | goto free_mem_out; | ||
1389 | *tp = driver->init_termios; | ||
1390 | } | ||
1391 | |||
1392 | if (!*ltp_loc) { | ||
1393 | ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1394 | if (!ltp) | ||
1395 | goto free_mem_out; | ||
1396 | } | ||
1397 | |||
1398 | if (driver->type == TTY_DRIVER_TYPE_PTY) { | ||
1399 | o_tty = alloc_tty_struct(); | ||
1400 | if (!o_tty) | ||
1401 | goto free_mem_out; | ||
1402 | if (!try_module_get(driver->other->owner)) { | ||
1403 | /* This cannot in fact currently happen */ | ||
1404 | free_tty_struct(o_tty); | ||
1405 | o_tty = NULL; | ||
1406 | goto free_mem_out; | ||
1407 | } | ||
1408 | initialize_tty_struct(o_tty); | ||
1409 | o_tty->driver = driver->other; | ||
1410 | o_tty->ops = driver->ops; | ||
1411 | o_tty->index = idx; | ||
1412 | tty_line_name(driver->other, idx, o_tty->name); | ||
1413 | |||
1414 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | ||
1415 | o_tp_loc = &o_tty->termios; | ||
1416 | o_ltp_loc = &o_tty->termios_locked; | ||
1417 | } else { | ||
1418 | o_tp_loc = &driver->other->termios[idx]; | ||
1419 | o_ltp_loc = &driver->other->termios_locked[idx]; | ||
1420 | } | ||
1421 | |||
1422 | if (!*o_tp_loc) { | ||
1423 | o_tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1424 | if (!o_tp) | ||
1425 | goto free_mem_out; | ||
1426 | *o_tp = driver->other->init_termios; | ||
1427 | } | ||
1428 | |||
1429 | if (!*o_ltp_loc) { | ||
1430 | o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1431 | if (!o_ltp) | ||
1432 | goto free_mem_out; | ||
1433 | } | ||
1434 | |||
1435 | /* | ||
1436 | * Everything allocated ... set up the o_tty structure. | ||
1437 | */ | ||
1438 | if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) | ||
1439 | driver->other->ttys[idx] = o_tty; | ||
1440 | if (!*o_tp_loc) | ||
1441 | *o_tp_loc = o_tp; | ||
1442 | if (!*o_ltp_loc) | ||
1443 | *o_ltp_loc = o_ltp; | ||
1444 | o_tty->termios = *o_tp_loc; | ||
1445 | o_tty->termios_locked = *o_ltp_loc; | ||
1446 | tty_driver_kref_get(driver->other); | ||
1447 | if (driver->subtype == PTY_TYPE_MASTER) | ||
1448 | o_tty->count++; | ||
1449 | |||
1450 | /* Establish the links in both directions */ | ||
1451 | tty->link = o_tty; | ||
1452 | o_tty->link = tty; | ||
1453 | } | ||
1454 | |||
1455 | /* | ||
1456 | * All structures have been allocated, so now we install them. | ||
1457 | * Failures after this point use release_tty to clean up, so | ||
1458 | * there's no need to null out the local pointers. | ||
1459 | */ | ||
1460 | |||
1461 | if (!*tp_loc) | ||
1462 | *tp_loc = tp; | ||
1463 | if (!*ltp_loc) | ||
1464 | *ltp_loc = ltp; | ||
1465 | tty->termios = *tp_loc; | ||
1466 | tty->termios_locked = *ltp_loc; | ||
1467 | /* Compatibility until drivers always set this */ | ||
1468 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
1469 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
1470 | tty_driver_kref_get(driver); | ||
1471 | tty->count++; | ||
1472 | 1412 | ||
1473 | retval = tty_driver_install_tty(driver, tty); | 1413 | retval = tty_driver_install_tty(driver, tty); |
1474 | if (retval < 0) | 1414 | if (retval < 0) { |
1475 | goto release_mem_out; | 1415 | free_tty_struct(tty); |
1416 | module_put(driver->owner); | ||
1417 | return ERR_PTR(retval); | ||
1418 | } | ||
1476 | 1419 | ||
1477 | /* | 1420 | /* |
1478 | * Structures all installed ... call the ldisc open routines. | 1421 | * Structures all installed ... call the ldisc open routines. |
@@ -1480,22 +1423,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | |||
1480 | * to decrement the use counts, as release_tty doesn't care. | 1423 | * to decrement the use counts, as release_tty doesn't care. |
1481 | */ | 1424 | */ |
1482 | 1425 | ||
1483 | retval = tty_ldisc_setup(tty, o_tty); | 1426 | retval = tty_ldisc_setup(tty, tty->link); |
1484 | if (retval) | 1427 | if (retval) |
1485 | goto release_mem_out; | 1428 | goto release_mem_out; |
1486 | return tty; | 1429 | return tty; |
1487 | 1430 | ||
1488 | /* Release locally allocated memory ... nothing placed in slots */ | ||
1489 | free_mem_out: | ||
1490 | kfree(o_tp); | ||
1491 | if (o_tty) { | ||
1492 | module_put(o_tty->driver->owner); | ||
1493 | free_tty_struct(o_tty); | ||
1494 | } | ||
1495 | kfree(ltp); | ||
1496 | kfree(tp); | ||
1497 | free_tty_struct(tty); | ||
1498 | |||
1499 | fail_no_mem: | 1431 | fail_no_mem: |
1500 | module_put(driver->owner); | 1432 | module_put(driver->owner); |
1501 | return ERR_PTR(-ENOMEM); | 1433 | return ERR_PTR(-ENOMEM); |
@@ -2852,7 +2784,8 @@ EXPORT_SYMBOL(do_SAK); | |||
2852 | * Locking: none - tty in question must not be exposed at this point | 2784 | * Locking: none - tty in question must not be exposed at this point |
2853 | */ | 2785 | */ |
2854 | 2786 | ||
2855 | static void initialize_tty_struct(struct tty_struct *tty) | 2787 | void initialize_tty_struct(struct tty_struct *tty, |
2788 | struct tty_driver *driver, int idx) | ||
2856 | { | 2789 | { |
2857 | memset(tty, 0, sizeof(struct tty_struct)); | 2790 | memset(tty, 0, sizeof(struct tty_struct)); |
2858 | kref_init(&tty->kref); | 2791 | kref_init(&tty->kref); |
@@ -2873,6 +2806,11 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
2873 | spin_lock_init(&tty->ctrl_lock); | 2806 | spin_lock_init(&tty->ctrl_lock); |
2874 | INIT_LIST_HEAD(&tty->tty_files); | 2807 | INIT_LIST_HEAD(&tty->tty_files); |
2875 | INIT_WORK(&tty->SAK_work, do_SAK_work); | 2808 | INIT_WORK(&tty->SAK_work, do_SAK_work); |
2809 | |||
2810 | tty->driver = driver; | ||
2811 | tty->ops = driver->ops; | ||
2812 | tty->index = idx; | ||
2813 | tty_line_name(driver, idx, tty->name); | ||
2876 | } | 2814 | } |
2877 | 2815 | ||
2878 | /** | 2816 | /** |