summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/arm64/iort.c19
-rw-r--r--drivers/acpi/property.c8
2 files changed, 22 insertions, 5 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e48eebc27b81..43c2615434b4 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1231,18 +1231,24 @@ static bool __init arm_smmu_v3_is_coherent(struct acpi_iort_node *node)
/*
* set numa proximity domain for smmuv3 device
*/
-static void __init arm_smmu_v3_set_proximity(struct device *dev,
+static int __init arm_smmu_v3_set_proximity(struct device *dev,
struct acpi_iort_node *node)
{
struct acpi_iort_smmu_v3 *smmu;
smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
if (smmu->flags & ACPI_IORT_SMMU_V3_PXM_VALID) {
- set_dev_node(dev, acpi_map_pxm_to_node(smmu->pxm));
+ int node = acpi_map_pxm_to_node(smmu->pxm);
+
+ if (node != NUMA_NO_NODE && !node_online(node))
+ return -EINVAL;
+
+ set_dev_node(dev, node);
pr_info("SMMU-v3[%llx] Mapped to Proximity domain %d\n",
smmu->base_address,
smmu->pxm);
}
+ return 0;
}
#else
#define arm_smmu_v3_set_proximity NULL
@@ -1317,7 +1323,7 @@ struct iort_dev_config {
int (*dev_count_resources)(struct acpi_iort_node *node);
void (*dev_init_resources)(struct resource *res,
struct acpi_iort_node *node);
- void (*dev_set_proximity)(struct device *dev,
+ int (*dev_set_proximity)(struct device *dev,
struct acpi_iort_node *node);
};
@@ -1368,8 +1374,11 @@ static int __init iort_add_platform_device(struct acpi_iort_node *node,
if (!pdev)
return -ENOMEM;
- if (ops->dev_set_proximity)
- ops->dev_set_proximity(&pdev->dev, node);
+ if (ops->dev_set_proximity) {
+ ret = ops->dev_set_proximity(&pdev->dev, node);
+ if (ret)
+ goto dev_put;
+ }
count = ops->dev_count_resources(node);
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 693cf05b0cc4..288673cff85e 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -975,6 +975,14 @@ struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
const struct acpi_data_node *data = to_acpi_data_node(fwnode);
struct acpi_data_node *dn;
+ /*
+ * We can have a combination of device and data nodes, e.g. with
+ * hierarchical _DSD properties. Make sure the adev pointer is
+ * restored before going through data nodes, otherwise we will
+ * be looking for data_nodes below the last device found instead
+ * of the common fwnode shared by device_nodes and data_nodes.
+ */
+ adev = to_acpi_device_node(fwnode);
if (adev)
head = &adev->data.subnodes;
else if (data)