mirror of https://gitee.com/openkylin/linux.git
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: Marc Zyngier <maz@kernel.org> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com> Link: https://lore.kernel.org/r/20200304203330.4967-15-maz@kernel.org
This commit is contained in:
parent
ae699ad348
commit
6d31b6ff98
|
@ -92,6 +92,47 @@ static bool has_v4_1(void)
|
|||
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 vpe_base_irq, i;
|
||||
|
@ -118,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
|
|||
if (vpe_base_irq <= 0)
|
||||
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;
|
||||
ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -132,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
|
|||
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)
|
||||
{
|
||||
its_free_sgi_irqs(vm);
|
||||
irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes);
|
||||
irq_domain_remove(vm->domain);
|
||||
irq_domain_free_fwnode(vm->fwnode);
|
||||
|
|
|
@ -49,6 +49,8 @@ struct its_vpe {
|
|||
};
|
||||
/* GICv4.1 implementations */
|
||||
struct {
|
||||
struct fwnode_handle *fwnode;
|
||||
struct irq_domain *sgi_domain;
|
||||
struct {
|
||||
u8 priority;
|
||||
bool enabled;
|
||||
|
|
Loading…
Reference in New Issue