diff --git a/common/console.c b/common/console.c index 74ccfcf..eccbeed 100644 --- a/common/console.c +++ b/common/console.c @@ -59,6 +59,39 @@ static struct kfifo *console_input_fifo = &__console_input_fifo; static struct kfifo *console_output_fifo = &__console_output_fifo; +int console_open(struct console_device *cdev) +{ + int ret; + + if (cdev->open && !cdev->open_count) { + ret = cdev->open(cdev); + if (ret) + return ret; + } + + cdev->open_count++; + + return 0; +} + +int console_close(struct console_device *cdev) +{ + int ret; + + if (!cdev->open_count) + return -EBADFD; + + cdev->open_count--; + + if (cdev->close && !cdev->open_count) { + ret = cdev->close(cdev); + if (ret) + return ret; + } + + return 0; +} + int console_set_active(struct console_device *cdev, unsigned flag) { int ret, i; @@ -71,8 +104,15 @@ if (!flag && cdev->f_active && cdev->flush) cdev->flush(cdev); - if (cdev->set_active) { - ret = cdev->set_active(cdev, flag); + if (flag == cdev->f_active) + return 0; + + if (!flag) { + ret = console_close(cdev); + if (ret) + return ret; + } else { + ret = console_open(cdev); if (ret) return ret; } @@ -264,6 +304,8 @@ if (newcdev->putc && !newcdev->puts) newcdev->puts = __console_puts; + newcdev->open_count = 0; + dev_add_param(dev, "active", console_active_set, console_active_get, 0); if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) { diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index b5e608e..3b5637b 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -413,21 +413,13 @@ return 0; } -static int fbc_set_active(struct console_device *cdev, unsigned flags) +static int fbc_open(struct console_device *cdev) { struct fbc_priv *priv = container_of(cdev, struct fbc_priv, cdev); struct fb_info *fb = priv->fb; int ret; - if (priv->active) { - fb_close(priv->sc); - priv->active = false; - } - - if (!(flags & (CONSOLE_STDOUT | CONSOLE_STDERR))) - return 0; - ret = setup_font(priv); if (ret) return ret; @@ -448,6 +440,21 @@ return 0; } +static int fbc_close(struct console_device *cdev) +{ + struct fbc_priv *priv = container_of(cdev, + struct fbc_priv, cdev); + + if (priv->active) { + fb_close(priv->sc); + priv->active = false; + + return 0; + } + + return -EINVAL; +} + static int set_font(struct param_d *p, void *vpriv) { struct fbc_priv *priv = vpriv; @@ -482,7 +489,8 @@ cdev->getc = fbc_getc; cdev->devname = "fbconsole"; cdev->devid = DEVICE_ID_DYNAMIC; - cdev->set_active = fbc_set_active; + cdev->open = fbc_open; + cdev->close = fbc_close; ret = console_register(cdev); if (ret) { diff --git a/include/console.h b/include/console.h index 4b2f134..a1ebc85 100644 --- a/include/console.h +++ b/include/console.h @@ -44,7 +44,8 @@ int (*setbrg)(struct console_device *cdev, int baudrate); void (*flush)(struct console_device *cdev); int (*set_mode)(struct console_device *cdev, enum console_mode mode); - int (*set_active)(struct console_device *cdev, unsigned active); + int (*open)(struct console_device *cdev); + int (*close)(struct console_device *cdev); char *devname; int devid; @@ -54,6 +55,8 @@ unsigned char f_active; char active[4]; + unsigned int open_count; + unsigned int baudrate; unsigned int baudrate_param; @@ -75,6 +78,8 @@ struct console_device *console_get_first_active(void); +int console_open(struct console_device *cdev); +int console_close(struct console_device *cdev); int console_set_active(struct console_device *cdev, unsigned active); unsigned console_get_active(struct console_device *cdev); int console_set_baudrate(struct console_device *cdev, unsigned baudrate); diff --git a/net/netconsole.c b/net/netconsole.c index ce3c418..ef8b185 100644 --- a/net/netconsole.c +++ b/net/netconsole.c @@ -105,19 +105,11 @@ priv->busy = 0; } -static int nc_set_active(struct console_device *cdev, unsigned flags) +static int nc_open(struct console_device *cdev) { struct nc_priv *priv = container_of(cdev, struct nc_priv, cdev); - if (priv->con) { - net_unregister(priv->con); - priv->con = NULL; - } - - if (!flags) - return 0; - if (!priv->port) { pr_err("port not set\n"); return -EINVAL; @@ -142,6 +134,20 @@ return 0; } +static int nc_close(struct console_device *cdev) +{ + struct nc_priv *priv = container_of(cdev, + struct nc_priv, cdev); + + if (priv->con) { + net_unregister(priv->con); + priv->con = NULL; + return 0; + } + + return -EINVAL; +} + static int netconsole_init(void) { struct nc_priv *priv; @@ -155,7 +161,8 @@ cdev->getc = nc_getc; cdev->devname = "netconsole"; cdev->devid = DEVICE_ID_SINGLE; - cdev->set_active = nc_set_active; + cdev->open = nc_open; + cdev->close = nc_close; g_priv = priv;