[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC 10/11] IORT parsing functions to prepare requesterId maps
From: Manish Jaggi <manish.jaggi@xxxxxxxxxx> This patch adds functions to parse the IORT and use the requesterID public API to update the maps. Signed-off-by: Manish jaggi <manish.jaggi@xxxxxxxxxx> --- xen/drivers/acpi/arm/iort.c | 200 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/xen/drivers/acpi/arm/iort.c b/xen/drivers/acpi/arm/iort.c index a47ee2df4c..00a9f18046 100644 --- a/xen/drivers/acpi/arm/iort.c +++ b/xen/drivers/acpi/arm/iort.c @@ -353,6 +353,205 @@ static inline struct fwnode_handle *acpi_alloc_fwnode_static(void) return fwnode; } +static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr) +{ + return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr); +} + +static inline bool is_acpi_static_node(const struct fwnode_handle *fwnode) +{ + return !IS_ERR_OR_NULL(fwnode) && + fwnode->ops == &acpi_static_fwnode_ops; +} + +static inline void acpi_free_fwnode_static(struct fwnode_handle *fwnode) +{ + if (WARN_ON(!is_acpi_static_node(fwnode))) + return; + + kfree(fwnode); +} +int fixup_rid_deviceid_map(struct acpi_iort_node *inode, + struct acpi_iort_id_mapping *pci_idmap, + struct acpi_iort_node *smmu_node) +{ + + unsigned int p_input_base, p_output_base, p_id_count; + unsigned int s_input_base, s_output_base, s_id_count; + unsigned int delta, i; + int ret = 0; + struct acpi_iort_id_mapping *smmu_idmap = NULL; + struct acpi_iort_node *its_node; + struct acpi_table_iort *iort; + + iort = (struct acpi_table_iort*) iort_table; + + p_input_base = pci_idmap->input_base; + p_output_base = pci_idmap->output_base; + p_id_count = pci_idmap->id_count; + + smmu_idmap = (struct acpi_iort_id_mapping*) ((u8*) smmu_node + + smmu_node->mapping_offset); + + for (i = 0; i < smmu_node->mapping_count; i++, smmu_idmap++) { + s_input_base = smmu_idmap->input_base; + s_output_base = smmu_idmap->output_base; + s_id_count = smmu_idmap->id_count; + its_node = ACPI_ADD_PTR(struct acpi_iort_node, iort, + smmu_idmap->output_reference); + + if (s_input_base <= p_output_base) { + int count; + if (s_input_base + s_id_count < p_output_base) + continue; + + delta = p_output_base - s_input_base; + count = s_input_base + s_id_count <= p_output_base + + p_id_count ? s_id_count - delta : p_id_count; + + ret = add_rid_deviceid_map (inode, its_node, + p_input_base, + s_output_base + delta, + count); + if (ret) + return ret; + } else { + int count; + if (p_output_base + p_id_count < s_input_base) + continue; + + delta = s_input_base - p_output_base; + count = s_input_base + s_id_count < p_output_base + + p_id_count ? s_id_count : p_id_count - delta; + + ret = add_rid_deviceid_map (inode, its_node, + p_input_base + delta, + s_output_base, count); + + if (ret) + return ret; + } + } + + return ret; +} + +void parse_pcirc_node(struct acpi_iort_node *iort_node) +{ + int j , ret; + struct acpi_iort_id_mapping *idmap; + struct acpi_iort_node *onode; + struct acpi_table_iort *iort; + + iort = (struct acpi_table_iort*) iort_table; + idmap = ACPI_ADD_PTR(struct acpi_iort_id_mapping, iort_node, + iort_node->mapping_offset); + + /* iterate over idmap */ + for ( j = 0; j < iort_node->mapping_count; j++ ) { + + struct acpi_iort_node *its_node; + struct acpi_iort_node *smmu_node; + onode = ACPI_ADD_PTR(struct acpi_iort_node, iort, + idmap->output_reference); + + switch (onode->type) { + case ACPI_IORT_NODE_ITS_GROUP: + + its_node = ACPI_ADD_PTR(struct acpi_iort_node, iort, + idmap->output_reference); + + ret = add_rid_deviceid_map(iort_node, its_node, + idmap->input_base, + idmap->output_base, + idmap->id_count); + if (ret) { + pr_err("%s: add_rid_deviceid_map" + "failed with ret=%d \r\n", + __func__, ret); + break; + } + break; + + case ACPI_IORT_NODE_SMMU: + case ACPI_IORT_NODE_SMMU_V3: + + smmu_node = ACPI_ADD_PTR( + struct acpi_iort_node, + iort_table, + idmap->output_reference); + + ret = add_rid_streamid_map(iort_node, + smmu_node, + idmap->input_base, + idmap->output_base, + idmap->id_count); + if (ret) { + pr_err("%s: add_rid_streamid_map" + "failed with ret=%d \r\n", + __func__, ret); + break; + } + + ret = fixup_rid_deviceid_map(iort_node, idmap, + onode); + if (ret) { + pr_err("%s: fixup_rid_deviceid_map" + "failed with ret=%d \r\n", + __func__, ret); + break; + } + break; + } + idmap++; + } +} + +void parse_smmu_node(struct acpi_iort_node *iort_node) +{ + int ret; + struct fwnode_handle *fwnode; + fwnode = acpi_alloc_fwnode_static(); + if (!fwnode) + return; + + iort_set_fwnode(iort_node, fwnode); + ret = iort_add_smmu_platform_device(iort_node); + if (ret) + acpi_free_fwnode_static(fwnode); +} + +void parse_iort(void) +{ + struct acpi_iort_node *iort_node, *iort_end; + struct acpi_table_iort *iort; + int i; + + iort = (struct acpi_table_iort*) iort_table; + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort, + iort->node_offset); + iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort, + iort->header.length); + init_ridmaps(); + + for (i = 0; i < iort->node_count; i++) { + if ( iort_node >= iort_end ) { + pr_err("iort node pointer overflows, bad table\n"); + return; + } + + if ( iort_node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ) + parse_pcirc_node(iort_node); + else if ( (iort_node->type == ACPI_IORT_NODE_SMMU || + iort_node->type == ACPI_IORT_NODE_SMMU_V3) ) + parse_smmu_node(iort_node); + + iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node, + iort_node->length); + } +} + + void __init acpi_iort_init(void) { acpi_status status; @@ -366,4 +565,5 @@ void __init acpi_iort_init(void) } return; } + parse_iort(); } -- 2.14.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |