]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/rpmsg/virtio_rpmsg_bus.c
Merge tag 'kvm-3.6-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[karo-tx-linux.git] / drivers / rpmsg / virtio_rpmsg_bus.c
index 9623327ba5094ed63016fe474b2827d7738ea99d..f56c8ba3a861cda16870e7456391fe564ec741c6 100644 (file)
@@ -227,6 +227,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
        }
 
        kref_init(&ept->refcount);
+       mutex_init(&ept->cb_lock);
 
        ept->rpdev = rpdev;
        ept->cb = cb;
@@ -324,10 +325,16 @@ EXPORT_SYMBOL(rpmsg_create_ept);
 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);
 }
 
@@ -821,14 +828,20 @@ static void rpmsg_recv_done(struct virtqueue *rvq)
 
        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);
@@ -1072,7 +1085,7 @@ static int __init rpmsg_init(void)
 
        return ret;
 }
-module_init(rpmsg_init);
+subsys_initcall(rpmsg_init);
 
 static void __exit rpmsg_fini(void)
 {