linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V9 0/9] vfio, platform: add ACPI support
@ 2016-07-14  2:06 Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 1/9] vfio: platform: rename reset function Sinan Kaya
                   ` (8 more replies)
  0 siblings, 9 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

The current code only supports the device tree based platforms.
The code checks for the presence of a reset driver and calls the reset
function pointer by looking up the reset driver as a module.

ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device.

The patchset is moving the device tree specific pieces out of the code
to common functions so that ACPI support is added without impacting the
rest
of the code.

During probe, the ACPI HID of the object will be saved and will be used to
determine if this is an ACPI capable platform or not. If acpihid is NULL
then, device tree functions are called.

In addition to plumbing ACPI support, reset functionality is now a
requirement by default.

The code was allowing platform devices to be used without a supporting
VFIO reset driver. The hardware can be left in some inconsistent state
after a guest machine abort.

The reset driver will put the hardware back to safe state and disable
interrupts before returning the control back to the host machine.

Adding a new reset_required kernel module option to platform
VFIO drivers with a default value of true.

New requirements are:
1. A reset function needs to be implemented by the corresponding driver
via DT/ACPI.
2. The reset function needs to be discovered via DT/ACPI.

The probe of the driver will fail if any of the above conditions are
not satisfied.

Changes from V8:
1. Return different error codes for the ACPI probe failures.
2. Document the CONFIG_ACPI and when/why error messages are printed along
with assumptions.
3. Reorder the reset call in vfio_platform_call_reset for consistency.
4. Introduce VFIO_PLATFORM_IS_ACPI to make the code more readable
5. Get rid of the ACPI stub functions and inline the CONFIG_ACPI for code
sharing.
6. Remove the reset_required kernel option from AMBA.
7. Change the permission to 444 for the reset_required kernel command line
parameter.

Sinan Kaya (9):
  vfio: platform: rename reset function
  vfio: platform: move reset call to a common function
  vfio: platform: determine reset capability
  vfio: platform: add support for ACPI probe
  vfio: platform: add extra debug info argument to call reset
  vfio: platform: call _RST method when using ACPI
  vfio, platform: make reset driver a requirement by default
  vfio: platform: check reset call return code during open
  vfio: platform: check reset call return code during release

 drivers/vfio/platform/vfio_amba.c             |   1 +
 drivers/vfio/platform/vfio_platform.c         |   5 +
 drivers/vfio/platform/vfio_platform_common.c  | 200 ++++++++++++++++++++++----
 drivers/vfio/platform/vfio_platform_private.h |   8 +-
 4 files changed, 180 insertions(+), 34 deletions(-)

-- 
1.8.2.1

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

* [PATCH V9 1/9] vfio: platform: rename reset function
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 2/9] vfio: platform: move reset call to a common function Sinan Kaya
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

Renaming the reset function to of_reset as it is only used
by the device tree based platforms.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 30 +++++++++++++--------------
 drivers/vfio/platform/vfio_platform_private.h |  6 +++---
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index e65b142..08fd7c2 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -41,7 +41,7 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 		if (!strcmp(iter->compat, compat) &&
 			try_module_get(iter->owner)) {
 			*module = iter->owner;
-			reset_fn = iter->reset;
+			reset_fn = iter->of_reset;
 			break;
 		}
 	}
@@ -51,18 +51,18 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
-	vdev->reset = vfio_platform_lookup_reset(vdev->compat,
-						&vdev->reset_module);
-	if (!vdev->reset) {
+	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
+						    &vdev->reset_module);
+	if (!vdev->of_reset) {
 		request_module("vfio-reset:%s", vdev->compat);
-		vdev->reset = vfio_platform_lookup_reset(vdev->compat,
-							 &vdev->reset_module);
+		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
+							&vdev->reset_module);
 	}
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
-	if (vdev->reset)
+	if (vdev->of_reset)
 		module_put(vdev->reset_module);
 }
 
@@ -141,9 +141,9 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		if (vdev->reset) {
+		if (vdev->of_reset) {
 			dev_info(vdev->device, "reset\n");
-			vdev->reset(vdev);
+			vdev->of_reset(vdev);
 		} else {
 			dev_warn(vdev->device, "no reset function found!\n");
 		}
@@ -175,9 +175,9 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		if (vdev->reset) {
+		if (vdev->of_reset) {
 			dev_info(vdev->device, "reset\n");
-			vdev->reset(vdev);
+			vdev->of_reset(vdev);
 		} else {
 			dev_warn(vdev->device, "no reset function found!\n");
 		}
@@ -213,7 +213,7 @@ static long vfio_platform_ioctl(void *device_data,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		if (vdev->reset)
+		if (vdev->of_reset)
 			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
@@ -312,8 +312,8 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		if (vdev->reset)
-			return vdev->reset(vdev);
+		if (vdev->of_reset)
+			return vdev->of_reset(vdev);
 		else
 			return -EINVAL;
 	}
@@ -611,7 +611,7 @@ void vfio_platform_unregister_reset(const char *compat,
 
 	mutex_lock(&driver_lock);
 	list_for_each_entry_safe(iter, temp, &reset_list, link) {
-		if (!strcmp(iter->compat, compat) && (iter->reset == fn)) {
+		if (!strcmp(iter->compat, compat) && (iter->of_reset == fn)) {
 			list_del(&iter->link);
 			break;
 		}
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 42816dd..71ed7d1 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -71,7 +71,7 @@ struct vfio_platform_device {
 	struct resource*
 		(*get_resource)(struct vfio_platform_device *vdev, int i);
 	int	(*get_irq)(struct vfio_platform_device *vdev, int i);
-	int	(*reset)(struct vfio_platform_device *vdev);
+	int	(*of_reset)(struct vfio_platform_device *vdev);
 };
 
 typedef int (*vfio_platform_reset_fn_t)(struct vfio_platform_device *vdev);
@@ -80,7 +80,7 @@ struct vfio_platform_reset_node {
 	struct list_head link;
 	char *compat;
 	struct module *owner;
-	vfio_platform_reset_fn_t reset;
+	vfio_platform_reset_fn_t of_reset;
 };
 
 extern int vfio_platform_probe_common(struct vfio_platform_device *vdev,
@@ -103,7 +103,7 @@ extern void vfio_platform_unregister_reset(const char *compat,
 static struct vfio_platform_reset_node __reset ## _node = {	\
 	.owner = THIS_MODULE,					\
 	.compat = __compat,					\
-	.reset = __reset,					\
+	.of_reset = __reset,					\
 };								\
 __vfio_platform_register_reset(&__reset ## _node)
 
-- 
1.8.2.1

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

* [PATCH V9 2/9] vfio: platform: move reset call to a common function
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 1/9] vfio: platform: rename reset function Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 3/9] vfio: platform: determine reset capability Sinan Kaya
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

The reset call sequence seems to replicate itself multiple times
across the file. Grouping them together for maintenance reasons.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 30 +++++++++++++---------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 08fd7c2..3e2a7c0 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -134,6 +134,17 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 	kfree(vdev->regions);
 }
 
+static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
+{
+	if (vdev->of_reset) {
+		dev_info(vdev->device, "reset\n");
+		return vdev->of_reset(vdev);
+	}
+
+	dev_warn(vdev->device, "no reset function found!\n");
+	return -EINVAL;
+}
+
 static void vfio_platform_release(void *device_data)
 {
 	struct vfio_platform_device *vdev = device_data;
@@ -141,12 +152,7 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		if (vdev->of_reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->of_reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
@@ -175,12 +181,7 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		if (vdev->of_reset) {
-			dev_info(vdev->device, "reset\n");
-			vdev->of_reset(vdev);
-		} else {
-			dev_warn(vdev->device, "no reset function found!\n");
-		}
+		vfio_platform_call_reset(vdev);
 	}
 
 	vdev->refcnt++;
@@ -312,10 +313,7 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		if (vdev->of_reset)
-			return vdev->of_reset(vdev);
-		else
-			return -EINVAL;
+		return vfio_platform_call_reset(vdev);
 	}
 
 	return -ENOTTY;
-- 
1.8.2.1

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

* [PATCH V9 3/9] vfio: platform: determine reset capability
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 1/9] vfio: platform: rename reset function Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 2/9] vfio: platform: move reset call to a common function Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 4/9] vfio: platform: add support for ACPI probe Sinan Kaya
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

Creating a new function to determine if this driver supports reset
function or not. This is an attempt to abstract device tree calls
from the rest of the code.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 3e2a7c0..6be92c3 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -49,6 +49,11 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
+static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
+{
+	return vdev->of_reset ? true : false;
+}
+
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
@@ -214,7 +219,7 @@ static long vfio_platform_ioctl(void *device_data,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		if (vdev->of_reset)
+		if (vfio_platform_has_reset(vdev))
 			vdev->flags |= VFIO_DEVICE_FLAGS_RESET;
 		info.flags = vdev->flags;
 		info.num_regions = vdev->num_regions;
-- 
1.8.2.1

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

* [PATCH V9 4/9] vfio: platform: add support for ACPI probe
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
                   ` (2 preceding siblings ...)
  2016-07-14  2:06 ` [PATCH V9 3/9] vfio: platform: determine reset capability Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14 21:41   ` Alex Williamson
  2016-07-14  2:06 ` [PATCH V9 5/9] vfio: platform: add extra debug info argument to call reset Sinan Kaya
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

The code is using the compatible DT string to associate a reset driver
with the actual device itself. The compatible string does not exist on
ACPI based systems. HID is the unique identifier for a device driver
instead.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c  | 70 +++++++++++++++++++++++++--
 drivers/vfio/platform/vfio_platform_private.h |  1 +
 2 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 6be92c3..ff148764 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -13,6 +13,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/acpi.h>
 #include <linux/iommu.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -49,6 +50,33 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 	return reset_fn;
 }
 
+static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
+				    struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (acpi_disabled)
+		return -EPERM;
+
+	if (!adev) {
+		pr_err("VFIO: ACPI companion device not found for %s\n",
+			vdev->name);
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_ACPI
+	vdev->acpihid = acpi_device_hid(adev);
+	if (!vdev->acpihid) {
+		pr_err("VFIO: cannot find ACPI HID for %s\n",
+		       vdev->name);
+		return -EINVAL;
+	}
+	return 0;
+#else
+	return -ENOENT;
+#endif
+}
+
 static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 {
 	return vdev->of_reset ? true : false;
@@ -547,6 +575,37 @@ static const struct vfio_device_ops vfio_platform_ops = {
 	.mmap		= vfio_platform_mmap,
 };
 
+int vfio_platform_of_probe(struct vfio_platform_device *vdev,
+			   struct device *dev)
+{
+	int ret;
+
+	ret = device_property_read_string(dev, "compatible",
+					  &vdev->compat);
+	if (ret)
+		pr_err("VFIO: cannot retrieve compat for %s\n",
+			vdev->name);
+
+	return ret;
+}
+
+/*
+ * There can be two kernel build combinations. One build where
+ * ACPI is not selected in Kconfig and another one with the ACPI Kconfig.
+ *
+ * In the first case, vfio_platform_acpi_probe will return since
+ * acpi_disabled  * is 1. DT user will not see any kind of messages from
+ * ACPI.
+ *
+ * In the second case, both DT and ACPI is compiled in but the system is
+ * booting with any of these combinations.
+ *
+ * If the firmware is DT type, then acpi_disabled is 1. The ACPI probe routine
+ * terminates immediately without any messages.
+ *
+ * If the firmware is ACPI type, then acpi_disabled is 0. All other checks are
+ * valid checks. We cannot claim that this system is DT.
+ */
 int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 			       struct device *dev)
 {
@@ -556,11 +615,12 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 	if (!vdev)
 		return -EINVAL;
 
-	ret = device_property_read_string(dev, "compatible", &vdev->compat);
-	if (ret) {
-		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
-		return -EINVAL;
-	}
+	ret = vfio_platform_acpi_probe(vdev, dev);
+	if (ret)
+		ret = vfio_platform_of_probe(vdev, dev);
+
+	if (ret)
+		return ret;
 
 	vdev->device = dev;
 
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 71ed7d1..ba9e4f8 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -58,6 +58,7 @@ struct vfio_platform_device {
 	struct mutex			igate;
 	struct module			*parent_module;
 	const char			*compat;
+	const char			*acpihid;
 	struct module			*reset_module;
 	struct device			*device;
 
-- 
1.8.2.1

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

* [PATCH V9 5/9] vfio: platform: add extra debug info argument to call reset
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
                   ` (3 preceding siblings ...)
  2016-07-14  2:06 ` [PATCH V9 4/9] vfio: platform: add support for ACPI probe Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI Sinan Kaya
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

Getting ready to bring out extra debug information to the caller
so that more verbose information can be printed when an error is
observed.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index ff148764..03483c2 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -167,7 +167,8 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 	kfree(vdev->regions);
 }
 
-static int vfio_platform_call_reset(struct vfio_platform_device *vdev)
+static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
+				    const char **extra_dbg)
 {
 	if (vdev->of_reset) {
 		dev_info(vdev->device, "reset\n");
@@ -185,7 +186,7 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		vfio_platform_call_reset(vdev);
+		vfio_platform_call_reset(vdev, NULL);
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
@@ -214,7 +215,7 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		vfio_platform_call_reset(vdev);
+		vfio_platform_call_reset(vdev, NULL);
 	}
 
 	vdev->refcnt++;
@@ -346,7 +347,7 @@ static long vfio_platform_ioctl(void *device_data,
 		return ret;
 
 	} else if (cmd == VFIO_DEVICE_RESET) {
-		return vfio_platform_call_reset(vdev);
+		return vfio_platform_call_reset(vdev, NULL);
 	}
 
 	return -ENOTTY;
-- 
1.8.2.1

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

* [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
                   ` (4 preceding siblings ...)
  2016-07-14  2:06 ` [PATCH V9 5/9] vfio: platform: add extra debug info argument to call reset Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14 22:04   ` Alex Williamson
  2016-07-14  2:06 ` [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default Sinan Kaya
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

The device tree code checks for the presence of a reset driver and calls
the of_reset function pointer by looking up the reset driver as a module.

ACPI defines _RST method to perform device level reset. After the _RST
method is executed, the OS can resume using the device. _RST method is
expected to stop DMA transfers and IRQs.

This patch introduces two functions as vfio_platform_acpi_has_reset and
vfio_platform_acpi_call_reset. The has reset method is used to declare
reset capability via the ioctl flag VFIO_DEVICE_FLAGS_RESET. The call
reset function is used to execute the _RST ACPI method.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/vfio/platform/vfio_platform_common.c | 52 +++++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 03483c2..2d9c905 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -28,6 +28,8 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO platform base module"
 
+#define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL)
+
 static LIST_HEAD(reset_list);
 static DEFINE_MUTEX(driver_lock);
 
@@ -77,13 +79,55 @@ static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
 #endif
 }
 
+static inline
+int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev,
+				  const char **extra_dbg)
+{
+#ifdef CONFIG_ACPI
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+	acpi_status acpi_ret;
+
+	acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, &buffer);
+	if (ACPI_FAILURE(acpi_ret)) {
+		if (extra_dbg)
+			*extra_dbg = acpi_format_exception(acpi_ret);
+		return -EINVAL;
+	}
+
+	return 0;
+#else
+	return -ENOENT;
+#endif
+}
+
+static inline
+bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
+{
+#ifdef CONFIG_ACPI
+	struct device *dev = vdev->device;
+	acpi_handle handle = ACPI_HANDLE(dev);
+
+	return acpi_has_method(handle, "_RST");
+#else
+	return false;
+#endif
+}
+
 static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 {
+	if (VFIO_PLATFORM_IS_ACPI(vdev))
+		return vfio_platform_acpi_has_reset(vdev);
+
 	return vdev->of_reset ? true : false;
 }
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
+	if (VFIO_PLATFORM_IS_ACPI(vdev))
+		return;
+
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 						    &vdev->reset_module);
 	if (!vdev->of_reset) {
@@ -95,6 +139,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
 {
+	if (VFIO_PLATFORM_IS_ACPI(vdev))
+		return;
+
 	if (vdev->of_reset)
 		module_put(vdev->reset_module);
 }
@@ -170,7 +217,10 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
 				    const char **extra_dbg)
 {
-	if (vdev->of_reset) {
+	if (VFIO_PLATFORM_IS_ACPI(vdev)) {
+		dev_info(vdev->device, "reset\n");
+		return vfio_platform_acpi_call_reset(vdev, extra_dbg);
+	} else if (vdev->of_reset) {
 		dev_info(vdev->device, "reset\n");
 		return vdev->of_reset(vdev);
 	}
-- 
1.8.2.1

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

* [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
                   ` (5 preceding siblings ...)
  2016-07-14  2:06 ` [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14 22:24   ` Alex Williamson
  2016-07-14  2:06 ` [PATCH V9 8/9] vfio: platform: check reset call return code during open Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 9/9] vfio: platform: check reset call return code during release Sinan Kaya
  8 siblings, 1 reply; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

The code was allowing platform devices to be used without a supporting
VFIO reset driver. The hardware can be left in some inconsistent state
after a guest machine abort.

The reset driver will put the hardware back to safe state and disable
interrupts before returning the control back to the host machine.

Adding a new reset_required kernel module option to platform VFIO drivers.
The default value is true for the DT and ACPI based drivers.
The reset requirement value for AMBA drivers is set to false and is
unchangeable to maintain the existing functionality.

New requirements are:
1. A reset function needs to be implemented by the corresponding driver
via DT/ACPI.
2. The reset function needs to be discovered via DT/ACPI.

The probe of the driver will fail if any of the above conditions are
not satisfied.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/vfio/platform/vfio_amba.c             |  1 +
 drivers/vfio/platform/vfio_platform.c         |  5 +++++
 drivers/vfio/platform/vfio_platform_common.c  | 15 +++++++++++----
 drivers/vfio/platform/vfio_platform_private.h |  1 +
 4 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
index a66479b..31372fb 100644
--- a/drivers/vfio/platform/vfio_amba.c
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -68,6 +68,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
 	vdev->get_resource = get_amba_resource;
 	vdev->get_irq = get_amba_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = false;
 
 	ret = vfio_platform_probe_common(vdev, &adev->dev);
 	if (ret) {
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index b1cc3a7..6561751 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -23,6 +23,10 @@
 #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
 #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
 
+static bool reset_required = true;
+module_param(reset_required, bool, 0444);
+MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
+
 /* probing devices from the linux platform bus */
 
 static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
@@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
 	vdev->get_resource = get_platform_resource;
 	vdev->get_irq = get_platform_irq;
 	vdev->parent_module = THIS_MODULE;
+	vdev->reset_required = reset_required;
 
 	ret = vfio_platform_probe_common(vdev, &pdev->dev);
 	if (ret)
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 2d9c905..71248a9 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -123,10 +123,10 @@ static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
 	return vdev->of_reset ? true : false;
 }
 
-static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
+static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
 	if (VFIO_PLATFORM_IS_ACPI(vdev))
-		return;
+		return vfio_platform_acpi_has_reset(vdev) ? 0 : -ENOENT;
 
 	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 						    &vdev->reset_module);
@@ -135,6 +135,8 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
 							&vdev->reset_module);
 	}
+
+	return vdev->of_reset ? 0 : -ENOENT;
 }
 
 static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
@@ -675,6 +677,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 
 	vdev->device = dev;
 
+	ret = vfio_platform_get_reset(vdev);
+	if (ret && vdev->reset_required) {
+		pr_err("vfio: no reset function found for device %s\n",
+		       vdev->name);
+		return ret;
+	}
+
 	group = iommu_group_get(dev);
 	if (!group) {
 		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
@@ -687,8 +696,6 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
 		return ret;
 	}
 
-	vfio_platform_get_reset(vdev);
-
 	mutex_init(&vdev->igate);
 
 	return 0;
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index ba9e4f8..68fbc00 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -50,6 +50,7 @@ struct vfio_platform_region {
 };
 
 struct vfio_platform_device {
+	bool				reset_required;
 	struct vfio_platform_region	*regions;
 	u32				num_regions;
 	struct vfio_platform_irq	*irqs;
-- 
1.8.2.1

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

* [PATCH V9 8/9] vfio: platform: check reset call return code during open
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
                   ` (6 preceding siblings ...)
  2016-07-14  2:06 ` [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  2016-07-14  2:06 ` [PATCH V9 9/9] vfio: platform: check reset call return code during release Sinan Kaya
  8 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

Open call is ignoring the return code from reset call and can
potentially continue even though reset call failed.

If reset_required module parameter is set, this patch is going
to validate the return code and will abort open if reset fails.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 71248a9..1898ff6 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -259,6 +259,8 @@ static int vfio_platform_open(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!vdev->refcnt) {
+		const char *extra_dbg = NULL;
+
 		ret = vfio_platform_regions_init(vdev);
 		if (ret)
 			goto err_reg;
@@ -267,7 +269,12 @@ static int vfio_platform_open(void *device_data)
 		if (ret)
 			goto err_irq;
 
-		vfio_platform_call_reset(vdev, NULL);
+		ret = vfio_platform_call_reset(vdev, &extra_dbg);
+		if (ret && vdev->reset_required) {
+			dev_warn(vdev->device, "reset driver is required and reset call failed in open (%d) %s\n",
+				 ret, extra_dbg ? extra_dbg : "");
+			goto err_rst;
+		}
 	}
 
 	vdev->refcnt++;
@@ -275,6 +282,8 @@ static int vfio_platform_open(void *device_data)
 	mutex_unlock(&driver_lock);
 	return 0;
 
+err_rst:
+	vfio_platform_irq_cleanup(vdev);
 err_irq:
 	vfio_platform_regions_cleanup(vdev);
 err_reg:
-- 
1.8.2.1

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

* [PATCH V9 9/9] vfio: platform: check reset call return code during release
  2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
                   ` (7 preceding siblings ...)
  2016-07-14  2:06 ` [PATCH V9 8/9] vfio: platform: check reset call return code during open Sinan Kaya
@ 2016-07-14  2:06 ` Sinan Kaya
  8 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-14  2:06 UTC (permalink / raw)
  To: linux-arm-kernel

Release call is ignoring the return code from reset call and can
potentially continue even though reset call failed.

If reset_required module parameter is set, this patch is going
to validate the return code and will cause stack dump with
WARN_ON and warn the user of failure.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 drivers/vfio/platform/vfio_platform_common.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 1898ff6..65e53c7 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -238,7 +238,15 @@ static void vfio_platform_release(void *device_data)
 	mutex_lock(&driver_lock);
 
 	if (!(--vdev->refcnt)) {
-		vfio_platform_call_reset(vdev, NULL);
+		const char *extra_dbg = NULL;
+		int ret;
+
+		ret = vfio_platform_call_reset(vdev, &extra_dbg);
+		if (ret && vdev->reset_required) {
+			dev_warn(vdev->device, "reset driver is required and reset call failed in release (%d) %s\n",
+				 ret, extra_dbg ? extra_dbg : "");
+			WARN_ON(1);
+		}
 		vfio_platform_regions_cleanup(vdev);
 		vfio_platform_irq_cleanup(vdev);
 	}
-- 
1.8.2.1

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

* [PATCH V9 4/9] vfio: platform: add support for ACPI probe
  2016-07-14  2:06 ` [PATCH V9 4/9] vfio: platform: add support for ACPI probe Sinan Kaya
