]> www.infradead.org Git - users/willy/xarray.git/commitdiff
rpmsg; Convert liids to XArray
authorMatthew Wilcox <willy@infradead.org>
Tue, 8 Jan 2019 17:50:33 +0000 (12:50 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Fri, 9 Aug 2019 01:38:14 +0000 (21:38 -0400)
Signed-off-by: Matthew Wilcox <willy@infradead.org>
drivers/rpmsg/qcom_glink_native.c

index 48fb7195d9b3fc4f896f363706480cb353354e9e..acd486d18bd8c6675aec33ed1620443fa492ff54 100644 (file)
@@ -134,8 +134,8 @@ enum {
  * @name:      unique channel name/identifier
  * @lcid:      channel id, in local space
  * @rcid:      channel id, in remote space
- * @intent_lock: lock for protection of @liids, @riids
- * @liids:     idr of all local intents
+ * @intent_lock: lock for protection of @riids
+ * @liids:     all local intents
  * @riids:     idr of all remote intents
  * @intent_work: worker responsible for transmitting rx_done packets
  * @done_intents: list of intents that needs to be announced rx_done
@@ -163,9 +163,10 @@ struct glink_channel {
        unsigned int rcid;
 
        spinlock_t intent_lock;
-       struct idr liids;
+       struct xarray liids;
        struct idr riids;
        struct work_struct intent_work;
+       u32 liid_next;
        struct list_head done_intents;
 
        struct glink_core_rx_intent *buf;
@@ -227,7 +228,8 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
        INIT_LIST_HEAD(&channel->done_intents);
        INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work);
 
-       idr_init(&channel->liids);
+       xa_init_flags(&channel->liids, XA_FLAGS_ALLOC1 | XA_FLAGS_LOCK_IRQ);
+       channel->liid_next = 1;
        idr_init(&channel->riids);
        kref_init(&channel->refcount);
 
@@ -240,8 +242,8 @@ static void qcom_glink_channel_release(struct kref *ref)
                                                     refcount);
        unsigned long flags;
 
+       xa_destroy(&channel->liids);
        spin_lock_irqsave(&channel->intent_lock, flags);
-       idr_destroy(&channel->liids);
        idr_destroy(&channel->riids);
        spin_unlock_irqrestore(&channel->intent_lock, flags);
 
@@ -484,11 +486,8 @@ static void qcom_glink_rx_done(struct qcom_glink *glink,
        }
 
        /* Take it off the tree of receive intents */
-       if (!intent->reuse) {
-               spin_lock(&channel->intent_lock);
-               idr_remove(&channel->liids, intent->id);
-               spin_unlock(&channel->intent_lock);
-       }
+       if (!intent->reuse)
+               xa_erase(&channel->liids, intent->id);
 
        /* Schedule the sending of a rx_done indication */
        spin_lock(&channel->intent_lock);
@@ -620,7 +619,6 @@ qcom_glink_alloc_intent(struct qcom_glink *glink,
 {
        struct glink_core_rx_intent *intent;
        int ret;
-       unsigned long flags;
 
        intent = kzalloc(sizeof(*intent), GFP_KERNEL);
        if (!intent)
@@ -630,15 +628,11 @@ qcom_glink_alloc_intent(struct qcom_glink *glink,
        if (!intent->data)
                goto free_intent;
 
-       spin_lock_irqsave(&channel->intent_lock, flags);
-       ret = idr_alloc_cyclic(&channel->liids, intent, 1, -1, GFP_ATOMIC);
-       if (ret < 0) {
-               spin_unlock_irqrestore(&channel->intent_lock, flags);
+       ret = xa_alloc_cyclic_irq(&channel->liids, &intent->id, intent,
+                       xa_limit_32b, &channel->liid_next, GFP_KERNEL);
+       if (ret < 0)
                goto free_data;
-       }
-       spin_unlock_irqrestore(&channel->intent_lock, flags);
 
-       intent->id = ret;
        intent->size = size;
        intent->reuse = reuseable;
 
@@ -758,7 +752,6 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
        unsigned int rcid;
        unsigned int liid;
        int ret = 0;
-       unsigned long flags;
 
        if (avail < sizeof(hdr)) {
                dev_dbg(glink->dev, "Not enough data in fifo\n");
@@ -807,11 +800,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
                }
        } else {
                liid = le32_to_cpu(hdr.msg.param2);
-
-               spin_lock_irqsave(&channel->intent_lock, flags);
-               intent = idr_find(&channel->liids, liid);
-               spin_unlock_irqrestore(&channel->intent_lock, flags);
-
+               intent = xa_load(&channel->liids, liid);
                if (!intent) {
                        dev_err(glink->dev,
                                "no intent found for channel %s intent %d",