This adds an helper to retrieve the smmuv3 dev(if any) associated
with the PMCG node. This will be used in subsequent SMMUv3 PMU
driver patch to name the pmu device.
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@xxxxxxxxxx>
---
drivers/acpi/arm64/iort.c | 84 ++++++++++++++++++++++++++++++++++++-----------
include/linux/acpi_iort.h | 4 +++
2 files changed, 69 insertions(+), 19 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index ac4d0d6..7940080 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -42,6 +42,7 @@ struct iort_fwnode {
struct list_head list;
struct acpi_iort_node *iort_node;
struct fwnode_handle *fwnode;
+ struct platform_device *pdev;
};
static LIST_HEAD(iort_fwnode_list);
static DEFINE_SPINLOCK(iort_fwnode_lock);
@@ -52,12 +53,14 @@ static DEFINE_SPINLOCK(iort_fwnode_lock);
*
* @node: IORT table node associated with the IOMMU
* @fwnode: fwnode associated with the IORT node
+ * @pdev: platform dev associated with the IORT node if any
*
* Returns: 0 on success
* <0 on failure
*/
static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
- struct fwnode_handle *fwnode)
+ struct fwnode_handle *fwnode,
+ struct platform_device *pdev)
{
struct iort_fwnode *np;
@@ -69,6 +72,7 @@ static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
INIT_LIST_HEAD(&np->list);
np->iort_node = iort_node;
np->fwnode = fwnode;
+ np->pdev = pdev;
spin_lock(&iort_fwnode_lock);
list_add_tail(&np->list, &iort_fwnode_list);
@@ -78,6 +82,31 @@ static inline int iort_set_fwnode(struct acpi_iort_node *iort_node,
}
/**
+ * iort_get_pdev() - Retrieve pdev associated with an IORT node
+ *
+ * @node: IORT table node to be looked-up
+ *
+ * Returns: platform dev pointer on success, NULL on failure
+ */
+static inline struct platform_device *iort_get_pdev(
+ struct acpi_iort_node *node)
+{
+ struct iort_fwnode *curr;
+ struct platform_device *pdev = NULL;
+
+ spin_lock(&iort_fwnode_lock);
+ list_for_each_entry(curr, &iort_fwnode_list, list) {
+ if (curr->iort_node == node) {
+ pdev = curr->pdev;
+ break;
+ }
+ }
+ spin_unlock(&iort_fwnode_lock);
+
+ return pdev;
+}
+
+/**
* iort_get_fwnode() - Retrieve fwnode associated with an IORT node
*
* @node: IORT table node to be looked-up
@@ -1347,6 +1376,32 @@ static struct acpi_iort_node *iort_find_pmcg_ref(struct acpi_iort_node *node)
return ref_node;
}
+/**
+ * iort_find_pmcg_ref_smmu - helper to retrieve SMMUv3 associated with PMCG
+ * @dev: PMCG device
+ *
+ * Returns: smmu dev associated with the PMCG on success, NULL on failure
+ */
+struct device *iort_find_pmcg_ref_smmu(struct device *dev)
+{
+ struct acpi_iort_node *node;
+ struct acpi_iort_node *ref_node = NULL;
+ struct platform_device *pdev = NULL;
+
+ node = iort_get_iort_node(dev->fwnode);
+ if (!node || node->type != ACPI_IORT_NODE_PMCG)
+ return NULL;
+
+ ref_node = iort_find_pmcg_ref(node);
+ if (ref_node && ref_node->type == ACPI_IORT_NODE_SMMU_V3)
+ pdev = iort_get_pdev(ref_node);
+
+ if (pdev)
+ return &pdev->dev;
+
+ return NULL;
+}
+
struct iort_dev_config {
const char *name;
int (*dev_init)(struct acpi_iort_node *node);
@@ -1453,13 +1508,14 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
if (ret)
goto dev_put;
- fwnode = iort_get_fwnode(node);
-
+ fwnode = acpi_alloc_fwnode_static();
if (!fwnode) {
ret = -ENODEV;
goto dev_put;
}
+ iort_set_fwnode(node, fwnode, pdev);
+
pdev->dev.fwnode = fwnode;
if (ops->dev_dma_configure) {
@@ -1472,12 +1528,14 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
ret = platform_device_add(pdev);
if (ret)
- goto dma_deconfigure;
+ goto out;
return 0;
-dma_deconfigure:
+out:
acpi_dma_deconfigure(&pdev->dev);
+ iort_delete_fwnode(node);
+ acpi_free_fwnode_static(fwnode);
dev_put:
platform_device_put(pdev);
@@ -1519,8 +1577,7 @@ static void __init iort_init_platform_devices(void)
{
struct acpi_iort_node *iort_node, *iort_end;
struct acpi_table_iort *iort;
- struct fwnode_handle *fwnode;
- int i, ret;
+ int i;
bool acs_enabled = false;
const struct iort_dev_config *ops;
@@ -1547,18 +1604,7 @@ static void __init iort_init_platform_devices(void)
ops = iort_get_dev_cfg(iort_node);
if (ops) {
- fwnode = acpi_alloc_fwnode_static();
- if (!fwnode)
- return;
-
- iort_set_fwnode(iort_node, fwnode);
-
- ret = iort_add_platform_device(iort_node, ops);
- if (ret) {
- iort_delete_fwnode(iort_node);
- acpi_free_fwnode_static(fwnode);
- return;
- }
+ iort_add_platform_device(iort_node, ops);
}
iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 38cd77b..54ccff2 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -36,6 +36,7 @@ u32 iort_msi_map_rid(struct device *dev, u32 req_id);
struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
void acpi_configure_pmsi_domain(struct device *dev);
int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
+struct device *iort_find_pmcg_ref_smmu(struct device *dev);
/* IOMMU interface */
void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
const struct iommu_ops *iort_iommu_configure(struct device *dev);
@@ -48,6 +49,9 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
u32 req_id)
{ return NULL; }
static inline void acpi_configure_pmsi_domain(struct device *dev) { }
+static inline
+struct device *iort_find_pmcg_ref_smmu(struct device *dev)
+{ return NULL; }
/* IOMMU interface */
static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
u64 *size) { }