mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 18:23:53 +08:00
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;
|
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)
|
|||||||
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 @@ err:
|
|||||||
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 {
|
|||||||
};
|
};
|
||||||
/* 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;
|
||||||
|
Loading…
Reference in New Issue
Block a user