Skip to content

Commit

Permalink
serial: core: Allow detach and attach serial device for console
Browse files Browse the repository at this point in the history
In the future we would like to disable power management on the serial devices
used as kernel consoles to avoid weird behaviour in some cases. However,
disabling PM may prevent system to go to deep sleep states, which in its turn
leads to the higher power consumption.

Tony Lindgren proposed a work around, i.e. allow user to detach such consoles
to make PM working again. In case user wants to see what's going on, it also
provides a mechanism to attach console back.

Link: https://lists.openwall.net/linux-kernel/2018/09/29/65
Suggested-by: Tony Lindgren <[email protected]>
Signed-off-by: Andy Shevchenko <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
andy-shev authored and gregkh committed Mar 17, 2020
1 parent 5f3a481 commit a3cb39d
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
7 changes: 7 additions & 0 deletions Documentation/ABI/testing/sysfs-tty
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
Description:
Allows user to detach or attach back the given device as
kernel console. It shows and accepts a boolean variable.
60 changes: 56 additions & 4 deletions drivers/tty/serial/serial_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand All @@ -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
Expand Down

0 comments on commit a3cb39d

Please sign in to comment.