tty: kref the tty driver object
Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
99f1fe189d
Коммит
7d7b93c145
|
@ -264,8 +264,8 @@ static int tracewrap;
|
||||||
/**********/
|
/**********/
|
||||||
|
|
||||||
#if defined(MODULE) && defined(IP2DEBUG_OPEN)
|
#if defined(MODULE) && defined(IP2DEBUG_OPEN)
|
||||||
#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \
|
#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
|
||||||
tty->name,(pCh->flags),ip2_tty_driver->refcount, \
|
tty->name,(pCh->flags), \
|
||||||
tty->count,/*GET_USE_COUNT(module)*/0,s)
|
tty->count,/*GET_USE_COUNT(module)*/0,s)
|
||||||
#else
|
#else
|
||||||
#define DBG_CNT(s)
|
#define DBG_CNT(s)
|
||||||
|
@ -2893,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
|
||||||
case 13:
|
case 13:
|
||||||
switch ( cmd ) {
|
switch ( cmd ) {
|
||||||
case 64: /* Driver - ip2stat */
|
case 64: /* Driver - ip2stat */
|
||||||
rc = put_user(ip2_tty_driver->refcount, pIndex++ );
|
rc = put_user(-1, pIndex++ );
|
||||||
rc = put_user(irq_counter, pIndex++ );
|
rc = put_user(irq_counter, pIndex++ );
|
||||||
rc = put_user(bh_counter, pIndex++ );
|
rc = put_user(bh_counter, pIndex++ );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -571,8 +571,11 @@ static void __init unix98_pty_init(void)
|
||||||
if (tty_register_driver(pts_driver))
|
if (tty_register_driver(pts_driver))
|
||||||
panic("Couldn't register Unix98 pts driver");
|
panic("Couldn't register Unix98 pts driver");
|
||||||
|
|
||||||
|
/* FIXME: WTF */
|
||||||
|
#if 0
|
||||||
pty_table[1].data = &ptm_driver->refcount;
|
pty_table[1].data = &ptm_driver->refcount;
|
||||||
register_sysctl_table(pty_root_table);
|
#endif
|
||||||
|
register_sysctl_table(pty_root_table);
|
||||||
|
|
||||||
/* Now create the /dev/ptmx special device */
|
/* Now create the /dev/ptmx special device */
|
||||||
tty_default_fops(&ptmx_fops);
|
tty_default_fops(&ptmx_fops);
|
||||||
|
|
|
@ -276,7 +276,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
|
||||||
if (device < base || device >= base + p->num)
|
if (device < base || device >= base + p->num)
|
||||||
continue;
|
continue;
|
||||||
*index = device - base;
|
*index = device - base;
|
||||||
return p;
|
return tty_driver_kref_get(p);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
|
||||||
|
|
||||||
if (tty_line >= 0 && tty_line <= p->num && p->ops &&
|
if (tty_line >= 0 && tty_line <= p->num && p->ops &&
|
||||||
p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
|
p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) {
|
||||||
res = p;
|
res = tty_driver_kref_get(p);
|
||||||
*line = tty_line;
|
*line = tty_line;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1410,7 @@ int tty_init_dev(struct tty_driver *driver, int idx,
|
||||||
*o_ltp_loc = o_ltp;
|
*o_ltp_loc = o_ltp;
|
||||||
o_tty->termios = *o_tp_loc;
|
o_tty->termios = *o_tp_loc;
|
||||||
o_tty->termios_locked = *o_ltp_loc;
|
o_tty->termios_locked = *o_ltp_loc;
|
||||||
driver->other->refcount++;
|
tty_driver_kref_get(driver->other);
|
||||||
if (driver->subtype == PTY_TYPE_MASTER)
|
if (driver->subtype == PTY_TYPE_MASTER)
|
||||||
o_tty->count++;
|
o_tty->count++;
|
||||||
|
|
||||||
|
@ -1438,7 +1438,7 @@ int tty_init_dev(struct tty_driver *driver, int idx,
|
||||||
/* Compatibility until drivers always set this */
|
/* Compatibility until drivers always set this */
|
||||||
tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
|
tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
|
||||||
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
|
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
|
||||||
driver->refcount++;
|
tty_driver_kref_get(driver);
|
||||||
tty->count++;
|
tty->count++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1530,8 +1530,7 @@ static void release_one_tty(struct kref *kref)
|
||||||
else
|
else
|
||||||
tty_shutdown(tty);
|
tty_shutdown(tty);
|
||||||
tty->magic = 0;
|
tty->magic = 0;
|
||||||
/* FIXME: locking on tty->driver->refcount */
|
tty_driver_kref_put(driver);
|
||||||
tty->driver->refcount--;
|
|
||||||
module_put(driver->owner);
|
module_put(driver->owner);
|
||||||
|
|
||||||
file_list_lock();
|
file_list_lock();
|
||||||
|
@ -1854,7 +1853,7 @@ retry_open:
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
driver = tty->driver;
|
driver = tty_driver_kref_get(tty->driver);
|
||||||
index = tty->index;
|
index = tty->index;
|
||||||
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
|
filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */
|
||||||
/* noctty = 1; */
|
/* noctty = 1; */
|
||||||
|
@ -1865,14 +1864,14 @@ retry_open:
|
||||||
#ifdef CONFIG_VT
|
#ifdef CONFIG_VT
|
||||||
if (device == MKDEV(TTY_MAJOR, 0)) {
|
if (device == MKDEV(TTY_MAJOR, 0)) {
|
||||||
extern struct tty_driver *console_driver;
|
extern struct tty_driver *console_driver;
|
||||||
driver = console_driver;
|
driver = tty_driver_kref_get(console_driver);
|
||||||
index = fg_console;
|
index = fg_console;
|
||||||
noctty = 1;
|
noctty = 1;
|
||||||
goto got_driver;
|
goto got_driver;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (device == MKDEV(TTYAUX_MAJOR, 1)) {
|
if (device == MKDEV(TTYAUX_MAJOR, 1)) {
|
||||||
driver = console_device(&index);
|
driver = tty_driver_kref_get(console_device(&index));
|
||||||
if (driver) {
|
if (driver) {
|
||||||
/* Don't let /dev/console block */
|
/* Don't let /dev/console block */
|
||||||
filp->f_flags |= O_NONBLOCK;
|
filp->f_flags |= O_NONBLOCK;
|
||||||
|
@ -1891,6 +1890,7 @@ retry_open:
|
||||||
got_driver:
|
got_driver:
|
||||||
retval = tty_init_dev(driver, index, &tty, 0);
|
retval = tty_init_dev(driver, index, &tty, 0);
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
|
tty_driver_kref_put(driver);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -2866,7 +2866,6 @@ int tty_put_char(struct tty_struct *tty, unsigned char ch)
|
||||||
return tty->ops->put_char(tty, ch);
|
return tty->ops->put_char(tty, ch);
|
||||||
return tty->ops->write(tty, &ch, 1);
|
return tty->ops->write(tty, &ch, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(tty_put_char);
|
EXPORT_SYMBOL_GPL(tty_put_char);
|
||||||
|
|
||||||
struct class *tty_class;
|
struct class *tty_class;
|
||||||
|
@ -2909,6 +2908,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index,
|
||||||
|
|
||||||
return device_create_drvdata(tty_class, device, dev, NULL, name);
|
return device_create_drvdata(tty_class, device, dev, NULL, name);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(tty_register_device);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tty_unregister_device - unregister a tty device
|
* tty_unregister_device - unregister a tty device
|
||||||
|
@ -2926,8 +2926,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
|
||||||
device_destroy(tty_class,
|
device_destroy(tty_class,
|
||||||
MKDEV(driver->major, driver->minor_start) + index);
|
MKDEV(driver->major, driver->minor_start) + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(tty_register_device);
|
|
||||||
EXPORT_SYMBOL(tty_unregister_device);
|
EXPORT_SYMBOL(tty_unregister_device);
|
||||||
|
|
||||||
struct tty_driver *alloc_tty_driver(int lines)
|
struct tty_driver *alloc_tty_driver(int lines)
|
||||||
|
@ -2936,28 +2934,71 @@ struct tty_driver *alloc_tty_driver(int lines)
|
||||||
|
|
||||||
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
|
driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
|
||||||
if (driver) {
|
if (driver) {
|
||||||
|
kref_init(&driver->kref);
|
||||||
driver->magic = TTY_DRIVER_MAGIC;
|
driver->magic = TTY_DRIVER_MAGIC;
|
||||||
driver->num = lines;
|
driver->num = lines;
|
||||||
/* later we'll move allocation of tables here */
|
/* later we'll move allocation of tables here */
|
||||||
}
|
}
|
||||||
return driver;
|
return driver;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(alloc_tty_driver);
|
||||||
|
|
||||||
void put_tty_driver(struct tty_driver *driver)
|
static void destruct_tty_driver(struct kref *kref)
|
||||||
{
|
{
|
||||||
|
struct tty_driver *driver = container_of(kref, struct tty_driver, kref);
|
||||||
|
int i;
|
||||||
|
struct ktermios *tp;
|
||||||
|
void *p;
|
||||||
|
|
||||||
|
if (driver->flags & TTY_DRIVER_INSTALLED) {
|
||||||
|
/*
|
||||||
|
* Free the termios and termios_locked structures because
|
||||||
|
* we don't want to get memory leaks when modular tty
|
||||||
|
* drivers are removed from the kernel.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < driver->num; i++) {
|
||||||
|
tp = driver->termios[i];
|
||||||
|
if (tp) {
|
||||||
|
driver->termios[i] = NULL;
|
||||||
|
kfree(tp);
|
||||||
|
}
|
||||||
|
tp = driver->termios_locked[i];
|
||||||
|
if (tp) {
|
||||||
|
driver->termios_locked[i] = NULL;
|
||||||
|
kfree(tp);
|
||||||
|
}
|
||||||
|
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
|
||||||
|
tty_unregister_device(driver, i);
|
||||||
|
}
|
||||||
|
p = driver->ttys;
|
||||||
|
proc_tty_unregister_driver(driver);
|
||||||
|
driver->ttys = NULL;
|
||||||
|
driver->termios = driver->termios_locked = NULL;
|
||||||
|
kfree(p);
|
||||||
|
cdev_del(&driver->cdev);
|
||||||
|
}
|
||||||
kfree(driver);
|
kfree(driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tty_driver_kref_put(struct tty_driver *driver)
|
||||||
|
{
|
||||||
|
kref_put(&driver->kref, destruct_tty_driver);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tty_driver_kref_put);
|
||||||
|
|
||||||
void tty_set_operations(struct tty_driver *driver,
|
void tty_set_operations(struct tty_driver *driver,
|
||||||
const struct tty_operations *op)
|
const struct tty_operations *op)
|
||||||
{
|
{
|
||||||
driver->ops = op;
|
driver->ops = op;
|
||||||
};
|
};
|
||||||
|
|
||||||
EXPORT_SYMBOL(alloc_tty_driver);
|
|
||||||
EXPORT_SYMBOL(put_tty_driver);
|
|
||||||
EXPORT_SYMBOL(tty_set_operations);
|
EXPORT_SYMBOL(tty_set_operations);
|
||||||
|
|
||||||
|
void put_tty_driver(struct tty_driver *d)
|
||||||
|
{
|
||||||
|
tty_driver_kref_put(d);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(put_tty_driver);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called by a tty driver to register itself.
|
* Called by a tty driver to register itself.
|
||||||
*/
|
*/
|
||||||
|
@ -2968,9 +3009,6 @@ int tty_register_driver(struct tty_driver *driver)
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
void **p = NULL;
|
void **p = NULL;
|
||||||
|
|
||||||
if (driver->flags & TTY_DRIVER_INSTALLED)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
|
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
|
||||||
p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
|
p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL);
|
||||||
if (!p)
|
if (!p)
|
||||||
|
@ -3024,6 +3062,7 @@ int tty_register_driver(struct tty_driver *driver)
|
||||||
tty_register_device(driver, i, NULL);
|
tty_register_device(driver, i, NULL);
|
||||||
}
|
}
|
||||||
proc_tty_register_driver(driver);
|
proc_tty_register_driver(driver);
|
||||||
|
driver->flags |= TTY_DRIVER_INSTALLED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3034,46 +3073,19 @@ EXPORT_SYMBOL(tty_register_driver);
|
||||||
*/
|
*/
|
||||||
int tty_unregister_driver(struct tty_driver *driver)
|
int tty_unregister_driver(struct tty_driver *driver)
|
||||||
{
|
{
|
||||||
int i;
|
#if 0
|
||||||
struct ktermios *tp;
|
/* FIXME */
|
||||||
void *p;
|
|
||||||
|
|
||||||
if (driver->refcount)
|
if (driver->refcount)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
#endif
|
||||||
unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
|
unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
|
||||||
driver->num);
|
driver->num);
|
||||||
mutex_lock(&tty_mutex);
|
mutex_lock(&tty_mutex);
|
||||||
list_del(&driver->tty_drivers);
|
list_del(&driver->tty_drivers);
|
||||||
mutex_unlock(&tty_mutex);
|
mutex_unlock(&tty_mutex);
|
||||||
|
|
||||||
/*
|
|
||||||
* Free the termios and termios_locked structures because
|
|
||||||
* we don't want to get memory leaks when modular tty
|
|
||||||
* drivers are removed from the kernel.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < driver->num; i++) {
|
|
||||||
tp = driver->termios[i];
|
|
||||||
if (tp) {
|
|
||||||
driver->termios[i] = NULL;
|
|
||||||
kfree(tp);
|
|
||||||
}
|
|
||||||
tp = driver->termios_locked[i];
|
|
||||||
if (tp) {
|
|
||||||
driver->termios_locked[i] = NULL;
|
|
||||||
kfree(tp);
|
|
||||||
}
|
|
||||||
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV))
|
|
||||||
tty_unregister_device(driver, i);
|
|
||||||
}
|
|
||||||
p = driver->ttys;
|
|
||||||
proc_tty_unregister_driver(driver);
|
|
||||||
driver->ttys = NULL;
|
|
||||||
driver->termios = driver->termios_locked = NULL;
|
|
||||||
kfree(p);
|
|
||||||
cdev_del(&driver->cdev);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(tty_unregister_driver);
|
EXPORT_SYMBOL(tty_unregister_driver);
|
||||||
|
|
||||||
dev_t tty_devnum(struct tty_struct *tty)
|
dev_t tty_devnum(struct tty_struct *tty)
|
||||||
|
|
|
@ -205,7 +205,7 @@ config WANXL_BUILD_FIRMWARE
|
||||||
|
|
||||||
config PC300
|
config PC300
|
||||||
tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
|
tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
|
||||||
depends on HDLC && PCI
|
depends on HDLC && PCI && BROKEN
|
||||||
---help---
|
---help---
|
||||||
Driver for the Cyclades-PC300 synchronous communication boards.
|
Driver for the Cyclades-PC300 synchronous communication boards.
|
||||||
|
|
||||||
|
|
|
@ -253,6 +253,7 @@ struct tty_operations {
|
||||||
|
|
||||||
struct tty_driver {
|
struct tty_driver {
|
||||||
int magic; /* magic number for this structure */
|
int magic; /* magic number for this structure */
|
||||||
|
struct kref kref; /* Reference management */
|
||||||
struct cdev cdev;
|
struct cdev cdev;
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
const char *driver_name;
|
const char *driver_name;
|
||||||
|
@ -266,7 +267,6 @@ struct tty_driver {
|
||||||
short subtype; /* subtype of tty driver */
|
short subtype; /* subtype of tty driver */
|
||||||
struct ktermios init_termios; /* Initial termios */
|
struct ktermios init_termios; /* Initial termios */
|
||||||
int flags; /* tty driver flags */
|
int flags; /* tty driver flags */
|
||||||
int refcount; /* for loadable tty drivers */
|
|
||||||
struct proc_dir_entry *proc_entry; /* /proc fs entry */
|
struct proc_dir_entry *proc_entry; /* /proc fs entry */
|
||||||
struct tty_driver *other; /* only used for the PTY driver */
|
struct tty_driver *other; /* only used for the PTY driver */
|
||||||
|
|
||||||
|
@ -288,12 +288,19 @@ struct tty_driver {
|
||||||
|
|
||||||
extern struct list_head tty_drivers;
|
extern struct list_head tty_drivers;
|
||||||
|
|
||||||
struct tty_driver *alloc_tty_driver(int lines);
|
extern struct tty_driver *alloc_tty_driver(int lines);
|
||||||
void put_tty_driver(struct tty_driver *driver);
|
extern void put_tty_driver(struct tty_driver *driver);
|
||||||
void tty_set_operations(struct tty_driver *driver,
|
extern void tty_set_operations(struct tty_driver *driver,
|
||||||
const struct tty_operations *op);
|
const struct tty_operations *op);
|
||||||
extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
|
extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
|
||||||
|
|
||||||
|
extern void tty_driver_kref_put(struct tty_driver *driver);
|
||||||
|
extern inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d)
|
||||||
|
{
|
||||||
|
kref_get(&d->kref);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
/* tty driver magic number */
|
/* tty driver magic number */
|
||||||
#define TTY_DRIVER_MAGIC 0x5402
|
#define TTY_DRIVER_MAGIC 0x5402
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче