diff options
Diffstat (limited to 'kernel/irq/chip.c')
| -rw-r--r-- | kernel/irq/chip.c | 378 |
1 files changed, 197 insertions, 181 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index b7091d5ca2f8..baa5c4acad83 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -18,108 +18,6 @@ | |||
| 18 | 18 | ||
| 19 | #include "internals.h" | 19 | #include "internals.h" |
| 20 | 20 | ||
| 21 | static void dynamic_irq_init_x(unsigned int irq, bool keep_chip_data) | ||
| 22 | { | ||
| 23 | struct irq_desc *desc; | ||
| 24 | unsigned long flags; | ||
| 25 | |||
| 26 | desc = irq_to_desc(irq); | ||
| 27 | if (!desc) { | ||
| 28 | WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq); | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | /* Ensure we don't have left over values from a previous use of this irq */ | ||
| 33 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 34 | desc->status = IRQ_DISABLED; | ||
| 35 | desc->chip = &no_irq_chip; | ||
| 36 | desc->handle_irq = handle_bad_irq; | ||
| 37 | desc->depth = 1; | ||
| 38 | desc->msi_desc = NULL; | ||
| 39 | desc->handler_data = NULL; | ||
| 40 | if (!keep_chip_data) | ||
| 41 | desc->chip_data = NULL; | ||
| 42 | desc->action = NULL; | ||
| 43 | desc->irq_count = 0; | ||
| 44 | desc->irqs_unhandled = 0; | ||
| 45 | #ifdef CONFIG_SMP | ||
| 46 | cpumask_setall(desc->affinity); | ||
| 47 | #ifdef CONFIG_GENERIC_PENDING_IRQ | ||
| 48 | cpumask_clear(desc->pending_mask); | ||
| 49 | #endif | ||
| 50 | #endif | ||
| 51 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 52 | } | ||
| 53 | |||
| 54 | /** | ||
| 55 | * dynamic_irq_init - initialize a dynamically allocated irq | ||
| 56 | * @irq: irq number to initialize | ||
| 57 | */ | ||
| 58 | void dynamic_irq_init(unsigned int irq) | ||
| 59 | { | ||
| 60 | dynamic_irq_init_x(irq, false); | ||
| 61 | } | ||
| 62 | |||
| 63 | /** | ||
| 64 | * dynamic_irq_init_keep_chip_data - initialize a dynamically allocated irq | ||
| 65 | * @irq: irq number to initialize | ||
| 66 | * | ||
| 67 | * does not set irq_to_desc(irq)->chip_data to NULL | ||
| 68 | */ | ||
| 69 | void dynamic_irq_init_keep_chip_data(unsigned int irq) | ||
| 70 | { | ||
| 71 | dynamic_irq_init_x(irq, true); | ||
| 72 | } | ||
| 73 | |||
| 74 | static void dynamic_irq_cleanup_x(unsigned int irq, bool keep_chip_data) | ||
| 75 | { | ||
| 76 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 77 | unsigned long flags; | ||
| 78 | |||
| 79 | if (!desc) { | ||
| 80 | WARN(1, KERN_ERR "Trying to cleanup invalid IRQ%d\n", irq); | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | |||
| 84 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 85 | if (desc->action) { | ||
| 86 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 87 | WARN(1, KERN_ERR "Destroying IRQ%d without calling free_irq\n", | ||
| 88 | irq); | ||
| 89 | return; | ||
| 90 | } | ||
| 91 | desc->msi_desc = NULL; | ||
| 92 | desc->handler_data = NULL; | ||
| 93 | if (!keep_chip_data) | ||
| 94 | desc->chip_data = NULL; | ||
| 95 | desc->handle_irq = handle_bad_irq; | ||
| 96 | desc->chip = &no_irq_chip; | ||
| 97 | desc->name = NULL; | ||
| 98 | clear_kstat_irqs(desc); | ||
| 99 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 100 | } | ||
| 101 | |||
| 102 | /** | ||
| 103 | * dynamic_irq_cleanup - cleanup a dynamically allocated irq | ||
| 104 | * @irq: irq number to initialize | ||
| 105 | */ | ||
| 106 | void dynamic_irq_cleanup(unsigned int irq) | ||
| 107 | { | ||
| 108 | dynamic_irq_cleanup_x(irq, false); | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * dynamic_irq_cleanup_keep_chip_data - cleanup a dynamically allocated irq | ||
| 113 | * @irq: irq number to initialize | ||
| 114 | * | ||
| 115 | * does not set irq_to_desc(irq)->chip_data to NULL | ||
| 116 | */ | ||
| 117 | void dynamic_irq_cleanup_keep_chip_data(unsigned int irq) | ||
| 118 | { | ||
| 119 | dynamic_irq_cleanup_x(irq, true); | ||
| 120 | } | ||
| 121 | |||
| 122 | |||
| 123 | /** | 21 | /** |
| 124 | * set_irq_chip - set the irq chip for an irq | 22 | * set_irq_chip - set the irq chip for an irq |
| 125 | * @irq: irq number | 23 | * @irq: irq number |
| @@ -140,7 +38,7 @@ int set_irq_chip(unsigned int irq, struct irq_chip *chip) | |||
| 140 | 38 | ||
| 141 | raw_spin_lock_irqsave(&desc->lock, flags); | 39 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 142 | irq_chip_set_defaults(chip); | 40 | irq_chip_set_defaults(chip); |
| 143 | desc->chip = chip; | 41 | desc->irq_data.chip = chip; |
| 144 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 42 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 145 | 43 | ||
| 146 | return 0; | 44 | return 0; |
| @@ -193,7 +91,7 @@ int set_irq_data(unsigned int irq, void *data) | |||
| 193 | } | 91 | } |
| 194 | 92 | ||
| 195 | raw_spin_lock_irqsave(&desc->lock, flags); | 93 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 196 | desc->handler_data = data; | 94 | desc->irq_data.handler_data = data; |
| 197 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 95 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 198 | return 0; | 96 | return 0; |
| 199 | } | 97 | } |
| @@ -218,7 +116,7 @@ int set_irq_msi(unsigned int irq, struct msi_desc *entry) | |||
| 218 | } | 116 | } |
| 219 | 117 | ||
| 220 | raw_spin_lock_irqsave(&desc->lock, flags); | 118 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 221 | desc->msi_desc = entry; | 119 | desc->irq_data.msi_desc = entry; |
| 222 | if (entry) | 120 | if (entry) |
| 223 | entry->irq = irq; | 121 | entry->irq = irq; |
| 224 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 122 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| @@ -243,19 +141,27 @@ int set_irq_chip_data(unsigned int irq, void *data) | |||
| 243 | return -EINVAL; | 141 | return -EINVAL; |
| 244 | } | 142 | } |
| 245 | 143 | ||
| 246 | if (!desc->chip) { | 144 | if (!desc->irq_data.chip) { |
| 247 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); | 145 | printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); |
| 248 | return -EINVAL; | 146 | return -EINVAL; |
| 249 | } | 147 | } |
| 250 | 148 | ||
| 251 | raw_spin_lock_irqsave(&desc->lock, flags); | 149 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 252 | desc->chip_data = data; | 150 | desc->irq_data.chip_data = data; |
| 253 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 151 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 254 | 152 | ||
| 255 | return 0; | 153 | return 0; |
| 256 | } | 154 | } |
| 257 | EXPORT_SYMBOL(set_irq_chip_data); | 155 | EXPORT_SYMBOL(set_irq_chip_data); |
| 258 | 156 | ||
| 157 | struct irq_data *irq_get_irq_data(unsigned int irq) | ||
| 158 | { | ||
| 159 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 160 | |||
| 161 | return desc ? &desc->irq_data : NULL; | ||
| 162 | } | ||
| 163 | EXPORT_SYMBOL_GPL(irq_get_irq_data); | ||
| 164 | |||
| 259 | /** | 165 | /** |
| 260 | * set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq | 166 | * set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq |
| 261 | * | 167 | * |
| @@ -287,93 +193,216 @@ EXPORT_SYMBOL_GPL(set_irq_nested_thread); | |||
| 287 | /* | 193 | /* |
| 288 | * default enable function | 194 | * default enable function |
| 289 | */ | 195 | */ |
| 290 | static void default_enable(unsigned int irq) | 196 | static void default_enable(struct irq_data *data) |
| 291 | { | 197 | { |
| 292 | struct irq_desc *desc = irq_to_desc(irq); | 198 | struct irq_desc *desc = irq_data_to_desc(data); |
| 293 | 199 | ||
| 294 | desc->chip->unmask(irq); | 200 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
| 295 | desc->status &= ~IRQ_MASKED; | 201 | desc->status &= ~IRQ_MASKED; |
| 296 | } | 202 | } |
| 297 | 203 | ||
| 298 | /* | 204 | /* |
| 299 | * default disable function | 205 | * default disable function |
| 300 | */ | 206 | */ |
| 301 | static void default_disable(unsigned int irq) | 207 | static void default_disable(struct irq_data *data) |
| 302 | { | 208 | { |
| 303 | } | 209 | } |
| 304 | 210 | ||
| 305 | /* | 211 | /* |
| 306 | * default startup function | 212 | * default startup function |
| 307 | */ | 213 | */ |
| 308 | static unsigned int default_startup(unsigned int irq) | 214 | static unsigned int default_startup(struct irq_data *data) |
| 309 | { | 215 | { |
| 310 | struct irq_desc *desc = irq_to_desc(irq); | 216 | struct irq_desc *desc = irq_data_to_desc(data); |
| 311 | 217 | ||
| 312 | desc->chip->enable(irq); | 218 | desc->irq_data.chip->irq_enable(data); |
| 313 | return 0; | 219 | return 0; |
| 314 | } | 220 | } |
| 315 | 221 | ||
| 316 | /* | 222 | /* |
| 317 | * default shutdown function | 223 | * default shutdown function |
| 318 | */ | 224 | */ |
| 319 | static void default_shutdown(unsigned int irq) | 225 | static void default_shutdown(struct irq_data *data) |
| 320 | { | 226 | { |
| 321 | struct irq_desc *desc = irq_to_desc(irq); | 227 | struct irq_desc *desc = irq_data_to_desc(data); |
| 322 | 228 | ||
| 323 | desc->chip->mask(irq); | 229 | desc->irq_data.chip->irq_mask(&desc->irq_data); |
| 324 | desc->status |= IRQ_MASKED; | 230 | desc->status |= IRQ_MASKED; |
| 325 | } | 231 | } |
| 326 | 232 | ||
| 233 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED | ||
| 234 | /* Temporary migration helpers */ | ||
| 235 | static void compat_irq_mask(struct irq_data *data) | ||
| 236 | { | ||
| 237 | data->chip->mask(data->irq); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void compat_irq_unmask(struct irq_data *data) | ||
| 241 | { | ||
| 242 | data->chip->unmask(data->irq); | ||
| 243 | } | ||
| 244 | |||
| 245 | static void compat_irq_ack(struct irq_data *data) | ||
| 246 | { | ||
| 247 | data->chip->ack(data->irq); | ||
| 248 | } | ||
| 249 | |||
| 250 | static void compat_irq_mask_ack(struct irq_data *data) | ||
| 251 | { | ||
| 252 | data->chip->mask_ack(data->irq); | ||
| 253 | } | ||
| 254 | |||
| 255 | static void compat_irq_eoi(struct irq_data *data) | ||
| 256 | { | ||
| 257 | data->chip->eoi(data->irq); | ||
| 258 | } | ||
| 259 | |||
| 260 | static void compat_irq_enable(struct irq_data *data) | ||
| 261 | { | ||
| 262 | data->chip->enable(data->irq); | ||
| 263 | } | ||
| 264 | |||
| 265 | static void compat_irq_disable(struct irq_data *data) | ||
| 266 | { | ||
| 267 | data->chip->disable(data->irq); | ||
| 268 | } | ||
| 269 | |||
| 270 | static void compat_irq_shutdown(struct irq_data *data) | ||
| 271 | { | ||
| 272 | data->chip->shutdown(data->irq); | ||
| 273 | } | ||
| 274 | |||
| 275 | static unsigned int compat_irq_startup(struct irq_data *data) | ||
| 276 | { | ||
| 277 | return data->chip->startup(data->irq); | ||
| 278 | } | ||
| 279 | |||
| 280 | static int compat_irq_set_affinity(struct irq_data *data, | ||
| 281 | const struct cpumask *dest, bool force) | ||
| 282 | { | ||
| 283 | return data->chip->set_affinity(data->irq, dest); | ||
| 284 | } | ||
| 285 | |||
| 286 | static int compat_irq_set_type(struct irq_data *data, unsigned int type) | ||
| 287 | { | ||
| 288 | return data->chip->set_type(data->irq, type); | ||
| 289 | } | ||
| 290 | |||
| 291 | static int compat_irq_set_wake(struct irq_data *data, unsigned int on) | ||
| 292 | { | ||
| 293 | return data->chip->set_wake(data->irq, on); | ||
| 294 | } | ||
| 295 | |||
| 296 | static int compat_irq_retrigger(struct irq_data *data) | ||
| 297 | { | ||
| 298 | return data->chip->retrigger(data->irq); | ||
| 299 | } | ||
| 300 | |||
| 301 | static void compat_bus_lock(struct irq_data *data) | ||
| 302 | { | ||
| 303 | data->chip->bus_lock(data->irq); | ||
| 304 | } | ||
| 305 | |||
| 306 | static void compat_bus_sync_unlock(struct irq_data *data) | ||
| 307 | { | ||
| 308 | data->chip->bus_sync_unlock(data->irq); | ||
| 309 | } | ||
| 310 | #endif | ||
| 311 | |||
| 327 | /* | 312 | /* |
| 328 | * Fixup enable/disable function pointers | 313 | * Fixup enable/disable function pointers |
| 329 | */ | 314 | */ |
| 330 | void irq_chip_set_defaults(struct irq_chip *chip) | 315 | void irq_chip_set_defaults(struct irq_chip *chip) |
| 331 | { | 316 | { |
| 332 | if (!chip->enable) | 317 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED |
| 333 | chip->enable = default_enable; | ||
| 334 | if (!chip->disable) | ||
| 335 | chip->disable = default_disable; | ||
| 336 | if (!chip->startup) | ||
| 337 | chip->startup = default_startup; | ||
| 338 | /* | 318 | /* |
| 339 | * We use chip->disable, when the user provided its own. When | 319 | * Compat fixup functions need to be before we set the |
| 340 | * we have default_disable set for chip->disable, then we need | 320 | * defaults for enable/disable/startup/shutdown |
| 321 | */ | ||
| 322 | if (chip->enable) | ||
| 323 | chip->irq_enable = compat_irq_enable; | ||
| 324 | if (chip->disable) | ||
| 325 | chip->irq_disable = compat_irq_disable; | ||
| 326 | if (chip->shutdown) | ||
| 327 | chip->irq_shutdown = compat_irq_shutdown; | ||
| 328 | if (chip->startup) | ||
| 329 | chip->irq_startup = compat_irq_startup; | ||
| 330 | #endif | ||
| 331 | /* | ||
| 332 | * The real defaults | ||
| 333 | */ | ||
| 334 | if (!chip->irq_enable) | ||
| 335 | chip->irq_enable = default_enable; | ||
| 336 | if (!chip->irq_disable) | ||
| 337 | chip->irq_disable = default_disable; | ||
| 338 | if (!chip->irq_startup) | ||
| 339 | chip->irq_startup = default_startup; | ||
| 340 | /* | ||
| 341 | * We use chip->irq_disable, when the user provided its own. When | ||
| 342 | * we have default_disable set for chip->irq_disable, then we need | ||
| 341 | * to use default_shutdown, otherwise the irq line is not | 343 | * to use default_shutdown, otherwise the irq line is not |
| 342 | * disabled on free_irq(): | 344 | * disabled on free_irq(): |
| 343 | */ | 345 | */ |
| 344 | if (!chip->shutdown) | 346 | if (!chip->irq_shutdown) |
| 345 | chip->shutdown = chip->disable != default_disable ? | 347 | chip->irq_shutdown = chip->irq_disable != default_disable ? |
| 346 | chip->disable : default_shutdown; | 348 | chip->irq_disable : default_shutdown; |
| 347 | if (!chip->name) | 349 | |
| 348 | chip->name = chip->typename; | 350 | #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED |
| 349 | if (!chip->end) | 351 | if (!chip->end) |
| 350 | chip->end = dummy_irq_chip.end; | 352 | chip->end = dummy_irq_chip.end; |
| 353 | |||
| 354 | /* | ||
| 355 | * Now fix up the remaining compat handlers | ||
| 356 | */ | ||
| 357 | if (chip->bus_lock) | ||
| 358 | chip->irq_bus_lock = compat_bus_lock; | ||
| 359 | if (chip->bus_sync_unlock) | ||
| 360 | chip->irq_bus_sync_unlock = compat_bus_sync_unlock; | ||
| 361 | if (chip->mask) | ||
| 362 | chip->irq_mask = compat_irq_mask; | ||
| 363 | if (chip->unmask) | ||
| 364 | chip->irq_unmask = compat_irq_unmask; | ||
| 365 | if (chip->ack) | ||
| 366 | chip->irq_ack = compat_irq_ack; | ||
| 367 | if (chip->mask_ack) | ||
| 368 | chip->irq_mask_ack = compat_irq_mask_ack; | ||
| 369 | if (chip->eoi) | ||
| 370 | chip->irq_eoi = compat_irq_eoi; | ||
| 371 | if (chip->set_affinity) | ||
| 372 | chip->irq_set_affinity = compat_irq_set_affinity; | ||
| 373 | if (chip->set_type) | ||
| 374 | chip->irq_set_type = compat_irq_set_type; | ||
| 375 | if (chip->set_wake) | ||
| 376 | chip->irq_set_wake = compat_irq_set_wake; | ||
| 377 | if (chip->retrigger) | ||
| 378 | chip->irq_retrigger = compat_irq_retrigger; | ||
| 379 | #endif | ||
| 351 | } | 380 | } |
| 352 | 381 | ||
| 353 | static inline void mask_ack_irq(struct irq_desc *desc, int irq) | 382 | static inline void mask_ack_irq(struct irq_desc *desc) |
| 354 | { | 383 | { |
| 355 | if (desc->chip->mask_ack) | 384 | if (desc->irq_data.chip->irq_mask_ack) |
| 356 | desc->chip->mask_ack(irq); | 385 | desc->irq_data.chip->irq_mask_ack(&desc->irq_data); |
| 357 | else { | 386 | else { |
| 358 | desc->chip->mask(irq); | 387 | desc->irq_data.chip->irq_mask(&desc->irq_data); |
| 359 | if (desc->chip->ack) | 388 | if (desc->irq_data.chip->irq_ack) |
| 360 | desc->chip->ack(irq); | 389 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
| 361 | } | 390 | } |
| 362 | desc->status |= IRQ_MASKED; | 391 | desc->status |= IRQ_MASKED; |
| 363 | } | 392 | } |
| 364 | 393 | ||
| 365 | static inline void mask_irq(struct irq_desc *desc, int irq) | 394 | static inline void mask_irq(struct irq_desc *desc) |
| 366 | { | 395 | { |
| 367 | if (desc->chip->mask) { | 396 | if (desc->irq_data.chip->irq_mask) { |
| 368 | desc->chip->mask(irq); | 397 | desc->irq_data.chip->irq_mask(&desc->irq_data); |
| 369 | desc->status |= IRQ_MASKED; | 398 | desc->status |= IRQ_MASKED; |
| 370 | } | 399 | } |
| 371 | } | 400 | } |
| 372 | 401 | ||
| 373 | static inline void unmask_irq(struct irq_desc *desc, int irq) | 402 | static inline void unmask_irq(struct irq_desc *desc) |
| 374 | { | 403 | { |
| 375 | if (desc->chip->unmask) { | 404 | if (desc->irq_data.chip->irq_unmask) { |
| 376 | desc->chip->unmask(irq); | 405 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
| 377 | desc->status &= ~IRQ_MASKED; | 406 | desc->status &= ~IRQ_MASKED; |
| 378 | } | 407 | } |
| 379 | } | 408 | } |
| @@ -476,7 +505,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 476 | irqreturn_t action_ret; | 505 | irqreturn_t action_ret; |
| 477 | 506 | ||
| 478 | raw_spin_lock(&desc->lock); | 507 | raw_spin_lock(&desc->lock); |
| 479 | mask_ack_irq(desc, irq); | 508 | mask_ack_irq(desc); |
| 480 | 509 | ||
| 481 | if (unlikely(desc->status & IRQ_INPROGRESS)) | 510 | if (unlikely(desc->status & IRQ_INPROGRESS)) |
| 482 | goto out_unlock; | 511 | goto out_unlock; |
| @@ -502,7 +531,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 502 | desc->status &= ~IRQ_INPROGRESS; | 531 | desc->status &= ~IRQ_INPROGRESS; |
| 503 | 532 | ||
| 504 | if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT))) | 533 | if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT))) |
| 505 | unmask_irq(desc, irq); | 534 | unmask_irq(desc); |
| 506 | out_unlock: | 535 | out_unlock: |
| 507 | raw_spin_unlock(&desc->lock); | 536 | raw_spin_unlock(&desc->lock); |
| 508 | } | 537 | } |
| @@ -539,7 +568,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 539 | action = desc->action; | 568 | action = desc->action; |
| 540 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) { | 569 | if (unlikely(!action || (desc->status & IRQ_DISABLED))) { |
| 541 | desc->status |= IRQ_PENDING; | 570 | desc->status |= IRQ_PENDING; |
| 542 | mask_irq(desc, irq); | 571 | mask_irq(desc); |
| 543 | goto out; | 572 | goto out; |
| 544 | } | 573 | } |
| 545 | 574 | ||
| @@ -554,7 +583,7 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 554 | raw_spin_lock(&desc->lock); | 583 | raw_spin_lock(&desc->lock); |
| 555 | desc->status &= ~IRQ_INPROGRESS; | 584 | desc->status &= ~IRQ_INPROGRESS; |
| 556 | out: | 585 | out: |
| 557 | desc->chip->eoi(irq); | 586 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
| 558 | 587 | ||
| 559 | raw_spin_unlock(&desc->lock); | 588 | raw_spin_unlock(&desc->lock); |
| 560 | } | 589 | } |
| @@ -590,14 +619,13 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 590 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || | 619 | if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || |
| 591 | !desc->action)) { | 620 | !desc->action)) { |
| 592 | desc->status |= (IRQ_PENDING | IRQ_MASKED); | 621 | desc->status |= (IRQ_PENDING | IRQ_MASKED); |
| 593 | mask_ack_irq(desc, irq); | 622 | mask_ack_irq(desc); |
| 594 | goto out_unlock; | 623 | goto out_unlock; |
| 595 | } | 624 | } |
| 596 | kstat_incr_irqs_this_cpu(irq, desc); | 625 | kstat_incr_irqs_this_cpu(irq, desc); |
| 597 | 626 | ||
| 598 | /* Start handling the irq */ | 627 | /* Start handling the irq */ |
| 599 | if (desc->chip->ack) | 628 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
| 600 | desc->chip->ack(irq); | ||
| 601 | 629 | ||
| 602 | /* Mark the IRQ currently in progress.*/ | 630 | /* Mark the IRQ currently in progress.*/ |
| 603 | desc->status |= IRQ_INPROGRESS; | 631 | desc->status |= IRQ_INPROGRESS; |
| @@ -607,7 +635,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 607 | irqreturn_t action_ret; | 635 | irqreturn_t action_ret; |
| 608 | 636 | ||
| 609 | if (unlikely(!action)) { | 637 | if (unlikely(!action)) { |
| 610 | mask_irq(desc, irq); | 638 | mask_irq(desc); |
| 611 | goto out_unlock; | 639 | goto out_unlock; |
| 612 | } | 640 | } |
| 613 | 641 | ||
| @@ -619,7 +647,7 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc) | |||
| 619 | if (unlikely((desc->status & | 647 | if (unlikely((desc->status & |
| 620 | (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == | 648 | (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == |
| 621 | (IRQ_PENDING | IRQ_MASKED))) { | 649 | (IRQ_PENDING | IRQ_MASKED))) { |
| 622 | unmask_irq(desc, irq); | 650 | unmask_irq(desc); |
| 623 | } | 651 | } |
| 624 | 652 | ||
| 625 | desc->status &= ~IRQ_PENDING; | 653 | desc->status &= ~IRQ_PENDING; |
| @@ -650,15 +678,15 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc) | |||
| 650 | 678 | ||
| 651 | kstat_incr_irqs_this_cpu(irq, desc); | 679 | kstat_incr_irqs_this_cpu(irq, desc); |
| 652 | 680 | ||
| 653 | if (desc->chip->ack) | 681 | if (desc->irq_data.chip->irq_ack) |
| 654 | desc->chip->ack(irq); | 682 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
| 655 | 683 | ||
| 656 | action_ret = handle_IRQ_event(irq, desc->action); | 684 | action_ret = handle_IRQ_event(irq, desc->action); |
| 657 | if (!noirqdebug) | 685 | if (!noirqdebug) |
| 658 | note_interrupt(irq, desc, action_ret); | 686 | note_interrupt(irq, desc, action_ret); |
| 659 | 687 | ||
| 660 | if (desc->chip->eoi) | 688 | if (desc->irq_data.chip->irq_eoi) |
| 661 | desc->chip->eoi(irq); | 689 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
| 662 | } | 690 | } |
| 663 | 691 | ||
| 664 | void | 692 | void |
| @@ -676,7 +704,7 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
| 676 | 704 | ||
| 677 | if (!handle) | 705 | if (!handle) |
| 678 | handle = handle_bad_irq; | 706 | handle = handle_bad_irq; |
| 679 | else if (desc->chip == &no_irq_chip) { | 707 | else if (desc->irq_data.chip == &no_irq_chip) { |
| 680 | printk(KERN_WARNING "Trying to install %sinterrupt handler " | 708 | printk(KERN_WARNING "Trying to install %sinterrupt handler " |
| 681 | "for IRQ%d\n", is_chained ? "chained " : "", irq); | 709 | "for IRQ%d\n", is_chained ? "chained " : "", irq); |
| 682 | /* | 710 | /* |
| @@ -686,16 +714,16 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
| 686 | * prevent us to setup the interrupt at all. Switch it to | 714 | * prevent us to setup the interrupt at all. Switch it to |
| 687 | * dummy_irq_chip for easy transition. | 715 | * dummy_irq_chip for easy transition. |
| 688 | */ | 716 | */ |
| 689 | desc->chip = &dummy_irq_chip; | 717 | desc->irq_data.chip = &dummy_irq_chip; |
| 690 | } | 718 | } |
| 691 | 719 | ||
| 692 | chip_bus_lock(irq, desc); | 720 | chip_bus_lock(desc); |
| 693 | raw_spin_lock_irqsave(&desc->lock, flags); | 721 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 694 | 722 | ||
| 695 | /* Uninstall? */ | 723 | /* Uninstall? */ |
| 696 | if (handle == handle_bad_irq) { | 724 | if (handle == handle_bad_irq) { |
| 697 | if (desc->chip != &no_irq_chip) | 725 | if (desc->irq_data.chip != &no_irq_chip) |
| 698 | mask_ack_irq(desc, irq); | 726 | mask_ack_irq(desc); |
| 699 | desc->status |= IRQ_DISABLED; | 727 | desc->status |= IRQ_DISABLED; |
| 700 | desc->depth = 1; | 728 | desc->depth = 1; |
| 701 | } | 729 | } |
| @@ -706,10 +734,10 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
| 706 | desc->status &= ~IRQ_DISABLED; | 734 | desc->status &= ~IRQ_DISABLED; |
| 707 | desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; | 735 | desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; |
| 708 | desc->depth = 0; | 736 | desc->depth = 0; |
| 709 | desc->chip->startup(irq); | 737 | desc->irq_data.chip->irq_startup(&desc->irq_data); |
| 710 | } | 738 | } |
| 711 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 739 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 712 | chip_bus_sync_unlock(irq, desc); | 740 | chip_bus_sync_unlock(desc); |
| 713 | } | 741 | } |
| 714 | EXPORT_SYMBOL_GPL(__set_irq_handler); | 742 | EXPORT_SYMBOL_GPL(__set_irq_handler); |
| 715 | 743 | ||
| @@ -729,32 +757,20 @@ set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, | |||
| 729 | __set_irq_handler(irq, handle, 0, name); | 757 | __set_irq_handler(irq, handle, 0, name); |
| 730 | } | 758 | } |
| 731 | 759 | ||
| 732 | void set_irq_noprobe(unsigned int irq) | 760 | void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) |
| 733 | { | 761 | { |
| 734 | struct irq_desc *desc = irq_to_desc(irq); | 762 | struct irq_desc *desc = irq_to_desc(irq); |
| 735 | unsigned long flags; | 763 | unsigned long flags; |
| 736 | 764 | ||
| 737 | if (!desc) { | 765 | if (!desc) |
| 738 | printk(KERN_ERR "Trying to mark IRQ%d non-probeable\n", irq); | ||
| 739 | return; | 766 | return; |
| 740 | } | ||
| 741 | |||
| 742 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 743 | desc->status |= IRQ_NOPROBE; | ||
| 744 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 745 | } | ||
| 746 | |||
| 747 | void set_irq_probe(unsigned int irq) | ||
| 748 | { | ||
| 749 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 750 | unsigned long flags; | ||
| 751 | 767 | ||
| 752 | if (!desc) { | 768 | /* Sanitize flags */ |
| 753 | printk(KERN_ERR "Trying to mark IRQ%d probeable\n", irq); | 769 | set &= IRQF_MODIFY_MASK; |
| 754 | return; | 770 | clr &= IRQF_MODIFY_MASK; |
| 755 | } | ||
| 756 | 771 | ||
| 757 | raw_spin_lock_irqsave(&desc->lock, flags); | 772 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 758 | desc->status &= ~IRQ_NOPROBE; | 773 | desc->status &= ~clr; |
| 774 | desc->status |= set; | ||
| 759 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 775 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 760 | } | 776 | } |
