diff options
| author | Thomas Gleixner <tglx@linutronix.de> | 2007-02-16 04:27:25 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-16 11:13:56 -0500 |
| commit | 771ee3b04eaac6184312825eb600b4c598f027a5 (patch) | |
| tree | f0db1cca6b9849855c1d2fd6a16828084311e03c | |
| parent | 950f4427c2ddc921164088a20f01304cf231437c (diff) | |
[PATCH] Add a function to handle interrupt affinity setting
Provide funtions to:
- check, whether an interrupt can set the affinity
- pin the interrupt to a given cpu
Necessary for the ability to setup clocksources more flexible (e.g. use the
different HPET channels per CPU)
[akpm@osdl.org: alpha build fix]
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rw-r--r-- | include/linux/irq.h | 10 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 40 | ||||
| -rw-r--r-- | kernel/irq/proc.c | 22 |
3 files changed, 51 insertions, 21 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 8930fb0ac9c7..29f715e71bdd 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -238,11 +238,21 @@ static inline void set_pending_irq(unsigned int irq, cpumask_t mask) | |||
| 238 | 238 | ||
| 239 | #endif /* CONFIG_GENERIC_PENDING_IRQ */ | 239 | #endif /* CONFIG_GENERIC_PENDING_IRQ */ |
| 240 | 240 | ||
| 241 | extern int irq_set_affinity(unsigned int irq, cpumask_t cpumask); | ||
| 242 | extern int irq_can_set_affinity(unsigned int irq); | ||
| 243 | |||
| 241 | #else /* CONFIG_SMP */ | 244 | #else /* CONFIG_SMP */ |
| 242 | 245 | ||
| 243 | #define move_native_irq(x) | 246 | #define move_native_irq(x) |
| 244 | #define move_masked_irq(x) | 247 | #define move_masked_irq(x) |
| 245 | 248 | ||
| 249 | static inline int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | ||
| 250 | { | ||
| 251 | return -EINVAL; | ||
| 252 | } | ||
| 253 | |||
| 254 | static inline int irq_can_set_affinity(unsigned int irq) { return 0; } | ||
| 255 | |||
| 246 | #endif /* CONFIG_SMP */ | 256 | #endif /* CONFIG_SMP */ |
| 247 | 257 | ||
| 248 | #ifdef CONFIG_IRQBALANCE | 258 | #ifdef CONFIG_IRQBALANCE |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index cd790ad0ae57..5597c157442a 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -38,6 +38,46 @@ void synchronize_irq(unsigned int irq) | |||
| 38 | } | 38 | } |
| 39 | EXPORT_SYMBOL(synchronize_irq); | 39 | EXPORT_SYMBOL(synchronize_irq); |
| 40 | 40 | ||
| 41 | /** | ||
| 42 | * irq_can_set_affinity - Check if the affinity of a given irq can be set | ||
| 43 | * @irq: Interrupt to check | ||
| 44 | * | ||
| 45 | */ | ||
| 46 | int irq_can_set_affinity(unsigned int irq) | ||
| 47 | { | ||
| 48 | struct irq_desc *desc = irq_desc + irq; | ||
| 49 | |||
| 50 | if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip || | ||
| 51 | !desc->chip->set_affinity) | ||
| 52 | return 0; | ||
| 53 | |||
| 54 | return 1; | ||
| 55 | } | ||
| 56 | |||
| 57 | /** | ||
| 58 | * irq_set_affinity - Set the irq affinity of a given irq | ||
| 59 | * @irq: Interrupt to set affinity | ||
| 60 | * @cpumask: cpumask | ||
| 61 | * | ||
| 62 | */ | ||
| 63 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | ||
| 64 | { | ||
| 65 | struct irq_desc *desc = irq_desc + irq; | ||
| 66 | |||
| 67 | if (!desc->chip->set_affinity) | ||
| 68 | return -EINVAL; | ||
| 69 | |||
| 70 | set_balance_irq_affinity(irq, cpumask); | ||
| 71 | |||
| 72 | #ifdef CONFIG_GENERIC_PENDING_IRQ | ||
| 73 | set_pending_irq(irq, cpumask); | ||
| 74 | #else | ||
| 75 | desc->affinity = cpumask; | ||
| 76 | desc->chip->set_affinity(irq, cpumask); | ||
| 77 | #endif | ||
| 78 | return 0; | ||
| 79 | } | ||
| 80 | |||
| 41 | #endif | 81 | #endif |
| 42 | 82 | ||
| 43 | /** | 83 | /** |
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index bb44bc995d6e..2db91eb54ad8 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
| @@ -16,26 +16,6 @@ static struct proc_dir_entry *root_irq_dir; | |||
| 16 | 16 | ||
| 17 | #ifdef CONFIG_SMP | 17 | #ifdef CONFIG_SMP |
| 18 | 18 | ||
| 19 | #ifdef CONFIG_GENERIC_PENDING_IRQ | ||
| 20 | void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) | ||
| 21 | { | ||
| 22 | set_balance_irq_affinity(irq, mask_val); | ||
| 23 | |||
| 24 | /* | ||
| 25 | * Save these away for later use. Re-progam when the | ||
| 26 | * interrupt is pending | ||
| 27 | */ | ||
| 28 | set_pending_irq(irq, mask_val); | ||
| 29 | } | ||
| 30 | #else | ||
| 31 | void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val) | ||
| 32 | { | ||
| 33 | set_balance_irq_affinity(irq, mask_val); | ||
| 34 | irq_desc[irq].affinity = mask_val; | ||
| 35 | irq_desc[irq].chip->set_affinity(irq, mask_val); | ||
| 36 | } | ||
| 37 | #endif | ||
| 38 | |||
| 39 | static int irq_affinity_read_proc(char *page, char **start, off_t off, | 19 | static int irq_affinity_read_proc(char *page, char **start, off_t off, |
| 40 | int count, int *eof, void *data) | 20 | int count, int *eof, void *data) |
| 41 | { | 21 | { |
| @@ -73,7 +53,7 @@ static int irq_affinity_write_proc(struct file *file, const char __user *buffer, | |||
| 73 | code to set default SMP affinity. */ | 53 | code to set default SMP affinity. */ |
| 74 | return select_smp_affinity(irq) ? -EINVAL : full_count; | 54 | return select_smp_affinity(irq) ? -EINVAL : full_count; |
| 75 | 55 | ||
| 76 | proc_set_irq_affinity(irq, new_value); | 56 | irq_set_affinity(irq, new_value); |
| 77 | 57 | ||
| 78 | return full_count; | 58 | return full_count; |
| 79 | } | 59 | } |
