* [RFC v2 4/6] serial: core: support deferring serdev controller registration
From: Ulrich Hecht @ 2017-07-17 15:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh, peda,
geert, linux-i2c, Ulrich Hecht
In-Reply-To: <1500305076-15570-1-git-send-email-ulrich.hecht+renesas@gmail.com>
serdev controllers may depend on other devices (such as multiplexers)
and thus require deferred probing support.
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
drivers/tty/serial/serial_core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index f534a40..30a8997 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2785,6 +2785,10 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
uport->line, uport->dev, port, uport->tty_groups);
if (likely(!IS_ERR(tty_dev))) {
device_set_wakeup_capable(tty_dev, 1);
+ } else if (PTR_ERR(tty_dev) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ state->uart_port = NULL;
+ goto out;
} else {
dev_err(uport->dev, "Cannot register tty device on line %d\n",
uport->line);
--
2.7.4
^ permalink raw reply related
* [RFC v2 3/6] serdev: add multiplexer support
From: Ulrich Hecht @ 2017-07-17 15:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh, peda,
geert, linux-i2c, Ulrich Hecht
In-Reply-To: <1500305076-15570-1-git-send-email-ulrich.hecht+renesas@gmail.com>
Adds an interface for slave device multiplexing using the mux subsystem.
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
drivers/tty/serdev/Kconfig | 3 +++
drivers/tty/serdev/Makefile | 1 +
drivers/tty/serdev/core.c | 14 +++++++++-
drivers/tty/serdev/mux.c | 66 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/serdev.h | 16 ++++++++---
5 files changed, 96 insertions(+), 4 deletions(-)
create mode 100644 drivers/tty/serdev/mux.c
diff --git a/drivers/tty/serdev/Kconfig b/drivers/tty/serdev/Kconfig
index cdc6b82..9096b71 100644
--- a/drivers/tty/serdev/Kconfig
+++ b/drivers/tty/serdev/Kconfig
@@ -13,4 +13,7 @@ config SERIAL_DEV_CTRL_TTYPORT
depends on TTY
depends on SERIAL_DEV_BUS != m
+config SERIAL_DEV_MUX
+ bool "Serial device multiplexer support"
+
endif
diff --git a/drivers/tty/serdev/Makefile b/drivers/tty/serdev/Makefile
index 0cbdb94..d713381 100644
--- a/drivers/tty/serdev/Makefile
+++ b/drivers/tty/serdev/Makefile
@@ -1,5 +1,6 @@
serdev-objs := core.o
obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o
+obj-$(CONFIG_SERIAL_DEV_MUX) += mux.o
obj-$(CONFIG_SERIAL_DEV_CTRL_TTYPORT) += serdev-ttyport.o
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 1fbaa4c..92c5bfa 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -305,7 +305,8 @@ struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl)
return NULL;
serdev->ctrl = ctrl;
- ctrl->serdev = serdev;
+ if (!ctrl->serdev)
+ ctrl->serdev = serdev;
device_initialize(&serdev->dev);
serdev->dev.parent = &ctrl->dev;
serdev->dev.bus = &serdev_bus_type;
@@ -368,6 +369,8 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
struct serdev_device *serdev = NULL;
int err;
bool found = false;
+ int nr = 0;
+ u32 reg;
for_each_available_child_of_node(ctrl->dev.of_node, node) {
if (!of_get_property(node, "compatible", NULL))
@@ -380,6 +383,10 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
continue;
serdev->dev.of_node = node;
+ serdev->nr = nr++;
+
+ if (!of_property_read_u32(node, "reg", ®))
+ serdev->mux_addr = reg;
err = serdev_device_add(serdev);
if (err) {
@@ -414,6 +421,11 @@ int serdev_controller_add(struct serdev_controller *ctrl)
if (ret)
return ret;
+#ifdef CONFIG_SERIAL_DEV_MUX
+ if (of_serdev_register_mux(ctrl) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+#endif
+
ret = of_serdev_register_devices(ctrl);
if (ret)
goto out_dev_del;
diff --git a/drivers/tty/serdev/mux.c b/drivers/tty/serdev/mux.c
new file mode 100644
index 0000000..fc9405b
--- /dev/null
+++ b/drivers/tty/serdev/mux.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 Ulrich Hecht
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mux/consumer.h>
+#include <linux/mux/driver.h>
+#include <linux/of_gpio.h>
+#include <linux/serdev.h>
+#include <linux/slab.h>
+
+int serdev_device_mux_select(struct serdev_device *serdev)
+{
+ struct mux_control *mux = serdev->ctrl->mux;
+ int ret;
+
+ if (!mux)
+ return -EINVAL;
+
+ ret = mux_control_select(mux, serdev->mux_addr);
+ serdev->ctrl->mux_do_not_deselect = ret < 0;
+
+ serdev->ctrl->serdev = serdev;
+
+ return ret;
+}
+
+int serdev_device_mux_deselect(struct serdev_device *serdev)
+{
+ struct mux_control *mux = serdev->ctrl->mux;
+
+ if (!mux)
+ return -EINVAL;
+
+ if (!serdev->ctrl->mux_do_not_deselect)
+ return mux_control_deselect(mux);
+ else
+ return 0;
+}
+
+int of_serdev_register_mux(struct serdev_controller *ctrl)
+{
+ struct mux_control *mux;
+ struct device *dev = &ctrl->dev;
+
+ mux = devm_mux_control_get(dev, NULL);
+
+ if (IS_ERR(mux)) {
+ if (PTR_ERR(mux) != -EPROBE_DEFER)
+ dev_err(dev, "failed to get control mux\n");
+ return PTR_ERR(mux);
+ }
+
+ ctrl->mux = mux;
+
+ return 0;
+}
+
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 8b67fcd..26d5994 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/termios.h>
#include <linux/delay.h>
+#include <linux/rtmutex.h>
struct serdev_controller;
struct serdev_device;
@@ -51,6 +52,7 @@ struct serdev_device {
const struct serdev_device_ops *ops;
struct completion write_comp;
struct mutex write_lock;
+ int mux_addr;
};
static inline struct serdev_device *to_serdev_device(struct device *d)
@@ -76,6 +78,8 @@ static inline struct serdev_device_driver *to_serdev_device_driver(struct device
return container_of(d, struct serdev_device_driver, driver);
}
+int of_serdev_register_mux(struct serdev_controller *ctrl);
+
/*
* serdev controller structures
*/
@@ -97,14 +101,18 @@ struct serdev_controller_ops {
* struct serdev_controller - interface to the serdev controller
* @dev: Driver model representation of the device.
* @nr: number identifier for this controller/bus.
- * @serdev: Pointer to slave device for this controller.
+ * @serdev: Pointer to active slave device for this controller.
* @ops: Controller operations.
+ * @mux: Slave multiplexer control.
+ * @mux_do_not_deselect: Set if slave selection failed.
*/
struct serdev_controller {
struct device dev;
unsigned int nr;
struct serdev_device *serdev;
const struct serdev_controller_ops *ops;
+ struct mux_control *mux;
+ int mux_do_not_deselect;
};
static inline struct serdev_controller *to_serdev_controller(struct device *d)
@@ -172,7 +180,7 @@ static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl
{
struct serdev_device *serdev = ctrl->serdev;
- if (!serdev || !serdev->ops->write_wakeup)
+ if (!serdev || !serdev->ops || !serdev->ops->write_wakeup)
return;
serdev->ops->write_wakeup(serdev);
@@ -184,7 +192,7 @@ static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
{
struct serdev_device *serdev = ctrl->serdev;
- if (!serdev || !serdev->ops->receive_buf)
+ if (!serdev || !serdev->ops || !serdev->ops->receive_buf)
return -EINVAL;
return serdev->ops->receive_buf(serdev, data, count);
@@ -204,6 +212,8 @@ void serdev_device_write_wakeup(struct serdev_device *);
int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, unsigned long);
void serdev_device_write_flush(struct serdev_device *);
int serdev_device_write_room(struct serdev_device *);
+int serdev_device_mux_select(struct serdev_device *);
+int serdev_device_mux_deselect(struct serdev_device *);
/*
* serdev device driver functions
--
2.7.4
^ permalink raw reply related
* [RFC v2 2/6] serdev: add method to set parity
From: Ulrich Hecht @ 2017-07-17 15:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh, peda,
geert, linux-i2c, Ulrich Hecht
In-Reply-To: <1500305076-15570-1-git-send-email-ulrich.hecht+renesas@gmail.com>
Adds serdev_device_set_parity() and an implementation for ttyport.
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
drivers/tty/serdev/core.c | 12 ++++++++++++
drivers/tty/serdev/serdev-ttyport.c | 17 +++++++++++++++++
include/linux/serdev.h | 4 ++++
3 files changed, 33 insertions(+)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index f71b473..1fbaa4c 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -242,6 +242,18 @@ int serdev_device_set_tiocm(struct serdev_device *serdev, int set, int clear)
}
EXPORT_SYMBOL_GPL(serdev_device_set_tiocm);
+int serdev_device_set_parity(struct serdev_device *serdev,
+ bool enable, bool odd)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+
+ if (!ctrl || !ctrl->ops->set_parity)
+ return -ENOTSUPP;
+
+ return ctrl->ops->set_parity(ctrl, enable, odd);
+}
+EXPORT_SYMBOL_GPL(serdev_device_set_parity);
+
static int serdev_drv_probe(struct device *dev)
{
const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index 302018d..9114956 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -195,6 +195,22 @@ static int ttyport_set_tiocm(struct serdev_controller *ctrl, unsigned int set, u
return tty->driver->ops->tiocmset(tty, set, clear);
}
+static int ttyport_set_parity(struct serdev_controller *ctrl,
+ bool enable, bool odd)
+{
+ struct serport *serport = serdev_controller_get_drvdata(ctrl);
+ struct tty_struct *tty = serport->tty;
+ struct ktermios ktermios = tty->termios;
+
+ ktermios.c_cflag &= ~(PARENB | PARODD);
+ if (enable)
+ ktermios.c_cflag |= PARENB;
+ if (odd)
+ ktermios.c_cflag |= PARODD;
+
+ return tty_set_termios(tty, &ktermios);
+}
+
static const struct serdev_controller_ops ctrl_ops = {
.write_buf = ttyport_write_buf,
.write_flush = ttyport_write_flush,
@@ -206,6 +222,7 @@ static const struct serdev_controller_ops ctrl_ops = {
.wait_until_sent = ttyport_wait_until_sent,
.get_tiocm = ttyport_get_tiocm,
.set_tiocm = ttyport_set_tiocm,
+ .set_parity = ttyport_set_parity,
};
struct device *serdev_tty_port_register(struct tty_port *port,
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index e69402d..8b67fcd 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -90,6 +90,7 @@ struct serdev_controller_ops {
void (*wait_until_sent)(struct serdev_controller *, long);
int (*get_tiocm)(struct serdev_controller *);
int (*set_tiocm)(struct serdev_controller *, unsigned int, unsigned int);
+ int (*set_parity)(struct serdev_controller *, bool, bool);
};
/**
@@ -298,6 +299,9 @@ static inline int serdev_device_set_rts(struct serdev_device *serdev, bool enabl
return serdev_device_set_tiocm(serdev, 0, TIOCM_RTS);
}
+int serdev_device_set_parity(struct serdev_device *serdev,
+ bool enable, bool odd);
+
/*
* serdev hooks into TTY core
*/
--
2.7.4
^ permalink raw reply related
* [RFC v2 1/6] mux: include compiler.h from mux/consumer.h
From: Ulrich Hecht @ 2017-07-17 15:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh, peda,
geert, linux-i2c, Ulrich Hecht
In-Reply-To: <1500305076-15570-1-git-send-email-ulrich.hecht+renesas@gmail.com>
Required for __must_check.
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
include/linux/mux/consumer.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h
index 5577e1b..ea96d4c 100644
--- a/include/linux/mux/consumer.h
+++ b/include/linux/mux/consumer.h
@@ -13,6 +13,8 @@
#ifndef _LINUX_MUX_CONSUMER_H
#define _LINUX_MUX_CONSUMER_H
+#include <linux/compiler.h>
+
struct device;
struct mux_control;
--
2.7.4
^ permalink raw reply related
* [RFC v2 0/6] serdev multiplexing support
From: Ulrich Hecht @ 2017-07-17 15:24 UTC (permalink / raw)
To: linux-serial
Cc: linux-renesas-soc, magnus.damm, laurent.pinchart, wsa, robh, peda,
geert, linux-i2c, Ulrich Hecht
Hi!
This is a new attempt to add multiplexer support to serdev. It is now based
on the mux subsystem, making it more generic than the previous iteration
("[RFC 0/4] serdev GPIO-based multiplexing support").
Thanks to reviewers for their comments. This revision incorporates the
changes suggested as far as they are still applicable, which mostly applies
to those concerning the MAX9260 i2c adapter driver.
New patches have been added that fix a small issue in the mux include files
("mux: include compiler.h from mux/consumer.h"), and implement deferred
probing of serdev controllers ("serial: core: support deferring serdev
controller registration"), hopefully correctly.
This series depends on the "pinctrl: sh-pfc: r8a7792: Add SCIF1 pin groups"
patch as well as v15 of the mux subsystem series ("[PATCH v15 00/13] mux
controller abstraction and iio/i2c muxes").
CU
Uli
Ulrich Hecht (6):
mux: include compiler.h from mux/consumer.h
serdev: add method to set parity
serdev: add multiplexer support
serial: core: support deferring serdev controller registration
max9260: add driver for i2c over GMSL passthrough
ARM: dts: blanche: add SCIF1 and MAX9260 deserializer
arch/arm/boot/dts/r8a7792-blanche.dts | 52 ++++++
drivers/media/i2c/Kconfig | 6 +
drivers/media/i2c/Makefile | 1 +
drivers/media/i2c/max9260.c | 288 ++++++++++++++++++++++++++++++++++
drivers/tty/serdev/Kconfig | 3 +
drivers/tty/serdev/Makefile | 1 +
drivers/tty/serdev/core.c | 26 ++-
drivers/tty/serdev/mux.c | 66 ++++++++
drivers/tty/serdev/serdev-ttyport.c | 17 ++
drivers/tty/serial/serial_core.c | 4 +
include/linux/mux/consumer.h | 2 +
include/linux/serdev.h | 20 ++-
12 files changed, 482 insertions(+), 4 deletions(-)
create mode 100644 drivers/media/i2c/max9260.c
create mode 100644 drivers/tty/serdev/mux.c
--
2.7.4
^ permalink raw reply
* Re: [Customers.Eckelmann] [PATCH] serial: imx: disable DMA for RS-485 on i.MX6 SMP
From: Fabio Estevam @ 2017-07-17 11:34 UTC (permalink / raw)
To: Schenk, Gavin
Cc: Clemens Gruber, linux-serial@vger.kernel.org, Greg Kroah-Hartman,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
u.kleine-koenig@pengutronix.de, Fabio Estevam, Ian Jamison
In-Reply-To: <D415CD2EC4182C4EAB90A76B7D9F16DC022038EACC@EX-DAG02.eckelmann.group>
Hi Gavin,
On Fri, Jun 23, 2017 at 6:26 AM, Schenk, Gavin <G.Schenk@eckelmann.de> wrote:
> Uwe Kleine-König had the idea to disable DMA on the i.MX6dl based platform via dts and this is our current workaround.
Please test Ian's patch:
http://marc.info/?l=linux-serial&m=150005865213531&w=2
It should fix this DMA problem with RS485.
^ permalink raw reply
* Re: [PATCH] serial: st-asc: Potential error pointer dereference
From: Lee Jones @ 2017-07-17 10:28 UTC (permalink / raw)
To: Dan Carpenter
Cc: Patrice Chotard, Greg Kroah-Hartman, Jiri Slaby, linux-serial,
kernel-janitors
In-Reply-To: <20170717081238.bjjp5vvzq56yv2q3@mwanda>
On Mon, 17 Jul 2017, Dan Carpenter wrote:
> It looks like we intended to return an error code here, because we
> dereference "ascport->pinctrl" on the next lines.
>
> Fixes: 6929cb00a501 ("serial: st-asc: Read in all Pinctrl states")
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
>
> diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
> index f5335be344f6..6b0ca65027d0 100644
> --- a/drivers/tty/serial/st-asc.c
> +++ b/drivers/tty/serial/st-asc.c
> @@ -758,6 +758,7 @@ static int asc_init_port(struct asc_port *ascport,
> if (IS_ERR(ascport->pinctrl)) {
> ret = PTR_ERR(ascport->pinctrl);
> dev_err(&pdev->dev, "Failed to get Pinctrl: %d\n", ret);
> + return ret;
> }
Good spot.
Acked-by: Lee Jones <lee.jones@linaro.org>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* [PATCH v2] serial: sh-sci: Uninitialized variables in sysfs files
From: Dan Carpenter @ 2017-07-17 8:34 UTC (permalink / raw)
To: Greg Kroah-Hartman, Ulrich Hecht
Cc: Jiri Slaby, linux-serial, kernel-janitors
In-Reply-To: <20170717081123.akqck2wmj7m7gtc4@mwanda>
The kstrtol() function returns -ERANGE as well as -EINVAL so these tests
are not enough. It's not a super serious bug, but my static checker
correctly complains that the "r" variable might be used uninitialized.
Fixes: 5d23188a473d ("serial: sh-sci: make RX FIFO parameters tunable via sysfs")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
v2: fix subject line
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index da5ddfc14778..e08b16b070c0 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1085,10 +1085,12 @@ static ssize_t rx_trigger_store(struct device *dev,
{
struct uart_port *port = dev_get_drvdata(dev);
struct sci_port *sci = to_sci_port(port);
+ int ret;
long r;
- if (kstrtol(buf, 0, &r) == -EINVAL)
- return -EINVAL;
+ ret = kstrtol(buf, 0, &r);
+ if (ret)
+ return ret;
sci->rx_trigger = scif_set_rtrg(port, r);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
@@ -1116,10 +1118,12 @@ static ssize_t rx_fifo_timeout_store(struct device *dev,
{
struct uart_port *port = dev_get_drvdata(dev);
struct sci_port *sci = to_sci_port(port);
+ int ret;
long r;
- if (kstrtol(buf, 0, &r) == -EINVAL)
- return -EINVAL;
+ ret = kstrtol(buf, 0, &r);
+ if (ret)
+ return ret;
sci->rx_fifo_timeout = r;
scif_set_rtrg(port, 1);
if (r > 0)
--
To unsubscribe from this list: send the line "unsubscribe kernel-janitors" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* Re: [PATCH] serial: sh-sci: Uninitialized versions in sysfs files
From: Dan Carpenter @ 2017-07-17 8:32 UTC (permalink / raw)
To: Greg Kroah-Hartman, Ulrich Hecht
Cc: Jiri Slaby, linux-serial, kernel-janitors
In-Reply-To: <20170717081123.akqck2wmj7m7gtc4@mwanda>
The subject is wrong. I meant to type "variables" but my fingers messed
up. I'll resend.
regards,
dan carpenter
^ permalink raw reply
* [PATCH] serial: st-asc: Potential error pointer dereference
From: Dan Carpenter @ 2017-07-17 8:12 UTC (permalink / raw)
To: Patrice Chotard, Lee Jones
Cc: Greg Kroah-Hartman, Jiri Slaby, linux-serial, kernel-janitors
It looks like we intended to return an error code here, because we
dereference "ascport->pinctrl" on the next lines.
Fixes: 6929cb00a501 ("serial: st-asc: Read in all Pinctrl states")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index f5335be344f6..6b0ca65027d0 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -758,6 +758,7 @@ static int asc_init_port(struct asc_port *ascport,
if (IS_ERR(ascport->pinctrl)) {
ret = PTR_ERR(ascport->pinctrl);
dev_err(&pdev->dev, "Failed to get Pinctrl: %d\n", ret);
+ return ret;
}
ascport->states[DEFAULT] =
^ permalink raw reply related
* [PATCH] serial: sh-sci: Uninitialized versions in sysfs files
From: Dan Carpenter @ 2017-07-17 8:11 UTC (permalink / raw)
To: Greg Kroah-Hartman, Ulrich Hecht
Cc: Jiri Slaby, linux-serial, kernel-janitors
The kstrtol() function returns -ERANGE as well as -EINVAL so these tests
are not enough. It's not a super serious bug, but my static checker
correctly complains that the "r" variable might be used uninitialized.
Fixes: 5d23188a473d ("serial: sh-sci: make RX FIFO parameters tunable via sysfs")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index da5ddfc14778..e08b16b070c0 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -1085,10 +1085,12 @@ static ssize_t rx_trigger_store(struct device *dev,
{
struct uart_port *port = dev_get_drvdata(dev);
struct sci_port *sci = to_sci_port(port);
+ int ret;
long r;
- if (kstrtol(buf, 0, &r) == -EINVAL)
- return -EINVAL;
+ ret = kstrtol(buf, 0, &r);
+ if (ret)
+ return ret;
sci->rx_trigger = scif_set_rtrg(port, r);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
@@ -1116,10 +1118,12 @@ static ssize_t rx_fifo_timeout_store(struct device *dev,
{
struct uart_port *port = dev_get_drvdata(dev);
struct sci_port *sci = to_sci_port(port);
+ int ret;
long r;
- if (kstrtol(buf, 0, &r) == -EINVAL)
- return -EINVAL;
+ ret = kstrtol(buf, 0, &r);
+ if (ret)
+ return ret;
sci->rx_fifo_timeout = r;
scif_set_rtrg(port, 1);
if (r > 0)
^ permalink raw reply related
* Re: [PATCH 0/2] Avoid crashes by early (boot) consoles using init memory
From: Fabio M. Di Nitto @ 2017-07-15 5:05 UTC (permalink / raw)
To: Petr Mladek
Cc: Sergey Senozhatsky, Steven Rostedt, Andrew Morton, Peter Zijlstra,
Matt Redfearn, Greg Kroah-Hartman, Jiri Slaby, David S. Miller,
Alan Cox, linux-serial, linux-kernel, Sergey Senozhatsky
In-Reply-To: <20170714143751.GB32632@pathway.suse.cz>
On 7/14/2017 4:37 PM, Petr Mladek wrote:
> On Fri 2017-07-14 14:57:45, Fabio M. Di Nitto wrote:
>> Hi Petr,
>>
>> On 7/14/2017 2:51 PM, Petr Mladek wrote:
>>> Some early consoles have code and data in the init section. It makes some
>>> sense but this might cause problems when they are not replaced by
>>> the real console in time. The two patches fix the safequard and
>>> help to avoid the problems.
>>>
>>> I though about removing keep_bootcon option completely. But it is useful
>>> at least for now.
>>
>> Let´s just keep in mind that keep_bootcon was introduced only to debug
>> issues (read crashes or hangs) that could happen between disabling
>> bootconsole and enabling the real console. It shouldn´t be used for
>> anything else really.
>
> This was my initial replay as well. But then I realized that
> it was a bad idea to use a freed code and data to debug any other
> issue. It would just create crazy issues on its own.
Perhaps some changes that were made later in the code introduced this
behavior. I honestly didn´t check. It´s been just so long ago :-)
>
> I tried to google 'keep_bootcon'. It found several links to strange
> crashes related to this option. Maybe I was not patient enough but
> I did not find any page where this option was suggested and helped.
It´s in Documentation/admin-guide/kernel-parameters.txt. It´s also rare
that consoles are not working or something is crashing in that small
window, so I am not entirely surprised that there are few to none
references of users using it.
>
> I still think that the option makes some sense but only when
> it does not cause more breakages on its own.
agreed.
Cheers
Fabio
>
>> If the new code can replace keep_bootcon, by all mean, go for it :-)
>
> keep_bootcon stays usable for most early consoles. We print a warning
> when an unusable console is disabled too early. Also there is a
> comment how to fix it.
>
> Best Regards,
> Petr
>
^ permalink raw reply
* Re: [PATCH 2/2] printk/console: Enhance the check for consoles using init memory
From: Sergey Senozhatsky @ 2017-07-14 22:06 UTC (permalink / raw)
To: Petr Mladek
Cc: Sergey Senozhatsky, Steven Rostedt, Andrew Morton, Peter Zijlstra,
Matt Redfearn, Greg Kroah-Hartman, Jiri Slaby, David S. Miller,
Alan Cox, Fabio M. Di Nitto, linux-serial, linux-kernel,
Sergey Senozhatsky
In-Reply-To: <1500036673-7122-3-git-send-email-pmladek@suse.com>
On (07/14/17 14:51), Petr Mladek wrote:
[..]
> diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
> index f35d3ac3b8c7..1ebe1525ef64 100644
> --- a/kernel/printk/printk.c
> +++ b/kernel/printk/printk.c
> @@ -2659,8 +2659,16 @@ static int __init printk_late_init(void)
> int ret;
>
> for_each_console(con) {
> - if ((con->flags & CON_BOOT) &&
> - init_section_intersects(con, sizeof(*con))) {
> + if (!(con->flags & CON_BOOT))
> + continue;
> +
> + /* Check addresses that might be used for enabled consoles. */
> + if (init_section_intersects(con, sizeof(*con)) ||
> + init_section_contains(con->write, 0) ||
> + init_section_contains(con->read, 0) ||
> + init_section_contains(con->device, 0) ||
> + init_section_contains(con->unblank, 0) ||
> + init_section_contains(con->data, 0)) {
sort of a problem here is that the next time anyone adds a new ->foo()
callback to struct console, that person also needs to remember to update
printk_late_init().
a completely crazy idea,
can we have a dedicated "console init" section which we will not offload
if we see keep_bootcon?
or... even crazier... disable bootmem offloading (do not offload init
section) at all if we see keep_bootcon? keep_bootcon is a purely debugging
option which people enable when things are bad and unclear, no one should
be using it otherwise, so may be that idea can be a way to go.
thoughts?
-ss
^ permalink raw reply
* Re: [PATCH 1/2] printk: Unconditionally unregister boot consoles if in init section
From: Sergey Senozhatsky @ 2017-07-14 21:54 UTC (permalink / raw)
To: Petr Mladek
Cc: Matt Redfearn, Sergey Senozhatsky, Sergey Senozhatsky,
Greg Kroah-Hartman, Jiri Slaby, linux-serial, Steven Rostedt,
linux-kernel
In-Reply-To: <20170711124308.GA3393@pathway.suse.cz>
Hello,
sorry, I'm on a sick leave and can't check emails that often.
On (07/11/17 14:43), Petr Mladek wrote:
[..]
> > >>The keep_bootcon flag prevents the unregistration of a boot console,
> > >>even if it's data and code reside in the init section and are about to
> > >>be freed. This can lead to crashes and weird panics when the bootconsole
> > >>is accessed after free, especially if page poisoning is in use and the
> > >>code / data have been overwritten with a poison value.
> > >>To prevent this, always free the boot console if it is within the init
> > >>section.
>
> > >if someone asked to `keep_bootcon' but we actually don't keep it, then
> > >what's the purpose of the flag and
> > > pr_info("debug: skip boot console de-registration.\n")?
>
> Exactly. The important information is in the commit 7bf693951a8e5f7e
> ("console: allow to retain boot console via boot option keep_bootcon"):
>
> On some architectures, the boot process involves de-registering the boot
> console (early boot), initialize drivers and then re-register the console.
>
> This mechanism introduces a window in which no printk can happen on the
> console and messages are buffered and then printed once the new console is
> available.
>
> If a kernel crashes during this window, all it's left on the boot console
> is "console [foo] enabled, boot console disabled" making debug of the crash
> rather 'interesting'.
sure. no objections here.
I probably mis-worded my thoughts. I agree with Matt's conclusions and
he made valid points I just disagree with the fix.
> > >keeping `early_printk' sometimes can be helpful and people even want to
> > >use `early_printk' as a panic() console fallback (because of those nasty
> > >deadlocks that spoil printk->call_console_drivers()).
> > >
> >
> > Sure, but as a user, how are you supposed to know that?
>
> Good point! I wonder if the authors of the keep_bootcon option
> actually knew about it. I do not see this risk mentioned anywhere
> and the early consoles might work long enough by chance.
>
> One problem is that real consoles might be registered much later
> when it is done using an async probe calls. It might open a big window
> when there is no visible output and debugging is "impossible".
yes. besides, Peter wants to have early consoles as panic fallback.
> I am not comfortable with removing the only way to debug some type
> of bugs. But the current state is broken as well.
yes and yes.
> IMHO, the reasonable solution is to move early console code and data
> out of the init sections. We should do this for the early consoles
> where the corresponding real console is registered using a deferred
> probe. Others should be already replaced by the real console when
> printk_late_init() is called. At least this is how I understand it.
so I was thinking about two options:
a) do not keep consoles in init section
b) have a special init section for consoles code and avoid offloading
the corresponding pages when we see that keep flag
"b" seems like a crazy idea at glance, but it kinda makes some sense at
the same time. dunno.
-ss
^ permalink raw reply
* Re: [PATCH 0/2] Avoid crashes by early (boot) consoles using init memory
From: Petr Mladek @ 2017-07-14 14:37 UTC (permalink / raw)
To: Fabio M. Di Nitto
Cc: Sergey Senozhatsky, Steven Rostedt, Andrew Morton, Peter Zijlstra,
Matt Redfearn, Greg Kroah-Hartman, Jiri Slaby, David S. Miller,
Alan Cox, linux-serial, linux-kernel, Sergey Senozhatsky
In-Reply-To: <956ce40c-1640-387a-0ec9-9045c7d8af4b@redhat.com>
On Fri 2017-07-14 14:57:45, Fabio M. Di Nitto wrote:
> Hi Petr,
>
> On 7/14/2017 2:51 PM, Petr Mladek wrote:
> > Some early consoles have code and data in the init section. It makes some
> > sense but this might cause problems when they are not replaced by
> > the real console in time. The two patches fix the safequard and
> > help to avoid the problems.
> >
> > I though about removing keep_bootcon option completely. But it is useful
> > at least for now.
>
> Let´s just keep in mind that keep_bootcon was introduced only to debug
> issues (read crashes or hangs) that could happen between disabling
> bootconsole and enabling the real console. It shouldn´t be used for
> anything else really.
This was my initial replay as well. But then I realized that
it was a bad idea to use a freed code and data to debug any other
issue. It would just create crazy issues on its own.
I tried to google 'keep_bootcon'. It found several links to strange
crashes related to this option. Maybe I was not patient enough but
I did not find any page where this option was suggested and helped.
I still think that the option makes some sense but only when
it does not cause more breakages on its own.
> If the new code can replace keep_bootcon, by all mean, go for it :-)
keep_bootcon stays usable for most early consoles. We print a warning
when an unusable console is disabled too early. Also there is a
comment how to fix it.
Best Regards,
Petr
^ permalink raw reply
* Re: [PATCH 1/2] printk: Unconditionally unregister boot consoles if in init section
From: Matt Redfearn @ 2017-07-14 13:58 UTC (permalink / raw)
To: Petr Mladek
Cc: Sergey Senozhatsky, Sergey Senozhatsky, Greg Kroah-Hartman,
Jiri Slaby, linux-serial, Steven Rostedt, linux-kernel
In-Reply-To: <20170714124026.GA32632@pathway.suse.cz>
On 14/07/17 13:40, Petr Mladek wrote:
> On Wed 2017-07-12 13:11:17, Petr Mladek wrote:
>> On Tue 2017-07-11 15:41:50, Matt Redfearn wrote:
>>> On 11/07/17 13:43, Petr Mladek wrote:
>>>> IMHO, the reasonable solution is to move early console code and data
>>>> out of the init sections. We should do this for the early consoles
>>>> where the corresponding real console is registered using a deferred
>>>> probe. Others should be already replaced by the real console when
>>>> printk_late_init() is called. At least this is how I understand it.
>>> This seems like the most reasonable way forward to me as well,
>>> though sadly will lead to some post-init kernel bloat.
>>>
>>> I still think, however, that this patch is a reasonable change to
>>> make.
>> The thing is that this patch "silently" makes the keep_bootcon
>> option almost unusable.
> I was wrong here. I thought that most early consoles used the init
> section. It was mentioned somewhere and I looked a wrong way.
> But this is not true. In fact, it seems that there are
> only few of them. Most early consoles have struct console
> and the write() callback in the normal section that is preserved.
>
> Matt's patch and the keep_bootcon option makes sense to me
> after all. Let me to resend Matt's patch with some small
> improvements and one more patch that improves the check
> of early consoles that use init section. I'll keep Matt
> as the author of the first patch.
Thanks for looking into this and your fix Petr!
Matt
>
> Best Regards,
> Petr
>
^ permalink raw reply
* Re: [PATCH 0/2] Avoid crashes by early (boot) consoles using init memory
From: Fabio M. Di Nitto @ 2017-07-14 12:57 UTC (permalink / raw)
To: Petr Mladek, Sergey Senozhatsky, Steven Rostedt
Cc: Andrew Morton, Peter Zijlstra, Matt Redfearn, Greg Kroah-Hartman,
Jiri Slaby, David S. Miller, Alan Cox, linux-serial, linux-kernel,
Sergey Senozhatsky
In-Reply-To: <1500036673-7122-1-git-send-email-pmladek@suse.com>
Hi Petr,
On 7/14/2017 2:51 PM, Petr Mladek wrote:
> Some early consoles have code and data in the init section. It makes some
> sense but this might cause problems when they are not replaced by
> the real console in time. The two patches fix the safequard and
> help to avoid the problems.
>
> I though about removing keep_bootcon option completely. But it is useful
> at least for now.
Let´s just keep in mind that keep_bootcon was introduced only to debug
issues (read crashes or hangs) that could happen between disabling
bootconsole and enabling the real console. It shouldn´t be used for
anything else really.
If the new code can replace keep_bootcon, by all mean, go for it :-)
Cheers
Fabio
> There is not an easy way to disable a particular bootconsole
> when the related real console is installed. Instead all bootconsoles are
> removed when the preferred (last on the commandline) console is registered.
> But this is a bit cumbersome and non-intuitive.
>
> In addition, the same problems might happen when the real console is
> registered using a deferred probe or when it is not registered at all
> for some reason.
>
> The patchset is based on and inspired by the original patch from
> Matt Redfearn, see the discussion starting by the mail
> https://lkml.kernel.org/r/1499337481-19397-1-git-send-email-matt.redfearn@imgtec.com
>
> Matt Redfearn (1):
> printk/console: Always disable boot consoles that use init memory
> before it is freed
>
> Petr Mladek (1):
> printk/console: Enhance the check for consoles using init memory
>
> kernel/printk/printk.c | 28 +++++++++++++++++-----------
> 1 file changed, 17 insertions(+), 11 deletions(-)
>
^ permalink raw reply
* [PATCH 2/2] printk/console: Enhance the check for consoles using init memory
From: Petr Mladek @ 2017-07-14 12:51 UTC (permalink / raw)
To: Sergey Senozhatsky, Steven Rostedt
Cc: Andrew Morton, Peter Zijlstra, Matt Redfearn, Greg Kroah-Hartman,
Jiri Slaby, David S. Miller, Alan Cox, Fabio M. Di Nitto,
linux-serial, linux-kernel, Sergey Senozhatsky, Petr Mladek
In-Reply-To: <1500036673-7122-1-git-send-email-pmladek@suse.com>
printk_late_init() is responsible for disabling boot consoles that
use init memory. It checks the address of struct console for this.
But this is not enough. For example, there are several early
consoles that have write() method in the init section and
struct console in the normal section. They are not disabled
and could cause fancy and hard to debug system states.
It is even more complicated by the macros EARLYCON_DECLARE() and
OF_EARLYCON_DECLARE() where various struct members are set at
runtime by the provided setup() function.
I have tried to reproduce this problem and forced the classic uart
early console to stay using keep_bootcon parameter. In particular
I used earlycon=uart,io,0x3f8 keep_bootcon console=ttyS0,115200.
The system did not boot:
[ 1.570496] PM: Image not found (code -22)
[ 1.570496] PM: Image not found (code -22)
[ 1.571886] PM: Hibernation image not present or could not be loaded.
[ 1.571886] PM: Hibernation image not present or could not be loaded.
[ 1.576407] Freeing unused kernel memory: 2528K
[ 1.577244] kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
The double lines are caused by having both early uart console and
ttyS0 console enabled at the same time. The early console stopped
working when the init memory was freed. Fortunately, the invalid
call was caught by the NX-protexted page check and did not cause
any silent fancy problems.
This patch adds a check for many other addresses stored in
struct console. It omits setup() and match() that are used
only when the console is registered. Therefore they have
already been used at this point and there is no reason
to use them again.
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
kernel/printk/printk.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index f35d3ac3b8c7..1ebe1525ef64 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2659,8 +2659,16 @@ static int __init printk_late_init(void)
int ret;
for_each_console(con) {
- if ((con->flags & CON_BOOT) &&
- init_section_intersects(con, sizeof(*con))) {
+ if (!(con->flags & CON_BOOT))
+ continue;
+
+ /* Check addresses that might be used for enabled consoles. */
+ if (init_section_intersects(con, sizeof(*con)) ||
+ init_section_contains(con->write, 0) ||
+ init_section_contains(con->read, 0) ||
+ init_section_contains(con->device, 0) ||
+ init_section_contains(con->unblank, 0) ||
+ init_section_contains(con->data, 0)) {
/*
* Please, consider moving the reported consoles out
* of the init section.
--
1.8.5.6
^ permalink raw reply related
* [PATCH 1/2] printk/console: Always disable boot consoles that use init memory before it is freed
From: Petr Mladek @ 2017-07-14 12:51 UTC (permalink / raw)
To: Sergey Senozhatsky, Steven Rostedt
Cc: Andrew Morton, Peter Zijlstra, Matt Redfearn, Greg Kroah-Hartman,
Jiri Slaby, David S. Miller, Alan Cox, Fabio M. Di Nitto,
linux-serial, linux-kernel, Sergey Senozhatsky, Petr Mladek
In-Reply-To: <1500036673-7122-1-git-send-email-pmladek@suse.com>
From: Matt Redfearn <matt.redfearn@imgtec.com>
Commit 4c30c6f566c0 ("kernel/printk: do not turn off bootconsole in
printk_late_init() if keep_bootcon") added a check on keep_bootcon to
ensure that boot consoles were kept around until the real console is
registered.
This can lead to problems if the boot console data and code are in the
init section, since it can be freed before the boot console is
unregistered.
Commit 81cc26f2bd11 ("printk: only unregister boot consoles when
necessary") fixed this a better way. It allowed to keep boot consoles
that did not use init data. Unfortunately it did not remove the check
of keep_bootcon.
This can lead to crashes and weird panics when the bootconsole is
accessed after free, especially if page poisoning is in use and the
code / data have been overwritten with a poison value.
To prevent this, always free the boot console if it is within the init
section. In addition, print a warning about that the console is removed
prematurely.
Finally there is a new comment how to avoid the warning. It replaced
an explanation that duplicated a more comprehensive function
description few lines above.
Fixes: 4c30c6f566c0 ("kernel/printk: do not turn off bootconsole in printk_late_init() if keep_bootcon")
Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com>
[pmladek@suse.com: print the warning, code and comments clean up]
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
kernel/printk/printk.c | 20 +++++++++-----------
1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index fc47863f629c..f35d3ac3b8c7 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2650,9 +2650,8 @@ void __init console_init(void)
* makes it difficult to diagnose problems that occur during this time.
*
* To mitigate this problem somewhat, only unregister consoles whose memory
- * intersects with the init section. Note that code exists elsewhere to get
- * rid of the boot console as soon as the proper console shows up, so there
- * won't be side-effects from postponing the removal.
+ * intersects with the init section. Note that all other boot consoles will
+ * get unregistred when the real preferred console is registered.
*/
static int __init printk_late_init(void)
{
@@ -2660,16 +2659,15 @@ static int __init printk_late_init(void)
int ret;
for_each_console(con) {
- if (!keep_bootcon && con->flags & CON_BOOT) {
+ if ((con->flags & CON_BOOT) &&
+ init_section_intersects(con, sizeof(*con))) {
/*
- * Make sure to unregister boot consoles whose data
- * resides in the init section before the init section
- * is discarded. Boot consoles whose data will stick
- * around will automatically be unregistered when the
- * proper console replaces them.
+ * Please, consider moving the reported consoles out
+ * of the init section.
*/
- if (init_section_intersects(con, sizeof(*con)))
- unregister_console(con);
+ pr_warn("bootconsole [%s%d] uses init memory and must be disabled even before the real one is ready\n",
+ con->name, con->index);
+ unregister_console(con);
}
}
ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL,
--
1.8.5.6
^ permalink raw reply related
* [PATCH 0/2] Avoid crashes by early (boot) consoles using init memory
From: Petr Mladek @ 2017-07-14 12:51 UTC (permalink / raw)
To: Sergey Senozhatsky, Steven Rostedt
Cc: Andrew Morton, Peter Zijlstra, Matt Redfearn, Greg Kroah-Hartman,
Jiri Slaby, David S. Miller, Alan Cox, Fabio M. Di Nitto,
linux-serial, linux-kernel, Sergey Senozhatsky, Petr Mladek
Some early consoles have code and data in the init section. It makes some
sense but this might cause problems when they are not replaced by
the real console in time. The two patches fix the safequard and
help to avoid the problems.
I though about removing keep_bootcon option completely. But it is useful
at least for now. There is not an easy way to disable a particular bootconsole
when the related real console is installed. Instead all bootconsoles are
removed when the preferred (last on the commandline) console is registered.
But this is a bit cumbersome and non-intuitive.
In addition, the same problems might happen when the real console is
registered using a deferred probe or when it is not registered at all
for some reason.
The patchset is based on and inspired by the original patch from
Matt Redfearn, see the discussion starting by the mail
https://lkml.kernel.org/r/1499337481-19397-1-git-send-email-matt.redfearn@imgtec.com
Matt Redfearn (1):
printk/console: Always disable boot consoles that use init memory
before it is freed
Petr Mladek (1):
printk/console: Enhance the check for consoles using init memory
kernel/printk/printk.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
--
1.8.5.6
^ permalink raw reply
* Re: [PATCH 1/2] printk: Unconditionally unregister boot consoles if in init section
From: Petr Mladek @ 2017-07-14 12:40 UTC (permalink / raw)
To: Matt Redfearn
Cc: Sergey Senozhatsky, Sergey Senozhatsky, Greg Kroah-Hartman,
Jiri Slaby, linux-serial, Steven Rostedt, linux-kernel
In-Reply-To: <20170712111117.GD3393@pathway.suse.cz>
On Wed 2017-07-12 13:11:17, Petr Mladek wrote:
> On Tue 2017-07-11 15:41:50, Matt Redfearn wrote:
> > On 11/07/17 13:43, Petr Mladek wrote:
> > >IMHO, the reasonable solution is to move early console code and data
> > >out of the init sections. We should do this for the early consoles
> > >where the corresponding real console is registered using a deferred
> > >probe. Others should be already replaced by the real console when
> > >printk_late_init() is called. At least this is how I understand it.
> >
> > This seems like the most reasonable way forward to me as well,
> > though sadly will lead to some post-init kernel bloat.
> >
> > I still think, however, that this patch is a reasonable change to
> > make.
>
> The thing is that this patch "silently" makes the keep_bootcon
> option almost unusable.
I was wrong here. I thought that most early consoles used the init
section. It was mentioned somewhere and I looked a wrong way.
But this is not true. In fact, it seems that there are
only few of them. Most early consoles have struct console
and the write() callback in the normal section that is preserved.
Matt's patch and the keep_bootcon option makes sense to me
after all. Let me to resend Matt's patch with some small
improvements and one more patch that improves the check
of early consoles that use init section. I'll keep Matt
as the author of the first patch.
Best Regards,
Petr
^ permalink raw reply
* [PATCH 8/9] serial: stm32: add wakeup mechanism
From: Bich HEMON @ 2017-07-13 15:08 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre TORGUE, Jiri Slaby, linux-serial@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Cc: Bich HEMON
In-Reply-To: <1499958494-19354-1-git-send-email-bich.hemon@st.com>
From: Fabrice Gasnier <fabrice.gasnier@st.com>
Add support for wake-up from low power modes. This extends stm32f7.
Introduce new compatible for stm32h7 to manage wake-up capability.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Bich Hemon <bich.hemon@st.com>
---
drivers/tty/serial/stm32-usart.c | 90 +++++++++++++++++++++++++++++++++++++++-
drivers/tty/serial/stm32-usart.h | 29 +++++++++++++
2 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 413ff49..684cbe3 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -26,6 +26,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_wakeirq.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/spinlock.h>
@@ -326,6 +327,10 @@ static irqreturn_t stm32_interrupt(int irq, void *ptr)
sr = readl_relaxed(port->membase + ofs->isr);
+ if ((sr & USART_SR_WUF) && (ofs->icr != UNDEF_REG))
+ writel_relaxed(USART_ICR_WUCF,
+ port->membase + ofs->icr);
+
if ((sr & USART_SR_RXNE) && !(stm32_port->rx_ch))
stm32_receive_chars(port, false);
@@ -442,6 +447,7 @@ static int stm32_startup(struct uart_port *port)
{
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ struct stm32_usart_config *cfg = &stm32_port->info->cfg;
const char *name = to_platform_device(port->dev)->name;
u32 val;
int ret;
@@ -452,6 +458,15 @@ static int stm32_startup(struct uart_port *port)
if (ret)
return ret;
+ if (cfg->has_wakeup && stm32_port->wakeirq >= 0) {
+ ret = dev_pm_set_dedicated_wake_irq(port->dev,
+ stm32_port->wakeirq);
+ if (ret) {
+ free_irq(port->irq, port);
+ return ret;
+ }
+ }
+
val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
stm32_set_bits(port, ofs->cr1, val);
@@ -469,6 +484,7 @@ static void stm32_shutdown(struct uart_port *port)
val |= BIT(cfg->uart_enable_bit);
stm32_clr_bits(port, ofs->cr1, val);
+ dev_pm_clear_wake_irq(port->dev);
free_irq(port->irq, port);
}
@@ -659,6 +675,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
port->ops = &stm32_uart_ops;
port->dev = &pdev->dev;
port->irq = platform_get_irq(pdev, 0);
+ stm32port->wakeirq = platform_get_irq(pdev, 1);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
@@ -716,6 +733,8 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev)
{ .compatible = "st,stm32-uart", .data = &stm32f4_info},
{ .compatible = "st,stm32f7-usart", .data = &stm32f7_info},
{ .compatible = "st,stm32f7-uart", .data = &stm32f7_info},
+ { .compatible = "st,stm32h7-usart", .data = &stm32h7_info},
+ { .compatible = "st,stm32h7-uart", .data = &stm32h7_info},
{},
};
@@ -865,9 +884,15 @@ static int stm32_serial_probe(struct platform_device *pdev)
if (ret)
return ret;
+ if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0) {
+ ret = device_init_wakeup(&pdev->dev, true);
+ if (ret)
+ goto err_uninit;
+ }
+
ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
if (ret)
- goto err_uninit;
+ goto err_nowup;
ret = stm32_of_dma_rx_probe(stm32port, pdev);
if (ret)
@@ -881,6 +906,10 @@ static int stm32_serial_probe(struct platform_device *pdev)
return 0;
+err_nowup:
+ if (stm32port->info->cfg.has_wakeup && stm32port->wakeirq >= 0)
+ device_init_wakeup(&pdev->dev, false);
+
err_uninit:
clk_disable_unprepare(stm32port->clk);
@@ -892,6 +921,7 @@ static int stm32_serial_remove(struct platform_device *pdev)
struct uart_port *port = platform_get_drvdata(pdev);
struct stm32_port *stm32_port = to_stm32_port(port);
struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ struct stm32_usart_config *cfg = &stm32_port->info->cfg;
stm32_clr_bits(port, ofs->cr3, USART_CR3_DMAR);
@@ -913,6 +943,9 @@ static int stm32_serial_remove(struct platform_device *pdev)
TX_BUF_L, stm32_port->tx_buf,
stm32_port->tx_dma_buf);
+ if (cfg->has_wakeup && stm32_port->wakeirq >= 0)
+ device_init_wakeup(&pdev->dev, false);
+
clk_disable_unprepare(stm32_port->clk);
return uart_remove_one_port(&stm32_usart_driver, port);
@@ -1018,11 +1051,66 @@ static int stm32_console_setup(struct console *co, char *options)
.cons = STM32_SERIAL_CONSOLE,
};
+#ifdef CONFIG_PM_SLEEP
+static void stm32_serial_enable_wakeup(struct uart_port *port, bool enable)
+{
+ struct stm32_port *stm32_port = to_stm32_port(port);
+ struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ struct stm32_usart_config *cfg = &stm32_port->info->cfg;
+ u32 val;
+
+ if (!cfg->has_wakeup || stm32_port->wakeirq < 0)
+ return;
+
+ if (enable) {
+ stm32_clr_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+ stm32_set_bits(port, ofs->cr1, USART_CR1_UESM);
+ val = readl_relaxed(port->membase + ofs->cr3);
+ val &= ~USART_CR3_WUS_MASK;
+ /* Enable Wake up interrupt from low power on start bit */
+ val |= USART_CR3_WUS_START_BIT | USART_CR3_WUFIE;
+ writel_relaxed(val, port->membase + ofs->cr3);
+ stm32_set_bits(port, ofs->cr1, BIT(cfg->uart_enable_bit));
+ } else {
+ stm32_clr_bits(port, ofs->cr1, USART_CR1_UESM);
+ }
+}
+
+static int stm32_serial_suspend(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+
+ uart_suspend_port(&stm32_usart_driver, port);
+
+ if (device_may_wakeup(dev))
+ stm32_serial_enable_wakeup(port, true);
+ else
+ stm32_serial_enable_wakeup(port, false);
+
+ return 0;
+}
+
+static int stm32_serial_resume(struct device *dev)
+{
+ struct uart_port *port = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ stm32_serial_enable_wakeup(port, false);
+
+ return uart_resume_port(&stm32_usart_driver, port);
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops stm32_serial_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(stm32_serial_suspend, stm32_serial_resume)
+};
+
static struct platform_driver stm32_serial_driver = {
.probe = stm32_serial_probe,
.remove = stm32_serial_remove,
.driver = {
.name = DRIVER_NAME,
+ .pm = &stm32_serial_pm_ops,
.of_match_table = of_match_ptr(stm32_match),
},
};
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index 6092789..5984a66 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -25,6 +25,7 @@ struct stm32_usart_offsets {
struct stm32_usart_config {
u8 uart_enable_bit; /* USART_CR1_UE */
bool has_7bits_data;
+ bool has_wakeup;
};
struct stm32_usart_info {
@@ -75,6 +76,27 @@ struct stm32_usart_info stm32f7_info = {
}
};
+struct stm32_usart_info stm32h7_info = {
+ .ofs = {
+ .cr1 = 0x00,
+ .cr2 = 0x04,
+ .cr3 = 0x08,
+ .brr = 0x0c,
+ .gtpr = 0x10,
+ .rtor = 0x14,
+ .rqr = 0x18,
+ .isr = 0x1c,
+ .icr = 0x20,
+ .rdr = 0x24,
+ .tdr = 0x28,
+ },
+ .cfg = {
+ .uart_enable_bit = 0,
+ .has_7bits_data = true,
+ .has_wakeup = true,
+ }
+};
+
/* USART_SR (F4) / USART_ISR (F7) */
#define USART_SR_PE BIT(0)
#define USART_SR_FE BIT(1)
@@ -94,6 +116,7 @@ struct stm32_usart_info stm32f7_info = {
#define USART_SR_BUSY BIT(16) /* F7 */
#define USART_SR_CMF BIT(17) /* F7 */
#define USART_SR_SBKF BIT(18) /* F7 */
+#define USART_SR_WUF BIT(20) /* H7 */
#define USART_SR_TEACK BIT(21) /* F7 */
#define USART_SR_ERR_MASK (USART_SR_LBD | USART_SR_ORE | \
USART_SR_FE | USART_SR_PE)
@@ -114,6 +137,7 @@ struct stm32_usart_info stm32f7_info = {
/* USART_CR1 */
#define USART_CR1_SBK BIT(0)
#define USART_CR1_RWU BIT(1) /* F4 */
+#define USART_CR1_UESM BIT(1) /* H7 */
#define USART_CR1_RE BIT(2)
#define USART_CR1_TE BIT(3)
#define USART_CR1_IDLEIE BIT(4)
@@ -176,6 +200,9 @@ struct stm32_usart_info stm32f7_info = {
#define USART_CR3_DEM BIT(14) /* F7 */
#define USART_CR3_DEP BIT(15) /* F7 */
#define USART_CR3_SCARCNT_MASK GENMASK(19, 17) /* F7 */
+#define USART_CR3_WUS_MASK GENMASK(21, 20) /* H7 */
+#define USART_CR3_WUS_START_BIT BIT(21) /* H7 */
+#define USART_CR3_WUFIE BIT(22) /* H7 */
/* USART_GTPR */
#define USART_GTPR_PSC_MASK GENMASK(7, 0)
@@ -204,6 +231,7 @@ struct stm32_usart_info stm32f7_info = {
#define USART_ICR_RTOCF BIT(11) /* F7 */
#define USART_ICR_EOBCF BIT(12) /* F7 */
#define USART_ICR_CMCF BIT(17) /* F7 */
+#define USART_ICR_WUCF BIT(20) /* H7 */
#define STM32_SERIAL_NAME "ttyS"
#define STM32_MAX_PORTS 8
@@ -225,6 +253,7 @@ struct stm32_port {
int last_res;
bool tx_dma_busy; /* dma tx busy */
bool hw_flow_control;
+ int wakeirq;
};
static struct stm32_port stm32_ports[STM32_MAX_PORTS];
--
1.9.1
^ permalink raw reply related
* [PATCH 9/9] serial: stm32: add fifo support
From: Bich HEMON @ 2017-07-13 15:08 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre TORGUE, Jiri Slaby,
linux-serial-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Bich HEMON
In-Reply-To: <1499958494-19354-1-git-send-email-bich.hemon-qxv4g6HH51o@public.gmane.org>
From: Gerald Baeza <gerald.baeza-qxv4g6HH51o@public.gmane.org>
This patch adds fifo mode support for rx and tx.
A fifo configuration is set in each port structure.
Add has_fifo flag to usart configuration to use fifo only when possible.
Signed-off-by: Gerald Baeza <gerald.baeza-qxv4g6HH51o@public.gmane.org>
Signed-off-by: Bich Hemon <bich.hemon-qxv4g6HH51o@public.gmane.org>
---
drivers/tty/serial/stm32-usart.c | 7 +++++++
drivers/tty/serial/stm32-usart.h | 4 ++++
2 files changed, 11 insertions(+)
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 684cbe3..b16e7e7 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -468,6 +468,8 @@ static int stm32_startup(struct uart_port *port)
}
val = USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
+ if (stm32_port->fifoen)
+ val |= USART_CR1_FIFOEN;
stm32_set_bits(port, ofs->cr1, val);
return 0;
@@ -482,6 +484,8 @@ static void stm32_shutdown(struct uart_port *port)
val = USART_CR1_TXEIE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE;
val |= BIT(cfg->uart_enable_bit);
+ if (stm32_port->fifoen)
+ val |= USART_CR1_FIFOEN;
stm32_clr_bits(port, ofs->cr1, val);
dev_pm_clear_wake_irq(port->dev);
@@ -512,6 +516,8 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios,
cr1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
cr1 |= BIT(cfg->uart_enable_bit);
+ if (stm32_port->fifoen)
+ cr1 |= USART_CR1_FIFOEN;
cr2 = 0;
cr3 = 0;
@@ -676,6 +682,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
port->dev = &pdev->dev;
port->irq = platform_get_irq(pdev, 0);
stm32port->wakeirq = platform_get_irq(pdev, 1);
+ stm32port->fifoen = stm32port->info->cfg.has_fifo;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
port->membase = devm_ioremap_resource(&pdev->dev, res);
diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h
index 5984a66..ffc0c52 100644
--- a/drivers/tty/serial/stm32-usart.h
+++ b/drivers/tty/serial/stm32-usart.h
@@ -26,6 +26,7 @@ struct stm32_usart_config {
u8 uart_enable_bit; /* USART_CR1_UE */
bool has_7bits_data;
bool has_wakeup;
+ bool has_fifo;
};
struct stm32_usart_info {
@@ -94,6 +95,7 @@ struct stm32_usart_info stm32h7_info = {
.uart_enable_bit = 0,
.has_7bits_data = true,
.has_wakeup = true,
+ .has_fifo = true,
}
};
@@ -159,6 +161,7 @@ struct stm32_usart_info stm32h7_info = {
#define USART_CR1_EOBIE BIT(27) /* F7 */
#define USART_CR1_M1 BIT(28) /* F7 */
#define USART_CR1_IE_MASK (GENMASK(8, 4) | BIT(14) | BIT(26) | BIT(27))
+#define USART_CR1_FIFOEN BIT(29) /* H7 */
/* USART_CR2 */
#define USART_CR2_ADD_MASK GENMASK(3, 0) /* F4 */
@@ -253,6 +256,7 @@ struct stm32_port {
int last_res;
bool tx_dma_busy; /* dma tx busy */
bool hw_flow_control;
+ bool fifoen;
int wakeirq;
};
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 7/9] dt-bindings: serial: add compatible for stm32h7
From: Bich HEMON @ 2017-07-13 15:08 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre TORGUE, Jiri Slaby, linux-serial@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Cc: Bich HEMON
In-Reply-To: <1499958494-19354-1-git-send-email-bich.hemon@st.com>
From: Fabrice Gasnier <fabrice.gasnier@st.com>
Introduce new compatibles for "st,stm32h7-usart" and "st,stm32h7-uart".
This new compatible allow to use optional wake-up interrupt.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Bich Hemon <bich.hemon@st.com>
---
.../devicetree/bindings/serial/st,stm32-usart.txt | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
index 85ec5f2..3657f9f 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
+++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
@@ -1,12 +1,19 @@
* STMicroelectronics STM32 USART
Required properties:
-- compatible: Can be either "st,stm32-usart", "st,stm32-uart",
-"st,stm32f7-usart" or "st,stm32f7-uart" depending on whether
-the device supports synchronous mode and is compatible with
-stm32(f4) or stm32f7.
+- compatible: can be either:
+ - "st,stm32-usart",
+ - "st,stm32-uart",
+ - "st,stm32f7-usart",
+ - "st,stm32f7-uart",
+ - "st,stm32h7-usart"
+ - "st,stm32h7-uart".
+ depending on whether the device supports synchronous mode
+ and is compatible with stm32(f4), stm32f7 or stm32h7.
- reg: The address and length of the peripheral registers space
-- interrupts: The interrupt line of the USART instance
+- interrupts:
+ - The interrupt line for the USART instance,
+ - An optional wake-up interrupt.
- clocks: The input clock of the USART instance
Optional properties:
--
1.9.1
^ permalink raw reply related
* [PATCH 6/9] serial: stm32: fix error handling in probe
From: Bich HEMON @ 2017-07-13 15:08 UTC (permalink / raw)
To: Greg Kroah-Hartman, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre TORGUE, Jiri Slaby, linux-serial@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Cc: Bich HEMON
In-Reply-To: <1499958494-19354-1-git-send-email-bich.hemon@st.com>
From: Fabrice Gasnier <fabrice.gasnier@st.com>
Disable clock properly in case of error.
Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: Bich Hemon <bich.hemon@st.com>
---
drivers/tty/serial/stm32-usart.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 9158d31..413ff49 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -678,8 +678,10 @@ static int stm32_init_port(struct stm32_port *stm32port,
return ret;
stm32port->port.uartclk = clk_get_rate(stm32port->clk);
- if (!stm32port->port.uartclk)
+ if (!stm32port->port.uartclk) {
+ clk_disable_unprepare(stm32port->clk);
ret = -EINVAL;
+ }
return ret;
}
@@ -865,7 +867,7 @@ static int stm32_serial_probe(struct platform_device *pdev)
ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
if (ret)
- return ret;
+ goto err_uninit;
ret = stm32_of_dma_rx_probe(stm32port, pdev);
if (ret)
@@ -878,6 +880,11 @@ static int stm32_serial_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, &stm32port->port);
return 0;
+
+err_uninit:
+ clk_disable_unprepare(stm32port->clk);
+
+ return ret;
}
static int stm32_serial_remove(struct platform_device *pdev)
--
1.9.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox