mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
xen/events: drop xen_allocate_irqs_dynamic()
Instead of having a common function for allocating a single IRQ or a consecutive number of IRQs, split up the functionality into the callers of xen_allocate_irqs_dynamic(). This allows to handle any allocation error in xen_irq_init() gracefully instead of panicing the system. Let xen_irq_init() return the irq_info pointer or NULL in case of an allocation error. Additionally set the IRQ into irq_info already at allocation time, as otherwise the IRQ would be '0' (which is a valid IRQ number) until being set. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> Signed-off-by: Juergen Gross <jgross@suse.com>
This commit is contained in:
parent
3bdb0ac350
commit
5dd9ad32d7
@ -304,6 +304,13 @@ static void channels_on_cpu_inc(struct irq_info *info)
|
||||
info->is_accounted = 1;
|
||||
}
|
||||
|
||||
static void xen_irq_free_desc(unsigned int irq)
|
||||
{
|
||||
/* Legacy IRQ descriptors are managed by the arch. */
|
||||
if (irq >= nr_legacy_irqs())
|
||||
irq_free_desc(irq);
|
||||
}
|
||||
|
||||
static void delayed_free_irq(struct work_struct *work)
|
||||
{
|
||||
struct irq_info *info = container_of(to_rcu_work(work), struct irq_info,
|
||||
@ -315,9 +322,7 @@ static void delayed_free_irq(struct work_struct *work)
|
||||
|
||||
kfree(info);
|
||||
|
||||
/* Legacy IRQ descriptors are managed by the arch. */
|
||||
if (irq >= nr_legacy_irqs())
|
||||
irq_free_desc(irq);
|
||||
xen_irq_free_desc(irq);
|
||||
}
|
||||
|
||||
/* Constructors for packed IRQ information. */
|
||||
@ -332,7 +337,6 @@ static int xen_irq_info_common_setup(struct irq_info *info,
|
||||
BUG_ON(info->type != IRQT_UNBOUND && info->type != type);
|
||||
|
||||
info->type = type;
|
||||
info->irq = irq;
|
||||
info->evtchn = evtchn;
|
||||
info->cpu = cpu;
|
||||
info->mask_reason = EVT_MASK_REASON_EXPLICIT;
|
||||
@ -733,45 +737,43 @@ void xen_irq_lateeoi(unsigned int irq, unsigned int eoi_flags)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xen_irq_lateeoi);
|
||||
|
||||
static void xen_irq_init(unsigned irq)
|
||||
static struct irq_info *xen_irq_init(unsigned int irq)
|
||||
{
|
||||
struct irq_info *info;
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (info == NULL)
|
||||
panic("Unable to allocate metadata for IRQ%d\n", irq);
|
||||
if (info) {
|
||||
info->irq = irq;
|
||||
info->type = IRQT_UNBOUND;
|
||||
info->refcnt = -1;
|
||||
INIT_RCU_WORK(&info->rwork, delayed_free_irq);
|
||||
|
||||
info->type = IRQT_UNBOUND;
|
||||
info->refcnt = -1;
|
||||
INIT_RCU_WORK(&info->rwork, delayed_free_irq);
|
||||
set_info_for_irq(irq, info);
|
||||
/*
|
||||
* Interrupt affinity setting can be immediate. No point
|
||||
* in delaying it until an interrupt is handled.
|
||||
*/
|
||||
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
|
||||
|
||||
set_info_for_irq(irq, info);
|
||||
/*
|
||||
* Interrupt affinity setting can be immediate. No point
|
||||
* in delaying it until an interrupt is handled.
|
||||
*/
|
||||
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
|
||||
|
||||
INIT_LIST_HEAD(&info->eoi_list);
|
||||
list_add_tail(&info->list, &xen_irq_list_head);
|
||||
}
|
||||
|
||||
static int __must_check xen_allocate_irqs_dynamic(int nvec)
|
||||
{
|
||||
int i, irq = irq_alloc_descs(-1, 0, nvec, -1);
|
||||
|
||||
if (irq >= 0) {
|
||||
for (i = 0; i < nvec; i++)
|
||||
xen_irq_init(irq + i);
|
||||
INIT_LIST_HEAD(&info->eoi_list);
|
||||
list_add_tail(&info->list, &xen_irq_list_head);
|
||||
}
|
||||
|
||||
return irq;
|
||||
return info;
|
||||
}
|
||||
|
||||
static inline int __must_check xen_allocate_irq_dynamic(void)
|
||||
{
|
||||
int irq = irq_alloc_desc_from(0, -1);
|
||||
|
||||
return xen_allocate_irqs_dynamic(1);
|
||||
if (irq >= 0) {
|
||||
if (!xen_irq_init(irq)) {
|
||||
xen_irq_free_desc(irq);
|
||||
irq = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static int __must_check xen_allocate_irq_gsi(unsigned gsi)
|
||||
@ -793,7 +795,10 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi)
|
||||
else
|
||||
irq = irq_alloc_desc_at(gsi, -1);
|
||||
|
||||
xen_irq_init(irq);
|
||||
if (!xen_irq_init(irq)) {
|
||||
xen_irq_free_desc(irq);
|
||||
irq = -1;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
@ -963,6 +968,11 @@ static void __unbind_from_irq(unsigned int irq)
|
||||
evtchn_port_t evtchn = evtchn_from_irq(irq);
|
||||
struct irq_info *info = info_for_irq(irq);
|
||||
|
||||
if (!info) {
|
||||
xen_irq_free_desc(irq);
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->refcnt > 0) {
|
||||
info->refcnt--;
|
||||
if (info->refcnt != 0)
|
||||
@ -1101,11 +1111,14 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
|
||||
|
||||
mutex_lock(&irq_mapping_update_lock);
|
||||
|
||||
irq = xen_allocate_irqs_dynamic(nvec);
|
||||
irq = irq_alloc_descs(-1, 0, nvec, -1);
|
||||
if (irq < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < nvec; i++) {
|
||||
if (!xen_irq_init(irq + i))
|
||||
goto error_irq;
|
||||
|
||||
irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name);
|
||||
|
||||
ret = xen_irq_info_pirq_setup(irq + i, 0, pirq + i, 0, domid,
|
||||
@ -1730,6 +1743,7 @@ void rebind_evtchn_irq(evtchn_port_t evtchn, int irq)
|
||||
so there should be a proper type */
|
||||
BUG_ON(info->type == IRQT_UNBOUND);
|
||||
|
||||
info->irq = irq;
|
||||
(void)xen_irq_info_evtchn_setup(irq, evtchn, NULL);
|
||||
|
||||
mutex_unlock(&irq_mapping_update_lock);
|
||||
|
Loading…
Reference in New Issue
Block a user