summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorEvan Green <evgreen@chromium.org>2019-03-01 13:09:08 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-03-28 19:04:16 -0700
commit49b8070623ee1cecac387488ce668a4a11403653 (patch)
treebf4cc3078a496e7a9c8aa14c902be79cd3897c69 /util
parenta029c7a27f3bd1a1066db9c167c6166688fe4ef3 (diff)
downloadchrome-ec-49b8070623ee1cecac387488ce668a4a11403653.tar.gz
power/intel_x86: Introduce s0ix failure detection
This change introduces logic in the EC that can detect if the host attempted to go into S0ix, but never made it. The host already sends commands indicating its intent to enter S0ix, and the EC has a SLP_S0 line that gets asserted by the AP when it actually enters S0ix. All that's needed to monitor failures is to arm a timer when receiving the S0ix suspend message. If the SLP_S0 pin goes low, then the suspend occurred and the timer is canceled. If the timer expires before SLP_S0 goes low, then the EC wakes the AP up, since it has entered a shallower idle state than intended, and should be alerted to avoid short battery life. The timer is also started when SLP_S0 is deasserted on resume. The SoC comes out of S0ix to perform housekeeping activities unbeknownst to Linux. In cases where housekeeping fails to suspend all the way back down, this timer will wake the AP. Additionally, the number of S0ix transitions is reported on resume. This enabled the AP to analyze the amount of "sleepwalking" that is done, and can complain if it seems to be waking up too often. Design doc at: https://docs.google.com/document/d/1mY-v02KAuOyET3td9s5GnxeUgMiAcD058oLEo57DZpY/edit BUG=b:123716513 BRANCH=None TEST=Test S0ix on hatch with modified code that forces a timeout, use ectool to send messages manually before and after timeout, Hack Linux to fail suspend very late to verify no regressions. Signed-off-by: Evan Green <evgreen@chromium.org> Change-Id: Ia64b496675a13dbed4ef74637f51e39eee68aa1a Reviewed-on: https://chromium-review.googlesource.com/1501512 Commit-Ready: Evan Green <evgreen@chromium.org> Tested-by: Evan Green <evgreen@chromium.org> Reviewed-by: Furquan Shaikh <furquan@chromium.org> Reviewed-by: Karthikeyan Ramasubramanian <kramasub@chromium.org>
Diffstat (limited to 'util')
-rw-r--r--util/ectool.c113
1 files changed, 92 insertions, 21 deletions
diff --git a/util/ectool.c b/util/ectool.c
index 707eab71ac..42646923c5 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -509,33 +509,116 @@ int cmd_hibdelay(int argc, char *argv[])
return 0;
}
+static int get_latest_cmd_version(uint8_t cmd, int *version)
+{
+ struct ec_params_get_cmd_versions p;
+ struct ec_response_get_cmd_versions r;
+ int rv;
+
+ *version = 0;
+ /* Figure out the latest version of the given command the EC supports */
+ p.cmd = cmd;
+ rv = ec_command(EC_CMD_GET_CMD_VERSIONS, 0, &p, sizeof(p),
+ &r, sizeof(r));
+ if (rv < 0) {
+ if (rv == -EC_RES_INVALID_PARAM)
+ printf("Command 0x%02x not supported by EC.\n",
+ EC_CMD_GET_CMD_VERSIONS);
+ return rv;
+ }
+
+ if (r.version_mask)
+ *version = __fls(r.version_mask);
+
+ return rv;
+}
+
int cmd_hostsleepstate(int argc, char *argv[])
{
struct ec_params_host_sleep_event p;
+ struct ec_params_host_sleep_event_v1 p1;
+ struct ec_response_host_sleep_event_v1 r;
+ void *pp = &p;
+ size_t psize = sizeof(p), rsize = 0;
+ char *afterscan;
+ int rv;
+ int version = 0, max_version = 0;
+ uint32_t timeout, transitions;
if (argc < 2) {
fprintf(stderr, "Usage: %s "
- "[suspend|wsuspend|resume|freeze|thaw]\n",
+ "[suspend|wsuspend|resume|freeze|thaw] [timeout]\n",
argv[0]);
return -1;
}
+ rv = get_latest_cmd_version(EC_CMD_HOST_SLEEP_EVENT, &max_version);
+ if (rv < 0)
+ return rv;
+
if (!strcmp(argv[1], "suspend"))
p.sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
else if (!strcmp(argv[1], "wsuspend"))
p.sleep_event = HOST_SLEEP_EVENT_S3_WAKEABLE_SUSPEND;
else if (!strcmp(argv[1], "resume"))
p.sleep_event = HOST_SLEEP_EVENT_S3_RESUME;
- else if (!strcmp(argv[1], "freeze"))
+ else if (!strcmp(argv[1], "freeze")) {
p.sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
- else if (!strcmp(argv[1], "thaw"))
+ if (max_version >= 1) {
+ p1.sleep_event = p.sleep_event;
+ p1.reserved = 0;
+ p1.suspend_params.sleep_timeout_ms =
+ EC_HOST_SLEEP_TIMEOUT_DEFAULT;
+
+ if (argc > 2) {
+ p1.suspend_params.sleep_timeout_ms =
+ strtoul(argv[2], &afterscan, 0);
+
+ if ((*afterscan != '\0') ||
+ (afterscan == argv[2])) {
+ fprintf(stderr,
+ "Invalid value: %s\n",
+ argv[2]);
+
+ return -1;
+ }
+ }
+
+ pp = &p1;
+ psize = sizeof(p1);
+ version = 1;
+ }
+
+ } else if (!strcmp(argv[1], "thaw")) {
p.sleep_event = HOST_SLEEP_EVENT_S0IX_RESUME;
- else {
+ if (max_version >= 1) {
+ version = 1;
+ rsize = sizeof(r);
+ }
+ } else {
fprintf(stderr, "Unknown command: %s\n", argv[1]);
return -1;
}
- return ec_command(EC_CMD_HOST_SLEEP_EVENT, 0, &p, sizeof(p), NULL, 0);
+ rv = ec_command(EC_CMD_HOST_SLEEP_EVENT, version, pp, psize, &r, rsize);
+ if (rv < 0) {
+ fprintf(stderr, "EC host sleep command failed: %d\n", rv);
+ return rv;
+ }
+
+ if (rsize) {
+ timeout = r.resume_response.sleep_transitions &
+ EC_HOST_RESUME_SLEEP_TIMEOUT;
+
+ transitions = r.resume_response.sleep_transitions &
+ EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK;
+
+ printf("%s%d sleep line transitions.\n",
+ timeout ? "Timeout: " : "",
+ transitions);
+ }
+
+ return 0;
}
int cmd_test(int argc, char *argv[])
@@ -4218,10 +4301,12 @@ static int cmd_motionsense(int argc, char **argv)
}
if (argc == 3 && !strcasecmp(argv[1], "info")) {
- struct ec_params_get_cmd_versions p;
- struct ec_response_get_cmd_versions r;
int version = 0;
+ rv = get_latest_cmd_version(EC_CMD_MOTION_SENSE_CMD, &version);
+ if (rv < 0)
+ return rv;
+
param.cmd = MOTIONSENSE_CMD_INFO;
param.sensor_odr.sensor_num = strtol(argv[2], &e, 0);
if (e && *e) {
@@ -4229,20 +4314,6 @@ static int cmd_motionsense(int argc, char **argv)
return -1;
}
- /* tool defaults to using latest version of info command */
- p.cmd = EC_CMD_MOTION_SENSE_CMD;
- rv = ec_command(EC_CMD_GET_CMD_VERSIONS, 0, &p, sizeof(p),
- &r, sizeof(r));
- if (rv < 0) {
- if (rv == -EC_RES_INVALID_PARAM)
- printf("Command 0x%02x not supported by EC.\n",
- EC_CMD_GET_CMD_VERSIONS);
- return rv;
- }
-
- if (r.version_mask)
- version = __fls(r.version_mask);
-
rv = ec_command(EC_CMD_MOTION_SENSE_CMD, version,
&param, ms_command_sizes[param.cmd].outsize,
resp, ms_command_sizes[param.cmd].insize);