diff options
author | Bjorn Andersson <bjorn.andersson@linaro.org> | 2016-09-01 18:28:04 -0400 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2016-09-09 01:15:23 -0400 |
commit | 5e619b48677ca8c9fb907c58383859cea78705c9 (patch) | |
tree | f67ad937b0c8531b0e3cad8d28acb2229733db72 /drivers/rpmsg | |
parent | 6eed598a049193917a2e15b163abb58c5c1ef466 (diff) |
rpmsg: Split rpmsg core and virtio backend
Extract the generic rpmsg core functionality from the virtio rpmsg
implementation, splitting the implementation in a rpmsg core and a
virtio backend.
Based on initial work by Sricharan R <sricharan@codeaurora.org>
Cc: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r-- | drivers/rpmsg/rpmsg_core.c | 231 | ||||
-rw-r--r-- | drivers/rpmsg/rpmsg_internal.h | 4 | ||||
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 225 |
3 files changed, 237 insertions, 223 deletions
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 81101775fed0..e1d765a7372c 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c | |||
@@ -262,3 +262,234 @@ struct device *rpmsg_find_device(struct device *parent, | |||
262 | 262 | ||
263 | } | 263 | } |
264 | EXPORT_SYMBOL(rpmsg_find_device); | 264 | EXPORT_SYMBOL(rpmsg_find_device); |
265 | |||
266 | /* sysfs show configuration fields */ | ||
267 | #define rpmsg_show_attr(field, path, format_string) \ | ||
268 | static ssize_t \ | ||
269 | field##_show(struct device *dev, \ | ||
270 | struct device_attribute *attr, char *buf) \ | ||
271 | { \ | ||
272 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ | ||
273 | \ | ||
274 | return sprintf(buf, format_string, rpdev->path); \ | ||
275 | } | ||
276 | |||
277 | /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ | ||
278 | rpmsg_show_attr(name, id.name, "%s\n"); | ||
279 | rpmsg_show_attr(src, src, "0x%x\n"); | ||
280 | rpmsg_show_attr(dst, dst, "0x%x\n"); | ||
281 | rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); | ||
282 | |||
283 | static ssize_t modalias_show(struct device *dev, | ||
284 | struct device_attribute *attr, char *buf) | ||
285 | { | ||
286 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
287 | |||
288 | return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); | ||
289 | } | ||
290 | |||
291 | static struct device_attribute rpmsg_dev_attrs[] = { | ||
292 | __ATTR_RO(name), | ||
293 | __ATTR_RO(modalias), | ||
294 | __ATTR_RO(dst), | ||
295 | __ATTR_RO(src), | ||
296 | __ATTR_RO(announce), | ||
297 | __ATTR_NULL | ||
298 | }; | ||
299 | |||
300 | /* rpmsg devices and drivers are matched using the service name */ | ||
301 | static inline int rpmsg_id_match(const struct rpmsg_device *rpdev, | ||
302 | const struct rpmsg_device_id *id) | ||
303 | { | ||
304 | return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0; | ||
305 | } | ||
306 | |||
307 | /* match rpmsg channel and rpmsg driver */ | ||
308 | static int rpmsg_dev_match(struct device *dev, struct device_driver *drv) | ||
309 | { | ||
310 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
311 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv); | ||
312 | const struct rpmsg_device_id *ids = rpdrv->id_table; | ||
313 | unsigned int i; | ||
314 | |||
315 | if (ids) | ||
316 | for (i = 0; ids[i].name[0]; i++) | ||
317 | if (rpmsg_id_match(rpdev, &ids[i])) | ||
318 | return 1; | ||
319 | |||
320 | return of_driver_match_device(dev, drv); | ||
321 | } | ||
322 | |||
323 | static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
324 | { | ||
325 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
326 | |||
327 | return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT, | ||
328 | rpdev->id.name); | ||
329 | } | ||
330 | |||
331 | /* | ||
332 | * when an rpmsg driver is probed with a channel, we seamlessly create | ||
333 | * it an endpoint, binding its rx callback to a unique local rpmsg | ||
334 | * address. | ||
335 | * | ||
336 | * if we need to, we also announce about this channel to the remote | ||
337 | * processor (needed in case the driver is exposing an rpmsg service). | ||
338 | */ | ||
339 | static int rpmsg_dev_probe(struct device *dev) | ||
340 | { | ||
341 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
342 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | ||
343 | struct rpmsg_channel_info chinfo = {}; | ||
344 | struct rpmsg_endpoint *ept; | ||
345 | int err; | ||
346 | |||
347 | strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); | ||
348 | chinfo.src = rpdev->src; | ||
349 | chinfo.dst = RPMSG_ADDR_ANY; | ||
350 | |||
351 | ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); | ||
352 | if (!ept) { | ||
353 | dev_err(dev, "failed to create endpoint\n"); | ||
354 | err = -ENOMEM; | ||
355 | goto out; | ||
356 | } | ||
357 | |||
358 | rpdev->ept = ept; | ||
359 | rpdev->src = ept->addr; | ||
360 | |||
361 | err = rpdrv->probe(rpdev); | ||
362 | if (err) { | ||
363 | dev_err(dev, "%s: failed: %d\n", __func__, err); | ||
364 | rpmsg_destroy_ept(ept); | ||
365 | goto out; | ||
366 | } | ||
367 | |||
368 | if (rpdev->ops->announce_create) | ||
369 | err = rpdev->ops->announce_create(rpdev); | ||
370 | out: | ||
371 | return err; | ||
372 | } | ||
373 | |||
374 | static int rpmsg_dev_remove(struct device *dev) | ||
375 | { | ||
376 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
377 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | ||
378 | int err = 0; | ||
379 | |||
380 | if (rpdev->ops->announce_destroy) | ||
381 | err = rpdev->ops->announce_destroy(rpdev); | ||
382 | |||
383 | rpdrv->remove(rpdev); | ||
384 | |||
385 | rpmsg_destroy_ept(rpdev->ept); | ||
386 | |||
387 | return err; | ||
388 | } | ||
389 | |||
390 | static struct bus_type rpmsg_bus = { | ||
391 | .name = "rpmsg", | ||
392 | .match = rpmsg_dev_match, | ||
393 | .dev_attrs = rpmsg_dev_attrs, | ||
394 | .uevent = rpmsg_uevent, | ||
395 | .probe = rpmsg_dev_probe, | ||
396 | .remove = rpmsg_dev_remove, | ||
397 | }; | ||
398 | |||
399 | static void rpmsg_release_device(struct device *dev) | ||
400 | { | ||
401 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
402 | |||
403 | kfree(rpdev); | ||
404 | } | ||
405 | |||
406 | int rpmsg_register_device(struct rpmsg_device *rpdev) | ||
407 | { | ||
408 | struct device *dev = &rpdev->dev; | ||
409 | int ret; | ||
410 | |||
411 | dev_set_name(&rpdev->dev, "%s:%s", | ||
412 | dev_name(dev->parent), rpdev->id.name); | ||
413 | |||
414 | rpdev->dev.bus = &rpmsg_bus; | ||
415 | rpdev->dev.release = rpmsg_release_device; | ||
416 | |||
417 | ret = device_register(&rpdev->dev); | ||
418 | if (ret) { | ||
419 | dev_err(dev, "device_register failed: %d\n", ret); | ||
420 | put_device(&rpdev->dev); | ||
421 | } | ||
422 | |||
423 | return ret; | ||
424 | } | ||
425 | EXPORT_SYMBOL(rpmsg_register_device); | ||
426 | |||
427 | /* | ||
428 | * find an existing channel using its name + address properties, | ||
429 | * and destroy it | ||
430 | */ | ||
431 | int rpmsg_unregister_device(struct device *parent, | ||
432 | struct rpmsg_channel_info *chinfo) | ||
433 | { | ||
434 | struct device *dev; | ||
435 | |||
436 | dev = rpmsg_find_device(parent, chinfo); | ||
437 | if (!dev) | ||
438 | return -EINVAL; | ||
439 | |||
440 | device_unregister(dev); | ||
441 | |||
442 | put_device(dev); | ||
443 | |||
444 | return 0; | ||
445 | } | ||
446 | EXPORT_SYMBOL(rpmsg_unregister_device); | ||
447 | |||
448 | /** | ||
449 | * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus | ||
450 | * @rpdrv: pointer to a struct rpmsg_driver | ||
451 | * @owner: owning module/driver | ||
452 | * | ||
453 | * Returns 0 on success, and an appropriate error value on failure. | ||
454 | */ | ||
455 | int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner) | ||
456 | { | ||
457 | rpdrv->drv.bus = &rpmsg_bus; | ||
458 | rpdrv->drv.owner = owner; | ||
459 | return driver_register(&rpdrv->drv); | ||
460 | } | ||
461 | EXPORT_SYMBOL(__register_rpmsg_driver); | ||
462 | |||
463 | /** | ||
464 | * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus | ||
465 | * @rpdrv: pointer to a struct rpmsg_driver | ||
466 | * | ||
467 | * Returns 0 on success, and an appropriate error value on failure. | ||
468 | */ | ||
469 | void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv) | ||
470 | { | ||
471 | driver_unregister(&rpdrv->drv); | ||
472 | } | ||
473 | EXPORT_SYMBOL(unregister_rpmsg_driver); | ||
474 | |||
475 | |||
476 | static int __init rpmsg_init(void) | ||
477 | { | ||
478 | int ret; | ||
479 | |||
480 | ret = bus_register(&rpmsg_bus); | ||
481 | if (ret) | ||
482 | pr_err("failed to register rpmsg bus: %d\n", ret); | ||
483 | |||
484 | return ret; | ||
485 | } | ||
486 | postcore_initcall(rpmsg_init); | ||
487 | |||
488 | static void __exit rpmsg_fini(void) | ||
489 | { | ||
490 | bus_unregister(&rpmsg_bus); | ||
491 | } | ||
492 | module_exit(rpmsg_fini); | ||
493 | |||
494 | MODULE_DESCRIPTION("remote processor messaging bus"); | ||
495 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h index 205debf4ea65..8ac98fd0bf1d 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h | |||
@@ -25,6 +25,10 @@ | |||
25 | #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev) | 25 | #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev) |
26 | #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) | 26 | #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) |
27 | 27 | ||
28 | int rpmsg_register_device(struct rpmsg_device *rpdev); | ||
29 | int rpmsg_unregister_device(struct device *parent, | ||
30 | struct rpmsg_channel_info *chinfo); | ||
31 | |||
28 | struct device *rpmsg_find_device(struct device *parent, | 32 | struct device *rpmsg_find_device(struct device *parent, |
29 | struct rpmsg_channel_info *chinfo); | 33 | struct rpmsg_channel_info *chinfo); |
30 | 34 | ||
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index e1052622c6a2..31cd526f690d 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -75,9 +75,6 @@ struct virtproc_info { | |||
75 | struct rpmsg_endpoint *ns_ept; | 75 | struct rpmsg_endpoint *ns_ept; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev) | ||
79 | #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv) | ||
80 | |||
81 | /* | 78 | /* |
82 | * We're allocating buffers of 512 bytes each for communications. The | 79 | * We're allocating buffers of 512 bytes each for communications. The |
83 | * number of buffers will be computed from the number of buffers supported | 80 | * number of buffers will be computed from the number of buffers supported |
@@ -120,72 +117,6 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, | |||
120 | int len, u32 dst); | 117 | int len, u32 dst); |
121 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, | 118 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, |
122 | u32 dst, void *data, int len); | 119 | u32 dst, void *data, int len); |
123 | static int rpmsg_register_device(struct rpmsg_device *rpdev); | ||
124 | |||
125 | /* sysfs show configuration fields */ | ||
126 | #define rpmsg_show_attr(field, path, format_string) \ | ||
127 | static ssize_t \ | ||
128 | field##_show(struct device *dev, \ | ||
129 | struct device_attribute *attr, char *buf) \ | ||
130 | { \ | ||
131 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ | ||
132 | \ | ||
133 | return sprintf(buf, format_string, rpdev->path); \ | ||
134 | } | ||
135 | |||
136 | /* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */ | ||
137 | rpmsg_show_attr(name, id.name, "%s\n"); | ||
138 | rpmsg_show_attr(src, src, "0x%x\n"); | ||
139 | rpmsg_show_attr(dst, dst, "0x%x\n"); | ||
140 | rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n"); | ||
141 | |||
142 | static ssize_t modalias_show(struct device *dev, | ||
143 | struct device_attribute *attr, char *buf) | ||
144 | { | ||
145 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
146 | |||
147 | return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name); | ||
148 | } | ||
149 | |||
150 | static struct device_attribute rpmsg_dev_attrs[] = { | ||
151 | __ATTR_RO(name), | ||
152 | __ATTR_RO(modalias), | ||
153 | __ATTR_RO(dst), | ||
154 | __ATTR_RO(src), | ||
155 | __ATTR_RO(announce), | ||
156 | __ATTR_NULL | ||
157 | }; | ||
158 | |||
159 | /* rpmsg devices and drivers are matched using the service name */ | ||
160 | static inline int rpmsg_id_match(const struct rpmsg_device *rpdev, | ||
161 | const struct rpmsg_device_id *id) | ||
162 | { | ||
163 | return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0; | ||
164 | } | ||
165 | |||
166 | /* match rpmsg channel and rpmsg driver */ | ||
167 | static int rpmsg_dev_match(struct device *dev, struct device_driver *drv) | ||
168 | { | ||
169 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
170 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv); | ||
171 | const struct rpmsg_device_id *ids = rpdrv->id_table; | ||
172 | unsigned int i; | ||
173 | |||
174 | if (ids) | ||
175 | for (i = 0; ids[i].name[0]; i++) | ||
176 | if (rpmsg_id_match(rpdev, &ids[i])) | ||
177 | return 1; | ||
178 | |||
179 | return of_driver_match_device(dev, drv); | ||
180 | } | ||
181 | |||
182 | static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
183 | { | ||
184 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
185 | |||
186 | return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT, | ||
187 | rpdev->id.name); | ||
188 | } | ||
189 | 120 | ||
190 | static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { | 121 | static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { |
191 | .destroy_ept = virtio_rpmsg_destroy_ept, | 122 | .destroy_ept = virtio_rpmsg_destroy_ept, |
@@ -307,49 +238,6 @@ static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | |||
307 | __rpmsg_destroy_ept(ept->rpdev->vrp, ept); | 238 | __rpmsg_destroy_ept(ept->rpdev->vrp, ept); |
308 | } | 239 | } |
309 | 240 | ||
310 | /* | ||
311 | * when an rpmsg driver is probed with a channel, we seamlessly create | ||
312 | * it an endpoint, binding its rx callback to a unique local rpmsg | ||
313 | * address. | ||
314 | * | ||
315 | * if we need to, we also announce about this channel to the remote | ||
316 | * processor (needed in case the driver is exposing an rpmsg service). | ||
317 | */ | ||
318 | static int rpmsg_dev_probe(struct device *dev) | ||
319 | { | ||
320 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
321 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | ||
322 | struct rpmsg_channel_info chinfo = {}; | ||
323 | struct rpmsg_endpoint *ept; | ||
324 | int err; | ||
325 | |||
326 | strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE); | ||
327 | chinfo.src = rpdev->src; | ||
328 | chinfo.dst = RPMSG_ADDR_ANY; | ||
329 | |||
330 | ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo); | ||
331 | if (!ept) { | ||
332 | dev_err(dev, "failed to create endpoint\n"); | ||
333 | err = -ENOMEM; | ||
334 | goto out; | ||
335 | } | ||
336 | |||
337 | rpdev->ept = ept; | ||
338 | rpdev->src = ept->addr; | ||
339 | |||
340 | err = rpdrv->probe(rpdev); | ||
341 | if (err) { | ||
342 | dev_err(dev, "%s: failed: %d\n", __func__, err); | ||
343 | rpmsg_destroy_ept(ept); | ||
344 | goto out; | ||
345 | } | ||
346 | |||
347 | if (rpdev->ops->announce_create) | ||
348 | err = rpdev->ops->announce_create(rpdev); | ||
349 | out: | ||
350 | return err; | ||
351 | } | ||
352 | |||
353 | static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev) | 241 | static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev) |
354 | { | 242 | { |
355 | struct virtproc_info *vrp = rpdev->vrp; | 243 | struct virtproc_info *vrp = rpdev->vrp; |
@@ -396,65 +284,6 @@ static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev) | |||
396 | return err; | 284 | return err; |
397 | } | 285 | } |
398 | 286 | ||
399 | static int rpmsg_dev_remove(struct device *dev) | ||
400 | { | ||
401 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
402 | struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver); | ||
403 | int err = 0; | ||
404 | |||
405 | if (rpdev->ops->announce_destroy) | ||
406 | err = rpdev->ops->announce_destroy(rpdev); | ||
407 | |||
408 | rpdrv->remove(rpdev); | ||
409 | |||
410 | rpmsg_destroy_ept(rpdev->ept); | ||
411 | |||
412 | return err; | ||
413 | } | ||
414 | |||
415 | static struct bus_type rpmsg_bus = { | ||
416 | .name = "rpmsg", | ||
417 | .match = rpmsg_dev_match, | ||
418 | .dev_attrs = rpmsg_dev_attrs, | ||
419 | .uevent = rpmsg_uevent, | ||
420 | .probe = rpmsg_dev_probe, | ||
421 | .remove = rpmsg_dev_remove, | ||
422 | }; | ||
423 | |||
424 | /** | ||
425 | * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus | ||
426 | * @rpdrv: pointer to a struct rpmsg_driver | ||
427 | * @owner: owning module/driver | ||
428 | * | ||
429 | * Returns 0 on success, and an appropriate error value on failure. | ||
430 | */ | ||
431 | int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner) | ||
432 | { | ||
433 | rpdrv->drv.bus = &rpmsg_bus; | ||
434 | rpdrv->drv.owner = owner; | ||
435 | return driver_register(&rpdrv->drv); | ||
436 | } | ||
437 | EXPORT_SYMBOL(__register_rpmsg_driver); | ||
438 | |||
439 | /** | ||
440 | * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus | ||
441 | * @rpdrv: pointer to a struct rpmsg_driver | ||
442 | * | ||
443 | * Returns 0 on success, and an appropriate error value on failure. | ||
444 | */ | ||
445 | void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv) | ||
446 | { | ||
447 | driver_unregister(&rpdrv->drv); | ||
448 | } | ||
449 | EXPORT_SYMBOL(unregister_rpmsg_driver); | ||
450 | |||
451 | static void rpmsg_release_device(struct device *dev) | ||
452 | { | ||
453 | struct rpmsg_device *rpdev = to_rpmsg_device(dev); | ||
454 | |||
455 | kfree(rpdev); | ||
456 | } | ||
457 | |||
458 | static const struct rpmsg_device_ops virtio_rpmsg_ops = { | 287 | static const struct rpmsg_device_ops virtio_rpmsg_ops = { |
459 | .create_ept = virtio_rpmsg_create_ept, | 288 | .create_ept = virtio_rpmsg_create_ept, |
460 | .announce_create = virtio_rpmsg_announce_create, | 289 | .announce_create = virtio_rpmsg_announce_create, |
@@ -508,47 +337,6 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp, | |||
508 | return rpdev; | 337 | return rpdev; |
509 | } | 338 | } |
510 | 339 | ||
511 | static int rpmsg_register_device(struct rpmsg_device *rpdev) | ||
512 | { | ||
513 | struct device *dev = &rpdev->dev; | ||
514 | int ret; | ||
515 | |||
516 | dev_set_name(&rpdev->dev, "%s:%s", | ||
517 | dev_name(dev->parent), rpdev->id.name); | ||
518 | |||
519 | rpdev->dev.bus = &rpmsg_bus; | ||
520 | rpdev->dev.release = rpmsg_release_device; | ||
521 | |||
522 | ret = device_register(&rpdev->dev); | ||
523 | if (ret) { | ||
524 | dev_err(dev, "device_register failed: %d\n", ret); | ||
525 | put_device(&rpdev->dev); | ||
526 | } | ||
527 | |||
528 | return ret; | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * find an existing channel using its name + address properties, | ||
533 | * and destroy it | ||
534 | */ | ||
535 | static int rpmsg_destroy_channel(struct virtproc_info *vrp, | ||
536 | struct rpmsg_channel_info *chinfo) | ||
537 | { | ||
538 | struct virtio_device *vdev = vrp->vdev; | ||
539 | struct device *dev; | ||
540 | |||
541 | dev = rpmsg_find_device(&vdev->dev, chinfo); | ||
542 | if (!dev) | ||
543 | return -EINVAL; | ||
544 | |||
545 | device_unregister(dev); | ||
546 | |||
547 | put_device(dev); | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | /* super simple buffer "allocator" that is just enough for now */ | 340 | /* super simple buffer "allocator" that is just enough for now */ |
553 | static void *get_a_tx_buf(struct virtproc_info *vrp) | 341 | static void *get_a_tx_buf(struct virtproc_info *vrp) |
554 | { | 342 | { |
@@ -967,7 +755,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len, | |||
967 | chinfo.dst = msg->addr; | 755 | chinfo.dst = msg->addr; |
968 | 756 | ||
969 | if (msg->flags & RPMSG_NS_DESTROY) { | 757 | if (msg->flags & RPMSG_NS_DESTROY) { |
970 | ret = rpmsg_destroy_channel(vrp, &chinfo); | 758 | ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo); |
971 | if (ret) | 759 | if (ret) |
972 | dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); | 760 | dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret); |
973 | } else { | 761 | } else { |
@@ -1152,17 +940,9 @@ static int __init rpmsg_init(void) | |||
1152 | { | 940 | { |
1153 | int ret; | 941 | int ret; |
1154 | 942 | ||
1155 | ret = bus_register(&rpmsg_bus); | ||
1156 | if (ret) { | ||
1157 | pr_err("failed to register rpmsg bus: %d\n", ret); | ||
1158 | return ret; | ||
1159 | } | ||
1160 | |||
1161 | ret = register_virtio_driver(&virtio_ipc_driver); | 943 | ret = register_virtio_driver(&virtio_ipc_driver); |
1162 | if (ret) { | 944 | if (ret) |
1163 | pr_err("failed to register virtio driver: %d\n", ret); | 945 | pr_err("failed to register virtio driver: %d\n", ret); |
1164 | bus_unregister(&rpmsg_bus); | ||
1165 | } | ||
1166 | 946 | ||
1167 | return ret; | 947 | return ret; |
1168 | } | 948 | } |
@@ -1171,7 +951,6 @@ subsys_initcall(rpmsg_init); | |||
1171 | static void __exit rpmsg_fini(void) | 951 | static void __exit rpmsg_fini(void) |
1172 | { | 952 | { |
1173 | unregister_virtio_driver(&virtio_ipc_driver); | 953 | unregister_virtio_driver(&virtio_ipc_driver); |
1174 | bus_unregister(&rpmsg_bus); | ||
1175 | } | 954 | } |
1176 | module_exit(rpmsg_fini); | 955 | module_exit(rpmsg_fini); |
1177 | 956 | ||