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); |
