* [RFC PATCH v2 1/4] vfio: platform: add device tree info API and skeleton
[not found] <1413474876-28544-1-git-send-email-a.motakis@virtualopensystems.com>
@ 2014-10-16 15:54 ` Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 2/4] vfio: platform: devtree: return available property names Antonios Motakis
` (2 subsequent siblings)
3 siblings, 0 replies; 4+ messages in thread
From: Antonios Motakis @ 2014-10-16 15:54 UTC (permalink / raw)
To: kvmarm, iommu, alex.williamson
Cc: tech, christoffer.dall, eric.auger, kim.phillips,
Antonios Motakis, open list, open list:VFIO DRIVER,
open list:ABI/API
This patch introduced the API to return device tree info about
a PLATFORM device (if described by a device tree) and the skeleton
of the implementation for VFIO_PLATFORM. Information about any device
node bound by VFIO_PLATFORM should be queried via the introduced ioctl
VFIO_DEVICE_GET_DEVTREE_INFO.
The proposed API allows to get a list of strings with available property
names, and then allows to query each property. Note that the properties
are not indexed numerically, so they are always accessed by property name.
The user needs to know the data type of the property he is accessing.
Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
drivers/vfio/platform/Makefile | 3 +-
drivers/vfio/platform/devtree.c | 70 +++++++++++++++++++++++++++
drivers/vfio/platform/vfio_platform_common.c | 39 +++++++++++++++
drivers/vfio/platform/vfio_platform_private.h | 6 +++
include/uapi/linux/vfio.h | 26 ++++++++++
5 files changed, 143 insertions(+), 1 deletion(-)
create mode 100644 drivers/vfio/platform/devtree.c
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 81de144..99f3ba1 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,5 +1,6 @@
-vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o \
+ devtree.o
obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
diff --git a/drivers/vfio/platform/devtree.c b/drivers/vfio/platform/devtree.c
new file mode 100644
index 0000000..c057be3
--- /dev/null
+++ b/drivers/vfio/platform/devtree.c
@@ -0,0 +1,70 @@
+#include <linux/slab.h>
+#include <linux/vfio.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include "vfio_platform_private.h"
+
+static int devtree_get_prop_list(struct device_node *np, unsigned *lenp,
+ void __user *datap, unsigned long datasz)
+{
+ return -EINVAL;
+}
+
+static int devtree_get_strings(struct device_node *np,
+ char *name, unsigned *lenp,
+ void __user *datap, unsigned long datasz)
+{
+ return -EINVAL;
+}
+
+static int devtree_get_uint(struct device_node *np, char *name,
+ uint32_t type, unsigned *lenp,
+ void __user *datap, unsigned long datasz)
+{
+ return -EINVAL;
+}
+
+int vfio_platform_devtree_info(struct device_node *np,
+ uint32_t type, unsigned *lenp,
+ void __user *datap, unsigned long datasz)
+{
+ char *name;
+ long namesz;
+ int ret;
+
+ if (type == VFIO_DEVTREE_PROP_LIST) {
+ return devtree_get_prop_list(np, lenp, datap, datasz);
+ }
+
+ namesz = strnlen_user(datap, datasz);
+ if (!namesz)
+ return -EFAULT;
+ if (namesz > datasz)
+ return -EINVAL;
+
+ name = kzalloc(namesz, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+ if (strncpy_from_user(name, datap, namesz) <= 0) {
+ kfree(name);
+ return -EFAULT;
+ }
+
+ switch (type) {
+ case VFIO_DEVTREE_TYPE_STRINGS:
+ ret = devtree_get_strings(np, name, lenp, datap, datasz);
+ break;
+
+ case VFIO_DEVTREE_TYPE_U32:
+ case VFIO_DEVTREE_TYPE_U16:
+ case VFIO_DEVTREE_TYPE_U8:
+ ret = devtree_get_uint(np, name, type, lenp, datap, datasz);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ kfree(name);
+ return ret;
+}
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 2a6c665..bfbee2f 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -24,6 +24,7 @@
#include <linux/uaccess.h>
#include <linux/vfio.h>
#include <linux/io.h>
+#include <linux/of.h>
#include "vfio_platform_private.h"
@@ -244,6 +245,34 @@ static long vfio_platform_ioctl(void *device_data,
return ret;
+ } else if (cmd == VFIO_DEVICE_GET_DEVTREE_INFO) {
+ struct vfio_devtree_info info;
+ void __user *datap;
+ unsigned long datasz;
+ int ret;
+
+ if (!vdev->of_node)
+ return -EINVAL;
+
+ minsz = offsetofend(struct vfio_devtree_info, length);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ datap = (void __user *) arg + minsz;
+ datasz = info.argsz - minsz;
+
+ ret = vfio_platform_devtree_info(vdev->of_node, info.type,
+ &info.length, datap, datasz);
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ ret = -EFAULT;
+
+ return ret;
+
} else if (cmd == VFIO_DEVICE_RESET)
return -EINVAL;
@@ -486,6 +515,11 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
return ret;
}
+ /* get device tree node for info if available */
+ vdev->of_node = of_node_get(dev->of_node);
+ if (vdev->of_node)
+ vdev->flags |= VFIO_DEVICE_FLAGS_DEVTREE;
+
mutex_init(&vdev->igate);
return 0;
@@ -500,6 +534,11 @@ int vfio_platform_remove_common(struct device *dev)
if (!vdev)
return -EINVAL;
+ if (vdev->of_node) {
+ of_node_put(vdev->of_node);
+ vdev->of_node = NULL;
+ }
+
iommu_group_put(dev->iommu_group);
kfree(vdev);
diff --git a/drivers/vfio/platform/vfio_platform_private.h b/drivers/vfio/platform/vfio_platform_private.h
index 23ef038..fd40a26 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -60,6 +60,7 @@ struct vfio_platform_device {
void *opaque;
const char *name;
uint32_t flags;
+ struct device_node *of_node;
/* callbacks to discover device resources */
struct resource*
(*get_resource)(struct vfio_platform_device *vdev, int i);
@@ -77,4 +78,9 @@ extern int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
uint32_t flags, unsigned index, unsigned start,
unsigned count, void *data);
+/* device tree info support in devtree.c */
+extern int vfio_platform_devtree_info(struct device_node *np,
+ uint32_t type, unsigned *lenp,
+ void __user *datap, unsigned long datasz);
+
#endif /* VFIO_PLATFORM_PRIVATE_H */
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 1a5986c..18e6763 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -160,12 +160,38 @@ struct vfio_device_info {
#define VFIO_DEVICE_FLAGS_PCI (1 << 1) /* vfio-pci device */
#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2) /* vfio-platform device */
#define VFIO_DEVICE_FLAGS_AMBA (1 << 3) /* vfio-amba device */
+#define VFIO_DEVICE_FLAGS_DEVTREE (1 << 4) /* device tree metadata */
__u32 num_regions; /* Max region index + 1 */
__u32 num_irqs; /* Max IRQ index + 1 */
};
#define VFIO_DEVICE_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 7)
/**
+ * VFIO_DEVICE_GET_DEVTREE_INFO - _IOR(VFIO_TYPE, VFIO_BASE + 16,
+ * struct vfio_devtree_info)
+ *
+ * Retrieve information from the device's device tree, if available.
+ * Caller will initialize data[] with a single string with the requested
+ * devicetree property name, and type depending on whether a array of strings
+ * or an array of u32 values is expected. On success, data[] will be extended
+ * with the requested information, either as an array of u32, or with a list
+ * of strings sepparated by the NULL terminating character.
+ * Return: 0 on success, -errno on failure.
+ */
+struct vfio_devtree_info {
+ __u32 argsz;
+ __u32 type;
+#define VFIO_DEVTREE_PROP_LIST 0
+#define VFIO_DEVTREE_TYPE_STRINGS 1
+#define VFIO_DEVTREE_TYPE_U8 2
+#define VFIO_DEVTREE_TYPE_U16 3
+#define VFIO_DEVTREE_TYPE_U32 4
+ __u32 length;
+ __u8 data[];
+};
+#define VFIO_DEVICE_GET_DEVTREE_INFO _IO(VFIO_TYPE, VFIO_BASE + 17)
+
+/**
* VFIO_DEVICE_GET_REGION_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 8,
* struct vfio_region_info)
*
--
2.1.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH v2 2/4] vfio: platform: devtree: return available property names
[not found] <1413474876-28544-1-git-send-email-a.motakis@virtualopensystems.com>
2014-10-16 15:54 ` [RFC PATCH v2 1/4] vfio: platform: add device tree info API and skeleton Antonios Motakis
@ 2014-10-16 15:54 ` Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 3/4] vfio: platform: devtree: access property as a list of strings Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 4/4] vfio: platform: devtree: return arrays of u32, u16, or u8 data Antonios Motakis
3 siblings, 0 replies; 4+ messages in thread
From: Antonios Motakis @ 2014-10-16 15:54 UTC (permalink / raw)
To: kvmarm, iommu, alex.williamson
Cc: tech, christoffer.dall, eric.auger, kim.phillips,
Antonios Motakis, open list:VFIO DRIVER, open list
The available properties of a device are not indexed numerically,
instead they are accessible by property name.
Passing type = VFIO_DEVTREE_PROP_LIST to VFIO_DEVICE_GET_DEVTREE_INFO,
returns a list of strings with the available properties that the VFIO
user can access.
Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
drivers/vfio/platform/devtree.c | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/vfio/platform/devtree.c b/drivers/vfio/platform/devtree.c
index c057be3..032ee16 100644
--- a/drivers/vfio/platform/devtree.c
+++ b/drivers/vfio/platform/devtree.c
@@ -7,7 +7,42 @@
static int devtree_get_prop_list(struct device_node *np, unsigned *lenp,
void __user *datap, unsigned long datasz)
{
- return -EINVAL;
+ struct property *prop;
+ int len = 0, sz;
+ int ret = 0;
+
+ for_each_property_of_node(np, prop) {
+ sz = strlen(prop->name) + 1;
+
+ if (datasz < sz) {
+ ret = -EAGAIN;
+ break;
+ }
+
+ if (copy_to_user(datap, prop->name, sz))
+ return -EFAULT;
+
+ datap += sz;
+ datasz -= sz;
+ len += sz;
+ }
+
+ /* if overflow occurs, calculate remaining length */
+ while (prop) {
+ len += strlen(prop->name) + 1;
+ prop = prop->next;
+ }
+
+ /* we expose the full_name in addition to the usual properties */
+ len += sz = strlen("full_name") + 1;
+ if (datasz < sz) {
+ ret = -EAGAIN;
+ } else if (copy_to_user(datap, "full_name", sz))
+ return -EFAULT;
+
+ *lenp = len;
+
+ return ret;
}
static int devtree_get_strings(struct device_node *np,
--
2.1.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH v2 3/4] vfio: platform: devtree: access property as a list of strings
[not found] <1413474876-28544-1-git-send-email-a.motakis@virtualopensystems.com>
2014-10-16 15:54 ` [RFC PATCH v2 1/4] vfio: platform: add device tree info API and skeleton Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 2/4] vfio: platform: devtree: return available property names Antonios Motakis
@ 2014-10-16 15:54 ` Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 4/4] vfio: platform: devtree: return arrays of u32, u16, or u8 data Antonios Motakis
3 siblings, 0 replies; 4+ messages in thread
From: Antonios Motakis @ 2014-10-16 15:54 UTC (permalink / raw)
To: kvmarm, iommu, alex.williamson
Cc: tech, christoffer.dall, eric.auger, kim.phillips,
Antonios Motakis, open list:VFIO DRIVER, open list
Certain device tree properties (e.g. the device node name, the compatible
string), are available as a list of strings (separated by the null
terminating character). Let the VFIO user query this type of properties.
Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
drivers/vfio/platform/devtree.c | 43 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/vfio/platform/devtree.c b/drivers/vfio/platform/devtree.c
index 032ee16..6d25f97 100644
--- a/drivers/vfio/platform/devtree.c
+++ b/drivers/vfio/platform/devtree.c
@@ -45,11 +45,52 @@ static int devtree_get_prop_list(struct device_node *np, unsigned *lenp,
return ret;
}
+static int devtree_get_full_name(struct device_node *np, unsigned *lenp,
+ void __user *datap, unsigned long datasz)
+{
+ int len = strlen(np->full_name) + 1;
+
+ if (lenp)
+ *lenp = len;
+
+ if (len > datasz)
+ return -EAGAIN;
+
+ if (copy_to_user(datap, np->full_name, len))
+ return -EFAULT;
+
+ return 0;
+}
+
static int devtree_get_strings(struct device_node *np,
char *name, unsigned *lenp,
void __user *datap, unsigned long datasz)
{
- return -EINVAL;
+ struct property *prop;
+ int len;
+
+ prop = of_find_property(np, name, &len);
+
+ if (!prop) {
+ /* special case full_name as a property that is not on the fdt,
+ * but we wish to return to the user as it includes the full
+ * path of the device */
+ if (!strcmp(name, "full_name"))
+ return devtree_get_full_name(np, lenp, datap, datasz);
+ else
+ return -EINVAL;
+ }
+
+ if (lenp)
+ *lenp = len;
+
+ if (len > datasz)
+ return -EAGAIN;
+
+ if (copy_to_user(datap, prop->value, len))
+ return -EFAULT;
+
+ return 0;
}
static int devtree_get_uint(struct device_node *np, char *name,
--
2.1.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH v2 4/4] vfio: platform: devtree: return arrays of u32, u16, or u8 data
[not found] <1413474876-28544-1-git-send-email-a.motakis@virtualopensystems.com>
` (2 preceding siblings ...)
2014-10-16 15:54 ` [RFC PATCH v2 3/4] vfio: platform: devtree: access property as a list of strings Antonios Motakis
@ 2014-10-16 15:54 ` Antonios Motakis
3 siblings, 0 replies; 4+ messages in thread
From: Antonios Motakis @ 2014-10-16 15:54 UTC (permalink / raw)
To: kvmarm, iommu, alex.williamson
Cc: tech, christoffer.dall, eric.auger, kim.phillips,
Antonios Motakis, open list:VFIO DRIVER, open list
Certain properties of a device tree node are accessible as an array
of unsigned integers, either u32, u16, or u8. Let the VFIO user query
this type of device node properties. Accessing u64 arrays is not yet
implemented in this RFC.
Signed-off-by: Antonios Motakis <a.motakis@virtualopensystems.com>
---
drivers/vfio/platform/devtree.c | 55 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 54 insertions(+), 1 deletion(-)
diff --git a/drivers/vfio/platform/devtree.c b/drivers/vfio/platform/devtree.c
index 6d25f97..17f55d4 100644
--- a/drivers/vfio/platform/devtree.c
+++ b/drivers/vfio/platform/devtree.c
@@ -97,7 +97,60 @@ static int devtree_get_uint(struct device_node *np, char *name,
uint32_t type, unsigned *lenp,
void __user *datap, unsigned long datasz)
{
- return -EINVAL;
+ int ret, n;
+ size_t sz;
+ u8 *out;
+ int (*func)(const struct device_node *, const char *, void *, size_t)
+ = NULL;
+
+ switch (type) {
+ case VFIO_DEVTREE_TYPE_U32:
+ sz = sizeof(u32);
+ func = (int (*)(const struct device_node *,
+ const char *, void *, size_t))
+ of_property_read_u32_array;
+ break;
+ case VFIO_DEVTREE_TYPE_U16:
+ sz = sizeof(u16);
+ func = (int (*)(const struct device_node *,
+ const char *, void *, size_t))
+ of_property_read_u16_array;
+ break;
+ case VFIO_DEVTREE_TYPE_U8:
+ sz = sizeof(u8);
+ func = (int (*)(const struct device_node *,
+ const char *, void *, size_t))
+ of_property_read_u8_array;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ n = of_property_count_elems_of_size(np, name, sz);
+ if (n < 0)
+ return n;
+
+ if (lenp)
+ *lenp = n * sz;
+
+ if (n * sz > datasz)
+ return -EAGAIN;
+
+ out = kcalloc(n, sz, GFP_KERNEL);
+ if (!out)
+ return -EFAULT;
+
+ ret = func(np, name, out, n);
+ if (ret)
+ goto out;
+
+ if (copy_to_user(datap, out, n * sz))
+ ret = -EFAULT;
+
+out:
+ kfree(out);
+ return ret;
}
int vfio_platform_devtree_info(struct device_node *np,
--
2.1.1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-10-16 15:55 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <1413474876-28544-1-git-send-email-a.motakis@virtualopensystems.com>
2014-10-16 15:54 ` [RFC PATCH v2 1/4] vfio: platform: add device tree info API and skeleton Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 2/4] vfio: platform: devtree: return available property names Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 3/4] vfio: platform: devtree: access property as a list of strings Antonios Motakis
2014-10-16 15:54 ` [RFC PATCH v2 4/4] vfio: platform: devtree: return arrays of u32, u16, or u8 data Antonios Motakis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®