From: Matthew Wilcox Date: Tue, 8 Jan 2019 17:07:21 +0000 (-0500) Subject: rpmsg: Convert lcids to XArray X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=b7a72f69a8e76bbe66742ad1669dc4c779047a35;p=users%2Fwilly%2Fxarray.git rpmsg: Convert lcids to XArray Signed-off-by: Matthew Wilcox --- diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index f46c787733e8..a177d13a1c4e 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include "rpmsg_internal.h" @@ -26,9 +27,6 @@ #define GLINK_NAME_SIZE 32 #define GLINK_VERSION_1 1 -#define RPM_GLINK_CID_MIN 1 -#define RPM_GLINK_CID_MAX 65536 - struct glink_msg { __le16 cmd; __le16 param1; @@ -87,8 +85,8 @@ struct glink_core_rx_intent { * @rx_lock: protects the @rx_queue * @rx_queue: queue of received control messages to be processed in @rx_work * @tx_lock: synchronizes operations on the tx fifo - * @idr_lock: synchronizes @lcids and @rcids modifications - * @lcids: idr of all channels with a known local channel id + * @idr_lock: synchronizes @rcids modifications + * @lcids: all channels with a known local channel id * @rcids: idr of all channels with a known remote channel id * @features: remote features * @intentless: flag to indicate that there is no intent @@ -113,7 +111,8 @@ struct qcom_glink { spinlock_t tx_lock; spinlock_t idr_lock; - struct idr lcids; + u32 lcid_next; + struct xarray lcids; struct idr rcids; unsigned long features; @@ -391,37 +390,25 @@ static int qcom_glink_send_open_req(struct qcom_glink *glink, int name_len = strlen(channel->name) + 1; int req_len = ALIGN(sizeof(req.msg) + name_len, 8); int ret; - unsigned long flags; kref_get(&channel->refcount); - spin_lock_irqsave(&glink->idr_lock, flags); - ret = idr_alloc_cyclic(&glink->lcids, channel, - RPM_GLINK_CID_MIN, RPM_GLINK_CID_MAX, - GFP_ATOMIC); - spin_unlock_irqrestore(&glink->idr_lock, flags); + ret = xa_alloc_cyclic_irq(&glink->lcids, &channel->lcid, channel, + XA_LIMIT(1, 65535), &glink->lcid_next, GFP_KERNEL); if (ret < 0) return ret; - channel->lcid = ret; - req.msg.cmd = cpu_to_le16(RPM_CMD_OPEN); req.msg.param1 = cpu_to_le16(channel->lcid); req.msg.param2 = cpu_to_le32(name_len); strcpy(req.name, channel->name); ret = qcom_glink_tx(glink, &req, req_len, NULL, 0, true); - if (ret) - goto remove_idr; - - return 0; + if (!ret) + return 0; -remove_idr: - spin_lock_irqsave(&glink->idr_lock, flags); - idr_remove(&glink->lcids, channel->lcid); + xa_erase_irq(&glink->lcids, channel->lcid); channel->lcid = 0; - spin_unlock_irqrestore(&glink->idr_lock, flags); - return ret; } @@ -941,9 +928,7 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) { struct glink_channel *channel; - spin_lock(&glink->idr_lock); - channel = idr_find(&glink->lcids, lcid); - spin_unlock(&glink->idr_lock); + channel = xa_load(&glink->lcids, lcid); if (!channel) { dev_err(glink->dev, "Invalid open ack packet\n"); return -EINVAL; @@ -1034,7 +1019,6 @@ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink, { struct glink_channel *channel; int ret; - unsigned long flags; channel = qcom_glink_alloc_channel(glink, name); if (IS_ERR(channel)) @@ -1058,9 +1042,7 @@ static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink, err_timeout: /* qcom_glink_send_open_req() did register the channel in lcids*/ - spin_lock_irqsave(&glink->idr_lock, flags); - idr_remove(&glink->lcids, channel->lcid); - spin_unlock_irqrestore(&glink->idr_lock, flags); + xa_erase_irq(&glink->lcids, channel->lcid); release_channel: /* Release qcom_glink_send_open_req() reference */ @@ -1363,16 +1345,15 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, struct rpmsg_device *rpdev; bool create_device = false; struct device_node *node; - int lcid; + unsigned long lcid; int ret; - unsigned long flags; - spin_lock_irqsave(&glink->idr_lock, flags); - idr_for_each_entry(&glink->lcids, channel, lcid) { + xa_lock_irq(&glink->lcids); + xa_for_each(&glink->lcids, lcid, channel) { if (!strcmp(channel->name, name)) break; } - spin_unlock_irqrestore(&glink->idr_lock, flags); + xa_unlock_irq(&glink->lcids); if (!channel) { channel = qcom_glink_alloc_channel(glink, name); @@ -1383,15 +1364,15 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, create_device = true; } - spin_lock_irqsave(&glink->idr_lock, flags); + spin_lock_irq(&glink->idr_lock); ret = idr_alloc(&glink->rcids, channel, rcid, rcid + 1, GFP_ATOMIC); if (ret < 0) { dev_err(glink->dev, "Unable to insert channel into rcid list\n"); - spin_unlock_irqrestore(&glink->idr_lock, flags); + spin_unlock_irq(&glink->idr_lock); goto free_channel; } channel->rcid = ret; - spin_unlock_irqrestore(&glink->idr_lock, flags); + spin_unlock_irq(&glink->idr_lock); complete(&channel->open_req); @@ -1425,10 +1406,10 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, free_rpdev: kfree(rpdev); rcid_remove: - spin_lock_irqsave(&glink->idr_lock, flags); + spin_lock_irq(&glink->idr_lock); idr_remove(&glink->rcids, channel->rcid); channel->rcid = 0; - spin_unlock_irqrestore(&glink->idr_lock, flags); + spin_unlock_irq(&glink->idr_lock); free_channel: /* Release the reference, iff we took it */ if (create_device) @@ -1475,17 +1456,13 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) struct glink_channel *channel; unsigned long flags; - spin_lock_irqsave(&glink->idr_lock, flags); - channel = idr_find(&glink->lcids, lcid); - if (WARN(!channel, "close ack on unknown channel\n")) { - spin_unlock_irqrestore(&glink->idr_lock, flags); + xa_lock_irqsave(&glink->lcids, flags); + channel = __xa_erase(&glink->lcids, lcid); + xa_unlock_irqrestore(&glink->lcids, flags); + if (WARN(!channel, "close ack on unknown channel\n")) return; - } - idr_remove(&glink->lcids, channel->lcid); channel->lcid = 0; - spin_unlock_irqrestore(&glink->idr_lock, flags); - kref_put(&channel->refcount, qcom_glink_channel_release); } @@ -1571,7 +1548,8 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, INIT_WORK(&glink->rx_work, qcom_glink_work); spin_lock_init(&glink->idr_lock); - idr_init(&glink->lcids); + xa_init_flags(&glink->lcids, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); + glink->lcid_next = 0; idr_init(&glink->rcids); ret = of_property_read_string(dev->of_node, "label", &glink->name); @@ -1617,7 +1595,7 @@ static int qcom_glink_remove_device(struct device *dev, void *data) void qcom_glink_native_remove(struct qcom_glink *glink) { struct glink_channel *channel; - int cid; + unsigned long cid; int ret; unsigned long flags; @@ -1628,14 +1606,14 @@ void qcom_glink_native_remove(struct qcom_glink *glink) if (ret) dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); - spin_lock_irqsave(&glink->idr_lock, flags); + xa_lock_irqsave(&glink->lcids, flags); /* Release any defunct local channels, waiting for close-ack */ - idr_for_each_entry(&glink->lcids, channel, cid) + xa_for_each(&glink->lcids, cid, channel) kref_put(&channel->refcount, qcom_glink_channel_release); + xa_unlock_irqrestore(&glink->lcids, flags); - idr_destroy(&glink->lcids); + xa_destroy(&glink->lcids); idr_destroy(&glink->rcids); - spin_unlock_irqrestore(&glink->idr_lock, flags); mbox_free_channel(glink->mbox_chan); } EXPORT_SYMBOL_GPL(qcom_glink_native_remove);