]> www.infradead.org Git - users/willy/xarray.git/commitdiff
rpmsg: Convert endpoints to XArray
authorMatthew Wilcox <willy@infradead.org>
Mon, 18 Feb 2019 21:56:39 +0000 (16:56 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 9 Aug 2019 01:38:18 +0000 (21:38 -0400)
Signed-off-by: Matthew Wilcox <willy@infradead.org>
drivers/rpmsg/virtio_rpmsg_bus.c

index 5d3685bd76a2d82f5a25df2928203306e17ee526..9e6994f616697f99e5032680bdf606fccfa8f9ff 100644 (file)
@@ -43,8 +43,7 @@
  * @tx_lock:   protects svq, sbufs and sleepers, to allow concurrent senders.
  *             sending a message might require waking up a dozing remote
  *             processor, which involves sleeping, hence the mutex.
- * @endpoints: idr of local endpoints, allows fast retrieval
- * @endpoints_lock: lock of the endpoints set
+ * @endpoints: local endpoints, allows fast retrieval
  * @sendq:     wait queue of sending contexts waiting for a tx buffers
  * @sleepers:  number of senders that are waiting for a tx buffer
  * @ns_ept:    the bus's name service endpoint
@@ -62,8 +61,7 @@ struct virtproc_info {
        int last_sbuf;
        dma_addr_t bufs_dma;
        struct mutex tx_lock;
-       struct idr endpoints;
-       struct mutex endpoints_lock;
+       struct xarray endpoints;
        wait_queue_head_t sendq;
        atomic_t sleepers;
        struct rpmsg_endpoint *ns_ept;
@@ -234,9 +232,9 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
                                                 rpmsg_rx_cb_t cb,
                                                 void *priv, u32 addr)
 {
-       int id_min, id_max, id;
        struct rpmsg_endpoint *ept;
        struct device *dev = rpdev ? &rpdev->dev : &vrp->vdev->dev;
+       int err;
 
        ept = kzalloc(sizeof(*ept), GFP_KERNEL);
        if (!ept)
@@ -250,33 +248,23 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
        ept->priv = priv;
        ept->ops = &virtio_endpoint_ops;
 
-       /* do we need to allocate a local address ? */
+       /* bind the endpoint to an rpmsg address (and allocate one if needed) */
        if (addr == RPMSG_ADDR_ANY) {
-               id_min = RPMSG_RESERVED_ADDRESSES;
-               id_max = 0;
+               err = xa_alloc(&vrp->endpoints, &ept->addr, ept,
+                               XA_LIMIT(RPMSG_RESERVED_ADDRESSES, INT_MAX),
+                               GFP_KERNEL);
        } else {
-               id_min = addr;
-               id_max = addr + 1;
+               ept->addr = addr;
+               err = xa_insert(&vrp->endpoints, addr, ept, GFP_KERNEL);
        }
 
-       mutex_lock(&vrp->endpoints_lock);
-
-       /* bind the endpoint to an rpmsg address (and allocate one if needed) */
-       id = idr_alloc(&vrp->endpoints, ept, id_min, id_max, GFP_KERNEL);
-       if (id < 0) {
-               dev_err(dev, "idr_alloc failed: %d\n", id);
-               goto free_ept;
+       if (err < 0) {
+               dev_err(dev, "address busy: %d\n", err);
+               kref_put(&ept->refcount, __ept_release);
+               ept = NULL;
        }
-       ept->addr = id;
-
-       mutex_unlock(&vrp->endpoints_lock);
 
        return ept;
-
-free_ept:
-       mutex_unlock(&vrp->endpoints_lock);
-       kref_put(&ept->refcount, __ept_release);
-       return NULL;
 }
 
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
@@ -303,9 +291,7 @@ 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);
+       xa_erase(&vrp->endpoints, ept->addr);
 
        /* make sure in-flight inbound messages won't invoke cb anymore */
        mutex_lock(&ept->cb_lock);
@@ -724,15 +710,13 @@ static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
        }
 
        /* use the dst addr to fetch the callback of the appropriate user */
-       mutex_lock(&vrp->endpoints_lock);
-
-       ept = idr_find(&vrp->endpoints, msg->dst);
+       xa_lock(&vrp->endpoints);
+       ept = xa_load(&vrp->endpoints, msg->dst);
 
        /* let's make sure no one deallocates ept while we use it */
        if (ept)
                kref_get(&ept->refcount);
-
-       mutex_unlock(&vrp->endpoints_lock);
+       xa_unlock(&vrp->endpoints);
 
        if (ept) {
                /* make sure ept->cb doesn't go away while we use it */
@@ -884,8 +868,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
 
        vrp->vdev = vdev;
 
-       idr_init(&vrp->endpoints);
-       mutex_init(&vrp->endpoints_lock);
+       xa_init_flags(&vrp->endpoints, XA_FLAGS_ALLOC);
        mutex_init(&vrp->tx_lock);
        init_waitqueue_head(&vrp->sendq);
 
@@ -1011,8 +994,6 @@ static void rpmsg_remove(struct virtio_device *vdev)
        if (vrp->ns_ept)
                __rpmsg_destroy_ept(vrp, vrp->ns_ept);
 
-       idr_destroy(&vrp->endpoints);
-
        vdev->config->del_vqs(vrp->vdev);
 
        dma_free_coherent(vdev->dev.parent, total_buf_space,