Commit dc96d885 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] tty_driver refcounting

drivers/s390/char/sclp_tty.c converted to dynamic allocation
parent 3e58964f
...@@ -163,7 +163,7 @@ static struct tty_driver * ...@@ -163,7 +163,7 @@ static struct tty_driver *
sclp_console_device(struct console *c, int *index) sclp_console_device(struct console *c, int *index)
{ {
*index = c->index; *index = c->index;
return &sclp_tty_driver; return sclp_tty_driver;
} }
/* /*
......
...@@ -57,7 +57,7 @@ static struct tty_struct *sclp_tty; ...@@ -57,7 +57,7 @@ static struct tty_struct *sclp_tty;
static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
static unsigned short int sclp_tty_chars_count; static unsigned short int sclp_tty_chars_count;
struct tty_driver sclp_tty_driver; struct tty_driver *sclp_tty_driver;
extern struct termios tty_std_termios; extern struct termios tty_std_termios;
...@@ -708,28 +708,48 @@ static struct sclp_register sclp_input_event = ...@@ -708,28 +708,48 @@ static struct sclp_register sclp_input_event =
.receiver_fn = sclp_tty_receiver .receiver_fn = sclp_tty_receiver
}; };
static struct tty_operations sclp_ops = {
.open = sclp_tty_open,
.close = sclp_tty_close,
.write = sclp_tty_write,
.put_char = sclp_tty_put_char,
.flush_chars = sclp_tty_flush_chars,
.write_room = sclp_tty_write_room,
.chars_in_buffer = sclp_tty_chars_in_buffer,
.flush_buffer = sclp_tty_flush_buffer,
.ioctl = sclp_tty_ioctl,
};
int __init int __init
sclp_tty_init(void) sclp_tty_init(void)
{ {
struct tty_driver *driver;
void *page; void *page;
int i; int i;
int rc; int rc;
if (!CONSOLE_IS_SCLP) if (!CONSOLE_IS_SCLP)
return 0; return 0;
driver = alloc_tty_driver(1);
if (!driver)
return -ENOMEM;
rc = sclp_rw_init(); rc = sclp_rw_init();
if (rc) { if (rc) {
printk(KERN_ERR SCLP_TTY_PRINT_HEADER printk(KERN_ERR SCLP_TTY_PRINT_HEADER
"could not register tty - " "could not register tty - "
"sclp_rw_init returned %d\n", rc); "sclp_rw_init returned %d\n", rc);
put_tty_driver(driver);
return rc; return rc;
} }
/* Allocate pages for output buffering */ /* Allocate pages for output buffering */
INIT_LIST_HEAD(&sclp_tty_pages); INIT_LIST_HEAD(&sclp_tty_pages);
for (i = 0; i < MAX_KMEM_PAGES; i++) { for (i = 0; i < MAX_KMEM_PAGES; i++) {
page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (page == NULL) if (page == NULL) {
put_tty_driver(driver);
return -ENOMEM; return -ENOMEM;
}
list_add_tail((struct list_head *) page, &sclp_tty_pages); list_add_tail((struct list_head *) page, &sclp_tty_pages);
} }
INIT_LIST_HEAD(&sclp_tty_outqueue); INIT_LIST_HEAD(&sclp_tty_outqueue);
...@@ -752,63 +772,33 @@ sclp_tty_init(void) ...@@ -752,63 +772,33 @@ sclp_tty_init(void)
sclp_tty = NULL; sclp_tty = NULL;
rc = sclp_register(&sclp_input_event); rc = sclp_register(&sclp_input_event);
if (rc) if (rc) {
put_tty_driver(driver);
return rc; return rc;
}
memset (&sclp_tty_driver, 0, sizeof(struct tty_driver)); driver->owner = THIS_MODULE;
sclp_tty_driver.magic = TTY_DRIVER_MAGIC; driver->driver_name = "sclp_line";
sclp_tty_driver.owner = THIS_MODULE; driver->name = "ttyS";
sclp_tty_driver.driver_name = "sclp_line"; driver->major = TTY_MAJOR;
sclp_tty_driver.name = "ttyS"; driver->minor_start = 64;
sclp_tty_driver.major = TTY_MAJOR; driver->type = TTY_DRIVER_TYPE_SYSTEM;
sclp_tty_driver.minor_start = 64; driver->subtype = SYSTEM_TYPE_TTY;
sclp_tty_driver.num = 1; driver->init_termios = tty_std_termios;
sclp_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; driver->init_termios.c_iflag = IGNBRK | IGNPAR;
sclp_tty_driver.subtype = SYSTEM_TYPE_TTY; driver->init_termios.c_oflag = ONLCR | XTABS;
sclp_tty_driver.init_termios = tty_std_termios; driver->init_termios.c_lflag = ISIG | ECHO;
sclp_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR; driver->flags = TTY_DRIVER_REAL_RAW;
sclp_tty_driver.init_termios.c_oflag = ONLCR | XTABS; tty_set_operations(driver, &sclp_ops);
sclp_tty_driver.init_termios.c_lflag = ISIG | ECHO; rc = tty_register_driver(driver);
sclp_tty_driver.flags = TTY_DRIVER_REAL_RAW; if (rc) {
/* sclp_tty_driver.proc_entry ? */
sclp_tty_driver.open = sclp_tty_open;
sclp_tty_driver.close = sclp_tty_close;
sclp_tty_driver.write = sclp_tty_write;
sclp_tty_driver.put_char = sclp_tty_put_char;
sclp_tty_driver.flush_chars = sclp_tty_flush_chars;
sclp_tty_driver.write_room = sclp_tty_write_room;
sclp_tty_driver.chars_in_buffer = sclp_tty_chars_in_buffer;
sclp_tty_driver.flush_buffer = sclp_tty_flush_buffer;
sclp_tty_driver.ioctl = sclp_tty_ioctl;
/*
* No need for these function because they would be only called when
* the line discipline is close to full. That means that there must be
* collected nearly 4kB of input data. I suppose it is very difficult
* for the operator to enter lines quickly enough to let overrun the
* line discipline. Besides the n_tty line discipline does not try to
* call such functions if the pointers are set to NULL. Finally I have
* no idea what to do within these function. I can not prevent the
* operator and the SCLP to deliver input. Because of the reasons
* above it seems not worth to implement a buffer mechanism.
*/
sclp_tty_driver.throttle = NULL;
sclp_tty_driver.unthrottle = NULL;
sclp_tty_driver.send_xchar = NULL;
sclp_tty_driver.set_termios = NULL;
sclp_tty_driver.set_ldisc = NULL;
sclp_tty_driver.stop = NULL;
sclp_tty_driver.start = NULL;
sclp_tty_driver.hangup = NULL;
sclp_tty_driver.break_ctl = NULL;
sclp_tty_driver.wait_until_sent = NULL;
sclp_tty_driver.read_proc = NULL;
sclp_tty_driver.write_proc = NULL;
rc = tty_register_driver(&sclp_tty_driver);
if (rc)
printk(KERN_ERR SCLP_TTY_PRINT_HEADER printk(KERN_ERR SCLP_TTY_PRINT_HEADER
"could not register tty - " "could not register tty - "
"tty_register_driver returned %d\n", rc); "tty_register_driver returned %d\n", rc);
return rc; put_tty_driver(driver);
return rc;
}
sclp_tty_driver = driver;
return 0;
} }
module_init(sclp_tty_init); module_init(sclp_tty_init);
...@@ -66,6 +66,6 @@ struct sclp_ioctls { ...@@ -66,6 +66,6 @@ struct sclp_ioctls {
/* get the number of buffers/pages got from kernel at startup */ /* get the number of buffers/pages got from kernel at startup */
#define TIOCSCLPGKBUF _IOR(SCLP_IOCTL_LETTER, 20, unsigned short) #define TIOCSCLPGKBUF _IOR(SCLP_IOCTL_LETTER, 20, unsigned short)
extern struct tty_driver sclp_tty_driver; extern struct tty_driver *sclp_tty_driver;
#endif /* __SCLP_TTY_H__ */ #endif /* __SCLP_TTY_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment