Re: [PATCH 1/2] ACPICA: Clear power button status before enabling event

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2009-06-18 at 11:38 +0800, Bjorn Helgaas wrote:
> On Wednesday 17 June 2009 8:14:26 pm yakui_zhao wrote:
> > On Thu, 2009-06-18 at 03:08 +0800, Bjorn Helgaas wrote:
> > > What's your opinion of the following patch?  This drops the clear
> > > from acpi_suspend_enter().  In the ACPI CA acpi_leave_sleep_state(),
> > > it clears first, then enables, and moves both before the _WAK
> > > execution.
> > > 
> > >   button press A causes wakeup
> > >   <possible button press (or BIOS sets event) B>
> > >   acpi_leave_sleep_state() clears all GPEs
> > >   acpi_leave_sleep_state() enables runtime GPEs
> > >   acpi_leave_sleep_state() clears power button event
> > >   <possible button press C>
> > >   acpi_leave_sleep_state() enables power button event
> > >   <possible button press D>
> > >   acpi_leave_sleep_state() runs _WAK
> > >   <possible button "press" E from _WAK>
> > >   <possible button press F>
> > >   
> > > This should work the same as the current code -- we drop event B
> > > as desired, and we handle all others.
> > > 
> > > It has the advantages that we remove a bit of code from Linux/ACPI,
> > > we only touch the power button events in one place, and we follow
> > > the same pattern (clear, then enable) as the GPEs.
> > > 
> > > I'm not sure why acpi_suspend_enter() only clears the event when
> > > the acpi_target_sleep_state == ACPI_STATE_S3.  Sec. 4.7.2.2.1.1
> > > doesn't mention that.
> > We had better not delete the code that clears the power button event in
> > course of acpi_suspend_enter. 
> > This is to avoid that the power button wake event hits the user space.
> > 
> > Maybe the BIOS will set the power button event enable/status bit. And
> > after the interrupt is enabled, the power button event will hit the
> > userland. So it is appropriate to clear the power button event as early
> > as possible.
> 
> OK, I think I see now.  I didn't think through the "should not reach
> userspace" language.  I think we just want to clear the event so we
> don't take another interrupt when we re-enable interrupts near the
> end of acpi_suspend_enter().
What you said is partially right.
   The power button wakeup event had better not hit the userland. If the
acpid receives the power button wakeup event, then the system will be
shutdown. This is not what we wanted.
   So it will be better that the power button event is cleared as early
as possible(At least it is cleared before the interrupt is re-enabled).
> 
> >     Of course it can be cleared in the function of
> > "acpi_leave_sleep_state_prep".
> 
> The interrupt path (acpi_ev_sci_xrupt_handler() ->
> acpi_ev_fixed_event_detect() -> acpi_ev_fixed_event_dispatch())
> is mostly in the ACPI CA, so I like your idea of clearing the
> power button event in acpi_leave_sleep_state_prep() because
> that's also in the CA, and it seems more robust if the CA
> clears it rather than assuming that the host OS will clear it.
> 
> I would probably suggest moving the acpi_disable_all_gpes() into
> acpi_leave_sleep_state_prep() for the same reason.
It is ok for me. 
> 
> It's still asymmetric because we disable & clear *all* GPEs,
> but only the power button fixed event.

> 
> And I still don't understand the ACPI_STATE_S3 test around the
> power button event clear.  Do you think that's necessary?
For the S3 test it is necessary to clear the power button event before
the interrupt is re-enabled.
Now the power button event is cleared at two places in course of resume.
One is  in the acpi_suspend_enter and another is in the function of
acpi_leave_sleep_state. As the acpi_leave_sleep_state is called with
interrupt enabled, it will be too late. Maybe when the interrupt is
enabled, the power button event is fired and then hit the userland.

If the power button event is cleared in the function of
acpi_leave_sleep_state_prep, it is unnecessary to clear it explicitly in
the acpi_suspend_enter.

Thanks.
> 
> Thanks for your patience in explaining all this to me.
> 
> Bjorn
> 
> > > diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
> > > index db307a3..c3252ee 100644
> > > --- a/drivers/acpi/acpica/hwsleep.c
> > > +++ b/drivers/acpi/acpica/hwsleep.c
> > > @@ -592,6 +592,18 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
> > >  		return_ACPI_STATUS(status);
> > >  	}
> > >  
> > > +	/* Enable power button */
> > > +
> > > +	(void)
> > > +	    acpi_write_bit_register(acpi_gbl_fixed_event_info
> > > +			      [ACPI_EVENT_POWER_BUTTON].
> > > +			      status_register_id, ACPI_CLEAR_STATUS);
> > > +
> > > +	(void)
> > > +	    acpi_write_bit_register(acpi_gbl_fixed_event_info
> > > +			      [ACPI_EVENT_POWER_BUTTON].
> > > +			      enable_register_id, ACPI_ENABLE_EVENT);
> > > +
> > >  	arg.integer.value = sleep_state;
> > >  	status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
> > >  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
> > > @@ -608,18 +620,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
> > >  
> > >  	acpi_gbl_system_awake_and_running = TRUE;
> > >  
> > > -	/* Enable power button */
> > > -
> > > -	(void)
> > > -	    acpi_write_bit_register(acpi_gbl_fixed_event_info
> > > -			      [ACPI_EVENT_POWER_BUTTON].
> > > -			      enable_register_id, ACPI_ENABLE_EVENT);
> > > -
> > > -	(void)
> > > -	    acpi_write_bit_register(acpi_gbl_fixed_event_info
> > > -			      [ACPI_EVENT_POWER_BUTTON].
> > > -			      status_register_id, ACPI_CLEAR_STATUS);
> > > -
> > >  	arg.integer.value = ACPI_SST_WORKING;
> > >  	status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
> > >  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
> > > diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
> > > index 01574a0..b63c525 100644
> > > --- a/drivers/acpi/sleep.c
> > > +++ b/drivers/acpi/sleep.c
> > > @@ -257,13 +257,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state)
> > >  	/* Reprogram control registers and execute _BFS */
> > >  	acpi_leave_sleep_state_prep(acpi_state);
> > >  
> > > -	/* ACPI 3.0 specs (P62) says that it's the responsibility
> > > -	 * of the OSPM to clear the status bit [ implying that the
> > > -	 * POWER_BUTTON event should not reach userspace ]
> > > -	 */
> > > -	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3))
> > > -		acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
> > > -
> > >  	/*
> > >  	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
> > >  	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> > > the body of a message to majordomo@xxxxxxxxxxxxxxx
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > 
> > 
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux