| From 3349fb64b2927407017d970dd5c4daf3c5ad69f8 Mon Sep 17 00:00:00 2001 |
| From: Chris Bainbridge <chris.bainbridge@gmail.com> |
| Date: Wed, 29 Apr 2015 21:21:40 +0100 |
| Subject: ACPI / SBS: Add 5 us delay to fix SBS hangs on MacBook |
| |
| From: Chris Bainbridge <chris.bainbridge@gmail.com> |
| |
| commit 3349fb64b2927407017d970dd5c4daf3c5ad69f8 upstream. |
| |
| Commit 7bc5a2bad0b8 'ACPI: Support _OSI("Darwin") correctly' caused |
| the MacBook firmware to expose the SBS, resulting in intermittent |
| hangs of several minutes on boot, and failure to detect or report |
| the battery. Fix this by adding a 5 us delay to the start of each |
| SMBUS transaction. This timing is the result of experimentation - |
| hangs were observed with 3 us but never with 5 us. |
| |
| Fixes: 7bc5a2bad0b8 'ACPI: Support _OSI("Darwin") correctly' |
| Link: https://bugzilla.kernel.org/show_bug.cgi?id=94651 |
| Signed-off-by: Chris Bainbridge <chris.bainbridge@gmail.com> |
| Cc: 3.18+ <stable@vger.kernel.org> # 3.18+ |
| [ rjw: Subject and changelog ] |
| Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/acpi/sbshc.c | 22 ++++++++++++++++++++++ |
| 1 file changed, 22 insertions(+) |
| |
| --- a/drivers/acpi/sbshc.c |
| +++ b/drivers/acpi/sbshc.c |
| @@ -14,6 +14,7 @@ |
| #include <linux/delay.h> |
| #include <linux/module.h> |
| #include <linux/interrupt.h> |
| +#include <linux/dmi.h> |
| #include "sbshc.h" |
| |
| #define PREFIX "ACPI: " |
| @@ -87,6 +88,8 @@ enum acpi_smb_offset { |
| ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */ |
| }; |
| |
| +static bool macbook; |
| + |
| static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data) |
| { |
| return ec_read(hc->offset + address, data); |
| @@ -132,6 +135,8 @@ static int acpi_smbus_transaction(struct |
| } |
| |
| mutex_lock(&hc->lock); |
| + if (macbook) |
| + udelay(5); |
| if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp)) |
| goto end; |
| if (temp) { |
| @@ -257,12 +262,29 @@ extern int acpi_ec_add_query_handler(str |
| acpi_handle handle, acpi_ec_query_func func, |
| void *data); |
| |
| +static int macbook_dmi_match(const struct dmi_system_id *d) |
| +{ |
| + pr_debug("Detected MacBook, enabling workaround\n"); |
| + macbook = true; |
| + return 0; |
| +} |
| + |
| +static struct dmi_system_id acpi_smbus_dmi_table[] = { |
| + { macbook_dmi_match, "Apple MacBook", { |
| + DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
| + DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") }, |
| + }, |
| + { }, |
| +}; |
| + |
| static int acpi_smbus_hc_add(struct acpi_device *device) |
| { |
| int status; |
| unsigned long long val; |
| struct acpi_smb_hc *hc; |
| |
| + dmi_check_system(acpi_smbus_dmi_table); |
| + |
| if (!device) |
| return -EINVAL; |
| |