diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/irq/autoprobe.c | 4 | ||||
| -rw-r--r-- | kernel/irq/chip.c | 42 | ||||
| -rw-r--r-- | kernel/irq/internals.h | 2 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 2 | ||||
| -rw-r--r-- | kernel/sched/core.c | 1 | ||||
| -rw-r--r-- | kernel/sched/fair.c | 2 |
6 files changed, 39 insertions, 14 deletions
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c index 342d8f44e401..0119b9d467ae 100644 --- a/kernel/irq/autoprobe.c +++ b/kernel/irq/autoprobe.c | |||
| @@ -53,7 +53,7 @@ unsigned long probe_irq_on(void) | |||
| 53 | if (desc->irq_data.chip->irq_set_type) | 53 | if (desc->irq_data.chip->irq_set_type) |
| 54 | desc->irq_data.chip->irq_set_type(&desc->irq_data, | 54 | desc->irq_data.chip->irq_set_type(&desc->irq_data, |
| 55 | IRQ_TYPE_PROBE); | 55 | IRQ_TYPE_PROBE); |
| 56 | irq_startup(desc); | 56 | irq_startup(desc, false); |
| 57 | } | 57 | } |
| 58 | raw_spin_unlock_irq(&desc->lock); | 58 | raw_spin_unlock_irq(&desc->lock); |
| 59 | } | 59 | } |
| @@ -70,7 +70,7 @@ unsigned long probe_irq_on(void) | |||
| 70 | raw_spin_lock_irq(&desc->lock); | 70 | raw_spin_lock_irq(&desc->lock); |
| 71 | if (!desc->action && irq_settings_can_probe(desc)) { | 71 | if (!desc->action && irq_settings_can_probe(desc)) { |
| 72 | desc->istate |= IRQS_AUTODETECT | IRQS_WAITING; | 72 | desc->istate |= IRQS_AUTODETECT | IRQS_WAITING; |
| 73 | if (irq_startup(desc)) | 73 | if (irq_startup(desc, false)) |
| 74 | desc->istate |= IRQS_PENDING; | 74 | desc->istate |= IRQS_PENDING; |
| 75 | } | 75 | } |
| 76 | raw_spin_unlock_irq(&desc->lock); | 76 | raw_spin_unlock_irq(&desc->lock); |
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index f7c543a801d9..fb7db75ee0c8 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c | |||
| @@ -157,19 +157,22 @@ static void irq_state_set_masked(struct irq_desc *desc) | |||
| 157 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); | 157 | irqd_set(&desc->irq_data, IRQD_IRQ_MASKED); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | int irq_startup(struct irq_desc *desc) | 160 | int irq_startup(struct irq_desc *desc, bool resend) |
| 161 | { | 161 | { |
| 162 | int ret = 0; | ||
| 163 | |||
| 162 | irq_state_clr_disabled(desc); | 164 | irq_state_clr_disabled(desc); |
| 163 | desc->depth = 0; | 165 | desc->depth = 0; |
| 164 | 166 | ||
| 165 | if (desc->irq_data.chip->irq_startup) { | 167 | if (desc->irq_data.chip->irq_startup) { |
| 166 | int ret = desc->irq_data.chip->irq_startup(&desc->irq_data); | 168 | ret = desc->irq_data.chip->irq_startup(&desc->irq_data); |
| 167 | irq_state_clr_masked(desc); | 169 | irq_state_clr_masked(desc); |
| 168 | return ret; | 170 | } else { |
| 171 | irq_enable(desc); | ||
| 169 | } | 172 | } |
| 170 | 173 | if (resend) | |
| 171 | irq_enable(desc); | 174 | check_irq_resend(desc, desc->irq_data.irq); |
| 172 | return 0; | 175 | return ret; |
| 173 | } | 176 | } |
| 174 | 177 | ||
| 175 | void irq_shutdown(struct irq_desc *desc) | 178 | void irq_shutdown(struct irq_desc *desc) |
| @@ -330,6 +333,24 @@ out_unlock: | |||
| 330 | } | 333 | } |
| 331 | EXPORT_SYMBOL_GPL(handle_simple_irq); | 334 | EXPORT_SYMBOL_GPL(handle_simple_irq); |
| 332 | 335 | ||
| 336 | /* | ||
| 337 | * Called unconditionally from handle_level_irq() and only for oneshot | ||
| 338 | * interrupts from handle_fasteoi_irq() | ||
| 339 | */ | ||
| 340 | static void cond_unmask_irq(struct irq_desc *desc) | ||
| 341 | { | ||
| 342 | /* | ||
| 343 | * We need to unmask in the following cases: | ||
| 344 | * - Standard level irq (IRQF_ONESHOT is not set) | ||
| 345 | * - Oneshot irq which did not wake the thread (caused by a | ||
| 346 | * spurious interrupt or a primary handler handling it | ||
| 347 | * completely). | ||
| 348 | */ | ||
| 349 | if (!irqd_irq_disabled(&desc->irq_data) && | ||
| 350 | irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot) | ||
| 351 | unmask_irq(desc); | ||
| 352 | } | ||
| 353 | |||
| 333 | /** | 354 | /** |
| 334 | * handle_level_irq - Level type irq handler | 355 | * handle_level_irq - Level type irq handler |
| 335 | * @irq: the interrupt number | 356 | * @irq: the interrupt number |
| @@ -362,8 +383,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc) | |||
| 362 | 383 | ||
| 363 | handle_irq_event(desc); | 384 | handle_irq_event(desc); |
| 364 | 385 | ||
| 365 | if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT)) | 386 | cond_unmask_irq(desc); |
| 366 | unmask_irq(desc); | 387 | |
| 367 | out_unlock: | 388 | out_unlock: |
| 368 | raw_spin_unlock(&desc->lock); | 389 | raw_spin_unlock(&desc->lock); |
| 369 | } | 390 | } |
| @@ -417,6 +438,9 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc) | |||
| 417 | preflow_handler(desc); | 438 | preflow_handler(desc); |
| 418 | handle_irq_event(desc); | 439 | handle_irq_event(desc); |
| 419 | 440 | ||
| 441 | if (desc->istate & IRQS_ONESHOT) | ||
| 442 | cond_unmask_irq(desc); | ||
| 443 | |||
| 420 | out_eoi: | 444 | out_eoi: |
| 421 | desc->irq_data.chip->irq_eoi(&desc->irq_data); | 445 | desc->irq_data.chip->irq_eoi(&desc->irq_data); |
| 422 | out_unlock: | 446 | out_unlock: |
| @@ -625,7 +649,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, | |||
| 625 | irq_settings_set_noprobe(desc); | 649 | irq_settings_set_noprobe(desc); |
| 626 | irq_settings_set_norequest(desc); | 650 | irq_settings_set_norequest(desc); |
| 627 | irq_settings_set_nothread(desc); | 651 | irq_settings_set_nothread(desc); |
| 628 | irq_startup(desc); | 652 | irq_startup(desc, true); |
| 629 | } | 653 | } |
| 630 | out: | 654 | out: |
| 631 | irq_put_desc_busunlock(desc, flags); | 655 | irq_put_desc_busunlock(desc, flags); |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index b7952316016a..40378ff877e7 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
| @@ -67,7 +67,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
| 67 | extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); | 67 | extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp); |
| 68 | extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); | 68 | extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume); |
| 69 | 69 | ||
| 70 | extern int irq_startup(struct irq_desc *desc); | 70 | extern int irq_startup(struct irq_desc *desc, bool resend); |
| 71 | extern void irq_shutdown(struct irq_desc *desc); | 71 | extern void irq_shutdown(struct irq_desc *desc); |
| 72 | extern void irq_enable(struct irq_desc *desc); | 72 | extern void irq_enable(struct irq_desc *desc); |
| 73 | extern void irq_disable(struct irq_desc *desc); | 73 | extern void irq_disable(struct irq_desc *desc); |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index a9a9dbe49fea..32313c084442 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -1027,7 +1027,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 1027 | desc->istate |= IRQS_ONESHOT; | 1027 | desc->istate |= IRQS_ONESHOT; |
| 1028 | 1028 | ||
| 1029 | if (irq_settings_can_autoenable(desc)) | 1029 | if (irq_settings_can_autoenable(desc)) |
| 1030 | irq_startup(desc); | 1030 | irq_startup(desc, true); |
| 1031 | else | 1031 | else |
| 1032 | /* Undo nested disables: */ | 1032 | /* Undo nested disables: */ |
| 1033 | desc->depth = 1; | 1033 | desc->depth = 1; |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 5255c9d2e053..b342f57879e6 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
| @@ -1932,7 +1932,6 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) | |||
| 1932 | local_irq_enable(); | 1932 | local_irq_enable(); |
| 1933 | #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ | 1933 | #endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */ |
| 1934 | finish_lock_switch(rq, prev); | 1934 | finish_lock_switch(rq, prev); |
| 1935 | trace_sched_stat_sleeptime(current, rq->clock); | ||
| 1936 | 1935 | ||
| 1937 | fire_sched_in_preempt_notifiers(current); | 1936 | fire_sched_in_preempt_notifiers(current); |
| 1938 | if (mm) | 1937 | if (mm) |
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7c6414fc669d..aca16b843b7e 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c | |||
| @@ -1003,6 +1003,7 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
| 1003 | if (unlikely(delta > se->statistics.sleep_max)) | 1003 | if (unlikely(delta > se->statistics.sleep_max)) |
| 1004 | se->statistics.sleep_max = delta; | 1004 | se->statistics.sleep_max = delta; |
| 1005 | 1005 | ||
| 1006 | se->statistics.sleep_start = 0; | ||
| 1006 | se->statistics.sum_sleep_runtime += delta; | 1007 | se->statistics.sum_sleep_runtime += delta; |
| 1007 | 1008 | ||
| 1008 | if (tsk) { | 1009 | if (tsk) { |
| @@ -1019,6 +1020,7 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
| 1019 | if (unlikely(delta > se->statistics.block_max)) | 1020 | if (unlikely(delta > se->statistics.block_max)) |
| 1020 | se->statistics.block_max = delta; | 1021 | se->statistics.block_max = delta; |
| 1021 | 1022 | ||
| 1023 | se->statistics.block_start = 0; | ||
| 1022 | se->statistics.sum_sleep_runtime += delta; | 1024 | se->statistics.sum_sleep_runtime += delta; |
| 1023 | 1025 | ||
| 1024 | if (tsk) { | 1026 | if (tsk) { |
