[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.