[ltp] Re: ACPI / dock: ThinkPad X220: \_SB_.PCI0.LPC_.EC__.BAT1: Unable to dock!

Paul Bolle linux-thinkpad@linux-thinkpad.org
Wed, 30 Jul 2014 00:02:53 +0200


Shaohua,

Could you please update your email address in MAINTAINERS?

Thanks,


Paul Bolle

On Tue, 2014-07-29 at 23:46 +0200, Paul Bolle wrote:
> 0) A ThinkPad X220 I use prints this error at the _first_ resume from
> suspend (to ram):
>     ACPI: \_SB_.PCI0.LPC_.EC__.BAT1: Unable to dock!
> 
> 1) BAT1 is apparently a "battery bay". Rubin suggested that it is a
> "slice" battery. I do not use a "slice" battery. (There are two other
> possible docks according to the ACPI printks is get. An "ata bay" and a
> "dock station". I don't use those either, but the kernel at least prints
> no errors about them.)
> 
> 2) I've peeked a bit at the DSDT of this machine. Its _WAK method
> contains this line:
>     \_SB.PCI0.LPC.EC.BATW (Arg0)
> 
> That BATW method is about 12 lines long. (Can I quote that in full?) It
> ends with this snippet:
>     If (XOr (Local0, Local1))
>     {
>         Store (Local1, [...])
>         Notify (\_SB.PCI0.LPC.EC.BAT1, 0x01) // Device Check
>     }
> 
> 3) That ACPI_NOTIFY_DEVICE_CHECK for BAT1 apparently triggers this call
> chain:
>     acpi_bus_notify()
>         acpi_hotplug_schedule()
>             acpi_hotplug_work_fn()
>                 acpi_device_hotplug()
>                     dock_notify()
> 
> 4) Perhaps Lenovo needs to update the ACPI part of this laptop's
> firmware. (I'm running the latest firmware.) Does Lenovo listen to
> suggestions to update its firmware?
> 
> 5) A workaround in the kernel _might_ be something utterly untested like
> this:
> 
> diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
> index d9339b442a4e..9e5856a6adfb 100644
> --- a/drivers/acpi/dock.c
> +++ b/drivers/acpi/dock.c
> @@ -333,7 +333,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
>   *
>   * Execute the _DCK method in response to an acpi event
>   */
> -static void handle_dock(struct dock_station *ds, int dock)
> +static acpi_status handle_dock(struct dock_station *ds, int dock)
>  {
>  	acpi_status status;
>  	struct acpi_object_list arg_list;
> @@ -351,11 +351,12 @@ static void handle_dock(struct dock_station *ds, int dock)
>  	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
>  		acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
>  				status);
> +	return status;
>  }
>  
> -static inline void dock(struct dock_station *ds)
> +static inline acpi_status dock(struct dock_station *ds)
>  {
> -	handle_dock(ds, 1);
> +	return handle_dock(ds, 1);
>  }
>  
>  static inline void undock(struct dock_station *ds)
> @@ -471,8 +472,12 @@ int dock_notify(struct acpi_device *adev, u32 event)
>  	case ACPI_NOTIFY_BUS_CHECK:
>  	case ACPI_NOTIFY_DEVICE_CHECK:
>  		if (!dock_in_progress(ds) && !acpi_device_enumerated(adev)) {
> +			acpi_status status;
> +
>  			begin_dock(ds);
> -			dock(ds);
> +			status = dock(ds);
> +			if (status == AE_NOT_FOUND)
> +				break;
>  			if (!dock_present(ds)) {
>  				acpi_handle_err(handle, "Unable to dock!\n");
>  				complete_dock(ds);
> 
> Please note that BAT1 does have a _EJ0 method but doesn't have a _DCK
> method.
> 
> 6) Any suggestions?
> 
> 
> Paul Bolle