Example #1
0
File: s4.c Project: 9elements/fwts
static int s4_hibernate(fwts_framework *fw,
	int *klog_errors,
	int *hw_errors,
	int *pm_errors,
	int *klog_oopses,
	int *klog_warn_ons,
	int *failed_alloc_image,
	int percent)
{
	fwts_list *klog_pre, *klog_post, *klog_diff;
	fwts_hwinfo hwinfo1, hwinfo2;
	int status;
	int duration;
	int differences;
	int rc = FWTS_OK;
	char *command = NULL;
	char *quirks = NULL;
	fwts_pm_method_vars *fwts_settings;

	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 (fw->pm_method == FWTS_PM_UNDEFINED) {
		/* Autodetection */
		fwts_log_info(fw, "Detecting the power method.");
		detect_pm_method(fwts_settings);
	}

	switch (fw->pm_method) {
#if FWTS_ENABLE_LOGIND
		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.");
				rc = FWTS_ERROR;
				goto tidy;
			}
			do_s4 = &wrap_logind_do_s4;
			break;
#endif
		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) {
			rc = FWTS_OUT_OF_MEMORY;
			goto tidy;
		}

		/* For now we only support quirks with pm-utils */
		if (s4_quirks) {
			if ((command = fwts_realloc_strcat(command, " ")) == NULL) {
				rc = FWTS_OUT_OF_MEMORY;
				goto tidy;
			}
			if ((quirks = fwts_args_comma_list(s4_quirks)) == NULL) {
				rc = FWTS_OUT_OF_MEMORY;
				goto tidy;
			}
			if ((command = fwts_realloc_strcat(command, quirks)) == NULL) {
				rc = FWTS_OUT_OF_MEMORY;
				goto tidy;
			}
		}
	}

	fwts_wakealarm_trigger(fw, s4_sleep_delay);

	/* Do s4 here */
	if ((klog_pre = fwts_klog_read()) == NULL)
		fwts_log_error(fw, "S4: hibernate: Cannot read kernel log.");

	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.");

	if (s4_device_check) {
		int i;

		for (i = 0; i < s4_device_check_delay; i++) {
			char buffer[80];

			snprintf(buffer, sizeof(buffer), "(Waiting %d/%d seconds)", i+1, s4_device_check_delay);
			fwts_progress_message(fw, percent, buffer);
			sleep(1);
		}
		fwts_progress_message(fw, percent, "(Checking devices)");
		fwts_hwinfo_get(fw, &hwinfo2);
		fwts_hwinfo_compare(fw, &hwinfo1, &hwinfo2, &differences);
		fwts_hwinfo_free(&hwinfo1);
		fwts_hwinfo_free(&hwinfo2);

		if (differences > 0) {
			fwts_failed(fw, LOG_LEVEL_HIGH, "DevConfigDiffAfterS4",
				"Found %d differences in device configuation during S4 cycle.", differences);
			(*hw_errors)++;
		}
	}

	fwts_progress_message(fw, percent, "(Checking for errors)");

	klog_diff = fwts_klog_find_changes(klog_pre, klog_post);
	s4_check_log(fw, klog_diff, klog_errors, klog_oopses, klog_warn_ons);

	fwts_progress_message(fw, percent, "(Checking for PM errors)");

	/* Add in error check for pm-hibernate status */
	if ((status > 0) && (status < 128)) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "PMActionFailedPreS4",
			"pm-action failed before trying to put the system "
			"in the requested power saving state.");
		(*pm_errors)++;
	} else if (status == 128) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "PMActionPowerStateS4",
			"pm-action tried to put the machine in the requested "
			"power state but failed.");
		(*pm_errors)++;
	} else if (status > 128) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "PMActionFailedS4",
			"pm-action encountered an error and also failed to "
			"enter the requested power saving state.");
		(*pm_errors)++;
	}

	if (fwts_klog_regex_find(fw, klog_diff, "Freezing user space processes.*done") < 1) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "UserSpaceTaskFreeze",
			"Failed to freeze user space processes.");
		(*pm_errors)++;
	}

	if (fwts_klog_regex_find(fw, klog_diff, "Freezing remaining freezable tasks.*done") < 1) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "KernelTaskFreeze",
			"Failed to freeze remaining non-user space processes.");
		(*pm_errors)++;
	}

	if ((fwts_klog_regex_find(fw, klog_diff, "PM: freeze of devices complete") < 1) &&
	    (fwts_klog_regex_find(fw, klog_diff, "PM: late freeze of devices complete") < 1)) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "DeviceFreeze",
			"Failed to freeze devices.");
		(*pm_errors)++;
	}

	if (fwts_klog_regex_find(fw, klog_diff, "PM: Allocated.*kbytes") < 1) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "HibernateImageAlloc",
			"Failed to allocate memory for hibernate image.");
		*failed_alloc_image = 1;
		(*pm_errors)++;
	}

	if (fwts_klog_regex_find(fw, klog_diff, "PM: Image restored successfully") < 1) {
		fwts_failed(fw, LOG_LEVEL_HIGH, "HibernateImageRestore",
			"Failed to restore hibernate image.");
		(*pm_errors)++;
	}

	fwts_klog_free(klog_pre);
	fwts_klog_free(klog_post);
	fwts_list_free(klog_diff, NULL);
tidy:
	free(command);
	free(quirks);
	free_pm_method_vars(fwts_settings);

	return rc;
}
Example #2
0
static int auto_brightness_test2(fwts_framework *fw)
{
	struct dirent *entry;
	int max_brightness;
	int actual_brightness;
	int saved_brightness;
	DIR *brightness_dir = brightness_get_dir();

	rewinddir(brightness_dir);
	do {
		int i;
		int failures = 0;
		bool *brightness_fail;

		entry = readdir(brightness_dir);
		if (entry == NULL || entry->d_name[0] == '.')
			continue;

		if (brightness_get_setting(entry->d_name, "max_brightness", &max_brightness) != FWTS_OK) {
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"BrightnessNotExist",
				"Maximum brightness could not be accessed for %s.",
				entry->d_name);
			continue;
		}

		if (max_brightness <= 0) {
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"BrightnessMaxTest2",
				"Maximum brightness for %s is %d and should be > 0.",
				entry->d_name, max_brightness);
			continue;
		}

		if (brightness_get_setting(entry->d_name, "actual_brightness", &saved_brightness) != FWTS_OK) {
			fwts_failed(fw, LOG_LEVEL_HIGH,
				"BrightnessNotExist",
				"Maximum brightness could not be accessed for %s.",
				entry->d_name);
			continue;
		}

		brightness_fail = calloc(sizeof(bool), max_brightness + 1);
		if (brightness_fail == NULL) {
			fwts_log_error(fw, "Cannot allocate brightness table.");
			continue;
		}

		for (i = 0; i <= max_brightness; i++) {
			brightness_set_setting(entry->d_name, "brightness", i);
			if (brightness_get_setting(entry->d_name, "actual_brightness", &actual_brightness) != FWTS_OK) {
				fwts_log_info(fw, "Cannot get brightness setting %d for backlight %s.", i, entry->d_name);
				failures++;
				brightness_fail[i] = true;
				continue;
			}
			if (actual_brightness != i) {
				failures++;
				brightness_fail[i] = true;
			} else {
				brightness_fail[i] = false;
			}
		}

		if (failures) {
			char *msg = NULL;
			char buf[40];

			/* Find the ranges of the failed levels */
			for (i = 0; i <= max_brightness; i++) {
				int end = i;

				if (brightness_fail[i]) {
					int j;

					/* Scan until we don't find a failure */
					for (j = i; j <= max_brightness && brightness_fail[j]; j++)
						end = j;

					if (i == end) {
						/* Just one failure */
						snprintf(buf, sizeof(buf), " %d", i);
					} else {
						/* A contiguous range of failures */
						snprintf(buf, sizeof(buf), " %d-%d", i, end);
						i = end;
					}
					msg = fwts_realloc_strcat(msg, buf);
				}
			}
			fwts_failed(fw, LOG_LEVEL_MEDIUM,
				"BrightnessMismatch",
				"%d brightness levels did not match the brightnesss level "
				"just set for backlight %s.",
				failures, entry->d_name);
			fwts_log_info(fw, "The failed brightness levels were:%s.", msg);
			free(msg);
		} else
			fwts_passed(fw, "Actual brightness matches the brightnesss level for "
				"all %d levels for backlight %s.", max_brightness, entry->d_name);

		free(brightness_fail);

		/* Restore original setting */
		brightness_set_setting(entry->d_name, "brightness", saved_brightness);
	} while (entry);

	return FWTS_OK;
}