Author: andrew
Date: Fri Jan 31 09:51:38 2020
New Revision: 357323
URL: https://svnweb.freebsd.org/changeset/base/357323

Log:
  Ignore the SMMUv3 and PMCG interrupt controller in the IORT tables
  
  When mapping MSI/MSI-X interrupts throught he Arm IORT ACPI tables we may
  need to ignore an interrupt controller even if it is within the bounds the
  entry describes. When the SMMUv3 is not using GSIV (non-MSI/MSI-X)
  interrupts we need to read the defined field. The Performance Monitoring
  Counter Group always ignores the first table entry.
  
  MFC after:    2 weeks
  Sponsored by: DARPA, AFRL

Modified:
  head/sys/arm64/acpica/acpi_iort.c

Modified: head/sys/arm64/acpica/acpi_iort.c
==============================================================================
--- head/sys/arm64/acpica/acpi_iort.c   Fri Jan 31 08:38:38 2020        
(r357322)
+++ head/sys/arm64/acpica/acpi_iort.c   Fri Jan 31 09:51:38 2020        
(r357323)
@@ -89,6 +89,7 @@ struct iort_node {
        u_int                   node_offset;    /* offset in IORT - node ID */
        u_int                   nentries;       /* items in array below */
        u_int                   usecount;       /* for bookkeeping */
+       u_int                   revision;       /* node revision */
        union {
                ACPI_IORT_ROOT_COMPLEX  pci_rc;         /* PCI root complex */
                ACPI_IORT_SMMU          smmu;
@@ -105,6 +106,39 @@ static TAILQ_HEAD(, iort_node) pci_nodes = TAILQ_HEAD_
 static TAILQ_HEAD(, iort_node) smmu_nodes = TAILQ_HEAD_INITIALIZER(smmu_nodes);
 static TAILQ_HEAD(, iort_node) its_groups = TAILQ_HEAD_INITIALIZER(its_groups);
 
+static int
+iort_entry_get_id_mapping_index(struct iort_node *node)
+{
+
+       switch(node->type) {
+       case ACPI_IORT_NODE_SMMU_V3:
+               /* The ID mapping field was added in version 1 */
+               if (node->revision < 1)
+                       return (-1);
+
+               /*
+                * If all the control interrupts are GISCV based the ID
+                * mapping field is ignored.
+                */
+               if (node->data.smmu_v3.EventGsiv != 0 &&
+                   node->data.smmu_v3.PriGsiv != 0 &&
+                   node->data.smmu_v3.GerrGsiv != 0 &&
+                   node->data.smmu_v3.SyncGsiv != 0)
+                       return (-1);
+
+               if (node->data.smmu_v3.IdMappingIndex >= node->nentries)
+                       return (-1);
+
+               return (node->data.smmu_v3.IdMappingIndex);
+       case ACPI_IORT_NODE_PMCG:
+               return (0);
+       default:
+               break;
+       }
+
+       return (-1);
+}
+
 /*
  * Lookup an ID in the mappings array. If successful, map the input ID
  * to the output ID and return the output node found.
@@ -113,10 +147,13 @@ static struct iort_node *
 iort_entry_lookup(struct iort_node *node, u_int id, u_int *outid)
 {
        struct iort_map_entry *entry;
-       int i;
+       int i, id_map;
 
+       id_map = iort_entry_get_id_mapping_index(node);
        entry = node->entries.mappings;
        for (i = 0; i < node->nentries; i++, entry++) {
+               if (i == id_map)
+                       continue;
                if (entry->base <= id && id <= entry->end)
                        break;
        }
@@ -243,6 +280,7 @@ iort_add_nodes(ACPI_IORT_NODE *node_entry, u_int node_
        node = malloc(sizeof(*node), M_DEVBUF, M_WAITOK | M_ZERO);
        node->type =  node_entry->Type;
        node->node_offset = node_offset;
+       node->revision = node_entry->Revision;
 
        /* copy nodes depending on type */
        switch(node_entry->Type) {
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to