Lines Matching +full:interrupt +full:- +full:affinity
1 // SPDX-License-Identifier: GPL-2.0-only
10 #include <linux/interrupt.h>
67 info->mask = mask; in init_irq_alloc_info()
83 while (irqd->parent_data) in apic_chip_data()
84 irqd = irqd->parent_data; in apic_chip_data()
86 return irqd->chip_data; in apic_chip_data()
93 return apicd ? &apicd->hw_irq_cfg : NULL; in irqd_cfg()
108 INIT_HLIST_NODE(&apicd->clist); in alloc_apic_chip_data()
124 apicd->hw_irq_cfg.vector = vector; in apic_update_irq_cfg()
125 apicd->hw_irq_cfg.dest_apicid = apic->calc_dest_apicid(cpu); in apic_update_irq_cfg()
127 trace_vector_config(irqd->irq, vector, cpu, in apic_update_irq_cfg()
128 apicd->hw_irq_cfg.dest_apicid); in apic_update_irq_cfg()
140 trace_vector_update(irqd->irq, newvec, newcpu, apicd->vector, in apic_update_vector()
141 apicd->cpu); in apic_update_vector()
149 apicd->prev_vector = 0; in apic_update_vector()
150 if (!apicd->vector || apicd->vector == MANAGED_IRQ_SHUTDOWN_VECTOR) in apic_update_vector()
155 * first interrupt on the new vector arrives. If the target CPU is in apic_update_vector()
160 if (cpu_online(apicd->cpu)) { in apic_update_vector()
161 apicd->move_in_progress = true; in apic_update_vector()
162 apicd->prev_vector = apicd->vector; in apic_update_vector()
163 apicd->prev_cpu = apicd->cpu; in apic_update_vector()
164 WARN_ON_ONCE(apicd->cpu == newcpu); in apic_update_vector()
166 irq_matrix_free(vector_matrix, apicd->cpu, apicd->vector, in apic_update_vector()
171 apicd->vector = newvec; in apic_update_vector()
172 apicd->cpu = newcpu; in apic_update_vector()
192 apicd->is_managed = true; in reserve_managed_vector()
195 trace_vector_reserve_managed(irqd->irq, ret); in reserve_managed_vector()
204 apicd->can_reserve = true; in reserve_irq_vector_locked()
205 apicd->has_reserved = true; in reserve_irq_vector_locked()
207 trace_vector_reserve(irqd->irq, 0); in reserve_irq_vector_locked()
225 bool resvd = apicd->has_reserved; in assign_vector_locked()
226 unsigned int cpu = apicd->cpu; in assign_vector_locked()
227 int vector = apicd->vector; in assign_vector_locked()
233 * affinity mask, there is no point in moving the interrupt from in assign_vector_locked()
245 if (apicd->move_in_progress || !hlist_unhashed(&apicd->clist)) in assign_vector_locked()
246 return -EBUSY; in assign_vector_locked()
249 trace_vector_alloc(irqd->irq, vector, resvd, vector); in assign_vector_locked()
272 /* Get the affinity mask - either irq_default_affinity or (user) set */ in assign_irq_vector_any_locked()
283 /* Try the full affinity mask */ in assign_irq_vector_any_locked()
303 if (info->mask) in assign_irq_vector_policy()
304 return assign_irq_vector(irqd, info->mask); in assign_irq_vector_policy()
322 if (apicd->vector && cpumask_test_cpu(apicd->cpu, vector_searchmask)) in assign_managed_vector()
326 trace_vector_alloc_managed(irqd->irq, vector, vector); in assign_managed_vector()
338 unsigned int vector = apicd->vector; in clear_irq_vector()
345 trace_vector_clear(irqd->irq, vector, apicd->cpu, apicd->prev_vector, in clear_irq_vector()
346 apicd->prev_cpu); in clear_irq_vector()
348 per_cpu(vector_irq, apicd->cpu)[vector] = VECTOR_SHUTDOWN; in clear_irq_vector()
349 irq_matrix_free(vector_matrix, apicd->cpu, vector, managed); in clear_irq_vector()
350 apicd->vector = 0; in clear_irq_vector()
353 vector = apicd->prev_vector; in clear_irq_vector()
357 per_cpu(vector_irq, apicd->prev_cpu)[vector] = VECTOR_SHUTDOWN; in clear_irq_vector()
358 irq_matrix_free(vector_matrix, apicd->prev_cpu, vector, managed); in clear_irq_vector()
359 apicd->prev_vector = 0; in clear_irq_vector()
360 apicd->move_in_progress = 0; in clear_irq_vector()
361 hlist_del_init(&apicd->clist); in clear_irq_vector()
369 trace_vector_deactivate(irqd->irq, apicd->is_managed, in x86_vector_deactivate()
370 apicd->can_reserve, false); in x86_vector_deactivate()
372 /* Regular fixed assigned interrupt */ in x86_vector_deactivate()
373 if (!apicd->is_managed && !apicd->can_reserve) in x86_vector_deactivate()
375 /* If the interrupt has a global reservation, nothing to do */ in x86_vector_deactivate()
376 if (apicd->has_reserved) in x86_vector_deactivate()
381 if (apicd->can_reserve) in x86_vector_deactivate()
395 apicd->has_reserved = false; in activate_reserved()
404 apicd->can_reserve = false; in activate_reserved()
408 * Check to ensure that the effective affinity mask is a subset in activate_reserved()
409 * the user supplied affinity mask, and warn the user if it is not in activate_reserved()
413 pr_warn("irq %u: Affinity broken due to vector space exhaustion.\n", in activate_reserved()
414 irqd->irq); in activate_reserved()
428 pr_err("Managed startup for irq %u, but no CPU\n", irqd->irq); in activate_managed()
429 return -EINVAL; in activate_managed()
439 irqd->irq); in activate_managed()
451 trace_vector_activate(irqd->irq, apicd->is_managed, in x86_vector_activate()
452 apicd->can_reserve, reserve); in x86_vector_activate()
455 if (!apicd->can_reserve && !apicd->is_managed) in x86_vector_activate()
459 else if (apicd->is_managed) in x86_vector_activate()
461 else if (apicd->has_reserved) in x86_vector_activate()
472 trace_vector_teardown(irqd->irq, apicd->is_managed, in vector_free_reserved_and_managed()
473 apicd->has_reserved); in vector_free_reserved_and_managed()
475 if (apicd->has_reserved) in vector_free_reserved_and_managed()
477 if (apicd->is_managed) in vector_free_reserved_and_managed()
491 if (irqd && irqd->chip_data) { in x86_vector_free_irqs()
495 apicd = irqd->chip_data; in x86_vector_free_irqs()
509 apicd->vector = ISA_IRQ_VECTOR(virq); in vector_configure_legacy()
510 apicd->cpu = 0; in vector_configure_legacy()
514 * If the interrupt is activated, then it must stay at this vector in vector_configure_legacy()
515 * position. That's usually the timer interrupt (0). in vector_configure_legacy()
519 apic_update_irq_cfg(irqd, apicd->vector, apicd->cpu); in vector_configure_legacy()
522 apicd->can_reserve = true; in vector_configure_legacy()
540 return -ENXIO; in x86_vector_alloc_irqs()
543 if ((info->flags & X86_IRQ_ALLOC_CONTIGUOUS_VECTORS) && nr_irqs > 1) in x86_vector_alloc_irqs()
544 return -ENOSYS; in x86_vector_alloc_irqs()
547 * Catch any attempt to touch the cascade interrupt on a PIC in x86_vector_alloc_irqs()
550 if (WARN_ON_ONCE(info->flags & X86_IRQ_ALLOC_LEGACY && in x86_vector_alloc_irqs()
552 return -EINVAL; in x86_vector_alloc_irqs()
558 WARN_ON_ONCE(irqd->chip_data); in x86_vector_alloc_irqs()
561 err = -ENOMEM; in x86_vector_alloc_irqs()
565 apicd->irq = virq + i; in x86_vector_alloc_irqs()
566 irqd->chip = &lapic_controller; in x86_vector_alloc_irqs()
567 irqd->chip_data = apicd; in x86_vector_alloc_irqs()
568 irqd->hwirq = virq + i; in x86_vector_alloc_irqs()
572 * non interrupt context via e.g. generic_handle_irq() in x86_vector_alloc_irqs()
573 * as that can corrupt the affinity move state. in x86_vector_alloc_irqs()
577 /* Don't invoke affinity setter on deactivated interrupts */ in x86_vector_alloc_irqs()
587 if (info->flags & X86_IRQ_ALLOC_LEGACY) { in x86_vector_alloc_irqs()
595 irqd->chip_data = NULL; in x86_vector_alloc_irqs()
621 irq = irqd->irq; in x86_vector_debug_show()
628 if (!irqd->chip_data) { in x86_vector_debug_show()
634 memcpy(&apicd, irqd->chip_data, sizeof(apicd)); in x86_vector_debug_show()
653 if (fwspec->param_count != 1) in x86_fwspec_is_ioapic()
656 if (is_fwnode_irqchip(fwspec->fwnode)) { in x86_fwspec_is_ioapic()
657 const char *fwname = fwnode_get_name(fwspec->fwnode); in x86_fwspec_is_ioapic()
658 return fwname && !strncmp(fwname, "IO-APIC-", 8) && in x86_fwspec_is_ioapic()
659 simple_strtol(fwname+8, NULL, 10) == fwspec->param[0]; in x86_fwspec_is_ioapic()
661 return to_of_node(fwspec->fwnode) && in x86_fwspec_is_ioapic()
662 of_device_is_compatible(to_of_node(fwspec->fwnode), in x86_fwspec_is_ioapic()
663 "intel,ce4100-ioapic"); in x86_fwspec_is_ioapic()
668 if (fwspec->param_count != 1) in x86_fwspec_is_hpet()
671 if (is_fwnode_irqchip(fwspec->fwnode)) { in x86_fwspec_is_hpet()
672 const char *fwname = fwnode_get_name(fwspec->fwnode); in x86_fwspec_is_hpet()
673 return fwname && !strncmp(fwname, "HPET-MSI-", 9) && in x86_fwspec_is_hpet()
674 simple_strtol(fwname+9, NULL, 10) == fwspec->param[0]; in x86_fwspec_is_hpet()
687 if (apic->apic_id_valid(32768)) in x86_vector_select()
728 return legacy_pic->probe(); in arch_probe_nr_irqs()
777 * Don't touch the cascade interrupt. It's unusable in lapic_assign_system_vectors()
814 int isairq = vector - ISA_IRQ_VECTOR(0); in __setup_vector_irq()
836 * The interrupt affinity logic never targets interrupts to offline in lapic_online()
861 return -EIO; in apic_set_affinity()
883 apic->send_IPI(apicd->cpu, apicd->vector); in apic_retrigger_irq()
919 unsigned int vector = apicd->prev_vector; in free_moved_vector()
920 unsigned int cpu = apicd->prev_cpu; in free_moved_vector()
921 bool managed = apicd->is_managed; in free_moved_vector()
930 * a non-isolated CPU which is in the calculated in free_moved_vector()
931 * affinity mask comes online. in free_moved_vector()
933 trace_vector_free_moved(apicd->irq, cpu, vector, managed); in free_moved_vector()
936 hlist_del_init(&apicd->clist); in free_moved_vector()
937 apicd->prev_vector = 0; in free_moved_vector()
938 apicd->move_in_progress = 0; in free_moved_vector()
952 unsigned int irr, vector = apicd->prev_vector; in DEFINE_IDTENTRY_SYSVEC()
961 * interrupt the device interrupt will happen first. in DEFINE_IDTENTRY_SYSVEC()
965 apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR); in DEFINE_IDTENTRY_SYSVEC()
979 apicd->move_in_progress = 0; in __send_cleanup_vector()
980 cpu = apicd->prev_cpu; in __send_cleanup_vector()
982 hlist_add_head(&apicd->clist, per_cpu_ptr(&cleanup_list, cpu)); in __send_cleanup_vector()
983 apic->send_IPI(cpu, IRQ_MOVE_CLEANUP_VECTOR); in __send_cleanup_vector()
985 apicd->prev_vector = 0; in __send_cleanup_vector()
995 if (apicd->move_in_progress) in send_cleanup_vector()
1004 if (likely(!apicd->move_in_progress)) in irq_complete_move()
1008 * If the interrupt arrived on the new target CPU, cleanup the in irq_complete_move()
1010 * because an interrupt can never move from one vector to another in irq_complete_move()
1013 if (apicd->cpu == smp_processor_id()) in irq_complete_move()
1018 * Called from fixup_irqs() with @desc->lock held and interrupts disabled.
1048 vector = apicd->prev_vector; in irq_force_complete_move()
1055 * -EBUSY. This can leave the interrupt in a stale state. in irq_force_complete_move()
1060 * 1) The interrupt is in move_in_progress state. That means that we in irq_force_complete_move()
1061 * have not seen an interrupt since the io_apic was reprogrammed to in irq_force_complete_move()
1064 * 2) The interrupt has fired on the new vector, but the cleanup IPIs in irq_force_complete_move()
1067 if (apicd->move_in_progress) { in irq_force_complete_move()
1071 * set_ioapic(new_vector) <-- Interrupt is raised before update in irq_force_complete_move()
1075 * So if the target cpu cannot handle that interrupt before in irq_force_complete_move()
1076 * the old vector is cleaned up, we get a spurious interrupt in irq_force_complete_move()
1080 * because if the affinity update happens right before all in irq_force_complete_move()
1082 * interrupt can be blocked on the target cpu because all cpus in irq_force_complete_move()
1084 * old vector is not yet cleaned up when the interrupt fires. in irq_force_complete_move()
1087 * of the interrupt on the apic/system bus would be delayed in irq_force_complete_move()
1101 irqd->irq, vector); in irq_force_complete_move()
1111 * prevent that the actual interrupt move will run out of vectors.
1124 ret = -ENOSPC; in lapic_can_unplug_cpu()
1309 int num = -1; in setup_show_lapic()