Commit dd3f050a authored by Marc Zyngier's avatar Marc Zyngier

irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP

With GICv4.1, VMOVP is extended to allow a default doorbell to be
specified, as well as a validity bit for this doorbell. As an added
bonus, VMOVP isn't required anymore of moving a VPE between
redistributors that share the same affinity.

Let's add this support to the VMOVP builder, and make sure we don't
issue the command if we don't really need to.
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Reviewed-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Link: https://lore.kernel.org/r/20191224111055.11836-9-maz@kernel.org
parent 0684c704
...@@ -470,6 +470,17 @@ static void its_encode_vmapp_default_db(struct its_cmd_block *cmd, ...@@ -470,6 +470,17 @@ static void its_encode_vmapp_default_db(struct its_cmd_block *cmd,
its_mask_encode(&cmd->raw_cmd[1], vpe_db_lpi, 31, 0); its_mask_encode(&cmd->raw_cmd[1], vpe_db_lpi, 31, 0);
} }
static void its_encode_vmovp_default_db(struct its_cmd_block *cmd,
u32 vpe_db_lpi)
{
its_mask_encode(&cmd->raw_cmd[3], vpe_db_lpi, 31, 0);
}
static void its_encode_db(struct its_cmd_block *cmd, bool db)
{
its_mask_encode(&cmd->raw_cmd[2], db, 63, 63);
}
static inline void its_fixup_cmd(struct its_cmd_block *cmd) static inline void its_fixup_cmd(struct its_cmd_block *cmd)
{ {
/* Let's fixup BE commands */ /* Let's fixup BE commands */
...@@ -756,6 +767,11 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its, ...@@ -756,6 +767,11 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
its_encode_vpeid(cmd, desc->its_vmovp_cmd.vpe->vpe_id); its_encode_vpeid(cmd, desc->its_vmovp_cmd.vpe->vpe_id);
its_encode_target(cmd, target); its_encode_target(cmd, target);
if (is_v4_1(its)) {
its_encode_db(cmd, true);
its_encode_vmovp_default_db(cmd, desc->its_vmovp_cmd.vpe->vpe_db_lpi);
}
its_fixup_cmd(cmd); its_fixup_cmd(cmd);
return valid_vpe(its, desc->its_vmovp_cmd.vpe); return valid_vpe(its, desc->its_vmovp_cmd.vpe);
...@@ -3327,7 +3343,7 @@ static int its_vpe_set_affinity(struct irq_data *d, ...@@ -3327,7 +3343,7 @@ static int its_vpe_set_affinity(struct irq_data *d,
bool force) bool force)
{ {
struct its_vpe *vpe = irq_data_get_irq_chip_data(d); struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
int cpu = cpumask_first(mask_val); int from, cpu = cpumask_first(mask_val);
/* /*
* Changing affinity is mega expensive, so let's be as lazy as * Changing affinity is mega expensive, so let's be as lazy as
...@@ -3335,14 +3351,24 @@ static int its_vpe_set_affinity(struct irq_data *d, ...@@ -3335,14 +3351,24 @@ static int its_vpe_set_affinity(struct irq_data *d,
* into the proxy device, we need to move the doorbell * into the proxy device, we need to move the doorbell
* interrupt to its new location. * interrupt to its new location.
*/ */
if (vpe->col_idx != cpu) { if (vpe->col_idx == cpu)
int from = vpe->col_idx; goto out;
from = vpe->col_idx;
vpe->col_idx = cpu; vpe->col_idx = cpu;
/*
* GICv4.1 allows us to skip VMOVP if moving to a cpu whose RD
* is sharing its VPE table with the current one.
*/
if (gic_data_rdist_cpu(cpu)->vpe_table_mask &&
cpumask_test_cpu(from, gic_data_rdist_cpu(cpu)->vpe_table_mask))
goto out;
its_send_vmovp(vpe); its_send_vmovp(vpe);
its_vpe_db_proxy_move(vpe, from, cpu); its_vpe_db_proxy_move(vpe, from, cpu);
}
out:
irq_data_update_effective_affinity(d, cpumask_of(cpu)); irq_data_update_effective_affinity(d, cpumask_of(cpu));
return IRQ_SET_MASK_OK_DONE; return IRQ_SET_MASK_OK_DONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment