All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] ACPI serdev support
@ 2017-10-10 10:12 ` Frédéric Danis
  0 siblings, 0 replies; 7+ messages in thread
From: Frédéric Danis @ 2017-10-10 10:12 UTC (permalink / raw)
  To: robh-DgEjT+Ai2ygdnm+yROfE0A, marcel-kz+m5ild9QBg9hUCZPvPmw,
	sre-DgEjT+Ai2ygdnm+yROfE0A, loic.poulain-Re5JQEeQqe8AvxtiuMwx3w,
	johan-DgEjT+Ai2ygdnm+yROfE0A, lukas-JFq808J9C/izQB+pC5nmwQ,
	hdegoede-H+wXaHxf7aLQT0dZR+AlfA, rafael-DgEjT+Ai2ygdnm+yROfE0A,
	greg-U8xfFu+wG4EAvxtiuMwx3w
  Cc: linux-bluetooth-u79uwXL29TY76Z2rM5mHXA,
	linux-serial-u79uwXL29TY76Z2rM5mHXA,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	frederic.danis.oss-Re5JQEeQqe8AvxtiuMwx3w

Add ACPI support for serial attached devices.

Currently, serial devices are not set as enumerated during ACPI scan for SPI
or i2c buses (but not for UART). This should also be done for UART serial
devices.
I renamed *spi_i2c_slave* to *serial_bus_slave* to reflect this.

Tested on T100TA with Broadcom BCM2E39.

Since v1:
  - Check if a serdev device as been allocated during acpi_walk_namespace() to
    prevent serdev controller registration instead of the tty-class device.
  - Reword dev_dbg() strings replacing Serial by serdev
  - Removing redundant "serdev%d" in dev_dbg() calls in serdev_controller_add()
Since RFC:
  - Add or reword commit messages
  - Rename *serial_slave* to *serial_bus_slave*
  - Add specific check for Apple in acpi_is_serial_bus_slave(), thanks to
    Lukas Wunner
  - Update comment in acpi_default_enumeration()
  - Remove patch 3 "Bluetooth: hci_bcm: Add ACPI serdev support for BCM2E39"
    in favor of patches from Hans de Goede

Frédéric Danis (2):
  serdev: Add ACPI support
  ACPI / scan: Fix enumeration for special UART devices

 drivers/acpi/scan.c       |  37 ++++++++--------
 drivers/tty/serdev/core.c | 106 +++++++++++++++++++++++++++++++++++++++++++---
 include/acpi/acpi_bus.h   |   2 +-
 3 files changed, 117 insertions(+), 28 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 0/2] ACPI serdev support
@ 2017-10-10 10:12 ` Frédéric Danis
  0 siblings, 0 replies; 7+ messages in thread
From: Frédéric Danis @ 2017-10-10 10:12 UTC (permalink / raw)
  To: robh, marcel, sre, loic.poulain, johan, lukas, hdegoede, rafael, greg
  Cc: linux-bluetooth, linux-serial, linux-acpi, frederic.danis.oss

Add ACPI support for serial attached devices.

Currently, serial devices are not set as enumerated during ACPI scan for SPI
or i2c buses (but not for UART). This should also be done for UART serial
devices.
I renamed *spi_i2c_slave* to *serial_bus_slave* to reflect this.

Tested on T100TA with Broadcom BCM2E39.

Since v1:
  - Check if a serdev device as been allocated during acpi_walk_namespace() to
    prevent serdev controller registration instead of the tty-class device.
  - Reword dev_dbg() strings replacing Serial by serdev
  - Removing redundant "serdev%d" in dev_dbg() calls in serdev_controller_add()
Since RFC:
  - Add or reword commit messages
  - Rename *serial_slave* to *serial_bus_slave*
  - Add specific check for Apple in acpi_is_serial_bus_slave(), thanks to
    Lukas Wunner
  - Update comment in acpi_default_enumeration()
  - Remove patch 3 "Bluetooth: hci_bcm: Add ACPI serdev support for BCM2E39"
    in favor of patches from Hans de Goede

