s390/irq,idle: simplify idle check
Use the per-cpu CIF_ENABLED_WAIT flag to decide if an interrupt occurred while a cpu was idle, instead of checking two conditions within the old psw. Also move clearing of the CIF_ENABLED_WAIT bit to the early interrupt handler, which in turn makes arch_vcpu_is_preempted() also a bit more precise, since the flag is now cleared before interrupt handlers have been called. Reviewed-by: Sven Schnelle <svens@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
This commit is contained in:
parent
f96f41aae2
commit
6472a2dcc4
|
@ -23,6 +23,5 @@ extern struct device_attribute dev_attr_idle_count;
|
||||||
extern struct device_attribute dev_attr_idle_time_us;
|
extern struct device_attribute dev_attr_idle_time_us;
|
||||||
|
|
||||||
void psw_idle(struct s390_idle_data *data, unsigned long psw_mask);
|
void psw_idle(struct s390_idle_data *data, unsigned long psw_mask);
|
||||||
void psw_idle_exit(void);
|
|
||||||
|
|
||||||
#endif /* _S390_IDLE_H */
|
#endif /* _S390_IDLE_H */
|
||||||
|
|
|
@ -28,7 +28,6 @@ void account_idle_time_irq(void)
|
||||||
u64 cycles_new[8];
|
u64 cycles_new[8];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
clear_cpu_flag(CIF_ENABLED_WAIT);
|
|
||||||
if (smp_cpu_mtid) {
|
if (smp_cpu_mtid) {
|
||||||
stcctm(MT_DIAG, smp_cpu_mtid, cycles_new);
|
stcctm(MT_DIAG, smp_cpu_mtid, cycles_new);
|
||||||
for (i = 0; i < smp_cpu_mtid; i++)
|
for (i = 0; i < smp_cpu_mtid; i++)
|
||||||
|
|
|
@ -136,7 +136,7 @@ void noinstr do_io_irq(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
irqentry_state_t state = irqentry_enter(regs);
|
irqentry_state_t state = irqentry_enter(regs);
|
||||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
int from_idle;
|
bool from_idle;
|
||||||
|
|
||||||
irq_enter_rcu();
|
irq_enter_rcu();
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ void noinstr do_io_irq(struct pt_regs *regs)
|
||||||
current->thread.last_break = regs->last_break;
|
current->thread.last_break = regs->last_break;
|
||||||
}
|
}
|
||||||
|
|
||||||
from_idle = !user_mode(regs) && regs->psw.addr == (unsigned long)psw_idle_exit;
|
from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
|
||||||
if (from_idle)
|
if (from_idle)
|
||||||
account_idle_time_irq();
|
account_idle_time_irq();
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ void noinstr do_ext_irq(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
irqentry_state_t state = irqentry_enter(regs);
|
irqentry_state_t state = irqentry_enter(regs);
|
||||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
int from_idle;
|
bool from_idle;
|
||||||
|
|
||||||
irq_enter_rcu();
|
irq_enter_rcu();
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ void noinstr do_ext_irq(struct pt_regs *regs)
|
||||||
regs->int_parm = S390_lowcore.ext_params;
|
regs->int_parm = S390_lowcore.ext_params;
|
||||||
regs->int_parm_long = S390_lowcore.ext_params2;
|
regs->int_parm_long = S390_lowcore.ext_params2;
|
||||||
|
|
||||||
from_idle = !user_mode(regs) && regs->psw.addr == (unsigned long)psw_idle_exit;
|
from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
|
||||||
if (from_idle)
|
if (from_idle)
|
||||||
account_idle_time_irq();
|
account_idle_time_irq();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue