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 | |
| 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>
| -rw-r--r-- | Documentation/ABI/testing/sysfs-bus-rpmsg | 20 | ||||
| -rw-r--r-- | drivers/rpmsg/rpmsg_core.c | 39 |
2 files changed, 59 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-rpmsg b/Documentation/ABI/testing/sysfs-bus-rpmsg index 189e419a5a2d..990fcc420935 100644 --- a/Documentation/ABI/testing/sysfs-bus-rpmsg +++ b/Documentation/ABI/testing/sysfs-bus-rpmsg | |||
| @@ -73,3 +73,23 @@ Description: | |||
| 73 | This sysfs entry tells us whether the channel is a local | 73 | This sysfs entry tells us whether the channel is a local |
| 74 | server channel that is announced (values are either | 74 | server channel that is announced (values are either |
| 75 | true or false). | 75 | true or false). |
| 76 | |||
| 77 | What: /sys/bus/rpmsg/devices/.../driver_override | ||
| 78 | Date: April 2018 | ||
| 79 | KernelVersion: 4.18 | ||
| 80 | Contact: Bjorn Andersson <bjorn.andersson@linaro.org> | ||
| 81 | Description: | ||
| 82 | Every rpmsg device is a communication channel with a remote | ||
| 83 | processor. Channels are identified by a textual name (see | ||
| 84 | /sys/bus/rpmsg/devices/.../name above) and have a local | ||
| 85 | ("source") rpmsg address, and remote ("destination") rpmsg | ||
| 86 | address. | ||
| 87 | |||
| 88 | The listening entity (or client) which communicates with a | ||
| 89 | remote processor is referred as rpmsg driver. The rpmsg device | ||
| 90 | and rpmsg driver are matched based on rpmsg device name and | ||
| 91 | rpmsg driver ID table. | ||
| 92 | |||
| 93 | This sysfs entry allows the rpmsg driver for a rpmsg device | ||
| 94 | to be specified which will override standard OF, ID table | ||
| 95 | and name matching. | ||
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); |
