Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 234181
b: refs/heads/master
c: 8991150
h: refs/heads/master
i:
  234179: 0e01b97
v: v3
  • Loading branch information
Ian Campbell authored and Konrad Rzeszutek Wilk committed Mar 3, 2011
1 parent d733d1d commit 3b0610f
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 51 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c9df1ce585e3bb5a2f101c1d87381b285a9f962f
refs/heads/master: 89911501f3aae44a43984793341a3bf1f4c583c2
77 changes: 27 additions & 50 deletions trunk/drivers/xen/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,72 +376,49 @@ static void unmask_evtchn(int port)
put_cpu();
}

static int get_nr_hw_irqs(void)
static int xen_allocate_irq_dynamic(void)
{
int ret = 1;
int first = 0;
int irq;

#ifdef CONFIG_X86_IO_APIC
ret = get_nr_irqs_gsi();
/*
* For an HVM guest or domain 0 which see "real" (emulated or
* actual repectively) GSIs we allocate dynamic IRQs
* e.g. those corresponding to event channels or MSIs
* etc. from the range above those "real" GSIs to avoid
* collisions.
*/
if (xen_initial_domain() || xen_hvm_domain())
first = get_nr_irqs_gsi();
#endif

return ret;
}
retry:
irq = irq_alloc_desc_from(first, -1);

static int xen_allocate_irq_dynamic(void)
{
struct irq_data *data;
int irq, res;
int bottom = get_nr_hw_irqs();
int top = nr_irqs-1;

if (bottom == nr_irqs)
goto no_irqs;

/* This loop starts from the top of IRQ space and goes down.
* We need this b/c if we have a PCI device in a Xen PV guest
* we do not have an IO-APIC (though the backend might have them)
* mapped in. To not have a collision of physical IRQs with the Xen
* event channels start at the top of the IRQ space for virtual IRQs.
*/
for (irq = top; irq > bottom; irq--) {
data = irq_get_irq_data(irq);
/* only 15->0 have init'd desc; handle irq > 16 */
if (!data)
break;
if (data->chip == &no_irq_chip)
break;
if (data->chip != &xen_dynamic_chip)
continue;
if (irq_info[irq].type == IRQT_UNBOUND)
return irq;
if (irq == -ENOMEM && first > NR_IRQS_LEGACY) {
printk(KERN_ERR "Out of dynamic IRQ space and eating into GSI space. You should increase nr_irqs\n");
first = max(NR_IRQS_LEGACY, first - NR_IRQS_LEGACY);
goto retry;
}

if (irq == bottom)
goto no_irqs;

res = irq_alloc_desc_at(irq, -1);

if (WARN_ON(res != irq))
return -1;
if (irq < 0)
panic("No available IRQ to bind to: increase nr_irqs!\n");

return irq;

no_irqs:
panic("No available IRQ to bind to: increase nr_irqs!\n");
}

static bool identity_mapped_irq(unsigned irq)
{
/* identity map all the hardware irqs */
return irq < get_nr_hw_irqs();
}

static int xen_allocate_irq_gsi(unsigned gsi)
{
int irq;

if (!identity_mapped_irq(gsi) &&
(xen_initial_domain() || !xen_pv_domain()))
/*
* A PV guest has no concept of a GSI (since it has no ACPI
* nor access to/knowledge of the physical APICs). Therefore
* all IRQs are dynamically allocated from the entire IRQ
* space.
*/
if (xen_pv_domain() && !xen_initial_domain())
return xen_allocate_irq_dynamic();

/* Legacy IRQ descriptors are already allocated by the arch. */
Expand Down

0 comments on commit 3b0610f

Please sign in to comment.