Skip to content

Commit a3cb39d

Browse files
andy-shevgregkh
authored andcommitted
serial: core: Allow detach and attach serial device for console
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]>
1 parent 5f3a481 commit a3cb39d

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

Documentation/ABI/testing/sysfs-tty

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,10 @@ Description:
154154
device specification. For example, when user sets 7bytes on
155155
16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
156156
automatically changed to 4 bytes.
157+
158+
What: /sys/class/tty/ttyS0/console
159+
Date: February 2020
160+
Contact: Andy Shevchenko <[email protected]>
161+
Description:
162+
Allows user to detach or attach back the given device as
163+
kernel console. It shows and accepts a boolean variable.

drivers/tty/serial/serial_core.c

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1922,7 +1922,7 @@ static inline bool uart_console_enabled(struct uart_port *port)
19221922
*/
19231923
static inline void uart_port_spin_lock_init(struct uart_port *port)
19241924
{
1925-
if (uart_console_enabled(port))
1925+
if (uart_console(port))
19261926
return;
19271927

19281928
spin_lock_init(&port->lock);
@@ -2751,6 +2751,56 @@ static ssize_t iomem_reg_shift_show(struct device *dev,
27512751
return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
27522752
}
27532753

2754+
static ssize_t console_show(struct device *dev,
2755+
struct device_attribute *attr, char *buf)
2756+
{
2757+
struct tty_port *port = dev_get_drvdata(dev);
2758+
struct uart_state *state = container_of(port, struct uart_state, port);
2759+
struct uart_port *uport;
2760+
bool console = false;
2761+
2762+
mutex_lock(&port->mutex);
2763+
uport = uart_port_check(state);
2764+
if (uport)
2765+
console = uart_console_enabled(uport);
2766+
mutex_unlock(&port->mutex);
2767+
2768+
return sprintf(buf, "%c\n", console ? 'Y' : 'N');
2769+
}
2770+
2771+
static ssize_t console_store(struct device *dev,
2772+
struct device_attribute *attr, const char *buf, size_t count)
2773+
{
2774+
struct tty_port *port = dev_get_drvdata(dev);
2775+
struct uart_state *state = container_of(port, struct uart_state, port);
2776+
struct uart_port *uport;
2777+
bool oldconsole, newconsole;
2778+
int ret;
2779+
2780+
ret = kstrtobool(buf, &newconsole);
2781+
if (ret)
2782+
return ret;
2783+
2784+
mutex_lock(&port->mutex);
2785+
uport = uart_port_check(state);
2786+
if (uport) {
2787+
oldconsole = uart_console_enabled(uport);
2788+
if (oldconsole && !newconsole) {
2789+
ret = unregister_console(uport->cons);
2790+
} else if (!oldconsole && newconsole) {
2791+
if (uart_console(uport))
2792+
register_console(uport->cons);
2793+
else
2794+
ret = -ENOENT;
2795+
}
2796+
} else {
2797+
ret = -ENXIO;
2798+
}
2799+
mutex_unlock(&port->mutex);
2800+
2801+
return ret < 0 ? ret : count;
2802+
}
2803+
27542804
static DEVICE_ATTR_RO(uartclk);
27552805
static DEVICE_ATTR_RO(type);
27562806
static DEVICE_ATTR_RO(line);
@@ -2764,6 +2814,7 @@ static DEVICE_ATTR_RO(custom_divisor);
27642814
static DEVICE_ATTR_RO(io_type);
27652815
static DEVICE_ATTR_RO(iomem_base);
27662816
static DEVICE_ATTR_RO(iomem_reg_shift);
2817+
static DEVICE_ATTR_RW(console);
27672818

27682819
static struct attribute *tty_dev_attrs[] = {
27692820
&dev_attr_uartclk.attr,
@@ -2779,12 +2830,13 @@ static struct attribute *tty_dev_attrs[] = {
27792830
&dev_attr_io_type.attr,
27802831
&dev_attr_iomem_base.attr,
27812832
&dev_attr_iomem_reg_shift.attr,
2782-
NULL,
2783-
};
2833+
&dev_attr_console.attr,
2834+
NULL
2835+
};
27842836

27852837
static const struct attribute_group tty_dev_attr_group = {
27862838
.attrs = tty_dev_attrs,
2787-
};
2839+
};
27882840

27892841
/**
27902842
* uart_add_one_port - attach a driver-defined port structure

0 commit comments

Comments
 (0)