: ACPI: duplicate ACPI sleep "alarm" attribute in sysfs
Subsystems (2)
PATCH 3/6 : ACPI: duplicate ACPI sleep "alarm" attribute in sysfs
From: Zhang Rui <[email protected]>
Create /sys/power/alarm.
The way it works is exactly the same as /proc/acpi/alarm.
I.e. "#echo yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports existing absolute time. And "#echo +yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports a duration.
NOTE: It's not very clean to refer struct subsystem power_subsys in ACPI. But I think /sys/power is the most reasonable place to locate this "alarm" attribute. So anybody who get better ideas, please let me know.
--- drivers/acpi/sleep/proc.c | 313 ++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 287 insertions(+), 26 deletions(-)
drivers/acpi/sleep/proc.c +287 -26
@@ -15,6 +15,290 @@#define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("sleep") + +static int get_date_field (char **p,u32 * value) +{ +char *next =NULL ; +char *string_end =NULL ; +int result = -EINVAL ; + +/* +* Try to find delimeter, only to insert null. The end of the +* string won't have one, but is still valid. +*/ + next =strpbrk (*p,"- :" ); +if (next) + *next++ ='\0' ; + + *value =simple_strtoul (*p, &string_end,10 ); + +/* Signal success if we got a good digit */ +if (string_end != *p) + result =0 ; + +if (next) + *p = next; + +return result; +} + +/* -------------------------------------------------------------------------- +FS Interface (/sys) +-------------------------------------------------------------------------- */ + +static ssize_t alarm_show (struct subsystem *subsys,char *buf){ +u32 sec, min, hr; +u32 day, mo, yr; +unsigned char rtc_control =0 ; +unsigned long flags; +ssize_t result =0 ; + +spin_lock_irqsave (&rtc_lock, flags); + + sec =CMOS_READ (RTC_SECONDS_ALARM ); + min =CMOS_READ (RTC_MINUTES_ALARM ); + hr =CMOS_READ (RTC_HOURS_ALARM ); + rtc_control =CMOS_READ (RTC_CONTROL ); + +/* If we ever get an FACP with proper values... */ +if (acpi_gbl_FADT->day_alrm) +/* ACPI spec: only low 6 its should be cared */ + day =CMOS_READ (acpi_gbl_FADT->day_alrm) &0x3F ; +else + day =CMOS_READ (RTC_DAY_OF_MONTH ); +if (acpi_gbl_FADT->mon_alrm) + mo =CMOS_READ (acpi_gbl_FADT->mon_alrm); +else + mo =CMOS_READ (RTC_MONTH ); +if (acpi_gbl_FADT->century) + yr =CMOS_READ (acpi_gbl_FADT->century) *100 + +CMOS_READ (RTC_YEAR ); +else + yr =CMOS_READ (RTC_YEAR ); + +spin_unlock_irqrestore (&rtc_lock, flags); + +if (!(rtc_control &RTC_DM_BINARY ) ||RTC_ALWAYS_BCD ) { +BCD_TO_BIN (sec); +BCD_TO_BIN (min); +BCD_TO_BIN (hr); +BCD_TO_BIN (day); +BCD_TO_BIN (mo); +BCD_TO_BIN (yr); + } + +/* we're trusting the FADT (see above) */ +if (!acpi_gbl_FADT->century) +/* If we're not trusting the FADT, we should at least make it +* right for _this_ century... ehm, what is _this_ century? +* +* TBD: +* ASAP: find piece of code in the kernel, e.g. star tracker driver, +* which we can trust to determine the century correctly. Atom +* watch driver would be nice, too... +* +* if that has not happened, change for first release in 2050: +* if (yr<50) +* yr += 2100; +* else +* yr += 2000; // current line of code +* +* if that has not happened either, please do on 2099/12/31:23:59:59 +* s/2000/2100 +* +*/ + yr +=2000 ; + + result =sprintf (buf+result,"%4.4u-" , yr); +if (mo >12 ) + result +=sprintf (buf+result,"**-" ); +else + result +=sprintf (buf+result,"%2.2u-" , mo); +if (day >31 ) + result +=sprintf (buf+result,"** " ); +else + result +=sprintf (buf+result,"%2.2u " , day); +if (hr >23 ) + result +=sprintf (buf+result,"**:" ); +else + result +=sprintf (buf+result,"%2.2u:" , hr); +if (min >59 ) + result +=sprintf (buf+result,"**:" ); +else + result +=sprintf (buf+result,"%2.2u:" , min); +if (sec >59 ) + result +=sprintf (buf+result,"**\n" ); +else + result +=sprintf (buf+result,"%2.2u\n" , sec); + +return result; +} + +static ssize_t alarm_store (struct subsystem *subsys,const char *buf,size_t count){ +int result =0 ; +char *p = (char *)buf; +u32 sec, min, hr, day, mo, yr; +int adjust =0 ; +unsigned char rtc_control =0 ; + +if (buf[0 ] =='+' ) { + p++; + adjust =1 ; + } + +if ((result =get_date_field (&p, &yr))) + goto end; +if ((result =get_date_field (&p, &mo))) + goto end; +if ((result =get_date_field (&p, &day))) + goto end; +if ((result =get_date_field (&p, &hr))) + goto end; +if ((result =get_date_field (&p, &min))) + goto end; +if ((result =get_date_field (&p, &sec))) + goto end; + +if (sec >59 ) { + min +=1 ; + sec -=60 ; + } +if (min >59 ) { + hr +=1 ; + min -=60 ; + } +if (hr >23 ) { + day +=1 ; + hr -=24 ; + } +if (day >31 ) { + mo +=1 ; + day -=31 ; + } +if (mo >12 ) { + yr +=1 ; + mo -=12 ; + } +spin_lock_irq (&rtc_lock); + + rtc_control =CMOS_READ (RTC_CONTROL ); +if (!(rtc_control &RTC_DM_BINARY ) ||RTC_ALWAYS_BCD ) { +BIN_TO_BCD (yr); +BIN_TO_BCD (mo); +BIN_TO_BCD (day); +BIN_TO_BCD (hr); +BIN_TO_BCD (min); +BIN_TO_BCD (sec); + } + +if (adjust) { + yr +=CMOS_READ (RTC_YEAR ); + mo +=CMOS_READ (RTC_MONTH ); + day +=CMOS_READ (RTC_DAY_OF_MONTH ); + hr +=CMOS_READ (RTC_HOURS ); + min +=CMOS_READ (RTC_MINUTES ); + sec +=CMOS_READ (RTC_SECONDS ); + } + +spin_unlock_irq (&rtc_lock); + +if (!(rtc_control &RTC_DM_BINARY ) ||RTC_ALWAYS_BCD ) { +BCD_TO_BIN (yr); +BCD_TO_BIN (mo); +BCD_TO_BIN (day); +BCD_TO_BIN (hr); +BCD_TO_BIN (min); +BCD_TO_BIN (sec); + } + +if (sec >59 ) { + min++; + sec -=60 ; + } +if (min >59 ) { + hr++; + min -=60 ; + } +if (hr >23 ) { + day++; + hr -=24 ; + } +if (day >31 ) { + mo++; + day -=31 ; + } +if (mo >12 ) { + yr++; + mo -=12 ; + } +if (!(rtc_control &RTC_DM_BINARY ) ||RTC_ALWAYS_BCD ) { +BIN_TO_BCD (yr); +BIN_TO_BCD (mo); +BIN_TO_BCD (day); +BIN_TO_BCD (hr); +BIN_TO_BCD (min); +BIN_TO_BCD (sec); + } + +spin_lock_irq (&rtc_lock); +/* +* Disable alarm interrupt before setting alarm timer or else +* when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs +*/ + rtc_control &= ~RTC_AIE ; +CMOS_WRITE (rtc_control,RTC_CONTROL ); +CMOS_READ (RTC_INTR_FLAGS ); + +/* write the fields the rtc knows about */ +CMOS_WRITE (hr,RTC_HOURS_ALARM ); +CMOS_WRITE (min,RTC_MINUTES_ALARM ); +CMOS_WRITE (sec,RTC_SECONDS_ALARM ); + +/* +* If the system supports an enhanced alarm it will have non-zero +* offsets into the CMOS RAM here -- which for some reason are pointing +* to the RTC area of memory. +*/ +if (acpi_gbl_FADT->day_alrm) +CMOS_WRITE (day, acpi_gbl_FADT->day_alrm); +if (acpi_gbl_FADT->mon_alrm) +CMOS_WRITE (mo, acpi_gbl_FADT->mon_alrm); +if (acpi_gbl_FADT->century) +CMOS_WRITE (yr /100 , acpi_gbl_FADT->century); +/* enable the rtc alarm interrupt */ + rtc_control |=RTC_AIE ; +CMOS_WRITE (rtc_control,RTC_CONTROL ); +CMOS_READ (RTC_INTR_FLAGS ); + +spin_unlock_irq (&rtc_lock); + +acpi_clear_event (ACPI_EVENT_RTC ); +acpi_enable_event (ACPI_EVENT_RTC ,0 ); + + result = count; + + end: +return result; +} + +static struct subsys_attribute alarm_attr = { + .attr = { + .name =__stringify (alarm), + .mode =0644 , + }, + .show = alarm_show, + .store = alarm_store, +}; + +extern struct subsystem power_subsys; +static int alarm_add_sysfs (void ) +{ +return sysfs_create_file (&power_subsys.kset.kobj, &alarm_attr.attr); +} + +/* -------------------------------------------------------------------------- +FS Interface (/proc) +-------------------------------------------------------------------------- */ #ifdef CONFIG_ACPI_SLEEP_PROC_SLEEP static int acpi_system_sleep_seq_show (struct seq_file *seq,void *offset) {
@@ -150,32 +434,6 @@ static int acpi_system_alarm_open_fs(strreturn single_open (file, acpi_system_alarm_seq_show,PDE (inode)->data); } -static int get_date_field (char **p,u32 * value) -{ -char *next =NULL ; -char *string_end =NULL ; -int result = -EINVAL ; - -/* -* Try to find delimeter, only to insert null. The end of the -* string won't have one, but is still valid. -*/ - next =strpbrk (*p,"- :" ); -if (next) - *next++ ='\0' ; - - *value =simple_strtoul (*p, &string_end,10 ); - -/* Signal success if we got a good digit */ -if (string_end != *p) - result =0 ; - -if (next) - *p = next; - -return result; -} -static ssize_t acpi_system_write_alarm (struct file *file,const char __user * buffer,size_t count,loff_t * ppos)
@@ -498,6 +756,9 @@ static int acpi_sleep_proc_init(void)if (entry) entry->proc_fops = &acpi_system_wakeup_device_fops; +if (alarm_add_sysfs ()) +return -EINVAL ; +acpi_install_fixed_event_handler (ACPI_EVENT_RTC , rtc_handler,NULL );return 0 ; }
Quoted 2 lines · Zhang Rui
Create
/sys/power/alarm.
Urg. This doesn't work with the RTC framework, which accepts the reality that some systems have multiple RTCs ... /sys/class/rtc/rtcN/alarm is a much more appropriate location for that RTC's alarm.
(How to handle RTCs with multiple alarms is a different issue; I'm just assuming for now that one of them wil be designated primary.)
Quoted 3 lines
The way it works is exactly the same as
/proc/acpi/alarm.
I.e. "#echo yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports existing absolute time. And "#echo +yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports a duration.
There was a proposal a while back to have /sys/class/rtc/rtcN/alarm files -- for alarm-capable RTCs, they don't all have alarms -- have only the absolute seconds. "date" can do the math for you; e.g.
# cd /sys/class/rtc/rtcN # date -d '5pm tuesday' "+%s" > alarm # date -d '5 hours 24 minutes 11 seconds' "+%s" > alarm # date -d '4pm 8 january 2007' "+%s" > alarm
It's usually felt to be a Good Thing if the kernel doesn't have to be in the business of parsing and validating complex input ...
(And "cat" of the alarm attribute would return either seconds since the POSIX epoch, if the alarm's active, else the null string.)
- Dave
Quoted 7 lines · David Brownell
Quoted 2 lines · Zhang Rui
Create
/sys/power/alarm.Urg. This doesn't work with the RTC framework, which accepts the reality that some systems have multiple RTCs ...
/sys/class/rtc/rtcN/alarmis a much more appropriate location for that RTC's alarm.
Especially since /proc/acpi/alarm is just banging on the RTC registers
- the only ACPI thing about it is that the FADT can expose whether or not the extended registers exist, and then making sure that the GPE is enabled.
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 5 lines · Matthew Garrett
Quoted 4 lines · David Brownell
Quoted 2 lines · Zhang Rui
Create
/sys/power/alarm.
Quoted 8 lines
Quoted 3 lines
Urg. This doesn't work with the RTC framework, which accepts the reality that some systems have multiple RTCs ...
/sys/class/rtc/rtcN/alarmis a much more appropriate location for that RTC's alarm.Especially since
/proc/acpi/alarmis just banging on the RTC registers
- the only ACPI thing about it is that the FADT can expose whether or not the extended registers exist, and then making sure that the GPE is enabled.
The FADT also exposes whether the RTC can wake from S4. You may have noticed that my rtc-cmos patch #3 exported the relevant FADT info to the RTC device using platform_data, but the S4 wake capability flag isn't useful for anything on today's Linux.
Not speaking as an ACPI expert, I do see the ACPI spec says (right under fig 4-11 in my version) that RTC events don't require GPEs.
Conceptually, one would expect that enable_irq_wake(RTC_IRQ) would set PM1.RTC_EN, and disable_irq_wake(RTC_IRQ) would clear it, on ACPI systems. It doesn't do that, though.
But I did notice there was a lot of event infrastructure behind the /proc/acpi/alarm thing ... which I never observed to fire. Maybe it would be needed on systems with different RTC implementations...
- Dave
Quoted 10 lines · David Brownell
Quoted 4 lines · Matthew Garrett
Especially since
/proc/acpi/alarmis just banging on the RTC registers
- the only ACPI thing about it is that the FADT can expose whether or not the extended registers exist, and then making sure that the GPE is enabled.The FADT also exposes whether the RTC can wake from S4. You may have noticed that my rtc-cmos patch #3 exported the relevant FADT info to the RTC device using
platform_data, but the S4 wake capability flag isn't useful for anything on today's Linux.
Isn't useful in what way? It'd be helpful for userspace to know that now that we're actually using S4 for swsusp, but I understand that it might not fit into the current API terribly well.
Quoted 2 lines
Not speaking as an ACPI expert, I do see the ACPI spec says (right under fig 4-11 in my version) that RTC events don't require GPEs.
Hmm. My interpretation of that section had been that RTC_EN and RTC_STS were optional, and that a GPE would be required if they weren't implemented. On re-reading it, I think you're right.
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 8 lines
Quoted 4 lines
The FADT also exposes whether the RTC can wake from S4. You may have noticed that my rtc-cmos patch #3 exported the relevant FADT info to the RTC device using
platform_data, but the S4 wake capability flag isn't useful for anything on today's Linux.Isn't useful in what way? It'd be helpful for userspace to know that now that we're actually using S4 for swsusp, but I understand that it might not fit into the current API terribly well.
In that current API there's no way to tell anything at all about the target system state inside a driver's suspend() method. So if there were some characteristic of S4 (or S3 etc) that mattered to the driver (it should test for the attribute, not S4/etc since S4 is ACPI-specific) the driver couldn't do anything about it ... so as I said, not useful.
- Dave
Quoted 5 lines · David Brownell
In that current API there's no way to tell anything at all about the target system state inside a driver's
suspend()method. So if there were some characteristic of S4 (or S3 etc) that mattered to the driver (it should test for the attribute, not S4/etc since S4 is ACPI-specific) the driver couldn't do anything about it ... so as I said, not useful.
Well, it's not just a matter for the driver - in terms of userspace UI, we want to be able to expose which wakeup events will work in suspend to disk. If the API can't currently expose that, then we probably want to look into ways of fixing that.
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 10 lines · Matthew Garrett
Quoted 5 lines · David Brownell
In that current API there's no way to tell anything at all about the target system state inside a driver's
suspend()method. So if there were some characteristic of S4 (or S3 etc) that mattered to the driver (it should test for the attribute, not S4/etc since S4 is ACPI-specific) the driver couldn't do anything about it ... so as I said, not useful.Well, it's not just a matter for the driver - in terms of userspace UI, we
... may potentially ...
Quoted 3 lines
want to be able to expose which wakeup events will work in suspend to disk. If the API can't currently expose that, then we probably want to look into ways of fixing that.
Considering that I've never seen ACPI wakeup GPEs work at all, having them work in the first place -- e.g. from STR -- would need to be a first step. It seems premature to discuss the UI of a tool that can't yet be written on Linux...
Agreed, by the way, that drivers need to be able to tell things about the target system sleep state. My original examples come from USB: drivers need to know whether the target state requires disabling specific clocks, which must be active for remote wakeup to work.
- Dave
Thanks for your attention.
Quoted 10 lines · David Brownell
Quoted 9 lines · Matthew Garrett
Quoted 7 lines · David Brownell
Quoted 2 lines · Zhang Rui
Create
/sys/power/alarm.Urg. This doesn't work with the RTC framework, which accepts the reality that some systems have multiple RTCs ...
/sys/class/rtc/rtcN/alarmis a much more appropriate location for that RTC's alarm.
Errr, I never met this multiple RTCs situation before and it's true that /sys/power/alarm can not handle multiple RTCs.
I don't know why they are needed, maybe for the embedded system? Could you provide me more details about this multiple RTCs please? Thanks.
Quoted 5 lines
Quoted 4 lines
Especially since
/proc/acpi/alarmis just banging on the RTC registers
- the only ACPI thing about it is that the FADT can expose whether or not the extended registers exist, and then making sure that the GPE is enabled.
Quoted 7 lines
The FADT also exposes whether the RTC can wake from S4. You may have noticed that my rtc-cmos patch #3 exported the relevant FADT info to the RTC device using
platform_data, but the S4 wake capability flag isn't useful for anything on today's Linux.
Not speaking as an ACPI expert, I do see the ACPI spec says (right under fig 4-11 in my version) that RTC events don't require GPEs.
Enabling the GPE for RTC is needed. According to the ACPI spec 3.0, which is the latest version, "If the RTC wake event status and enable bits are implemented in fixed hardware, the platform are able to indicate an RTC wake source without consuming a GPE bit, as would be required if RTC wake was not implemented using the fixed hardware RTC feature". You can get it in 4.7.2.4.
Thanks,
Rui
Quoted 3 lines · Zhang Rui
Errr, I never met this multiple RTCs situation before and it's true that
/sys/power/alarmcan not handle multiple RTCs.
I don't know why they are needed, maybe for the embedded system?
Yes.
Quoted 1 line
Could you provide me more details about this multiple RTCs please?
An example would be one board I have, with one highly functional RTC integrated into a system-on-chip processor ... but without battery backup, since the SOC doesn't have a separate power domain for that.
Systems that want to use that SOC with an RTC may accordingly need a battery backed RTC, probably connected with I2C or SPI. On this board, that's a simple one that's used mostly when starting from a power-off state, to initialize system clock and then the SOC's RTC. The more functional integrated RTC (rtc0) is used for normal operation, but the battery backed one (rtc1) sets the system clock at boot.
Quoted 8 lines
Quoted 7 lines
The FADT also exposes whether the RTC can wake from S4. You may have noticed that my rtc-cmos patch #3 exported the relevant FADT info to the RTC device using
platform_data, but the S4 wake capability flag isn't useful for anything on today's Linux.Not speaking as an ACPI expert, I do see the ACPI spec says (right under fig 4-11 in my version) that RTC events don't require GPEs.
Quoted 6 lines
Enabling the GPE for RTC is needed. According to the ACPI spec 3.0, which is the latest version, "If the RTC wake event status and enable bits are implemented in fixed hardware, the platform are able to indicate an RTC wake source without consuming a GPE bit, as would be required if RTC wake was not implemented using the fixed hardware RTC feature". You can get it in 4.7.2.4.
That doesn't disagree with what I said. "Not consuming a GPE bit" is clearly not requiring a GPE (bit).
I suspect what you mean to say is that the OS needs some hook into ACPI so it behaves in both cases. I'm not disagreeing with that. It would be nice if that were {enable,disable}_irq_wake(RTC_IRQ), which is what bare metal (non-ACPI) systems would normally use.
- Dave
Hi!
Quoted 4 lines
Create
/sys/power/alarm.
The way it works is exactly the same as/proc/acpi/alarm.
I.e. "#echo yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports existing absolute time. And "#echo +yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports a duration.
NAK. /proc/acpi/alarm is a mess, and this just moves it to /sysfs. 'One value per file', please.
Pavel
Signature · 1 line
Thanks for all the (sleeping) penguins.
Quoted 8 lines · Pavel Machek
Quoted 5 lines
Create
/sys/power/alarm.
The way it works is exactly the same as/proc/acpi/alarm.
I.e. "#echo yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports existing absolute time. And "#echo +yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports a duration.NAK.
/proc/acpi/alarmis a mess, and this just moves it to /sysfs. 'One value per file', please.
Sort of like the appended patch, instead ... which doesn't need to know a thing about ACPI. This is what I suggested in response to an earlier patch from Paul Sokolovsky.
- Dave
================ CUT HERE
This adds a new "wakealarm" sysfs attribute to RTC class devices which support alarm operations and are wakeup-capable:
- It reads as either empty, or the scheduled alarm time as seconds since the POSIX epoch. (That time may already have passed, since nothing currently enforces one-shot alarm semantics...)
- It can be written with an alarm time in the future, again seconds since the POSIX epoch, which enables the alarm.
- It can be written with an alarm time not in the future (such as 0, the start of the POSIX epoch) to disable the alarm.
Usage examples, after "cd /sys/class/rtc/rtcN":
alarm after 45 minutes:
# echo $(( $(cat since_epoch) + 45 * 60 )) > wakealarm
alarm next tuesday evening (using GNU date):
# date -d '10pm tuesday' "+%s" > wakealarm
disable alarm:
# echo 0 > wakealarm
This resembles the /proc/acpi/alarm file in that nothing happens when the alarm triggers ... except possibly waking the system from sleep. It's also like that in a nasty way: not much can be done to prevent one task from clobbering another task's alarm settings.
It differs from that file in that there's no in-kernel date parser.
Note that a few RTCs ignore rtc_wkalrm.enabled when setting alarms, or aren't set up correctly, so they won't yet behave with this attribute.
drivers/rtc/rtc-sysfs.c +101 -2
@@ -78,6 +78,92 @@ static struct attribute_group rtc_attr_g .attrs = rtc_attrs, }; + +static ssize_t +rtc_sysfs_show_wakealarm (struct class_device *dev,char *buf) +{ +ssize_t retval; +unsigned long alarm; +struct rtc_wkalrm alm; + +/* Don't show disabled alarms; but the RTC could leave the +* alarm enabled after it's already triggered. Alarms are +* conceptually one-shot, even though some common hardware +* (PCs) doesn't actually work that way. +* +* REVISIT maybe we should require RTC implementations to +* disable the RTC alarm after it triggers, for uniformity. +*/ + retval =rtc_read_alarm (dev, &alm); +if (retval ==0 && alm.enabled) { +rtc_tm_to_time (&alm.time, &alarm); + retval =sprintf (buf,"%lu\n" , alarm); + } + +return retval; +} + +static ssize_t +rtc_sysfs_set_wakealarm (struct class_device *dev,const char *buf,size_t n) +{ +ssize_t retval; +unsigned long now, alarm; +struct rtc_wkalrm alm; + +/* Only request alarms that trigger in the future. Disable them +* by writing another time, e.g. 0 meaning Jan 1 1970 UTC. +*/ + retval =rtc_read_time (dev, &alm.time); +if (retval <0 ) +return retval; +rtc_tm_to_time (&alm.time, &now); + + alarm =simple_strtoul (buf,NULL ,0 ); +if (alarm > now) { +/* Avoid accidentally clobbering active alarms; we can't +* entirely prevent that here, without even the minimal +* locking from the /dev/rtcN api. +*/ + retval =rtc_read_alarm (dev, &alm); +if (retval <0 ) +return retval; +if (alm.enabled) +return -EBUSY ; + + alm.enabled =1 ; + }else { + alm.enabled =0 ; + +/* Provide a valid future alarm time. Linux isn't EFI, +* this time won't be ignored when disabling the alarm. +*/ + alarm = now +300 ; + } +rtc_time_to_tm (alarm, &alm.time); + + retval =rtc_set_alarm (dev, &alm); +return (retval <0 ) ? retval : n; +} +static const CLASS_DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, + rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm); + + +/* The reason to trigger an alarm with no process watching it (via sysfs) +* is its side effect: waking from a system state like suspend-to-RAM or +* suspend-to-disk. So: no attribute unless that side effect is possible. +* (Userspace may disable that mechanism later.) +*/ +static inline int rtc_does_wakealarm (struct class_device *class_dev) +{ +struct rtc_device *rtc; + +if (!device_can_wakeup (class_dev->dev)) +return 0 ; + rtc =to_rtc_device (class_dev); +return rtc->ops->set_alarm !=NULL ; +} + +static int __devinit rtc_sysfs_add_device (struct class_device *class_dev,struct class_interface *class_intf) {
@@ -87,8 +173,18 @@ static int __devinit rtc_sysfs_add_devic err =sysfs_create_group (&class_dev->kobj, &rtc_attr_group);if (err) -dev_err (class_dev->dev, -"failed to create sysfs attributes\n" ); +dev_err (class_dev->dev,"failed to create %s\n" , +"sysfs attributes" ); +else if (rtc_does_wakealarm (class_dev)) { +/* not all RTCs support both alarms and wakeup */ + err =class_device_create_file (class_dev, + &class_device_attr_wakealarm); +if (err) { +dev_err (class_dev->dev,"failed to create %s\n" , +"alarm attribute" ); +sysfs_remove_group (&class_dev->kobj, &rtc_attr_group); + } + }return err; }
@@ -96,6 +192,9 @@ static int __devinit rtc_sysfs_add_devicstatic void rtc_sysfs_remove_device (struct class_device *class_dev,struct class_interface *class_intf) { +if (rtc_does_wakealarm (class_dev)) +class_device_remove_file (class_dev, + &class_device_attr_wakealarm);sysfs_remove_group (&class_dev->kobj, &rtc_attr_group); }
Hi!
Quoted 11 lines
Quoted 7 lines
Quoted 4 lines
Create
/sys/power/alarm.
The way it works is exactly the same as/proc/acpi/alarm.
I.e. "#echo yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports existing absolute time. And "#echo +yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports a duration.NAK.
/proc/acpi/alarmis a mess, and this just moves it to /sysfs. 'One value per file', please.Sort of like the appended patch, instead ... which doesn't need to know a thing about ACPI. This is what I suggested in response to an earlier patch from Paul Sokolovsky.
Yes, I suspected your patches would be solving this one.
Quoted 5 lines
- It can be written with an alarm time in the future, again seconds since the POSIX epoch, which enables the alarm.
- It can be written with an alarm time not in the future (such as 0, the start of the POSIX epoch) to disable the alarm.
...and it is certainly way better than original (parsing) solution. ACK.
(What about periodic alarms? I guess we want to simply forget about them? Doc*/ file would be nice, but you probably have that in separate patch.)
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Quoted 2 lines · Pavel Machek
What about periodic alarms?
So far as I'm concerned they're not part of the API. The periodicity notion of the alarm on PC RTCs is pretty bizarre if you look at it ... not portable to much non-PC hardware (without extremely ugly hacks nobody's likely to do), and so not appropriate to include in a cross-platform API framework.
The user model of a one-shot alarm is simple and easy to understand; plus it's a direct match for the alarms people use all the time in the kitchen and to wake up in the morning.
- Dave
Len Brown
reviewerQuoted 45 lines · David Brownell
Quoted 8 lines · Pavel Machek
Quoted 5 lines
Create
/sys/power/alarm.
The way it works is exactly the same as/proc/acpi/alarm.
I.e. "#echo yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports existing absolute time. And "#echo +yyyy-mm-dd hh-mm-ss >/sys/power/alarm" supports a duration.NAK.
/proc/acpi/alarmis a mess, and this just moves it to /sysfs. 'One value per file', please.Sort of like the appended patch, instead ... which doesn't need to know a thing about ACPI. This is what I suggested in response to an earlier patch from Paul Sokolovsky.
- Dave
================ CUT HERE
This adds a new "wakealarm" sysfs attribute to RTC class devices which support alarm operations and are wakeup-capable:- It reads as either empty, or the scheduled alarm time as seconds since the POSIX epoch. (That time may already have passed, since nothing currently enforces one-shot alarm semantics...)
- It can be written with an alarm time in the future, again seconds since the POSIX epoch, which enables the alarm.
- It can be written with an alarm time not in the future (such as 0, the start of the POSIX epoch) to disable the alarm.
Usage examples, after "cd
/sys/class/rtc/rtcN":alarm after 45 minutes:
# echo $(( $(catsince_epoch) + 45 * 60 )) > wakealarm
alarm next tuesday evening (using GNU date):
# date -d '10pm tuesday' "+%s" > wakealarm
disable alarm:
# echo 0 > wakealarmThis resembles the
/proc/acpi/alarmfile in that nothing happens when the alarm triggers ... except possibly waking the system from sleep. It's also like that in a nasty way: not much can be done to prevent one task from clobbering another task's alarm settings.
Quoted 6 lines
It differs from that file in that there's no in-kernel date parser.
Note that a few RTCs ignore rtc_wkalrm.enabled when setting alarms, or aren't set up correctly, so they won't yet behave with this attribute.
Signed-off-by David Brownell <[email protected]>
How do I ask to wake up "as soon as possible"?
This is what a box that is testing suspend-resume would want to do.
thanks,
-Len
Quoted 10 lines
Quoted 10 lines
This adds a new "wakealarm" sysfs attribute to RTC class devices which support alarm operations and are wakeup-capable:
- It reads as either empty, or the scheduled alarm time as seconds since the POSIX epoch. (That time may already have passed, since nothing currently enforces one-shot alarm semantics...)
- It can be written with an alarm time in the future, again seconds since the POSIX epoch, which enables the alarm.
Quoted 6 lines
Quoted 4 lines
- It can be written with an alarm time not in the future (such as 0, the start of the POSIX epoch) to disable the alarm.
...
How do I ask to wake up "as soon as possible"?
That doesn't exactly correspond to a hardware mechanism. The hardware supports only "wake up at <this> specific time".
Quoted 1 line
This is what a box that is testing suspend-resume would want to do.
What I've done in that case is notice how long the suspend cycle takes, add a bit of fuzz (I use 10 seconds), and specify that for the relative "when to wake" time.
Of course, "how long suspend takes" is variable. If you disable IDE DMA (maybe the native driver doesn't suspend right yet?), suspend-to-disk seems to take forever on a PC.
And even without suspend-to-disk, it often doesn't seem to be as quick as you'd think it should be. Traversing the list of devices, and then suspending them, seems to take surprisingly long even on slim systems without ACPI in the way.
On the plus side, at least most systems seem to be able to handle RTCs as wakeup devices, so at least you _can_ automate that testing!
- Dave
Hi!
Quoted 6 lines
Quoted 4 lines
Note that a few RTCs ignore rtc_wkalrm.enabled when setting alarms, or aren't set up correctly, so they won't yet behave with this attribute.
Signed-off-by David Brownell <[email protected]>How do I ask to wake up "as soon as possible"?
If you want to wake up ASAP, don't go to sleep :-).
I see it might be handy for debugging... but I guess we should not mess rtc design because of that. Just set alarm 10 seconds into future.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Len Brown
reviewerQuoted 7 lines · Pavel Machek
Hi!
Quoted 5 lines
Quoted 4 lines
Note that a few RTCs ignore rtc_wkalrm.enabled when setting alarms, or aren't set up correctly, so they won't yet behave with this attribute.
Signed-off-by David Brownell <[email protected]>
Quoted 7 lines
Quoted 1 line
How do I ask to wake up "as soon as possible"?
If you want to wake up ASAP, don't go to sleep :-).
I see it might be handy for debugging... but I guess we should not mess rtc design because of that. Just set alarm 10 seconds into future.
That's my point.
What is the syntax to request "10-seconds into the future"?
Hi.
Quoted 10 lines · Len Brown
Quoted 9 lines · Pavel Machek
Hi!
Quoted 6 lines
Quoted 4 lines
Note that a few RTCs ignore rtc_wkalrm.enabled when setting alarms, or aren't set up correctly, so they won't yet behave with this attribute.
Signed-off-by David Brownell <[email protected]>How do I ask to wake up "as soon as possible"?
Quoted 8 lines
Quoted 5 lines
If you want to wake up ASAP, don't go to sleep :-).
I see it might be handy for debugging... but I guess we should not mess rtc design because of that. Just set alarm 10 seconds into future.
That's my point.
What is the syntax to request "10-seconds into the future"?
AFAIK (and I think this is what Pavel is saying) there isn't one - you'd have to use a shell script of some sort or such like to calculate now + 10s and echo the result to the entry.
Regards,
Nigel
Quoted 2 lines · Len Brown
That's my point.
What is the syntax to request "10-seconds into the future"?
See
http://lists.osdl.org/pipermail/linux-pm/2007-January/004459.html
and morph the first example ... it shows 45*60 seconds into the future. Substitute "45*60" ...
Quoted 10 lines · Len Brown
Quoted 9 lines · Pavel Machek
Hi!
Quoted 6 lines
Quoted 4 lines
Note that a few RTCs ignore rtc_wkalrm.enabled when setting alarms, or aren't set up correctly, so they won't yet behave with this attribute.
Signed-off-by David Brownell <[email protected]>How do I ask to wake up "as soon as possible"?
Quoted 8 lines
Quoted 5 lines
If you want to wake up ASAP, don't go to sleep :-).
I see it might be handy for debugging... but I guess we should not mess rtc design because of that. Just set alarm 10 seconds into future.
That's my point.
What is the syntax to request "10-seconds into the future"?
echo $(( $(cat since_epoch) + 10 )) > wakealarm
...which is what you should expect. Yep, for users, nice utility would be nice... but absence of nice utility does not mean that it belongs in kernel.
Plus, old alarm file was such a mess that I were not figure out how to use it within two hours... or maybe it just did not work on my machine? ... so utility will be needed, anyway.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html