Commit 6d31b6ff authored by Marc Zyngier's avatar Marc Zyngier

irqchip/gic-v4.1: Add VSGI allocation/teardown

Allocate per-VPE SGIs when initializing the GIC-specific part of the
VPE data structure.
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Reviewed-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Link: https://lore.kernel.org/r/20200304203330.4967-15-maz@kernel.org
parent ae699ad3
...@@ -92,6 +92,47 @@ static bool has_v4_1(void) ...@@ -92,6 +92,47 @@ static bool has_v4_1(void)
return !!sgi_domain_ops; return !!sgi_domain_ops;
} }
static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
{
char *name;
int sgi_base;
if (!has_v4_1())
return 0;
name = kasprintf(GFP_KERNEL, "GICv4-sgi-%d", task_pid_nr(current));
if (!name)
goto err;
vpe->fwnode = irq_domain_alloc_named_id_fwnode(name, idx);
if (!vpe->fwnode)
goto err;
kfree(name);
name = NULL;
vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, 16,
sgi_domain_ops, vpe);
if (!vpe->sgi_domain)
goto err;
sgi_base = __irq_domain_alloc_irqs(vpe->sgi_domain, -1, 16,
NUMA_NO_NODE, vpe,
false, NULL);
if (sgi_base <= 0)
goto err;
return 0;
err:
if (vpe->sgi_domain)
irq_domain_remove(vpe->sgi_domain);
if (vpe->fwnode)
irq_domain_free_fwnode(vpe->fwnode);
kfree(name);
return -ENOMEM;
}
int its_alloc_vcpu_irqs(struct its_vm *vm) int its_alloc_vcpu_irqs(struct its_vm *vm)
{ {
int vpe_base_irq, i; int vpe_base_irq, i;
...@@ -118,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm) ...@@ -118,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
if (vpe_base_irq <= 0) if (vpe_base_irq <= 0)
goto err; goto err;
for (i = 0; i < vm->nr_vpes; i++) for (i = 0; i < vm->nr_vpes; i++) {
int ret;
vm->vpes[i]->irq = vpe_base_irq + i; vm->vpes[i]->irq = vpe_base_irq + i;
ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
if (ret)
goto err;
}
return 0; return 0;
...@@ -132,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm) ...@@ -132,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
return -ENOMEM; return -ENOMEM;
} }
static void its_free_sgi_irqs(struct its_vm *vm)
{
int i;
if (!has_v4_1())
return;
for (i = 0; i < vm->nr_vpes; i++) {
unsigned int irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);
if (WARN_ON(!irq))
continue;
irq_domain_free_irqs(irq, 16);
irq_domain_remove(vm->vpes[i]->sgi_domain);
irq_domain_free_fwnode(vm->vpes[i]->fwnode);
}
}
void its_free_vcpu_irqs(struct its_vm *vm) void its_free_vcpu_irqs(struct its_vm *vm)
{ {
its_free_sgi_irqs(vm);
irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes); irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes);
irq_domain_remove(vm->domain); irq_domain_remove(vm->domain);
irq_domain_free_fwnode(vm->fwnode); irq_domain_free_fwnode(vm->fwnode);
......
...@@ -49,6 +49,8 @@ struct its_vpe { ...@@ -49,6 +49,8 @@ struct its_vpe {
}; };
/* GICv4.1 implementations */ /* GICv4.1 implementations */
struct { struct {
struct fwnode_handle *fwnode;
struct irq_domain *sgi_domain;
struct { struct {
u8 priority; u8 priority;
bool enabled; bool enabled;
......
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