diff options
Diffstat (limited to 'arch/x86/kernel/apic/vector.c')
-rw-r--r-- | arch/x86/kernel/apic/vector.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 6a823a25eaff..3cc471beb50b 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
@@ -184,6 +184,7 @@ static void reserve_irq_vector_locked(struct irq_data *irqd) | |||
184 | irq_matrix_reserve(vector_matrix); | 184 | irq_matrix_reserve(vector_matrix); |
185 | apicd->can_reserve = true; | 185 | apicd->can_reserve = true; |
186 | apicd->has_reserved = true; | 186 | apicd->has_reserved = true; |
187 | irqd_set_can_reserve(irqd); | ||
187 | trace_vector_reserve(irqd->irq, 0); | 188 | trace_vector_reserve(irqd->irq, 0); |
188 | vector_assign_managed_shutdown(irqd); | 189 | vector_assign_managed_shutdown(irqd); |
189 | } | 190 | } |
@@ -368,8 +369,18 @@ static int activate_reserved(struct irq_data *irqd) | |||
368 | int ret; | 369 | int ret; |
369 | 370 | ||
370 | ret = assign_irq_vector_any_locked(irqd); | 371 | ret = assign_irq_vector_any_locked(irqd); |
371 | if (!ret) | 372 | if (!ret) { |
372 | apicd->has_reserved = false; | 373 | apicd->has_reserved = false; |
374 | /* | ||
375 | * Core might have disabled reservation mode after | ||
376 | * allocating the irq descriptor. Ideally this should | ||
377 | * happen before allocation time, but that would require | ||
378 | * completely convoluted ways of transporting that | ||
379 | * information. | ||
380 | */ | ||
381 | if (!irqd_can_reserve(irqd)) | ||
382 | apicd->can_reserve = false; | ||
383 | } | ||
373 | return ret; | 384 | return ret; |
374 | } | 385 | } |
375 | 386 | ||
@@ -398,21 +409,21 @@ static int activate_managed(struct irq_data *irqd) | |||
398 | } | 409 | } |
399 | 410 | ||
400 | static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd, | 411 | static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd, |
401 | bool early) | 412 | bool reserve) |
402 | { | 413 | { |
403 | struct apic_chip_data *apicd = apic_chip_data(irqd); | 414 | struct apic_chip_data *apicd = apic_chip_data(irqd); |
404 | unsigned long flags; | 415 | unsigned long flags; |
405 | int ret = 0; | 416 | int ret = 0; |
406 | 417 | ||
407 | trace_vector_activate(irqd->irq, apicd->is_managed, | 418 | trace_vector_activate(irqd->irq, apicd->is_managed, |
408 | apicd->can_reserve, early); | 419 | apicd->can_reserve, reserve); |
409 | 420 | ||
410 | /* Nothing to do for fixed assigned vectors */ | 421 | /* Nothing to do for fixed assigned vectors */ |
411 | if (!apicd->can_reserve && !apicd->is_managed) | 422 | if (!apicd->can_reserve && !apicd->is_managed) |
412 | return 0; | 423 | return 0; |
413 | 424 | ||
414 | raw_spin_lock_irqsave(&vector_lock, flags); | 425 | raw_spin_lock_irqsave(&vector_lock, flags); |
415 | if (early || irqd_is_managed_and_shutdown(irqd)) | 426 | if (reserve || irqd_is_managed_and_shutdown(irqd)) |
416 | vector_assign_managed_shutdown(irqd); | 427 | vector_assign_managed_shutdown(irqd); |
417 | else if (apicd->is_managed) | 428 | else if (apicd->is_managed) |
418 | ret = activate_managed(irqd); | 429 | ret = activate_managed(irqd); |
@@ -478,6 +489,7 @@ static bool vector_configure_legacy(unsigned int virq, struct irq_data *irqd, | |||
478 | } else { | 489 | } else { |
479 | /* Release the vector */ | 490 | /* Release the vector */ |
480 | apicd->can_reserve = true; | 491 | apicd->can_reserve = true; |
492 | irqd_set_can_reserve(irqd); | ||
481 | clear_irq_vector(irqd); | 493 | clear_irq_vector(irqd); |
482 | realloc = true; | 494 | realloc = true; |
483 | } | 495 | } |
@@ -530,20 +542,23 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq, | |||
530 | 542 | ||
531 | err = assign_irq_vector_policy(irqd, info); | 543 | err = assign_irq_vector_policy(irqd, info); |
532 | trace_vector_setup(virq + i, false, err); | 544 | trace_vector_setup(virq + i, false, err); |
533 | if (err) | 545 | if (err) { |
546 | irqd->chip_data = NULL; | ||
547 | free_apic_chip_data(apicd); | ||
534 | goto error; | 548 | goto error; |
549 | } | ||
535 | } | 550 | } |
536 | 551 | ||
537 | return 0; | 552 | return 0; |
538 | 553 | ||
539 | error: | 554 | error: |
540 | x86_vector_free_irqs(domain, virq, i + 1); | 555 | x86_vector_free_irqs(domain, virq, i); |
541 | return err; | 556 | return err; |
542 | } | 557 | } |
543 | 558 | ||
544 | #ifdef CONFIG_GENERIC_IRQ_DEBUGFS | 559 | #ifdef CONFIG_GENERIC_IRQ_DEBUGFS |
545 | void x86_vector_debug_show(struct seq_file *m, struct irq_domain *d, | 560 | static void x86_vector_debug_show(struct seq_file *m, struct irq_domain *d, |
546 | struct irq_data *irqd, int ind) | 561 | struct irq_data *irqd, int ind) |
547 | { | 562 | { |
548 | unsigned int cpu, vector, prev_cpu, prev_vector; | 563 | unsigned int cpu, vector, prev_cpu, prev_vector; |
549 | struct apic_chip_data *apicd; | 564 | struct apic_chip_data *apicd; |