* [PATCH v7 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
The of_iommu_{set/get}_ops() API is used to associate a device
tree node with a specific set of IOMMU operations. The same
kernel interface is required on systems booting with ACPI, where
devices are not associated with a device tree node, therefore
the interface requires generalization.
The struct device fwnode member represents the fwnode token
associated with the device and the struct it points at is firmware
specific; regardless, it is initialized on both ACPI and DT systems
and makes an ideal candidate to use it to associate a set of IOMMU
operations to a given device, through its struct device.fwnode member
pointer.
Convert the DT specific of_iommu_{set/get}_ops() interface to
use struct device.fwnode as a look-up token, making the interface
usable on ACPI systems.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
drivers/iommu/iommu.c | 42 ++++++++++++++++++++++++++++++++++++++++++
drivers/iommu/of_iommu.c | 39 ---------------------------------------
include/linux/iommu.h | 14 ++++++++++++++
include/linux/of_iommu.h | 12 ++++++++++--
4 files changed, 66 insertions(+), 41 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9a2f196..5c97c01 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1615,6 +1615,48 @@ int iommu_request_dm_for_dev(struct device *dev)
return ret;
}
+struct iommu_fwentry {
+ struct list_head list;
+ struct fwnode_handle *fwnode;
+ const struct iommu_ops *ops;
+};
+static LIST_HEAD(iommu_fwentry_list);
+static DEFINE_SPINLOCK(iommu_fwentry_lock);
+
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+ struct iommu_fwentry *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+ if (WARN_ON(!iommu))
+ return;
+
+ if (is_of_node(fwnode))
+ of_node_get(to_of_node(fwnode));
+
+ INIT_LIST_HEAD(&iommu->list);
+ iommu->fwnode = fwnode;
+ iommu->ops = ops;
+ spin_lock(&iommu_fwentry_lock);
+ list_add_tail(&iommu->list, &iommu_fwentry_list);
+ spin_unlock(&iommu_fwentry_lock);
+}
+
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ struct iommu_fwentry *node;
+ const struct iommu_ops *ops = NULL;
+
+ spin_lock(&iommu_fwentry_lock);
+ list_for_each_entry(node, &iommu_fwentry_list, list)
+ if (node->fwnode == fwnode) {
+ ops = node->ops;
+ break;
+ }
+ spin_unlock(&iommu_fwentry_lock);
+ return ops;
+}
+
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops)
{
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 5b82862..0f57ddc 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,45 +96,6 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
}
EXPORT_SYMBOL_GPL(of_get_dma_window);
-struct of_iommu_node {
- struct list_head list;
- struct device_node *np;
- const struct iommu_ops *ops;
-};
-static LIST_HEAD(of_iommu_list);
-static DEFINE_SPINLOCK(of_iommu_lock);
-
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops)
-{
- struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-
- if (WARN_ON(!iommu))
- return;
-
- of_node_get(np);
- INIT_LIST_HEAD(&iommu->list);
- iommu->np = np;
- iommu->ops = ops;
- spin_lock(&of_iommu_lock);
- list_add_tail(&iommu->list, &of_iommu_list);
- spin_unlock(&of_iommu_lock);
-}
-
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
-{
- struct of_iommu_node *node;
- const struct iommu_ops *ops = NULL;
-
- spin_lock(&of_iommu_lock);
- list_for_each_entry(node, &of_iommu_list, list)
- if (node->np == np) {
- ops = node->ops;
- break;
- }
- spin_unlock(&of_iommu_lock);
- return ops;
-}
-
static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
{
struct of_phandle_args *iommu_spec = data;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 436dc21..15d5478 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops);
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops);
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode);
#else /* CONFIG_IOMMU_API */
@@ -580,6 +583,17 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
return -ENODEV;
}
+static inline void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+}
+
+static inline
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index e80b9c7..7681007 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -31,8 +31,16 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
#endif /* CONFIG_OF_IOMMU */
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+static inline void of_iommu_set_ops(struct device_node *np,
+ const struct iommu_ops *ops)
+{
+ fwnode_iommu_set_ops(&np->fwnode, ops);
+}
+
+static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
+{
+ return fwnode_iommu_get_ops(&np->fwnode);
+}
extern struct of_device_id __iommu_of_table;
--
2.10.0
^ permalink raw reply related
* [PATCH v7 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Will Deacon, Hanjun Guo, Robin Murphy,
Joerg Roedel, Marc Zyngier, Rafael J. Wysocki, Tomasz Nowicki,
Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
The of_iommu_{set/get}_ops() API is used to associate a device
tree node with a specific set of IOMMU operations. The same
kernel interface is required on systems booting with ACPI, where
devices are not associated with a device tree node, therefore
the interface requires generalization.
The struct device fwnode member represents the fwnode token
associated with the device and the struct it points at is firmware
specific; regardless, it is initialized on both ACPI and DT systems
and makes an ideal candidate to use it to associate a set of IOMMU
operations to a given device, through its struct device.fwnode member
pointer.
Convert the DT specific of_iommu_{set/get}_ops() interface to
use struct device.fwnode as a look-up token, making the interface
usable on ACPI systems.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
---
drivers/iommu/iommu.c | 42 ++++++++++++++++++++++++++++++++++++++++++
drivers/iommu/of_iommu.c | 39 ---------------------------------------
include/linux/iommu.h | 14 ++++++++++++++
include/linux/of_iommu.h | 12 ++++++++++--
4 files changed, 66 insertions(+), 41 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9a2f196..5c97c01 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1615,6 +1615,48 @@ int iommu_request_dm_for_dev(struct device *dev)
return ret;
}
+struct iommu_fwentry {
+ struct list_head list;
+ struct fwnode_handle *fwnode;
+ const struct iommu_ops *ops;
+};
+static LIST_HEAD(iommu_fwentry_list);
+static DEFINE_SPINLOCK(iommu_fwentry_lock);
+
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+ struct iommu_fwentry *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+ if (WARN_ON(!iommu))
+ return;
+
+ if (is_of_node(fwnode))
+ of_node_get(to_of_node(fwnode));
+
+ INIT_LIST_HEAD(&iommu->list);
+ iommu->fwnode = fwnode;
+ iommu->ops = ops;
+ spin_lock(&iommu_fwentry_lock);
+ list_add_tail(&iommu->list, &iommu_fwentry_list);
+ spin_unlock(&iommu_fwentry_lock);
+}
+
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ struct iommu_fwentry *node;
+ const struct iommu_ops *ops = NULL;
+
+ spin_lock(&iommu_fwentry_lock);
+ list_for_each_entry(node, &iommu_fwentry_list, list)
+ if (node->fwnode == fwnode) {
+ ops = node->ops;
+ break;
+ }
+ spin_unlock(&iommu_fwentry_lock);
+ return ops;
+}
+
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops)
{
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 5b82862..0f57ddc 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,45 +96,6 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
}
EXPORT_SYMBOL_GPL(of_get_dma_window);
-struct of_iommu_node {
- struct list_head list;
- struct device_node *np;
- const struct iommu_ops *ops;
-};
-static LIST_HEAD(of_iommu_list);
-static DEFINE_SPINLOCK(of_iommu_lock);
-
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops)
-{
- struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-
- if (WARN_ON(!iommu))
- return;
-
- of_node_get(np);
- INIT_LIST_HEAD(&iommu->list);
- iommu->np = np;
- iommu->ops = ops;
- spin_lock(&of_iommu_lock);
- list_add_tail(&iommu->list, &of_iommu_list);
- spin_unlock(&of_iommu_lock);
-}
-
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
-{
- struct of_iommu_node *node;
- const struct iommu_ops *ops = NULL;
-
- spin_lock(&of_iommu_lock);
- list_for_each_entry(node, &of_iommu_list, list)
- if (node->np == np) {
- ops = node->ops;
- break;
- }
- spin_unlock(&of_iommu_lock);
- return ops;
-}
-
static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
{
struct of_phandle_args *iommu_spec = data;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 436dc21..15d5478 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops);
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops);
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode);
#else /* CONFIG_IOMMU_API */
@@ -580,6 +583,17 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
return -ENODEV;
}
+static inline void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+}
+
+static inline
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index e80b9c7..7681007 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -31,8 +31,16 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
#endif /* CONFIG_OF_IOMMU */
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+static inline void of_iommu_set_ops(struct device_node *np,
+ const struct iommu_ops *ops)
+{
+ fwnode_iommu_set_ops(&np->fwnode, ops);
+}
+
+static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
+{
+ return fwnode_iommu_get_ops(&np->fwnode);
+}
extern struct of_device_id __iommu_of_table;
--
2.10.0
^ permalink raw reply related
* [PATCH v7 04/16] drivers: iommu: make of_iommu_set/get_ops() DT agnostic
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-acpi-u79uwXL29TY76Z2rM5mHXA, Marc Zyngier,
Rafael J. Wysocki, Will Deacon,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya, Dennis Chen,
Tomasz Nowicki, Prem Mallappa, Jon Masters
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
The of_iommu_{set/get}_ops() API is used to associate a device
tree node with a specific set of IOMMU operations. The same
kernel interface is required on systems booting with ACPI, where
devices are not associated with a device tree node, therefore
the interface requires generalization.
The struct device fwnode member represents the fwnode token
associated with the device and the struct it points at is firmware
specific; regardless, it is initialized on both ACPI and DT systems
and makes an ideal candidate to use it to associate a set of IOMMU
operations to a given device, through its struct device.fwnode member
pointer.
Convert the DT specific of_iommu_{set/get}_ops() interface to
use struct device.fwnode as a look-up token, making the interface
usable on ACPI systems.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Tested-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Tested-by: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
Cc: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
---
drivers/iommu/iommu.c | 42 ++++++++++++++++++++++++++++++++++++++++++
drivers/iommu/of_iommu.c | 39 ---------------------------------------
include/linux/iommu.h | 14 ++++++++++++++
include/linux/of_iommu.h | 12 ++++++++++--
4 files changed, 66 insertions(+), 41 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9a2f196..5c97c01 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1615,6 +1615,48 @@ int iommu_request_dm_for_dev(struct device *dev)
return ret;
}
+struct iommu_fwentry {
+ struct list_head list;
+ struct fwnode_handle *fwnode;
+ const struct iommu_ops *ops;
+};
+static LIST_HEAD(iommu_fwentry_list);
+static DEFINE_SPINLOCK(iommu_fwentry_lock);
+
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+ struct iommu_fwentry *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
+
+ if (WARN_ON(!iommu))
+ return;
+
+ if (is_of_node(fwnode))
+ of_node_get(to_of_node(fwnode));
+
+ INIT_LIST_HEAD(&iommu->list);
+ iommu->fwnode = fwnode;
+ iommu->ops = ops;
+ spin_lock(&iommu_fwentry_lock);
+ list_add_tail(&iommu->list, &iommu_fwentry_list);
+ spin_unlock(&iommu_fwentry_lock);
+}
+
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ struct iommu_fwentry *node;
+ const struct iommu_ops *ops = NULL;
+
+ spin_lock(&iommu_fwentry_lock);
+ list_for_each_entry(node, &iommu_fwentry_list, list)
+ if (node->fwnode == fwnode) {
+ ops = node->ops;
+ break;
+ }
+ spin_unlock(&iommu_fwentry_lock);
+ return ops;
+}
+
int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops)
{
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 5b82862..0f57ddc 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,45 +96,6 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
}
EXPORT_SYMBOL_GPL(of_get_dma_window);
-struct of_iommu_node {
- struct list_head list;
- struct device_node *np;
- const struct iommu_ops *ops;
-};
-static LIST_HEAD(of_iommu_list);
-static DEFINE_SPINLOCK(of_iommu_lock);
-
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops)
-{
- struct of_iommu_node *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
-
- if (WARN_ON(!iommu))
- return;
-
- of_node_get(np);
- INIT_LIST_HEAD(&iommu->list);
- iommu->np = np;
- iommu->ops = ops;
- spin_lock(&of_iommu_lock);
- list_add_tail(&iommu->list, &of_iommu_list);
- spin_unlock(&of_iommu_lock);
-}
-
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
-{
- struct of_iommu_node *node;
- const struct iommu_ops *ops = NULL;
-
- spin_lock(&of_iommu_lock);
- list_for_each_entry(node, &of_iommu_list, list)
- if (node->np == np) {
- ops = node->ops;
- break;
- }
- spin_unlock(&of_iommu_lock);
- return ops;
-}
-
static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
{
struct of_phandle_args *iommu_spec = data;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 436dc21..15d5478 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -351,6 +351,9 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
const struct iommu_ops *ops);
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops);
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode);
#else /* CONFIG_IOMMU_API */
@@ -580,6 +583,17 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,
return -ENODEV;
}
+static inline void fwnode_iommu_set_ops(struct fwnode_handle *fwnode,
+ const struct iommu_ops *ops)
+{
+}
+
+static inline
+const struct iommu_ops *fwnode_iommu_get_ops(struct fwnode_handle *fwnode)
+{
+ return NULL;
+}
+
#endif /* CONFIG_IOMMU_API */
#endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index e80b9c7..7681007 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -31,8 +31,16 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
#endif /* CONFIG_OF_IOMMU */
-void of_iommu_set_ops(struct device_node *np, const struct iommu_ops *ops);
-const struct iommu_ops *of_iommu_get_ops(struct device_node *np);
+static inline void of_iommu_set_ops(struct device_node *np,
+ const struct iommu_ops *ops)
+{
+ fwnode_iommu_set_ops(&np->fwnode, ops);
+}
+
+static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np)
+{
+ return fwnode_iommu_get_ops(&np->fwnode);
+}
extern struct of_device_id __iommu_of_table;
--
2.10.0
^ permalink raw reply related
* [PATCH v7 03/16] drivers: acpi: iort: add support for IOMMU fwnode registration
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
The ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.
This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/arm64/iort.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 2c46ebc..1ac2720 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -20,7 +20,9 @@
#include <linux/acpi_iort.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/slab.h>
struct iort_its_msi_chip {
struct list_head list;
@@ -28,6 +30,90 @@ struct iort_its_msi_chip {
u32 translation_id;
};
+struct iort_fwnode {
+ struct list_head list;
+ struct acpi_iort_node *iort_node;
+ struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ * iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ * <0 on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+ struct fwnode_handle *fwnode)
+{
+ struct iort_fwnode *np;
+
+ np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
+
+ if (WARN_ON(!np))
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&np->list);
+ np->iort_node = iort_node;
+ np->fwnode = fwnode;
+
+ spin_lock(&iort_fwnode_lock);
+ list_add_tail(&np->list, &iort_fwnode_list);
+ spin_unlock(&iort_fwnode_lock);
+
+ return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success, NULL on failure
+ */
+static inline
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr;
+ struct fwnode_handle *fwnode = NULL;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ fwnode = curr->fwnode;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+
+ return fwnode;
+}
+
+/**
+ * iort_delete_fwnode() - Delete fwnode associated with an IORT node
+ *
+ * @node: IORT table node associated with fwnode to delete
+ */
+static inline void iort_delete_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr, *tmp;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ list_del(&curr->list);
+ kfree(curr);
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+}
+
typedef acpi_status (*iort_find_node_callback)
(struct acpi_iort_node *node, void *context);
--
2.10.0
^ permalink raw reply related
* [PATCH v7 03/16] drivers: acpi: iort: add support for IOMMU fwnode registration
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
The ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.
This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/arm64/iort.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 2c46ebc..1ac2720 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -20,7 +20,9 @@
#include <linux/acpi_iort.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/slab.h>
struct iort_its_msi_chip {
struct list_head list;
@@ -28,6 +30,90 @@ struct iort_its_msi_chip {
u32 translation_id;
};
+struct iort_fwnode {
+ struct list_head list;
+ struct acpi_iort_node *iort_node;
+ struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ * iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ * <0 on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+ struct fwnode_handle *fwnode)
+{
+ struct iort_fwnode *np;
+
+ np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
+
+ if (WARN_ON(!np))
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&np->list);
+ np->iort_node = iort_node;
+ np->fwnode = fwnode;
+
+ spin_lock(&iort_fwnode_lock);
+ list_add_tail(&np->list, &iort_fwnode_list);
+ spin_unlock(&iort_fwnode_lock);
+
+ return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success, NULL on failure
+ */
+static inline
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr;
+ struct fwnode_handle *fwnode = NULL;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ fwnode = curr->fwnode;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+
+ return fwnode;
+}
+
+/**
+ * iort_delete_fwnode() - Delete fwnode associated with an IORT node
+ *
+ * @node: IORT table node associated with fwnode to delete
+ */
+static inline void iort_delete_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr, *tmp;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ list_del(&curr->list);
+ kfree(curr);
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+}
+
typedef acpi_status (*iort_find_node_callback)
(struct acpi_iort_node *node, void *context);
--
2.10.0
^ permalink raw reply related
* [PATCH v7 03/16] drivers: acpi: iort: add support for IOMMU fwnode registration
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-acpi-u79uwXL29TY76Z2rM5mHXA, Marc Zyngier, Tomasz Nowicki,
Rafael J. Wysocki, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Will Deacon, Sinan Kaya, linux-pci-u79uwXL29TY76Z2rM5mHXA,
Jon Masters, Dennis Chen, Prem Mallappa
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
The ACPI IORT table provide entries for IOMMU (aka SMMU in ARM world)
components that allow creating the kernel data structures required to
probe and initialize the IOMMU devices.
This patch provides support in the IORT kernel code to register IOMMU
components and their respective fwnode.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Reviewed-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Tested-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Tested-by: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
drivers/acpi/arm64/iort.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 2c46ebc..1ac2720 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -20,7 +20,9 @@
#include <linux/acpi_iort.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/slab.h>
struct iort_its_msi_chip {
struct list_head list;
@@ -28,6 +30,90 @@ struct iort_its_msi_chip {
u32 translation_id;
};
+struct iort_fwnode {
+ struct list_head list;
+ struct acpi_iort_node *iort_node;
+ struct fwnode_handle *fwnode;
+};
+static LIST_HEAD(iort_fwnode_list);
+static DEFINE_SPINLOCK(iort_fwnode_lock);
+
+/**
+ * iort_set_fwnode() - Create iort_fwnode and use it to register
+ * iommu data in the iort_fwnode_list
+ *
+ * @node: IORT table node associated with the IOMMU
+ * @fwnode: fwnode associated with the IORT node
+ *
+ * Returns: 0 on success
+ * <0 on failure
+ */
+static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
+ struct fwnode_handle *fwnode)
+{
+ struct iort_fwnode *np;
+
+ np = kzalloc(sizeof(struct iort_fwnode), GFP_ATOMIC);
+
+ if (WARN_ON(!np))
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&np->list);
+ np->iort_node = iort_node;
+ np->fwnode = fwnode;
+
+ spin_lock(&iort_fwnode_lock);
+ list_add_tail(&np->list, &iort_fwnode_list);
+ spin_unlock(&iort_fwnode_lock);
+
+ return 0;
+}
+
+/**
+ * iort_get_fwnode() - Retrieve fwnode associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: fwnode_handle pointer on success, NULL on failure
+ */
+static inline
+struct fwnode_handle *iort_get_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr;
+ struct fwnode_handle *fwnode = NULL;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ fwnode = curr->fwnode;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+
+ return fwnode;
+}
+
+/**
+ * iort_delete_fwnode() - Delete fwnode associated with an IORT node
+ *
+ * @node: IORT table node associated with fwnode to delete
+ */
+static inline void iort_delete_fwnode(struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr, *tmp;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry_safe(curr, tmp, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ list_del(&curr->list);
+ kfree(curr);
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+}
+
typedef acpi_status (*iort_find_node_callback)
(struct acpi_iort_node *node, void *context);
--
2.10.0
^ permalink raw reply related
* [PATCH v7 02/16] drivers: acpi: iort: introduce linker section for IORT entries probing
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).
Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.
To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.
Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/acpi/arm64/iort.c | 13 ++++++++++---
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi_iort.h | 3 +++
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 6b81746..2c46ebc 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -361,8 +361,15 @@ void __init acpi_iort_init(void)
acpi_status status;
status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- const char *msg = acpi_format_exception(status);
- pr_err("Failed to get table, %s\n", msg);
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NOT_FOUND) {
+ const char *msg = acpi_format_exception(status);
+
+ pr_err("Failed to get table, %s\n", msg);
+ }
+
+ return;
}
+
+ acpi_probe_device_table(iort);
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 3074796..f9c9f3c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -563,6 +563,7 @@
IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(clksrc) \
+ ACPI_PROBE_TABLE(iort) \
EARLYCON_TABLE()
#define INIT_TEXT \
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 0e32dac..d16fdda 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -39,4 +39,7 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
{ return NULL; }
#endif
+#define IORT_ACPI_DECLARE(name, table_id, fn) \
+ ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
#endif /* __ACPI_IORT_H__ */
--
2.10.0
^ permalink raw reply related
* [PATCH v7 02/16] drivers: acpi: iort: introduce linker section for IORT entries probing
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Tomasz Nowicki, Rafael J. Wysocki,
Marc Zyngier, Will Deacon, Robin Murphy, Joerg Roedel, Hanjun Guo,
Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
Since commit e647b532275b ("ACPI: Add early device probing
infrastructure") the kernel has gained the infrastructure that allows
adding linker script section entries to execute ACPI driver callbacks
(ie probe routines) for all subsystems that register a table entry
in the respective kernel section (eg clocksource, irqchip).
Since ARM IOMMU devices data is described through IORT tables when
booting with ACPI, the ARM IOMMU drivers must be made able to hook ACPI
callback routines that are called to probe IORT entries and initialize
the respective IOMMU devices.
To avoid adding driver specific hooks into IORT table initialization
code (breaking therefore code modularity - ie ACPI IORT code must be made
aware of ARM SMMU drivers ACPI init callbacks), this patch adds code
that allows ARM SMMU drivers to take advantage of the ACPI early probing
infrastructure, so that they can add linker script section entries
containing drivers callback to be executed on IORT tables detection.
Since IORT nodes are differentiated by a type, the callback routines
can easily parse the IORT table entries, check the IORT nodes and
carry out some actions whenever the IORT node type associated with
the driver specific callback is matched.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/acpi/arm64/iort.c | 13 ++++++++++---
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi_iort.h | 3 +++
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 6b81746..2c46ebc 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -361,8 +361,15 @@ void __init acpi_iort_init(void)
acpi_status status;
status = acpi_get_table(ACPI_SIG_IORT, 0, &iort_table);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- const char *msg = acpi_format_exception(status);
- pr_err("Failed to get table, %s\n", msg);
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NOT_FOUND) {
+ const char *msg = acpi_format_exception(status);
+
+ pr_err("Failed to get table, %s\n", msg);
+ }
+
+ return;
}
+
+ acpi_probe_device_table(iort);
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 3074796..f9c9f3c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -563,6 +563,7 @@
IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(clksrc) \
+ ACPI_PROBE_TABLE(iort) \
EARLYCON_TABLE()
#define INIT_TEXT \
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 0e32dac..d16fdda 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -39,4 +39,7 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
{ return NULL; }
#endif
+#define IORT_ACPI_DECLARE(name, table_id, fn) \
+ ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
+
#endif /* __ACPI_IORT_H__ */
--
2.10.0
^ permalink raw reply related
* [PATCH v7 01/16] drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
On systems booting with a device tree, every struct device is associated
with a struct device_node, that provides its DT firmware representation.
The device node can be used in generic kernel contexts (eg IRQ
translation, IOMMU streamid mapping), to retrieve the properties
associated with the device and carry out kernel operations accordingly.
Owing to the 1:1 relationship between the device and its device_node,
the device_node can also be used as a look-up token for the device (eg
looking up a device through its device_node), to retrieve the device in
kernel paths where the device_node is available.
On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.
The struct acpi_device, that represents firmware objects in the
ACPI namespace already includes a struct fwnode_handle of
type FWNODE_ACPI as their member; the same abstraction is missing
though for devices that are instantiated out of static ACPI tables
entries (eg ARM SMMU devices).
Add a new fwnode_handle type to associate devices created out
of static ACPI table entries to the respective firmware components
and create a simple ACPI core layer interface to dynamically allocate
and free the corresponding firmware nodes so that kernel subsystems
can use it to instantiate the nodes and associate them with the
respective devices.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
include/linux/acpi.h | 21 +++++++++++++++++++++
include/linux/fwnode.h | 3 ++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 689a8b9..6efb13c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -56,6 +56,27 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
+static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
+{
+ struct fwnode_handle *fwnode;
+
+ fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+ if (!fwnode)
+ return NULL;
+
+ fwnode->type = FWNODE_ACPI_STATIC;
+
+ return fwnode;
+}
+
+static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
+{
+ if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC))
+ return;
+
+ kfree(fwnode);
+}
+
/**
* ACPI_DEVICE_CLASS - macro used to describe an ACPI device with
* the PCI-defined class-code information
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..8bd28ce 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,8 +17,9 @@ enum fwnode_type {
FWNODE_OF,
FWNODE_ACPI,
FWNODE_ACPI_DATA,
+ FWNODE_ACPI_STATIC,
FWNODE_PDATA,
- FWNODE_IRQCHIP,
+ FWNODE_IRQCHIP
};
struct fwnode_handle {
--
2.10.0
^ permalink raw reply related
* [PATCH v7 01/16] drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-acpi-u79uwXL29TY76Z2rM5mHXA, Marc Zyngier,
Rafael J. Wysocki, Will Deacon,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya, Dennis Chen,
Tomasz Nowicki, Prem Mallappa, Jon Masters
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
On systems booting with a device tree, every struct device is associated
with a struct device_node, that provides its DT firmware representation.
The device node can be used in generic kernel contexts (eg IRQ
translation, IOMMU streamid mapping), to retrieve the properties
associated with the device and carry out kernel operations accordingly.
Owing to the 1:1 relationship between the device and its device_node,
the device_node can also be used as a look-up token for the device (eg
looking up a device through its device_node), to retrieve the device in
kernel paths where the device_node is available.
On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.
The struct acpi_device, that represents firmware objects in the
ACPI namespace already includes a struct fwnode_handle of
type FWNODE_ACPI as their member; the same abstraction is missing
though for devices that are instantiated out of static ACPI tables
entries (eg ARM SMMU devices).
Add a new fwnode_handle type to associate devices created out
of static ACPI table entries to the respective firmware components
and create a simple ACPI core layer interface to dynamically allocate
and free the corresponding firmware nodes so that kernel subsystems
can use it to instantiate the nodes and associate them with the
respective devices.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi-5wv7dgnIgG8@public.gmane.org>
Reviewed-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Tested-by: Hanjun Guo <hanjun.guo-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Tested-by: Tomasz Nowicki <tn-nYOzD4b6Jr9Wk0Htik3J/w@public.gmane.org>
Cc: "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org>
---
include/linux/acpi.h | 21 +++++++++++++++++++++
include/linux/fwnode.h | 3 ++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 689a8b9..6efb13c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -56,6 +56,27 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
+static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
+{
+ struct fwnode_handle *fwnode;
+
+ fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+ if (!fwnode)
+ return NULL;
+
+ fwnode->type = FWNODE_ACPI_STATIC;
+
+ return fwnode;
+}
+
+static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
+{
+ if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC))
+ return;
+
+ kfree(fwnode);
+}
+
/**
* ACPI_DEVICE_CLASS - macro used to describe an ACPI device with
* the PCI-defined class-code information
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..8bd28ce 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,8 +17,9 @@ enum fwnode_type {
FWNODE_OF,
FWNODE_ACPI,
FWNODE_ACPI_DATA,
+ FWNODE_ACPI_STATIC,
FWNODE_PDATA,
- FWNODE_IRQCHIP,
+ FWNODE_IRQCHIP
};
struct fwnode_handle {
--
2.10.0
^ permalink raw reply related
* [PATCH v7 00/16] ACPI IORT ARM SMMU support
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: linux-arm-kernel
This patch series is v7 of a previous posting:
https://lkml.org/lkml/2016/10/18/506
v6 -> v7
- Rebased against v4.9-rc4
- Fixed IORT probing on ACPI systems with missing IORT table
- Fixed SMMUv1/v2 global interrupt detection
- Updated iommu_ops firmware look-up
v5 -> v6
- Rebased against v4.9-rc1
- Changed FWNODE_IOMMU to FWNODE_ACPI_STATIC
- Moved platform devices creation into IORT code
- Updated fwnode handling
- Added default dma masks initialization
v4 -> v5
- Added SMMUv1/v2 support
- Rebased against v4.8-rc5 and dependencies series
- Consolidated IORT platform devices creation
v3 -> v4
- Added single mapping API (for IORT named components)
- Fixed arm_smmu_iort_xlate() return value
- Reworked fwnode registration and platform device creation
ordering to fix probe ordering dependencies
- Added code to keep device_node ref count with new iommu
fwspec API
- Added patch to make iommu_fwspec arch agnostic
- Dropped RFC status
- Rebased against v4.8-rc2
v2 -> v3
- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
- Added back reliance on ACPI early probing infrastructure
- Patch[1-3] merged through other dependent series
- Added back IOMMU fwnode generalization
- Move SMMU v3 static functions configuration to IORT code
- Implemented generic IOMMU fwspec API
- Added code to implement fwnode platform device look-up
v1 -> v2:
- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
- Removed IOMMU fwnode generalization
- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
owing to patch series dependencies [1]
- Moved platform device creation logic to IORT code to
generalize its usage for ARM SMMU v1-v2-v3 components
- Removed reliance on ACPI early device probing
- Created IORT specific iommu_xlate() translation hook leaving
OF code unchanged according to v1 reviews
The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).
http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
Building on basic IORT support, this patchset enables ARM SMMUs support
on ACPI systems.
Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.
PATCH (1) adds a FWNODE_ACPI_STATIC type to the struct fwnode_handle type.
It is required to attach a fwnode identifier to platform
devices allocated/detected through static ACPI table entries
(ie IORT tables entries).
IOMMU devices have to have an identifier to look them up
eg IOMMU core layer carrying out id translation. This can be
done through a fwnode_handle (ie IOMMU platform devices created
out of IORT tables are not ACPI devices hence they can't be
allocated as such, otherwise they would have a fwnode_handle of
type FWNODE_ACPI).
PATCH (2) makes use of the ACPI early probing API to add a linker script
section for probing devices via IORT ACPI kernel code.
PATCH (3) provides IORT support for registering IOMMU IORT node through
their fwnode handle.
PATCH (4) make of_iommu_{set/get}_ops() functions DT agnostic.
PATCH (5) convert ARM SMMU driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (6) convert ARM SMMU v3 driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (7) implements the of_dma_configure() API in ACPI world -
acpi_dma_configure() - and patches PCI and ACPI core code to
start making use of it.
PATCH (8) provides an IORT function to detect existence of specific type
of IORT components.
PATCH (9) creates the kernel infrastructure required to create ARM SMMU
platform devices for IORT nodes.
PATCH (10) refactors the ARM SMMU v3 driver so that the init functions are
split in a way that groups together code that probes through DT
and code that carries out HW registers FW agnostic probing, in
preparation for adding the ACPI probing path.
PATCH (11) adds ARM SMMU v3 IORT IOMMU operations to create and probe
ARM SMMU v3 components.
PATCH (12) refactors the ARM SMMU v1/v2 driver so that the init functions
are split in a way that groups together code that probes
through DT and code that carries out HW registers FW agnostic
probing, in preparation for adding the ACPI probing path.
PATCH (13) adds ARM SMMU v1/v2 IORT IOMMU operations to create and
probe ARM SMMU v1/v2 components.
PATCH (14) Extend the IORT iort_node_map_rid() to work on a type mask
instead of a single type so that the translation API can
be used on a range of components.
PATCH (15) Add IORT API to carry out id mappings for components that do
do not have an input identifier/RIDs (ie named components).
PATCH (16) provides IORT infrastructure to carry out IOMMU configuration
for devices and hook it up to the previously introduced ACPI
DMA configure API.
This patchset is provided for review/testing purposes here:
git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v7
Tested on Juno and FVP models for ARM SMMU v1 and v3 probing path.
Lorenzo Pieralisi (16):
drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
drivers: acpi: iort: introduce linker section for IORT entries probing
drivers: acpi: iort: add support for IOMMU fwnode registration
drivers: iommu: make of_iommu_set/get_ops() DT agnostic
drivers: iommu: arm-smmu: convert struct device of_node to fwnode
usage
drivers: iommu: arm-smmu-v3: convert struct device of_node to fwnode
usage
drivers: acpi: implement acpi_dma_configure
drivers: acpi: iort: add node match function
drivers: acpi: iort: add support for ARM SMMU platform devices
creation
drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu-v3: add IORT configuration
drivers: iommu: arm-smmu: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu: add IORT configuration
drivers: acpi: iort: replace rid map type with type mask
drivers: acpi: iort: add single mapping function
drivers: acpi: iort: introduce iort_iommu_configure
drivers/acpi/arm64/iort.c | 596 +++++++++++++++++++++++++++++++++++++-
drivers/acpi/glue.c | 4 +-
drivers/acpi/scan.c | 45 +++
drivers/iommu/arm-smmu-v3.c | 105 +++++--
drivers/iommu/arm-smmu.c | 154 ++++++++--
drivers/iommu/iommu.c | 42 +++
drivers/iommu/of_iommu.c | 39 ---
drivers/pci/probe.c | 3 +-
include/acpi/acpi_bus.h | 2 +
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi.h | 26 ++
include/linux/acpi_iort.h | 14 +
include/linux/fwnode.h | 3 +-
include/linux/iommu.h | 14 +
include/linux/of_iommu.h | 12 +-
15 files changed, 956 insertions(+), 104 deletions(-)
--
2.10.0
^ permalink raw reply
* [PATCH v7 00/16] ACPI IORT ARM SMMU support
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Will Deacon, Marc Zyngier, Robin Murphy,
Joerg Roedel, Rafael J. Wysocki, Tomasz Nowicki, Hanjun Guo,
Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
This patch series is v7 of a previous posting:
https://lkml.org/lkml/2016/10/18/506
v6 -> v7
- Rebased against v4.9-rc4
- Fixed IORT probing on ACPI systems with missing IORT table
- Fixed SMMUv1/v2 global interrupt detection
- Updated iommu_ops firmware look-up
v5 -> v6
- Rebased against v4.9-rc1
- Changed FWNODE_IOMMU to FWNODE_ACPI_STATIC
- Moved platform devices creation into IORT code
- Updated fwnode handling
- Added default dma masks initialization
v4 -> v5
- Added SMMUv1/v2 support
- Rebased against v4.8-rc5 and dependencies series
- Consolidated IORT platform devices creation
v3 -> v4
- Added single mapping API (for IORT named components)
- Fixed arm_smmu_iort_xlate() return value
- Reworked fwnode registration and platform device creation
ordering to fix probe ordering dependencies
- Added code to keep device_node ref count with new iommu
fwspec API
- Added patch to make iommu_fwspec arch agnostic
- Dropped RFC status
- Rebased against v4.8-rc2
v2 -> v3
- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
- Added back reliance on ACPI early probing infrastructure
- Patch[1-3] merged through other dependent series
- Added back IOMMU fwnode generalization
- Move SMMU v3 static functions configuration to IORT code
- Implemented generic IOMMU fwspec API
- Added code to implement fwnode platform device look-up
v1 -> v2:
- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
- Removed IOMMU fwnode generalization
- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
owing to patch series dependencies [1]
- Moved platform device creation logic to IORT code to
generalize its usage for ARM SMMU v1-v2-v3 components
- Removed reliance on ACPI early device probing
- Created IORT specific iommu_xlate() translation hook leaving
OF code unchanged according to v1 reviews
The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).
http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
Building on basic IORT support, this patchset enables ARM SMMUs support
on ACPI systems.
Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.
PATCH (1) adds a FWNODE_ACPI_STATIC type to the struct fwnode_handle type.
It is required to attach a fwnode identifier to platform
devices allocated/detected through static ACPI table entries
(ie IORT tables entries).
IOMMU devices have to have an identifier to look them up
eg IOMMU core layer carrying out id translation. This can be
done through a fwnode_handle (ie IOMMU platform devices created
out of IORT tables are not ACPI devices hence they can't be
allocated as such, otherwise they would have a fwnode_handle of
type FWNODE_ACPI).
PATCH (2) makes use of the ACPI early probing API to add a linker script
section for probing devices via IORT ACPI kernel code.
PATCH (3) provides IORT support for registering IOMMU IORT node through
their fwnode handle.
PATCH (4) make of_iommu_{set/get}_ops() functions DT agnostic.
PATCH (5) convert ARM SMMU driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (6) convert ARM SMMU v3 driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (7) implements the of_dma_configure() API in ACPI world -
acpi_dma_configure() - and patches PCI and ACPI core code to
start making use of it.
PATCH (8) provides an IORT function to detect existence of specific type
of IORT components.
PATCH (9) creates the kernel infrastructure required to create ARM SMMU
platform devices for IORT nodes.
PATCH (10) refactors the ARM SMMU v3 driver so that the init functions are
split in a way that groups together code that probes through DT
and code that carries out HW registers FW agnostic probing, in
preparation for adding the ACPI probing path.
PATCH (11) adds ARM SMMU v3 IORT IOMMU operations to create and probe
ARM SMMU v3 components.
PATCH (12) refactors the ARM SMMU v1/v2 driver so that the init functions
are split in a way that groups together code that probes
through DT and code that carries out HW registers FW agnostic
probing, in preparation for adding the ACPI probing path.
PATCH (13) adds ARM SMMU v1/v2 IORT IOMMU operations to create and
probe ARM SMMU v1/v2 components.
PATCH (14) Extend the IORT iort_node_map_rid() to work on a type mask
instead of a single type so that the translation API can
be used on a range of components.
PATCH (15) Add IORT API to carry out id mappings for components that do
do not have an input identifier/RIDs (ie named components).
PATCH (16) provides IORT infrastructure to carry out IOMMU configuration
for devices and hook it up to the previously introduced ACPI
DMA configure API.
This patchset is provided for review/testing purposes here:
git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v7
Tested on Juno and FVP models for ARM SMMU v1 and v3 probing path.
Lorenzo Pieralisi (16):
drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
drivers: acpi: iort: introduce linker section for IORT entries probing
drivers: acpi: iort: add support for IOMMU fwnode registration
drivers: iommu: make of_iommu_set/get_ops() DT agnostic
drivers: iommu: arm-smmu: convert struct device of_node to fwnode
usage
drivers: iommu: arm-smmu-v3: convert struct device of_node to fwnode
usage
drivers: acpi: implement acpi_dma_configure
drivers: acpi: iort: add node match function
drivers: acpi: iort: add support for ARM SMMU platform devices
creation
drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu-v3: add IORT configuration
drivers: iommu: arm-smmu: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu: add IORT configuration
drivers: acpi: iort: replace rid map type with type mask
drivers: acpi: iort: add single mapping function
drivers: acpi: iort: introduce iort_iommu_configure
drivers/acpi/arm64/iort.c | 596 +++++++++++++++++++++++++++++++++++++-
drivers/acpi/glue.c | 4 +-
drivers/acpi/scan.c | 45 +++
drivers/iommu/arm-smmu-v3.c | 105 +++++--
drivers/iommu/arm-smmu.c | 154 ++++++++--
drivers/iommu/iommu.c | 42 +++
drivers/iommu/of_iommu.c | 39 ---
drivers/pci/probe.c | 3 +-
include/acpi/acpi_bus.h | 2 +
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi.h | 26 ++
include/linux/acpi_iort.h | 14 +
include/linux/fwnode.h | 3 +-
include/linux/iommu.h | 14 +
include/linux/of_iommu.h | 12 +-
15 files changed, 956 insertions(+), 104 deletions(-)
--
2.10.0
^ permalink raw reply
* [PATCH v7 00/16] ACPI IORT ARM SMMU support
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-acpi-u79uwXL29TY76Z2rM5mHXA, Marc Zyngier,
Rafael J. Wysocki, Will Deacon,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-pci-u79uwXL29TY76Z2rM5mHXA, Sinan Kaya, Dennis Chen,
Tomasz Nowicki, Prem Mallappa, Jon Masters
This patch series is v7 of a previous posting:
https://lkml.org/lkml/2016/10/18/506
v6 -> v7
- Rebased against v4.9-rc4
- Fixed IORT probing on ACPI systems with missing IORT table
- Fixed SMMUv1/v2 global interrupt detection
- Updated iommu_ops firmware look-up
v5 -> v6
- Rebased against v4.9-rc1
- Changed FWNODE_IOMMU to FWNODE_ACPI_STATIC
- Moved platform devices creation into IORT code
- Updated fwnode handling
- Added default dma masks initialization
v4 -> v5
- Added SMMUv1/v2 support
- Rebased against v4.8-rc5 and dependencies series
- Consolidated IORT platform devices creation
v3 -> v4
- Added single mapping API (for IORT named components)
- Fixed arm_smmu_iort_xlate() return value
- Reworked fwnode registration and platform device creation
ordering to fix probe ordering dependencies
- Added code to keep device_node ref count with new iommu
fwspec API
- Added patch to make iommu_fwspec arch agnostic
- Dropped RFC status
- Rebased against v4.8-rc2
v2 -> v3
- Rebased on top of dependencies series [1][2][3](v4.7-rc3)
- Added back reliance on ACPI early probing infrastructure
- Patch[1-3] merged through other dependent series
- Added back IOMMU fwnode generalization
- Move SMMU v3 static functions configuration to IORT code
- Implemented generic IOMMU fwspec API
- Added code to implement fwnode platform device look-up
v1 -> v2:
- Rebased on top of dependencies series [1][2][3](v4.7-rc1)
- Removed IOMMU fwnode generalization
- Implemented ARM SMMU v3 ACPI probing instead of ARM SMMU v2
owing to patch series dependencies [1]
- Moved platform device creation logic to IORT code to
generalize its usage for ARM SMMU v1-v2-v3 components
- Removed reliance on ACPI early device probing
- Created IORT specific iommu_xlate() translation hook leaving
OF code unchanged according to v1 reviews
The ACPI IORT table provides information that allows instantiating
ARM SMMU devices and carrying out id mappings between components on
ARM based systems (devices, IOMMUs, interrupt controllers).
http://infocenter.arm.com/help/topic/com.arm.doc.den0049b/DEN0049B_IO_Remapping_Table.pdf
Building on basic IORT support, this patchset enables ARM SMMUs support
on ACPI systems.
Most of the code is aimed at building the required generic ACPI
infrastructure to create and enable IOMMU components and to bring
the IOMMU infrastructure for ACPI on par with DT, which is going to
make future ARM SMMU components easier to integrate.
PATCH (1) adds a FWNODE_ACPI_STATIC type to the struct fwnode_handle type.
It is required to attach a fwnode identifier to platform
devices allocated/detected through static ACPI table entries
(ie IORT tables entries).
IOMMU devices have to have an identifier to look them up
eg IOMMU core layer carrying out id translation. This can be
done through a fwnode_handle (ie IOMMU platform devices created
out of IORT tables are not ACPI devices hence they can't be
allocated as such, otherwise they would have a fwnode_handle of
type FWNODE_ACPI).
PATCH (2) makes use of the ACPI early probing API to add a linker script
section for probing devices via IORT ACPI kernel code.
PATCH (3) provides IORT support for registering IOMMU IORT node through
their fwnode handle.
PATCH (4) make of_iommu_{set/get}_ops() functions DT agnostic.
PATCH (5) convert ARM SMMU driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (6) convert ARM SMMU v3 driver to use fwnode instead of of_node as
look-up and iommu_ops retrieval token.
PATCH (7) implements the of_dma_configure() API in ACPI world -
acpi_dma_configure() - and patches PCI and ACPI core code to
start making use of it.
PATCH (8) provides an IORT function to detect existence of specific type
of IORT components.
PATCH (9) creates the kernel infrastructure required to create ARM SMMU
platform devices for IORT nodes.
PATCH (10) refactors the ARM SMMU v3 driver so that the init functions are
split in a way that groups together code that probes through DT
and code that carries out HW registers FW agnostic probing, in
preparation for adding the ACPI probing path.
PATCH (11) adds ARM SMMU v3 IORT IOMMU operations to create and probe
ARM SMMU v3 components.
PATCH (12) refactors the ARM SMMU v1/v2 driver so that the init functions
are split in a way that groups together code that probes
through DT and code that carries out HW registers FW agnostic
probing, in preparation for adding the ACPI probing path.
PATCH (13) adds ARM SMMU v1/v2 IORT IOMMU operations to create and
probe ARM SMMU v1/v2 components.
PATCH (14) Extend the IORT iort_node_map_rid() to work on a type mask
instead of a single type so that the translation API can
be used on a range of components.
PATCH (15) Add IORT API to carry out id mappings for components that do
do not have an input identifier/RIDs (ie named components).
PATCH (16) provides IORT infrastructure to carry out IOMMU configuration
for devices and hook it up to the previously introduced ACPI
DMA configure API.
This patchset is provided for review/testing purposes here:
git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git acpi/iort-smmu-v7
Tested on Juno and FVP models for ARM SMMU v1 and v3 probing path.
Lorenzo Pieralisi (16):
drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
drivers: acpi: iort: introduce linker section for IORT entries probing
drivers: acpi: iort: add support for IOMMU fwnode registration
drivers: iommu: make of_iommu_set/get_ops() DT agnostic
drivers: iommu: arm-smmu: convert struct device of_node to fwnode
usage
drivers: iommu: arm-smmu-v3: convert struct device of_node to fwnode
usage
drivers: acpi: implement acpi_dma_configure
drivers: acpi: iort: add node match function
drivers: acpi: iort: add support for ARM SMMU platform devices
creation
drivers: iommu: arm-smmu-v3: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu-v3: add IORT configuration
drivers: iommu: arm-smmu: split probe functions into DT/generic
portions
drivers: iommu: arm-smmu: add IORT configuration
drivers: acpi: iort: replace rid map type with type mask
drivers: acpi: iort: add single mapping function
drivers: acpi: iort: introduce iort_iommu_configure
drivers/acpi/arm64/iort.c | 596 +++++++++++++++++++++++++++++++++++++-
drivers/acpi/glue.c | 4 +-
drivers/acpi/scan.c | 45 +++
drivers/iommu/arm-smmu-v3.c | 105 +++++--
drivers/iommu/arm-smmu.c | 154 ++++++++--
drivers/iommu/iommu.c | 42 +++
drivers/iommu/of_iommu.c | 39 ---
drivers/pci/probe.c | 3 +-
include/acpi/acpi_bus.h | 2 +
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/acpi.h | 26 ++
include/linux/acpi_iort.h | 14 +
include/linux/fwnode.h | 3 +-
include/linux/iommu.h | 14 +
include/linux/of_iommu.h | 12 +-
15 files changed, 956 insertions(+), 104 deletions(-)
--
2.10.0
^ permalink raw reply
* [PATCH v7 08/16] drivers: acpi: iort: add node match function
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Hanjun Guo, Tomasz Nowicki, Rafael J. Wysocki,
Will Deacon, Marc Zyngier, Robin Murphy, Joerg Roedel,
Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
Device drivers (eg ARM SMMU) need to know if a specific component
is part of the IORT table, so that kernel data structures are not
initialized at initcalls time if the respective component is not
part of the IORT table.
To this end, this patch adds a trivial function that allows detecting
if a given IORT node type is present or not in the ACPI table, providing
an ACPI IORT equivalent for of_find_matching_node().
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/arm64/iort.c | 15 +++++++++++++++
include/linux/acpi_iort.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 1ac2720..4bb6acb 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -227,6 +227,21 @@ static struct acpi_iort_node *iort_scan_node(enum acpi_iort_node_type type,
return NULL;
}
+static acpi_status
+iort_match_type_callback(struct acpi_iort_node *node, void *context)
+{
+ return AE_OK;
+}
+
+bool iort_node_match(u8 type)
+{
+ struct acpi_iort_node *node;
+
+ node = iort_scan_node(type, iort_match_type_callback, NULL);
+
+ return node != NULL;
+}
+
static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
void *context)
{
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index d16fdda..17bb078 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -28,10 +28,12 @@ void iort_deregister_domain_token(int trans_id);
struct fwnode_handle *iort_find_domain_token(int trans_id);
#ifdef CONFIG_ACPI_IORT
void acpi_iort_init(void);
+bool iort_node_match(u8 type);
u32 iort_msi_map_rid(struct device *dev, u32 req_id);
struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
#else
static inline void acpi_iort_init(void) { }
+static inline bool iort_node_match(u8 type) { return false; }
static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
{ return req_id; }
static inline struct irq_domain *iort_get_device_domain(struct device *dev,
--
2.10.0
^ permalink raw reply related
* [PATCH v7 07/16] drivers: acpi: implement acpi_dma_configure
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Bjorn Helgaas, Robin Murphy, Tomasz Nowicki,
Joerg Roedel, Rafael J. Wysocki, Will Deacon, Marc Zyngier,
Hanjun Guo, Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
On DT based systems, the of_dma_configure() API implements DMA
configuration for a given device. On ACPI systems an API equivalent to
of_dma_configure() is missing which implies that it is currently not
possible to set-up DMA operations for devices through the ACPI generic
kernel layer.
This patch fills the gap by introducing acpi_dma_configure/deconfigure()
calls that for now are just wrappers around arch_setup_dma_ops() and
arch_teardown_dma_ops() and also updates ACPI and PCI core code to use
the newly introduced acpi_dma_configure/acpi_dma_deconfigure functions.
Since acpi_dma_configure() is used to configure DMA operations, the
function initializes the dma/coherent_dma masks to sane default values
if the current masks are uninitialized (also to keep the default values
consistent with DT systems) to make sure the device has a complete
default DMA set-up.
The DMA range size passed to arch_setup_dma_ops() is sized according
to the device coherent_dma_mask (starting at address 0x0), mirroring the
DT probing path behaviour when a dma-ranges property is not provided
for the device being probed; this changes the current arch_setup_dma_ops()
call parameters in the ACPI probing case, but since arch_setup_dma_ops()
is a NOP on all architectures but ARM/ARM64 this patch does not change
the current kernel behaviour on them.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com> [pci]
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Tomasz Nowicki <tn@semihalf.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
drivers/acpi/glue.c | 4 ++--
drivers/acpi/scan.c | 40 ++++++++++++++++++++++++++++++++++++++++
drivers/pci/probe.c | 3 +--
include/acpi/acpi_bus.h | 2 ++
include/linux/acpi.h | 5 +++++
5 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 5ea5dc2..f8d6564 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -227,8 +227,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
attr = acpi_get_dma_attr(acpi_dev);
if (attr != DEV_DMA_NOT_SUPPORTED)
- arch_setup_dma_ops(dev, 0, 0, NULL,
- attr == DEV_DMA_COHERENT);
+ acpi_dma_configure(dev, attr);
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
@@ -251,6 +250,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
return 0;
err:
+ acpi_dma_deconfigure(dev);
ACPI_COMPANION_SET(dev, NULL);
put_device(dev);
put_device(&acpi_dev->dev);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 035ac64..694e0b6 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1370,6 +1370,46 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
return DEV_DMA_NON_COHERENT;
}
+/**
+ * acpi_dma_configure - Set-up DMA configuration for the device.
+ * @dev: The pointer to the device
+ * @attr: device dma attributes
+ */
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+{
+ /*
+ * Set default coherent_dma_mask to 32 bit. Drivers are expected to
+ * setup the correct supported mask.
+ */
+ if (!dev->coherent_dma_mask)
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ /*
+ * Set it to coherent_dma_mask by default if the architecture
+ * code has not set it.
+ */
+ if (!dev->dma_mask)
+ dev->dma_mask = &dev->coherent_dma_mask;
+
+ /*
+ * Assume dma valid range starts at 0 and covers the whole
+ * coherent_dma_mask.
+ */
+ arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, NULL,
+ attr == DEV_DMA_COHERENT);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_configure);
+
+/**
+ * acpi_dma_deconfigure - Tear-down DMA configuration for the device.
+ * @dev: The pointer to the device
+ */
+void acpi_dma_deconfigure(struct device *dev)
+{
+ arch_teardown_dma_ops(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_dma_deconfigure);
+
static void acpi_init_coherency(struct acpi_device *adev)
{
unsigned long long cca = 0;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ab00267..c29e07a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1738,8 +1738,7 @@ static void pci_dma_configure(struct pci_dev *dev)
if (attr == DEV_DMA_NOT_SUPPORTED)
dev_warn(&dev->dev, "DMA not supported.\n");
else
- arch_setup_dma_ops(&dev->dev, 0, 0, NULL,
- attr == DEV_DMA_COHERENT);
+ acpi_dma_configure(&dev->dev, attr);
}
pci_put_host_bridge_device(bridge);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index c1a524d..4242c31 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -573,6 +573,8 @@ struct acpi_pci_root {
bool acpi_dma_supported(struct acpi_device *adev);
enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
+void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
+void acpi_dma_deconfigure(struct device *dev);
struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
u64 address, bool check_children);
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 6efb13c..df961f4 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -764,6 +764,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
return DEV_DMA_NOT_SUPPORTED;
}
+static inline void acpi_dma_configure(struct device *dev,
+ enum dev_dma_attr attr) { }
+
+static inline void acpi_dma_deconfigure(struct device *dev) { }
+
#define ACPI_PTR(_ptr) (NULL)
static inline void acpi_device_set_enumerated(struct acpi_device *adev)
--
2.10.0
^ permalink raw reply related
* Re: [PATCH v4 0/4] MIPS: Remote processor driver
From: Thomas Gleixner @ 2016-11-09 14:16 UTC (permalink / raw)
To: Matt Redfearn
Cc: Ralf Baechle, Bjorn Andersson, Ohad Ben-Cohen, linux-mips,
linux-remoteproc, Lisa Parratt, LKML, Qais Yousef,
Masahiro Yamada, Paul Gortmaker, Jason Cooper, James Hogan,
Marc Zyngier, Paul Burton, Peter Zijlstra, Ingo Molnar
In-Reply-To: <b06e60b3-6175-db52-1cc8-706a4d3a04f0@imgtec.com>
On Wed, 9 Nov 2016, Matt Redfearn wrote:
> On 09/11/16 10:15, Thomas Gleixner wrote:
> > On Wed, 2 Nov 2016, Matt Redfearn wrote:
> > > The MIPS remote processor driver allows non-Linux firmware to take
> > > control of and execute on one of the systems VPEs. The CPU must be
> > > offlined from Linux first. A sysfs interface is created which allows
> > > firmware to be loaded and changed at runtime. A full description is
> > > available at [1]. An example firmware that can be used with this driver
> > > is available at [2].
> > >
> > > This is useful to allow running bare metal code, or an RTOS, on one or
> > > more CPUs while allowing Linux to continue running on those remaining.
> > And how is actually guaranteed that these two things are properly seperated
> > (memory, devices, interrupts etc.) ?
>
> Memory separation is primarily handled by the remoteproc subsystem, which will
> allocate and map memory as required by the firmware, though because the CPU is
> executing in kernel mode there is nothing preventing it accessing anything in
> the system. But that is of course the same as any root process which could do
> the same thing via /dev/mem. One must be root to offline the CPU from Linux
> and load firmware to it, so there is no greater hazard to the system than that
> firmware running as a root process within userland.
Oh yes, there is. You can deny access to /dev/mem even for root, which is a
sensible thing to do. And even a process running as root has restrictions
which the kernel can enforce.
> Separation of devices and interrupts is a system design issue, as this feature
> will find use in embedded systems where the system will be partitioned into
> Linux and bare metal components. This is done where there are requirements
> such as needing to run real time code as well as Linux, or enforce separation
> through firmware binaries running separately to Linux.
> This would be useful, for example, for a modem driver running as bare metal
> code within one of the system VPEs and providing a virtio-net interface to the
> kernel. There would be no kernel driver present for such a device, therefore
> there would be no resource conflicts.
In theory.
> There only different thing about the MIPS implementation of remoteproc is that
> it turns one of the general purpose Linux CPUs into a remote processor, rather
> than there being a separate remote CPU within the SoC, as is the case with
> most remoteproc drivers. But unless there is some form of MMU between that CPU
> and the system bus, then it will have the same ability to access all system
> resources as is the case with this driver.
That's true, but that's a design issue on the SoC level where we cannot do
anything about.
> Again I don't think there is any greater risk to the system here as
> there would be with any other remoteproc based system.
Well. The whole thing is just a proliferation of a really bad mechanism,
which was rejected several times in the past. Surely MIPS as being MIPS has
this mechanism already, but that does not make it any better.
> There is already a mechanism to do this in the upstream MIPS kernel - the VPE
> loader, which has been there 2005 (commit
> e01402b115cccb6357f956649487aca2c6f7fbba). One user of the VPE loader was
> Lantiq, who used it to load a proprietary modem driver, for which there is no
> GPL driver.
> What we are proposing here is to move from that MIPS specific mechanism of
> running bare metal code to the standardized remoteproc subsystem such that
> people wanting to design a MIPS based system with both real time firmware and
> general Linux processing tasks may do so using standardized kernel interfaces.
Again, you should either use NOHZ_FULL (and you can implement a proprietary
user space driver w/o using /dev/mem) or seperate the CPUs in the boot
loader already and have some tiny piece of firmware which lets you load the
real firmware blob and control it. Ideally you use hw-virtualization, but
in absence of that you can do a halfways sane paritioning w/o abusing CPU
hotplug for this.
Thanks,
tglx
^ permalink raw reply
* Re: master branch merges must pass unit tests
From: Sage Weil @ 2016-11-09 14:19 UTC (permalink / raw)
To: Igor Fedotov; +Cc: ceph-devel
In-Reply-To: <61b91df6-3c19-65da-05c5-6f9cfb5cdbae@mirantis.com>
On Wed, 9 Nov 2016, Igor Fedotov wrote:
> Sage,
>
> looks like you made even stronger restrictions.
>
> I'm unable to merge https://github.com/ceph/ceph/pull/11823 after approving
> the changes.
That's strange. I merged this one.. next time it happens, can you do a
screen cap and we can figure out why it's doing it?
sage
^ permalink raw reply
* [PATCH v7 01/16] drivers: acpi: add FWNODE_ACPI_STATIC fwnode type
From: Lorenzo Pieralisi @ 2016-11-09 14:19 UTC (permalink / raw)
To: iommu
Cc: Lorenzo Pieralisi, Rafael J. Wysocki, Will Deacon, Marc Zyngier,
Robin Murphy, Joerg Roedel, Tomasz Nowicki, Hanjun Guo,
Jon Masters, Eric Auger, Sinan Kaya, Nate Watterson,
Prem Mallappa, Dennis Chen, linux-acpi, linux-pci, linux-kernel,
linux-arm-kernel
In-Reply-To: <20161109141948.19244-1-lorenzo.pieralisi@arm.com>
On systems booting with a device tree, every struct device is associated
with a struct device_node, that provides its DT firmware representation.
The device node can be used in generic kernel contexts (eg IRQ
translation, IOMMU streamid mapping), to retrieve the properties
associated with the device and carry out kernel operations accordingly.
Owing to the 1:1 relationship between the device and its device_node,
the device_node can also be used as a look-up token for the device (eg
looking up a device through its device_node), to retrieve the device in
kernel paths where the device_node is available.
On systems booting with ACPI, the same abstraction provided by
the device_node is required to provide look-up functionality.
The struct acpi_device, that represents firmware objects in the
ACPI namespace already includes a struct fwnode_handle of
type FWNODE_ACPI as their member; the same abstraction is missing
though for devices that are instantiated out of static ACPI tables
entries (eg ARM SMMU devices).
Add a new fwnode_handle type to associate devices created out
of static ACPI table entries to the respective firmware components
and create a simple ACPI core layer interface to dynamically allocate
and free the corresponding firmware nodes so that kernel subsystems
can use it to instantiate the nodes and associate them with the
respective devices.
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Hanjun Guo <hanjun.guo@linaro.org>
Tested-by: Tomasz Nowicki <tn@semihalf.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
include/linux/acpi.h | 21 +++++++++++++++++++++
include/linux/fwnode.h | 3 ++-
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 689a8b9..6efb13c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -56,6 +56,27 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
acpi_fwnode_handle(adev) : NULL)
#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
+static inline struct fwnode_handle *acpi_alloc_fwnode_static(void)
+{
+ struct fwnode_handle *fwnode;
+
+ fwnode = kzalloc(sizeof(struct fwnode_handle), GFP_KERNEL);
+ if (!fwnode)
+ return NULL;
+
+ fwnode->type = FWNODE_ACPI_STATIC;
+
+ return fwnode;
+}
+
+static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode)
+{
+ if (WARN_ON(!fwnode || fwnode->type != FWNODE_ACPI_STATIC))
+ return;
+
+ kfree(fwnode);
+}
+
/**
* ACPI_DEVICE_CLASS - macro used to describe an ACPI device with
* the PCI-defined class-code information
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 8516717..8bd28ce 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -17,8 +17,9 @@ enum fwnode_type {
FWNODE_OF,
FWNODE_ACPI,
FWNODE_ACPI_DATA,
+ FWNODE_ACPI_STATIC,
FWNODE_PDATA,
- FWNODE_IRQCHIP,
+ FWNODE_IRQCHIP
};
struct fwnode_handle {
--
2.10.0
^ permalink raw reply related
* [PATCH] pinctrl: single: check for any error when getting rows
From: Axel Haslam @ 2016-11-09 14:17 UTC (permalink / raw)
To: tony, haojian.zhuang, linus.walleij, khilman, nsekhar
Cc: linux-arm-kernel, linux-omap, linux-gpio, linux-kernel,
Axel Haslam
pinctrl_count_index_with_args returns -ENOENT not
-EINVAL. The return check would pass, and we would
try to kzalloc with a negative error size throwing
a warning.
Instead of checking for -EINVAL specifically, lets
check for any error and avoid negative size allocations.
Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
---
drivers/pinctrl/pinctrl-single.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 539f31c..56e22be 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1228,7 +1228,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
struct pcs_function *function;
rows = pinctrl_count_index_with_args(np, name);
- if (rows == -EINVAL)
+ if (rows < 0)
return rows;
npins_in_row = pcs->width / pcs->bits_per_pin;
--
2.10.1
^ permalink raw reply related
* [PATCH] pinctrl: single: check for any error when getting rows
From: Axel Haslam @ 2016-11-09 14:17 UTC (permalink / raw)
To: linux-arm-kernel
pinctrl_count_index_with_args returns -ENOENT not
-EINVAL. The return check would pass, and we would
try to kzalloc with a negative error size throwing
a warning.
Instead of checking for -EINVAL specifically, lets
check for any error and avoid negative size allocations.
Signed-off-by: Axel Haslam <ahaslam@baylibre.com>
---
drivers/pinctrl/pinctrl-single.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 539f31c..56e22be 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1228,7 +1228,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
struct pcs_function *function;
rows = pinctrl_count_index_with_args(np, name);
- if (rows == -EINVAL)
+ if (rows < 0)
return rows;
npins_in_row = pcs->width / pcs->bits_per_pin;
--
2.10.1
^ permalink raw reply related
* Re: [PATCH 1/2] iio: bmi160: Support hardware fifo
From: Marcin Niestroj @ 2016-11-09 14:16 UTC (permalink / raw)
To: Peter Meerwald-Stadler
Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
Daniel Baluta, Gregor Boirie, Sanchayan Maity, Rob Herring,
linux-iio
In-Reply-To: <alpine.DEB.2.02.1611031252480.11256@pmeerw.net>
Hi,
Thanks for review, below are my comments.
On 03.11.2016 13:09, Peter Meerwald-Stadler wrote:
>
>> This patch was developed primarily based on bmc150_accel hardware fifo
>> implementation.
>
> parts of the patch are cleanup and bugfixing; should be separate?
>
> more comments below
>
>> IRQ handler was added, which for now is responsible only for handling
>> watermark interrupts. The BMI160 chip has two interrupt outputs. By
>> default INT is considered to be connected. If INT2 is used instead, the
>> interrupt-names device-tree property can be used to specify that.
>>
>> Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
>> ---
>> drivers/iio/imu/bmi160/bmi160.h | 3 +-
>> drivers/iio/imu/bmi160/bmi160_core.c | 633 +++++++++++++++++++++++++++++++++--
>> drivers/iio/imu/bmi160/bmi160_i2c.c | 7 +-
>> drivers/iio/imu/bmi160/bmi160_spi.c | 3 +-
>> 4 files changed, 618 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/iio/imu/bmi160/bmi160.h b/drivers/iio/imu/bmi160/bmi160.h
>> index d2ae6ed..4a7c10e 100644
>> --- a/drivers/iio/imu/bmi160/bmi160.h
>> +++ b/drivers/iio/imu/bmi160/bmi160.h
>> @@ -4,7 +4,8 @@
>> extern const struct regmap_config bmi160_regmap_config;
>>
>> int bmi160_core_probe(struct device *dev, struct regmap *regmap,
>> - const char *name, bool use_spi);
>> + const char *name, int irq,
>> + bool use_spi, bool block_supported);
>> void bmi160_core_remove(struct device *dev);
>>
>> #endif /* BMI160_H_ */
>> diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
>> index e0251b8..153734c 100644
>> --- a/drivers/iio/imu/bmi160/bmi160_core.c
>> +++ b/drivers/iio/imu/bmi160/bmi160_core.c
>> @@ -2,6 +2,7 @@
>> * BMI160 - Bosch IMU (accel, gyro plus external magnetometer)
>> *
>> * Copyright (c) 2016, Intel Corporation.
>> + * Copyright (c) 2016, Grinn
>> *
>> * This file is subject to the terms and conditions of version 2 of
>> * the GNU General Public License. See the file COPYING in the main
>> @@ -9,7 +10,7 @@
>> *
>> * IIO core driver for BMI160, with support for I2C/SPI busses
>> *
>> - * TODO: magnetometer, interrupts, hardware FIFO
>> + * TODO: magnetometer, interrupts
>> */
>> #include <linux/module.h>
>> #include <linux/regmap.h>
>> @@ -22,8 +23,12 @@
>> #include <linux/iio/buffer.h>
>> #include <linux/iio/sysfs.h>
>>
>> +#include <linux/of_irq.h>
>> +
>> #include "bmi160.h"
>>
>> +#define BMI160_IRQ_NAME "bmi160_event"
>> +
>> #define BMI160_REG_CHIP_ID 0x00
>> #define BMI160_CHIP_ID_VAL 0xD1
>>
>> @@ -34,6 +39,21 @@
>> #define BMI160_REG_DATA_GYRO_XOUT_L 0x0C
>> #define BMI160_REG_DATA_ACCEL_XOUT_L 0x12
>>
>> +#define BMI160_REG_STATUS 0x1B
>> +#define BMI160_STATUS_MAG_MAN_OP BIT(2)
>> +
>> +#define BMI160_REG_INT_STATUS0 0x1C
>> +
>> +#define BMI160_REG_INT_STATUS1 0x1D
>> +#define BMI160_INT_STATUS_FWM BIT(6)
>> +
>> +#define BMI160_REG_INT_STATUS2 0x1E
>> +
>> +#define BMI160_REG_INT_STATUS3 0x1F
>> +
>> +#define BMI160_REG_FIFO_LENGTH 0x22
>> +#define BMI160_REG_FIFO_DATA 0x24
>> +
>> #define BMI160_REG_ACCEL_CONFIG 0x40
>> #define BMI160_ACCEL_CONFIG_ODR_MASK GENMASK(3, 0)
>> #define BMI160_ACCEL_CONFIG_BWP_MASK GENMASK(6, 4)
>> @@ -55,6 +75,36 @@
>> #define BMI160_GYRO_RANGE_250DPS 0x03
>> #define BMI160_GYRO_RANGE_125DPS 0x04
>>
>> +#define BMI160_REG_FIFO_CONFIG_0 0x46
>> +
>> +#define BMI160_REG_FIFO_CONFIG_1 0x47
>> +#define BMI160_FIFO_GYRO_EN BIT(7)
>> +#define BMI160_FIFO_ACCEL_EN BIT(6)
>> +#define BMI160_FIFO_MAGN_EN BIT(5)
>> +#define BMI160_FIFO_HEADER_EN BIT(4)
>> +#define BMI160_FIFO_TAG_INT1_EN BIT(3)
>> +#define BMI160_FIFO_TAG_INT2_EN BIT(2)
>> +#define BMI160_FIFO_TIME_EN BIT(1)
>> +
>> +#define BMI160_REG_INT_EN_1 0x51
>> +#define BMI160_INT_FWM_EN BIT(6)
>> +#define BMI160_INT_FFULL_EN BIT(5)
>> +#define BMI160_INT_DRDY_EN BIT(4)
>> +
>> +#define BMI160_REG_INT_OUT_CTRL 0x53
>> +#define BMI160_INT2_OUTPUT_EN BIT(7)
>> +#define BMI160_INT1_OUTPUT_EN BIT(3)
>> +
>> +#define BMI160_REG_INT_LATCH 0x54
>> +
>> +#define BMI160_REG_INT_MAP_1 0x56
>> +#define BMI160_INT1_MAP_DRDY BIT(7)
>> +#define BMI160_INT1_MAP_FWM BIT(6)
>> +#define BMI160_INT1_MAP_FFULL BIT(5)
>> +#define BMI160_INT2_MAP_DRDY BIT(3)
>> +#define BMI160_INT2_MAP_FWM BIT(2)
>> +#define BMI160_INT2_MAP_FFULL BIT(1)
>> +
>> #define BMI160_REG_CMD 0x7E
>> #define BMI160_CMD_ACCEL_PM_SUSPEND 0x10
>> #define BMI160_CMD_ACCEL_PM_NORMAL 0x11
>> @@ -66,6 +116,8 @@
>>
>> #define BMI160_REG_DUMMY 0x7F
>>
>> +#define BMI160_FIFO_LENGTH 1024
>> +
>> #define BMI160_ACCEL_PMU_MIN_USLEEP 3200
>> #define BMI160_ACCEL_PMU_MAX_USLEEP 3800
>> #define BMI160_GYRO_PMU_MIN_USLEEP 55000
>> @@ -110,8 +162,33 @@ enum bmi160_sensor_type {
>> BMI160_NUM_SENSORS /* must be last */
>> };
>>
>> +struct bmi160_irq_data {
>> + unsigned int map_fwm;
>> + unsigned int output_en;
>> +};
>> +
>> +static const struct bmi160_irq_data bmi160_irq1_data = {
>> + .map_fwm = BMI160_INT1_MAP_FWM,
>> + .output_en = BMI160_INT1_OUTPUT_EN,
>> +};
>> +
>> +static const struct bmi160_irq_data bmi160_irq2_data = {
>> + .map_fwm = BMI160_INT2_MAP_FWM,
>> + .output_en = BMI160_INT2_OUTPUT_EN,
>> +};
>> +
>> struct bmi160_data {
>> struct regmap *regmap;
>> + struct mutex mutex;
>> + const struct bmi160_irq_data *irq_data;
>> + int irq;
>> + int64_t timestamp;
>> + int64_t fifo_sample_period;
>> + bool fifo_enabled;
>> + unsigned int fifo_config;
>> + unsigned int fifo_sample_size;
>> + u8 *fifo_buffer;
>> + unsigned int watermark;
>> };
>>
>> const struct regmap_config bmi160_regmap_config = {
>> @@ -159,11 +236,11 @@ struct bmi160_pmu_time {
>> static struct bmi160_pmu_time bmi160_pmu_time[] = {
>> [BMI160_ACCEL] = {
>> .min = BMI160_ACCEL_PMU_MIN_USLEEP,
>> - .max = BMI160_ACCEL_PMU_MAX_USLEEP
>> + .max = BMI160_ACCEL_PMU_MAX_USLEEP,
>
> this is cosmetic cleanup
>
>> },
>> [BMI160_GYRO] = {
>> .min = BMI160_GYRO_PMU_MIN_USLEEP,
>> - .max = BMI160_GYRO_PMU_MIN_USLEEP,
>
> this looks like bug fixing
I agree this should be a separate patch.
I looked more deeply into the datasheet (2.11.38 Register 0x7E CMD).
What we have specified in code as MIN value is in datasheet specified as
typical time the command is executed. MAX value in the code corresponds
to datasheet's maximum time the command takes place.
According to that I think we should wait *at least* the maximum time
specified in datasheet. Please correct me if I am wrong.
>
>> + .max = BMI160_GYRO_PMU_MAX_USLEEP,
>> },
>> };
>>
>> @@ -285,7 +362,9 @@ int bmi160_set_mode(struct bmi160_data *data, enum bmi160_sensor_type t,
>> else
>> cmd = bmi160_regs[t].pmu_cmd_suspend;
>>
>> + mutex_lock(&data->mutex);
>
> what does the mutex protect?
> is it also needed without the fifo/irq support?
> probably split out as a separate patch
It protects data transmission on regmap_* functions. They are used from
sysfs access functions as well as from bmi160_trigger_handler. I will
create a separate bugfix patch for it.
Additionally fifo_enabled and fifo_buffer are protected by mutex, after
adding fifo support.
>
>> ret = regmap_write(data->regmap, BMI160_REG_CMD, cmd);
>> + mutex_unlock(&data->mutex);
>> if (ret < 0)
>> return ret;
>>
>> @@ -298,6 +377,7 @@ static
>> int bmi160_set_scale(struct bmi160_data *data, enum bmi160_sensor_type t,
>> int uscale)
>> {
>> + int ret;
>> int i;
>>
>> for (i = 0; i < bmi160_scale_table[t].num; i++)
>> @@ -307,8 +387,12 @@ int bmi160_set_scale(struct bmi160_data *data, enum bmi160_sensor_type t,
>> if (i == bmi160_scale_table[t].num)
>> return -EINVAL;
>>
>> - return regmap_write(data->regmap, bmi160_regs[t].range,
>> - bmi160_scale_table[t].tbl[i].bits);
>> + mutex_lock(&data->mutex);
>> + ret = regmap_write(data->regmap, bmi160_regs[t].range,
>> + bmi160_scale_table[t].tbl[i].bits);
>> + mutex_unlock(&data->mutex);
>> +
>> + return ret;
>> }
>>
>> static
>> @@ -317,7 +401,9 @@ int bmi160_get_scale(struct bmi160_data *data, enum bmi160_sensor_type t,
>> {
>> int i, ret, val;
>>
>> + mutex_lock(&data->mutex);
>> ret = regmap_read(data->regmap, bmi160_regs[t].range, &val);
>> + mutex_unlock(&data->mutex);
>> if (ret < 0)
>> return ret;
>>
>> @@ -340,7 +426,9 @@ static int bmi160_get_data(struct bmi160_data *data, int chan_type,
>>
>> reg = bmi160_regs[t].data + (axis - IIO_MOD_X) * sizeof(__le16);
>>
>> + mutex_lock(&data->mutex);
>> ret = regmap_bulk_read(data->regmap, reg, &sample, sizeof(__le16));
>> + mutex_unlock(&data->mutex);
>> if (ret < 0)
>> return ret;
>>
>> @@ -353,6 +441,7 @@ static
>> int bmi160_set_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
>> int odr, int uodr)
>> {
>> + int ret;
>> int i;
>>
>> for (i = 0; i < bmi160_odr_table[t].num; i++)
>> @@ -363,20 +452,30 @@ int bmi160_set_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
>> if (i >= bmi160_odr_table[t].num)
>> return -EINVAL;
>>
>> - return regmap_update_bits(data->regmap,
>> - bmi160_regs[t].config,
>> - bmi160_regs[t].config_odr_mask,
>> - bmi160_odr_table[t].tbl[i].bits);
>> + mutex_lock(&data->mutex);
>> + ret = regmap_update_bits(data->regmap,
>> + bmi160_regs[t].config,
>> + bmi160_regs[t].config_odr_mask,
>> + bmi160_odr_table[t].tbl[i].bits);
>> + mutex_unlock(&data->mutex);
>> +
>> + return ret;
>> }
>>
>> -static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
>> - int *odr, int *uodr)
>> +static int64_t bmi160_frequency_to_period(int odr, int uodr)
>> {
>> - int i, val, ret;
>> + uint64_t period = 1000000000000000;
>> + int64_t frequency = (int64_t) odr * 1000000 + uodr;
>>
>> - ret = regmap_read(data->regmap, bmi160_regs[t].config, &val);
>> - if (ret < 0)
>> - return ret;
>> + do_div(period, frequency);
>> +
>> + return period;
>> +}
>> +
>> +static const struct bmi160_odr *bmi160_reg_to_odr(enum bmi160_sensor_type t,
>> + unsigned int val)
>> +{
>> + int i;
>>
>> val &= bmi160_regs[t].config_odr_mask;
>>
>> @@ -385,10 +484,52 @@ static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
>> break;
>>
>> if (i >= bmi160_odr_table[t].num)
>> - return -EINVAL;
>> + return ERR_PTR(-EINVAL);
>> +
>> + return &bmi160_odr_table[t].tbl[i];
>> +}
>> +
>> +static int bmi160_get_sample_period(struct bmi160_data *data,
>> + enum bmi160_sensor_type t,
>> + int64_t *sample_period)
>> +{
>> + const struct bmi160_odr *odr_entry;
>> + int ret;
>> + unsigned int val;
>> +
>
> no mutex here?
This function should be called when mutex is already acquired. Should be
propably renamed to __bmi160_*.
>
>> + ret = regmap_read(data->regmap, bmi160_regs[t].config, &val);
>> + if (ret < 0)
>> + return ret;
>>
>> - *odr = bmi160_odr_table[t].tbl[i].odr;
>> - *uodr = bmi160_odr_table[t].tbl[i].uodr;
>> + odr_entry = bmi160_reg_to_odr(t, val);
>> + if (IS_ERR(odr_entry))
>> + return PTR_ERR(odr_entry);
>> +
>> + *sample_period = bmi160_frequency_to_period(odr_entry->odr,
>> + odr_entry->uodr);
>> +
>> + return 0;
>> +}
>> +
>> +static int bmi160_get_odr(struct bmi160_data *data, enum bmi160_sensor_type t,
>> + int *odr, int *uodr)
>> +{
>> + const struct bmi160_odr *odr_entry;
>> + int ret;
>> + unsigned int val;
>> +
>> + mutex_lock(&data->mutex);
>> + ret = regmap_read(data->regmap, bmi160_regs[t].config, &val);
>> + mutex_unlock(&data->mutex);
>> + if (ret < 0)
>> + return ret;
>> +
>> + odr_entry = bmi160_reg_to_odr(t, val);
>> + if (IS_ERR(odr_entry))
>> + return PTR_ERR(odr_entry);
>> +
>> + *odr = odr_entry->odr;
>> + *uodr = odr_entry->uodr;
>>
>> return 0;
>> }
>> @@ -402,14 +543,18 @@ static irqreturn_t bmi160_trigger_handler(int irq, void *p)
>> int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L;
>> __le16 sample;
>>
>> + mutex_lock(&data->mutex);
>> for_each_set_bit(i, indio_dev->active_scan_mask,
>> indio_dev->masklength) {
>> ret = regmap_bulk_read(data->regmap, base + i * sizeof(__le16),
>> &sample, sizeof(__le16));
>> - if (ret < 0)
>> + if (ret < 0) {
>> + mutex_unlock(&data->mutex);
>> goto done;
>> + }
>> buf[j++] = sample;
>> }
>> + mutex_unlock(&data->mutex);
>>
>> iio_push_to_buffers_with_timestamp(indio_dev, buf,
>> iio_get_time_ns(indio_dev));
>> @@ -493,11 +638,364 @@ static const struct attribute_group bmi160_attrs_group = {
>> .attrs = bmi160_attrs,
>> };
>>
>> +static int bmi160_update_sample_period(struct bmi160_data *data,
>> + enum bmi160_sensor_type sensor_type)
>> +{
>> + struct device *dev = regmap_get_device(data->regmap);
>> + int64_t sample_period;
>> + int ret;
>> +
>> + ret = bmi160_get_sample_period(data, sensor_type, &sample_period);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (data->fifo_sample_period) {
>> + if (data->fifo_sample_period != sample_period) {
>> + dev_warn(dev, "Enabled sensors have unequal ODR values\n");
>> + return -EINVAL;
>> + }
>> + } else {
>> + data->fifo_sample_period = sample_period;
>
> brackets not needed
Sure.
>
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int bmi160_fifo_enable(struct iio_dev *indio_dev,
>> + struct bmi160_data *data)
>> +{
>> + struct regmap *regmap = data->regmap;
>> + struct device *dev = regmap_get_device(regmap);
>> + int ret;
>> + int i;
>> + unsigned int val;
>> + unsigned int fifo_config = 0;
>> +
>> + /* Set fifo sample size and period */
>> + for_each_set_bit(i, indio_dev->active_scan_mask,
>> + indio_dev->masklength) {
>> + if (i <= BMI160_SCAN_GYRO_Z)
>> + fifo_config |= BMI160_FIFO_GYRO_EN;
>> + else if (i <= BMI160_SCAN_ACCEL_Z)
>> + fifo_config |= BMI160_FIFO_ACCEL_EN;
>> + }
>> +
>> + data->fifo_sample_period = 0;
>> + data->fifo_sample_size = 0;
>> + if (fifo_config & BMI160_FIFO_GYRO_EN) {
>> + data->fifo_sample_size += 6;
>> + ret = bmi160_update_sample_period(data, BMI160_GYRO);
>> + if (ret < 0)
>> + return ret;
>> + }
>> + if (fifo_config & BMI160_FIFO_ACCEL_EN) {
>> + data->fifo_sample_size += 6;
>> + ret = bmi160_update_sample_period(data, BMI160_ACCEL);
>> + if (ret < 0)
>> + return ret;
>> + }
>> +
>> + /*
>> + * Set watermark level and write real value back, as it will be used
>> + * in timestamp calculation.
>> + */
>> + val = data->watermark * data->fifo_sample_size;
>> + if (val > BMI160_FIFO_LENGTH - 1) {
>> + val = BMI160_FIFO_LENGTH - 1;
>> + data->watermark = val / data->fifo_sample_size;
>> + }
>> + val = data->watermark * data->fifo_sample_size / 4;
>> +
>> + ret = regmap_write(regmap, BMI160_REG_FIFO_CONFIG_0, val);
>> + if (ret < 0) {
>> + dev_err(dev, "Failed to set watermark\n");
>> + return ret;
>> + }
>> +
>> + /* Enable FIFO channels */
>> + ret = regmap_write(regmap, BMI160_REG_FIFO_CONFIG_1,
>> + fifo_config);
>> + if (ret < 0) {
>> + dev_err(dev, "Failed to write FIFO_CONFIG_1\n");
>> + return ret;
>> + }
>> +
>> + data->fifo_config = fifo_config;
>> + data->fifo_enabled = true;
>> +
>> + return 0;
>> +}
>> +
>> +static int bmi160_fifo_disable(struct bmi160_data *data)
>> +{
>> + struct regmap *regmap = data->regmap;
>> + struct device *dev = regmap_get_device(regmap);
>> + int ret;
>> +
>> + /* Disable all FIFO channels */
>> + ret = regmap_write(regmap, BMI160_REG_FIFO_CONFIG_1, 0);
>> + if (ret < 0) {
>> + dev_err(dev, "Failed to write FIFO_CONFIG_1\n");
>> + return ret;
>> + }
>> +
>> + data->fifo_enabled = false;
>> +
>> + return 0;
>> +}
>> +
>> +static int bmi160_buffer_postenable(struct iio_dev *indio_dev)
>> +{
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + int ret;
>> +
>> + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
>> + return iio_triggered_buffer_postenable(indio_dev);
>> +
>> + mutex_lock(&data->mutex);
>> + ret = regmap_update_bits(data->regmap, BMI160_REG_INT_MAP_1,
>> + data->irq_data->map_fwm, data->irq_data->map_fwm);
>> + if (ret < 0)
>> + goto unlock;
>> +
>> + ret = regmap_update_bits(data->regmap, BMI160_REG_INT_EN_1,
>> + BMI160_INT_FWM_EN, BMI160_INT_FWM_EN);
>> + if (ret < 0)
>> + goto unlock;
>> +
>> + ret = bmi160_fifo_enable(indio_dev, data);
>> +
>> +unlock:
>> + mutex_unlock(&data->mutex);
>> +
>> + return ret;
>> +}
>> +
>> +static int bmi160_buffer_predisable(struct iio_dev *indio_dev)
>> +{
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + struct regmap *regmap = data->regmap;
>> + int ret = 0;
>> +
>> + if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED)
>> + return iio_triggered_buffer_predisable(indio_dev);
>> +
>> + mutex_lock(&data->mutex);
>> +
>> + ret = regmap_update_bits(regmap, BMI160_REG_INT_EN_1,
>> + BMI160_INT_FWM_EN, 0);
>> + if (ret < 0)
>> + goto unlock;
>> +
>> + ret = bmi160_fifo_disable(data);
>> +
>> +unlock:
>> + mutex_unlock(&data->mutex);
>> +
>> + return ret;
>> +}
>> +
>> +static const struct iio_buffer_setup_ops bmi160_buffer_ops = {
>> + .postenable = bmi160_buffer_postenable,
>> + .predisable = bmi160_buffer_predisable,
>> +};
>> +
>> +static ssize_t bmi160_get_fifo_state(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + bool state;
>> +
>> + mutex_lock(&data->mutex);
>> + state = data->fifo_enabled;
>> + mutex_unlock(&data->mutex);
>> +
>> + return sprintf(buf, "%d\n", (int) state);
>> +}
>> +
>> +static ssize_t bmi160_get_fifo_watermark(struct device *dev,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct iio_dev *indio_dev = dev_to_iio_dev(dev);
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + int wm;
>> +
>> + mutex_lock(&data->mutex);
>> + wm = data->watermark;
>> + mutex_unlock(&data->mutex);
>> +
>> + return sprintf(buf, "%d\n", wm);
>> +}
>> +
>> +static IIO_CONST_ATTR(hwfifo_watermark_min, "1");
>> +static IIO_CONST_ATTR(hwfifo_watermark_max,
>> + __stringify(BMI160_FIFO_LENGTH));
>> +static IIO_DEVICE_ATTR(hwfifo_enabled, S_IRUGO,
>> + bmi160_get_fifo_state, NULL, 0);
>> +static IIO_DEVICE_ATTR(hwfifo_watermark, S_IRUGO,
>> + bmi160_get_fifo_watermark, NULL, 0);
>> +
>> +static const struct attribute *bmi160_fifo_attributes[] = {
>> + &iio_const_attr_hwfifo_watermark_min.dev_attr.attr,
>> + &iio_const_attr_hwfifo_watermark_max.dev_attr.attr,
>> + &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
>> + &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
>> + NULL,
>> +};
>> +
>> +static int bmi160_set_watermark(struct iio_dev *indio_dev, unsigned int val)
>> +{
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> +
>> + if (val > BMI160_FIFO_LENGTH)
>> + val = BMI160_FIFO_LENGTH;
>> +
>> + data->watermark = val;
>> +
>> + return 0;
>> +}
>> +
>> +static int bmi160_fifo_transfer(struct bmi160_data *data,
>> + char *buffer, int num_bytes)
>> +{
>> + struct regmap *regmap = data->regmap;
>> + struct device *dev = regmap_get_device(regmap);
>> + size_t step = regmap_get_raw_read_max(regmap);
>> + int ret = 0;
>> + int i;
>> +
>> + if (!step || step > num_bytes)
>> + step = num_bytes;
>> + else if (step < num_bytes)
>> + step = data->fifo_sample_size;
>> +
>> + for (i = 0; i < num_bytes; i += step) {
>> + ret = regmap_raw_read(regmap, BMI160_REG_FIFO_DATA,
>> + &buffer[i], step);
>> +
>> + if (ret)
>> + break;
>> + }
>> +
>> + if (ret)
>> + dev_err(dev,
>> + "Error transferring data from fifo in single steps of %zu\n",
>> + step);
>> +
>> + return ret;
>> +}
>> +
>> +static int __bmi160_fifo_flush(struct iio_dev *indio_dev,
>> + unsigned int samples, bool irq)
>
> what does the __ prefix denote?
> likely that the function is supposed to be called with mutex held --
> maybe use that convention elsewhere as well?
I will rename it together with other functions that assume mutex already
acquired.
>
>> +{
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + struct regmap *regmap = data->regmap;
>> + struct device *dev = regmap_get_device(regmap);
>> + int ret;
>> + __le16 fifo_length;
>> + unsigned int fifo_samples;
>> + unsigned int fifo_bytes;
>> + u8 *buffer = data->fifo_buffer;
>> + u8 *buffer_iter;
>> + int64_t last_timestamp, timestamp;
>> + unsigned int last_samples;
>> + unsigned int i;
>> +
>> + /* Get the current FIFO length */
>> + ret = regmap_bulk_read(regmap, BMI160_REG_FIFO_LENGTH,
>> + &fifo_length, sizeof(__le16));
>> + if (ret < 0) {
>> + dev_err(dev, "Error reading FIFO_LENGTH\n");
>> + return ret;
>> + }
>> +
>> + fifo_bytes = le16_to_cpu(fifo_length);
>> + fifo_samples = fifo_bytes / data->fifo_sample_size;
>> +
>> + if (fifo_bytes % data->fifo_sample_size)
>> + dev_warn(dev, "fifo_bytes %u is not dividable by %u\n",
>> + fifo_bytes, data->fifo_sample_size);
>> +
>> + if (!fifo_samples)
>> + return 0;
>> +
>> + if (samples && fifo_samples > samples) {
>> + fifo_samples = samples;
>> + fifo_bytes = fifo_samples * data->fifo_sample_size;
>> + }
>> +
>> + /*
>> + * If we are not called from IRQ, it means that we are flushing data
>> + * on demand. In that case we do not have latest timestamp saved in
>> + * data->timestamp. Get the time now instead.
>> + *
>> + * In case of IRQ flush, saved timestamp shows the time when number
>> + * of samples configured by watermark were ready. Currently there might
>> + * be more samples already.
>> + * If we are not called from IRQ, than we are getting the current fifo
>> + * length, as we are setting timestamp just after getting it.
>> + */
>> + if (!irq) {
>> + last_timestamp = iio_get_time_ns(indio_dev);
>> + last_samples = fifo_samples;
>> + } else {
>> + last_timestamp = data->timestamp;
>> + last_samples = data->watermark;
>> + }
>> +
>> + /* Get all measurements */
>> + ret = bmi160_fifo_transfer(data, buffer, fifo_bytes);
>> + if (ret)
>> + return ret;
>> +
>> + /* Handle demux */
>> + timestamp = last_timestamp - (last_samples * data->fifo_sample_period);
>> + buffer_iter = buffer;
>> + for (i = 0; i < fifo_samples; i++) {
>> + u8 tmp_buf[indio_dev->scan_bytes];
>
> non-constant array size, is this allowed these days?
I am not sure if this is permitted in kernel. [1] says that ISO C99 adds
arrays of variable length.
The reason I have used it is that iio_push_to_buffers_with_timestamp
uses indio_dev->scan_bytes to write timestamp to last element in array.
One of the possiblities to get rid of non-constant array size is to
determine maximum size. Is that what I should do?
[1] https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html
>
>> +
>> + memcpy(tmp_buf, buffer_iter, data->fifo_sample_size);
>> +
>> + timestamp += data->fifo_sample_period;
>> + iio_push_to_buffers_with_timestamp(indio_dev,
>> + tmp_buf,
>> + timestamp);
>> +
>> + buffer_iter += data->fifo_sample_size;
>> + }
>> +
>> + return fifo_samples;
>> +}
>> +
>> +static int bmi160_fifo_flush(struct iio_dev *indio_dev, unsigned int samples)
>> +{
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + int ret;
>> +
>> + mutex_lock(&data->mutex);
>> + ret = __bmi160_fifo_flush(indio_dev, samples, false);
>> + mutex_unlock(&data->mutex);
>> +
>> + return ret;
>> +}
>> +
>> static const struct iio_info bmi160_info = {
>> - .driver_module = THIS_MODULE,
>> - .read_raw = bmi160_read_raw,
>> - .write_raw = bmi160_write_raw,
>> - .attrs = &bmi160_attrs_group,
>> + .driver_module = THIS_MODULE,
>> + .read_raw = bmi160_read_raw,
>> + .write_raw = bmi160_write_raw,
>> + .attrs = &bmi160_attrs_group,
>> +};
>> +
>> +static const struct iio_info bmi160_info_fifo = {
>> + .driver_module = THIS_MODULE,
>> + .read_raw = bmi160_read_raw,
>> + .write_raw = bmi160_write_raw,
>> + .attrs = &bmi160_attrs_group,
>> + .hwfifo_set_watermark = bmi160_set_watermark,
>> + .hwfifo_flush_to_buffer = bmi160_fifo_flush,
>> };
>>
>> static const char *bmi160_match_acpi_device(struct device *dev)
>> @@ -561,12 +1059,54 @@ static void bmi160_chip_uninit(struct bmi160_data *data)
>> bmi160_set_mode(data, BMI160_ACCEL, false);
>> }
>>
>> +static int bmi160_enable_irq(struct bmi160_data *data)
>> +{
>> + int ret;
>> +
>> + mutex_lock(&data->mutex);
>> + ret = regmap_update_bits(data->regmap, BMI160_REG_INT_OUT_CTRL,
>> + data->irq_data->output_en,
>> + data->irq_data->output_en);
>> + mutex_unlock(&data->mutex);
>> +
>> + return ret;
>> +}
>> +
>> +static irqreturn_t bmi160_irq_thread_handler(int irq, void *p)
>> +{
>> + struct iio_dev *indio_dev = p;
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> + struct device *dev = regmap_get_device(data->regmap);
>> +
>> + mutex_lock(&data->mutex);
>> + if (data->fifo_enabled)
>> + __bmi160_fifo_flush(indio_dev, BMI160_FIFO_LENGTH, true);
>> + else
>> + dev_warn(dev,
>> + "IRQ has been triggered, but FIFO is not enabled.\n");
>> + mutex_unlock(&data->mutex);
>> +
>> + return IRQ_HANDLED;
>> +}
>> +
>> +static irqreturn_t bmi160_irq_handler(int irq, void *p)
>> +{
>> + struct iio_dev *indio_dev = p;
>> + struct bmi160_data *data = iio_priv(indio_dev);
>> +
>> + data->timestamp = iio_get_time_ns(indio_dev);
>> +
>> + return IRQ_WAKE_THREAD;
>> +}
>> +
>> int bmi160_core_probe(struct device *dev, struct regmap *regmap,
>> - const char *name, bool use_spi)
>> + const char *name, int irq,
>> + bool use_spi, bool block_supported)
>> {
>> struct iio_dev *indio_dev;
>> struct bmi160_data *data;
>> int ret;
>> + int irq2;
>>
>> indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
>> if (!indio_dev)
>> @@ -574,8 +1114,11 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
>>
>> data = iio_priv(indio_dev);
>> dev_set_drvdata(dev, indio_dev);
>> + data->irq = irq;
>> data->regmap = regmap;
>>
>> + mutex_init(&data->mutex);
>> +
>> ret = bmi160_chip_init(data, use_spi);
>> if (ret < 0)
>> return ret;
>> @@ -591,10 +1134,50 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
>> indio_dev->info = &bmi160_info;
>>
>> ret = iio_triggered_buffer_setup(indio_dev, NULL,
>> - bmi160_trigger_handler, NULL);
>> + bmi160_trigger_handler,
>> + &bmi160_buffer_ops);
>> if (ret < 0)
>> goto uninit;
>>
>> + if (data->irq > 0) {
>> + /* Check which interrupt pin is connected to our board */
>> + irq2 = of_irq_get_byname(dev->of_node, "INT2");
>> + if (irq2 == data->irq) {
>> + dev_dbg(dev, "Using interrupt line INT2\n");
>> + data->irq_data = &bmi160_irq2_data;
>> + } else {
>> + dev_dbg(dev, "Using interrupt line INT1\n");
>> + data->irq_data = &bmi160_irq1_data;
>> + }
>> +
>> + ret = devm_request_threaded_irq(dev,
>> + data->irq,
>> + bmi160_irq_handler,
>> + bmi160_irq_thread_handler,
>> + IRQF_ONESHOT,
>> + BMI160_IRQ_NAME,
>> + indio_dev);
>> + if (ret)
>> + return ret;
>> +
>> + ret = bmi160_enable_irq(data);
>> + if (ret < 0)
>> + goto buffer_cleanup;
>> +
>> + if (block_supported) {
>> + indio_dev->modes |= INDIO_BUFFER_SOFTWARE;
>> + indio_dev->info = &bmi160_info_fifo;
>> + indio_dev->buffer->attrs = bmi160_fifo_attributes;
>> + data->fifo_buffer = devm_kmalloc(dev,
>> + BMI160_FIFO_LENGTH,
>> + GFP_KERNEL);
>> + if (!data->fifo_buffer) {
>> + ret = -ENOMEM;
>
> need to disable irq on failure?
Yes, I missed that.
>
>> + goto buffer_cleanup;
>> + }
>> + }
>> + }
>> +
>> ret = iio_device_register(indio_dev);
>> if (ret < 0)
>> goto buffer_cleanup;
>> diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c
>> index 07a179d..aa63f89 100644
>> --- a/drivers/iio/imu/bmi160/bmi160_i2c.c
>> +++ b/drivers/iio/imu/bmi160/bmi160_i2c.c
>> @@ -23,6 +23,10 @@ static int bmi160_i2c_probe(struct i2c_client *client,
>> {
>> struct regmap *regmap;
>> const char *name = NULL;
>> + bool block_supported =
>> + i2c_check_functionality(client->adapter, I2C_FUNC_I2C) ||
>> + i2c_check_functionality(client->adapter,
>> + I2C_FUNC_SMBUS_READ_I2C_BLOCK);
>>
>> regmap = devm_regmap_init_i2c(client, &bmi160_regmap_config);
>> if (IS_ERR(regmap)) {
>> @@ -34,7 +38,8 @@ static int bmi160_i2c_probe(struct i2c_client *client,
>> if (id)
>> name = id->name;
>>
>> - return bmi160_core_probe(&client->dev, regmap, name, false);
>> + return bmi160_core_probe(&client->dev, regmap, name, client->irq,
>> + false, block_supported);
>> }
>>
>> static int bmi160_i2c_remove(struct i2c_client *client)
>> diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c
>> index 1ec8b12..9b57fbe 100644
>> --- a/drivers/iio/imu/bmi160/bmi160_spi.c
>> +++ b/drivers/iio/imu/bmi160/bmi160_spi.c
>> @@ -25,7 +25,8 @@ static int bmi160_spi_probe(struct spi_device *spi)
>> (int)PTR_ERR(regmap));
>> return PTR_ERR(regmap);
>> }
>> - return bmi160_core_probe(&spi->dev, regmap, id->name, true);
>> + return bmi160_core_probe(&spi->dev, regmap, id->name, spi->irq,
>> + true, true);
>> }
>>
>> static int bmi160_spi_remove(struct spi_device *spi)
>>
>
--
Marcin Niestroj
^ permalink raw reply
* Re: [PATCH v4 1/3] spi-nor: Add support for Intel SPI serial flash controller
From: Mika Westerberg @ 2016-11-09 14:15 UTC (permalink / raw)
To: Cyrille Pitchen
Cc: linux-mtd, mkraemer, David Woodhouse, key.seong.lim, linux-kernel,
Peter Tyser, Brian Norris, Lee Jones, Marek Vasut
In-Reply-To: <36b27635-8163-f3cb-5953-88f102e22ee4@atmel.com>
On Wed, Nov 09, 2016 at 02:51:20PM +0100, Cyrille Pitchen wrote:
> > +/* Reads max 64 bytes from the device fifo */
> > +static int intel_spi_read_block(struct intel_spi *ispi, void *buf, size_t size)
> > +{
> > + size_t bytes;
> > + int i = 0;
> > +
> > + if (size > 64)
>
> This is not a blocking point but just a recommendation: you should define
> and use a macro for this 64 byte FIFO size instead of using this hardcoded
> 64 value here and in intel_spi_write_block(), intel_spi_write(),
> intel_spi_read().
Good point. I'll change that to use a macro.
> > + return -EINVAL;
> > +
> > + while (size > 0) {
> > + bytes = min_t(size_t, size, 4);
> > + memcpy_fromio(buf, ispi->base + FDATA(i++), bytes);
> Here again another general recommendation: be careful about using
> operators like ++ on macro parameters. In the case of this FDATA() macro
> it will work as expected but unwanted side effect might occur depending on
> the actual macro definition:
>
> int i = 1;
>
> #define DOUBLE(n) ((n) + (n))
> DOUBLE(i++); /* here i is incremented twice, not just once. */
Indeed, even though with the current macro it does not happen I'm going
change it to update i separately like:
memcpy_fromio(buf, ispi->base + FDATA(i), bytes);
i++
> > + size -= bytes;
> > + buf += bytes;
> > + }
> > +
> > + return 0;
> > +}
[snip]
> > +static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
> > + u_char *read_buf)
> > +{
> > + struct intel_spi *ispi = nor->priv;
> > + size_t block_size, retlen = 0;
> > + u32 val, status;
> > + ssize_t ret;
> > +
>
> As I understand some Intel SPI controllers can only use op codes in a fixed
> instruction set, so here you should check the nor->read_opcode.
> Indeed when the support of SFDP tables will be integrated, the
> nor->read_opcode might change between calls of the nor->read() handler.
OK, I did not know that it can change.
> spi_nor_read_sfdp() make use of this nor->read() handler but set
> nor->read_opcode to SPINOR_OP_RDSFDP (5Ah) before calling the handler.
>
> Then, if intel_spi_read() is called with an unsupported nor->read_opcode,
> it should fail returning -EINVAL. The spi-nor framework will handle this
> failure correctly.
>
> You can find the SFDP patch here:
> http://patchwork.ozlabs.org/patch/685984/
Thanks for the pointer. I'll update the driver to take read_opcode into
account in intel_spi_read().
Thanks for the comments.
^ permalink raw reply
* [PATCHv2] ARM: socfpga_defconfig: enable FS configs to support Angstrom filesystem
From: Dinh Nguyen @ 2016-11-09 14:15 UTC (permalink / raw)
To: linux-arm-kernel
systemd on the Angstrom root file system expects AUTOFS to be configured
as a module and NFSD to be statically linked into the kernel. This patch
adds the necessary configuration to get rid two "FAILED" error messages
during systemd startup.
Signed-off-by: Matthew Gerlach <mgerlach@opensource.altera.com>
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v2: provide a more descriptive changelog
---
arch/arm/configs/socfpga_defconfig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index 18d3ec1..2e1d254 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -116,13 +116,18 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT3_FS=y
+CONFIG_AUTOFS4_FS=y
CONFIG_VFAT_FS=y
CONFIG_NTFS_FS=y
CONFIG_NTFS_RW=y
CONFIG_TMPFS=y
CONFIG_CONFIGFS_FS=y
CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
CONFIG_ROOT_NFS=y
+CONFIG_NFSD=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
--
2.8.3
^ permalink raw reply related
* Re: [PATCH for-4.8] x86/svm: Don't clobber eax and edx if an RDMSR intercept fails
From: Jan Beulich @ 2016-11-09 14:14 UTC (permalink / raw)
To: Andrew Cooper; +Cc: Boris Ostrovsky, Wei Liu, SuraveeSuthikulpanit, Xen-devel
In-Reply-To: <1478694507-26060-1-git-send-email-andrew.cooper3@citrix.com>
>>> On 09.11.16 at 13:28, <andrew.cooper3@citrix.com> wrote:
> The original code has a bug; eax and edx get unconditionally updated even when
> hvm_msr_read_intercept() doesn't return X86EMUL_OKAY.
>
> It is only by blind luck (vmce_rdmsr() eagerly initialising its msr_content
> pointer) that this isn't an information leak into guests.
>
> While fixing this bug, reduce the scope of msr_content and initialise it to 0.
> This makes it obvious that a stack leak won't occur, even if there were to be
> a buggy codepath in hvm_msr_read_intercept().
>
> Also make some non-functional improvements. Make the insn_len calculation
> common, and reduce the quantity of explicit casting by making better use of
> the existing register names.
>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
with two possible further adjustments:
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -1948,26 +1948,28 @@ static int svm_msr_write_intercept(unsigned int msr, uint64_t msr_content)
>
> static void svm_do_msr_access(struct cpu_user_regs *regs)
> {
> - int rc, inst_len;
> struct vcpu *v = current;
> - struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
> - uint64_t msr_content;
> + bool rdmsr = v->arch.hvm_svm.vmcb->exitinfo1 == 0;
> + int rc, inst_len = __get_instruction_length(
> + v, rdmsr ? INSTR_RDMSR : INSTR_WRMSR);
With all of this I think it wouldn't make the patch worse to look at if
you also renamed v -> curr.
> + if ( inst_len == 0 )
> + return;
>
> - if ( vmcb->exitinfo1 == 0 )
> + if ( rdmsr )
> {
> - if ( (inst_len = __get_instruction_length(v, INSTR_RDMSR)) == 0 )
> - return;
> - rc = hvm_msr_read_intercept(regs->ecx, &msr_content);
> - regs->eax = (uint32_t)msr_content;
> - regs->edx = (uint32_t)(msr_content >> 32);
> + uint64_t msr_content = 0;
> +
> + rc = hvm_msr_read_intercept(regs->_ecx, &msr_content);
> + if ( rc == X86EMUL_OKAY )
> + {
> + regs->rax = (uint32_t)msr_content;
> + regs->rdx = (uint32_t)(msr_content >> 32);
While the first of the casts is needed, the second one isn't.
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply
* Xen, EFI and kexec
From: Sylvain Munaut @ 2016-11-09 14:13 UTC (permalink / raw)
To: xen-devel@lists.xen.org
Hi,
A bit of background: What I'm currently trying to do is to network
boot a first linux image in EFI mode (using UEFI network boot), then
from that image, kexec into Xen in EFI mode as well.
It's not working.
When you kexec into another linux in EFI mode, kexec actually passes
some more infos to the kernel to allow it to use EFI mode properly.
IIUC Linux also maps the various EFI ranges at deterministic addresses
because the seting up EFI virtual address mode is only allowed once
per boot and so both the old and new kernel have to use the same
mappings.
I have seen the patch series by Daniel Kiper to add support for
multiboot2 protocol and EFI support for it. This seems like a good
step toward what I'd like to do. Adding multiboot2 support to kexec
user tools seems like something I could do. This should allow Xen to
get the info it needs.
However I don't think that'll be sufficient.
By the time kexec will launch Xen, the first kernel will have done an
"ExitBootServices". And looking at Daniel's patch, that seems to be an
issue.
I'm also not sure if the EFI virtual address mode will be an issue or
not yet. (i.e. Xen uses the physical address mode, but is that usable
after the first linux setup the virtual mode).
Is there anything else I overlooked that will be an issue ?
Is this a use case worth supporting ? (Obviously I think so, but I'm biased :p)
And if I'm looking at it the wrong way, what way should I be looking at it ?
Cheers,
Sylvain Munaut
PS: I'm currently making my way through the 2000+ pages of the EFI
specs so I probably got some things wrong above ...
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
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.