Frédéric Danis (2):
  serdev: Add ACPI support
  ACPI / scan: Fix enumeration for special UART devices

 drivers/acpi/scan.c       |  37 ++++++++--------
 drivers/tty/serdev/core.c | 106 +++++++++++++++++++++++++++++++++++++++++++---
 include/acpi/acpi_bus.h   |   2 +-
 3 files changed, 117 insertions(+), 28 deletions(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/2] serdev: Add ACPI support
  2017-10-10 10:12 ` Frédéric Danis
  (?)
@ 2017-10-10 10:12 ` Frédéric Danis
  2017-10-10 15:16     ` Ian W MORRISON
  2017-10-10 15:35   ` Johan Hovold
  -1 siblings, 2 replies; 7+ messages in thread
From: Frédéric Danis @ 2017-10-10 10:12 UTC (permalink / raw)
  To: robh, marcel, sre, loic.poulain, johan, lukas, hdegoede, rafael, greg
  Cc: linux-bluetooth, linux-serial, linux-acpi, frederic.danis.oss

This patch allows SerDev module to manage serial devices declared as
attached to an UART in ACPI table.

acpi_serdev_add_device() callback will only take into account entries
without enumerated flag set. This flags is set for all entries during
ACPI scan, except for SPI and I2C serial devices, and for UART with
2nd patch in the series.

Check if a serdev device as been allocated during acpi_walk_namespace()
to prevent serdev controller registration instead of the tty-class device.

Signed-off-by: Frédéric Danis <frederic.danis.oss@gmail.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/tty/serdev/core.c | 106 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 99 insertions(+), 7 deletions(-)

diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index c68fb3a..7e00e2e 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -14,6 +14,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/acpi.h>
 #include <linux/errno.h>
 #include <linux/idr.h>
 #include <linux/kernel.h>
@@ -49,13 +50,22 @@ static const struct device_type serdev_ctrl_type = {
 
 static int serdev_device_match(struct device *dev, struct device_driver *drv)
 {
-	/* TODO: ACPI and platform matching */
+	/* TODO: platform matching */
+	if (acpi_driver_match_device(dev, drv))
+		return 1;
+
 	return of_driver_match_device(dev, drv);
 }
 
 static int serdev_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-	/* TODO: ACPI and platform modalias */
+	int rc;
+
+	/* TODO: platform modalias */
+	rc = acpi_device_uevent_modalias(dev, env);
+	if (rc != -ENODEV)
+		return rc;
+
 	return of_device_uevent_modalias(dev, env);
 }
 
@@ -260,6 +270,12 @@ static int serdev_drv_remove(struct device *dev)
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
+	int len;
+
+	len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
+	if (len != -ENODEV)
+		return len;
+
 	return of_device_modalias(dev, buf, PAGE_SIZE);
 }
 DEVICE_ATTR_RO(modalias);
@@ -385,6 +401,78 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
+					    struct acpi_device *adev)
+{
+	struct serdev_device *serdev = NULL;
+	int err;
+
+	if (acpi_bus_get_status(adev) || !adev->status.present ||
+	    acpi_device_enumerated(adev))
+		return AE_OK;
+
+	serdev = serdev_device_alloc(ctrl);
+	if (!serdev) {
+		dev_err(&ctrl->dev, "failed to allocate serdev device for %s\n",
+			dev_name(&adev->dev));
+		return AE_NO_MEMORY;
+	}
+
+	ACPI_COMPANION_SET(&serdev->dev, adev);
+	acpi_device_set_enumerated(adev);
+
+	err = serdev_device_add(serdev);
+	if (err) {
+		dev_err(&serdev->dev,
+			"failure adding ACPI serdev device. status %d\n", err);
+		serdev_device_put(serdev);
+		ctrl->serdev = NULL;
+	}
+
+	return AE_OK;
+}
+
+static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
+				       void *data, void **return_value)
+{
+	struct serdev_controller *ctrl = data;
+	struct acpi_device *adev;
+
+	if (acpi_bus_get_device(handle, &adev))
+		return AE_OK;
+
+	return acpi_serdev_register_device(ctrl, adev);
+}
+
+static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
+{
+	acpi_status status;
+	acpi_handle handle;
+
+	handle = ACPI_HANDLE(ctrl->dev.parent);
+	if (!handle)
+		return -ENODEV;
+
+	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+				     acpi_serdev_add_device, NULL, ctrl, NULL);
+	if (ACPI_FAILURE(status)) {
+		dev_dbg(&ctrl->dev, "failed to enumerate serdev slaves\n");
+		return -ENODEV;
+	}
+
+	if (!ctrl->serdev)
+		return -ENODEV;
+
+	return 0;
+}
+#else
+static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_ACPI */
+
 /**
  * serdev_controller_add() - Add an serdev controller
  * @ctrl:	controller to be registered.
@@ -394,7 +482,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
  */
 int serdev_controller_add(struct serdev_controller *ctrl)
 {
-	int ret;
+	int ret_of, ret_acpi, ret;
 
 	/* Can't register until after driver model init */
 	if (WARN_ON(!is_registered))
@@ -404,12 +492,16 @@ int serdev_controller_add(struct serdev_controller *ctrl)
 	if (ret)
 		return ret;
 
-	ret = of_serdev_register_devices(ctrl);
-	if (ret)
+	ret_of = of_serdev_register_devices(ctrl);
+	ret_acpi = acpi_serdev_register_devices(ctrl);
+	if (ret_of && ret_acpi) {
+		dev_dbg(&ctrl->dev, "no devices registered: of:%d acpi:%d\n",
+			ret_of, ret_acpi);
+		ret = -ENODEV;
 		goto out_dev_del;
+	}
 
-	dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n",
-		ctrl->nr, &ctrl->dev);
+	dev_dbg(&ctrl->dev, "registered: dev:%p\n", &ctrl->dev);
 	return 0;
 
 out_dev_del:
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/2] ACPI / scan: Fix enumeration for special UART devices
  2017-10-10 10:12 ` Frédéric Danis
  (?)
  (?)
@ 2017-10-10 10:12 ` Frédéric Danis
  -1 siblings, 0 replies; 7+ messages in thread
From: Frédéric Danis @ 2017-10-10 10:12 UTC (permalink / raw)
  To: robh, marcel, sre, loic.poulain, johan, lukas, hdegoede, rafael, greg
  Cc: linux-bluetooth, linux-serial, linux-acpi, frederic.danis.oss

UART devices is expected to be enumerated by SerDev subsystem.

During ACPI scan, serial devices behind SPI, I2C or UART buses are not
enumerated, allowing them to be enumerated by their respective parents.

Rename *spi_i2c_slave* to *serial_bus_slave* as this will be used for serial
devices on serial buses (SPI, I2C or UART).

On Macs an empty ResourceTemplate is returned for uart slaves.
Instead the device properties "baud", "parity", "dataBits", "stopBits" are
provided. Add a check for "baud" in acpi_is_serial_bus_slave().

Signed-off-by: Frédéric Danis <frederic.danis.oss@gmail.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
---
 drivers/acpi/scan.c     | 37 +++++++++++++++++--------------------
 include/acpi/acpi_bus.h |  2 +-
 2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 602f8ff..860b698 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1505,41 +1505,38 @@ static void acpi_init_coherency(struct acpi_device *adev)
 	adev->flags.coherent_dma = cca;
 }
 
-static int acpi_check_spi_i2c_slave(struct acpi_resource *ares, void *data)
+static int acpi_check_serial_bus_slave(struct acpi_resource *ares, void *data)
 {
-	bool *is_spi_i2c_slave_p = data;
+	bool *is_serial_bus_slave_p = data;
 
 	if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
 		return 1;
 
-	/*
-	 * devices that are connected to UART still need to be enumerated to
-	 * platform bus
-	 */
-	if (ares->data.common_serial_bus.type != ACPI_RESOURCE_SERIAL_TYPE_UART)
-		*is_spi_i2c_slave_p = true;
+	*is_serial_bus_slave_p = true;
 
 	 /* no need to do more checking */
 	return -1;
 }
 
