diff options
Diffstat (limited to 'drivers/rtc/rtc-sysfs.c')
-rw-r--r-- | drivers/rtc/rtc-sysfs.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 454da38c6012..f1ff30ade534 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -317,3 +317,46 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void) | |||
317 | { | 317 | { |
318 | return rtc_attr_groups; | 318 | return rtc_attr_groups; |
319 | } | 319 | } |
320 | |||
321 | int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) | ||
322 | { | ||
323 | size_t old_cnt = 0, add_cnt = 0, new_cnt; | ||
324 | const struct attribute_group **groups, **old; | ||
325 | |||
326 | if (rtc->registered) | ||
327 | return -EINVAL; | ||
328 | if (!grps) | ||
329 | return -EINVAL; | ||
330 | |||
331 | groups = rtc->dev.groups; | ||
332 | if (groups) | ||
333 | for (; *groups; groups++) | ||
334 | old_cnt++; | ||
335 | |||
336 | for (groups = grps; *groups; groups++) | ||
337 | add_cnt++; | ||
338 | |||
339 | new_cnt = old_cnt + add_cnt + 1; | ||
340 | groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL); | ||
341 | if (IS_ERR_OR_NULL(groups)) | ||
342 | return PTR_ERR(groups); | ||
343 | memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups)); | ||
344 | memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups)); | ||
345 | groups[old_cnt + add_cnt] = NULL; | ||
346 | |||
347 | old = rtc->dev.groups; | ||
348 | rtc->dev.groups = groups; | ||
349 | if (old && old != rtc_attr_groups) | ||
350 | devm_kfree(&rtc->dev, old); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | EXPORT_SYMBOL(rtc_add_groups); | ||
355 | |||
356 | int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp) | ||
357 | { | ||
358 | const struct attribute_group *groups[] = { grp, NULL }; | ||
359 | |||
360 | return rtc_add_groups(rtc, groups); | ||
361 | } | ||
362 | EXPORT_SYMBOL(rtc_add_group); | ||