aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Bainbridge <chris.bainbridge@gmail.com>2015-04-29 16:21:40 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-04-30 17:18:11 -0400
commit3349fb64b2927407017d970dd5c4daf3c5ad69f8 (patch)
tree7f446e4537f411daa245f1b0a16ec628a76442d1
parent61f8ff693923e4b19748b0e8287b99778f2661c7 (diff)
ACPI / SBS: Add 5 us delay to fix SBS hangs on MacBook
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>
-rw-r--r--drivers/acpi/sbshc.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 26e5b5060523..bf034f8b7c1a 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -14,6 +14,7 @@
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/dmi.h>
17#include "sbshc.h" 18#include "sbshc.h"
18 19
19#define PREFIX "ACPI: " 20#define PREFIX "ACPI: "
@@ -87,6 +88,8 @@ enum acpi_smb_offset {
87 ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */ 88 ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */
88}; 89};
89 90
91static bool macbook;
92
90static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data) 93static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
91{ 94{
92 return ec_read(hc->offset + address, data); 95 return ec_read(hc->offset + address, data);
@@ -132,6 +135,8 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
132 } 135 }
133 136
134 mutex_lock(&hc->lock); 137 mutex_lock(&hc->lock);
138 if (macbook)
139 udelay(5);
135 if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp)) 140 if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
136 goto end; 141 goto end;
137 if (temp) { 142 if (temp) {
@@ -257,12 +262,29 @@ extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit,
257 acpi_handle handle, acpi_ec_query_func func, 262 acpi_handle handle, acpi_ec_query_func func,
258 void *data); 263 void *data);
259 264
265static int macbook_dmi_match(const struct dmi_system_id *d)
266{
267 pr_debug("Detected MacBook, enabling workaround\n");
268 macbook = true;
269 return 0;
270}
271
272static struct dmi_system_id acpi_smbus_dmi_table[] = {
273 { macbook_dmi_match, "Apple MacBook", {
274 DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
275 DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
276 },
277 { },
278};
279
260static int acpi_smbus_hc_add(struct acpi_device *device) 280static int acpi_smbus_hc_add(struct acpi_device *device)
261{ 281{
262 int status; 282 int status;
263 unsigned long long val; 283 unsigned long long val;
264 struct acpi_smb_hc *hc; 284 struct acpi_smb_hc *hc;
265 285
286 dmi_check_system(acpi_smbus_dmi_table);
287
266 if (!device) 288 if (!device)
267 return -EINVAL; 289 return -EINVAL;
268 290