diff options
| -rw-r--r-- | drivers/xen/events.c | 77 |
1 files changed, 27 insertions, 50 deletions
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 81a53eb6cd1d..06f2e61de691 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -376,72 +376,49 @@ static void unmask_evtchn(int port) | |||
| 376 | put_cpu(); | 376 | put_cpu(); |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | static int get_nr_hw_irqs(void) | 379 | static int xen_allocate_irq_dynamic(void) |
| 380 | { | 380 | { |
| 381 | int ret = 1; | 381 | int first = 0; |
| 382 | int irq; | ||
| 382 | 383 | ||
| 383 | #ifdef CONFIG_X86_IO_APIC | 384 | #ifdef CONFIG_X86_IO_APIC |
| 384 | ret = get_nr_irqs_gsi(); | 385 | /* |
| 386 | * For an HVM guest or domain 0 which see "real" (emulated or | ||
| 387 | * actual repectively) GSIs we allocate dynamic IRQs | ||
| 388 | * e.g. those corresponding to event channels or MSIs | ||
| 389 | * etc. from the range above those "real" GSIs to avoid | ||
| 390 | * collisions. | ||
| 391 | */ | ||
| 392 | if (xen_initial_domain() || xen_hvm_domain()) | ||
| 393 | first = get_nr_irqs_gsi(); | ||
| 385 | #endif | 394 | #endif |
| 386 | 395 | ||
| 387 | return ret; | 396 | retry: |
| 388 | } | 397 | irq = irq_alloc_desc_from(first, -1); |
| 389 | 398 | ||
| 390 | static int xen_allocate_irq_dynamic(void) | 399 | if (irq == -ENOMEM && first > NR_IRQS_LEGACY) { |
| 391 | { | 400 | printk(KERN_ERR "Out of dynamic IRQ space and eating into GSI space. You should increase nr_irqs\n"); |
| 392 | struct irq_data *data; | 401 | first = max(NR_IRQS_LEGACY, first - NR_IRQS_LEGACY); |
| 393 | int irq, res; | 402 | goto retry; |
| 394 | int bottom = get_nr_hw_irqs(); | ||
| 395 | int top = nr_irqs-1; | ||
| 396 | |||
| 397 | if (bottom == nr_irqs) | ||
| 398 | goto no_irqs; | ||
| 399 | |||
| 400 | /* This loop starts from the top of IRQ space and goes down. | ||
| 401 | * We need this b/c if we have a PCI device in a Xen PV guest | ||
| 402 | * we do not have an IO-APIC (though the backend might have them) | ||
| 403 | * mapped in. To not have a collision of physical IRQs with the Xen | ||
| 404 | * event channels start at the top of the IRQ space for virtual IRQs. | ||
| 405 | */ | ||
| 406 | for (irq = top; irq > bottom; irq--) { | ||
| 407 | data = irq_get_irq_data(irq); | ||
| 408 | /* only 15->0 have init'd desc; handle irq > 16 */ | ||
| 409 | if (!data) | ||
| 410 | break; | ||
| 411 | if (data->chip == &no_irq_chip) | ||
| 412 | break; | ||
| 413 | if (data->chip != &xen_dynamic_chip) | ||
| 414 | continue; | ||
| 415 | if (irq_info[irq].type == IRQT_UNBOUND) | ||
| 416 | return irq; | ||
| 417 | } | 403 | } |
| 418 | 404 | ||
| 419 | if (irq == bottom) | 405 | if (irq < 0) |
| 420 | goto no_irqs; | 406 | panic("No available IRQ to bind to: increase nr_irqs!\n"); |
| 421 | |||
| 422 | res = irq_alloc_desc_at(irq, -1); | ||
| 423 | |||
| 424 | if (WARN_ON(res != irq)) | ||
| 425 | return -1; | ||
| 426 | 407 | ||
| 427 | return irq; | 408 | return irq; |
| 428 | |||
| 429 | no_irqs: | ||
| 430 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | ||
| 431 | } | ||
| 432 | |||
| 433 | static bool identity_mapped_irq(unsigned irq) | ||
| 434 | { | ||
| 435 | /* identity map all the hardware irqs */ | ||
| 436 | return irq < get_nr_hw_irqs(); | ||
| 437 | } | 409 | } |
| 438 | 410 | ||
| 439 | static int xen_allocate_irq_gsi(unsigned gsi) | 411 | static int xen_allocate_irq_gsi(unsigned gsi) |
| 440 | { | 412 | { |
| 441 | int irq; | 413 | int irq; |
| 442 | 414 | ||
| 443 | if (!identity_mapped_irq(gsi) && | 415 | /* |
| 444 | (xen_initial_domain() || !xen_pv_domain())) | 416 | * A PV guest has no concept of a GSI (since it has no ACPI |
| 417 | * nor access to/knowledge of the physical APICs). Therefore | ||
| 418 | * all IRQs are dynamically allocated from the entire IRQ | ||
| 419 | * space. | ||
| 420 | */ | ||
| 421 | if (xen_pv_domain() && !xen_initial_domain()) | ||
| 445 | return xen_allocate_irq_dynamic(); | 422 | return xen_allocate_irq_dynamic(); |
| 446 | 423 | ||
| 447 | /* Legacy IRQ descriptors are already allocated by the arch. */ | 424 | /* Legacy IRQ descriptors are already allocated by the arch. */ |
