}
kref_init(&ept->refcount);
+ mutex_init(&ept->cb_lock);
ept->rpdev = rpdev;
ept->cb = cb;
static void
__rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
{
+ /* make sure new inbound messages can't find this ept anymore */
mutex_lock(&vrp->endpoints_lock);
idr_remove(&vrp->endpoints, ept->addr);
mutex_unlock(&vrp->endpoints_lock);
+ /* make sure in-flight inbound messages won't invoke cb anymore */
+ mutex_lock(&ept->cb_lock);
+ ept->cb = NULL;
+ mutex_unlock(&ept->cb_lock);
+
kref_put(&ept->refcount, __ept_release);
}
mutex_unlock(&vrp->endpoints_lock);
- if (ept && ept->cb)
- ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src);
- else
- dev_warn(dev, "msg received with no recepient\n");
+ if (ept) {
+ /* make sure ept->cb doesn't go away while we use it */
+ mutex_lock(&ept->cb_lock);
- /* farewell, ept, we don't need you anymore */
- if (ept)
+ if (ept->cb)
+ ept->cb(ept->rpdev, msg->data, msg->len, ept->priv,
+ msg->src);
+
+ mutex_unlock(&ept->cb_lock);
+
+ /* farewell, ept, we don't need you anymore */
kref_put(&ept->refcount, __ept_release);
+ } else
+ dev_warn(dev, "msg received with no recepient\n");
/* publish the real size of the buffer */
sg_init_one(&sg, msg, RPMSG_BUF_SIZE);
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/kref.h>
+#include <linux/mutex.h>
/* The feature bitmap for virtio rpmsg */
#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */
* @rpdev: rpmsg channel device
* @refcount: when this drops to zero, the ept is deallocated
* @cb: rx callback handler
+ * @cb_lock: must be taken before accessing/changing @cb
* @addr: local rpmsg address
* @priv: private data for the driver's use
*
struct rpmsg_channel *rpdev;
struct kref refcount;
rpmsg_rx_cb_t cb;
+ struct mutex cb_lock;
u32 addr;
void *priv;
};