diff options
author | Anup Patel <anup@brainfault.org> | 2018-03-23 12:11:17 -0400 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2018-04-25 19:59:53 -0400 |
commit | 39e47767ec9b22f844c2a07c9d329256960d4021 (patch) | |
tree | d34066f379c86a35f0a249af39046c784b6a850d /drivers/rpmsg | |
parent | 60cc43fc888428bb2f18f08997432d426a243338 (diff) |
rpmsg: Add driver_override device attribute for rpmsg_device
This patch adds "driver_override" device attribute for rpmsg_device which
will allow users to explicitly specify the rpmsg_driver to be used via
sysfs entry.
The "driver_override" device attribute implemented here is very similar
to "driver_override" implemented for platform, pci, and amba bus types.
One important use-case of "driver_override" device attribute is to force
use of rpmsg_chrdev driver for certain rpmsg_device instances.
Signed-off-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r-- | drivers/rpmsg/rpmsg_core.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 920a02f0462c..bea7c74e12eb 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c | |||
@@ -333,11 +333,49 @@ field##_show(struct device *dev, \ | |||
333 | } \ | 333 | } \ |
334 | static DEVICE_ATTR_RO(field); | 334 | static DEVICE_ATTR_RO(field); |
335 | 335 | ||
336 | #define rpmsg_string_attr(field, member) \ | ||
337 | static ssize_t \ | ||
338 | field##_store(struct device *dev, struct device_attribute *attr, \ | ||
339 | const char *buf, size_t sz) \ | ||
340 | { \ | ||
341 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ | ||
342 | char *new, *old; \ | ||
343 | \ | ||
344 | new = kstrndup(buf, sz, GFP_KERNEL); \ | ||
345 | if (!new) \ | ||
346 | return -ENOMEM; \ | ||
347 | new[strcspn(new, "\n")] = '\0'; \ | ||
348 | \ | ||
349 | device_lock(dev); \ | ||
350 | old = rpdev->member; \ | ||
351 | if (strlen(new)) { \ | ||
352 | rpdev->member = new; \ | ||
353 | } else { \ | ||
354 | kfree(new); \ | ||
355 | rpdev->member = NULL; \ | ||
356 | } \ | ||
357 | device_unlock(dev); \ | ||
358 | \ | ||
359 | kfree(old); \ | ||
360 | \ | ||
361 | return sz; \ | ||
362 | } \ | ||
363 | static ssize_t \ | ||
364 | field##_show(struct device *dev, \ | ||
365 | struct device_attribute *attr, char *buf) \ | ||
366 | { \ | ||
367 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ | ||
368 | \ | ||
369 | return sprintf(buf, "%s\n", rpdev->member); \ | ||
370 | } \ | ||
371 | static DEVICE_ATTR_RW(field) | ||
372 | |||
336 | /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ | 373 | /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ |
337 | rpmsg_show_attr(name, id.name, "%s\n"); | 374 | rpmsg_show_attr(name, id.name, "%s\n"); |
338 | rpmsg_show_attr(src, src, "0x%x\n"); | 375 | rpmsg_show_attr(src, src, "0x%x\n"); |
339 | rpmsg_show_attr(dst, dst, "0x%x\n"); | 376 | rpmsg_show_attr(dst, dst, "0x%x\n"); |
340 | rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); | 377 | rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); |
378 | rpmsg_string_attr(driver_override, driver_override); | ||
341 | 379 | ||
342 | static ssize_t modalias_show(struct device *dev, | 380 | static ssize_t modalias_show(struct device *dev, |
343 | struct device_attribute *attr, char *buf) | 381 | struct device_attribute *attr, char *buf) |
@@ -359,6 +397,7 @@ static struct attribute *rpmsg_dev_attrs[] = { | |||
359 | &dev_attr_dst.attr, | 397 | &dev_attr_dst.attr, |
360 | &dev_attr_src.attr, | 398 | &dev_attr_src.attr, |
361 | &dev_attr_announce.attr, | 399 | &dev_attr_announce.attr, |
400 | &dev_attr_driver_override.attr, | ||
362 | NULL, | 401 | NULL, |
363 | }; | 402 | }; |
364 | ATTRIBUTE_GROUPS(rpmsg_dev); | 403 | ATTRIBUTE_GROUPS(rpmsg_dev); |