Hi, Rui

> From: Zhang, Rui
> Subject: RE: [RFC PATCH v6 1/3] ACPI / EC: Fix possible driver order issue by 
> moving EC event handling
> earlier
> 
> 
> > From: linux-acpi-ow...@vger.kernel.org [mailto:linux-acpi-
> > Subject: [RFC PATCH v6 1/3] ACPI / EC: Fix possible driver order issue by
> > moving EC event handling earlier
> >
> > This patch tries to detect EC events earlier after resume, so that if an 
> > event
> > occurred before invoking acpi_ec_unblock_transactions(), it could be
> > detected by acpi_ec_unblock_transactions() which is the earliest EC driver
> > call after resume.
> >
> > However after the noirq stage, if an event ocurred after
> > acpi_ec_unblock_transactions() and before acpi_ec_resume(), there was no
> > mean to detect and trigger it right then, but can only detect it and handle 
> > it
> > after acpi_ec_resume().
> >
> > Now the final logic is:
> > 1. If ec_freeze_events=Y, event handling is stopped in acpi_ec_suspend(),
> >    restarted in acpi_ec_resume();
> > 2. If ec_freeze_events=N, event handling is stopped in
> >    acpi_ec_block_transactions(), restarted in
> >    acpi_ec_unblock_transactions();
> > 3. In order to handling the conflict of the edge-trigger nature of EC IRQ
> >    and the Linux noirq stage, advance_transaction() is invoked where the
> >    event handling is enabled and the noirq stage is ended.
> >
> > Known issue:
> > 1. Event ocurred between acpi_ec_unblock_transactions() and
> >    acpi_ec_resume() may still lead to the order issue. This can only be
> >    fixed by adding a periodic detection mechanism during the noirq stage.
> >
> > Signed-off-by: Lv Zheng <lv.zh...@intel.com>
> > Tested-by: Tomislav Ivek <tomislav.i...@gmail.com>
> > Tested-by: Luya Tshimbalanga <l...@fedoraproject.org>
> 
> I don't know what issue this patch has been tested for. Lv, can you please 
> clarify?

The testers' names are listed here because they have tried the commit and no
regressions can be found on their test platforms.

> 
> I agree with lv that it can probably fix some issues brought by the device 
> order issue.
> And I'll be glad to push this after we have verified it is really helpful.
> Lv,
> Do you still remember the bug report for the lid issue?

Maybe you should ask Benjamin.
Let me Cc him for further investigation.

Thanks,
Lv

> 
> Thanks,
> rui
> > ---
> >  drivers/acpi/ec.c | 35 ++++++++++++++++++++++++++---------
> >  1 file changed, 26 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index df84246..f1f320b
> > 100644
> > --- a/drivers/acpi/ec.c
> > +++ b/drivers/acpi/ec.c
> > @@ -249,6 +249,11 @@ static bool acpi_ec_started(struct acpi_ec *ec)
> >            !test_bit(EC_FLAGS_STOPPED, &ec->flags);  }
> >
> > +static bool acpi_ec_no_sleep_events(void) {
> > +   return acpi_sleep_no_ec_events() && ec_freeze_events; }
> > +
> >  static bool acpi_ec_event_enabled(struct acpi_ec *ec)  {
> >     /*
> > @@ -260,14 +265,14 @@ static bool acpi_ec_event_enabled(struct acpi_ec
> > *ec)
> >             return false;
> >     /*
> >      * However, disabling the event handling is experimental for late
> > -    * stage (suspend), and is controlled by the boot parameter of
> > -    * "ec_freeze_events":
> > +    * stage (suspend), and is controlled by
> > +    * "acpi_ec_no_sleep_events()":
> >      * 1. true:  The EC event handling is disabled before entering
> >      *           the noirq stage.
> >      * 2. false: The EC event handling is automatically disabled as
> >      *           soon as the EC driver is stopped.
> >      */
> > -   if (ec_freeze_events)
> > +   if (acpi_ec_no_sleep_events())
> >             return acpi_ec_started(ec);
> >     else
> >             return test_bit(EC_FLAGS_STARTED, &ec->flags); @@ -524,8
> > +529,8 @@ static bool acpi_ec_query_flushed(struct acpi_ec *ec)  static void
> > __acpi_ec_flush_event(struct acpi_ec *ec)  {
> >     /*
> > -    * When ec_freeze_events is true, we need to flush events in
> > -    * the proper position before entering the noirq stage.
> > +    * When acpi_ec_no_sleep_events() is true, we need to flush events
> > +    * in the proper position before entering the noirq stage.
> >      */
> >     wait_event(ec->wait, acpi_ec_query_flushed(ec));
> >     if (ec_query_wq)
> > @@ -948,7 +953,8 @@ static void acpi_ec_start(struct acpi_ec *ec, bool
> > resuming)
> >             if (!resuming) {
> >                     acpi_ec_submit_request(ec);
> >                     ec_dbg_ref(ec, "Increase driver");
> > -           }
> > +           } else if (!acpi_ec_no_sleep_events())
> > +                   __acpi_ec_enable_event(ec);
> >             ec_log_drv("EC started");
> >     }
> >     spin_unlock_irqrestore(&ec->lock, flags); @@ -980,7 +986,7 @@
> > static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
> >             if (!suspending) {
> >                     acpi_ec_complete_request(ec);
> >                     ec_dbg_ref(ec, "Decrease driver");
> > -           } else if (!ec_freeze_events)
> > +           } else if (!acpi_ec_no_sleep_events())
> >                     __acpi_ec_disable_event(ec);
> >             clear_bit(EC_FLAGS_STARTED, &ec->flags);
> >             clear_bit(EC_FLAGS_STOPPED, &ec->flags); @@ -1910,7
> > +1916,7 @@ static int acpi_ec_suspend(struct device *dev)
> >     struct acpi_ec *ec =
> >             acpi_driver_data(to_acpi_device(dev));
> >
> > -   if (acpi_sleep_no_ec_events() && ec_freeze_events)
> > +   if (acpi_ec_no_sleep_events())
> >             acpi_ec_disable_event(ec);
> >     return 0;
> >  }
> > @@ -1946,7 +1952,18 @@ static int acpi_ec_resume(struct device *dev)
> >     struct acpi_ec *ec =
> >             acpi_driver_data(to_acpi_device(dev));
> >
> > -   acpi_ec_enable_event(ec);
> > +   if (acpi_ec_no_sleep_events())
> > +           acpi_ec_enable_event(ec);
> > +   else {
> > +           /*
> > +            * Though whether there is an event pending has been
> > +            * checked in acpi_ec_unblock_transactions() when
> > +            * acpi_ec_no_sleep_events() is false, check it one more
> > +            * time after noirq stage to detect events occurred after
> > +            * acpi_ec_unblock_transactions().
> > +            */
> > +           advance_transaction(ec);
> > +   }
> >     return 0;
> >  }
> >  #endif
> > --
> > 2.7.4
> >
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the
> > body of a message to majord...@vger.kernel.org More majordomo info at
> > http://vger.kernel.org/majordomo-info.html

Reply via email to