diff options
author | Bjorn Andersson <bjorn.andersson@linaro.org> | 2016-09-01 18:28:00 -0400 |
---|---|---|
committer | Bjorn Andersson <bjorn.andersson@linaro.org> | 2016-09-09 01:15:21 -0400 |
commit | 8a228ecfe086b84e237a8d78be079e286e1ea67b (patch) | |
tree | 0a32e0fb4b0ee0da8f4d4ba82a4ad3c4936d753e | |
parent | 026dad47a814cd32aad6174a8f1218b020a277b1 (diff) |
rpmsg: Indirection table for rpmsg_endpoint operations
Add indirection table for rpmsg_endpoint related operations and move
virtio implementation behind this, this finishes of the decoupling of
the virtio implementation from the public API.
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 85 | ||||
-rw-r--r-- | include/linux/rpmsg.h | 62 |
2 files changed, 120 insertions, 27 deletions
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 605e09c96d65..e5f256791fd3 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -107,6 +107,18 @@ struct virtproc_info { | |||
107 | /* Address 53 is reserved for advertising remote services */ | 107 | /* Address 53 is reserved for advertising remote services */ |
108 | #define RPMSG_NS_ADDR (53) | 108 | #define RPMSG_NS_ADDR (53) |
109 | 109 | ||
110 | static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept); | ||
111 | static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len); | ||
112 | static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, | ||
113 | u32 dst); | ||
114 | static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, | ||
115 | u32 dst, void *data, int len); | ||
116 | static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len); | ||
117 | static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, | ||
118 | int len, u32 dst); | ||
119 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, | ||
120 | u32 dst, void *data, int len); | ||
121 | |||
110 | /* sysfs show configuration fields */ | 122 | /* sysfs show configuration fields */ |
111 | #define rpmsg_show_attr(field, path, format_string) \ | 123 | #define rpmsg_show_attr(field, path, format_string) \ |
112 | static ssize_t \ | 124 | static ssize_t \ |
@@ -172,6 +184,16 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
172 | rpdev->id.name); | 184 | rpdev->id.name); |
173 | } | 185 | } |
174 | 186 | ||
187 | static const struct rpmsg_endpoint_ops virtio_endpoint_ops = { | ||
188 | .destroy_ept = virtio_rpmsg_destroy_ept, | ||
189 | .send = virtio_rpmsg_send, | ||
190 | .sendto = virtio_rpmsg_sendto, | ||
191 | .send_offchannel = virtio_rpmsg_send_offchannel, | ||
192 | .trysend = virtio_rpmsg_trysend, | ||
193 | .trysendto = virtio_rpmsg_trysendto, | ||
194 | .trysend_offchannel = virtio_rpmsg_trysend_offchannel, | ||
195 | }; | ||
196 | |||
175 | /** | 197 | /** |
176 | * __ept_release() - deallocate an rpmsg endpoint | 198 | * __ept_release() - deallocate an rpmsg endpoint |
177 | * @kref: the ept's reference count | 199 | * @kref: the ept's reference count |
@@ -212,6 +234,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, | |||
212 | ept->rpdev = rpdev; | 234 | ept->rpdev = rpdev; |
213 | ept->cb = cb; | 235 | ept->cb = cb; |
214 | ept->priv = priv; | 236 | ept->priv = priv; |
237 | ept->ops = &virtio_endpoint_ops; | ||
215 | 238 | ||
216 | /* do we need to allocate a local address ? */ | 239 | /* do we need to allocate a local address ? */ |
217 | if (addr == RPMSG_ADDR_ANY) { | 240 | if (addr == RPMSG_ADDR_ANY) { |
@@ -285,10 +308,15 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) | |||
285 | */ | 308 | */ |
286 | void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | 309 | void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) |
287 | { | 310 | { |
288 | __rpmsg_destroy_ept(ept->rpdev->vrp, ept); | 311 | ept->ops->destroy_ept(ept); |
289 | } | 312 | } |
290 | EXPORT_SYMBOL(rpmsg_destroy_ept); | 313 | EXPORT_SYMBOL(rpmsg_destroy_ept); |
291 | 314 | ||
315 | static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | ||
316 | { | ||
317 | __rpmsg_destroy_ept(ept->rpdev->vrp, ept); | ||
318 | } | ||
319 | |||
292 | /* | 320 | /* |
293 | * when an rpmsg driver is probed with a channel, we seamlessly create | 321 | * when an rpmsg driver is probed with a channel, we seamlessly create |
294 | * it an endpoint, binding its rx callback to a unique local rpmsg | 322 | * it an endpoint, binding its rx callback to a unique local rpmsg |
@@ -657,8 +685,9 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp) | |||
657 | * | 685 | * |
658 | * Returns 0 on success and an appropriate error value on failure. | 686 | * Returns 0 on success and an appropriate error value on failure. |
659 | */ | 687 | */ |
660 | int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev, u32 src, u32 dst, | 688 | static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev, |
661 | void *data, int len, bool wait) | 689 | u32 src, u32 dst, |
690 | void *data, int len, bool wait) | ||
662 | { | 691 | { |
663 | struct virtproc_info *vrp = rpdev->vrp; | 692 | struct virtproc_info *vrp = rpdev->vrp; |
664 | struct device *dev = &rpdev->dev; | 693 | struct device *dev = &rpdev->dev; |
@@ -754,6 +783,56 @@ out: | |||
754 | } | 783 | } |
755 | EXPORT_SYMBOL(rpmsg_send_offchannel_raw); | 784 | EXPORT_SYMBOL(rpmsg_send_offchannel_raw); |
756 | 785 | ||
786 | static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) | ||
787 | { | ||
788 | struct rpmsg_device *rpdev = ept->rpdev; | ||
789 | u32 src = ept->addr, dst = rpdev->dst; | ||
790 | |||
791 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
792 | } | ||
793 | |||
794 | static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, | ||
795 | u32 dst) | ||
796 | { | ||
797 | struct rpmsg_device *rpdev = ept->rpdev; | ||
798 | u32 src = ept->addr; | ||
799 | |||
800 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
801 | } | ||
802 | |||
803 | static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, | ||
804 | u32 dst, void *data, int len) | ||
805 | { | ||
806 | struct rpmsg_device *rpdev = ept->rpdev; | ||
807 | |||
808 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
809 | } | ||
810 | |||
811 | static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) | ||
812 | { | ||
813 | struct rpmsg_device *rpdev = ept->rpdev; | ||
814 | u32 src = ept->addr, dst = rpdev->dst; | ||
815 | |||
816 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
817 | } | ||
818 | |||
819 | static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, | ||
820 | int len, u32 dst) | ||
821 | { | ||
822 | struct rpmsg_device *rpdev = ept->rpdev; | ||
823 | u32 src = ept->addr; | ||
824 | |||
825 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
826 | } | ||
827 | |||
828 | static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, | ||
829 | u32 dst, void *data, int len) | ||
830 | { | ||
831 | struct rpmsg_device *rpdev = ept->rpdev; | ||
832 | |||
833 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
834 | } | ||
835 | |||
757 | static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, | 836 | static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev, |
758 | struct rpmsg_hdr *msg, unsigned int len) | 837 | struct rpmsg_hdr *msg, unsigned int len) |
759 | { | 838 | { |
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 9fdcfc7c7837..d54458effd54 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h | |||
@@ -96,8 +96,10 @@ enum rpmsg_ns_flags { | |||
96 | #define RPMSG_ADDR_ANY 0xFFFFFFFF | 96 | #define RPMSG_ADDR_ANY 0xFFFFFFFF |
97 | 97 | ||
98 | struct virtproc_info; | 98 | struct virtproc_info; |
99 | struct rpmsg_device; | ||
99 | struct rpmsg_endpoint; | 100 | struct rpmsg_endpoint; |
100 | struct rpmsg_device_ops; | 101 | struct rpmsg_device_ops; |
102 | struct rpmsg_endpoint_ops; | ||
101 | 103 | ||
102 | /** | 104 | /** |
103 | * struct rpmsg_channel_info - channel info representation | 105 | * struct rpmsg_channel_info - channel info representation |
@@ -184,6 +186,36 @@ struct rpmsg_endpoint { | |||
184 | struct mutex cb_lock; | 186 | struct mutex cb_lock; |
185 | u32 addr; | 187 | u32 addr; |
186 | void *priv; | 188 | void *priv; |
189 | |||
190 | const struct rpmsg_endpoint_ops *ops; | ||
191 | }; | ||
192 | |||
193 | /** | ||
194 | * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations | ||
195 | * @destroy_ept: destroy the given endpoint, required | ||
196 | * @send: see @rpmsg_send(), required | ||
197 | * @sendto: see @rpmsg_sendto(), optional | ||
198 | * @send_offchannel: see @rpmsg_send_offchannel(), optional | ||
199 | * @trysend: see @rpmsg_trysend(), required | ||
200 | * @trysendto: see @rpmsg_trysendto(), optional | ||
201 | * @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional | ||
202 | * | ||
203 | * Indirection table for the operations that a rpmsg backend should implement. | ||
204 | * In addition to @destroy_ept, the backend must at least implement @send and | ||
205 | * @trysend, while the variants sending data off-channel are optional. | ||
206 | */ | ||
207 | struct rpmsg_endpoint_ops { | ||
208 | void (*destroy_ept)(struct rpmsg_endpoint *ept); | ||
209 | |||
210 | int (*send)(struct rpmsg_endpoint *ept, void *data, int len); | ||
211 | int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); | ||
212 | int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst, | ||
213 | void *data, int len); | ||
214 | |||
215 | int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len); | ||
216 | int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst); | ||
217 | int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst, | ||
218 | void *data, int len); | ||
187 | }; | 219 | }; |
188 | 220 | ||
189 | /** | 221 | /** |
@@ -210,8 +242,6 @@ void rpmsg_destroy_ept(struct rpmsg_endpoint *); | |||
210 | struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *, | 242 | struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *, |
211 | rpmsg_rx_cb_t cb, void *priv, | 243 | rpmsg_rx_cb_t cb, void *priv, |
212 | struct rpmsg_channel_info chinfo); | 244 | struct rpmsg_channel_info chinfo); |
213 | int | ||
214 | rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool); | ||
215 | 245 | ||
216 | /* use a macro to avoid include chaining to get THIS_MODULE */ | 246 | /* use a macro to avoid include chaining to get THIS_MODULE */ |
217 | #define register_rpmsg_driver(drv) \ | 247 | #define register_rpmsg_driver(drv) \ |
@@ -249,10 +279,7 @@ rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool); | |||
249 | */ | 279 | */ |
250 | static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) | 280 | static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) |
251 | { | 281 | { |
252 | struct rpmsg_device *rpdev = ept->rpdev; | 282 | return ept->ops->send(ept, data, len); |
253 | u32 src = ept->addr, dst = rpdev->dst; | ||
254 | |||
255 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
256 | } | 283 | } |
257 | 284 | ||
258 | /** | 285 | /** |
@@ -276,10 +303,7 @@ static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len) | |||
276 | static inline | 303 | static inline |
277 | int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) | 304 | int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) |
278 | { | 305 | { |
279 | struct rpmsg_device *rpdev = ept->rpdev; | 306 | return ept->ops->sendto(ept, data, len, dst); |
280 | u32 src = ept->addr; | ||
281 | |||
282 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
283 | } | 307 | } |
284 | 308 | ||
285 | /** | 309 | /** |
@@ -306,9 +330,7 @@ static inline | |||
306 | int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, | 330 | int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, |
307 | void *data, int len) | 331 | void *data, int len) |
308 | { | 332 | { |
309 | struct rpmsg_device *rpdev = ept->rpdev; | 333 | return ept->ops->send_offchannel(ept, src, dst, data, len); |
310 | |||
311 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true); | ||
312 | } | 334 | } |
313 | 335 | ||
314 | /** | 336 | /** |
@@ -331,10 +353,7 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, | |||
331 | static inline | 353 | static inline |
332 | int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) | 354 | int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) |
333 | { | 355 | { |
334 | struct rpmsg_device *rpdev = ept->rpdev; | 356 | return ept->ops->trysend(ept, data, len); |
335 | u32 src = ept->addr, dst = rpdev->dst; | ||
336 | |||
337 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
338 | } | 357 | } |
339 | 358 | ||
340 | /** | 359 | /** |
@@ -357,10 +376,7 @@ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len) | |||
357 | static inline | 376 | static inline |
358 | int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) | 377 | int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst) |
359 | { | 378 | { |
360 | struct rpmsg_device *rpdev = ept->rpdev; | 379 | return ept->ops->trysendto(ept, data, len, dst); |
361 | u32 src = ept->addr; | ||
362 | |||
363 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
364 | } | 380 | } |
365 | 381 | ||
366 | /** | 382 | /** |
@@ -386,9 +402,7 @@ static inline | |||
386 | int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, | 402 | int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, |
387 | void *data, int len) | 403 | void *data, int len) |
388 | { | 404 | { |
389 | struct rpmsg_device *rpdev = ept->rpdev; | 405 | return ept->ops->trysend_offchannel(ept, src, dst, data, len); |
390 | |||
391 | return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false); | ||
392 | } | 406 | } |
393 | 407 | ||
394 | #endif /* _LINUX_RPMSG_H */ | 408 | #endif /* _LINUX_RPMSG_H */ |