diff options
| -rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 25 | ||||
| -rw-r--r-- | include/linux/rpmsg.h | 3 |
2 files changed, 22 insertions, 6 deletions
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 9623327ba509..39d3aa41adda 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
| @@ -227,6 +227,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, | |||
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | kref_init(&ept->refcount); | 229 | kref_init(&ept->refcount); |
| 230 | mutex_init(&ept->cb_lock); | ||
| 230 | 231 | ||
| 231 | ept->rpdev = rpdev; | 232 | ept->rpdev = rpdev; |
| 232 | ept->cb = cb; | 233 | ept->cb = cb; |
| @@ -324,10 +325,16 @@ EXPORT_SYMBOL(rpmsg_create_ept); | |||
| 324 | static void | 325 | static void |
| 325 | __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) | 326 | __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) |
| 326 | { | 327 | { |
| 328 | /* make sure new inbound messages can't find this ept anymore */ | ||
| 327 | mutex_lock(&vrp->endpoints_lock); | 329 | mutex_lock(&vrp->endpoints_lock); |
| 328 | idr_remove(&vrp->endpoints, ept->addr); | 330 | idr_remove(&vrp->endpoints, ept->addr); |
| 329 | mutex_unlock(&vrp->endpoints_lock); | 331 | mutex_unlock(&vrp->endpoints_lock); |
| 330 | 332 | ||
| 333 | /* make sure in-flight inbound messages won't invoke cb anymore */ | ||
| 334 | mutex_lock(&ept->cb_lock); | ||
| 335 | ept->cb = NULL; | ||
| 336 | mutex_unlock(&ept->cb_lock); | ||
| 337 | |||
| 331 | kref_put(&ept->refcount, __ept_release); | 338 | kref_put(&ept->refcount, __ept_release); |
| 332 | } | 339 | } |
| 333 | 340 | ||
| @@ -821,14 +828,20 @@ static void rpmsg_recv_done(struct virtqueue *rvq) | |||
| 821 | 828 | ||
| 822 | mutex_unlock(&vrp->endpoints_lock); | 829 | mutex_unlock(&vrp->endpoints_lock); |
| 823 | 830 | ||
| 824 | if (ept && ept->cb) | 831 | if (ept) { |
| 825 | ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src); | 832 | /* make sure ept->cb doesn't go away while we use it */ |
| 826 | else | 833 | mutex_lock(&ept->cb_lock); |
| 827 | dev_warn(dev, "msg received with no recepient\n"); | ||
| 828 | 834 | ||
| 829 | /* farewell, ept, we don't need you anymore */ | 835 | if (ept->cb) |
| 830 | if (ept) | 836 | ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, |
| 837 | msg->src); | ||
| 838 | |||
| 839 | mutex_unlock(&ept->cb_lock); | ||
| 840 | |||
| 841 | /* farewell, ept, we don't need you anymore */ | ||
| 831 | kref_put(&ept->refcount, __ept_release); | 842 | kref_put(&ept->refcount, __ept_release); |
| 843 | } else | ||
| 844 | dev_warn(dev, "msg received with no recepient\n"); | ||
| 832 | 845 | ||
| 833 | /* publish the real size of the buffer */ | 846 | /* publish the real size of the buffer */ |
| 834 | sg_init_one(&sg, msg, RPMSG_BUF_SIZE); | 847 | sg_init_one(&sg, msg, RPMSG_BUF_SIZE); |
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index 195f373590b8..82a673905edb 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/device.h> | 39 | #include <linux/device.h> |
| 40 | #include <linux/mod_devicetable.h> | 40 | #include <linux/mod_devicetable.h> |
| 41 | #include <linux/kref.h> | 41 | #include <linux/kref.h> |
| 42 | #include <linux/mutex.h> | ||
| 42 | 43 | ||
| 43 | /* The feature bitmap for virtio rpmsg */ | 44 | /* The feature bitmap for virtio rpmsg */ |
| 44 | #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ | 45 | #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ |
| @@ -123,6 +124,7 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32); | |||
| 123 | * @rpdev: rpmsg channel device | 124 | * @rpdev: rpmsg channel device |
| 124 | * @refcount: when this drops to zero, the ept is deallocated | 125 | * @refcount: when this drops to zero, the ept is deallocated |
| 125 | * @cb: rx callback handler | 126 | * @cb: rx callback handler |
| 127 | * @cb_lock: must be taken before accessing/changing @cb | ||
| 126 | * @addr: local rpmsg address | 128 | * @addr: local rpmsg address |
| 127 | * @priv: private data for the driver's use | 129 | * @priv: private data for the driver's use |
| 128 | * | 130 | * |
| @@ -144,6 +146,7 @@ struct rpmsg_endpoint { | |||
| 144 | struct rpmsg_channel *rpdev; | 146 | struct rpmsg_channel *rpdev; |
| 145 | struct kref refcount; | 147 | struct kref refcount; |
| 146 | rpmsg_rx_cb_t cb; | 148 | rpmsg_rx_cb_t cb; |
| 149 | struct mutex cb_lock; | ||
| 147 | u32 addr; | 150 | u32 addr; |
| 148 | void *priv; | 151 | void *priv; |
| 149 | }; | 152 | }; |
