ACK: [PATCH 4/7] s4.c: add support for logind and sysfs methods
Keng-Yu Lin
keng-yu.lin at canonical.com
Mon Aug 4 14:15:51 UTC 2014
On Mon, Aug 4, 2014 at 6:03 PM, Alex Hung <alex.hung at canonical.com> wrote:
> On 08/01/2014 06:20 PM, Alberto Milone wrote:
>>
>> As with s3.c, we now make use of different power methods and default
>> to logind, leaving pm-utils as an option.
>>
>> Signed-off-by: Alberto Milone <alberto.milone at canonical.com>
>> ---
>> src/acpi/s4/s4.c | 167
>> ++++++++++++++++++++++++++++++++++++++++++++++---------
>> 1 file changed, 140 insertions(+), 27 deletions(-)
>>
>> diff --git a/src/acpi/s4/s4.c b/src/acpi/s4/s4.c
>> index 1904095..2ce8b3d 100644
>> --- a/src/acpi/s4/s4.c
>> +++ b/src/acpi/s4/s4.c
>> @@ -17,6 +17,7 @@
>> *
>> */
>> #include "fwts.h"
>> +#include "fwts_pm_method.h"
>>
>> #ifdef FWTS_ARCH_INTEL
>>
>> @@ -26,10 +27,11 @@
>> #include <sys/stat.h>
>> #include <unistd.h>
>>
>> -#define PM_HIBERNATE "pm-hibernate"
>> -#define FWTS_HIBERNATE "FWTS_HIBERNATE"
>> -#define FWTS_RESUME "FWTS_RESUME"
>> +static inline void freep(void *);
>> +
>> +#define _cleanup_free_ __attribute__((cleanup(freep)))
>>
>> +#define PM_HIBERNATE "pm-hibernate"
>>
>> #define FWTS_TRACING_BUFFER_SIZE
>> "/sys/kernel/debug/tracing/buffer_size_kb"
>>
>> @@ -43,6 +45,11 @@ static char *s4_quirks = NULL; /* Quirks
>> to be passed to pm-hibernate */
>> static int s4_device_check_delay = 15; /* Time to sleep after
>> waking up and then running device check */
>> static bool s4_min_max_delay = false;
>>
>> +static inline void freep(void *p)
>> +{
>> + free(*(void**) p);
>> +}
>> +
>> static int s4_init(fwts_framework *fw)
>> {
>> fwts_list* swap_devs;
>> @@ -88,6 +95,79 @@ static void s4_check_log(fwts_framework *fw,
>> *warn_ons += warn_on;
>> }
>>
>> +/* Detect the best power method available */
>> +static void detect_pm_method(fwts_pm_method_vars *fwts_settings)
>> +{
>> + if (fwts_logind_can_hibernate(fwts_settings))
>> + fwts_settings->fw->pm_method = FWTS_PM_LOGIND;
>> + else if (fwts_sysfs_can_hibernate(fwts_settings))
>> + fwts_settings->fw->pm_method = FWTS_PM_SYSFS;
>> + else
>> + fwts_settings->fw->pm_method = FWTS_PM_PMUTILS;
>> +}
>> +
>> +static int wrap_logind_do_s4(fwts_pm_method_vars *fwts_settings,
>> + const int percent,
>> + int *duration,
>> + const char *str)
>> +{
>> + FWTS_UNUSED(str);
>> + char *action = PM_HIBERNATE_LOGIND;
>> + fwts_progress_message(fwts_settings->fw, percent,
>> "(Hibernating)");
>> +
>> + /* This blocks by entering a glib mainloop */
>> + *duration = fwts_logind_wait_for_resume_from_action(fwts_settings,
>> action, s4_min_delay);
>> + fwts_log_info(fwts_settings->fw, "S4 duration = %d.", *duration);
>> + fwts_progress_message(fwts_settings->fw, percent, "(Resumed)");
>> +
>> + return *duration > 0 ? 0 : 1;
>> +}
>> +
>> +static int wrap_sysfs_do_s4(fwts_pm_method_vars *fwts_settings,
>> + const int percent,
>> + int *duration,
>> + const char *str)
>> +{
>> + int status;
>> +
>> + FWTS_UNUSED(str);
>> + fwts_progress_message(fwts_settings->fw, percent,
>> "(Hibernating)");
>> + time(&(fwts_settings->t_start));
>> + (void)fwts_klog_write(fwts_settings->fw, "Starting fwts
>> hibernate\n");
>> + (void)fwts_klog_write(fwts_settings->fw, FWTS_HIBERNATE "\n");
>> + status = fwts_sysfs_do_hibernate(fwts_settings);
>> + (void)fwts_klog_write(fwts_settings->fw, FWTS_RESUME "\n");
>> + (void)fwts_klog_write(fwts_settings->fw, "Finished fwts
>> resume\n");
>> + time(&(fwts_settings->t_end));
>> + fwts_progress_message(fwts_settings->fw, percent, "(Resumed)");
>> +
>> + *duration = (int)(fwts_settings->t_end - fwts_settings->t_start);
>> +
>> + return status;
>> +}
>> +
>> +static int wrap_pmutils_do_s4(fwts_pm_method_vars *fwts_settings,
>> + const int percent,
>> + int *duration,
>> + const char *command)
>> +{
>> + int status;
>> +
>> + fwts_progress_message(fwts_settings->fw, percent,
>> "(Hibernating)");
>> + time(&(fwts_settings->t_start));
>> + (void)fwts_klog_write(fwts_settings->fw, "Starting fwts
>> hibernate\n");
>> + (void)fwts_klog_write(fwts_settings->fw, FWTS_HIBERNATE "\n");
>> + (void)fwts_exec(command, &status);
>> + (void)fwts_klog_write(fwts_settings->fw, FWTS_RESUME "\n");
>> + (void)fwts_klog_write(fwts_settings->fw, "Finished fwts
>> resume\n");
>> + time(&(fwts_settings->t_end));
>> + fwts_progress_message(fwts_settings->fw, percent, "(Resumed)");
>> +
>> + *duration = (int)(fwts_settings->t_end - fwts_settings->t_start);
>> +
>> + return status;
>> +}
>> +
>> static int s4_hibernate(fwts_framework *fw,
>> int *klog_errors,
>> int *hw_errors,
>> @@ -100,30 +180,70 @@ static int s4_hibernate(fwts_framework *fw,
>> fwts_list *klog_pre, *klog_post, *klog_diff;
>> fwts_hwinfo hwinfo1, hwinfo2;
>> int status;
>> + int duration;
>> int differences;
>> - char *command;
>> - char *quirks;
>> + _cleanup_free_ char *command = NULL;
>> + _cleanup_free_ char *quirks = NULL;
>> + _cleanup_free_pm_vars_ fwts_pm_method_vars * fwts_settings = NULL;
>> char buffer[80];
>>
>> - if (s4_device_check)
>> - fwts_hwinfo_get(fw, &hwinfo1);
>>
>> - /* Format up pm-hibernate command with optional quirking arguments
>> */
>> - if ((command = fwts_realloc_strcat(NULL, PM_HIBERNATE)) == NULL)
>> + int (*do_s4)(fwts_pm_method_vars *, const int, int*, const char*);
>> +
>> + fwts_settings = calloc(1, sizeof(fwts_pm_method_vars));
>> + if (fwts_settings == NULL)
>> return FWTS_OUT_OF_MEMORY;
>> + fwts_settings->fw = fw;
>>
>> - if (s4_quirks) {
>> - if ((command = fwts_realloc_strcat(command, " ")) == NULL)
>> - return FWTS_OUT_OF_MEMORY;
>> - if ((quirks = fwts_args_comma_list(s4_quirks)) == NULL) {
>> - free(command);
>> - return FWTS_OUT_OF_MEMORY;
>> - }
>> - if ((command = fwts_realloc_strcat(command, quirks)) ==
>> NULL) {
>> - free(quirks);
>> + if (fw->pm_method == FWTS_PM_UNDEFINED) {
>> + /* Autodetection */
>> + fwts_log_info(fw, "Detecting the power method.");
>> + detect_pm_method(fwts_settings);
>> + }
>> +
>> + switch (fw->pm_method) {
>> + case FWTS_PM_LOGIND:
>> + fwts_log_info(fw, "Using logind as the default
>> power method.");
>> + if (fwts_logind_init_proxy(fwts_settings) != 0) {
>> + fwts_log_error(fw, "Failure to connect to
>> Logind.");
>> + return FWTS_ERROR;
>> + }
>> + do_s4 = &wrap_logind_do_s4;
>> + break;
>> + case FWTS_PM_PMUTILS:
>> + fwts_log_info(fw, "Using pm-utils as the default
>> power method.");
>> + do_s4 = &wrap_pmutils_do_s4;
>> + break;
>> + case FWTS_PM_SYSFS:
>> + fwts_log_info(fw, "Using sysfs as the default
>> power method.");
>> + do_s4 = &wrap_sysfs_do_s4;
>> + break;
>> + default:
>> + /* This should never happen */
>> + fwts_log_info(fw, "Using sysfs as the default
>> power method.");
>> + do_s4 = &wrap_sysfs_do_s4;
>> + break;
>> + }
>> +
>> + if (s4_device_check)
>> + fwts_hwinfo_get(fw, &hwinfo1);
>> +
>> + if (fw->pm_method == FWTS_PM_PMUTILS) {
>> + /* Format up pm-hibernate command with optional quirking
>> arguments */
>> + if ((command = fwts_realloc_strcat(NULL, PM_HIBERNATE)) ==
>> NULL)
>> return FWTS_OUT_OF_MEMORY;
>> +
>> + /* For now we only support quirks with pm-utils */
>> + if (s4_quirks) {
>> + if ((command = fwts_realloc_strcat(command, " "))
>> == NULL)
>> + return FWTS_OUT_OF_MEMORY;
>> + if ((quirks = fwts_args_comma_list(s4_quirks)) ==
>> NULL) {
>> + return FWTS_OUT_OF_MEMORY;
>> + }
>> + if ((command = fwts_realloc_strcat(command,
>> quirks)) == NULL) {
>> + return FWTS_OUT_OF_MEMORY;
>> + }
>> }
>> - free(quirks);
>> }
>>
>> fwts_wakealarm_trigger(fw, s4_sleep_delay);
>> @@ -132,14 +252,7 @@ static int s4_hibernate(fwts_framework *fw,
>> if ((klog_pre = fwts_klog_read()) == NULL)
>> fwts_log_error(fw, "S4: hibernate: Cannot read kernel
>> log.");
>>
>> - fwts_progress_message(fw, percent, "(Hibernating)");
>> - (void)fwts_klog_write(fw, "Starting fwts hibernate\n");
>> - (void)fwts_klog_write(fw, FWTS_HIBERNATE "\n");
>> - (void)fwts_exec(command, &status);
>> - (void)fwts_klog_write(fw, FWTS_RESUME "\n");
>> - (void)fwts_klog_write(fw, "Finished fwts resume\n");
>> - fwts_progress_message(fw, percent, "(Resumed)");
>> - free(command);
>> + status = do_s4(fwts_settings, percent, &duration, command);
>>
>> if ((klog_post = fwts_klog_read()) == NULL)
>> fwts_log_error(fw, "S4: hibernate: Cannot re-read kernel
>> log.");
>>
>
> Acked-by: Alex Hung <alex.hung at canonical.com>
>
Acked-by: Keng-Yu Lin <kengyu at canonical.com>
More information about the fwts-devel
mailing list