@ 2016-07-14 21:41   ` Alex Williamson
  2016-07-16  1:27     ` Sinan Kaya
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Williamson @ 2016-07-14 21:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 13 Jul 2016 22:06:30 -0400
Sinan Kaya <okaya@codeaurora.org> wrote:

> The code is using the compatible DT string to associate a reset driver
> with the actual device itself. The compatible string does not exist on
> ACPI based systems. HID is the unique identifier for a device driver
> instead.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
> ---
>  drivers/vfio/platform/vfio_platform_common.c  | 70 +++++++++++++++++++++++++--
>  drivers/vfio/platform/vfio_platform_private.h |  1 +
>  2 files changed, 66 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index 6be92c3..ff148764 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -13,6 +13,7 @@
>   */
>  
>  #include <linux/device.h>
> +#include <linux/acpi.h>
>  #include <linux/iommu.h>
>  #include <linux/module.h>
>  #include <linux/mutex.h>
> @@ -49,6 +50,33 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>  	return reset_fn;
>  }
>

This function still feels a bit sloppy
  
> +static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
> +				    struct device *dev)
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);

When !CONFIG_ACPI, this returns NULL

> +
> +	if (acpi_disabled)

When !CONFIG_ACPI, this is defined as 1, so we'll always exit here.

> +		return -EPERM;
> +
> +	if (!adev) {

This is really the only (ACPI_CONFIG && !acpi_disabled) error exit,
because...

> +		pr_err("VFIO: ACPI companion device not found for %s\n",
> +			vdev->name);
> +		return -ENODEV;
> +	}
> +
> +#ifdef CONFIG_ACPI
> +	vdev->acpihid = acpi_device_hid(adev);

