[PATCH 3/3] serial: Check result of console_unregister()

Andrey Smirnov andrew.smirnov at gmail.com
Mon Mar 26 06:09:15 PDT 2018


In order to allow 'serdev' devices to prevent parent console device
removal and correspondign memory deallocation add code to all serial
driver to check result of console_unregister() and bail out early if
it is unsuccessful.

One example of a use-case for this would be a reset handler relying on
a serdev device for transport. Without this patch underlying console
device would be removed and de-allocated before reset handler is even
run thus leading to unpredictable behaviour and crashes.

Signed-off-by: Andrey Smirnov <andrew.smirnov at gmail.com>
---
 drivers/serial/serial_auart.c    | 6 +++++-
 drivers/serial/serial_cadence.c  | 6 +++++-
 drivers/serial/serial_clps711x.c | 6 +++++-
 drivers/serial/serial_imx.c      | 6 +++++-
 drivers/serial/serial_lpuart.c   | 6 +++++-
 drivers/serial/serial_pxa.c      | 6 +++++-
 drivers/serial/serial_s3c.c      | 6 +++++-
 drivers/serial/stm-serial.c      | 6 +++++-
 include/console.h                | 2 +-
 9 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/drivers/serial/serial_auart.c b/drivers/serial/serial_auart.c
index c3b9a1995..9bd0d991e 100644
--- a/drivers/serial/serial_auart.c
+++ b/drivers/serial/serial_auart.c
@@ -224,9 +224,13 @@ static int auart_serial_probe(struct device_d *dev)
 static void auart_serial_remove(struct device_d *dev)
 {
 	struct auart_priv *priv = dev->priv;
+	int ret;
 
 	auart_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
+	ret = console_unregister(&priv->cdev);
+	if (ret < 0)
+		return;
+
 	free(priv);
 }
 
diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
index 36dfa2084..f43d98172 100644
--- a/drivers/serial/serial_cadence.c
+++ b/drivers/serial/serial_cadence.c
@@ -270,8 +270,12 @@ err_free:
 static void cadence_serial_remove(struct device_d *dev)
 {
 	struct cadence_serial_priv *priv = dev->priv;
+	int ret;
+
+	ret = console_unregister(&priv->cdev);
+	if (ret < 0)
+		return;
 
-	console_unregister(&priv->cdev);
 	free(priv);
 }
 
diff --git a/drivers/serial/serial_clps711x.c b/drivers/serial/serial_clps711x.c
index ad14373ac..24ae3fdd3 100644
--- a/drivers/serial/serial_clps711x.c
+++ b/drivers/serial/serial_clps711x.c
@@ -184,9 +184,13 @@ out_err:
 static void clps711x_remove(struct device_d *dev)
 {
 	struct clps711x_uart *s = dev->priv;
+	int ret;
 
 	clps711x_flush(&s->cdev);
-	console_unregister(&s->cdev);
+	ret = console_unregister(&s->cdev);
+	if (ret < 0)
+		return;
+
 	free(s);
 }
 
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index e8c3836a6..fb865f554 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -274,9 +274,13 @@ err_free:
 static void imx_serial_remove(struct device_d *dev)
 {
 	struct imx_serial_priv *priv = dev->priv;
+	int ret;
 
 	imx_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
+	ret = console_unregister(&priv->cdev);
+	if (ret < 0)
+		return;
+
 	free(priv);
 }
 
diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c
index 52fb6d39c..42fab8a56 100644
--- a/drivers/serial/serial_lpuart.c
+++ b/drivers/serial/serial_lpuart.c
@@ -194,9 +194,13 @@ err_free:
 static void lpuart_serial_remove(struct device_d *dev)
 {
 	struct lpuart *lpuart = dev->priv;
+	int ret;
 
 	lpuart_serial_flush(&lpuart->cdev);
-	console_unregister(&lpuart->cdev);
+	ret = console_unregister(&lpuart->cdev);
+	if (ret < 0)
+		return;
+
 	release_region(lpuart->io);
 	clk_put(lpuart->clk);
 
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index 1a4d7b430..146f19cf3 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -188,8 +188,12 @@ static int pxa_serial_probe(struct device_d *dev)
 static void pxa_serial_remove(struct device_d *dev)
 {
 	struct pxa_serial_priv *priv = dev->priv;
+	int ret;
+
+	ret = console_unregister(&priv->cdev);
+	if (ret < 0)
+		return;
 
-	console_unregister(&priv->cdev);
 	free(priv);
 }
 
diff --git a/drivers/serial/serial_s3c.c b/drivers/serial/serial_s3c.c
index 0a6e22d97..8c6443acd 100644
--- a/drivers/serial/serial_s3c.c
+++ b/drivers/serial/serial_s3c.c
@@ -205,9 +205,13 @@ static int s3c_serial_probe(struct device_d *dev)
 static void s3c_serial_remove(struct device_d *dev)
 {
 	struct s3c_uart *priv= dev->priv;
+	int ret;
 
 	s3c_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
+	ret = console_unregister(&priv->cdev);
+	if (ret < 0)
+		return;
+
 	free(priv);
 }
 
diff --git a/drivers/serial/stm-serial.c b/drivers/serial/stm-serial.c
index 83328f455..3edcdd7e8 100644
--- a/drivers/serial/stm-serial.c
+++ b/drivers/serial/stm-serial.c
@@ -185,9 +185,13 @@ static int stm_serial_probe(struct device_d *dev)
 static void stm_serial_remove(struct device_d *dev)
 {
 	struct stm_priv *priv = dev->priv;
+	int ret;
 
 	stm_serial_flush(&priv->cdev);
-	console_unregister(&priv->cdev);
+	ret = console_unregister(&priv->cdev);
+	if (ret < 0)
+		return;
+
 	free(priv);
 }
 
diff --git a/include/console.h b/include/console.h
index 14f00fa1e..3870e67a4 100644
--- a/include/console.h
+++ b/include/console.h
@@ -95,7 +95,7 @@ console_is_serdev_node(struct console_device *cdev)
 }
 
 int console_register(struct console_device *cdev);
-int console_unregister(struct console_device *cdev);
+int __must_check console_unregister(struct console_device *cdev);
 
 struct console_device *console_get_by_dev(struct device_d *dev);
 struct console_device *console_get_by_name(const char *name);
-- 
2.14.3




More information about the barebox mailing list