History

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.

Andy Shevchenko committed 6 years ago

Commit a3cb39d1 parent 5f3a4812 files · +63 −4Browse files

Unified · Split

2 files
  1. Documentation/ABI/testing/sysfs-tty +7 −0
  2. drivers/tty/serial/serial_core.c +56 −4
Documentation/ABI/testing/sysfs-tty+7−0
@@ -154,3 +154,10 @@ Description: · 153 unmodified lines
154 device specification. For example, when user sets 7bytes on154 device specification. For example, when user sets 7bytes on
155 16550A, which has 1/4/8/14 bytes trigger, the RX trigger is155 16550A, which has 1/4/8/14 bytes trigger, the RX trigger is
156 automatically changed to 4 bytes.156 automatically changed to 4 bytes.
157
158What: /sys/class/tty/ttyS0/console
159Date: February 2020
160Contact: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
161Description:
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+56−4
@@ -1922,7 +1922,7 @@ static inline bool uart_console_enabled(struct uart_port *port) · 1921 unmodified lines
1922 */1922 */
1923static inline void uart_port_spin_lock_init(struct uart_port *port)1923static inline void uart_port_spin_lock_init(struct uart_port *port)
1924{1924{
1925 if (uart_console_enabled(port))1925 if (uart_console(port))
1926 return;1926 return;
1927 1927
1928 spin_lock_init(&port->lock);1928 spin_lock_init(&port->lock);
@@ -2751,6 +2751,56 @@ static ssize_t iomem_reg_shift_show(struct device *dev, · 822 unmodified lines
2751 return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);2751 return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);
2752}2752}
2753 2753
2754static 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
2771static 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
2754static DEVICE_ATTR_RO(uartclk);2804static DEVICE_ATTR_RO(uartclk);
2755static DEVICE_ATTR_RO(type);2805static DEVICE_ATTR_RO(type);
2756static DEVICE_ATTR_RO(line);2806static DEVICE_ATTR_RO(line);
@@ -2764,6 +2814,7 @@ static DEVICE_ATTR_RO(custom_divisor); · 7 unmodified lines
2764static DEVICE_ATTR_RO(io_type);2814static DEVICE_ATTR_RO(io_type);
2765static DEVICE_ATTR_RO(iomem_base);2815static DEVICE_ATTR_RO(iomem_base);
2766static DEVICE_ATTR_RO(iomem_reg_shift);2816static DEVICE_ATTR_RO(iomem_reg_shift);
2817static DEVICE_ATTR_RW(console);
2767 2818
2768static struct attribute *tty_dev_attrs[] = {2819static struct attribute *tty_dev_attrs[] = {
2769 &dev_attr_uartclk.attr,2820 &dev_attr_uartclk.attr,
@@ -2779,12 +2830,13 @@ static struct attribute *tty_dev_attrs[] = { · 9 unmodified lines
2779 &dev_attr_io_type.attr,2830 &dev_attr_io_type.attr,
2780 &dev_attr_iomem_base.attr,2831 &dev_attr_iomem_base.attr,
2781 &dev_attr_iomem_reg_shift.attr,2832 &dev_attr_iomem_reg_shift.attr,
2782 NULL,2833 &dev_attr_console.attr,
2783 };2834 NULL
2835};
2784 2836
2785static const struct attribute_group tty_dev_attr_group = {2837static const struct attribute_group tty_dev_attr_group = {
2786 .attrs = tty_dev_attrs,2838 .attrs = tty_dev_attrs,
2787 };2839};
2788 2840
2789/**2841/**
2790 * uart_add_one_port - attach a driver-defined port structure2842 * uart_add_one_port - attach a driver-defined port structure