aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorPrarit Bhargava <prarit@redhat.com>2014-04-02 08:11:13 -0400
committerIngo Molnar <mingo@kernel.org>2014-04-16 07:30:49 -0400
commitfb24da805729ee4a83efa34015948f7d64da4b28 (patch)
tree507cb1fa6e38bc442b27093f46b416d3a30ab0bd /arch
parent820fca91d4b927420861eba9d30dbd4e9d3e3939 (diff)
x86/irq: Fix fixup_irqs() error handling
Several patches to fix cpu hotplug and the down'd cpu's irq relocations have been submitted in the past month or so. The patches should resolve the problems with cpu hotplug and irq relocation, however, there is always a possibility that a bug still exists. The big problem with debugging these irq reassignments is that the cpu down completes and then we get random stack traces from drivers for which irqs have not been properly assigned to a new cpu. The stack traces are a mix of storage, network, and other kernel subsystem (I once saw the serial port stop working ...) warnings and failures. The problem with these failures is that they are difficult to diagnose. There is no warning in the cpu hotplug down path to indicate that an IRQ has failed to be assigned to a new cpu, and all we are left with is a stack trace from a driver, or a non-functional device. If we had some information on the console debugging these situations would be much easier; after all we can map an IRQ to a device by simply using lspci or /proc/interrupts. The current code, fixup_irqs(), which migrates IRQs from the down'd cpu and is called close to the end of the cpu down path, calls chip->set_irq_affinity which eventually calls __assign_irq_vector(). Errors are not propogated back from this function call and this results in silent irq relocation failures. This patch fixes this issue by returning the error codes up the call stack and prints out a warning if there is a relocation failure. Signed-off-by: Prarit Bhargava <prarit@redhat.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Rui Wang <rui.y.wang@intel.com> Cc: Liu Ping Fan <kernelfans@gmail.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com> Cc: Lv Zheng <lv.zheng@intel.com> Cc: Seiji Aguchi <seiji.aguchi@hds.com> Cc: Yang Zhang <yang.z.zhang@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Steven Rostedt (Red Hat) <rostedt@goodmis.org> Cc: Li Fei <fei.li@intel.com> Cc: gong.chen@linux.intel.com Link: http://lkml.kernel.org/r/1396440673-18286-1-git-send-email-prarit@redhat.com [ Made small cleanliness tweaks. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/apic/io_apic.c28
-rw-r--r--arch/x86/kernel/irq.c13
2 files changed, 27 insertions, 14 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 6ad4658de705..b4b21db9f4ad 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2312,7 +2312,7 @@ int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
2312 int err; 2312 int err;
2313 2313
2314 if (!config_enabled(CONFIG_SMP)) 2314 if (!config_enabled(CONFIG_SMP))
2315 return -1; 2315 return -EPERM;
2316 2316
2317 if (!cpumask_intersects(mask, cpu_online_mask)) 2317 if (!cpumask_intersects(mask, cpu_online_mask))
2318 return -EINVAL; 2318 return -EINVAL;
@@ -2343,7 +2343,7 @@ int native_ioapic_set_affinity(struct irq_data *data,
2343 int ret; 2343 int ret;
2344 2344
2345 if (!config_enabled(CONFIG_SMP)) 2345 if (!config_enabled(CONFIG_SMP))
2346 return -1; 2346 return -EPERM;
2347 2347
2348 raw_spin_lock_irqsave(&ioapic_lock, flags); 2348 raw_spin_lock_irqsave(&ioapic_lock, flags);
2349 ret = __ioapic_set_affinity(data, mask, &dest); 2349 ret = __ioapic_set_affinity(data, mask, &dest);
@@ -3075,9 +3075,11 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
3075 struct irq_cfg *cfg = data->chip_data; 3075 struct irq_cfg *cfg = data->chip_data;
3076 struct msi_msg msg; 3076 struct msi_msg msg;
3077 unsigned int dest; 3077 unsigned int dest;
3078 int ret;
3078 3079
3079 if (__ioapic_set_affinity(data, mask, &dest)) 3080 ret = __ioapic_set_affinity(data, mask, &dest);
3080 return -1; 3081 if (ret)
3082 return ret;
3081 3083
3082 __get_cached_msi_msg(data->msi_desc, &msg); 3084 __get_cached_msi_msg(data->msi_desc, &msg);
3083 3085
@@ -3177,9 +3179,11 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
3177 struct irq_cfg *cfg = data->chip_data; 3179 struct irq_cfg *cfg = data->chip_data;
3178 unsigned int dest, irq = data->irq; 3180 unsigned int dest, irq = data->irq;
3179 struct msi_msg msg; 3181 struct msi_msg msg;
3182 int ret;
3180 3183
3181 if (__ioapic_set_affinity(data, mask, &dest)) 3184 ret = __ioapic_set_affinity(data, mask, &dest);
3182 return -1; 3185 if (ret)
3186 return ret;
3183 3187
3184 dmar_msi_read(irq, &msg); 3188 dmar_msi_read(irq, &msg);
3185 3189
@@ -3226,9 +3230,11 @@ static int hpet_msi_set_affinity(struct irq_data *data,
3226 struct irq_cfg *cfg = data->chip_data; 3230 struct irq_cfg *cfg = data->chip_data;
3227 struct msi_msg msg; 3231 struct msi_msg msg;
3228 unsigned int dest; 3232 unsigned int dest;
3233 int ret;
3229 3234
3230 if (__ioapic_set_affinity(data, mask, &dest)) 3235 ret = __ioapic_set_affinity(data, mask, &dest);
3231 return -1; 3236 if (ret)
3237 return ret;
3232 3238
3233 hpet_msi_read(data->handler_data, &msg); 3239 hpet_msi_read(data->handler_data, &msg);
3234 3240
@@ -3295,9 +3301,11 @@ ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
3295{ 3301{
3296 struct irq_cfg *cfg = data->chip_data; 3302 struct irq_cfg *cfg = data->chip_data;
3297 unsigned int dest; 3303 unsigned int dest;
3304 int ret;
3298 3305
3299 if (__ioapic_set_affinity(data, mask, &dest)) 3306 ret = __ioapic_set_affinity(data, mask, &dest);
3300 return -1; 3307 if (ret)
3308 return ret;
3301 3309
3302 target_ht_irq(data->irq, dest, cfg->vector); 3310 target_ht_irq(data->irq, dest, cfg->vector);
3303 return IRQ_SET_MASK_OK_NOCOPY; 3311 return IRQ_SET_MASK_OK_NOCOPY;
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 283a76a9cc40..49bbb57da7f5 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -357,6 +357,7 @@ void fixup_irqs(void)
357 struct irq_desc *desc; 357 struct irq_desc *desc;
358 struct irq_data *data; 358 struct irq_data *data;
359 struct irq_chip *chip; 359 struct irq_chip *chip;
360 int ret;
360 361
361 for_each_irq_desc(irq, desc) { 362 for_each_irq_desc(irq, desc) {
362 int break_affinity = 0; 363 int break_affinity = 0;
@@ -395,10 +396,14 @@ void fixup_irqs(void)
395 if (!irqd_can_move_in_process_context(data) && chip->irq_mask) 396 if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
396 chip->irq_mask(data); 397 chip->irq_mask(data);
397 398
398 if (chip->irq_set_affinity) 399 if (chip->irq_set_affinity) {
399 chip->irq_set_affinity(data, affinity, true); 400 ret = chip->irq_set_affinity(data, affinity, true);
400 else if (!(warned++)) 401 if (ret == -ENOSPC)
401 set_affinity = 0; 402 pr_crit("IRQ %d set affinity failed because there are no available vectors. The device assigned to this IRQ is unstable.\n", irq);
403 } else {
404 if (!(warned++))
405 set_affinity = 0;
406 }
402 407
403 /* 408 /*
404 * We unmask if the irq was not marked masked by the 409 * We unmask if the irq was not marked masked by the