mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
CAPI: Dynamically register minor devices
Register capiminors dynamically with the TTY core so that udev can make them show up as the NCCIs appear or disappear. This removes the need to check if the capiminor requested in capinc_tty_open actually exists. And this completely obsoletes capifs which will be scheduled for removal in a later patch. Signed-off-by: Jan Kiszka <jan.kiszka@web.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e76b154407
commit
40fb2d0da7
@ -153,6 +153,8 @@ static LIST_HEAD(capidev_list);
|
|||||||
static DEFINE_RWLOCK(capiminors_lock);
|
static DEFINE_RWLOCK(capiminors_lock);
|
||||||
static struct capiminor **capiminors;
|
static struct capiminor **capiminors;
|
||||||
|
|
||||||
|
static struct tty_driver *capinc_tty_driver;
|
||||||
|
|
||||||
/* -------- datahandles --------------------------------------------- */
|
/* -------- datahandles --------------------------------------------- */
|
||||||
|
|
||||||
static int capiminor_add_ack(struct capiminor *mp, u16 datahandle)
|
static int capiminor_add_ack(struct capiminor *mp, u16 datahandle)
|
||||||
@ -213,6 +215,7 @@ static void capiminor_del_all_ack(struct capiminor *mp)
|
|||||||
static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
|
static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
|
||||||
{
|
{
|
||||||
struct capiminor *mp;
|
struct capiminor *mp;
|
||||||
|
struct device *dev;
|
||||||
unsigned int minor;
|
unsigned int minor;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -243,19 +246,33 @@ static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
|
|||||||
|
|
||||||
if (minor == capi_ttyminors) {
|
if (minor == capi_ttyminors) {
|
||||||
printk(KERN_NOTICE "capi: out of minors\n");
|
printk(KERN_NOTICE "capi: out of minors\n");
|
||||||
kfree(mp);
|
goto err_out1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mp->minor = minor;
|
mp->minor = minor;
|
||||||
|
|
||||||
|
dev = tty_register_device(capinc_tty_driver, minor, NULL);
|
||||||
|
if (IS_ERR(dev))
|
||||||
|
goto err_out2;
|
||||||
|
|
||||||
return mp;
|
return mp;
|
||||||
|
|
||||||
|
err_out2:
|
||||||
|
write_lock_irqsave(&capiminors_lock, flags);
|
||||||
|
capiminors[minor] = NULL;
|
||||||
|
write_unlock_irqrestore(&capiminors_lock, flags);
|
||||||
|
|
||||||
|
err_out1:
|
||||||
|
kfree(mp);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void capiminor_free(struct capiminor *mp)
|
static void capiminor_free(struct capiminor *mp)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
tty_unregister_device(capinc_tty_driver, mp->minor);
|
||||||
|
|
||||||
write_lock_irqsave(&capiminors_lock, flags);
|
write_lock_irqsave(&capiminors_lock, flags);
|
||||||
capiminors[mp->minor] = NULL;
|
capiminors[mp->minor] = NULL;
|
||||||
write_unlock_irqrestore(&capiminors_lock, flags);
|
write_unlock_irqrestore(&capiminors_lock, flags);
|
||||||
@ -268,13 +285,10 @@ static void capiminor_free(struct capiminor *mp)
|
|||||||
kfree(mp);
|
kfree(mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct capiminor *capiminor_find(unsigned int minor)
|
static struct capiminor *capiminor_get(unsigned int minor)
|
||||||
{
|
{
|
||||||
struct capiminor *mp;
|
struct capiminor *mp;
|
||||||
|
|
||||||
if (minor >= capi_ttyminors)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
read_lock(&capiminors_lock);
|
read_lock(&capiminors_lock);
|
||||||
mp = capiminors[minor];
|
mp = capiminors[minor];
|
||||||
read_unlock(&capiminors_lock);
|
read_unlock(&capiminors_lock);
|
||||||
@ -981,8 +995,7 @@ static int capinc_tty_open(struct tty_struct * tty, struct file * file)
|
|||||||
struct capiminor *mp;
|
struct capiminor *mp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == NULL)
|
mp = capiminor_get(iminor(file->f_path.dentry->d_inode));
|
||||||
return -ENXIO;
|
|
||||||
if (mp->nccip == NULL)
|
if (mp->nccip == NULL)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
||||||
@ -1284,8 +1297,6 @@ static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct tty_driver *capinc_tty_driver;
|
|
||||||
|
|
||||||
static const struct tty_operations capinc_ops = {
|
static const struct tty_operations capinc_ops = {
|
||||||
.open = capinc_tty_open,
|
.open = capinc_tty_open,
|
||||||
.close = capinc_tty_close,
|
.close = capinc_tty_close,
|
||||||
@ -1339,7 +1350,9 @@ static int __init capinc_tty_init(void)
|
|||||||
drv->init_termios.c_oflag = OPOST | ONLCR;
|
drv->init_termios.c_oflag = OPOST | ONLCR;
|
||||||
drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||||
drv->init_termios.c_lflag = 0;
|
drv->init_termios.c_lflag = 0;
|
||||||
drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS;
|
drv->flags =
|
||||||
|
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
|
||||||
|
TTY_DRIVER_DYNAMIC_DEV;
|
||||||
tty_set_operations(drv, &capinc_ops);
|
tty_set_operations(drv, &capinc_ops);
|
||||||
|
|
||||||
err = tty_register_driver(drv);
|
err = tty_register_driver(drv);
|
||||||
|
Loading…
Reference in New Issue
Block a user