For ECs that support it, the EC returns the number of slp_s0 transitions and whether or not there was a timeout in the resume response. Expose the last resume result to usermode via debugfs so that usermode can detect and report S0ix timeouts.
Unified · Split
| @@ -32,3 +32,25 @@ Description: · 31 unmodified lines | ||
| 32 | 32 | is used for synchronizing the AP host time with the EC |
| 33 | 33 | log. An error is returned if the command is not supported |
| 34 | 34 | by the EC or there is a communication problem. |
| 35 | + | |
| 36 | +What: /sys/kernel/debug/<cros-ec-device>/last_resume_result | |
| 37 | +Date: June 2019 | |
| 38 | +KernelVersion: 5.3 | |
| 39 | +Description: | |
| 40 | + Some ECs have a feature where they will track transitions to | |
| 41 | + the (Intel) processor's SLP_S0 line, in order to detect cases | |
| 42 | + where a system failed to go into S0ix. When the system resumes, | |
| 43 | + an EC with this feature will return a summary of SLP_S0 | |
| 44 | + transitions that occurred. The last_resume_result file returns | |
| 45 | + the most recent response from the AP's resume message to the EC. | |
| 46 | + | |
| 47 | + The bottom 31 bits contain a count of the number of SLP_S0 | |
| 48 | + transitions that occurred since the suspend message was | |
| 49 | + received. Bit 31 is set if the EC attempted to wake the | |
| 50 | + system due to a timeout when watching for SLP_S0 transitions. | |
| 51 | + Callers can use this to detect a wake from the EC due to | |
| 52 | + S0ix timeouts. The result will be zero if no suspend | |
| 53 | + transitions have been attempted, or the EC does not support | |
| 54 | + this feature. | |
| 55 | + | |
| 56 | + Output will be in the format: "0x%08x\n". | |
| @@ -110,12 +110,16 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | /* For now, report failure to transition to S0ix with a warning. */ |
| 112 | 112 | if (ret >= 0 && ec_dev->host_sleep_v1 && |
| 113 | − (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) | |
| 113 | + (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME)) { | |
| 114 | + ec_dev->last_resume_result = | |
| 115 | + buf.u.resp1.resume_response.sleep_transitions; | |
| 116 | + | |
| 114 | 117 | WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions & |
| 115 | 118 | EC_HOST_RESUME_SLEEP_TIMEOUT, |
| 116 | 119 | "EC detected sleep transition timeout. Total slp_s0 transitions: %d", |
| 117 | 120 | buf.u.resp1.resume_response.sleep_transitions & |
| 118 | 121 | EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK); |
| 122 | + } | |
| 119 | 123 | |
| 120 | 124 | return ret; |
| 121 | 125 | } |
| @@ -447,6 +447,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd) · 446 unmodified lines | ||
| 447 | 447 | debugfs_create_file("uptime", 0444, debug_info->dir, debug_info, |
| 448 | 448 | &cros_ec_uptime_fops); |
| 449 | 449 | |
| 450 | + debugfs_create_x32("last_resume_result", 0444, debug_info->dir, | |
| 451 | + &ec->ec_dev->last_resume_result); | |
| 452 | + | |
| 450 | 453 | ec->debug_info = debug_info; |
| 451 | 454 | |
| 452 | 455 | dev_set_drvdata(&pd->dev, ec); |
| @@ -163,6 +163,7 @@ struct cros_ec_device { · 162 unmodified lines | ||
| 163 | 163 | struct ec_response_get_next_event_v1 event_data; |
| 164 | 164 | int event_size; |
| 165 | 165 | u32 host_event_wake_mask; |
| 166 | + u32 last_resume_result; | |
| 166 | 167 | }; |
| 167 | 168 | |
| 168 | 169 | /** |