genirq: Let irq_set_vcpu_affinity() iterate over hierarchy

When assigning an interrupt to a vcpu, it is not unlikely that
the level of the hierarchy implementing irq_set_vcpu_affinity
is not the top level (think a generic MSI domain on top of a
virtualization aware interrupt controller).

In such a case, let's iterate over the hierarchy until we find
an irqchip implementing it.

Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

+12 -2
+12 -2
kernel/irq/manage.c
··· 400 return -EINVAL; 401 402 data = irq_desc_get_irq_data(desc); 403 - chip = irq_data_get_irq_chip(data); 404 - if (chip && chip->irq_set_vcpu_affinity) 405 ret = chip->irq_set_vcpu_affinity(data, vcpu_info); 406 irq_put_desc_unlock(desc, flags); 407
··· 400 return -EINVAL; 401 402 data = irq_desc_get_irq_data(desc); 403 + do { 404 + chip = irq_data_get_irq_chip(data); 405 + if (chip && chip->irq_set_vcpu_affinity) 406 + break; 407 + #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 408 + data = data->parent_data; 409 + #else 410 + data = NULL; 411 + #endif 412 + } while (data); 413 + 414 + if (data) 415 ret = chip->irq_set_vcpu_affinity(data, vcpu_info); 416 irq_put_desc_unlock(desc, flags); 417