Skip to content

Commit d97c97b

Browse files
author
Marc Zyngier
committed
irqchip/gic-v4.1: Add mask/unmask doorbell callbacks
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 <[email protected]> Reviewed-by: Zenghui Yu <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 29c647f commit d97c97b

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

drivers/irqchip/irq-gic-v3-its.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,10 @@ struct its_cmd_desc {
333333
u16 seq_num;
334334
u16 its_list;
335335
} its_vmovp_cmd;
336+
337+
struct {
338+
struct its_vpe *vpe;
339+
} its_invdb_cmd;
336340
};
337341
};
338342

@@ -831,6 +835,21 @@ static struct its_vpe *its_build_vclear_cmd(struct its_node *its,
831835
return valid_vpe(its, map->vpe);
832836
}
833837

838+
static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
839+
struct its_cmd_block *cmd,
840+
struct its_cmd_desc *desc)
841+
{
842+
if (WARN_ON(!is_v4_1(its)))
843+
return NULL;
844+
845+
its_encode_cmd(cmd, GITS_CMD_INVDB);
846+
its_encode_vpeid(cmd, desc->its_invdb_cmd.vpe->vpe_id);
847+
848+
its_fixup_cmd(cmd);
849+
850+
return valid_vpe(its, desc->its_invdb_cmd.vpe);
851+
}
852+
834853
static u64 its_cmd_ptr_to_offset(struct its_node *its,
835854
struct its_cmd_block *ptr)
836855
{
@@ -1239,6 +1258,14 @@ static void its_send_vclear(struct its_device *dev, u32 event_id)
12391258
its_send_single_vcommand(dev->its, its_build_vclear_cmd, &desc);
12401259
}
12411260

1261+
static void its_send_invdb(struct its_node *its, struct its_vpe *vpe)
1262+
{
1263+
struct its_cmd_desc desc;
1264+
1265+
desc.its_invdb_cmd.vpe = vpe;
1266+
its_send_single_vcommand(its, its_build_invdb_cmd, &desc);
1267+
}
1268+
12421269
/*
12431270
* irqchip functions - assumes MSI, mostly.
12441271
*/
@@ -3553,6 +3580,50 @@ static struct irq_chip its_vpe_irq_chip = {
35533580
.irq_set_vcpu_affinity = its_vpe_set_vcpu_affinity,
35543581
};
35553582

3583+
static struct its_node *find_4_1_its(void)
3584+
{
3585+
static struct its_node *its = NULL;
3586+
3587+
if (!its) {
3588+
list_for_each_entry(its, &its_nodes, entry) {
3589+
if (is_v4_1(its))
3590+
return its;
3591+
}
3592+
3593+
/* Oops? */
3594+
its = NULL;
3595+
}
3596+
3597+
return its;
3598+
}
3599+
3600+
static void its_vpe_4_1_send_inv(struct irq_data *d)
3601+
{
3602+
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
3603+
struct its_node *its;
3604+
3605+
/*
3606+
* GICv4.1 wants doorbells to be invalidated using the
3607+
* INVDB command in order to be broadcast to all RDs. Send
3608+
* it to the first valid ITS, and let the HW do its magic.
3609+
*/
3610+
its = find_4_1_its();
3611+
if (its)
3612+
its_send_invdb(its, vpe);
3613+
}
3614+
3615+
static void its_vpe_4_1_mask_irq(struct irq_data *d)
3616+
{
3617+
lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0);
3618+
its_vpe_4_1_send_inv(d);
3619+
}
3620+
3621+
static void its_vpe_4_1_unmask_irq(struct irq_data *d)
3622+
{
3623+
lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED);
3624+
its_vpe_4_1_send_inv(d);
3625+
}
3626+
35563627
static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
35573628
{
35583629
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)
35743645

35753646
static struct irq_chip its_vpe_4_1_irq_chip = {
35763647
.name = "GICv4.1-vpe",
3648+
.irq_mask = its_vpe_4_1_mask_irq,
3649+
.irq_unmask = its_vpe_4_1_unmask_irq,
35773650
.irq_eoi = irq_chip_eoi_parent,
35783651
.irq_set_affinity = its_vpe_set_affinity,
35793652
.irq_set_vcpu_affinity = its_vpe_4_1_set_vcpu_affinity,

include/linux/irqchip/arm-gic-v3.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,9 @@
484484
#define GITS_CMD_VMAPTI GITS_CMD_GICv4(GITS_CMD_MAPTI)
485485
#define GITS_CMD_VMOVI GITS_CMD_GICv4(GITS_CMD_MOVI)
486486
#define GITS_CMD_VSYNC GITS_CMD_GICv4(GITS_CMD_SYNC)
487-
/* VMOVP is the odd one, as it doesn't have a physical counterpart */
487+
/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
488488
#define GITS_CMD_VMOVP GITS_CMD_GICv4(2)
489+
#define GITS_CMD_INVDB GITS_CMD_GICv4(0xe)
489490

490491
/*
491492
* ITS error numbers

0 commit comments

Comments
 (0)