Commit 76eae9d7 authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by David Mosberger

[PATCH] ia64: fix bug in irq_affinity_write_proc()

Writing 'R' or 'r' character to /proc/irq/<IRQ#>/smp_affinity
cause a kernel Oops. The following patch fixes this issue.
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarDavid Mosberger <davidm@hpl.hp.com>
parent 2292bf26
...@@ -88,6 +88,7 @@ irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned = { ...@@ -88,6 +88,7 @@ irq_desc_t _irq_desc[NR_IRQS] __cacheline_aligned = {
* This is updated when the user sets irq affinity via /proc * This is updated when the user sets irq affinity via /proc
*/ */
cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS]; cpumask_t __cacheline_aligned pending_irq_cpumask[NR_IRQS];
static unsigned long pending_irq_redir[BITS_TO_LONGS(NR_IRQS)];
#ifdef CONFIG_IA64_GENERIC #ifdef CONFIG_IA64_GENERIC
irq_desc_t * __ia64_irq_desc (unsigned int irq) irq_desc_t * __ia64_irq_desc (unsigned int irq)
...@@ -973,6 +974,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -973,6 +974,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
int prelen; int prelen;
irq_desc_t *desc = irq_descp(irq); irq_desc_t *desc = irq_descp(irq);
unsigned long flags; unsigned long flags;
int redir = 0;
if (!desc->handler->set_affinity) if (!desc->handler->set_affinity)
return -EIO; return -EIO;
...@@ -995,7 +997,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -995,7 +997,7 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
prelen = 0; prelen = 0;
if (tolower(*rbuf) == 'r') { if (tolower(*rbuf) == 'r') {
prelen = strspn(rbuf, "Rr "); prelen = strspn(rbuf, "Rr ");
irq |= IA64_IRQ_REDIRECTED; redir++;
} }
err = cpumask_parse(buffer+prelen, count-prelen, new_value); err = cpumask_parse(buffer+prelen, count-prelen, new_value);
...@@ -1013,6 +1015,10 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer, ...@@ -1013,6 +1015,10 @@ static int irq_affinity_write_proc (struct file *file, const char *buffer,
spin_lock_irqsave(&desc->lock, flags); spin_lock_irqsave(&desc->lock, flags);
pending_irq_cpumask[irq] = new_value; pending_irq_cpumask[irq] = new_value;
if (redir)
set_bit(irq, pending_irq_redir);
else
clear_bit(irq, pending_irq_redir);
spin_unlock_irqrestore(&desc->lock, flags); spin_unlock_irqrestore(&desc->lock, flags);
return full_count; return full_count;
...@@ -1023,11 +1029,12 @@ void move_irq(int irq) ...@@ -1023,11 +1029,12 @@ void move_irq(int irq)
/* note - we hold desc->lock */ /* note - we hold desc->lock */
cpumask_t tmp; cpumask_t tmp;
irq_desc_t *desc = irq_descp(irq); irq_desc_t *desc = irq_descp(irq);
int irq_with_redir = test_bit(irq, pending_irq_redir) ? (irq | IA64_IRQ_REDIRECTED) : irq;
if (!cpus_empty(pending_irq_cpumask[irq])) { if (!cpus_empty(pending_irq_cpumask[irq])) {
cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map); cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
if (unlikely(!cpus_empty(tmp))) { if (unlikely(!cpus_empty(tmp))) {
desc->handler->set_affinity(irq, pending_irq_cpumask[irq]); desc->handler->set_affinity(irq_with_redir, pending_irq_cpumask[irq]);
} }
cpus_clear(pending_irq_cpumask[irq]); cpus_clear(pending_irq_cpumask[irq]);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment