From patchwork Wed Aug 16 17:19:03 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 9904393 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id D068E60244 for ; Wed, 16 Aug 2017 17:32:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B942528946 for ; Wed, 16 Aug 2017 17:32:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AE29E28A50; Wed, 16 Aug 2017 17:32:37 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 0E78F28949 for ; Wed, 16 Aug 2017 17:32:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=dmB38Y7NY8MjU39vFtYe8Yrhj4pyMmChjeI3ow0t/PE=; b=bo97EX1O9WLI1UaS9c1Wyp/IPs mxkPt1EFIOv8d7tMeWwyln81273j0kiwqTeoVXQF5wrcvV+SsMbzL+mYFqTdRTn4LHUBcqEupEauk sAMfji6QmbYakj1fTET84YMq/I6rB9ROowf2qkckr7PJJflYyHhDUSmaDLL1xbBsoQuRNwbJU7jin MymOdiVluMBRtuGDXCAiw9XL/aHIelAcQ8209QH8dEIU+888prOfx/lQjb59atuczRaGGv33jg6vB myl1sHLpXF00Ddm4ypqoutfdJuVyt5C4Z6icLRne6XLHg2HM4JBfRHYnaEsl0DbhUI0VTsYalBjNg lv6bTMoA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1di2BC-0002GD-U3; Wed, 16 Aug 2017 17:32:30 +0000 Received: from casper.infradead.org ([85.118.1.10]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1di2BA-00026t-32 for linux-arm-kernel@bombadil.infradead.org; Wed, 16 Aug 2017 17:32:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=fdIp5/Uo81lVqaK+jGV8zYB35nR7h3Ry5+4wmDJ9P/0=; b=eHTzRTcHs2DZ1DlM4uHtvFC3b YQmLPE0R771NRvw03BCjJ3UEgDrVZIWsJ5ZmELORYHVFxuSCk9cdM6I3yccnwrSM1iapv1B3C9E1x Z3u4c2eYm/OhpfUbYp+5mGHaAwLyXjryNoV/Pf7fwhejTMGd8e4gQLc4CVjVmgj4n179sMIJGC0pi 0tv6OSY6LDzeyGNEIug/MpF8TRmFKrz5Q+nCVB29NFkC8plk1JuHT1y2pATyFFmq+mS06pUBup53x DEt0tjpqul/eQj+/LriRJDaRHIj0tp+LdF39Ba3Cy5MF3gJ/xRxGt8ucB5IQqlLaIvm/cCDUq9EHk G8FXtITDw==; Received: from smtp.codeaurora.org ([198.145.29.96]) by casper.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1di209-0004xW-5t for linux-arm-kernel@lists.infradead.org; Wed, 16 Aug 2017 17:21:07 +0000 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 3B10F60722; Wed, 16 Aug 2017 17:20:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502904038; bh=ApaS+/9c26ME1m6OfRZi8nqJX9nogXSD8Cju4RZ09J0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L1koQRVdBxlrha+bHmGz83YOtLbKBPSTXIHC0eduyLSPUT/6ACpLh80JtAraSXAST BUS895sOqAE8SgwbTrox2MDaCVDgdphzBsdlkZzbagYz4MC1+LPBf40XAvKcC17mZb EzXm+nzVqv5GLj2Hf2o0Si0i5IKZT9LPJFhJ8INA= Received: from srichara-linux.qualcomm.com (blr-c-bdr-fw-01_globalnat_allzones-outside.qualcomm.com [103.229.19.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: sricharan@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 153CB6081B; Wed, 16 Aug 2017 17:19:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903998; bh=ApaS+/9c26ME1m6OfRZi8nqJX9nogXSD8Cju4RZ09J0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=khRnc8Gkyh7CEHjj9KjuDGGcPeMs1wT6+bnbEksoHQAMduu5A78TLgY4iD2iSFKxF lAQirl++0LhWyp0axv8kjvG1sMCHl5cXXLrRcYdeTudYwuf88gNc2E7u89y6MgRVSy 0pOqw1v20MTVp/+1FgU/C+eUoVQ0PlCW8VHd6qHg= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 153CB6081B Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=sricharan@codeaurora.org From: Sricharan R To: ohad@wizery.com, bjorn.andersson@linaro.org, linux-remoteproc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 10/18] rpmsg: glink: Add support for TX intents Date: Wed, 16 Aug 2017 22:49:03 +0530 Message-Id: <1502903951-5403-11-git-send-email-sricharan@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1502903951-5403-1-git-send-email-sricharan@codeaurora.org> References: <1502903951-5403-1-git-send-email-sricharan@codeaurora.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170816_182105_493665_4AF662B8 X-CRM114-Status: GOOD ( 30.69 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: sricharan@codeaurora.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Intents are nothing but pre-allocated buffers of appropriate size that are allocated on the local side and communicated to the remote side and the remote stores the list of intent ids that it is informed. Later when remote side is intenting to send data, it picks up a right intent (based on the size) and sends the data buffer and the intent id. Local side receives the data and copies it to the local intent buffer. The whole idea is to avoid stalls on the transport for allocating memory, used for copy based transports. When the remote request to allocate buffers using CMD_RX_INTENT_REQ, we allocate buffers of requested size, store the buffer id locally and also communicate the intent id to the remote. Signed-off-by: Sricharan R Signed-off-by: Bjorn Andersson --- drivers/rpmsg/qcom_glink_native.c | 161 +++++++++++++++++++++++++++++++++++++- drivers/rpmsg/qcom_glink_native.h | 3 +- drivers/rpmsg/qcom_glink_rpm.c | 3 +- drivers/rpmsg/qcom_glink_smem.c | 5 +- 4 files changed, 167 insertions(+), 5 deletions(-) diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index acf5558..cbc9f9e 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -60,6 +60,25 @@ struct glink_defer_cmd { }; /** + * RX intent + * + * data: pointer to the data (may be NULL for zero-copy) + * id: remote or local intent ID + * size: size of the original intent (do not modify) + * reuse: To mark if the intent can be reused after first use + * in_use: To mark if intent is already in use for the channel + * offset: next write offset (initially 0) + */ +struct glink_core_rx_intent { + void *data; + u32 id; + size_t size; + bool reuse; + bool in_use; + u32 offset; +}; + +/** * struct glink_rpm - driver context, relates to one remote subsystem * @dev: reference to the associated struct device * @doorbell: "rpm_hlos" ipc doorbell @@ -116,6 +135,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 + * @liids: idr of all local intents * @buf: receive buffer, for gathering fragments * @buf_offset: write offset in @buf * @buf_size: size of current @buf @@ -136,6 +157,9 @@ struct glink_channel { unsigned int lcid; unsigned int rcid; + spinlock_t intent_lock; + struct idr liids; + void *buf; int buf_offset; int buf_size; @@ -153,6 +177,9 @@ struct glink_channel { #define RPM_CMD_OPEN 2 #define RPM_CMD_CLOSE 3 #define RPM_CMD_OPEN_ACK 4 +#define RPM_CMD_INTENT 5 +#define RPM_CMD_RX_INTENT_REQ 7 +#define RPM_CMD_RX_INTENT_REQ_ACK 8 #define RPM_CMD_TX_DATA 9 #define RPM_CMD_CLOSE_ACK 11 #define RPM_CMD_TX_DATA_CONT 12 @@ -177,6 +204,7 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, init_completion(&channel->open_req); init_completion(&channel->open_ack); + idr_init(&channel->liids); kref_init(&channel->refcount); return channel; @@ -187,6 +215,7 @@ static void qcom_glink_channel_release(struct kref *ref) struct glink_channel *channel = container_of(ref, struct glink_channel, refcount); + idr_destroy(&channel->liids); kfree(channel->name); kfree(channel); } @@ -423,6 +452,130 @@ static void qcom_glink_receive_version_ack(struct qcom_glink *glink, } } +/** + * qcom_glink_send_intent_req_ack() - convert an rx intent request ack cmd to + wire format and transmit + * @glink: The transport to transmit on. + * @channel: The glink channel + * @granted: The request response to encode. + * + * Return: 0 on success or standard Linux error code. + */ +static int qcom_glink_send_intent_req_ack(struct qcom_glink *glink, + struct glink_channel *channel, + bool granted) +{ + struct glink_msg msg; + + msg.cmd = cpu_to_le16(RPM_CMD_RX_INTENT_REQ_ACK); + msg.param1 = cpu_to_le16(channel->lcid); + msg.param2 = cpu_to_le32(granted); + + qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); + + return 0; +} + +/** + * tx_cmd_local_rx_intent() - convert an rx intent cmd to wire format and + * transmit + * @glink: The transport to transmit on. + * @channel: The local channel + * @size: The intent to pass on to remote. + * + * Return: 0 on success or standard Linux error code. + */ +static int qcom_glink_advertise_intent(struct qcom_glink *glink, + struct glink_channel *channel, + struct glink_core_rx_intent *intent) +{ + struct command { + u16 id; + u16 lcid; + u32 count; + u32 size; + u32 liid; + } __packed; + struct command cmd; + + cmd.id = cpu_to_le16(RPM_CMD_INTENT); + cmd.lcid = cpu_to_le16(channel->lcid); + cmd.count = cpu_to_le32(1); + cmd.size = cpu_to_le32(intent->size); + cmd.liid = cpu_to_le32(intent->id); + + qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true); + + return 0; +} + +static struct glink_core_rx_intent * +qcom_glink_alloc_intent(struct qcom_glink *glink, + struct glink_channel *channel, + size_t size, + bool reuseable) +{ + struct glink_core_rx_intent *intent; + int ret; + unsigned long flags; + + intent = kzalloc(sizeof(*intent), GFP_KERNEL); + + if (!intent) + return NULL; + + intent->data = kzalloc(size, GFP_KERNEL); + if (!intent->data) + return NULL; + + 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); + return NULL; + } + spin_unlock_irqrestore(&channel->intent_lock, flags); + + intent->id = ret; + intent->size = size; + intent->reuse = reuseable; + + return intent; +} + +/** + * glink_core_rx_cmd_remote_rx_intent_req() - Receive a request for rx_intent + * from remote side + * if_ptr: Pointer to the transport interface + * rcid: Remote channel ID + * size: size of the intent + * + * The function searches for the local channel to which the request for + * rx_intent has arrived and allocates and notifies the remote back + */ +static void qcom_glink_handle_intent_req(struct qcom_glink *glink, + u32 cid, size_t size) +{ + struct glink_core_rx_intent *intent; + struct glink_channel *channel; + unsigned long flags; + + spin_lock_irqsave(&glink->idr_lock, flags); + channel = idr_find(&glink->rcids, cid); + spin_unlock_irqrestore(&glink->idr_lock, flags); + + if (!channel) { + pr_err("%s channel not found for cid %d\n", __func__, cid); + return; + } + + intent = qcom_glink_alloc_intent(glink, channel, size, false); + if (intent) + qcom_glink_advertise_intent(glink, channel, intent); + + qcom_glink_send_intent_req_ack(glink, channel, !!intent); +} + static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) { struct glink_defer_cmd *dcmd; @@ -585,6 +738,7 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) case RPM_CMD_VERSION_ACK: case RPM_CMD_CLOSE: case RPM_CMD_CLOSE_ACK: + case RPM_CMD_RX_INTENT_REQ: ret = qcom_glink_rx_defer(glink, 0); break; case RPM_CMD_OPEN_ACK: @@ -1002,6 +1156,9 @@ static void qcom_glink_work(struct work_struct *work) case RPM_CMD_CLOSE_ACK: qcom_glink_rx_close_ack(glink, param1); break; + case RPM_CMD_RX_INTENT_REQ: + qcom_glink_handle_intent_req(glink, param1, param2); + break; default: WARN(1, "Unknown defer object %d\n", cmd); break; @@ -1014,7 +1171,8 @@ static void qcom_glink_work(struct work_struct *work) struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, struct qcom_glink_pipe *rx, - struct qcom_glink_pipe *tx) + struct qcom_glink_pipe *tx, + bool intentless) { int irq; int ret; @@ -1029,6 +1187,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, glink->rx_pipe = rx; glink->features = features; + glink->intentless = intentless; mutex_init(&glink->tx_lock); spin_lock_init(&glink->rx_lock); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index f418787..d7538c3 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -37,7 +37,8 @@ struct qcom_glink_pipe { struct qcom_glink *qcom_glink_native_probe(struct device *dev, unsigned long features, struct qcom_glink_pipe *rx, - struct qcom_glink_pipe *tx); + struct qcom_glink_pipe *tx, + bool intentless); void qcom_glink_native_remove(struct qcom_glink *glink); #endif diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 7d039cd..5a86e08 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -305,7 +305,8 @@ static int glink_rpm_probe(struct platform_device *pdev) glink = qcom_glink_native_probe(&pdev->dev, 0, &rx_pipe->native, - &tx_pipe->native); + &tx_pipe->native, + true); if (IS_ERR(glink)) return PTR_ERR(glink); diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index 496a5e3..e792895 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -278,8 +278,9 @@ struct qcom_glink *qcom_glink_smem_register(struct device *parent, *tx_pipe->head = 0; glink = qcom_glink_native_probe(dev, - GLINK_FEATURE_TRACER_PKT, - &rx_pipe->native, &tx_pipe->native); + GLINK_FEATURE_INTENT_REUSE, + &rx_pipe->native, &tx_pipe->native, + false); if (IS_ERR(glink)) { ret = PTR_ERR(glink); goto err_put_dev;