Skip to content

Commit 5dd9ad3

Browse files
committed
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>
1 parent 3bdb0ac commit 5dd9ad3

File tree

1 file changed

+44
-30
lines changed

1 file changed

+44
-30
lines changed

drivers/xen/events/events_base.c

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ static void channels_on_cpu_inc(struct irq_info *info)
304304
info->is_accounted = 1;
305305
}
306306

307+
static void xen_irq_free_desc(unsigned int irq)
308+
{
309+
/* Legacy IRQ descriptors are managed by the arch. */
310+
if (irq >= nr_legacy_irqs())
311+
irq_free_desc(irq);
312+
}
313+
307314
static void delayed_free_irq(struct work_struct *work)
308315
{
309316
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)
315322

316323
kfree(info);
317324

318-
/* Legacy IRQ descriptors are managed by the arch. */
319-
if (irq >= nr_legacy_irqs())
320-
irq_free_desc(irq);
325+
xen_irq_free_desc(irq);
321326
}
322327

323328
/* Constructors for packed IRQ information. */
@@ -332,7 +337,6 @@ static int xen_irq_info_common_setup(struct irq_info *info,
332337
BUG_ON(info->type != IRQT_UNBOUND && info->type != type);
333338

334339
info->type = type;
335-
info->irq = irq;
336340
info->evtchn = evtchn;
337341
info->cpu = cpu;
338342
info->mask_reason = EVT_MASK_REASON_EXPLICIT;
@@ -733,47 +737,45 @@ void xen_irq_lateeoi(unsigned int irq, unsigned int eoi_flags)
733737
}
734738
EXPORT_SYMBOL_GPL(xen_irq_lateeoi);
735739

736-
static void xen_irq_init(unsigned irq)
740+
static struct irq_info *xen_irq_init(unsigned int irq)
737741
{
738742
struct irq_info *info;
739743

740744
info = kzalloc(sizeof(*info), GFP_KERNEL);
741-
if (info == NULL)
742-
panic("Unable to allocate metadata for IRQ%d\n", irq);
745+
if (info) {
746+
info->irq = irq;
747+
info->type = IRQT_UNBOUND;
748+
info->refcnt = -1;
749+
INIT_RCU_WORK(&info->rwork, delayed_free_irq);
743750

744-
info->type = IRQT_UNBOUND;
745-
info->refcnt = -1;
746-
INIT_RCU_WORK(&info->rwork, delayed_free_irq);
751+
set_info_for_irq(irq, info);
752+
/*
753+
* Interrupt affinity setting can be immediate. No point
754+
* in delaying it until an interrupt is handled.
755+
*/
756+
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
747757

748-
set_info_for_irq(irq, info);
749-
/*
750-
* Interrupt affinity setting can be immediate. No point
751-
* in delaying it until an interrupt is handled.
752-
*/
753-
irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
758+
INIT_LIST_HEAD(&info->eoi_list);
759+
list_add_tail(&info->list, &xen_irq_list_head);
760+
}
754761

755-
INIT_LIST_HEAD(&info->eoi_list);
756-
list_add_tail(&info->list, &xen_irq_list_head);
762+
return info;
757763
}
758764

759-
static int __must_check xen_allocate_irqs_dynamic(int nvec)
765+
static inline int __must_check xen_allocate_irq_dynamic(void)
760766
{
761-
int i, irq = irq_alloc_descs(-1, 0, nvec, -1);
767+
int irq = irq_alloc_desc_from(0, -1);
762768

763769
if (irq >= 0) {
764-
for (i = 0; i < nvec; i++)
765-
xen_irq_init(irq + i);
770+
if (!xen_irq_init(irq)) {
771+
xen_irq_free_desc(irq);
772+
irq = -1;
773+
}
766774
}
767775

768776
return irq;
769777
}
770778

771-
static inline int __must_check xen_allocate_irq_dynamic(void)
772-
{
773-
774-
return xen_allocate_irqs_dynamic(1);
775-
}
776-
777779
static int __must_check xen_allocate_irq_gsi(unsigned gsi)
778780
{
779781
int irq;
@@ -793,7 +795,10 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi)
793795
else
794796
irq = irq_alloc_desc_at(gsi, -1);
795797

796-
xen_irq_init(irq);
798+
if (!xen_irq_init(irq)) {
799+
xen_irq_free_desc(irq);
800+
irq = -1;
801+
}
797802

798803
return irq;
799804
}
@@ -963,6 +968,11 @@ static void __unbind_from_irq(unsigned int irq)
963968
evtchn_port_t evtchn = evtchn_from_irq(irq);
964969
struct irq_info *info = info_for_irq(irq);
965970

971+
if (!info) {
972+
xen_irq_free_desc(irq);
973+
return;
974+
}
975+
966976
if (info->refcnt > 0) {
967977
info->refcnt--;
968978
if (info->refcnt != 0)
@@ -1101,11 +1111,14 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
11011111

11021112
mutex_lock(&irq_mapping_update_lock);
11031113

1104-
irq = xen_allocate_irqs_dynamic(nvec);
1114+
irq = irq_alloc_descs(-1, 0, nvec, -1);
11051115
if (irq < 0)
11061116
goto out;
11071117

11081118
for (i = 0; i < nvec; i++) {
1119+
if (!xen_irq_init(irq + i))
1120+
goto error_irq;
1121+
11091122
irq_set_chip_and_handler_name(irq + i, &xen_pirq_chip, handle_edge_irq, name);
11101123

11111124
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)
17301743
so there should be a proper type */
17311744
BUG_ON(info->type == IRQT_UNBOUND);
17321745

1746+
info->irq = irq;
17331747
(void)xen_irq_info_evtchn_setup(irq, evtchn, NULL);
17341748

17351749
mutex_unlock(&irq_mapping_update_lock);

0 commit comments

Comments
 (0)