hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/acpi/acpi_tad.c
....@@ -52,6 +52,201 @@
5252 u32 capabilities;
5353 };
5454
55
+struct acpi_tad_rt {
56
+ u16 year; /* 1900 - 9999 */
57
+ u8 month; /* 1 - 12 */
58
+ u8 day; /* 1 - 31 */
59
+ u8 hour; /* 0 - 23 */
60
+ u8 minute; /* 0 - 59 */
61
+ u8 second; /* 0 - 59 */
62
+ u8 valid; /* 0 (failed) or 1 (success) for reads, 0 for writes */
63
+ u16 msec; /* 1 - 1000 */
64
+ s16 tz; /* -1440 to 1440 or 2047 (unspecified) */
65
+ u8 daylight;
66
+ u8 padding[3]; /* must be 0 */
67
+} __packed;
68
+
69
+static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt)
70
+{
71
+ acpi_handle handle = ACPI_HANDLE(dev);
72
+ union acpi_object args[] = {
73
+ { .type = ACPI_TYPE_BUFFER, },
74
+ };
75
+ struct acpi_object_list arg_list = {
76
+ .pointer = args,
77
+ .count = ARRAY_SIZE(args),
78
+ };
79
+ unsigned long long retval;
80
+ acpi_status status;
81
+
82
+ if (rt->year < 1900 || rt->year > 9999 ||
83
+ rt->month < 1 || rt->month > 12 ||
84
+ rt->hour > 23 || rt->minute > 59 || rt->second > 59 ||
85
+ rt->tz < -1440 || (rt->tz > 1440 && rt->tz != 2047) ||
86
+ rt->daylight > 3)
87
+ return -ERANGE;
88
+
89
+ args[0].buffer.pointer = (u8 *)rt;
90
+ args[0].buffer.length = sizeof(*rt);
91
+
92
+ pm_runtime_get_sync(dev);
93
+
94
+ status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval);
95
+
96
+ pm_runtime_put_sync(dev);
97
+
98
+ if (ACPI_FAILURE(status) || retval)
99
+ return -EIO;
100
+
101
+ return 0;
102
+}
103
+
104
+static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
105
+{
106
+ acpi_handle handle = ACPI_HANDLE(dev);
107
+ struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER };
108
+ union acpi_object *out_obj;
109
+ struct acpi_tad_rt *data;
110
+ acpi_status status;
111
+ int ret = -EIO;
112
+
113
+ pm_runtime_get_sync(dev);
114
+
115
+ status = acpi_evaluate_object(handle, "_GRT", NULL, &output);
116
+
117
+ pm_runtime_put_sync(dev);
118
+
119
+ if (ACPI_FAILURE(status))
120
+ goto out_free;
121
+
122
+ out_obj = output.pointer;
123
+ if (out_obj->type != ACPI_TYPE_BUFFER)
124
+ goto out_free;
125
+
126
+ if (out_obj->buffer.length != sizeof(*rt))
127
+ goto out_free;
128
+
129
+ data = (struct acpi_tad_rt *)(out_obj->buffer.pointer);
130
+ if (!data->valid)
131
+ goto out_free;
132
+
133
+ memcpy(rt, data, sizeof(*rt));
134
+ ret = 0;
135
+
136
+out_free:
137
+ ACPI_FREE(output.pointer);
138
+ return ret;
139
+}
140
+
141
+static char *acpi_tad_rt_next_field(char *s, int *val)
142
+{
143
+ char *p;
144
+
145
+ p = strchr(s, ':');
146
+ if (!p)
147
+ return NULL;
148
+
149
+ *p = '\0';
150
+ if (kstrtoint(s, 10, val))
151
+ return NULL;
152
+
153
+ return p + 1;
154
+}
155
+
156
+static ssize_t time_store(struct device *dev, struct device_attribute *attr,
157
+ const char *buf, size_t count)
158
+{
159
+ struct acpi_tad_rt rt;
160
+ char *str, *s;
161
+ int val, ret = -ENODATA;
162
+
163
+ str = kmemdup_nul(buf, count, GFP_KERNEL);
164
+ if (!str)
165
+ return -ENOMEM;
166
+
167
+ s = acpi_tad_rt_next_field(str, &val);
168
+ if (!s)
169
+ goto out_free;
170
+
171
+ rt.year = val;
172
+
173
+ s = acpi_tad_rt_next_field(s, &val);
174
+ if (!s)
175
+ goto out_free;
176
+
177
+ rt.month = val;
178
+
179
+ s = acpi_tad_rt_next_field(s, &val);
180
+ if (!s)
181
+ goto out_free;
182
+
183
+ rt.day = val;
184
+
185
+ s = acpi_tad_rt_next_field(s, &val);
186
+ if (!s)
187
+ goto out_free;
188
+
189
+ rt.hour = val;
190
+
191
+ s = acpi_tad_rt_next_field(s, &val);
192
+ if (!s)
193
+ goto out_free;
194
+
195
+ rt.minute = val;
196
+
197
+ s = acpi_tad_rt_next_field(s, &val);
198
+ if (!s)
199
+ goto out_free;
200
+
201
+ rt.second = val;
202
+
203
+ s = acpi_tad_rt_next_field(s, &val);
204
+ if (!s)
205
+ goto out_free;
206
+
207
+ rt.tz = val;
208
+
209
+ if (kstrtoint(s, 10, &val))
210
+ goto out_free;
211
+
212
+ rt.daylight = val;
213
+
214
+ rt.valid = 0;
215
+ rt.msec = 0;
216
+ memset(rt.padding, 0, 3);
217
+
218
+ ret = acpi_tad_set_real_time(dev, &rt);
219
+
220
+out_free:
221
+ kfree(str);
222
+ return ret ? ret : count;
223
+}
224
+
225
+static ssize_t time_show(struct device *dev, struct device_attribute *attr,
226
+ char *buf)
227
+{
228
+ struct acpi_tad_rt rt;
229
+ int ret;
230
+
231
+ ret = acpi_tad_get_real_time(dev, &rt);
232
+ if (ret)
233
+ return ret;
234
+
235
+ return sprintf(buf, "%u:%u:%u:%u:%u:%u:%d:%u\n",
236
+ rt.year, rt.month, rt.day, rt.hour, rt.minute, rt.second,
237
+ rt.tz, rt.daylight);
238
+}
239
+
240
+static DEVICE_ATTR_RW(time);
241
+
242
+static struct attribute *acpi_tad_time_attrs[] = {
243
+ &dev_attr_time.attr,
244
+ NULL,
245
+};
246
+static const struct attribute_group acpi_tad_time_attr_group = {
247
+ .attrs = acpi_tad_time_attrs,
248
+};
249
+
55250 static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id,
56251 u32 value)
57252 {
....@@ -251,7 +446,7 @@
251446 return acpi_tad_alarm_read(dev, buf, ACPI_TAD_AC_TIMER);
252447 }
253448
254
-static DEVICE_ATTR(ac_alarm, S_IRUSR | S_IWUSR, ac_alarm_show, ac_alarm_store);
449
+static DEVICE_ATTR_RW(ac_alarm);
255450
256451 static ssize_t ac_policy_store(struct device *dev, struct device_attribute *attr,
257452 const char *buf, size_t count)
....@@ -267,7 +462,7 @@
267462 return acpi_tad_policy_read(dev, buf, ACPI_TAD_AC_TIMER);
268463 }
269464
270
-static DEVICE_ATTR(ac_policy, S_IRUSR | S_IWUSR, ac_policy_show, ac_policy_store);
465
+static DEVICE_ATTR_RW(ac_policy);
271466
272467 static ssize_t ac_status_store(struct device *dev, struct device_attribute *attr,
273468 const char *buf, size_t count)
....@@ -283,7 +478,7 @@
283478 return acpi_tad_status_read(dev, buf, ACPI_TAD_AC_TIMER);
284479 }
285480
286
-static DEVICE_ATTR(ac_status, S_IRUSR | S_IWUSR, ac_status_show, ac_status_store);
481
+static DEVICE_ATTR_RW(ac_status);
287482
288483 static struct attribute *acpi_tad_attrs[] = {
289484 &dev_attr_caps.attr,
....@@ -310,7 +505,7 @@
310505 return acpi_tad_alarm_read(dev, buf, ACPI_TAD_DC_TIMER);
311506 }
312507
313
-static DEVICE_ATTR(dc_alarm, S_IRUSR | S_IWUSR, dc_alarm_show, dc_alarm_store);
508
+static DEVICE_ATTR_RW(dc_alarm);
314509
315510 static ssize_t dc_policy_store(struct device *dev, struct device_attribute *attr,
316511 const char *buf, size_t count)
....@@ -326,7 +521,7 @@
326521 return acpi_tad_policy_read(dev, buf, ACPI_TAD_DC_TIMER);
327522 }
328523
329
-static DEVICE_ATTR(dc_policy, S_IRUSR | S_IWUSR, dc_policy_show, dc_policy_store);
524
+static DEVICE_ATTR_RW(dc_policy);
330525
331526 static ssize_t dc_status_store(struct device *dev, struct device_attribute *attr,
332527 const char *buf, size_t count)
....@@ -342,7 +537,7 @@
342537 return acpi_tad_status_read(dev, buf, ACPI_TAD_DC_TIMER);
343538 }
344539
345
-static DEVICE_ATTR(dc_status, S_IRUSR | S_IWUSR, dc_status_show, dc_status_store);
540
+static DEVICE_ATTR_RW(dc_status);
346541
347542 static struct attribute *acpi_tad_dc_attrs[] = {
348543 &dev_attr_dc_alarm.attr,
....@@ -429,7 +624,7 @@
429624 */
430625 device_init_wakeup(dev, true);
431626 dev_pm_set_driver_flags(dev, DPM_FLAG_SMART_SUSPEND |
432
- DPM_FLAG_LEAVE_SUSPENDED);
627
+ DPM_FLAG_MAY_SKIP_RESUME);
433628 /*
434629 * The platform bus type layer tells the ACPI PM domain powers up the
435630 * device, so set the runtime PM status of it to "active".
....@@ -448,6 +643,12 @@
448643 goto fail;
449644 }
450645
646
+ if (caps & ACPI_TAD_RT) {
647
+ ret = sysfs_create_group(&dev->kobj, &acpi_tad_time_attr_group);
648
+ if (ret)
649
+ goto fail;
650
+ }
651
+
451652 return 0;
452653
453654 fail: