]> git.baikalelectronics.ru Git - kernel.git/commitdiff
irqchip/gic-v4.1: Add mask/unmask doorbell callbacks
authorMarc Zyngier <maz@kernel.org>
Tue, 24 Dec 2019 11:10:33 +0000 (11:10 +0000)
committerMarc Zyngier <maz@kernel.org>
Wed, 22 Jan 2020 14:22:20 +0000 (14:22 +0000)
masking/unmasking doorbells on GICv4.1 relies on a new INVDB command,
which broadcasts the invalidation to all RDs.

Implement the new command as well as the masking callbacks, and plug
the whole thing into the v4.1 VPE irqchip.

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

index 2b477e29eb4c69e775c47a0ab49119fac35623fd..5ef706e8fc1ff6b413bf4fc4649e7f791c2763e8 100644 (file)
@@ -333,6 +333,10 @@ struct its_cmd_desc {
                        u16 seq_num;
                        u16 its_list;
                } its_vmovp_cmd;
+
+               struct {
+                       struct its_vpe *vpe;
+               } its_invdb_cmd;
        };
 };
 
@@ -831,6 +835,21 @@ static struct its_vpe *its_build_vclear_cmd(struct its_node *its,
        return valid_vpe(its, map->vpe);
 }
 
+static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
+                                          struct its_cmd_block *cmd,
+                                          struct its_cmd_desc *desc)
+{
+       if (WARN_ON(!is_v4_1(its)))
+               return NULL;
+
+       its_encode_cmd(cmd, GITS_CMD_INVDB);
+       its_encode_vpeid(cmd, desc->its_invdb_cmd.vpe->vpe_id);
+
+       its_fixup_cmd(cmd);
+
+       return valid_vpe(its, desc->its_invdb_cmd.vpe);
+}
+
 static u64 its_cmd_ptr_to_offset(struct its_node *its,
                                 struct its_cmd_block *ptr)
 {
@@ -1239,6 +1258,14 @@ static void its_send_vclear(struct its_device *dev, u32 event_id)
        its_send_single_vcommand(dev->its, its_build_vclear_cmd, &desc);
 }
 
+static void its_send_invdb(struct its_node *its, struct its_vpe *vpe)
+{
+       struct its_cmd_desc desc;
+
+       desc.its_invdb_cmd.vpe = vpe;
+       its_send_single_vcommand(its, its_build_invdb_cmd, &desc);
+}
+
 /*
  * irqchip functions - assumes MSI, mostly.
  */
@@ -3553,6 +3580,50 @@ static struct irq_chip its_vpe_irq_chip = {
        .irq_set_vcpu_affinity  = its_vpe_set_vcpu_affinity,
 };
 
+static struct its_node *find_4_1_its(void)
+{
+       static struct its_node *its = NULL;
+
+       if (!its) {
+               list_for_each_entry(its, &its_nodes, entry) {
+                       if (is_v4_1(its))
+                               return its;
+               }
+
+               /* Oops? */
+               its = NULL;
+       }
+
+       return its;
+}
+
+static void its_vpe_4_1_send_inv(struct irq_data *d)
+{
+       struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+       struct its_node *its;
+
+       /*
+        * GICv4.1 wants doorbells to be invalidated using the
+        * INVDB command in order to be broadcast to all RDs. Send
+        * it to the first valid ITS, and let the HW do its magic.
+        */
+       its = find_4_1_its();
+       if (its)
+               its_send_invdb(its, vpe);
+}
+
+static void its_vpe_4_1_mask_irq(struct irq_data *d)
+{
+       lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0);
+       its_vpe_4_1_send_inv(d);
+}
+
+static void its_vpe_4_1_unmask_irq(struct irq_data *d)
+{
+       lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED);
+       its_vpe_4_1_send_inv(d);
+}
+
 static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
        struct its_cmd_info *info = vcpu_info;
@@ -3574,6 +3645,8 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 
 static struct irq_chip its_vpe_4_1_irq_chip = {
        .name                   = "GICv4.1-vpe",
+       .irq_mask               = its_vpe_4_1_mask_irq,
+       .irq_unmask             = its_vpe_4_1_unmask_irq,
        .irq_eoi                = irq_chip_eoi_parent,
        .irq_set_affinity       = its_vpe_set_affinity,
        .irq_set_vcpu_affinity  = its_vpe_4_1_set_vcpu_affinity,
index db0a11193d928f1d7e5928ee5aa62113d3e6554f..1f17181a9f7e689c4a45b5bc14062fa4529a7b79 100644 (file)
 #define GITS_CMD_VMAPTI                        GITS_CMD_GICv4(GITS_CMD_MAPTI)
 #define GITS_CMD_VMOVI                 GITS_CMD_GICv4(GITS_CMD_MOVI)
 #define GITS_CMD_VSYNC                 GITS_CMD_GICv4(GITS_CMD_SYNC)
-/* VMOVP is the odd one, as it doesn't have a physical counterpart */
+/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
 #define GITS_CMD_VMOVP                 GITS_CMD_GICv4(2)
+#define GITS_CMD_INVDB                 GITS_CMD_GICv4(0xe)
 
 /*
  * ITS error numbers