diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-30 16:06:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-11-30 16:06:20 -0500 |
commit | 72244c0e68dd664b894adb34a8772a6e4673b4c1 (patch) | |
tree | 5fa5bd9ff7b3d52f9b89898c0f12cfe163b72987 /kernel | |
parent | 93b10052f9146eab4e848b474baf10c2ea22acb3 (diff) | |
parent | 2ed1cdcf9a83205d1343f29b630abff232eaa72c (diff) |
Merge branch 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
irq.h: fix missing/extra kernel-doc
genirq: __irq_set_trigger: change pr_warning to pr_debug
irq: fix typo
x86: apic honour irq affinity which was set in early boot
genirq: fix the affinity setting in setup_irq
genirq: keep affinities set from userspace across free/request_irq()
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/irq/internals.h | 2 | ||||
-rw-r--r-- | kernel/irq/manage.c | 68 | ||||
-rw-r--r-- | kernel/irq/migration.c | 11 | ||||
-rw-r--r-- | kernel/irq/proc.c | 2 |
4 files changed, 56 insertions, 27 deletions
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index c9767e641980..64c1c7253dae 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
@@ -25,6 +25,8 @@ static inline void unregister_handler_proc(unsigned int irq, | |||
25 | struct irqaction *action) { } | 25 | struct irqaction *action) { } |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | extern int irq_select_affinity_usr(unsigned int irq); | ||
29 | |||
28 | /* | 30 | /* |
29 | * Debugging printout: | 31 | * Debugging printout: |
30 | */ | 32 | */ |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index c498a1b8c621..801addda3c43 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -82,24 +82,27 @@ int irq_can_set_affinity(unsigned int irq) | |||
82 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | 82 | int irq_set_affinity(unsigned int irq, cpumask_t cpumask) |
83 | { | 83 | { |
84 | struct irq_desc *desc = irq_to_desc(irq); | 84 | struct irq_desc *desc = irq_to_desc(irq); |
85 | unsigned long flags; | ||
85 | 86 | ||
86 | if (!desc->chip->set_affinity) | 87 | if (!desc->chip->set_affinity) |
87 | return -EINVAL; | 88 | return -EINVAL; |
88 | 89 | ||
90 | spin_lock_irqsave(&desc->lock, flags); | ||
91 | |||
89 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 92 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
90 | if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { | 93 | if (desc->status & IRQ_MOVE_PCNTXT || desc->status & IRQ_DISABLED) { |
91 | unsigned long flags; | ||
92 | |||
93 | spin_lock_irqsave(&desc->lock, flags); | ||
94 | desc->affinity = cpumask; | 94 | desc->affinity = cpumask; |
95 | desc->chip->set_affinity(irq, cpumask); | 95 | desc->chip->set_affinity(irq, cpumask); |
96 | spin_unlock_irqrestore(&desc->lock, flags); | 96 | } else { |
97 | } else | 97 | desc->status |= IRQ_MOVE_PENDING; |
98 | set_pending_irq(irq, cpumask); | 98 | desc->pending_mask = cpumask; |
99 | } | ||
99 | #else | 100 | #else |
100 | desc->affinity = cpumask; | 101 | desc->affinity = cpumask; |
101 | desc->chip->set_affinity(irq, cpumask); | 102 | desc->chip->set_affinity(irq, cpumask); |
102 | #endif | 103 | #endif |
104 | desc->status |= IRQ_AFFINITY_SET; | ||
105 | spin_unlock_irqrestore(&desc->lock, flags); | ||
103 | return 0; | 106 | return 0; |
104 | } | 107 | } |
105 | 108 | ||
@@ -107,24 +110,59 @@ int irq_set_affinity(unsigned int irq, cpumask_t cpumask) | |||
107 | /* | 110 | /* |
108 | * Generic version of the affinity autoselector. | 111 | * Generic version of the affinity autoselector. |
109 | */ | 112 | */ |
110 | int irq_select_affinity(unsigned int irq) | 113 | int do_irq_select_affinity(unsigned int irq, struct irq_desc *desc) |
111 | { | 114 | { |
112 | cpumask_t mask; | 115 | cpumask_t mask; |
113 | struct irq_desc *desc; | ||
114 | 116 | ||
115 | if (!irq_can_set_affinity(irq)) | 117 | if (!irq_can_set_affinity(irq)) |
116 | return 0; | 118 | return 0; |
117 | 119 | ||
118 | cpus_and(mask, cpu_online_map, irq_default_affinity); | 120 | cpus_and(mask, cpu_online_map, irq_default_affinity); |
119 | 121 | ||
120 | desc = irq_to_desc(irq); | 122 | /* |
123 | * Preserve an userspace affinity setup, but make sure that | ||
124 | * one of the targets is online. | ||
125 | */ | ||
126 | if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) { | ||
127 | if (cpus_intersects(desc->affinity, cpu_online_map)) | ||
128 | mask = desc->affinity; | ||
129 | else | ||
130 | desc->status &= ~IRQ_AFFINITY_SET; | ||
131 | } | ||
132 | |||
121 | desc->affinity = mask; | 133 | desc->affinity = mask; |
122 | desc->chip->set_affinity(irq, mask); | 134 | desc->chip->set_affinity(irq, mask); |
123 | 135 | ||
124 | return 0; | 136 | return 0; |
125 | } | 137 | } |
138 | #else | ||
139 | static inline int do_irq_select_affinity(unsigned int irq, struct irq_desc *d) | ||
140 | { | ||
141 | return irq_select_affinity(irq); | ||
142 | } | ||
126 | #endif | 143 | #endif |
127 | 144 | ||
145 | /* | ||
146 | * Called when affinity is set via /proc/irq | ||
147 | */ | ||
148 | int irq_select_affinity_usr(unsigned int irq) | ||
149 | { | ||
150 | struct irq_desc *desc = irq_to_desc(irq); | ||
151 | unsigned long flags; | ||
152 | int ret; | ||
153 | |||
154 | spin_lock_irqsave(&desc->lock, flags); | ||
155 | ret = do_irq_select_affinity(irq, desc); | ||
156 | spin_unlock_irqrestore(&desc->lock, flags); | ||
157 | |||
158 | return ret; | ||
159 | } | ||
160 | |||
161 | #else | ||
162 | static inline int do_irq_select_affinity(int irq, struct irq_desc *desc) | ||
163 | { | ||
164 | return 0; | ||
165 | } | ||
128 | #endif | 166 | #endif |
129 | 167 | ||
130 | /** | 168 | /** |
@@ -327,7 +365,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
327 | * IRQF_TRIGGER_* but the PIC does not support multiple | 365 | * IRQF_TRIGGER_* but the PIC does not support multiple |
328 | * flow-types? | 366 | * flow-types? |
329 | */ | 367 | */ |
330 | pr_warning("No set_type function for IRQ %d (%s)\n", irq, | 368 | pr_debug("No set_type function for IRQ %d (%s)\n", irq, |
331 | chip ? (chip->name ? : "unknown") : "unknown"); | 369 | chip ? (chip->name ? : "unknown") : "unknown"); |
332 | return 0; | 370 | return 0; |
333 | } | 371 | } |
@@ -445,8 +483,12 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
445 | /* Undo nested disables: */ | 483 | /* Undo nested disables: */ |
446 | desc->depth = 1; | 484 | desc->depth = 1; |
447 | 485 | ||
486 | /* Exclude IRQ from balancing if requested */ | ||
487 | if (new->flags & IRQF_NOBALANCING) | ||
488 | desc->status |= IRQ_NO_BALANCING; | ||
489 | |||
448 | /* Set default affinity mask once everything is setup */ | 490 | /* Set default affinity mask once everything is setup */ |
449 | irq_select_affinity(irq); | 491 | do_irq_select_affinity(irq, desc); |
450 | 492 | ||
451 | } else if ((new->flags & IRQF_TRIGGER_MASK) | 493 | } else if ((new->flags & IRQF_TRIGGER_MASK) |
452 | && (new->flags & IRQF_TRIGGER_MASK) | 494 | && (new->flags & IRQF_TRIGGER_MASK) |
@@ -459,10 +501,6 @@ __setup_irq(unsigned int irq, struct irq_desc * desc, struct irqaction *new) | |||
459 | 501 | ||
460 | *p = new; | 502 | *p = new; |
461 | 503 | ||
462 | /* Exclude IRQ from balancing */ | ||
463 | if (new->flags & IRQF_NOBALANCING) | ||
464 | desc->status |= IRQ_NO_BALANCING; | ||
465 | |||
466 | /* Reset broken irq detection when installing new handler */ | 504 | /* Reset broken irq detection when installing new handler */ |
467 | desc->irq_count = 0; | 505 | desc->irq_count = 0; |
468 | desc->irqs_unhandled = 0; | 506 | desc->irqs_unhandled = 0; |
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c index 90b920d3f52b..9db681d95814 100644 --- a/kernel/irq/migration.c +++ b/kernel/irq/migration.c | |||
@@ -1,17 +1,6 @@ | |||
1 | 1 | ||
2 | #include <linux/irq.h> | 2 | #include <linux/irq.h> |
3 | 3 | ||
4 | void set_pending_irq(unsigned int irq, cpumask_t mask) | ||
5 | { | ||
6 | struct irq_desc *desc = irq_to_desc(irq); | ||
7 | unsigned long flags; | ||
8 | |||
9 | spin_lock_irqsave(&desc->lock, flags); | ||
10 | desc->status |= IRQ_MOVE_PENDING; | ||
11 | desc->pending_mask = mask; | ||
12 | spin_unlock_irqrestore(&desc->lock, flags); | ||
13 | } | ||
14 | |||
15 | void move_masked_irq(int irq) | 4 | void move_masked_irq(int irq) |
16 | { | 5 | { |
17 | struct irq_desc *desc = irq_to_desc(irq); | 6 | struct irq_desc *desc = irq_to_desc(irq); |
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 4d161c70ba55..d257e7d6a8a4 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c | |||
@@ -62,7 +62,7 @@ static ssize_t irq_affinity_proc_write(struct file *file, | |||
62 | if (!cpus_intersects(new_value, cpu_online_map)) | 62 | if (!cpus_intersects(new_value, cpu_online_map)) |
63 | /* Special case for empty set - allow the architecture | 63 | /* Special case for empty set - allow the architecture |
64 | code to set default SMP affinity. */ | 64 | code to set default SMP affinity. */ |
65 | return irq_select_affinity(irq) ? -EINVAL : count; | 65 | return irq_select_affinity_usr(irq) ? -EINVAL : count; |
66 | 66 | ||
67 | irq_set_affinity(irq, new_value); | 67 | irq_set_affinity(irq, new_value); |
68 | 68 | ||