--- zzzz-none-000/linux-3.10.107/drivers/rtc/rtc-sysfs.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/rtc/rtc-sysfs.c 2021-02-04 17:41:59.000000000 +0000 @@ -25,15 +25,14 @@ */ static ssize_t -rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, - char *buf) +name_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", to_rtc_device(dev)->name); } +static DEVICE_ATTR_RO(name); static ssize_t -rtc_sysfs_show_date(struct device *dev, struct device_attribute *attr, - char *buf) +date_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; @@ -46,10 +45,10 @@ return retval; } +static DEVICE_ATTR_RO(date); static ssize_t -rtc_sysfs_show_time(struct device *dev, struct device_attribute *attr, - char *buf) +time_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; @@ -62,10 +61,10 @@ return retval; } +static DEVICE_ATTR_RO(time); static ssize_t -rtc_sysfs_show_since_epoch(struct device *dev, struct device_attribute *attr, - char *buf) +since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; struct rtc_time tm; @@ -79,16 +78,16 @@ return retval; } +static DEVICE_ATTR_RO(since_epoch); static ssize_t -rtc_sysfs_show_max_user_freq(struct device *dev, struct device_attribute *attr, - char *buf) +max_user_freq_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%d\n", to_rtc_device(dev)->max_user_freq); } static ssize_t -rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, +max_user_freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { struct rtc_device *rtc = to_rtc_device(dev); @@ -101,6 +100,7 @@ return n; } +static DEVICE_ATTR_RW(max_user_freq); /** * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time @@ -109,8 +109,7 @@ * boot or resume event. */ static ssize_t -rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, - char *buf) +hctosys_show(struct device *dev, struct device_attribute *attr, char *buf) { #ifdef CONFIG_RTC_HCTOSYS_DEVICE if (rtc_hctosys_ret == 0 && @@ -121,21 +120,10 @@ #endif return sprintf(buf, "0\n"); } - -static struct device_attribute rtc_attrs[] = { - __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), - __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), - __ATTR(time, S_IRUGO, rtc_sysfs_show_time, NULL), - __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), - __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, - rtc_sysfs_set_max_user_freq), - __ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL), - { }, -}; +static DEVICE_ATTR_RO(hctosys); static ssize_t -rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, - char *buf) +wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t retval; unsigned long alarm; @@ -159,11 +147,12 @@ } static ssize_t -rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr, +wakealarm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { ssize_t retval; unsigned long now, alarm; + unsigned long push = 0; struct rtc_wkalrm alm; struct rtc_device *rtc = to_rtc_device(dev); char *buf_ptr; @@ -180,13 +169,17 @@ buf_ptr = (char *)buf; if (*buf_ptr == '+') { buf_ptr++; - adjust = 1; + if (*buf_ptr == '=') { + buf_ptr++; + push = 1; + } else + adjust = 1; } alarm = simple_strtoul(buf_ptr, NULL, 0); if (adjust) { alarm += now; } - if (alarm > now) { + if (alarm > now || push) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. @@ -194,9 +187,14 @@ retval = rtc_read_alarm(rtc, &alm); if (retval < 0) return retval; - if (alm.enabled) - return -EBUSY; - + if (alm.enabled) { + if (push) { + rtc_tm_to_time(&alm.time, &push); + alarm += push; + } else + return -EBUSY; + } else if (push) + return -EINVAL; alm.enabled = 1; } else { alm.enabled = 0; @@ -211,45 +209,57 @@ retval = rtc_set_alarm(rtc, &alm); return (retval < 0) ? retval : n; } -static DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR, - rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm); +static DEVICE_ATTR_RW(wakealarm); +static struct attribute *rtc_attrs[] = { + &dev_attr_name.attr, + &dev_attr_date.attr, + &dev_attr_time.attr, + &dev_attr_since_epoch.attr, + &dev_attr_max_user_freq.attr, + &dev_attr_hctosys.attr, + &dev_attr_wakealarm.attr, + NULL, +}; /* 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 rtc_device *rtc) +static bool rtc_does_wakealarm(struct rtc_device *rtc) { if (!device_can_wakeup(rtc->dev.parent)) - return 0; + return false; + return rtc->ops->set_alarm != NULL; } - -void rtc_sysfs_add_device(struct rtc_device *rtc) +static umode_t rtc_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int n) { - int err; + struct device *dev = container_of(kobj, struct device, kobj); + struct rtc_device *rtc = to_rtc_device(dev); + umode_t mode = attr->mode; - /* not all RTCs support both alarms and wakeup */ - if (!rtc_does_wakealarm(rtc)) - return; + if (attr == &dev_attr_wakealarm.attr) + if (!rtc_does_wakealarm(rtc)) + mode = 0; - err = device_create_file(&rtc->dev, &dev_attr_wakealarm); - if (err) - dev_err(rtc->dev.parent, - "failed to create alarm attribute, %d\n", err); + return mode; } -void rtc_sysfs_del_device(struct rtc_device *rtc) -{ - /* REVISIT did we add it successfully? */ - if (rtc_does_wakealarm(rtc)) - device_remove_file(&rtc->dev, &dev_attr_wakealarm); -} +static struct attribute_group rtc_attr_group = { + .is_visible = rtc_attr_is_visible, + .attrs = rtc_attrs, +}; + +static const struct attribute_group *rtc_attr_groups[] = { + &rtc_attr_group, + NULL +}; -void __init rtc_sysfs_init(struct class *rtc_class) +const struct attribute_group **rtc_get_dev_attribute_groups(void) { - rtc_class->dev_attrs = rtc_attrs; + return rtc_attr_groups; }