summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-tty7
-rw-r--r--drivers/tty/serial/serial_core.c60
2 files changed, 63 insertions, 4 deletions
diff --git a/Documentation/ABI/testing/sysfs-tty b/Documentation/ABI/testing/sysfs-tty
index 9eb3c2b6b040..e157130a6792 100644
--- a/Documentation/ABI/testing/sysfs-tty
+++ b/Documentation/ABI/testing/sysfs-tty
@@ -154,3 +154,10 @@ Description:
device specification. For example, when user sets 7bytes on
16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
automatically changed to 4 bytes.
+
+What: /sys/class/tty/ttyS0/console
+Date: February 2020
+Contact: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Description:
+ Allows user to detach or attach back the given device as
+ kernel console. It shows and accepts a boolean variable.
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 38ef6afddce8..66a5e2faf57e 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1922,7 +1922,7 @@ static inline bool uart_console_enabled(struct uart_port *port)
*/
static inline void uart_port_spin_lock_init(struct uart_port *port)
{
- if (uart_console_enabled(port))
+ if (uart_console(port))
return;
spin_lock_init(&port->lock);
@@ -2751,6 +2751,56 @@ static ssize_t iomem_reg_shift_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
}
+static ssize_t console_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tty_port *port = dev_get_drvdata(dev);
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct uart_port *uport;
+ bool console = false;
+
+ mutex_lock(&port->mutex);
+ uport = uart_port_check(state);
+ if (uport)
+ console = uart_console_enabled(uport);
+ mutex_unlock(&port->mutex);
+
+ return sprintf(buf, "%c\n", console ? 'Y' : 'N');
+}
+
+static ssize_t console_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct tty_port *port = dev_get_drvdata(dev);
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct uart_port *uport;
+ bool oldconsole, newconsole;
+ int ret;
+
+ ret = kstrtobool(buf, &newconsole);
+ if (ret)
+ return ret;
+
+ mutex_lock(&port->mutex);
+ uport = uart_port_check(state);
+ if (uport) {
+ oldconsole = uart_console_enabled(uport);
+ if (oldconsole && !newconsole) {
+ ret = unregister_console(uport->cons);
+ } else if (!oldconsole && newconsole) {
+ if (uart_console(uport))
+ register_console(uport->cons);
+ else
+ ret = -ENOENT;
+ }
+ } else {
+ ret = -ENXIO;
+ }
+ mutex_unlock(&port->mutex);
+
+ return ret < 0 ? ret : count;
+}
+
static DEVICE_ATTR_RO(uartclk);
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(line);
@@ -2764,6 +2814,7 @@ static DEVICE_ATTR_RO(custom_divisor);
static DEVICE_ATTR_RO(io_type);
static DEVICE_ATTR_RO(iomem_base);
static DEVICE_ATTR_RO(iomem_reg_shift);
+static DEVICE_ATTR_RW(console);
static struct attribute *tty_dev_attrs[] = {
&dev_attr_uartclk.attr,
@@ -2779,12 +2830,13 @@ static struct attribute *tty_dev_attrs[] = {
&dev_attr_io_type.attr,
&dev_attr_iomem_base.attr,
&dev_attr_iomem_reg_shift.attr,
- NULL,
- };
+ &dev_attr_console.attr,
+ NULL
+};
static const struct attribute_group tty_dev_attr_group = {
.attrs = tty_dev_attrs,
- };
+};
/**
* uart_add_one_port - attach a driver-defined port structure