-static bool acpi_is_spi_i2c_slave(struct acpi_device *device)
+static bool acpi_is_serial_bus_slave(struct acpi_device *device)
 {
 	struct list_head resource_list;
-	bool is_spi_i2c_slave = false;
+	bool is_serial_bus_slave = false;
 
 	/* Macs use device properties in lieu of _CRS resources */
 	if (x86_apple_machine &&
 	    (fwnode_property_present(&device->fwnode, "spiSclkPeriod") ||
-	     fwnode_property_present(&device->fwnode, "i2cAddress")))
+	     fwnode_property_present(&device->fwnode, "i2cAddress") ||
+	     fwnode_property_present(&device->fwnode, "baud")))
 		return true;
 
 	INIT_LIST_HEAD(&resource_list);
-	acpi_dev_get_resources(device, &resource_list, acpi_check_spi_i2c_slave,
-			       &is_spi_i2c_slave);
+	acpi_dev_get_resources(device, &resource_list,
+			       acpi_check_serial_bus_slave,
+			       &is_serial_bus_slave);
 	acpi_dev_free_resource_list(&resource_list);
 
-	return is_spi_i2c_slave;
+	return is_serial_bus_slave;
 }
 
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
@@ -1557,7 +1554,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 	acpi_bus_get_flags(device);
 	device->flags.match_driver = false;
 	device->flags.initialized = true;
-	device->flags.spi_i2c_slave = acpi_is_spi_i2c_slave(device);
+	device->flags.serial_bus_slave = acpi_is_serial_bus_slave(device);
 	acpi_device_clear_enumerated(device);
 	device_initialize(&device->dev);
 	dev_set_uevent_suppress(&device->dev, true);
@@ -1841,10 +1838,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
 static void acpi_default_enumeration(struct acpi_device *device)
 {
 	/*
-	 * Do not enumerate SPI/I2C slaves as they will be enumerated by their
-	 * respective parents.
+	 * Do not enumerate SPI/I2C/UART slaves as they will be enumerated by
+	 * their respective parents.
 	 */
-	if (!device->flags.spi_i2c_slave) {
+	if (!device->flags.serial_bus_slave) {
 		acpi_create_platform_device(device, NULL);
 		acpi_device_set_enumerated(device);
 	} else {
@@ -1941,7 +1938,7 @@ static void acpi_bus_attach(struct acpi_device *device)
 		return;
 
 	device->flags.match_driver = true;
-	if (ret > 0 && !device->flags.spi_i2c_slave) {
+	if (ret > 0 && !device->flags.serial_bus_slave) {
 		acpi_device_set_enumerated(device);
 		goto ok;
 	}
@@ -1950,7 +1947,7 @@ static void acpi_bus_attach(struct acpi_device *device)
 	if (ret < 0)
 		return;
 
-	if (!device->pnp.type.platform_id && !device->flags.spi_i2c_slave)
+	if (!device->pnp.type.platform_id && !device->flags.serial_bus_slave)
 		acpi_device_set_enumerated(device);
 	else
 		acpi_default_enumeration(device);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index fa15052..f849be2 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -211,7 +211,7 @@ struct acpi_device_flags {
 	u32 of_compatible_ok:1;
 	u32 coherent_dma:1;
 	u32 cca_seen:1;
-	u32 spi_i2c_slave:1;
+	u32 serial_bus_slave:1;
 	u32 reserved:19;
 };
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] serdev: Add ACPI support
  2017-10-10 10:12 ` [PATCH v2 1/2] serdev: Add ACPI support Frédéric Danis
@ 2017-10-10 15:16     ` Ian W MORRISON
  2017-10-10 15:35   ` Johan Hovold
  1 sibling, 0 replies; 7+ messages in thread
From: Ian W MORRISON @ 2017-10-10 15:16 UTC (permalink / raw)
  To: Frédéric Danis
  Cc: Rob Herring, Marcel Holtmann, Sebastian Reichel, Loic Poulain,
	Johan Hovold, Lukas Wunner, Hans de Goede, Rafael J. Wysocki,
	Greg KH, bluez mailin list (linux-bluetooth@vger.kernel.org),
	linux-serial, linux-acpi

On 10 October 2017 at 21:12, Frédéric Danis
<frederic.danis.oss@gmail.com> wrote:
> This patch allows SerDev module to manage serial devices declared as
> attached to an UART in ACPI table.
>
> acpi_serdev_add_device() callback will only take into account entries
> without enumerated flag set. This flags is set for all entries during
> ACPI scan, except for SPI and I2C serial devices, and for UART with
> 2nd patch in the series.
>
> Check if a serdev device as been allocated during acpi_walk_namespace()
> to prevent serdev controller registration instead of the tty-class device.

<snip>

Hi Fred,

I tested the v2 patch and can confirm it works:

Before v1 patch:
$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    2.409003] 00:01: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200)
is a 16550A
[    5.380336] 8086228A:00: ttyS4 at MMIO 0x9151b000 (irq = 39,
base_baud = 2764800) is a 16550A
[    5.388412] 8086228A:01: ttyS5 at MMIO 0x91519000 (irq = 40,
base_baud = 2764800) is a 16550A
$

After v1 patch:
$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    2.416973] 00:01: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200)
is a 16550A
[    2.417317] serial serial0: tty port ttyS0 registered
[    5.928492] 8086228A:00: ttyS4 at MMIO 0x9151b000 (irq = 39,
base_baud = 2764800) is a 16550A
[    5.982195] serial serial1: tty port ttyS4 registered
[    6.004426] 8086228A:01: ttyS5 at MMIO 0x91519000 (irq = 40,
base_baud = 2764800) is a 16550A
[    6.019369] serial serial2: tty port ttyS5 registered
$

After v2 patch:
$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    2.420295] 00:01: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200)
is a 16550A
[    5.884777] 8086228A:00: ttyS4 at MMIO 0x9151b000 (irq = 39,
base_baud = 2764800) is a 16550A
[    5.917980] serial serial0: tty port ttyS4 registered
[    5.933160] 8086228A:01: ttyS5 at MMIO 0x91519000 (irq = 40,
base_baud = 2764800) is a 16550A
$

Regards,
Ian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] serdev: Add ACPI support
@ 2017-10-10 15:16     ` Ian W MORRISON
  0 siblings, 0 replies; 7+ messages in thread
From: Ian W MORRISON @ 2017-10-10 15:16 UTC (permalink / raw)
  To: Frédéric Danis
  Cc: Rob Herring, Marcel Holtmann, Sebastian Reichel, Loic Poulain,
	Johan Hovold, Lukas Wunner, Hans de Goede, Rafael J. Wysocki,
	Greg KH, bluez mailin list (linux-bluetooth@vger.kernel.org),
	linux-serial, linux-acpi

On 10 October 2017 at 21:12, Fr=C3=A9d=C3=A9ric Danis
<frederic.danis.oss@gmail.com> wrote:
> This patch allows SerDev module to manage serial devices declared as
> attached to an UART in ACPI table.
>
> acpi_serdev_add_device() callback will only take into account entries
> without enumerated flag set. This flags is set for all entries during
> ACPI scan, except for SPI and I2C serial devices, and for UART with
> 2nd patch in the series.
>
> Check if a serdev device as been allocated during acpi_walk_namespace()
> to prevent serdev controller registration instead of the tty-class device=
.

<snip>

Hi Fred,

I tested the v2 patch and can confirm it works:

Before v1 patch:
$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    2.409003] 00:01: ttyS0 at I/O 0x3f8 (irq =3D 4, base_baud =3D 115200)
is a 16550A
[    5.380336] 8086228A:00: ttyS4 at MMIO 0x9151b000 (irq =3D 39,
base_baud =3D 2764800) is a 16550A
[    5.388412] 8086228A:01: ttyS5 at MMIO 0x91519000 (irq =3D 40,
base_baud =3D 2764800) is a 16550A
$

After v1 patch:
$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    2.416973] 00:01: ttyS0 at I/O 0x3f8 (irq =3D 4, base_baud =3D 115200)
is a 16550A
[    2.417317] serial serial0: tty port ttyS0 registered
[    5.928492] 8086228A:00: ttyS4 at MMIO 0x9151b000 (irq =3D 39,
base_baud =3D 2764800) is a 16550A
[    5.982195] serial serial1: tty port ttyS4 registered
[    6.004426] 8086228A:01: ttyS5 at MMIO 0x91519000 (irq =3D 40,
base_baud =3D 2764800) is a 16550A
[    6.019369] serial serial2: tty port ttyS5 registered
$

After v2 patch:
$ dmesg | grep tty
[    0.000000] console [tty0] enabled
[    2.420295] 00:01: ttyS0 at I/O 0x3f8 (irq =3D 4, base_baud =3D 115200)
is a 16550A
[    5.884777] 8086228A:00: ttyS4 at MMIO 0x9151b000 (irq =3D 39,
base_baud =3D 2764800) is a 16550A
[    5.917980] serial serial0: tty port ttyS4 registered
[    5.933160] 8086228A:01: ttyS5 at MMIO 0x91519000 (irq =3D 40,
base_baud =3D 2764800) is a 16550A
$

Regards,
Ian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] serdev: Add ACPI support
  2017-10-10 10:12 ` [PATCH v2 1/2] serdev: Add ACPI support Frédéric Danis
  2017-10-10 15:16     ` Ian W MORRISON