This can't actually return NULL.  So the test below is unreached.
Maybe we should just conclude this function here with:

#endif

return vdev->acpihid ? 0 : -ENOENT;

which is even still a bit paranoid since it can't actually happen.

> +	if (!vdev->acpihid) {
> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
> +		       vdev->name);
> +		return -EINVAL;
> +	}
> +	return 0;
> +#else
> +	return -ENOENT;
> +#endif
> +}
> +
>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  {
>  	return vdev->of_reset ? true : false;
> @@ -547,6 +575,37 @@ static const struct vfio_device_ops vfio_platform_ops = {
>  	.mmap		= vfio_platform_mmap,
>  };
>  
> +int vfio_platform_of_probe(struct vfio_platform_device *vdev,
> +			   struct device *dev)
> +{
> +	int ret;
> +
> +	ret = device_property_read_string(dev, "compatible",
> +					  &vdev->compat);
> +	if (ret)
> +		pr_err("VFIO: cannot retrieve compat for %s\n",
> +			vdev->name);
> +
> +	return ret;
> +}
> +
> +/*
> + * There can be two kernel build combinations. One build where
> + * ACPI is not selected in Kconfig and another one with the ACPI Kconfig.
> + *
> + * In the first case, vfio_platform_acpi_probe will return since
> + * acpi_disabled  * is 1. DT user will not see any kind of messages from

                    ^^ Previous editing cruft?

> + * ACPI.
> + *
> + * In the second case, both DT and ACPI is compiled in but the system is
> + * booting with any of these combinations.
> + *
> + * If the firmware is DT type, then acpi_disabled is 1. The ACPI probe routine
> + * terminates immediately without any messages.
> + *
> + * If the firmware is ACPI type, then acpi_disabled is 0. All other checks are
> + * valid checks. We cannot claim that this system is DT.
> + */
>  int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  			       struct device *dev)
>  {
> @@ -556,11 +615,12 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  	if (!vdev)
>  		return -EINVAL;
>  
> -	ret = device_property_read_string(dev, "compatible", &vdev->compat);
> -	if (ret) {
> -		pr_err("VFIO: cannot retrieve compat for %s\n", vdev->name);
> -		return -EINVAL;
> -	}
> +	ret = vfio_platform_acpi_probe(vdev, dev);
> +	if (ret)
> +		ret = vfio_platform_of_probe(vdev, dev);
> +
> +	if (ret)
> +		return ret;
>  
>  	vdev->device = dev;
>  
> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
> index 71ed7d1..ba9e4f8 100644
> --- a/drivers/vfio/platform/vfio_platform_private.h
> +++ b/drivers/vfio/platform/vfio_platform_private.h
> @@ -58,6 +58,7 @@ struct vfio_platform_device {
>  	struct mutex			igate;
>  	struct module			*parent_module;
>  	const char			*compat;
> +	const char			*acpihid;
>  	struct module			*reset_module;
>  	struct device			*device;
>  

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

* [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI
  2016-07-14  2:06 ` [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI Sinan Kaya
@ 2016-07-14 22:04   ` Alex Williamson
  2016-07-16  1:09     ` Sinan Kaya
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Williamson @ 2016-07-14 22:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 13 Jul 2016 22:06:32 -0400
Sinan Kaya <okaya@codeaurora.org> wrote:

> The device tree code checks for the presence of a reset driver and calls
> the of_reset function pointer by looking up the reset driver as a module.
> 
> ACPI defines _RST method to perform device level reset. After the _RST
> method is executed, the OS can resume using the device. _RST method is
> expected to stop DMA transfers and IRQs.
> 
> This patch introduces two functions as vfio_platform_acpi_has_reset and
> vfio_platform_acpi_call_reset. The has reset method is used to declare
> reset capability via the ioctl flag VFIO_DEVICE_FLAGS_RESET. The call
> reset function is used to execute the _RST ACPI method.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_platform_common.c | 52 +++++++++++++++++++++++++++-
>  1 file changed, 51 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index 03483c2..2d9c905 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -28,6 +28,8 @@
>  #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
>  #define DRIVER_DESC     "VFIO platform base module"
>  
> +#define VFIO_PLATFORM_IS_ACPI(vdev) ((vdev)->acpihid != NULL)
> +
>  static LIST_HEAD(reset_list);
>  static DEFINE_MUTEX(driver_lock);
>  
> @@ -77,13 +79,55 @@ static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>  #endif
>  }
>  
> +static inline
> +int vfio_platform_acpi_call_reset(struct vfio_platform_device *vdev,
> +				  const char **extra_dbg)
> +{
> +#ifdef CONFIG_ACPI
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +	acpi_status acpi_ret;
> +
> +	acpi_ret = acpi_evaluate_object(handle, "_RST", NULL, &buffer);
> +	if (ACPI_FAILURE(acpi_ret)) {
> +		if (extra_dbg)
> +			*extra_dbg = acpi_format_exception(acpi_ret);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +#else
> +	return -ENOENT;
> +#endif
> +}
> +
> +static inline
> +bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
> +{
> +#ifdef CONFIG_ACPI
> +	struct device *dev = vdev->device;
> +	acpi_handle handle = ACPI_HANDLE(dev);
> +
> +	return acpi_has_method(handle, "_RST");
> +#else
> +	return false;
> +#endif
> +}

What exactly is the rationale for making these inline?  Clearly reset
is not a performance relevant path.  Thanks,

Alex

> +
>  static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  {
> +	if (VFIO_PLATFORM_IS_ACPI(vdev))
> +		return vfio_platform_acpi_has_reset(vdev);
> +
>  	return vdev->of_reset ? true : false;
>  }
>  
>  static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
> +	if (VFIO_PLATFORM_IS_ACPI(vdev))
> +		return;
> +
>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  						    &vdev->reset_module);
>  	if (!vdev->of_reset) {
> @@ -95,6 +139,9 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
>  {
> +	if (VFIO_PLATFORM_IS_ACPI(vdev))
> +		return;
> +
>  	if (vdev->of_reset)
>  		module_put(vdev->reset_module);
>  }
> @@ -170,7 +217,10 @@ static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
>  static int vfio_platform_call_reset(struct vfio_platform_device *vdev,
>  				    const char **extra_dbg)
>  {
> -	if (vdev->of_reset) {
> +	if (VFIO_PLATFORM_IS_ACPI(vdev)) {
> +		dev_info(vdev->device, "reset\n");
> +		return vfio_platform_acpi_call_reset(vdev, extra_dbg);
> +	} else if (vdev->of_reset) {
>  		dev_info(vdev->device, "reset\n");
>  		return vdev->of_reset(vdev);
>  	}

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

* [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default
  2016-07-14  2:06 ` [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default Sinan Kaya
@ 2016-07-14 22:24   ` Alex Williamson
  2016-07-16  1:07     ` Sinan Kaya
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Williamson @ 2016-07-14 22:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 13 Jul 2016 22:06:33 -0400
Sinan Kaya <okaya@codeaurora.org> wrote:

> The code was allowing platform devices to be used without a supporting
> VFIO reset driver. The hardware can be left in some inconsistent state
> after a guest machine abort.
> 
> The reset driver will put the hardware back to safe state and disable
> interrupts before returning the control back to the host machine.
> 
> Adding a new reset_required kernel module option to platform VFIO drivers.
> The default value is true for the DT and ACPI based drivers.
> The reset requirement value for AMBA drivers is set to false and is
> unchangeable to maintain the existing functionality.
> 
> New requirements are:
> 1. A reset function needs to be implemented by the corresponding driver
> via DT/ACPI.
> 2. The reset function needs to be discovered via DT/ACPI.
> 
> The probe of the driver will fail if any of the above conditions are
> not satisfied.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/vfio/platform/vfio_amba.c             |  1 +
>  drivers/vfio/platform/vfio_platform.c         |  5 +++++
>  drivers/vfio/platform/vfio_platform_common.c  | 15 +++++++++++----
>  drivers/vfio/platform/vfio_platform_private.h |  1 +
>  4 files changed, 18 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/vfio/platform/vfio_amba.c b/drivers/vfio/platform/vfio_amba.c
> index a66479b..31372fb 100644
> --- a/drivers/vfio/platform/vfio_amba.c
> +++ b/drivers/vfio/platform/vfio_amba.c
> @@ -68,6 +68,7 @@ static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
>  	vdev->get_resource = get_amba_resource;
>  	vdev->get_irq = get_amba_irq;
>  	vdev->parent_module = THIS_MODULE;
> +	vdev->reset_required = false;
>  
>  	ret = vfio_platform_probe_common(vdev, &adev->dev);
>  	if (ret) {
> diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
> index b1cc3a7..6561751 100644
> --- a/drivers/vfio/platform/vfio_platform.c
> +++ b/drivers/vfio/platform/vfio_platform.c
> @@ -23,6 +23,10 @@
>  #define DRIVER_AUTHOR   "Antonios Motakis <a.motakis@virtualopensystems.com>"
>  #define DRIVER_DESC     "VFIO for platform devices - User Level meta-driver"
>  
> +static bool reset_required = true;
> +module_param(reset_required, bool, 0444);
> +MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");
> +
>  /* probing devices from the linux platform bus */
>  
>  static struct resource *get_platform_resource(struct vfio_platform_device *vdev,
> @@ -66,6 +70,7 @@ static int vfio_platform_probe(struct platform_device *pdev)
>  	vdev->get_resource = get_platform_resource;
>  	vdev->get_irq = get_platform_irq;
>  	vdev->parent_module = THIS_MODULE;
> +	vdev->reset_required = reset_required;
>  
>  	ret = vfio_platform_probe_common(vdev, &pdev->dev);
>  	if (ret)
> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> index 2d9c905..71248a9 100644
> --- a/drivers/vfio/platform/vfio_platform_common.c
> +++ b/drivers/vfio/platform/vfio_platform_common.c
> @@ -123,10 +123,10 @@ static bool vfio_platform_has_reset(struct vfio_platform_device *vdev)
>  	return vdev->of_reset ? true : false;
>  }
>  
> -static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
> +static int vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  {
>  	if (VFIO_PLATFORM_IS_ACPI(vdev))
> -		return;
> +		return vfio_platform_acpi_has_reset(vdev) ? 0 : -ENOENT;
>  
>  	vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  						    &vdev->reset_module);
> @@ -135,6 +135,8 @@ static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
>  		vdev->of_reset = vfio_platform_lookup_reset(vdev->compat,
>  							&vdev->reset_module);
>  	}
> +
> +	return vdev->of_reset ? 0 : -ENOENT;
>  }
>  
>  static void vfio_platform_put_reset(struct vfio_platform_device *vdev)
> @@ -675,6 +677,13 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  
>  	vdev->device = dev;
>  
> +	ret = vfio_platform_get_reset(vdev);
> +	if (ret && vdev->reset_required) {
> +		pr_err("vfio: no reset function found for device %s\n",
> +		       vdev->name);
> +		return ret;
> +	}
> +
>  	group = iommu_group_get(dev);
>  	if (!group) {
>  		pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
> @@ -687,8 +696,6 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
>  		return ret;
>  	}
>  
> -	vfio_platform_get_reset(vdev);
> -
>  	mutex_init(&vdev->igate);
>  
>  	return 0;
> diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
> index ba9e4f8..68fbc00 100644
> --- a/drivers/vfio/platform/vfio_platform_private.h
> +++ b/drivers/vfio/platform/vfio_platform_private.h
> @@ -50,6 +50,7 @@ struct vfio_platform_region {
>  };
>  
>  struct vfio_platform_device {
> +	bool				reset_required;
>  	struct vfio_platform_region	*regions;
>  	u32				num_regions;
>  	struct vfio_platform_irq	*irqs;

Either you have 64bit bools or you're not paying any attention to
to the alignment of this structure.  If we only care about 64bit
systems we could tuck this into the gap after num_regions, otherwise
append it to the end of the structure, we certainly don't care about
keeping a reset flag within cache line boundaries.  Thanks,

Alex

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

* [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default
  2016-07-14 22:24   ` Alex Williamson
@ 2016-07-16  1:07     ` Sinan Kaya
  0 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-16  1:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 7/14/2016 6:24 PM, Alex Williamson wrote:
>> struct vfio_platform_device {
>> > +	bool				reset_required;
>> >  	struct vfio_platform_region	*regions;
>> >  	u32				num_regions;
>> >  	struct vfio_platform_irq	*irqs;
> Either you have 64bit bools or you're not paying any attention to
> to the alignment of this structure.  If we only care about 64bit
> systems we could tuck this into the gap after num_regions, otherwise
> append it to the end of the structure, we certainly don't care about
> keeping a reset flag within cache line boundaries.  Thanks,

OK, I moved it to the end of the structure.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI
  2016-07-14 22:04   ` Alex Williamson
@ 2016-07-16  1:09     ` Sinan Kaya
  0 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-16  1:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 7/14/2016 6:04 PM, Alex Williamson wrote:
>> +static inline
>> > +bool vfio_platform_acpi_has_reset(struct vfio_platform_device *vdev)
>> > +{
>> > +#ifdef CONFIG_ACPI
>> > +	struct device *dev = vdev->device;
>> > +	acpi_handle handle = ACPI_HANDLE(dev);
>> > +
>> > +	return acpi_has_method(handle, "_RST");
>> > +#else
>> > +	return false;
>> > +#endif
>> > +}
> What exactly is the rationale for making these inline?  Clearly reset
> is not a performance relevant path.  Thanks,
> 
> Alex
> 

It is remaining from the previous stub functions which were inline. I'll get rid
of the inlines.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH V9 4/9] vfio: platform: add support for ACPI probe
  2016-07-14 21:41   ` Alex Williamson
@ 2016-07-16  1:27     ` Sinan Kaya
  2016-07-18 17:32       ` Alex Williamson
  0 siblings, 1 reply; 18+ messages in thread
From: Sinan Kaya @ 2016-07-16  1:27 UTC (permalink / raw)
  To: linux-arm-kernel

On 7/14/2016 5:41 PM, Alex Williamson wrote:
> On Wed, 13 Jul 2016 22:06:30 -0400
> Sinan Kaya <okaya@codeaurora.org> wrote:
> 
>> The code is using the compatible DT string to associate a reset driver
>> with the actual device itself. The compatible string does not exist on
>> ACPI based systems. HID is the unique identifier for a device driver
>> instead.
>>
>> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
>> Reviewed-by: Eric Auger <eric.auger@redhat.com>
>> Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
>> ---
>>  drivers/vfio/platform/vfio_platform_common.c  | 70 +++++++++++++++++++++++++--
>>  drivers/vfio/platform/vfio_platform_private.h |  1 +
>>  2 files changed, 66 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
>> index 6be92c3..ff148764 100644
>> --- a/drivers/vfio/platform/vfio_platform_common.c
>> +++ b/drivers/vfio/platform/vfio_platform_common.c
>> @@ -13,6 +13,7 @@
>>   */
>>  
>>  #include <linux/device.h>
>> +#include <linux/acpi.h>
>>  #include <linux/iommu.h>
>>  #include <linux/module.h>
>>  #include <linux/mutex.h>
>> @@ -49,6 +50,33 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
>>  	return reset_fn;
>>  }
>>
> 
> This function still feels a bit sloppy
>   
>> +static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
>> +				    struct device *dev)
>> +{
>> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> 
> When !CONFIG_ACPI, this returns NULL
> 
>> +
>> +	if (acpi_disabled)
> 
> When !CONFIG_ACPI, this is defined as 1, so we'll always exit here.
> 
>> +		return -EPERM;
>> +

I'll move this here and leave the variable definition above only.

	adev = ACPI_COMPANION(dev);

>> +	if (!adev) {
> 
> This is really the only (ACPI_CONFIG && !acpi_disabled) error exit,
> because...
> 
>> +		pr_err("VFIO: ACPI companion device not found for %s\n",
>> +			vdev->name);
>> +		return -ENODEV;
>> +	}
>> +
>> +#ifdef CONFIG_ACPI
>> +	vdev->acpihid = acpi_device_hid(adev);
> 

Based on the current implementation of acpi_device_hid, the function wlll 
return a name of "device" when the pnp device id list is empty. 

Do you want to rely on the current implementation behavior rather than be
safe?

> This can't actually return NULL.  So the test below is unreached.
> Maybe we should just conclude this function here with:
> 
> #endif
> 
> return vdev->acpihid ? 0 : -ENOENT;
> 
> which is even still a bit paranoid since it can't actually happen.
> 
>> +	if (!vdev->acpihid) {
>> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
>> +		       vdev->name);
>> +		return -EINVAL;
>> +	}
>> +	return 0;
>> +#else
>> +	return -ENOENT;
>> +#endif
>> +}
>> +


>> +
>> +/*
>> + * There can be two kernel build combinations. One build where
>> + * ACPI is not selected in Kconfig and another one with the ACPI Kconfig.
>> + *
>> + * In the first case, vfio_platform_acpi_probe will return since
>> + * acpi_disabled  * is 1. DT user will not see any kind of messages from
> 
>                     ^^ Previous editing cruft?

Yep, good catch. Got warned by checkpatch for 80 characters. 



-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH V9 4/9] vfio: platform: add support for ACPI probe
  2016-07-16  1:27     ` Sinan Kaya
@ 2016-07-18 17:32       ` Alex Williamson
  2016-07-18 21:23         ` Sinan Kaya
  0 siblings, 1 reply; 18+ messages in thread
From: Alex Williamson @ 2016-07-18 17:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 15 Jul 2016 21:27:24 -0400
Sinan Kaya <okaya@codeaurora.org> wrote:

> On 7/14/2016 5:41 PM, Alex Williamson wrote:
> > On Wed, 13 Jul 2016 22:06:30 -0400
> > Sinan Kaya <okaya@codeaurora.org> wrote:
> >   
> >> The code is using the compatible DT string to associate a reset driver
> >> with the actual device itself. The compatible string does not exist on
> >> ACPI based systems. HID is the unique identifier for a device driver
> >> instead.
> >>
> >> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> >> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> >> Reviewed-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
> >> ---
> >>  drivers/vfio/platform/vfio_platform_common.c  | 70 +++++++++++++++++++++++++--
> >>  drivers/vfio/platform/vfio_platform_private.h |  1 +
> >>  2 files changed, 66 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
> >> index 6be92c3..ff148764 100644
> >> --- a/drivers/vfio/platform/vfio_platform_common.c
> >> +++ b/drivers/vfio/platform/vfio_platform_common.c
> >> @@ -13,6 +13,7 @@
> >>   */
> >>  
> >>  #include <linux/device.h>
> >> +#include <linux/acpi.h>
> >>  #include <linux/iommu.h>
> >>  #include <linux/module.h>
> >>  #include <linux/mutex.h>
> >> @@ -49,6 +50,33 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
> >>  	return reset_fn;
> >>  }
> >>  
> > 
> > This function still feels a bit sloppy
> >     
> >> +static int vfio_platform_acpi_probe(struct vfio_platform_device *vdev,
> >> +				    struct device *dev)
> >> +{
> >> +	struct acpi_device *adev = ACPI_COMPANION(dev);  
> > 
> > When !CONFIG_ACPI, this returns NULL
> >   
> >> +
> >> +	if (acpi_disabled)  
> > 
> > When !CONFIG_ACPI, this is defined as 1, so we'll always exit here.
> >   
> >> +		return -EPERM;
> >> +  
> 
> I'll move this here and leave the variable definition above only.
> 
> 	adev = ACPI_COMPANION(dev);
> 
> >> +	if (!adev) {  
> > 
> > This is really the only (ACPI_CONFIG && !acpi_disabled) error exit,
> > because...
> >   
> >> +		pr_err("VFIO: ACPI companion device not found for %s\n",
> >> +			vdev->name);
> >> +		return -ENODEV;
> >> +	}
> >> +
> >> +#ifdef CONFIG_ACPI
> >> +	vdev->acpihid = acpi_device_hid(adev);  
> >   
> 
> Based on the current implementation of acpi_device_hid, the function wlll 
> return a name of "device" when the pnp device id list is empty. 
> 
> Do you want to rely on the current implementation behavior rather than be
> safe?

The implementation looks pretty fixed, it seems like a lot would break
if that were changed, so the callers of the function would need to be
updated, including this one.  The ternary below is already paranoid
enough to handle an API change, but if you want to add one more level
of paranoia, you could use WARN_ON(!vdev->acpihid) to make it user
visible.  It could still be done as:

return WARN_ON(!vdev->acpihid) ? -ENOENT : 0;

Thanks,
Alex
 
> > This can't actually return NULL.  So the test below is unreached.
> > Maybe we should just conclude this function here with:
> > 
> > #endif
> > 
> > return vdev->acpihid ? 0 : -ENOENT;
> > 
> > which is even still a bit paranoid since it can't actually happen.
> >   
> >> +	if (!vdev->acpihid) {
> >> +		pr_err("VFIO: cannot find ACPI HID for %s\n",
> >> +		       vdev->name);
> >> +		return -EINVAL;
> >> +	}
> >> +	return 0;
> >> +#else
> >> +	return -ENOENT;
> >> +#endif
> >> +}
> >> +  
> 
> 
> >> +
> >> +/*
> >> + * There can be two kernel build combinations. One build where
> >> + * ACPI is not selected in Kconfig and another one with the ACPI Kconfig.
> >> + *
> >> + * In the first case, vfio_platform_acpi_probe will return since
> >> + * acpi_disabled  * is 1. DT user will not see any kind of messages from  
> > 
> >                     ^^ Previous editing cruft?  
> 
> Yep, good catch. Got warned by checkpatch for 80 characters. 
> 
> 
> 

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

* [PATCH V9 4/9] vfio: platform: add support for ACPI probe
  2016-07-18 17:32       ` Alex Williamson
@ 2016-07-18 21:23         ` Sinan Kaya
  0 siblings, 0 replies; 18+ messages in thread
From: Sinan Kaya @ 2016-07-18 21:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 7/18/2016 1:32 PM, Alex Williamson wrote:
> The implementation looks pretty fixed, it seems like a lot would break
> if that were changed, so the callers of the function would need to be
> updated, including this one.  The ternary below is already paranoid
> enough to handle an API change, but if you want to add one more level
> of paranoia, you could use WARN_ON(!vdev->acpihid) to make it user
> visible.  It could still be done as:
> 
> return WARN_ON(!vdev->acpihid) ? -ENOENT : 0;

OK. I'm adding this and will post a new version after testing.

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

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

end of thread, other threads:[~2016-07-18 21:23 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-14  2:06 [PATCH V9 0/9] vfio, platform: add ACPI support Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 1/9] vfio: platform: rename reset function Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 2/9] vfio: platform: move reset call to a common function Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 3/9] vfio: platform: determine reset capability Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 4/9] vfio: platform: add support for ACPI probe Sinan Kaya
2016-07-14 21:41   ` Alex Williamson
2016-07-16  1:27     ` Sinan Kaya
2016-07-18 17:32       ` Alex Williamson
2016-07-18 21:23         ` Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 5/9] vfio: platform: add extra debug info argument to call reset Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 6/9] vfio: platform: call _RST method when using ACPI Sinan Kaya
2016-07-14 22:04   ` Alex Williamson
2016-07-16  1:09     ` Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 7/9] vfio, platform: make reset driver a requirement by default Sinan Kaya
2016-07-14 22:24   ` Alex Williamson
2016-07-16  1:07     ` Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 8/9] vfio: platform: check reset call return code during open Sinan Kaya
2016-07-14  2:06 ` [PATCH V9 9/9] vfio: platform: check reset call return code during release Sinan Kaya

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).