diff options
author | Bjorn Andersson <bjorn.andersson@linaro.org> | 2016-10-08 00:23:13 -0400 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2016-10-31 18:41:55 -0400 |
commit | bbd188092e3bd7536583b37e7d7d2e38a65de74d (patch) | |
tree | b815146f5b7d48a1a90f5e6b49265ae27d3defda /drivers/rpmsg | |
parent | e950604782440c8635d289552bb5db58658fcbe9 (diff) |
rpmsg: Support drivers without primary endpoint
Some types of rpmsg drivers does not have a primary endpoint to tie
their existence upon, but wishes to create and destroy endpoints
dynamically, e.g. based on user interactions.
Allow rpmsg drivers to omit a driver callback to signal this case and
make the probe path not create a primary endpoint in this case.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r-- | drivers/rpmsg/rpmsg_core.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 087d4db896c8..7561941ba413 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c | |||
@@ -347,27 +347,30 @@ static int rpmsg_dev_probe(struct device *dev) | |||
347 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | 347 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); |
348 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | 348 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); |
349 | struct rpmsg_channel_info chinfo = {}; | 349 | struct rpmsg_channel_info chinfo = {}; |
350 | struct rpmsg_endpoint *ept; | 350 | struct rpmsg_endpoint *ept = NULL; |
351 | int err; | 351 | int err; |
352 | 352 | ||
353 | strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); | 353 | if (rpdrv->callback) { |
354 | chinfo.src = rpdev->src; | 354 | strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); |
355 | chinfo.dst = RPMSG_ADDR_ANY; | 355 | chinfo.src = rpdev->src; |
356 | chinfo.dst = RPMSG_ADDR_ANY; | ||
356 | 357 | ||
357 | ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); | 358 | ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); |
358 | if (!ept) { | 359 | if (!ept) { |
359 | dev_err(dev, "failed to create endpoint\n"); | 360 | dev_err(dev, "failed to create endpoint\n"); |
360 | err = -ENOMEM; | 361 | err = -ENOMEM; |
361 | goto out; | 362 | goto out; |
362 | } | 363 | } |
363 | 364 | ||
364 | rpdev->ept = ept; | 365 | rpdev->ept = ept; |
365 | rpdev->src = ept->addr; | 366 | rpdev->src = ept->addr; |
367 | } | ||
366 | 368 | ||
367 | err = rpdrv->probe(rpdev); | 369 | err = rpdrv->probe(rpdev); |
368 | if (err) { | 370 | if (err) { |
369 | dev_err(dev, "%s: failed: %d\n", __func__, err); | 371 | dev_err(dev, "%s: failed: %d\n", __func__, err); |
370 | rpmsg_destroy_ept(ept); | 372 | if (ept) |
373 | rpmsg_destroy_ept(ept); | ||
371 | goto out; | 374 | goto out; |
372 | } | 375 | } |
373 | 376 | ||
@@ -388,7 +391,8 @@ static int rpmsg_dev_remove(struct device *dev) | |||
388 | 391 | ||
389 | rpdrv->remove(rpdev); | 392 | rpdrv->remove(rpdev); |
390 | 393 | ||
391 | rpmsg_destroy_ept(rpdev->ept); | 394 | if (rpdev->ept) |
395 | rpmsg_destroy_ept(rpdev->ept); | ||
392 | 396 | ||
393 | return err; | 397 | return err; |
394 | } | 398 | } |