diff options
author | Jeffy Chen <jeffy.chen@rock-chips.com> | 2017-06-26 07:33:34 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-06-26 09:47:00 -0400 |
commit | bf22ff45bed664aefb5c4e43029057a199b7070c (patch) | |
tree | 2cb9598c3f09a473df3b4bfc6290e4575b4fcdab | |
parent | d829b8fb2431595422289cfc210f0a955a8bec74 (diff) |
genirq: Avoid unnecessary low level irq function calls
Check irq state in enable/disable/unmask/mask_irq to avoid unnecessary
low level irq function calls.
This has two advantages:
- Conditionals are faster than hardware access
- Solves issues with the underlying refcounting of the pinctrl
infrastructure
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: tfiga@chromium.org
Cc: briannorris@chromium.org
Cc: dianders@chromium.org
Link: http://lkml.kernel.org/r/1498476814-12563-2-git-send-email-jeffy.chen@rock-chips.com
-rw-r--r-- | kernel/irq/chip.c | 53 |
1 files changed, 33 insertions, 20 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index fc89eeb8a6b4..2e30d925a40d 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
@@ -314,22 +314,32 @@ void irq_shutdown(struct irq_desc *desc) | |||
314 | 314 | ||
315 | void irq_enable(struct irq_desc *desc) | 315 | void irq_enable(struct irq_desc *desc) |
316 | { | 316 | { |
317 | irq_state_clr_disabled(desc); | 317 | if (!irqd_irq_disabled(&desc->irq_data)) { |
318 | if (desc->irq_data.chip->irq_enable) | 318 | unmask_irq(desc); |
319 | desc->irq_data.chip->irq_enable(&desc->irq_data); | 319 | } else { |
320 | else | 320 | irq_state_clr_disabled(desc); |
321 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | 321 | if (desc->irq_data.chip->irq_enable) { |
322 | irq_state_clr_masked(desc); | 322 | desc->irq_data.chip->irq_enable(&desc->irq_data); |
323 | irq_state_clr_masked(desc); | ||
324 | } else { | ||
325 | unmask_irq(desc); | ||
326 | } | ||
327 | } | ||
323 | } | 328 | } |
324 | 329 | ||
325 | static void __irq_disable(struct irq_desc *desc, bool mask) | 330 | static void __irq_disable(struct irq_desc *desc, bool mask) |
326 | { | 331 | { |
327 | irq_state_set_disabled(desc); | 332 | if (irqd_irq_disabled(&desc->irq_data)) { |
328 | if (desc->irq_data.chip->irq_disable) { | 333 | if (mask) |
329 | desc->irq_data.chip->irq_disable(&desc->irq_data); | 334 | mask_irq(desc); |
330 | irq_state_set_masked(desc); | 335 | } else { |
331 | } else if (mask) { | 336 | irq_state_set_disabled(desc); |
332 | mask_irq(desc); | 337 | if (desc->irq_data.chip->irq_disable) { |
338 | desc->irq_data.chip->irq_disable(&desc->irq_data); | ||
339 | irq_state_set_masked(desc); | ||
340 | } else if (mask) { | ||
341 | mask_irq(desc); | ||
342 | } | ||
333 | } | 343 | } |
334 | } | 344 | } |
335 | 345 | ||
@@ -378,18 +388,21 @@ void irq_percpu_disable(struct irq_desc *desc, unsigned int cpu) | |||
378 | 388 | ||
379 | static inline void mask_ack_irq(struct irq_desc *desc) | 389 | static inline void mask_ack_irq(struct irq_desc *desc) |
380 | { | 390 | { |
381 | if (desc->irq_data.chip->irq_mask_ack) | 391 | if (desc->irq_data.chip->irq_mask_ack) { |
382 | desc->irq_data.chip->irq_mask_ack(&desc->irq_data); | 392 | desc->irq_data.chip->irq_mask_ack(&desc->irq_data); |
383 | else { | 393 | irq_state_set_masked(desc); |
384 | desc->irq_data.chip->irq_mask(&desc->irq_data); | 394 | } else { |
395 | mask_irq(desc); | ||
385 | if (desc->irq_data.chip->irq_ack) | 396 | if (desc->irq_data.chip->irq_ack) |
386 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 397 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
387 | } | 398 | } |
388 | irq_state_set_masked(desc); | ||
389 | } | 399 | } |
390 | 400 | ||
391 | void mask_irq(struct irq_desc *desc) | 401 | void mask_irq(struct irq_desc *desc) |
392 | { | 402 | { |
403 | if (irqd_irq_masked(&desc->irq_data)) | ||
404 | return; | ||
405 | |||
393 | if (desc->irq_data.chip->irq_mask) { | 406 | if (desc->irq_data.chip->irq_mask) { |
394 | desc->irq_data.chip->irq_mask(&desc->irq_data); | 407 | desc->irq_data.chip->irq_mask(&desc->irq_data); |
395 | irq_state_set_masked(desc); | 408 | irq_state_set_masked(desc); |
@@ -398,6 +411,9 @@ void mask_irq(struct irq_desc *desc) | |||
398 | 411 | ||
399 | void unmask_irq(struct irq_desc *desc) | 412 | void unmask_irq(struct irq_desc *desc) |
400 | { | 413 | { |
414 | if (!irqd_irq_masked(&desc->irq_data)) | ||
415 | return; | ||
416 | |||
401 | if (desc->irq_data.chip->irq_unmask) { | 417 | if (desc->irq_data.chip->irq_unmask) { |
402 | desc->irq_data.chip->irq_unmask(&desc->irq_data); | 418 | desc->irq_data.chip->irq_unmask(&desc->irq_data); |
403 | irq_state_clr_masked(desc); | 419 | irq_state_clr_masked(desc); |
@@ -411,10 +427,7 @@ void unmask_threaded_irq(struct irq_desc *desc) | |||
411 | if (chip->flags & IRQCHIP_EOI_THREADED) | 427 | if (chip->flags & IRQCHIP_EOI_THREADED) |
412 | chip->irq_eoi(&desc->irq_data); | 428 | chip->irq_eoi(&desc->irq_data); |
413 | 429 | ||
414 | if (chip->irq_unmask) { | 430 | unmask_irq(desc); |
415 | chip->irq_unmask(&desc->irq_data); | ||
416 | irq_state_clr_masked(desc); | ||
417 | } | ||
418 | } | 431 | } |
419 | 432 | ||
420 | /* | 433 | /* |