OSDN Git Service

irqchip/gic-v3: Add GICv4.1 VPEID size discovery
authorMarc Zyngier <maz@kernel.org>
Tue, 24 Dec 2019 11:10:25 +0000 (11:10 +0000)
committerMarc Zyngier <maz@kernel.org>
Wed, 22 Jan 2020 14:22:19 +0000 (14:22 +0000)
While GICv4.0 mandates 16 bit worth of VPEIDs, GICv4.1 allows smaller
implementations to be built. Add the required glue to dynamically
compute the limit.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
Link: https://lore.kernel.org/r/20191224111055.11836-3-maz@kernel.org
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
include/linux/irqchip/arm-gic-v3.h

index b704214..6b0a8d6 100644 (file)
@@ -121,7 +121,16 @@ struct its_node {
 #define ITS_ITT_ALIGN          SZ_256
 
 /* The maximum number of VPEID bits supported by VLPI commands */
-#define ITS_MAX_VPEID_BITS     (16)
+#define ITS_MAX_VPEID_BITS                                             \
+       ({                                                              \
+               int nvpeid = 16;                                        \
+               if (gic_rdists->has_rvpeid &&                           \
+                   gic_rdists->gicd_typer2 & GICD_TYPER2_VIL)          \
+                       nvpeid = 1 + (gic_rdists->gicd_typer2 &         \
+                                     GICD_TYPER2_VID);                 \
+                                                                       \
+               nvpeid;                                                 \
+       })
 #define ITS_MAX_VPEID          (1 << (ITS_MAX_VPEID_BITS))
 
 /* Convert page order to size in bytes */
index ffcb018..286f982 100644 (file)
@@ -1576,6 +1576,9 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
        pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
        pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
+
+       gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2);
+
        gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
                                                 &gic_data);
        irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
index 9a5f85d..9dfe641 100644 (file)
@@ -13,6 +13,7 @@
 #define GICD_CTLR                      0x0000
 #define GICD_TYPER                     0x0004
 #define GICD_IIDR                      0x0008
+#define GICD_TYPER2                    0x000C
 #define GICD_STATUSR                   0x0010
 #define GICD_SETSPI_NSR                        0x0040
 #define GICD_CLRSPI_NSR                        0x0048
@@ -89,6 +90,9 @@
 #define GICD_TYPER_ESPIS(typer)                                                \
        (((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
 
+#define GICD_TYPER2_VIL                        (1U << 7)
+#define GICD_TYPER2_VID                        GENMASK(4, 0)
+
 #define GICD_IROUTER_SPI_MODE_ONE      (0U << 31)
 #define GICD_IROUTER_SPI_MODE_ANY      (1U << 31)
 
@@ -615,6 +619,7 @@ struct rdists {
        void                    *prop_table_va;
        u64                     flags;
        u32                     gicd_typer;
+       u32                     gicd_typer2;
        bool                    has_vlpis;
        bool                    has_rvpeid;
        bool                    has_direct_lpi;