* [PATCH] Avoid _BIX ACPI method on Lenovo Yoga 300.
@ 2016-09-14 8:40 Dave Lambley
2016-09-14 10:34 ` Zheng, Lv
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-09-14 8:40 UTC (permalink / raw)
To: linux-acpi; +Cc: Dave Lambley, Rafael J. Wysocki, Len Brown
On the (current?) Yoga 300 firmware, the _BIX method fails with an error.
This prevents the kernel from correctly detecting the presence of a
battery.
[ 28.641906] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160422/exoparg2-427)
[ 28.641924] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff9145fb0b2230), AE_AML_PACKAGE_LIMIT (20160422/psparse-542)
Fortunately, the _BIF method can be used to get battery information. This
change causes the kernel to use the _BIF method to preference on the
Yogo 300, allowing the battery to be detected correctly.
Signed-off-by: Dave Lambley <linux@davel.me.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
CC: Len Brown <lenb@kernel.org>
---
drivers/acpi/battery.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index ab23479..2b165a8 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -69,6 +69,7 @@ MODULE_LICENSE("GPL");
static async_cookie_t async_cookie;
static int battery_bix_broken_package;
static int battery_notification_delay_ms;
+static int battery_avoid_bix;
static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -434,11 +435,16 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
{
int result = -EFAULT;
acpi_status status = 0;
- char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
- "_BIX" : "_BIF";
+ bool use_bix = !battery_avoid_bix &&
+ test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
+
+ char *name = use_bix ? "_BIX" : "_BIF";
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ if (battery_avoid_bix)
+ dev_dbg(&battery->device->dev, "ACPI _BIX method blacklisted on this hardware, avoiding.");
+
if (!acpi_battery_present(battery))
return 0;
mutex_lock(&battery->lock);
@@ -451,11 +457,11 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
return -ENODEV;
}
- if (battery_bix_broken_package)
+ if (use_bix && battery_bix_broken_package)
result = extract_package(battery, buffer.pointer,
extended_info_offsets + 1,
ARRAY_SIZE(extended_info_offsets) - 1);
- else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
+ else if (use_bix)
result = extract_package(battery, buffer.pointer,
extended_info_offsets,
ARRAY_SIZE(extended_info_offsets));
@@ -1134,6 +1140,12 @@ battery_notification_delay_quirk(const struct dmi_system_id *d)
return 0;
}
+static int __init
+battery_avoid_bix_quirk(const struct dmi_system_id *d)
+{
+ battery_avoid_bix = 1;
+ return 0;
+}
static const struct dmi_system_id bat_dmi_table[] __initconst = {
{
.callback = battery_bix_broken_package_quirk,
@@ -1151,6 +1163,15 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
},
},
+ {
+ .callback = battery_avoid_bix_quirk,
+ .ident = "Lenovo Yogo 3000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "80M1"),
+ },
+ },
+
{},
};
--
2.7.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* RE: [PATCH] Avoid _BIX ACPI method on Lenovo Yoga 300.
2016-09-14 8:40 [PATCH] Avoid _BIX ACPI method on Lenovo Yoga 300 Dave Lambley
@ 2016-09-14 10:34 ` Zheng, Lv
2016-09-17 22:56 ` [PATCH] If _BIX fails, retry with _BIF Dave Lambley
0 siblings, 1 reply; 11+ messages in thread
From: Zheng, Lv @ 2016-09-14 10:34 UTC (permalink / raw)
To: Dave Lambley, linux-acpi; +Cc: Rafael J. Wysocki, Len Brown
Hi,
> From: linux-acpi-owner@vger.kernel.org [mailto:linux-acpi-owner@vger.kernel.org] On Behalf Of Dave
> Lambley
> Subject: [PATCH] Avoid _BIX ACPI method on Lenovo Yoga 300.
>
> On the (current?) Yoga 300 firmware, the _BIX method fails with an error.
> This prevents the kernel from correctly detecting the presence of a
> battery.
>
> [ 28.641906] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object
> (length 0xD) (20160422/exoparg2-427)
> [ 28.641924] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node
> ffff9145fb0b2230), AE_AML_PACKAGE_LIMIT (20160422/psparse-542)
>
> Fortunately, the _BIF method can be used to get battery information. This
> change causes the kernel to use the _BIF method to preference on the
> Yogo 300, allowing the battery to be detected correctly.
Wasn't it better to try _BIX first, and then _BIF next when _BIX failed.
What's the merit of increasing the number of the platform quirks?
Thanks
Lv
>
> Signed-off-by: Dave Lambley <linux@davel.me.uk>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> CC: Len Brown <lenb@kernel.org>
> ---
> drivers/acpi/battery.c | 29 +++++++++++++++++++++++++----
> 1 file changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
> index ab23479..2b165a8 100644
> --- a/drivers/acpi/battery.c
> +++ b/drivers/acpi/battery.c
> @@ -69,6 +69,7 @@ MODULE_LICENSE("GPL");
> static async_cookie_t async_cookie;
> static int battery_bix_broken_package;
> static int battery_notification_delay_ms;
> +static int battery_avoid_bix;
> static unsigned int cache_time = 1000;
> module_param(cache_time, uint, 0644);
> MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
> @@ -434,11 +435,16 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
> {
> int result = -EFAULT;
> acpi_status status = 0;
> - char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
> - "_BIX" : "_BIF";
> + bool use_bix = !battery_avoid_bix &&
> + test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
> +
> + char *name = use_bix ? "_BIX" : "_BIF";
>
> struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>
> + if (battery_avoid_bix)
> + dev_dbg(&battery->device->dev, "ACPI _BIX method blacklisted on this hardware, avoiding.");
> +
> if (!acpi_battery_present(battery))
> return 0;
> mutex_lock(&battery->lock);
> @@ -451,11 +457,11 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
> return -ENODEV;
> }
>
> - if (battery_bix_broken_package)
> + if (use_bix && battery_bix_broken_package)
> result = extract_package(battery, buffer.pointer,
> extended_info_offsets + 1,
> ARRAY_SIZE(extended_info_offsets) - 1);
> - else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
> + else if (use_bix)
> result = extract_package(battery, buffer.pointer,
> extended_info_offsets,
> ARRAY_SIZE(extended_info_offsets));
> @@ -1134,6 +1140,12 @@ battery_notification_delay_quirk(const struct dmi_system_id *d)
> return 0;
> }
>
> +static int __init
> +battery_avoid_bix_quirk(const struct dmi_system_id *d)
> +{
> + battery_avoid_bix = 1;
> + return 0;
> +}
> static const struct dmi_system_id bat_dmi_table[] __initconst = {
> {
> .callback = battery_bix_broken_package_quirk,
> @@ -1151,6 +1163,15 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
> DMI_MATCH(DMI_PRODUCT_NAME, "Aspire V5-573G"),
> },
> },
> + {
> + .callback = battery_avoid_bix_quirk,
> + .ident = "Lenovo Yogo 3000",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "80M1"),
> + },
> + },
> +
> {},
> };
>
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] If _BIX fails, retry with _BIF.
2016-09-14 10:34 ` Zheng, Lv
@ 2016-09-17 22:56 ` Dave Lambley
2016-11-02 18:37 ` [PATCH v2] Lenovo Yoga 300 battery support Dave Lambley
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-09-17 22:56 UTC (permalink / raw)
To: linux-acpi; +Cc: Dave Lambley, Rafael J. Wysocki, Len Brown
The Lenovo Yoga 300 laptop's firmware advertises that it provides the _BIX
method. Unfortunately (some versions of?) the implementation return
badly-formed data.
[ 21.712228] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160422/exoparg2-427)
[ 21.712244] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff95f8ff0b20f0), AE_AML_PACKAGE_LIMIT (2016042
2/psparse-542)
The _BIF method does succeed.
Signed-off-by: Dave Lambley <linux@davel.me.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
CC: Len Brown <lenb@kernel.org>
---
drivers/acpi/battery.c | 68 ++++++++++++++++++++++++++++++++------------------
1 file changed, 44 insertions(+), 24 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index ab23479..71ae7e7 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -430,39 +430,24 @@ static int acpi_battery_get_status(struct acpi_battery *battery)
return 0;
}
-static int acpi_battery_get_info(struct acpi_battery *battery)
+
+int extract_battery_info(const int use_bix,
+ struct acpi_battery *battery,
+ const struct acpi_buffer *buffer)
{
int result = -EFAULT;
- acpi_status status = 0;
- char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
- "_BIX" : "_BIF";
-
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- if (!acpi_battery_present(battery))
- return 0;
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(battery->device->handle, name,
- NULL, &buffer);
- mutex_unlock(&battery->lock);
-
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
- return -ENODEV;
- }
-
- if (battery_bix_broken_package)
- result = extract_package(battery, buffer.pointer,
+ if (use_bix && battery_bix_broken_package)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets + 1,
ARRAY_SIZE(extended_info_offsets) - 1);
- else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
- result = extract_package(battery, buffer.pointer,
+ else if (use_bix)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets,
ARRAY_SIZE(extended_info_offsets));
else
- result = extract_package(battery, buffer.pointer,
+ result = extract_package(battery, buffer->pointer,
info_offsets, ARRAY_SIZE(info_offsets));
- kfree(buffer.pointer);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
battery->full_charge_capacity = battery->design_capacity;
if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
@@ -483,6 +468,41 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
return result;
}
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+ acpi_status status = 0;
+ const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
+ int use_bix;
+
+ if (!acpi_battery_present(battery))
+ return 0;
+
+
+ for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle,
+ use_bix ? "_BIX":"_BIF",
+ NULL, &buffer);
+ mutex_unlock(&battery->lock);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
+ use_bix ? "_BIX":"_BIF"));
+ } else {
+ const int result = extract_battery_info(use_bix,
+ battery,
+ &buffer);
+
+ kfree(buffer.pointer);
+ return result;
+ }
+ }
+
+ return -ENODEV;
+}
+
static int acpi_battery_get_state(struct acpi_battery *battery)
{
int result = 0;
--
2.7.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2] Lenovo Yoga 300 battery support
2016-09-17 22:56 ` [PATCH] If _BIX fails, retry with _BIF Dave Lambley
@ 2016-11-02 18:37 ` Dave Lambley
2016-11-02 18:37 ` [PATCH v2] If _BIX fails, retry with _BIF Dave Lambley
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-11-02 18:37 UTC (permalink / raw)
To: linux-acpi; +Cc: Dave Lambley, Rafael J. Wysocki, Len Brown
This patch allows Linux to detect the battery in the Lenovo Yoga 300
laptop. It does this by tolerating a bug in the firmware which breaks the
_BIX method but not _BIF. Without this patch, the battery is not presented
to userland.
On a system with non-buggy firmware, the behaviour should be unchanged.
With the patch, something like this gets logged,
[ 3004.858993] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160831/exoparg2-427)
[ 3004.859015] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff955bbb0b32d0), AE_AML_PACKAGE_LIMIT (20160831/psparse-543)
[ 3004.859038] ACPI Exception: AE_AML_PACKAGE_LIMIT, Evaluating _BIX (20160831/battery-493)
[ 3004.873413] [Firmware Bug]: The _BIX method is broken, using _BIF.
v1 -> v2
- Log when falling back to _BIF method.
- Rebased against v4.9-rc2.
Signed-off-by: Dave Lambley <linux@davel.me.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
Dave Lambley (1):
If _BIX fails, retry with _BIF.
drivers/acpi/battery.c | 72 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 48 insertions(+), 24 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2] If _BIX fails, retry with _BIF.
2016-11-02 18:37 ` [PATCH v2] Lenovo Yoga 300 battery support Dave Lambley
@ 2016-11-02 18:37 ` Dave Lambley
2016-11-02 23:26 ` Henrique de Moraes Holschuh
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-11-02 18:37 UTC (permalink / raw)
To: linux-acpi; +Cc: Dave Lambley, Rafael J. Wysocki, Len Brown
The Lenovo Yoga 300 laptop's firmware advertises that it provides the _BIX
the method to retrieve battery information. Unfortunately (some versions
of?) the implementation return with an error.
[ 21.712228] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160422/exoparg2-427)
[ 21.712244] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff95f8ff0b20f0), AE_AML_PACKAGE_LIMIT (2016042
2/psparse-542)
The _BIF method does succeed and returns convincing data. We detect _BIX
failing and automatically retry with _BIF.
Signed-off-by: Dave Lambley <linux@davel.me.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
drivers/acpi/battery.c | 72 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 48 insertions(+), 24 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 93ecae5..ad5a62c 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -430,39 +430,24 @@ static int acpi_battery_get_status(struct acpi_battery *battery)
return 0;
}
-static int acpi_battery_get_info(struct acpi_battery *battery)
+
+int extract_battery_info(const int use_bix,
+ struct acpi_battery *battery,
+ const struct acpi_buffer *buffer)
{
int result = -EFAULT;
- acpi_status status = 0;
- char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
- "_BIX" : "_BIF";
-
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- if (!acpi_battery_present(battery))
- return 0;
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(battery->device->handle, name,
- NULL, &buffer);
- mutex_unlock(&battery->lock);
-
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
- return -ENODEV;
- }
-
- if (battery_bix_broken_package)
- result = extract_package(battery, buffer.pointer,
+ if (use_bix && battery_bix_broken_package)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets + 1,
ARRAY_SIZE(extended_info_offsets) - 1);
- else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
- result = extract_package(battery, buffer.pointer,
+ else if (use_bix)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets,
ARRAY_SIZE(extended_info_offsets));
else
- result = extract_package(battery, buffer.pointer,
+ result = extract_package(battery, buffer->pointer,
info_offsets, ARRAY_SIZE(info_offsets));
- kfree(buffer.pointer);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
battery->full_charge_capacity = battery->design_capacity;
if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
@@ -483,6 +468,45 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
return result;
}
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+ const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
+ int use_bix;
+ int result = -ENODEV;
+
+ if (!acpi_battery_present(battery))
+ return 0;
+
+
+ for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_status status = AE_ERROR;
+
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle,
+ use_bix ? "_BIX":"_BIF",
+ NULL, &buffer);
+ mutex_unlock(&battery->lock);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
+ use_bix ? "_BIX":"_BIF"));
+ } else {
+ result = extract_battery_info(use_bix,
+ battery,
+ &buffer);
+
+ kfree(buffer.pointer);
+ break;
+ }
+ }
+
+ if (!result && !use_bix && xinfo)
+ pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
+
+ return result;
+}
+
static int acpi_battery_get_state(struct acpi_battery *battery)
{
int result = 0;
--
2.7.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v2] If _BIX fails, retry with _BIF.
2016-11-02 18:37 ` [PATCH v2] If _BIX fails, retry with _BIF Dave Lambley
@ 2016-11-02 23:26 ` Henrique de Moraes Holschuh
2016-11-03 8:33 ` Dave Lambley
0 siblings, 1 reply; 11+ messages in thread
From: Henrique de Moraes Holschuh @ 2016-11-02 23:26 UTC (permalink / raw)
To: Dave Lambley; +Cc: linux-acpi, Rafael J. Wysocki, Len Brown
On Wed, 02 Nov 2016, Dave Lambley wrote:
> -static int acpi_battery_get_info(struct acpi_battery *battery)
> +
> +int extract_battery_info(const int use_bix,
> + struct acpi_battery *battery,
> + const struct acpi_buffer *buffer)
Shouldn't extract_battery_info() be static as well?
--
Henrique Holschuh
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] If _BIX fails, retry with _BIF.
2016-11-02 23:26 ` Henrique de Moraes Holschuh
@ 2016-11-03 8:33 ` Dave Lambley
2016-11-03 22:38 ` Henrique de Moraes Holschuh
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-11-03 8:33 UTC (permalink / raw)
To: Henrique de Moraes Holschuh; +Cc: linux-acpi, Rafael J. Wysocki, Len Brown
On 2 November 2016 at 23:26, Henrique de Moraes Holschuh <hmh@hmh.eng.br> wrote:
>
> On Wed, 02 Nov 2016, Dave Lambley wrote:
> > -static int acpi_battery_get_info(struct acpi_battery *battery)
> > +
> > +int extract_battery_info(const int use_bix,
> > + struct acpi_battery *battery,
> > + const struct acpi_buffer *buffer)
>
> Shouldn't extract_battery_info() be static as well?
I do not believe it needs to be exported. It is a new function only
used inside battery.c.
Best regards,
Dave
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v2] If _BIX fails, retry with _BIF.
2016-11-03 8:33 ` Dave Lambley
@ 2016-11-03 22:38 ` Henrique de Moraes Holschuh
2016-11-04 1:05 ` [PATCH v3 0/1] Lenovo Yoga 300 battery support Dave Lambley
0 siblings, 1 reply; 11+ messages in thread
From: Henrique de Moraes Holschuh @ 2016-11-03 22:38 UTC (permalink / raw)
To: Dave Lambley; +Cc: linux-acpi, Rafael J. Wysocki, Len Brown
On Thu, 03 Nov 2016, Dave Lambley wrote:
> On 2 November 2016 at 23:26, Henrique de Moraes Holschuh <hmh@hmh.eng.br> wrote:
> >
> > On Wed, 02 Nov 2016, Dave Lambley wrote:
> > > -static int acpi_battery_get_info(struct acpi_battery *battery)
> > > +
> > > +int extract_battery_info(const int use_bix,
> > > + struct acpi_battery *battery,
> > > + const struct acpi_buffer *buffer)
> >
> > Shouldn't extract_battery_info() be static as well?
>
> I do not believe it needs to be exported. It is a new function only
> used inside battery.c.
Indeed. Therefore, it really should be made static.
Please fix that on the next version of your patch...
--
Henrique Holschuh
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 0/1] Lenovo Yoga 300 battery support
2016-11-03 22:38 ` Henrique de Moraes Holschuh
@ 2016-11-04 1:05 ` Dave Lambley
2016-11-04 1:05 ` [PATCH v3 1/1] If _BIX fails, retry with _BIF Dave Lambley
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-11-04 1:05 UTC (permalink / raw)
To: linux-acpi
Cc: Henrique de Moraes Holschuh, Dave Lambley, Rafael J. Wysocki, Len Brown
This patch allows Linux to detect the battery in the Lenovo Yoga 300
laptop. It does this by tolerating a bug in the firmware which breaks the
_BIX method but not _BIF. Without this patch, the battery is not presented
to userland.
On a system with non-buggy firmware, the behaviour should be unchanged.
With the patch, on affected systems something like this gets logged,
[ 3004.858993] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160831/exoparg2-427)
[ 3004.859015] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff955bbb0b32d0), AE_AML_PACKAGE_LIMIT (20160831/psparse-543)
[ 3004.859038] ACPI Exception: AE_AML_PACKAGE_LIMIT, Evaluating _BIX (20160831/battery-493)
[ 3004.873413] [Firmware Bug]: The _BIX method is broken, using _BIF.
v2 -> v3
- No longer unnecessarily exports extract_battery_info().
v1 -> v2
- Log when falling back to _BIF method.
- Rebased against v4.9-rc2.
Signed-off-by: Dave Lambley <linux@davel.me.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
Dave Lambley (1):
If _BIX fails, retry with _BIF.
drivers/acpi/battery.c | 72 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 48 insertions(+), 24 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v3 1/1] If _BIX fails, retry with _BIF.
2016-11-04 1:05 ` [PATCH v3 0/1] Lenovo Yoga 300 battery support Dave Lambley
@ 2016-11-04 1:05 ` Dave Lambley
2016-11-24 1:25 ` Rafael J. Wysocki
0 siblings, 1 reply; 11+ messages in thread
From: Dave Lambley @ 2016-11-04 1:05 UTC (permalink / raw)
To: linux-acpi
Cc: Henrique de Moraes Holschuh, Dave Lambley, Rafael J. Wysocki, Len Brown
The Lenovo Yoga 300 laptop's firmware advertises that it provides the _BIX
the method to retrieve battery information. Unfortunately (some versions
of?) the implementation return with an error.
[ 21.712228] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160422/exoparg2-427)
[ 21.712244] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff95f8ff0b20f0), AE_AML_PACKAGE_LIMIT (20160422/psparse-542)
The _BIF method does succeed and returns convincing data. We detect _BIX
failing and automatically retry with _BIF.
Signed-off-by: Dave Lambley <linux@davel.me.uk>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Cc: Len Brown <lenb@kernel.org>
---
drivers/acpi/battery.c | 72 +++++++++++++++++++++++++++++++++-----------------
1 file changed, 48 insertions(+), 24 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 93ecae5..05fe9eb 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -430,39 +430,24 @@ static int acpi_battery_get_status(struct acpi_battery *battery)
return 0;
}
-static int acpi_battery_get_info(struct acpi_battery *battery)
+
+static int extract_battery_info(const int use_bix,
+ struct acpi_battery *battery,
+ const struct acpi_buffer *buffer)
{
int result = -EFAULT;
- acpi_status status = 0;
- char *name = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags) ?
- "_BIX" : "_BIF";
-
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- if (!acpi_battery_present(battery))
- return 0;
- mutex_lock(&battery->lock);
- status = acpi_evaluate_object(battery->device->handle, name,
- NULL, &buffer);
- mutex_unlock(&battery->lock);
-
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s", name));
- return -ENODEV;
- }
-
- if (battery_bix_broken_package)
- result = extract_package(battery, buffer.pointer,
+ if (use_bix && battery_bix_broken_package)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets + 1,
ARRAY_SIZE(extended_info_offsets) - 1);
- else if (test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags))
- result = extract_package(battery, buffer.pointer,
+ else if (use_bix)
+ result = extract_package(battery, buffer->pointer,
extended_info_offsets,
ARRAY_SIZE(extended_info_offsets));
else
- result = extract_package(battery, buffer.pointer,
+ result = extract_package(battery, buffer->pointer,
info_offsets, ARRAY_SIZE(info_offsets));
- kfree(buffer.pointer);
if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
battery->full_charge_capacity = battery->design_capacity;
if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
@@ -483,6 +468,45 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
return result;
}
+static int acpi_battery_get_info(struct acpi_battery *battery)
+{
+ const int xinfo = test_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
+ int use_bix;
+ int result = -ENODEV;
+
+ if (!acpi_battery_present(battery))
+ return 0;
+
+
+ for (use_bix = xinfo ? 1 : 0; use_bix >= 0; use_bix--) {
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ acpi_status status = AE_ERROR;
+
+ mutex_lock(&battery->lock);
+ status = acpi_evaluate_object(battery->device->handle,
+ use_bix ? "_BIX":"_BIF",
+ NULL, &buffer);
+ mutex_unlock(&battery->lock);
+
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status, "Evaluating %s",
+ use_bix ? "_BIX":"_BIF"));
+ } else {
+ result = extract_battery_info(use_bix,
+ battery,
+ &buffer);
+
+ kfree(buffer.pointer);
+ break;
+ }
+ }
+
+ if (!result && !use_bix && xinfo)
+ pr_warn(FW_BUG "The _BIX method is broken, using _BIF.\n");
+
+ return result;
+}
+
static int acpi_battery_get_state(struct acpi_battery *battery)
{
int result = 0;
--
2.7.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v3 1/1] If _BIX fails, retry with _BIF.
2016-11-04 1:05 ` [PATCH v3 1/1] If _BIX fails, retry with _BIF Dave Lambley
@ 2016-11-24 1:25 ` Rafael J. Wysocki
0 siblings, 0 replies; 11+ messages in thread
From: Rafael J. Wysocki @ 2016-11-24 1:25 UTC (permalink / raw)
To: Dave Lambley; +Cc: linux-acpi, Henrique de Moraes Holschuh, Len Brown
On Friday, November 04, 2016 01:05:40 AM Dave Lambley wrote:
> The Lenovo Yoga 300 laptop's firmware advertises that it provides the _BIX
> the method to retrieve battery information. Unfortunately (some versions
> of?) the implementation return with an error.
>
> [ 21.712228] ACPI Exception: AE_AML_PACKAGE_LIMIT, Index (0x000000010) is beyond end of object (length 0xD) (20160422/exoparg2-427)
> [ 21.712244] ACPI Error: Method parse/execution failed [\_SB.PCI0.LPCB.H_EC.BAT1._BIX] (Node ffff95f8ff0b20f0), AE_AML_PACKAGE_LIMIT (20160422/psparse-542)
>
> The _BIF method does succeed and returns convincing data. We detect _BIX
> failing and automatically retry with _BIF.
>
> Signed-off-by: Dave Lambley <linux@davel.me.uk>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Cc: Len Brown <lenb@kernel.org>
Patch applied.
Thanks,
Rafael
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2016-11-24 1:17 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-14 8:40 [PATCH] Avoid _BIX ACPI method on Lenovo Yoga 300 Dave Lambley
2016-09-14 10:34 ` Zheng, Lv
2016-09-17 22:56 ` [PATCH] If _BIX fails, retry with _BIF Dave Lambley
2016-11-02 18:37 ` [PATCH v2] Lenovo Yoga 300 battery support Dave Lambley
2016-11-02 18:37 ` [PATCH v2] If _BIX fails, retry with _BIF Dave Lambley
2016-11-02 23:26 ` Henrique de Moraes Holschuh
2016-11-03 8:33 ` Dave Lambley
2016-11-03 22:38 ` Henrique de Moraes Holschuh
2016-11-04 1:05 ` [PATCH v3 0/1] Lenovo Yoga 300 battery support Dave Lambley
2016-11-04 1:05 ` [PATCH v3 1/1] If _BIX fails, retry with _BIF Dave Lambley
2016-11-24 1:25 ` Rafael J. Wysocki
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.