Skip to content

Commit 60c7df6

Browse files
walshbTzung-Bi Shih
authored andcommitted
platform/chrome: cros_ec_lpc: MEC access can use an AML mutex
Framework Laptops have ACPI code which accesses the MEC memory. It uses an AML mutex to prevent concurrent access. But the cros_ec_lpc driver was not aware of this mutex. The ACPI code and LPC driver both attempted to talk to the EC at the same time, messing up communication with the EC. Allow the LPC driver MEC code to find and use the AML mutex. Tested-by: Dustin L. Howett <[email protected]> Signed-off-by: Ben Walsh <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Tzung-Bi Shih <[email protected]>
1 parent 68dbac0 commit 60c7df6

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

drivers/platform/chrome/cros_ec_lpc_mec.c

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,65 @@
1010

1111
#include "cros_ec_lpc_mec.h"
1212

13+
#define ACPI_LOCK_DELAY_MS 500
14+
1315
/*
1416
* This mutex must be held while accessing the EMI unit. We can't rely on the
1517
* EC mutex because memmap data may be accessed without it being held.
1618
*/
1719
static DEFINE_MUTEX(io_mutex);
20+
/*
21+
* An alternative mutex to be used when the ACPI AML code may also
22+
* access memmap data. When set, this mutex is used in preference to
23+
* io_mutex.
24+
*/
25+
static acpi_handle aml_mutex;
26+
1827
static u16 mec_emi_base, mec_emi_end;
1928

29+
/**
30+
* cros_ec_lpc_mec_lock() - Acquire mutex for EMI
31+
*
32+
* @return: Negative error code, or zero for success
33+
*/
34+
static int cros_ec_lpc_mec_lock(void)
35+
{
36+
bool success;
37+
38+
if (!aml_mutex) {
39+
mutex_lock(&io_mutex);
40+
return 0;
41+
}
42+
43+
success = ACPI_SUCCESS(acpi_acquire_mutex(aml_mutex,
44+
NULL, ACPI_LOCK_DELAY_MS));
45+
if (!success)
46+
return -EBUSY;
47+
48+
return 0;
49+
}
50+
51+
/**
52+
* cros_ec_lpc_mec_unlock() - Release mutex for EMI
53+
*
54+
* @return: Negative error code, or zero for success
55+
*/
56+
static int cros_ec_lpc_mec_unlock(void)
57+
{
58+
bool success;
59+
60+
if (!aml_mutex) {
61+
mutex_unlock(&io_mutex);
62+
return 0;
63+
}
64+
65+
success = ACPI_SUCCESS(acpi_release_mutex(aml_mutex, NULL));
66+
if (!success)
67+
return -EBUSY;
68+
69+
return 0;
70+
}
71+
2072
/**
2173
* cros_ec_lpc_mec_emi_write_address() - Initialize EMI at a given address.
2274
*
@@ -78,6 +130,7 @@ int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
78130
int io_addr;
79131
u8 sum = 0;
80132
enum cros_ec_lpc_mec_emi_access_mode access, new_access;
133+
int ret;
81134

82135
/* Return checksum of 0 if window is not initialized */
83136
WARN_ON(mec_emi_base == 0 || mec_emi_end == 0);
@@ -93,7 +146,9 @@ int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
93146
else
94147
access = ACCESS_TYPE_LONG_AUTO_INCREMENT;
95148

96-
mutex_lock(&io_mutex);
149+
ret = cros_ec_lpc_mec_lock();
150+
if (ret)
151+
return ret;
97152

98153
/* Initialize I/O at desired address */
99154
cros_ec_lpc_mec_emi_write_address(offset, access);
@@ -135,7 +190,9 @@ int cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
135190
}
136191

137192
done:
138-
mutex_unlock(&io_mutex);
193+
ret = cros_ec_lpc_mec_unlock();
194+
if (ret)
195+
return ret;
139196

140197
return sum;
141198
}
@@ -147,3 +204,18 @@ void cros_ec_lpc_mec_init(unsigned int base, unsigned int end)
147204
mec_emi_end = end;
148205
}
149206
EXPORT_SYMBOL(cros_ec_lpc_mec_init);
207+
208+
int cros_ec_lpc_mec_acpi_mutex(struct acpi_device *adev, const char *pathname)
209+
{
210+
int status;
211+
212+
if (!adev)
213+
return -ENOENT;
214+
215+
status = acpi_get_handle(adev->handle, pathname, &aml_mutex);
216+
if (ACPI_FAILURE(status))
217+
return -ENOENT;
218+
219+
return 0;
220+
}
221+
EXPORT_SYMBOL(cros_ec_lpc_mec_acpi_mutex);

drivers/platform/chrome/cros_ec_lpc_mec.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#ifndef __CROS_EC_LPC_MEC_H
99
#define __CROS_EC_LPC_MEC_H
1010

11+
#include <linux/acpi.h>
12+
1113
enum cros_ec_lpc_mec_emi_access_mode {
1214
/* 8-bit access */
1315
ACCESS_TYPE_BYTE = 0x0,
@@ -45,6 +47,15 @@ enum cros_ec_lpc_mec_io_type {
4547
*/
4648
void cros_ec_lpc_mec_init(unsigned int base, unsigned int end);
4749

50+
/**
51+
* cros_ec_lpc_mec_acpi_mutex() - Find and set ACPI mutex for MEC
52+
*
53+
* @adev: Parent ACPI device
54+
* @pathname: Name of AML mutex
55+
* @return: Negative error code, or zero for success
56+
*/
57+
int cros_ec_lpc_mec_acpi_mutex(struct acpi_device *adev, const char *pathname);
58+
4859
/**
4960
* cros_ec_lpc_mec_in_range() - Determine if addresses are in MEC EMI range.
5061
*

0 commit comments

Comments
 (0)