ACK: [PATCH][RESEND] wakealarm: use ioctl() interface as this more of a generic interface (LP: #1244184)
Alex Hung
alex.hung at canonical.com
Thu Oct 31 03:36:23 UTC 2013
On 10/29/2013 01:42 AM, Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
>
> This test fails on non-x86 architectures, so use the more generic ioctl
> alarm interface instead.
>
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
> src/acpi/wakealarm/wakealarm.c | 18 ++---
> src/lib/include/fwts_wakealarm.h | 5 +-
> src/lib/src/fwts_wakealarm.c | 159 ++++++++++++++++++++++++++++++---------
> 3 files changed, 132 insertions(+), 50 deletions(-)
>
> diff --git a/src/acpi/wakealarm/wakealarm.c b/src/acpi/wakealarm/wakealarm.c
> index 7f4886a..1176be0 100644
> --- a/src/acpi/wakealarm/wakealarm.c
> +++ b/src/acpi/wakealarm/wakealarm.c
> @@ -25,27 +25,23 @@
> #include <unistd.h>
> #include <string.h>
>
> -static const char *wkalarm = WAKEALARM;
> -
> static int wakealarm_test1(fwts_framework *fw)
> {
> - struct stat buf;
> -
> - if (stat(wkalarm, &buf) == 0)
> - fwts_passed(fw, WAKEALARM " found.");
> + if (fwts_wakealarm_exits(fw) == FWTS_OK)
> + fwts_passed(fw, "RTC with a RTC alarm ioctl() interface found.");
> else {
> fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoWakeAlarmTest1",
> - "Could not find " WAKEALARM ".");
> + "Could not find an RTC with an alarm ioctl() interface.");
> #ifdef FWTS_ARCH_INTEL
> /* For x86 devices, this is considered a failure */
> fwts_advice(fw,
> "x86 devices generally should have an RTC wake alarm that "
> - "is normally controlled by the " WAKEALARM " interface. This interface "
> + "is normally controlled by the RTC alarm ioctl() interface. This interface "
> "does not exist, so the wake alarm tests will be aborted.");
> #else
> fwts_advice(fw,
> "non-x86 devices sometimes do not have an RTC wake alarm that "
> - "is normally controlled by the " WAKEALARM " interface. This "
> + "is normally controlled by the RTC alarm ioctl() interface. This "
> "interface does not exist, so the wake alarm tests will be aborted.");
> #endif
> return FWTS_ABORTED;
> @@ -64,6 +60,8 @@ static int wakealarm_test2(fwts_framework *fw)
> return FWTS_OK;
> }
>
> + (void)fwts_wakealarm_cancel(fw);
> +
> fwts_passed(fw, "RTC wakealarm was triggered successfully.");
>
> return FWTS_OK;
> @@ -122,7 +120,7 @@ static int wakealarm_test4(fwts_framework *fw)
> }
>
> static fwts_framework_minor_test wakealarm_tests[] = {
> - { wakealarm_test1, "Check existence of " WAKEALARM "." },
> + { wakealarm_test1, "Check existence of RTC with alarm interface." },
> { wakealarm_test2, "Trigger wakealarm for 1 seconds in the future." },
> { wakealarm_test3, "Check if wakealarm is fired." },
> { wakealarm_test4, "Multiple wakealarm firing tests." },
> diff --git a/src/lib/include/fwts_wakealarm.h b/src/lib/include/fwts_wakealarm.h
> index df95e41..b4994fd 100644
> --- a/src/lib/include/fwts_wakealarm.h
> +++ b/src/lib/include/fwts_wakealarm.h
> @@ -22,10 +22,9 @@
>
> #include "fwts_framework.h"
>
> -#define WAKEALARM "/sys/class/rtc/rtc0/wakealarm"
> -
> -int fwts_wakealarm_get_irq_state(void);
> +int fwts_wakealarm_exits(fwts_framework *fw);
> int fwts_wakealarm_test_firing(fwts_framework *fw, const int sleep);
> int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds);
> +int fwts_wakealarm_cancel(fwts_framework *fw);
>
> #endif
> diff --git a/src/lib/src/fwts_wakealarm.c b/src/lib/src/fwts_wakealarm.c
> index f22ce4c..a2573b3 100644
> --- a/src/lib/src/fwts_wakealarm.c
> +++ b/src/lib/src/fwts_wakealarm.c
> @@ -18,38 +18,42 @@
> */
> #include <stdlib.h>
> #include <stdio.h>
> +#include <stdint.h>
> +#include <errno.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> +#include <sys/ioctl.h>
> #include <unistd.h>
> #include <string.h>
> +#include <fcntl.h>
> +#include <linux/rtc.h>
>
> #include "fwts.h"
>
> -static char *fwts_wkalarm = "/sys/class/rtc/rtc0/wakealarm";
> +static char *fwts_rtc = "/dev/rtc0";
>
> /*
> - * fwts_wakealarm_get_irq_state()
> - * get wakealarm IRQ state. checks if alarm_IRQ exists and if
> - * it is set.
> + * fwts_wakealarm_exits()
> + * check that a RTC exists that supports minimal RTC alarm ioctl
> */
> -int fwts_wakealarm_get_irq_state(void)
> +int fwts_wakealarm_exits(fwts_framework *fw)
> {
> - FILE *fp;
> - char field[32];
> - char value[32];
> + int fd;
> + int ret = FWTS_OK;
> + struct rtc_time rtc_tm;
>
> - if ((fp = fopen("/proc/driver/rtc", "r")) == NULL)
> + if ((fd = open(fwts_rtc, O_RDWR)) < 0) {
> + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc);
> return FWTS_ERROR;
> + }
>
> - while (fscanf(fp, "%s : %s\n", field, value) != EOF) {
> - if (!strcmp(field, "alarm_IRQ")) {
> - fclose(fp);
> - return strcmp(value, "no");
> - }
> + if (ioctl(fd, RTC_ALM_READ, &rtc_tm) < 0) {
> + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc);
> + ret = FWTS_ERROR;
> }
> - fclose(fp);
> + (void)close(fd);
>
> - return FWTS_ERROR;
> + return ret;
> }
>
> /*
> @@ -58,29 +62,110 @@ int fwts_wakealarm_get_irq_state(void)
> */
> int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds)
> {
> - char buffer[32];
> - int ret;
> -
> - snprintf(buffer, sizeof(buffer), "+%d", seconds);
> + int fd, ret = FWTS_OK;
> + struct rtc_time rtc_tm;
>
> - if (fwts_set("0", fwts_wkalarm)) {
> - fwts_log_error(fw, "Cannot write '0' to %s", fwts_wkalarm);
> + if ((fd = open(fwts_rtc, O_RDWR)) < 0) {
> + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc);
> return FWTS_ERROR;
> }
> - if (fwts_set(buffer, fwts_wkalarm)) {
> - fwts_log_error(fw, "Cannot write '%s' to %s", buffer, fwts_wkalarm);
> - return FWTS_ERROR;
> +
> + if (ioctl(fd, RTC_RD_TIME, &rtc_tm) < 0) {
> + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc);
> + ret = FWTS_ERROR;
> + goto out;
> }
> - if ((ret = fwts_wakealarm_get_irq_state()) == FWTS_ERROR)
> +
> + rtc_tm.tm_sec += seconds;
> + if (rtc_tm.tm_sec >= 60) {
> + rtc_tm.tm_min += rtc_tm.tm_sec / 60;
> + rtc_tm.tm_sec %= 60;
> + }
> + if (rtc_tm.tm_min >= 60) {
> + rtc_tm.tm_hour += rtc_tm.tm_min / 60;
> + rtc_tm.tm_min %= 60;
> + }
> + if (rtc_tm.tm_hour >= 24) {
> + rtc_tm.tm_hour %= 24;
> + }
> + errno = 0;
> + if (ioctl(fd, RTC_ALM_SET, &rtc_tm) < 0) {
> + if (errno == ENOTTY) {
> + fwts_log_error(fw, "Real Time Clock device %s does not support alarm interrupts.", fwts_rtc);
> + ret = FWTS_ERROR;
> + goto out;
> + }
> + }
> + if (ioctl(fd, RTC_AIE_ON, 0) < 0) {
> + fwts_log_error(fw, "Cannot enable alarm interrupts on Real Time Clock device %s.", fwts_rtc);
> + ret = FWTS_ERROR;
> + }
> +out:
> + (void)close(fd);
> +
> + return ret;
> +}
> +
> +int fwts_wakealarm_cancel(fwts_framework *fw)
> +{
> + int fd, ret = FWTS_OK;
> +
> + if ((fd = open(fwts_rtc, O_RDWR)) < 0) {
> + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc);
> return FWTS_ERROR;
> + }
> +
> + if (ioctl(fd, RTC_AIE_OFF, 0) < 0) {
> + fwts_log_error(fw, "Cannot read Real Time Clock with ioctl RTC_RD_TIME %s.", fwts_rtc);
> + ret = FWTS_ERROR;
> + }
> + (void)close(fd);
> +
> + return ret;
> +}
> +
> +/*
> + * fwts_wakealarm_check_fired()
> + * check if wakealarm fires
> + */
> +int fwts_wakealarm_check_fired(fwts_framework *fw, const int seconds)
> +{
> + int fd, rc, ret = FWTS_OK;
> + fd_set rfds;
> + struct timeval tv;
>
> - if (!fwts_wakealarm_get_irq_state()) {
> - fwts_log_error(fw, "Wakealarm %s did not get set", fwts_wkalarm);
> + if ((fd = open(fwts_rtc, O_RDWR)) < 0) {
> + fwts_log_error(fw, "Cannot access Real Time Clock device %s.", fwts_rtc);
> return FWTS_ERROR;
> }
> - return FWTS_OK;
> +
> + FD_ZERO(&rfds);
> + FD_SET(fd, &rfds);
> +
> + /* Wait for 1 second longer than the alarm */
> + tv.tv_sec = seconds + 1;
> + tv.tv_usec = 0;
> +
> + /* Wait for data to be available or timeout */
> + rc = select(fd + 1, &rfds, NULL, NULL, &tv);
> + if (rc == -1) {
> + fwts_log_error(fw, "Select failed waitin for Real Time Clock device %s to fire.\n", fwts_rtc);
> + ret = FWTS_ERROR;
> + goto out;
> + }
> +
> + /* Timed out, no data available, so alarm did not fire */
> + if (rc == 0) {
> + fwts_log_error(fw, "Wakealarm Real Time Clock device %s did not fire", fwts_rtc);
> + ret = FWTS_ERROR;
> + }
> +out:
> + (void)close(fd);
> +
> + return ret;
> }
>
> +
> /*
> * fwts_wakealarm_test_firing()
> * test RTC wakealarm trigger and firing from 'seconds' seconds time
> @@ -88,15 +173,15 @@ int fwts_wakealarm_trigger(fwts_framework *fw, const int seconds)
> */
> int fwts_wakealarm_test_firing(fwts_framework *fw, const int seconds)
> {
> - int ret;
> + int ret = FWTS_OK;
>
> - if ((ret = fwts_wakealarm_trigger(fw, seconds)) != FWTS_OK)
> + if (fwts_wakealarm_trigger(fw, seconds + 2) != FWTS_OK)
> return FWTS_ERROR;
>
> - sleep(seconds+1);
> - if (fwts_wakealarm_get_irq_state() != FWTS_OK) {
> - fwts_log_error(fw, "Wakealarm %s did not fire", fwts_wkalarm);
> - return FWTS_ERROR;
> - }
> - return FWTS_OK;
> + if (fwts_wakealarm_check_fired(fw, seconds + 2) != FWTS_OK)
> + ret = FWTS_ERROR;
> +
> + fwts_wakealarm_cancel(fw);
> +
> + return ret;
> }
>
Acked-by: Alex Hung <alex.hung at canonical.com>
More information about the fwts-devel
mailing list