@ 2017-10-10 15:35   ` Johan Hovold
  1 sibling, 0 replies; 7+ messages in thread
From: Johan Hovold @ 2017-10-10 15:35 UTC (permalink / raw)
  To: Frédéric Danis
  Cc: robh, marcel, sre, loic.poulain, johan, lukas, hdegoede, rafael,
	greg, linux-bluetooth, linux-serial, linux-acpi

On Tue, Oct 10, 2017 at 12:12:44PM +0200, Frédéric Danis wrote:
> This patch allows SerDev module to manage serial devices declared as
> attached to an UART in ACPI table.
> 
> acpi_serdev_add_device() callback will only take into account entries
> without enumerated flag set. This flags is set for all entries during
> ACPI scan, except for SPI and I2C serial devices, and for UART with
> 2nd patch in the series.
> 
> Check if a serdev device as been allocated during acpi_walk_namespace()
> to prevent serdev controller registration instead of the tty-class device.

Good that we caught that one before every ACPI serial port broke. ;)

> Signed-off-by: Frédéric Danis <frederic.danis.oss@gmail.com>
> Reviewed-by: Rob Herring <robh@kernel.org>
> Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
>  drivers/tty/serdev/core.c | 106 +++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 99 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c

> @@ -385,6 +401,78 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
>  	return 0;
>  }
>  
> +#ifdef CONFIG_ACPI
> +static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
> +					    struct acpi_device *adev)
> +{
> +	struct serdev_device *serdev = NULL;
> +	int err;
> +
> +	if (acpi_bus_get_status(adev) || !adev->status.present ||
> +	    acpi_device_enumerated(adev))
> +		return AE_OK;
> +
> +	serdev = serdev_device_alloc(ctrl);
> +	if (!serdev) {
> +		dev_err(&ctrl->dev, "failed to allocate serdev device for %s\n",
> +			dev_name(&adev->dev));
> +		return AE_NO_MEMORY;
> +	}
> +
> +	ACPI_COMPANION_SET(&serdev->dev, adev);
> +	acpi_device_set_enumerated(adev);

Looks like this flag needs to be cleared when the device is later
deregistered or you will not be able to reprobe the device (mostly
useful for development). Can probably done in a follow-up patch.

> +
> +	err = serdev_device_add(serdev);
> +	if (err) {
> +		dev_err(&serdev->dev,
> +			"failure adding ACPI serdev device. status %d\n", err);
> +		serdev_device_put(serdev);
> +		ctrl->serdev = NULL;

You should not clear this pointer here. This should be taken care of by
serdev core when registration fails, something which would also address
the problem with how to deal with multiple child nodes which is a
problem for ACPI as well as DT (as I mentioned briefly at Kernel
Recipes).

I'll submit a fix for that shortly, but the NULL assignment above needs
to go.

> +	}
> +
> +	return AE_OK;
> +}
> +
> +static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
> +				       void *data, void **return_value)
> +{
> +	struct serdev_controller *ctrl = data;
> +	struct acpi_device *adev;
> +
> +	if (acpi_bus_get_device(handle, &adev))
> +		return AE_OK;
> +
> +	return acpi_serdev_register_device(ctrl, adev);
> +}
> +
> +static int acpi_serdev_register_devices(struct serdev_controller *ctrl)
> +{
> +	acpi_status status;
> +	acpi_handle handle;
> +
> +	handle = ACPI_HANDLE(ctrl->dev.parent);
> +	if (!handle)
> +		return -ENODEV;
> +
> +	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
> +				     acpi_serdev_add_device, NULL, ctrl, NULL);
> +	if (ACPI_FAILURE(status)) {
> +		dev_dbg(&ctrl->dev, "failed to enumerate serdev slaves\n");

So what if there are more than one child node defined? You could end up
with an error here but with a slave still registered. And then when you
return -ENODEV, that memory will leak.

> +		return -ENODEV;

Simply falling through here, and then return 0 or -ENODEV based on
ctrl->serdev should suffice for now.

> +	}
> +
> +	if (!ctrl->serdev)
> +		return -ENODEV;
> +
> +	return 0;
> +}
> +#else
> +static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl)
> +{
> +	return -ENODEV;
> +}
> +#endif /* CONFIG_ACPI */
> +
>  /**
>   * serdev_controller_add() - Add an serdev controller
>   * @ctrl:	controller to be registered.
> @@ -394,7 +482,7 @@ static int of_serdev_register_devices(struct serdev_controller *ctrl)
>   */
>  int serdev_controller_add(struct serdev_controller *ctrl)
>  {
> -	int ret;
> +	int ret_of, ret_acpi, ret;
>  
>  	/* Can't register until after driver model init */
>  	if (WARN_ON(!is_registered))
> @@ -404,12 +492,16 @@ int serdev_controller_add(struct serdev_controller *ctrl)
>  	if (ret)
>  		return ret;
>  
> -	ret = of_serdev_register_devices(ctrl);
> -	if (ret)
> +	ret_of = of_serdev_register_devices(ctrl);
> +	ret_acpi = acpi_serdev_register_devices(ctrl);
> +	if (ret_of && ret_acpi) {
> +		dev_dbg(&ctrl->dev, "no devices registered: of:%d acpi:%d\n",
> +			ret_of, ret_acpi);
> +		ret = -ENODEV;
>  		goto out_dev_del;
> +	}
>  
> -	dev_dbg(&ctrl->dev, "serdev%d registered: dev:%p\n",
> -		ctrl->nr, &ctrl->dev);
> +	dev_dbg(&ctrl->dev, "registered: dev:%p\n", &ctrl->dev);

This change belongs in a separate patch. There seem to be a few more
instances like this one, which can all be fixed in a later patch
instead.

>  	return 0;
>  
>  out_dev_del:

Johan

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-10-10 15:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-10 10:12 [PATCH v2 0/2] ACPI serdev support Frédéric Danis
2017-10-10 10:12 ` Frédéric Danis
2017-10-10 10:12 ` [PATCH v2 1/2] serdev: Add ACPI support Frédéric Danis
2017-10-10 15:16   ` Ian W MORRISON
2017-10-10 15:16     ` Ian W MORRISON
2017-10-10 15:35   ` Johan Hovold
2017-10-10 10:12 ` [PATCH v2 2/2] ACPI / scan: Fix enumeration for special UART devices Frédéric Danis

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.