aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/vector.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/vector.c')
-rw-r--r--arch/x86/kernel/apic/vector.c31
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
400static int x86_vector_activate(struct irq_domain *dom, struct irq_data *irqd, 411static 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
539error: 554error:
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
545void x86_vector_debug_show(struct seq_file *m, struct irq_domain *d, 560static 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;