From patchwork Wed Aug 16 17:18:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 110262 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1066493qge; Wed, 16 Aug 2017 10:19:45 -0700 (PDT) X-Received: by 10.101.73.72 with SMTP id q8mr2255351pgs.219.1502903985001; Wed, 16 Aug 2017 10:19:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502903984; cv=none; d=google.com; s=arc-20160816; b=OQP9++0IPf1kmlmMa/l/Dx8tF/08D+CMRR3bY3hniHMeSTKO5gqkBUToScihwt87UY QL+Dg+tG5te2EU1dRqqsgND6EZVKFhYpa2tc8TChyO3jbul6K2tdazes2y9+FfYZ6X+n 28LjDUNma7KZJaRRWbwmQmfwUX+Qc/wRu5d1a94mZQAMpzVfV5IbyhsxNyDXyodQDfVG ADCvuH3TxmAL3hPo1Y0sJDzCSjo5YqVe3rlr/1NGPkpvlhFi3ZVuhD0xsD1Af2Zobbr4 b8ytxjNs4Q7hx4tCsAFNgv4QKXIqJHbBnBpaSwmvFRqFUSXV7izvAsRyYkVbHaLa6BuI J6mQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=PDPM451OQKLRwwo5C9tMbBmSbsXr1NceLKOz4ncvTF0=; b=GY0A0gj0wlQApoNllZ7yB6PC0g9rjf053/dyjQin/ghTdzqiPMfmuXs27O1BZea/mW IKLWX/bqNL/wMGzlyl5YXuKQhJTKovgHiIFDxQsVuX80zm27deKImFv04akQKSkER+m3 RGTlkujvpeq7BJJ6RJbmM+uRulkbwxy0XJ+iiDU2BgEogQrBB8i5JebhDVstHt3B/42I 4tBaBfOUWj0p1ydpDjZm30NwATPBRc0rKLvU/xf+NLdBk6eXU6UdVh1WwvkXs/Ev1Otc IOZgZDFnB85Cix1MRNKBMy8FJumzq5DGTOSjJvbjDjdWMWFjLs7wc1vFycr5nSKMfBUG 0LVA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=GBbtg2Wg; dkim=pass header.i=@codeaurora.org header.s=default header.b=lAAsgetZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 15si822397pla.449.2017.08.16.10.19.44; Wed, 16 Aug 2017 10:19:44 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=GBbtg2Wg; dkim=pass header.i=@codeaurora.org header.s=default header.b=lAAsgetZ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752663AbdHPRTl (ORCPT + 26 others); Wed, 16 Aug 2017 13:19:41 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:50070 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752627AbdHPRTh (ORCPT ); Wed, 16 Aug 2017 13:19:37 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id BF0326072C; Wed, 16 Aug 2017 17:19:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903976; bh=HhK2TVn1f7DytJ21Te0V8wQY3DJn6kppo1mI50bDlOM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GBbtg2WgWE1J2Y3jcgOUqz1Hplw9x+6tTrRWirqvjK7vJNBsWsqrA0cEUsEaQgEBI xfYRk76yV0roLVSwybFh9PgJVXdAMNKF2ITSh1KWLUSBWismXlf/o5f4ZgSAr7F35O JkBbTXJxbGFVpZ1KuiZ15nPzPnQo0ZncYpAVISw0= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED, T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 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 797436047C; Wed, 16 Aug 2017 17:19:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903971; bh=HhK2TVn1f7DytJ21Te0V8wQY3DJn6kppo1mI50bDlOM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lAAsgetZS6BGGifVurd4etrthIHXOYP0Nny6cUJ54fY1c9nm9sGqwxfkkBKKqEtC+ KjcvOCebZbW7BIdOaRPZYffCxYe4co5x8JM8Lo6Y/JErbdAocHwhPxCgzVTEoAzthX lyRl+X8YireOXSBTWAT32w/HbvJEr+ZkmT6fNHss= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 797436047C 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 Cc: sricharan@codeaurora.org Subject: [PATCH 01/18] rpmsg: glink: Rename glink_rpm_xx functions to qcom_glink_xx Date: Wed, 16 Aug 2017 22:48:54 +0530 Message-Id: <1502903951-5403-2-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> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bjorn Andersson Renaming the glink_rpm_xx functions and structs to qcom_glink_xx equivalents helps to reuse the core glink protocol while adding support for smem based glink transport in the later patches. Signed-off-by: Bjorn Andersson Signed-off-by: Sricharan R --- drivers/rpmsg/qcom_glink_rpm.c | 248 +++++++++++++++++++++-------------------- 1 file changed, 128 insertions(+), 120 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 3559a3e..56a0a66 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -101,7 +101,7 @@ struct glink_defer_cmd { * @lcids: idr of all channels with a known local channel id * @rcids: idr of all channels with a known remote channel id */ -struct glink_rpm { +struct qcom_glink { struct device *dev; struct mbox_client mbox_client; @@ -134,7 +134,7 @@ enum { * struct glink_channel - internal representation of a channel * @rpdev: rpdev reference, only used for primary endpoints * @ept: rpmsg endpoint this channel is associated with - * @glink: glink_rpm context handle + * @glink: qcom_glink context handle * @refcount: refcount for the channel object * @recv_lock: guard for @ept.cb * @name: unique channel name/identifier @@ -150,7 +150,7 @@ struct glink_channel { struct rpmsg_endpoint ept; struct rpmsg_device *rpdev; - struct glink_rpm *glink; + struct qcom_glink *glink; struct kref refcount; @@ -184,8 +184,8 @@ struct glink_channel { #define GLINK_FEATURE_INTENTLESS BIT(1) -static struct glink_channel *glink_rpm_alloc_channel(struct glink_rpm *glink, - const char *name) +static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, + const char *name) { struct glink_channel *channel; @@ -206,7 +206,7 @@ static struct glink_channel *glink_rpm_alloc_channel(struct glink_rpm *glink, return channel; } -static void glink_rpm_channel_release(struct kref *ref) +static void qcom_glink_channel_release(struct kref *ref) { struct glink_channel *channel = container_of(ref, struct glink_channel, refcount); @@ -215,7 +215,7 @@ static void glink_rpm_channel_release(struct kref *ref) kfree(channel); } -static size_t glink_rpm_rx_avail(struct glink_rpm *glink) +static size_t qcom_glink_rx_avail(struct qcom_glink *glink) { struct glink_rpm_pipe *pipe = &glink->rx_pipe; unsigned int head; @@ -230,8 +230,8 @@ static size_t glink_rpm_rx_avail(struct glink_rpm *glink) return head - tail; } -static void glink_rpm_rx_peak(struct glink_rpm *glink, - void *data, size_t count) +static void qcom_glink_rx_peak(struct qcom_glink *glink, + void *data, size_t count) { struct glink_rpm_pipe *pipe = &glink->rx_pipe; unsigned int tail; @@ -251,8 +251,8 @@ static void glink_rpm_rx_peak(struct glink_rpm *glink, } } -static void glink_rpm_rx_advance(struct glink_rpm *glink, - size_t count) +static void qcom_glink_rx_advance(struct qcom_glink *glink, + size_t count) { struct glink_rpm_pipe *pipe = &glink->rx_pipe; unsigned int tail; @@ -266,7 +266,7 @@ static void glink_rpm_rx_advance(struct glink_rpm *glink, writel(tail, pipe->tail); } -static size_t glink_rpm_tx_avail(struct glink_rpm *glink) +static size_t qcom_glink_tx_avail(struct qcom_glink *glink) { struct glink_rpm_pipe *pipe = &glink->tx_pipe; unsigned int head; @@ -281,9 +281,9 @@ static size_t glink_rpm_tx_avail(struct glink_rpm *glink) return tail - head; } -static unsigned int glink_rpm_tx_write(struct glink_rpm *glink, - unsigned int head, - const void *data, size_t count) +static unsigned int qcom_glink_tx_write(struct qcom_glink *glink, + unsigned int head, + const void *data, size_t count) { struct glink_rpm_pipe *pipe = &glink->tx_pipe; size_t len; @@ -306,8 +306,8 @@ static unsigned int glink_rpm_tx_write(struct glink_rpm *glink, return head; } -static int glink_rpm_tx(struct glink_rpm *glink, - const void *hdr, size_t hlen, +static int qcom_glink_tx(struct qcom_glink *glink, + const void *hdr, size_t hlen, const void *data, size_t dlen, bool wait) { struct glink_rpm_pipe *pipe = &glink->tx_pipe; @@ -326,7 +326,7 @@ static int glink_rpm_tx(struct glink_rpm *glink, if (ret) return ret; - while (glink_rpm_tx_avail(glink) < tlen) { + while (qcom_glink_tx_avail(glink) < tlen) { if (!wait) { ret = -ENOMEM; goto out; @@ -336,8 +336,8 @@ static int glink_rpm_tx(struct glink_rpm *glink, } head = readl(pipe->head); - head = glink_rpm_tx_write(glink, head, hdr, hlen); - head = glink_rpm_tx_write(glink, head, data, dlen); + head = qcom_glink_tx_write(glink, head, hdr, hlen); + head = qcom_glink_tx_write(glink, head, data, dlen); writel(head, pipe->head); mbox_send_message(glink->mbox_chan, NULL); @@ -349,7 +349,7 @@ static int glink_rpm_tx(struct glink_rpm *glink, return ret; } -static int glink_rpm_send_version(struct glink_rpm *glink) +static int qcom_glink_send_version(struct qcom_glink *glink) { struct glink_msg msg; @@ -357,10 +357,10 @@ static int glink_rpm_send_version(struct glink_rpm *glink) msg.param1 = cpu_to_le16(1); msg.param2 = cpu_to_le32(GLINK_FEATURE_INTENTLESS); - return glink_rpm_tx(glink, &msg, sizeof(msg), NULL, 0, true); + return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); } -static void glink_rpm_send_version_ack(struct glink_rpm *glink) +static void qcom_glink_send_version_ack(struct qcom_glink *glink) { struct glink_msg msg; @@ -368,11 +368,11 @@ static void glink_rpm_send_version_ack(struct glink_rpm *glink) msg.param1 = cpu_to_le16(1); msg.param2 = cpu_to_le32(0); - glink_rpm_tx(glink, &msg, sizeof(msg), NULL, 0, true); + qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); } -static void glink_rpm_send_open_ack(struct glink_rpm *glink, - struct glink_channel *channel) +static void qcom_glink_send_open_ack(struct qcom_glink *glink, + struct glink_channel *channel) { struct glink_msg msg; @@ -380,11 +380,11 @@ static void glink_rpm_send_open_ack(struct glink_rpm *glink, msg.param1 = cpu_to_le16(channel->rcid); msg.param2 = cpu_to_le32(0); - glink_rpm_tx(glink, &msg, sizeof(msg), NULL, 0, true); + qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); } /** - * glink_rpm_send_open_req() - send a RPM_CMD_OPEN request to the remote + * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote * @glink: * @channel: * @@ -393,8 +393,8 @@ static void glink_rpm_send_open_ack(struct glink_rpm *glink, * * Returns 0 on success, negative errno otherwise. */ -static int glink_rpm_send_open_req(struct glink_rpm *glink, - struct glink_channel *channel) +static int qcom_glink_send_open_req(struct qcom_glink *glink, + struct glink_channel *channel) { struct { struct glink_msg msg; @@ -420,7 +420,7 @@ static int glink_rpm_send_open_req(struct glink_rpm *glink, req.msg.param2 = cpu_to_le32(name_len); strcpy(req.name, channel->name); - ret = glink_rpm_tx(glink, &req, req_len, NULL, 0, true); + ret = qcom_glink_tx(glink, &req, req_len, NULL, 0, true); if (ret) goto remove_idr; @@ -435,8 +435,8 @@ static int glink_rpm_send_open_req(struct glink_rpm *glink, return ret; } -static void glink_rpm_send_close_req(struct glink_rpm *glink, - struct glink_channel *channel) +static void qcom_glink_send_close_req(struct qcom_glink *glink, + struct glink_channel *channel) { struct glink_msg req; @@ -444,10 +444,11 @@ static void glink_rpm_send_close_req(struct glink_rpm *glink, req.param1 = cpu_to_le16(channel->lcid); req.param2 = 0; - glink_rpm_tx(glink, &req, sizeof(req), NULL, 0, true); + qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true); } -static void glink_rpm_send_close_ack(struct glink_rpm *glink, unsigned int rcid) +static void qcom_glink_send_close_ack(struct qcom_glink *glink, + unsigned int rcid) { struct glink_msg req; @@ -455,16 +456,16 @@ static void glink_rpm_send_close_ack(struct glink_rpm *glink, unsigned int rcid) req.param1 = cpu_to_le16(rcid); req.param2 = 0; - glink_rpm_tx(glink, &req, sizeof(req), NULL, 0, true); + qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true); } -static int glink_rpm_rx_defer(struct glink_rpm *glink, size_t extra) +static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) { struct glink_defer_cmd *dcmd; extra = ALIGN(extra, 8); - if (glink_rpm_rx_avail(glink) < sizeof(struct glink_msg) + extra) { + if (qcom_glink_rx_avail(glink) < sizeof(struct glink_msg) + extra) { dev_dbg(glink->dev, "Insufficient data in rx fifo"); return -ENXIO; } @@ -475,19 +476,19 @@ static int glink_rpm_rx_defer(struct glink_rpm *glink, size_t extra) INIT_LIST_HEAD(&dcmd->node); - glink_rpm_rx_peak(glink, &dcmd->msg, sizeof(dcmd->msg) + extra); + qcom_glink_rx_peak(glink, &dcmd->msg, sizeof(dcmd->msg) + extra); spin_lock(&glink->rx_lock); list_add_tail(&dcmd->node, &glink->rx_queue); spin_unlock(&glink->rx_lock); schedule_work(&glink->rx_work); - glink_rpm_rx_advance(glink, sizeof(dcmd->msg) + extra); + qcom_glink_rx_advance(glink, sizeof(dcmd->msg) + extra); return 0; } -static int glink_rpm_rx_data(struct glink_rpm *glink, size_t avail) +static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) { struct glink_channel *channel; struct { @@ -504,7 +505,7 @@ static int glink_rpm_rx_data(struct glink_rpm *glink, size_t avail) return -EAGAIN; } - glink_rpm_rx_peak(glink, &hdr, sizeof(hdr)); + qcom_glink_rx_peak(glink, &hdr, sizeof(hdr)); chunk_size = le32_to_cpu(hdr.chunk_size); left_size = le32_to_cpu(hdr.left_size); @@ -522,7 +523,8 @@ static int glink_rpm_rx_data(struct glink_rpm *glink, size_t avail) dev_dbg(glink->dev, "Data on non-existing channel\n"); /* Drop the message */ - glink_rpm_rx_advance(glink, ALIGN(sizeof(hdr) + chunk_size, 8)); + qcom_glink_rx_advance(glink, + ALIGN(sizeof(hdr) + chunk_size, 8)); return 0; } @@ -536,17 +538,18 @@ static int glink_rpm_rx_data(struct glink_rpm *glink, size_t avail) channel->buf_offset = 0; } - glink_rpm_rx_advance(glink, sizeof(hdr)); + qcom_glink_rx_advance(glink, sizeof(hdr)); if (channel->buf_size - channel->buf_offset < chunk_size) { dev_err(glink->dev, "Insufficient space in input buffer\n"); /* The packet header lied, drop payload */ - glink_rpm_rx_advance(glink, chunk_size); + qcom_glink_rx_advance(glink, chunk_size); return -ENOMEM; } - glink_rpm_rx_peak(glink, channel->buf + channel->buf_offset, chunk_size); + qcom_glink_rx_peak(glink, channel->buf + channel->buf_offset, + chunk_size); channel->buf_offset += chunk_size; /* Handle message when no fragments remain to be received */ @@ -567,12 +570,12 @@ static int glink_rpm_rx_data(struct glink_rpm *glink, size_t avail) } /* Each message starts at 8 byte aligned address */ - glink_rpm_rx_advance(glink, ALIGN(chunk_size, 8)); + qcom_glink_rx_advance(glink, ALIGN(chunk_size, 8)); return 0; } -static int glink_rpm_rx_open_ack(struct glink_rpm *glink, unsigned int lcid) +static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) { struct glink_channel *channel; @@ -587,9 +590,9 @@ static int glink_rpm_rx_open_ack(struct glink_rpm *glink, unsigned int lcid) return 0; } -static irqreturn_t glink_rpm_intr(int irq, void *data) +static irqreturn_t qcom_glink_intr(int irq, void *data) { - struct glink_rpm *glink = data; + struct qcom_glink *glink = data; struct glink_msg msg; unsigned int param1; unsigned int param2; @@ -598,11 +601,11 @@ static irqreturn_t glink_rpm_intr(int irq, void *data) int ret; for (;;) { - avail = glink_rpm_rx_avail(glink); + avail = qcom_glink_rx_avail(glink); if (avail < sizeof(msg)) break; - glink_rpm_rx_peak(glink, &msg, sizeof(msg)); + qcom_glink_rx_peak(glink, &msg, sizeof(msg)); cmd = le16_to_cpu(msg.cmd); param1 = le16_to_cpu(msg.param1); @@ -613,21 +616,21 @@ static irqreturn_t glink_rpm_intr(int irq, void *data) case RPM_CMD_VERSION_ACK: case RPM_CMD_CLOSE: case RPM_CMD_CLOSE_ACK: - ret = glink_rpm_rx_defer(glink, 0); + ret = qcom_glink_rx_defer(glink, 0); break; case RPM_CMD_OPEN_ACK: - ret = glink_rpm_rx_open_ack(glink, param1); - glink_rpm_rx_advance(glink, ALIGN(sizeof(msg), 8)); + ret = qcom_glink_rx_open_ack(glink, param1); + qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); break; case RPM_CMD_OPEN: - ret = glink_rpm_rx_defer(glink, param2); + ret = qcom_glink_rx_defer(glink, param2); break; case RPM_CMD_TX_DATA: case RPM_CMD_TX_DATA_CONT: - ret = glink_rpm_rx_data(glink, avail); + ret = qcom_glink_rx_data(glink, avail); break; case RPM_CMD_READ_NOTIF: - glink_rpm_rx_advance(glink, ALIGN(sizeof(msg), 8)); + qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); mbox_send_message(glink->mbox_chan, NULL); mbox_client_txdone(glink->mbox_chan, 0); @@ -648,17 +651,17 @@ static irqreturn_t glink_rpm_intr(int irq, void *data) } /* Locally initiated rpmsg_create_ept */ -static struct glink_channel *glink_rpm_create_local(struct glink_rpm *glink, - const char *name) +static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink, + const char *name) { struct glink_channel *channel; int ret; - channel = glink_rpm_alloc_channel(glink, name); + channel = qcom_glink_alloc_channel(glink, name); if (IS_ERR(channel)) return ERR_CAST(channel); - ret = glink_rpm_send_open_req(glink, channel); + ret = qcom_glink_send_open_req(glink, channel); if (ret) goto release_channel; @@ -670,34 +673,34 @@ static struct glink_channel *glink_rpm_create_local(struct glink_rpm *glink, if (!ret) goto err_timeout; - glink_rpm_send_open_ack(glink, channel); + qcom_glink_send_open_ack(glink, channel); return channel; err_timeout: - /* glink_rpm_send_open_req() did register the channel in lcids*/ + /* qcom_glink_send_open_req() did register the channel in lcids*/ mutex_lock(&glink->idr_lock); idr_remove(&glink->lcids, channel->lcid); mutex_unlock(&glink->idr_lock); release_channel: - /* Release glink_rpm_send_open_req() reference */ - kref_put(&channel->refcount, glink_rpm_channel_release); - /* Release glink_rpm_alloc_channel() reference */ - kref_put(&channel->refcount, glink_rpm_channel_release); + /* Release qcom_glink_send_open_req() reference */ + kref_put(&channel->refcount, qcom_glink_channel_release); + /* Release qcom_glink_alloc_channel() reference */ + kref_put(&channel->refcount, qcom_glink_channel_release); return ERR_PTR(-ETIMEDOUT); } /* Remote initiated rpmsg_create_ept */ -static int glink_rpm_create_remote(struct glink_rpm *glink, - struct glink_channel *channel) +static int qcom_glink_create_remote(struct qcom_glink *glink, + struct glink_channel *channel) { int ret; - glink_rpm_send_open_ack(glink, channel); + qcom_glink_send_open_ack(glink, channel); - ret = glink_rpm_send_open_req(glink, channel); + ret = qcom_glink_send_open_req(glink, channel); if (ret) goto close_link; @@ -714,21 +717,23 @@ static int glink_rpm_create_remote(struct glink_rpm *glink, * Send a close request to "undo" our open-ack. The close-ack will * release the last reference. */ - glink_rpm_send_close_req(glink, channel); + qcom_glink_send_close_req(glink, channel); - /* Release glink_rpm_send_open_req() reference */ - kref_put(&channel->refcount, glink_rpm_channel_release); + /* Release qcom_glink_send_open_req() reference */ + kref_put(&channel->refcount, qcom_glink_channel_release); return ret; } -static struct rpmsg_endpoint *glink_rpm_create_ept(struct rpmsg_device *rpdev, - rpmsg_rx_cb_t cb, void *priv, - struct rpmsg_channel_info chinfo) +static struct rpmsg_endpoint *qcom_glink_create_ept(struct rpmsg_device *rpdev, + rpmsg_rx_cb_t cb, + void *priv, + struct rpmsg_channel_info + chinfo) { struct glink_channel *parent = to_glink_channel(rpdev->ept); struct glink_channel *channel; - struct glink_rpm *glink = parent->glink; + struct qcom_glink *glink = parent->glink; struct rpmsg_endpoint *ept; const char *name = chinfo.name; int cid; @@ -740,11 +745,11 @@ static struct rpmsg_endpoint *glink_rpm_create_ept(struct rpmsg_device *rpdev, } if (!channel) { - channel = glink_rpm_create_local(glink, name); + channel = qcom_glink_create_local(glink, name); if (IS_ERR(channel)) return NULL; } else { - ret = glink_rpm_create_remote(glink, channel); + ret = qcom_glink_create_remote(glink, channel); if (ret) return NULL; } @@ -758,10 +763,10 @@ static struct rpmsg_endpoint *glink_rpm_create_ept(struct rpmsg_device *rpdev, return ept; } -static void glink_rpm_destroy_ept(struct rpmsg_endpoint *ept) +static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) { struct glink_channel *channel = to_glink_channel(ept); - struct glink_rpm *glink = channel->glink; + struct qcom_glink *glink = channel->glink; unsigned long flags; spin_lock_irqsave(&channel->recv_lock, flags); @@ -771,13 +776,13 @@ static void glink_rpm_destroy_ept(struct rpmsg_endpoint *ept) /* Decouple the potential rpdev from the channel */ channel->rpdev = NULL; - glink_rpm_send_close_req(glink, channel); + qcom_glink_send_close_req(glink, channel); } -static int __glink_rpm_send(struct glink_channel *channel, +static int __qcom_glink_send(struct glink_channel *channel, void *data, int len, bool wait) { - struct glink_rpm *glink = channel->glink; + struct qcom_glink *glink = channel->glink; struct { struct glink_msg msg; __le32 chunk_size; @@ -793,27 +798,27 @@ static int __glink_rpm_send(struct glink_channel *channel, req.chunk_size = cpu_to_le32(len); req.left_size = cpu_to_le32(0); - return glink_rpm_tx(glink, &req, sizeof(req), data, len, wait); + return qcom_glink_tx(glink, &req, sizeof(req), data, len, wait); } -static int glink_rpm_send(struct rpmsg_endpoint *ept, void *data, int len) +static int qcom_glink_send(struct rpmsg_endpoint *ept, void *data, int len) { struct glink_channel *channel = to_glink_channel(ept); - return __glink_rpm_send(channel, data, len, true); + return __qcom_glink_send(channel, data, len, true); } -static int glink_rpm_trysend(struct rpmsg_endpoint *ept, void *data, int len) +static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len) { struct glink_channel *channel = to_glink_channel(ept); - return __glink_rpm_send(channel, data, len, false); + return __qcom_glink_send(channel, data, len, false); } /* * Finds the device_node for the glink child interested in this channel. */ -static struct device_node *glink_rpm_match_channel(struct device_node *node, +static struct device_node *qcom_glink_match_channel(struct device_node *node, const char *channel) { struct device_node *child; @@ -835,16 +840,16 @@ static struct device_node *glink_rpm_match_channel(struct device_node *node, } static const struct rpmsg_device_ops glink_device_ops = { - .create_ept = glink_rpm_create_ept, + .create_ept = qcom_glink_create_ept, }; static const struct rpmsg_endpoint_ops glink_endpoint_ops = { - .destroy_ept = glink_rpm_destroy_ept, - .send = glink_rpm_send, - .trysend = glink_rpm_trysend, + .destroy_ept = qcom_glink_destroy_ept, + .send = qcom_glink_send, + .trysend = qcom_glink_trysend, }; -static void glink_rpm_rpdev_release(struct device *dev) +static void qcom_glink_rpdev_release(struct device *dev) { struct rpmsg_device *rpdev = to_rpmsg_device(dev); struct glink_channel *channel = to_glink_channel(rpdev->ept); @@ -853,14 +858,15 @@ static void glink_rpm_rpdev_release(struct device *dev) kfree(rpdev); } -static int glink_rpm_rx_open(struct glink_rpm *glink, unsigned int rcid, - char *name) +static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, + char *name) { struct glink_channel *channel; struct rpmsg_device *rpdev; bool create_device = false; int lcid; int ret; + struct device_node *node; idr_for_each_entry(&glink->lcids, channel, lcid) { if (!strcmp(channel->name, name)) @@ -868,7 +874,7 @@ static int glink_rpm_rx_open(struct glink_rpm *glink, unsigned int rcid, } if (!channel) { - channel = glink_rpm_alloc_channel(glink, name); + channel = qcom_glink_alloc_channel(glink, name); if (IS_ERR(channel)) return PTR_ERR(channel); @@ -901,9 +907,10 @@ static int glink_rpm_rx_open(struct glink_rpm *glink, unsigned int rcid, rpdev->dst = RPMSG_ADDR_ANY; rpdev->ops = &glink_device_ops; - rpdev->dev.of_node = glink_rpm_match_channel(glink->dev->of_node, name); + node = qcom_glink_match_channel(glink->dev->of_node, name); + rpdev->dev.of_node = node; rpdev->dev.parent = glink->dev; - rpdev->dev.release = glink_rpm_rpdev_release; + rpdev->dev.release = qcom_glink_rpdev_release; ret = rpmsg_register_device(rpdev); if (ret) @@ -924,12 +931,12 @@ static int glink_rpm_rx_open(struct glink_rpm *glink, unsigned int rcid, free_channel: /* Release the reference, iff we took it */ if (create_device) - kref_put(&channel->refcount, glink_rpm_channel_release); + kref_put(&channel->refcount, qcom_glink_channel_release); return ret; } -static void glink_rpm_rx_close(struct glink_rpm *glink, unsigned int rcid) +static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid) { struct rpmsg_channel_info chinfo; struct glink_channel *channel; @@ -946,17 +953,17 @@ static void glink_rpm_rx_close(struct glink_rpm *glink, unsigned int rcid) rpmsg_unregister_device(glink->dev, &chinfo); } - glink_rpm_send_close_ack(glink, channel->rcid); + qcom_glink_send_close_ack(glink, channel->rcid); mutex_lock(&glink->idr_lock); idr_remove(&glink->rcids, channel->rcid); channel->rcid = 0; mutex_unlock(&glink->idr_lock); - kref_put(&channel->refcount, glink_rpm_channel_release); + kref_put(&channel->refcount, qcom_glink_channel_release); } -static void glink_rpm_rx_close_ack(struct glink_rpm *glink, unsigned int lcid) +static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) { struct glink_channel *channel; @@ -969,12 +976,13 @@ static void glink_rpm_rx_close_ack(struct glink_rpm *glink, unsigned int lcid) channel->lcid = 0; mutex_unlock(&glink->idr_lock); - kref_put(&channel->refcount, glink_rpm_channel_release); + kref_put(&channel->refcount, qcom_glink_channel_release); } -static void glink_rpm_work(struct work_struct *work) +static void qcom_glink_work(struct work_struct *work) { - struct glink_rpm *glink = container_of(work, struct glink_rpm, rx_work); + struct qcom_glink *glink = container_of(work, struct qcom_glink, + rx_work); struct glink_defer_cmd *dcmd; struct glink_msg *msg; unsigned long flags; @@ -999,18 +1007,18 @@ static void glink_rpm_work(struct work_struct *work) switch (cmd) { case RPM_CMD_VERSION: - glink_rpm_send_version_ack(glink); + qcom_glink_send_version_ack(glink); break; case RPM_CMD_VERSION_ACK: break; case RPM_CMD_OPEN: - glink_rpm_rx_open(glink, param1, msg->data); + qcom_glink_rx_open(glink, param1, msg->data); break; case RPM_CMD_CLOSE: - glink_rpm_rx_close(glink, param1); + qcom_glink_rx_close(glink, param1); break; case RPM_CMD_CLOSE_ACK: - glink_rpm_rx_close_ack(glink, param1); + qcom_glink_rx_close_ack(glink, param1); break; default: WARN(1, "Unknown defer object %d\n", cmd); @@ -1098,7 +1106,7 @@ static int glink_rpm_parse_toc(struct device *dev, static int glink_rpm_probe(struct platform_device *pdev) { - struct glink_rpm *glink; + struct qcom_glink *glink; struct device_node *np; void __iomem *msg_ram; size_t msg_ram_size; @@ -1116,7 +1124,7 @@ static int glink_rpm_probe(struct platform_device *pdev) mutex_init(&glink->tx_lock); spin_lock_init(&glink->rx_lock); INIT_LIST_HEAD(&glink->rx_queue); - INIT_WORK(&glink->rx_work, glink_rpm_work); + INIT_WORK(&glink->rx_work, qcom_glink_work); mutex_init(&glink->idr_lock); idr_init(&glink->lcids); @@ -1151,7 +1159,7 @@ static int glink_rpm_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); ret = devm_request_irq(dev, irq, - glink_rpm_intr, + qcom_glink_intr, IRQF_NO_SUSPEND | IRQF_SHARED, "glink-rpm", glink); if (ret) { @@ -1161,7 +1169,7 @@ static int glink_rpm_probe(struct platform_device *pdev) glink->irq = irq; - ret = glink_rpm_send_version(glink); + ret = qcom_glink_send_version(glink); if (ret) return ret; @@ -1179,7 +1187,7 @@ static int glink_rpm_remove_device(struct device *dev, void *data) static int glink_rpm_remove(struct platform_device *pdev) { - struct glink_rpm *glink = platform_get_drvdata(pdev); + struct qcom_glink *glink = platform_get_drvdata(pdev); struct glink_channel *channel; int cid; int ret; @@ -1193,7 +1201,7 @@ static int glink_rpm_remove(struct platform_device *pdev) /* Release any defunct local channels, waiting for close-ack */ idr_for_each_entry(&glink->lcids, channel, cid) - kref_put(&channel->refcount, glink_rpm_channel_release); + kref_put(&channel->refcount, qcom_glink_channel_release); idr_destroy(&glink->lcids); idr_destroy(&glink->rcids); From patchwork Wed Aug 16 17:18:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 110268 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1071949qge; Wed, 16 Aug 2017 10:24:50 -0700 (PDT) X-Received: by 10.84.132.44 with SMTP id 41mr2634506ple.194.1502904290037; Wed, 16 Aug 2017 10:24:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502904290; cv=none; d=google.com; s=arc-20160816; b=GX9Wm83gzV7SbeggS9iIE+hc7buWPb0trP1LXsENkdGByuC2uJov737ipmuDIkAS22 Izt8DNnszh1dr3bJXCcmhHailpgI9dMkrujvmQ+CFssj3dAGYEZfhFNT46D/WKikhr79 bebdxT/YJ9pi/0IWh/d+IynXB/pYhnhnVHQn0yfYc0Rx1ODLkh0xhr4ebWRYx+0QUtkC 9ZmtDtq7jPTmaKNZzNv+Xt5JF3WS2Hvw0vEuDnFSalH83oP3NsGpsN+8EpWLAtA2QUIw X50AIsyeTS/0Jut2qShQfE5gxTpICwysotyX4jvTZnpqrV4wlZBnadVEflvv3poJxObF XwGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=DkxiTUb6NzVHhko/ekleMDchrUjss7xl/mMB25IYnv4=; b=ED3pMe1JjwOhKeBKfZ+PYOblZvbTuDpsnjPmyFIYRhNwn2Q9dRdoCJpQw+pUJ3RsJ8 B80SIzF7aPFpEnbVObtu/9MgDqiEz1jqvgs/eyRvSRvOfR4KGHOQEAOqHjhe1RbSZk9Y AMsMcY8cvP15rh7Y3iIq+Yl22AUFmZs535rYBoLba3zk57ZTEEEQY4pj0c4C68zWQIeh MOTxcgQNOLcfOikk+yVGebebVwcFXrnYClBwz3t4Feq2YsIR1aORercfX4rltyi6FO1h py7a0WbeV6akkuwmNPSdFkxbwbY8qcLTprPcv4lgg9SCweta0A2z9JrikYx/Qb453gxW BTZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=N2lMjqLS; dkim=pass header.i=@codeaurora.org header.s=default header.b=UjNNFLZI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m9si746575pgs.644.2017.08.16.10.24.49; Wed, 16 Aug 2017 10:24:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=N2lMjqLS; dkim=pass header.i=@codeaurora.org header.s=default header.b=UjNNFLZI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752749AbdHPRYr (ORCPT + 26 others); Wed, 16 Aug 2017 13:24:47 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:51218 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752229AbdHPRTv (ORCPT ); Wed, 16 Aug 2017 13:19:51 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 6D93C60766; Wed, 16 Aug 2017 17:19:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903990; bh=zNFr/LDvETYl/VT/zuBHLdyNPvcrzswdBeKisZZGyPU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N2lMjqLSPUU1qEeXAklH4mX5v4dr0Re1fJ/H/QAoIwi9AaXIM8RYbEtWahbHgyhqp J9hhetZpJR76fl755eZmbt7+Wi8hFpQDj+pM0m4HAfa3O7u1wJMDgrvg0adYxpYcLA 0u3RTPYmuU11wVV04w/oFGVzBBBha6bjT9JcR/S8= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED, T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 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 7606160727; Wed, 16 Aug 2017 17:19:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903977; bh=zNFr/LDvETYl/VT/zuBHLdyNPvcrzswdBeKisZZGyPU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UjNNFLZI1IAYBov7y62stXdnPGDQmuzXTbsX3+LL+EYtfI9chiPnMT9CSDLuKj+5O +SoTV7zFXTjia1C+Wuw4dODftW5cXQDZRcUswa+OEWxnE7wUiu6A1B6TmBLhYCdTdE JcVJ+APvztmaTT7duVXgo90z+XOx59E3nYI45FHU= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 7606160727 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 Cc: sricharan@codeaurora.org Subject: [PATCH 03/18] rpmsg: glink: Split rpm_probe to reuse the common code Date: Wed, 16 Aug 2017 22:48:56 +0530 Message-Id: <1502903951-5403-4-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> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bjorn Andersson There is quite some code common in glink_rpm_probe that can reused for glink-smem based transport as well. So split the function and move the code to glink_native_probe that can be used later when we add the support for glink-smem based transport. Also reuse driver's remove as well. Signed-off-by: Bjorn Andersson Signed-off-by: Sricharan R --- drivers/rpmsg/qcom_glink_rpm.c | 85 ++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 36 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 870ce32..5f0fa0d 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1155,29 +1156,21 @@ static int glink_rpm_parse_toc(struct device *dev, return -EINVAL; } -static int glink_rpm_probe(struct platform_device *pdev) +struct qcom_glink *qcom_glink_native_probe(struct device *dev, + struct qcom_glink_pipe *rx, + struct qcom_glink_pipe *tx) { - struct qcom_glink *glink; - struct glink_rpm_pipe *rx_pipe; - struct glink_rpm_pipe *tx_pipe; - struct device_node *np; - void __iomem *msg_ram; - size_t msg_ram_size; - struct device *dev = &pdev->dev; - struct resource r; int irq; int ret; + struct qcom_glink *glink; glink = devm_kzalloc(dev, sizeof(*glink), GFP_KERNEL); if (!glink) - return -ENOMEM; + return ERR_PTR(-ENOMEM); glink->dev = dev; - - rx_pipe = devm_kzalloc(&pdev->dev, sizeof(*rx_pipe), GFP_KERNEL); - tx_pipe = devm_kzalloc(&pdev->dev, sizeof(*tx_pipe), GFP_KERNEL); - if (!rx_pipe || !tx_pipe) - return -ENOMEM; + glink->tx_pipe = tx; + glink->rx_pipe = rx; mutex_init(&glink->tx_lock); spin_lock_init(&glink->rx_lock); @@ -1188,14 +1181,48 @@ static int glink_rpm_probe(struct platform_device *pdev) idr_init(&glink->lcids); idr_init(&glink->rcids); - glink->mbox_client.dev = &pdev->dev; + glink->mbox_client.dev = dev; glink->mbox_chan = mbox_request_channel(&glink->mbox_client, 0); if (IS_ERR(glink->mbox_chan)) { if (PTR_ERR(glink->mbox_chan) != -EPROBE_DEFER) - dev_err(&pdev->dev, "failed to acquire IPC channel\n"); - return PTR_ERR(glink->mbox_chan); + dev_err(dev, "failed to acquire IPC channel\n"); + return ERR_CAST(glink->mbox_chan); + } + + irq = of_irq_get(dev->of_node, 0); + ret = devm_request_irq(dev, irq, + qcom_glink_intr, + IRQF_NO_SUSPEND | IRQF_SHARED, + "glink-native", glink); + if (ret) { + dev_err(dev, "failed to request IRQ\n"); + return ERR_PTR(ret); } + ret = qcom_glink_send_version(glink); + if (ret) + return ERR_PTR(ret); + + return glink; +} + +static int glink_rpm_probe(struct platform_device *pdev) +{ + struct qcom_glink *glink; + struct glink_rpm_pipe *rx_pipe; + struct glink_rpm_pipe *tx_pipe; + struct device_node *np; + void __iomem *msg_ram; + size_t msg_ram_size; + struct device *dev = &pdev->dev; + struct resource r; + int ret; + + rx_pipe = devm_kzalloc(&pdev->dev, sizeof(*rx_pipe), GFP_KERNEL); + tx_pipe = devm_kzalloc(&pdev->dev, sizeof(*tx_pipe), GFP_KERNEL); + if (!rx_pipe || !tx_pipe) + return -ENOMEM; + np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", 0); ret = of_address_to_resource(np, 0, &r); of_node_put(np); @@ -1219,27 +1246,13 @@ static int glink_rpm_probe(struct platform_device *pdev) tx_pipe->native.avail = glink_rpm_tx_avail; tx_pipe->native.write = glink_rpm_tx_write; - glink->tx_pipe = &tx_pipe->native; - glink->rx_pipe = &rx_pipe->native; - writel(0, tx_pipe->head); writel(0, rx_pipe->tail); - irq = platform_get_irq(pdev, 0); - ret = devm_request_irq(dev, irq, - qcom_glink_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, - "glink-rpm", glink); - if (ret) { - dev_err(dev, "Failed to request IRQ\n"); - return ret; - } - - glink->irq = irq; - - ret = qcom_glink_send_version(glink); - if (ret) - return ret; + glink = qcom_glink_native_probe(&pdev->dev, &rx_pipe->native, + &tx_pipe->native); + if (IS_ERR(glink)) + return PTR_ERR(glink); platform_set_drvdata(pdev, glink); From patchwork Wed Aug 16 17:18:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 110264 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1066720qge; Wed, 16 Aug 2017 10:19:56 -0700 (PDT) X-Received: by 10.98.220.214 with SMTP id c83mr2432894pfl.334.1502903996233; Wed, 16 Aug 2017 10:19:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502903996; cv=none; d=google.com; s=arc-20160816; b=EOmHEXQtQ6pQxWPjf57hGV2bgKTkj9z0sv6VB0xduhMHAo+UrRL698OHJXNdkvmDPR 63qIyKlU8NnkIKzuKf6rMguXMr1I48SyBTRrw7wzDdinwlKRgUGmmD/Wur3WcbFZ44Ho ZlLY1I77QazMsJ0OKq9lC6FJxIvRNaM+IKuZB2LNOaVHkgFt8Ihu80aynHTmudwfdVNR nuyvflu7VUW2nTZl+k9HXBq8yV3bGfY+GlhAAhsv5yH3pgE75V3+g8hgJgdEuPMwxsMu l68vzYrtydTASYHQmGLjwPv/7HChHSfshmyVDfINGyQQWWlAr0g2K/DHyWJIX4Oi3v2d nAzw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=0e/nMvIA2LVI9jRYmhVK5kHyM1xvf9FMEHBCBbqz89Q=; b=DoZOW8tJT81iqCS6hGNos2nx1X9YVFqmNPsfNFHr+MeX+pBgHV/NAwLofAhZG0coHU a/8kBbrsqWPScPY94xl8H0nCGvLWXavlDvwlFdBRpQbOp5RYhhni5Flg+twyqQ9lNhny 4YZ/fJ2rKvHN71nuUvzoMO+tdBn4NLS4+BqkwIEwWurrUXn+2aKd0XcKtzkE0TNVqieC 03H9ckfyyX2Bfh++4PMKH+0J435iyZ6ESmhYUtVDoCUn4fy2Kck6fdlHe5i3suDftrxU E9tkxiUYJ4RTuqItzTndLxxq4XMXtGIXb1EtCH1VoPTk/8b5kIUCAfphhyr1c9YOtXGO U5BA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=cZBrVf4p; dkim=pass header.i=@codeaurora.org header.s=default header.b=IjU8hQbs; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p14si835089pli.372.2017.08.16.10.19.55; Wed, 16 Aug 2017 10:19:56 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=cZBrVf4p; dkim=pass header.i=@codeaurora.org header.s=default header.b=IjU8hQbs; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752706AbdHPRTx (ORCPT + 26 others); Wed, 16 Aug 2017 13:19:53 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:50996 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751969AbdHPRTs (ORCPT ); Wed, 16 Aug 2017 13:19:48 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 6282560300; Wed, 16 Aug 2017 17:19:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903987; bh=kqoLW3qlK9If6eScfPjNvVQ6gWhq4JWag7A/vcztp+s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cZBrVf4pvN76VL/YsS9AKK76ZrLU3MYMm/4WOaLJqsUWlzJU6FtKxk7Sp518ckcUw CcfV6ER5sZW8afn8AcFtbxDsBVUI1QG0OJS7720QzhvLuUI8GdySt9XVG1uL4Rz/Rs XVSN14BBQusnbcAKr7Ck0kPmNtNBn/ApLKUURKPs= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED, T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 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 75F196071D; Wed, 16 Aug 2017 17:19:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903980; bh=kqoLW3qlK9If6eScfPjNvVQ6gWhq4JWag7A/vcztp+s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IjU8hQbsAfNj7FuGid0vBWw6bXTeuMBjX/F7M1MTXJVbFh7fhvozrkO20KPHYDEG5 OFg8If/OGBGCtFgb8oYK3KYi1kBWxMdiW8IgWfQqKnjEM8mUD4SzbF6DG2AKAEHGV0 jcaNTkgjyJiOnfb+m6ROTD079T4M+2FresATpsTs= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 75F196071D 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 Cc: sricharan@codeaurora.org Subject: [PATCH 04/18] rpmsg: glink: Move the common glink protocol implementation to glink_native.c Date: Wed, 16 Aug 2017 22:48:57 +0530 Message-Id: <1502903951-5403-5-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> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bjorn Andersson Move the common part of glink core protocol implementation to glink_native.c that can be shared with the smem based glink transport in the later patches. Signed-off-by: Bjorn Andersson Signed-off-by: Sricharan R --- drivers/rpmsg/Kconfig | 6 +- drivers/rpmsg/Makefile | 1 + drivers/rpmsg/qcom_glink_native.c | 1014 +++++++++++++++++++++++++++++++++++++ drivers/rpmsg/qcom_glink_native.h | 38 ++ drivers/rpmsg/qcom_glink_rpm.c | 995 +----------------------------------- 5 files changed, 1061 insertions(+), 993 deletions(-) create mode 100644 drivers/rpmsg/qcom_glink_native.c create mode 100644 drivers/rpmsg/qcom_glink_native.h -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig index 2a5d2b4..ac33688 100644 --- a/drivers/rpmsg/Kconfig +++ b/drivers/rpmsg/Kconfig @@ -13,9 +13,13 @@ config RPMSG_CHAR in /dev. They make it possible for user-space programs to send and receive rpmsg packets. +config RPMSG_QCOM_GLINK_NATIVE + tristate + select RPMSG + config RPMSG_QCOM_GLINK_RPM tristate "Qualcomm RPM Glink driver" - select RPMSG + select RPMSG_QCOM_GLINK_NATIVE depends on HAS_IOMEM depends on MAILBOX help diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile index 28cc190..09a756c 100644 --- a/drivers/rpmsg/Makefile +++ b/drivers/rpmsg/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_RPMSG) += rpmsg_core.o obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o obj-$(CONFIG_RPMSG_QCOM_GLINK_RPM) += qcom_glink_rpm.o +obj-$(CONFIG_RPMSG_QCOM_GLINK_NATIVE) += qcom_glink_native.o obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c new file mode 100644 index 0000000..04afbb2 --- /dev/null +++ b/drivers/rpmsg/qcom_glink_native.c @@ -0,0 +1,1014 @@ +/* + * Copyright (c) 2016-2017, Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rpmsg_internal.h" +#include "qcom_glink_native.h" + +#define GLINK_NAME_SIZE 32 + +#define RPM_GLINK_CID_MIN 1 +#define RPM_GLINK_CID_MAX 65536 + +struct glink_msg { + __le16 cmd; + __le16 param1; + __le32 param2; + u8 data[]; +} __packed; + +/** + * struct glink_defer_cmd - deferred incoming control message + * @node: list node + * @msg: message header + * data: payload of the message + * + * Copy of a received control message, to be added to @rx_queue and processed + * by @rx_work of @glink_rpm. + */ +struct glink_defer_cmd { + struct list_head node; + + struct glink_msg msg; + u8 data[]; +}; + +/** + * struct glink_rpm - driver context, relates to one remote subsystem + * @dev: reference to the associated struct device + * @doorbell: "rpm_hlos" ipc doorbell + * @rx_pipe: pipe object for receive FIFO + * @tx_pipe: pipe object for transmit FIFO + * @irq: IRQ for signaling incoming events + * @rx_work: worker for handling received control messages + * @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 + * @rcids: idr of all channels with a known remote channel id + */ +struct qcom_glink { + struct device *dev; + + struct mbox_client mbox_client; + struct mbox_chan *mbox_chan; + + struct qcom_glink_pipe *rx_pipe; + struct qcom_glink_pipe *tx_pipe; + + int irq; + + struct work_struct rx_work; + spinlock_t rx_lock; + struct list_head rx_queue; + + struct mutex tx_lock; + + struct mutex idr_lock; + struct idr lcids; + struct idr rcids; +}; + +enum { + GLINK_STATE_CLOSED, + GLINK_STATE_OPENING, + GLINK_STATE_OPEN, + GLINK_STATE_CLOSING, +}; + +/** + * struct glink_channel - internal representation of a channel + * @rpdev: rpdev reference, only used for primary endpoints + * @ept: rpmsg endpoint this channel is associated with + * @glink: qcom_glink context handle + * @refcount: refcount for the channel object + * @recv_lock: guard for @ept.cb + * @name: unique channel name/identifier + * @lcid: channel id, in local space + * @rcid: channel id, in remote space + * @buf: receive buffer, for gathering fragments + * @buf_offset: write offset in @buf + * @buf_size: size of current @buf + * @open_ack: completed once remote has acked the open-request + * @open_req: completed once open-request has been received + */ +struct glink_channel { + struct rpmsg_endpoint ept; + + struct rpmsg_device *rpdev; + struct qcom_glink *glink; + + struct kref refcount; + + spinlock_t recv_lock; + + char *name; + unsigned int lcid; + unsigned int rcid; + + void *buf; + int buf_offset; + int buf_size; + + struct completion open_ack; + struct completion open_req; +}; + +#define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept) + +static const struct rpmsg_endpoint_ops glink_endpoint_ops; + +#define RPM_CMD_VERSION 0 +#define RPM_CMD_VERSION_ACK 1 +#define RPM_CMD_OPEN 2 +#define RPM_CMD_CLOSE 3 +#define RPM_CMD_OPEN_ACK 4 +#define RPM_CMD_TX_DATA 9 +#define RPM_CMD_CLOSE_ACK 11 +#define RPM_CMD_TX_DATA_CONT 12 +#define RPM_CMD_READ_NOTIF 13 + +#define GLINK_FEATURE_INTENTLESS BIT(1) + +static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, + const char *name) +{ + struct glink_channel *channel; + + channel = kzalloc(sizeof(*channel), GFP_KERNEL); + if (!channel) + return ERR_PTR(-ENOMEM); + + /* Setup glink internal glink_channel data */ + spin_lock_init(&channel->recv_lock); + channel->glink = glink; + channel->name = kstrdup(name, GFP_KERNEL); + + init_completion(&channel->open_req); + init_completion(&channel->open_ack); + + kref_init(&channel->refcount); + + return channel; +} + +static void qcom_glink_channel_release(struct kref *ref) +{ + struct glink_channel *channel = container_of(ref, struct glink_channel, + refcount); + + kfree(channel->name); + kfree(channel); +} + +static size_t qcom_glink_rx_avail(struct qcom_glink *glink) +{ + return glink->rx_pipe->avail(glink->rx_pipe); +} + +static void qcom_glink_rx_peak(struct qcom_glink *glink, + void *data, size_t count) +{ + glink->rx_pipe->peak(glink->rx_pipe, data, count); +} + +static void qcom_glink_rx_advance(struct qcom_glink *glink, size_t count) +{ + glink->rx_pipe->advance(glink->rx_pipe, count); +} + +static size_t qcom_glink_tx_avail(struct qcom_glink *glink) +{ + return glink->tx_pipe->avail(glink->tx_pipe); +} + +static void qcom_glink_tx_write(struct qcom_glink *glink, + const void *hdr, size_t hlen, + const void *data, size_t dlen) +{ + glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen); +} + +static int qcom_glink_tx(struct qcom_glink *glink, + const void *hdr, size_t hlen, + const void *data, size_t dlen, bool wait) +{ + unsigned int tlen = hlen + dlen; + int ret; + + /* Reject packets that are too big */ + if (tlen >= glink->tx_pipe->length) + return -EINVAL; + + if (WARN(tlen % 8, "Unaligned TX request")) + return -EINVAL; + + ret = mutex_lock_interruptible(&glink->tx_lock); + if (ret) + return ret; + + while (qcom_glink_tx_avail(glink) < tlen) { + if (!wait) { + ret = -ENOMEM; + goto out; + } + + msleep(10); + } + + qcom_glink_tx_write(glink, hdr, hlen, data, dlen); + + mbox_send_message(glink->mbox_chan, NULL); + mbox_client_txdone(glink->mbox_chan, 0); + +out: + mutex_unlock(&glink->tx_lock); + + return ret; +} + +static int qcom_glink_send_version(struct qcom_glink *glink) +{ + struct glink_msg msg; + + msg.cmd = cpu_to_le16(RPM_CMD_VERSION); + msg.param1 = cpu_to_le16(1); + msg.param2 = cpu_to_le32(GLINK_FEATURE_INTENTLESS); + + return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); +} + +static void qcom_glink_send_version_ack(struct qcom_glink *glink) +{ + struct glink_msg msg; + + msg.cmd = cpu_to_le16(RPM_CMD_VERSION_ACK); + msg.param1 = cpu_to_le16(1); + msg.param2 = cpu_to_le32(0); + + qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); +} + +static void qcom_glink_send_open_ack(struct qcom_glink *glink, + struct glink_channel *channel) +{ + struct glink_msg msg; + + msg.cmd = cpu_to_le16(RPM_CMD_OPEN_ACK); + msg.param1 = cpu_to_le16(channel->rcid); + msg.param2 = cpu_to_le32(0); + + qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); +} + +/** + * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote + * @glink: + * @channel: + * + * Allocates a local channel id and sends a RPM_CMD_OPEN message to the remote. + * Will return with refcount held, regardless of outcome. + * + * Returns 0 on success, negative errno otherwise. + */ +static int qcom_glink_send_open_req(struct qcom_glink *glink, + struct glink_channel *channel) +{ + struct { + struct glink_msg msg; + u8 name[GLINK_NAME_SIZE]; + } __packed req; + int name_len = strlen(channel->name) + 1; + int req_len = ALIGN(sizeof(req.msg) + name_len, 8); + int ret; + + kref_get(&channel->refcount); + + mutex_lock(&glink->idr_lock); + ret = idr_alloc_cyclic(&glink->lcids, channel, + RPM_GLINK_CID_MIN, RPM_GLINK_CID_MAX, + GFP_KERNEL); + mutex_unlock(&glink->idr_lock); + 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; + +remove_idr: + mutex_lock(&glink->idr_lock); + idr_remove(&glink->lcids, channel->lcid); + channel->lcid = 0; + mutex_unlock(&glink->idr_lock); + + return ret; +} + +static void qcom_glink_send_close_req(struct qcom_glink *glink, + struct glink_channel *channel) +{ + struct glink_msg req; + + req.cmd = cpu_to_le16(RPM_CMD_CLOSE); + req.param1 = cpu_to_le16(channel->lcid); + req.param2 = 0; + + qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true); +} + +static void qcom_glink_send_close_ack(struct qcom_glink *glink, + unsigned int rcid) +{ + struct glink_msg req; + + req.cmd = cpu_to_le16(RPM_CMD_CLOSE_ACK); + req.param1 = cpu_to_le16(rcid); + req.param2 = 0; + + qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true); +} + +static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) +{ + struct glink_defer_cmd *dcmd; + + extra = ALIGN(extra, 8); + + if (qcom_glink_rx_avail(glink) < sizeof(struct glink_msg) + extra) { + dev_dbg(glink->dev, "Insufficient data in rx fifo"); + return -ENXIO; + } + + dcmd = kzalloc(sizeof(*dcmd) + extra, GFP_ATOMIC); + if (!dcmd) + return -ENOMEM; + + INIT_LIST_HEAD(&dcmd->node); + + qcom_glink_rx_peak(glink, &dcmd->msg, sizeof(dcmd->msg) + extra); + + spin_lock(&glink->rx_lock); + list_add_tail(&dcmd->node, &glink->rx_queue); + spin_unlock(&glink->rx_lock); + + schedule_work(&glink->rx_work); + qcom_glink_rx_advance(glink, sizeof(dcmd->msg) + extra); + + return 0; +} + +static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) +{ + struct glink_channel *channel; + struct { + struct glink_msg msg; + __le32 chunk_size; + __le32 left_size; + } __packed hdr; + unsigned int chunk_size; + unsigned int left_size; + unsigned int rcid; + + if (avail < sizeof(hdr)) { + dev_dbg(glink->dev, "Not enough data in fifo\n"); + return -EAGAIN; + } + + qcom_glink_rx_peak(glink, &hdr, sizeof(hdr)); + chunk_size = le32_to_cpu(hdr.chunk_size); + left_size = le32_to_cpu(hdr.left_size); + + if (avail < sizeof(hdr) + chunk_size) { + dev_dbg(glink->dev, "Payload not yet in fifo\n"); + return -EAGAIN; + } + + if (WARN(chunk_size % 4, "Incoming data must be word aligned\n")) + return -EINVAL; + + rcid = le16_to_cpu(hdr.msg.param1); + channel = idr_find(&glink->rcids, rcid); + if (!channel) { + dev_dbg(glink->dev, "Data on non-existing channel\n"); + + /* Drop the message */ + qcom_glink_rx_advance(glink, + ALIGN(sizeof(hdr) + chunk_size, 8)); + return 0; + } + + /* Might have an ongoing, fragmented, message to append */ + if (!channel->buf) { + channel->buf = kmalloc(chunk_size + left_size, GFP_ATOMIC); + if (!channel->buf) + return -ENOMEM; + + channel->buf_size = chunk_size + left_size; + channel->buf_offset = 0; + } + + qcom_glink_rx_advance(glink, sizeof(hdr)); + + if (channel->buf_size - channel->buf_offset < chunk_size) { + dev_err(glink->dev, "Insufficient space in input buffer\n"); + + /* The packet header lied, drop payload */ + qcom_glink_rx_advance(glink, chunk_size); + return -ENOMEM; + } + + qcom_glink_rx_peak(glink, channel->buf + channel->buf_offset, + chunk_size); + channel->buf_offset += chunk_size; + + /* Handle message when no fragments remain to be received */ + if (!left_size) { + spin_lock(&channel->recv_lock); + if (channel->ept.cb) { + channel->ept.cb(channel->ept.rpdev, + channel->buf, + channel->buf_offset, + channel->ept.priv, + RPMSG_ADDR_ANY); + } + spin_unlock(&channel->recv_lock); + + kfree(channel->buf); + channel->buf = NULL; + channel->buf_size = 0; + } + + /* Each message starts at 8 byte aligned address */ + qcom_glink_rx_advance(glink, ALIGN(chunk_size, 8)); + + return 0; +} + +static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) +{ + struct glink_channel *channel; + + channel = idr_find(&glink->lcids, lcid); + if (!channel) { + dev_err(glink->dev, "Invalid open ack packet\n"); + return -EINVAL; + } + + complete(&channel->open_ack); + + return 0; +} + +static irqreturn_t qcom_glink_native_intr(int irq, void *data) +{ + struct qcom_glink *glink = data; + struct glink_msg msg; + unsigned int param1; + unsigned int param2; + unsigned int avail; + unsigned int cmd; + int ret; + + for (;;) { + avail = qcom_glink_rx_avail(glink); + if (avail < sizeof(msg)) + break; + + qcom_glink_rx_peak(glink, &msg, sizeof(msg)); + + cmd = le16_to_cpu(msg.cmd); + param1 = le16_to_cpu(msg.param1); + param2 = le32_to_cpu(msg.param2); + + switch (cmd) { + case RPM_CMD_VERSION: + case RPM_CMD_VERSION_ACK: + case RPM_CMD_CLOSE: + case RPM_CMD_CLOSE_ACK: + ret = qcom_glink_rx_defer(glink, 0); + break; + case RPM_CMD_OPEN_ACK: + ret = qcom_glink_rx_open_ack(glink, param1); + qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); + break; + case RPM_CMD_OPEN: + ret = qcom_glink_rx_defer(glink, param2); + break; + case RPM_CMD_TX_DATA: + case RPM_CMD_TX_DATA_CONT: + ret = qcom_glink_rx_data(glink, avail); + break; + case RPM_CMD_READ_NOTIF: + qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); + + mbox_send_message(glink->mbox_chan, NULL); + mbox_client_txdone(glink->mbox_chan, 0); + + ret = 0; + break; + default: + dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd); + ret = -EINVAL; + break; + } + + if (ret) + break; + } + + return IRQ_HANDLED; +} + +/* Locally initiated rpmsg_create_ept */ +static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink, + const char *name) +{ + struct glink_channel *channel; + int ret; + + channel = qcom_glink_alloc_channel(glink, name); + if (IS_ERR(channel)) + return ERR_CAST(channel); + + ret = qcom_glink_send_open_req(glink, channel); + if (ret) + goto release_channel; + + ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); + if (!ret) + goto err_timeout; + + ret = wait_for_completion_timeout(&channel->open_req, 5 * HZ); + if (!ret) + goto err_timeout; + + qcom_glink_send_open_ack(glink, channel); + + return channel; + +err_timeout: + /* qcom_glink_send_open_req() did register the channel in lcids*/ + mutex_lock(&glink->idr_lock); + idr_remove(&glink->lcids, channel->lcid); + mutex_unlock(&glink->idr_lock); + +release_channel: + /* Release qcom_glink_send_open_req() reference */ + kref_put(&channel->refcount, qcom_glink_channel_release); + /* Release qcom_glink_alloc_channel() reference */ + kref_put(&channel->refcount, qcom_glink_channel_release); + + return ERR_PTR(-ETIMEDOUT); +} + +/* Remote initiated rpmsg_create_ept */ +static int qcom_glink_create_remote(struct qcom_glink *glink, + struct glink_channel *channel) +{ + int ret; + + qcom_glink_send_open_ack(glink, channel); + + ret = qcom_glink_send_open_req(glink, channel); + if (ret) + goto close_link; + + ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); + if (!ret) { + ret = -ETIMEDOUT; + goto close_link; + } + + return 0; + +close_link: + /* + * Send a close request to "undo" our open-ack. The close-ack will + * release the last reference. + */ + qcom_glink_send_close_req(glink, channel); + + /* Release qcom_glink_send_open_req() reference */ + kref_put(&channel->refcount, qcom_glink_channel_release); + + return ret; +} + +static struct rpmsg_endpoint *qcom_glink_create_ept(struct rpmsg_device *rpdev, + rpmsg_rx_cb_t cb, + void *priv, + struct rpmsg_channel_info + chinfo) +{ + struct glink_channel *parent = to_glink_channel(rpdev->ept); + struct glink_channel *channel; + struct qcom_glink *glink = parent->glink; + struct rpmsg_endpoint *ept; + const char *name = chinfo.name; + int cid; + int ret; + + idr_for_each_entry(&glink->rcids, channel, cid) { + if (!strcmp(channel->name, name)) + break; + } + + if (!channel) { + channel = qcom_glink_create_local(glink, name); + if (IS_ERR(channel)) + return NULL; + } else { + ret = qcom_glink_create_remote(glink, channel); + if (ret) + return NULL; + } + + ept = &channel->ept; + ept->rpdev = rpdev; + ept->cb = cb; + ept->priv = priv; + ept->ops = &glink_endpoint_ops; + + return ept; +} + +static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) +{ + struct glink_channel *channel = to_glink_channel(ept); + struct qcom_glink *glink = channel->glink; + unsigned long flags; + + spin_lock_irqsave(&channel->recv_lock, flags); + channel->ept.cb = NULL; + spin_unlock_irqrestore(&channel->recv_lock, flags); + + /* Decouple the potential rpdev from the channel */ + channel->rpdev = NULL; + + qcom_glink_send_close_req(glink, channel); +} + +static int __qcom_glink_send(struct glink_channel *channel, + void *data, int len, bool wait) +{ + struct qcom_glink *glink = channel->glink; + struct { + struct glink_msg msg; + __le32 chunk_size; + __le32 left_size; + } __packed req; + + if (WARN(len % 8, "RPM GLINK expects 8 byte aligned messages\n")) + return -EINVAL; + + req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA); + req.msg.param1 = cpu_to_le16(channel->lcid); + req.msg.param2 = cpu_to_le32(channel->rcid); + req.chunk_size = cpu_to_le32(len); + req.left_size = cpu_to_le32(0); + + return qcom_glink_tx(glink, &req, sizeof(req), data, len, wait); +} + +static int qcom_glink_send(struct rpmsg_endpoint *ept, void *data, int len) +{ + struct glink_channel *channel = to_glink_channel(ept); + + return __qcom_glink_send(channel, data, len, true); +} + +static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len) +{ + struct glink_channel *channel = to_glink_channel(ept); + + return __qcom_glink_send(channel, data, len, false); +} + +/* + * Finds the device_node for the glink child interested in this channel. + */ +static struct device_node *qcom_glink_match_channel(struct device_node *node, + const char *channel) +{ + struct device_node *child; + const char *name; + const char *key; + int ret; + + for_each_available_child_of_node(node, child) { + key = "qcom,glink-channels"; + ret = of_property_read_string(child, key, &name); + if (ret) + continue; + + if (strcmp(name, channel) == 0) + return child; + } + + return NULL; +} + +static const struct rpmsg_device_ops glink_device_ops = { + .create_ept = qcom_glink_create_ept, +}; + +static const struct rpmsg_endpoint_ops glink_endpoint_ops = { + .destroy_ept = qcom_glink_destroy_ept, + .send = qcom_glink_send, + .trysend = qcom_glink_trysend, +}; + +static void qcom_glink_rpdev_release(struct device *dev) +{ + struct rpmsg_device *rpdev = to_rpmsg_device(dev); + struct glink_channel *channel = to_glink_channel(rpdev->ept); + + channel->rpdev = NULL; + kfree(rpdev); +} + +static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, + char *name) +{ + struct glink_channel *channel; + struct rpmsg_device *rpdev; + bool create_device = false; + struct device_node *node; + int lcid; + int ret; + + idr_for_each_entry(&glink->lcids, channel, lcid) { + if (!strcmp(channel->name, name)) + break; + } + + if (!channel) { + channel = qcom_glink_alloc_channel(glink, name); + if (IS_ERR(channel)) + return PTR_ERR(channel); + + /* The opening dance was initiated by the remote */ + create_device = true; + } + + mutex_lock(&glink->idr_lock); + ret = idr_alloc(&glink->rcids, channel, rcid, rcid + 1, GFP_KERNEL); + if (ret < 0) { + dev_err(glink->dev, "Unable to insert channel into rcid list\n"); + mutex_unlock(&glink->idr_lock); + goto free_channel; + } + channel->rcid = ret; + mutex_unlock(&glink->idr_lock); + + complete(&channel->open_req); + + if (create_device) { + rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL); + if (!rpdev) { + ret = -ENOMEM; + goto rcid_remove; + } + + rpdev->ept = &channel->ept; + strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE); + rpdev->src = RPMSG_ADDR_ANY; + rpdev->dst = RPMSG_ADDR_ANY; + rpdev->ops = &glink_device_ops; + + node = qcom_glink_match_channel(glink->dev->of_node, name); + rpdev->dev.of_node = node; + rpdev->dev.parent = glink->dev; + rpdev->dev.release = qcom_glink_rpdev_release; + + ret = rpmsg_register_device(rpdev); + if (ret) + goto free_rpdev; + + channel->rpdev = rpdev; + } + + return 0; + +free_rpdev: + kfree(rpdev); +rcid_remove: + mutex_lock(&glink->idr_lock); + idr_remove(&glink->rcids, channel->rcid); + channel->rcid = 0; + mutex_unlock(&glink->idr_lock); +free_channel: + /* Release the reference, iff we took it */ + if (create_device) + kref_put(&channel->refcount, qcom_glink_channel_release); + + return ret; +} + +static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid) +{ + struct rpmsg_channel_info chinfo; + struct glink_channel *channel; + + channel = idr_find(&glink->rcids, rcid); + if (WARN(!channel, "close request on unknown channel\n")) + return; + + if (channel->rpdev) { + strncpy(chinfo.name, channel->name, sizeof(chinfo.name)); + chinfo.src = RPMSG_ADDR_ANY; + chinfo.dst = RPMSG_ADDR_ANY; + + rpmsg_unregister_device(glink->dev, &chinfo); + } + + qcom_glink_send_close_ack(glink, channel->rcid); + + mutex_lock(&glink->idr_lock); + idr_remove(&glink->rcids, channel->rcid); + channel->rcid = 0; + mutex_unlock(&glink->idr_lock); + + kref_put(&channel->refcount, qcom_glink_channel_release); +} + +static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) +{ + struct glink_channel *channel; + + channel = idr_find(&glink->lcids, lcid); + if (WARN(!channel, "close ack on unknown channel\n")) + return; + + mutex_lock(&glink->idr_lock); + idr_remove(&glink->lcids, channel->lcid); + channel->lcid = 0; + mutex_unlock(&glink->idr_lock); + + kref_put(&channel->refcount, qcom_glink_channel_release); +} + +static void qcom_glink_work(struct work_struct *work) +{ + struct qcom_glink *glink = container_of(work, struct qcom_glink, + rx_work); + struct glink_defer_cmd *dcmd; + struct glink_msg *msg; + unsigned long flags; + unsigned int param1; + unsigned int param2; + unsigned int cmd; + + for (;;) { + spin_lock_irqsave(&glink->rx_lock, flags); + if (list_empty(&glink->rx_queue)) { + spin_unlock_irqrestore(&glink->rx_lock, flags); + break; + } + dcmd = list_first_entry(&glink->rx_queue, + struct glink_defer_cmd, node); + list_del(&dcmd->node); + spin_unlock_irqrestore(&glink->rx_lock, flags); + + msg = &dcmd->msg; + cmd = le16_to_cpu(msg->cmd); + param1 = le16_to_cpu(msg->param1); + param2 = le32_to_cpu(msg->param2); + + switch (cmd) { + case RPM_CMD_VERSION: + qcom_glink_send_version_ack(glink); + break; + case RPM_CMD_VERSION_ACK: + break; + case RPM_CMD_OPEN: + qcom_glink_rx_open(glink, param1, msg->data); + break; + case RPM_CMD_CLOSE: + qcom_glink_rx_close(glink, param1); + break; + case RPM_CMD_CLOSE_ACK: + qcom_glink_rx_close_ack(glink, param1); + break; + default: + WARN(1, "Unknown defer object %d\n", cmd); + break; + } + + kfree(dcmd); + } +} + +struct qcom_glink *qcom_glink_native_probe(struct device *dev, + struct qcom_glink_pipe *rx, + struct qcom_glink_pipe *tx) +{ + int irq; + int ret; + struct qcom_glink *glink; + + glink = devm_kzalloc(dev, sizeof(*glink), GFP_KERNEL); + if (!glink) + return ERR_PTR(-ENOMEM); + + glink->dev = dev; + glink->tx_pipe = tx; + glink->rx_pipe = rx; + + mutex_init(&glink->tx_lock); + spin_lock_init(&glink->rx_lock); + INIT_LIST_HEAD(&glink->rx_queue); + INIT_WORK(&glink->rx_work, qcom_glink_work); + + mutex_init(&glink->idr_lock); + idr_init(&glink->lcids); + idr_init(&glink->rcids); + + glink->mbox_client.dev = dev; + glink->mbox_chan = mbox_request_channel(&glink->mbox_client, 0); + if (IS_ERR(glink->mbox_chan)) { + if (PTR_ERR(glink->mbox_chan) != -EPROBE_DEFER) + dev_err(dev, "failed to acquire IPC channel\n"); + return ERR_CAST(glink->mbox_chan); + } + + irq = of_irq_get(dev->of_node, 0); + ret = devm_request_irq(dev, irq, + qcom_glink_native_intr, + IRQF_NO_SUSPEND | IRQF_SHARED, + "glink-native", glink); + if (ret) { + dev_err(dev, "failed to request IRQ\n"); + return ERR_PTR(ret); + } + + ret = qcom_glink_send_version(glink); + if (ret) + return ERR_PTR(ret); + + return glink; +} + +static int qcom_glink_remove_device(struct device *dev, void *data) +{ + device_unregister(dev); + + return 0; +} + +void qcom_glink_native_remove(struct qcom_glink *glink) +{ + struct glink_channel *channel; + int cid; + int ret; + + disable_irq(glink->irq); + cancel_work_sync(&glink->rx_work); + + ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); + if (ret) + dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); + + /* Release any defunct local channels, waiting for close-ack */ + idr_for_each_entry(&glink->lcids, channel, cid) + kref_put(&channel->refcount, qcom_glink_channel_release); + + idr_destroy(&glink->lcids); + idr_destroy(&glink->rcids); +} diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h new file mode 100644 index 0000000..d5627a4 --- /dev/null +++ b/drivers/rpmsg/qcom_glink_native.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016-2017, Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __QCOM_GLINK_NATIVE_H__ +#define __QCOM_GLINK_NATIVE_H__ + +struct qcom_glink_pipe { + size_t length; + + size_t (*avail)(struct qcom_glink_pipe *glink_pipe); + + void (*peak)(struct qcom_glink_pipe *glink_pipe, void *data, + size_t count); + void (*advance)(struct qcom_glink_pipe *glink_pipe, size_t count); + + void (*write)(struct qcom_glink_pipe *glink_pipe, + const void *hdr, size_t hlen, + const void *data, size_t dlen); +}; + +struct qcom_glink; + +struct qcom_glink *qcom_glink_native_probe(struct device *dev, + struct qcom_glink_pipe *rx, + struct qcom_glink_pipe *tx); +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 5f0fa0d..33daa32 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,7 @@ #include #include "rpmsg_internal.h" +#include "qcom_glink_native.h" #define RPM_TOC_SIZE 256 #define RPM_TOC_MAGIC 0x67727430 /* grt0 */ @@ -37,12 +37,7 @@ #define RPM_TX_FIFO_ID 0x61703272 /* ap2r */ #define RPM_RX_FIFO_ID 0x72326170 /* r2ap */ -#define GLINK_NAME_SIZE 32 - -#define RPM_GLINK_CID_MIN 1 -#define RPM_GLINK_CID_MAX 65536 - -#define to_rpm_pipe(p) container_of(p, struct glink_rpm_pipe, native) +#define to_rpm_pipe(p) container_of(p, struct glink_rpm_pipe, native) struct rpm_toc_entry { __le32 id; @@ -50,20 +45,6 @@ struct rpm_toc_entry { __le32 size; } __packed; -struct qcom_glink; - -struct qcom_glink_pipe { - size_t length; - - size_t (*avail)(struct qcom_glink_pipe *glink_pipe); - void (*peak)(struct qcom_glink_pipe *glink_pipe, void *data, - size_t count); - void (*advance)(struct qcom_glink_pipe *glink_pipe, size_t count); - void (*write)(struct qcom_glink_pipe *glink_pipe, - const void *hdr, size_t hlen, - const void *data, size_t dlen); -}; - struct rpm_toc { __le32 magic; __le32 count; @@ -71,13 +52,6 @@ struct rpm_toc { struct rpm_toc_entry entries[]; } __packed; -struct glink_msg { - __le16 cmd; - __le16 param1; - __le32 param2; - u8 data[]; -} __packed; - struct glink_rpm_pipe { struct qcom_glink_pipe native; @@ -87,151 +61,6 @@ struct glink_rpm_pipe { void __iomem *fifo; }; -/** - * struct glink_defer_cmd - deferred incoming control message - * @node: list node - * @msg: message header - * data: payload of the message - * - * Copy of a received control message, to be added to @rx_queue and processed - * by @rx_work of @glink_rpm. - */ -struct glink_defer_cmd { - struct list_head node; - - struct glink_msg msg; - u8 data[]; -}; - -/** - * struct glink_rpm - driver context, relates to one remote subsystem - * @dev: reference to the associated struct device - * @doorbell: "rpm_hlos" ipc doorbell - * @rx_pipe: pipe object for receive FIFO - * @tx_pipe: pipe object for transmit FIFO - * @irq: IRQ for signaling incoming events - * @rx_work: worker for handling received control messages - * @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 - * @rcids: idr of all channels with a known remote channel id - */ -struct qcom_glink { - struct device *dev; - - struct mbox_client mbox_client; - struct mbox_chan *mbox_chan; - - struct qcom_glink_pipe *rx_pipe; - struct qcom_glink_pipe *tx_pipe; - - int irq; - - struct work_struct rx_work; - spinlock_t rx_lock; - struct list_head rx_queue; - - struct mutex tx_lock; - - struct mutex idr_lock; - struct idr lcids; - struct idr rcids; -}; - -enum { - GLINK_STATE_CLOSED, - GLINK_STATE_OPENING, - GLINK_STATE_OPEN, - GLINK_STATE_CLOSING, -}; - -/** - * struct glink_channel - internal representation of a channel - * @rpdev: rpdev reference, only used for primary endpoints - * @ept: rpmsg endpoint this channel is associated with - * @glink: qcom_glink context handle - * @refcount: refcount for the channel object - * @recv_lock: guard for @ept.cb - * @name: unique channel name/identifier - * @lcid: channel id, in local space - * @rcid: channel id, in remote space - * @buf: receive buffer, for gathering fragments - * @buf_offset: write offset in @buf - * @buf_size: size of current @buf - * @open_ack: completed once remote has acked the open-request - * @open_req: completed once open-request has been received - */ -struct glink_channel { - struct rpmsg_endpoint ept; - - struct rpmsg_device *rpdev; - struct qcom_glink *glink; - - struct kref refcount; - - spinlock_t recv_lock; - - char *name; - unsigned int lcid; - unsigned int rcid; - - void *buf; - int buf_offset; - int buf_size; - - struct completion open_ack; - struct completion open_req; -}; - -#define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept) - -static const struct rpmsg_endpoint_ops glink_endpoint_ops; - -#define RPM_CMD_VERSION 0 -#define RPM_CMD_VERSION_ACK 1 -#define RPM_CMD_OPEN 2 -#define RPM_CMD_CLOSE 3 -#define RPM_CMD_OPEN_ACK 4 -#define RPM_CMD_TX_DATA 9 -#define RPM_CMD_CLOSE_ACK 11 -#define RPM_CMD_TX_DATA_CONT 12 -#define RPM_CMD_READ_NOTIF 13 - -#define GLINK_FEATURE_INTENTLESS BIT(1) - -static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink, - const char *name) -{ - struct glink_channel *channel; - - channel = kzalloc(sizeof(*channel), GFP_KERNEL); - if (!channel) - return ERR_PTR(-ENOMEM); - - /* Setup glink internal glink_channel data */ - spin_lock_init(&channel->recv_lock); - channel->glink = glink; - channel->name = kstrdup(name, GFP_KERNEL); - - init_completion(&channel->open_req); - init_completion(&channel->open_ack); - - kref_init(&channel->refcount); - - return channel; -} - -static void qcom_glink_channel_release(struct kref *ref) -{ - struct glink_channel *channel = container_of(ref, struct glink_channel, - refcount); - - kfree(channel->name); - kfree(channel); -} - static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe) { struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); @@ -247,11 +76,6 @@ static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe) return head - tail; } -static size_t qcom_glink_rx_avail(struct qcom_glink *glink) -{ - return glink->rx_pipe->avail(glink->rx_pipe); -} - static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe, void *data, size_t count) { @@ -273,12 +97,6 @@ static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe, } } -static void qcom_glink_rx_peak(struct qcom_glink *glink, - void *data, size_t count) -{ - glink->rx_pipe->peak(glink->rx_pipe, data, count); -} - static void glink_rpm_rx_advance(struct qcom_glink_pipe *glink_pipe, size_t count) { @@ -294,11 +112,6 @@ static void glink_rpm_rx_advance(struct qcom_glink_pipe *glink_pipe, writel(tail, pipe->tail); } -static void qcom_glink_rx_advance(struct qcom_glink *glink, size_t count) -{ - glink->rx_pipe->advance(glink->rx_pipe, count); -} - static size_t glink_rpm_tx_avail(struct qcom_glink_pipe *glink_pipe) { struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); @@ -314,11 +127,6 @@ static size_t glink_rpm_tx_avail(struct qcom_glink_pipe *glink_pipe) return tail - head; } -static size_t qcom_glink_tx_avail(struct qcom_glink *glink) -{ - return glink->tx_pipe->avail(glink->tx_pipe); -} - static unsigned int glink_rpm_tx_write_one(struct glink_rpm_pipe *pipe, unsigned int head, const void *data, size_t count) @@ -356,731 +164,6 @@ static void glink_rpm_tx_write(struct qcom_glink_pipe *glink_pipe, writel(head, pipe->head); } -static void qcom_glink_tx_write(struct qcom_glink *glink, - const void *hdr, size_t hlen, - const void *data, size_t dlen) -{ - glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen); -} - -static int qcom_glink_tx(struct qcom_glink *glink, - const void *hdr, size_t hlen, - const void *data, size_t dlen, bool wait) -{ - unsigned int tlen = hlen + dlen; - int ret; - - /* Reject packets that are too big */ - if (tlen >= glink->tx_pipe->length) - return -EINVAL; - - if (WARN(tlen % 8, "Unaligned TX request")) - return -EINVAL; - - ret = mutex_lock_interruptible(&glink->tx_lock); - if (ret) - return ret; - - while (qcom_glink_tx_avail(glink) < tlen) { - if (!wait) { - ret = -ENOMEM; - goto out; - } - - msleep(10); - } - - qcom_glink_tx_write(glink, hdr, hlen, data, dlen); - - mbox_send_message(glink->mbox_chan, NULL); - mbox_client_txdone(glink->mbox_chan, 0); - -out: - mutex_unlock(&glink->tx_lock); - - return ret; -} - -static int qcom_glink_send_version(struct qcom_glink *glink) -{ - struct glink_msg msg; - - msg.cmd = cpu_to_le16(RPM_CMD_VERSION); - msg.param1 = cpu_to_le16(1); - msg.param2 = cpu_to_le32(GLINK_FEATURE_INTENTLESS); - - return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); -} - -static void qcom_glink_send_version_ack(struct qcom_glink *glink) -{ - struct glink_msg msg; - - msg.cmd = cpu_to_le16(RPM_CMD_VERSION_ACK); - msg.param1 = cpu_to_le16(1); - msg.param2 = cpu_to_le32(0); - - qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); -} - -static void qcom_glink_send_open_ack(struct qcom_glink *glink, - struct glink_channel *channel) -{ - struct glink_msg msg; - - msg.cmd = cpu_to_le16(RPM_CMD_OPEN_ACK); - msg.param1 = cpu_to_le16(channel->rcid); - msg.param2 = cpu_to_le32(0); - - qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true); -} - -/** - * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote - * @glink: - * @channel: - * - * Allocates a local channel id and sends a RPM_CMD_OPEN message to the remote. - * Will return with refcount held, regardless of outcome. - * - * Returns 0 on success, negative errno otherwise. - */ -static int qcom_glink_send_open_req(struct qcom_glink *glink, - struct glink_channel *channel) -{ - struct { - struct glink_msg msg; - u8 name[GLINK_NAME_SIZE]; - } __packed req; - int name_len = strlen(channel->name) + 1; - int req_len = ALIGN(sizeof(req.msg) + name_len, 8); - int ret; - - kref_get(&channel->refcount); - - mutex_lock(&glink->idr_lock); - ret = idr_alloc_cyclic(&glink->lcids, channel, - RPM_GLINK_CID_MIN, RPM_GLINK_CID_MAX, GFP_KERNEL); - mutex_unlock(&glink->idr_lock); - 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; - -remove_idr: - mutex_lock(&glink->idr_lock); - idr_remove(&glink->lcids, channel->lcid); - channel->lcid = 0; - mutex_unlock(&glink->idr_lock); - - return ret; -} - -static void qcom_glink_send_close_req(struct qcom_glink *glink, - struct glink_channel *channel) -{ - struct glink_msg req; - - req.cmd = cpu_to_le16(RPM_CMD_CLOSE); - req.param1 = cpu_to_le16(channel->lcid); - req.param2 = 0; - - qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true); -} - -static void qcom_glink_send_close_ack(struct qcom_glink *glink, - unsigned int rcid) -{ - struct glink_msg req; - - req.cmd = cpu_to_le16(RPM_CMD_CLOSE_ACK); - req.param1 = cpu_to_le16(rcid); - req.param2 = 0; - - qcom_glink_tx(glink, &req, sizeof(req), NULL, 0, true); -} - -static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) -{ - struct glink_defer_cmd *dcmd; - - extra = ALIGN(extra, 8); - - if (qcom_glink_rx_avail(glink) < sizeof(struct glink_msg) + extra) { - dev_dbg(glink->dev, "Insufficient data in rx fifo"); - return -ENXIO; - } - - dcmd = kzalloc(sizeof(*dcmd) + extra, GFP_ATOMIC); - if (!dcmd) - return -ENOMEM; - - INIT_LIST_HEAD(&dcmd->node); - - qcom_glink_rx_peak(glink, &dcmd->msg, sizeof(dcmd->msg) + extra); - - spin_lock(&glink->rx_lock); - list_add_tail(&dcmd->node, &glink->rx_queue); - spin_unlock(&glink->rx_lock); - - schedule_work(&glink->rx_work); - qcom_glink_rx_advance(glink, sizeof(dcmd->msg) + extra); - - return 0; -} - -static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) -{ - struct glink_channel *channel; - struct { - struct glink_msg msg; - __le32 chunk_size; - __le32 left_size; - } __packed hdr; - unsigned int chunk_size; - unsigned int left_size; - unsigned int rcid; - - if (avail < sizeof(hdr)) { - dev_dbg(glink->dev, "Not enough data in fifo\n"); - return -EAGAIN; - } - - qcom_glink_rx_peak(glink, &hdr, sizeof(hdr)); - chunk_size = le32_to_cpu(hdr.chunk_size); - left_size = le32_to_cpu(hdr.left_size); - - if (avail < sizeof(hdr) + chunk_size) { - dev_dbg(glink->dev, "Payload not yet in fifo\n"); - return -EAGAIN; - } - - if (WARN(chunk_size % 4, "Incoming data must be word aligned\n")) - return -EINVAL; - - rcid = le16_to_cpu(hdr.msg.param1); - channel = idr_find(&glink->rcids, rcid); - if (!channel) { - dev_dbg(glink->dev, "Data on non-existing channel\n"); - - /* Drop the message */ - qcom_glink_rx_advance(glink, - ALIGN(sizeof(hdr) + chunk_size, 8)); - return 0; - } - - /* Might have an ongoing, fragmented, message to append */ - if (!channel->buf) { - channel->buf = kmalloc(chunk_size + left_size, GFP_ATOMIC); - if (!channel->buf) - return -ENOMEM; - - channel->buf_size = chunk_size + left_size; - channel->buf_offset = 0; - } - - qcom_glink_rx_advance(glink, sizeof(hdr)); - - if (channel->buf_size - channel->buf_offset < chunk_size) { - dev_err(glink->dev, "Insufficient space in input buffer\n"); - - /* The packet header lied, drop payload */ - qcom_glink_rx_advance(glink, chunk_size); - return -ENOMEM; - } - - qcom_glink_rx_peak(glink, channel->buf + channel->buf_offset, - chunk_size); - channel->buf_offset += chunk_size; - - /* Handle message when no fragments remain to be received */ - if (!left_size) { - spin_lock(&channel->recv_lock); - if (channel->ept.cb) { - channel->ept.cb(channel->ept.rpdev, - channel->buf, - channel->buf_offset, - channel->ept.priv, - RPMSG_ADDR_ANY); - } - spin_unlock(&channel->recv_lock); - - kfree(channel->buf); - channel->buf = NULL; - channel->buf_size = 0; - } - - /* Each message starts at 8 byte aligned address */ - qcom_glink_rx_advance(glink, ALIGN(chunk_size, 8)); - - return 0; -} - -static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid) -{ - struct glink_channel *channel; - - channel = idr_find(&glink->lcids, lcid); - if (!channel) { - dev_err(glink->dev, "Invalid open ack packet\n"); - return -EINVAL; - } - - complete(&channel->open_ack); - - return 0; -} - -static irqreturn_t qcom_glink_intr(int irq, void *data) -{ - struct qcom_glink *glink = data; - struct glink_msg msg; - unsigned int param1; - unsigned int param2; - unsigned int avail; - unsigned int cmd; - int ret; - - for (;;) { - avail = qcom_glink_rx_avail(glink); - if (avail < sizeof(msg)) - break; - - qcom_glink_rx_peak(glink, &msg, sizeof(msg)); - - cmd = le16_to_cpu(msg.cmd); - param1 = le16_to_cpu(msg.param1); - param2 = le32_to_cpu(msg.param2); - - switch (cmd) { - case RPM_CMD_VERSION: - case RPM_CMD_VERSION_ACK: - case RPM_CMD_CLOSE: - case RPM_CMD_CLOSE_ACK: - ret = qcom_glink_rx_defer(glink, 0); - break; - case RPM_CMD_OPEN_ACK: - ret = qcom_glink_rx_open_ack(glink, param1); - qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); - break; - case RPM_CMD_OPEN: - ret = qcom_glink_rx_defer(glink, param2); - break; - case RPM_CMD_TX_DATA: - case RPM_CMD_TX_DATA_CONT: - ret = qcom_glink_rx_data(glink, avail); - break; - case RPM_CMD_READ_NOTIF: - qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8)); - - mbox_send_message(glink->mbox_chan, NULL); - mbox_client_txdone(glink->mbox_chan, 0); - - ret = 0; - break; - default: - dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd); - ret = -EINVAL; - break; - } - - if (ret) - break; - } - - return IRQ_HANDLED; -} - -/* Locally initiated rpmsg_create_ept */ -static struct glink_channel *qcom_glink_create_local(struct qcom_glink *glink, - const char *name) -{ - struct glink_channel *channel; - int ret; - - channel = qcom_glink_alloc_channel(glink, name); - if (IS_ERR(channel)) - return ERR_CAST(channel); - - ret = qcom_glink_send_open_req(glink, channel); - if (ret) - goto release_channel; - - ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); - if (!ret) - goto err_timeout; - - ret = wait_for_completion_timeout(&channel->open_req, 5 * HZ); - if (!ret) - goto err_timeout; - - qcom_glink_send_open_ack(glink, channel); - - return channel; - -err_timeout: - /* qcom_glink_send_open_req() did register the channel in lcids*/ - mutex_lock(&glink->idr_lock); - idr_remove(&glink->lcids, channel->lcid); - mutex_unlock(&glink->idr_lock); - -release_channel: - /* Release qcom_glink_send_open_req() reference */ - kref_put(&channel->refcount, qcom_glink_channel_release); - /* Release qcom_glink_alloc_channel() reference */ - kref_put(&channel->refcount, qcom_glink_channel_release); - - return ERR_PTR(-ETIMEDOUT); -} - -/* Remote initiated rpmsg_create_ept */ -static int qcom_glink_create_remote(struct qcom_glink *glink, - struct glink_channel *channel) -{ - int ret; - - qcom_glink_send_open_ack(glink, channel); - - ret = qcom_glink_send_open_req(glink, channel); - if (ret) - goto close_link; - - ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); - if (!ret) { - ret = -ETIMEDOUT; - goto close_link; - } - - return 0; - -close_link: - /* - * Send a close request to "undo" our open-ack. The close-ack will - * release the last reference. - */ - qcom_glink_send_close_req(glink, channel); - - /* Release qcom_glink_send_open_req() reference */ - kref_put(&channel->refcount, qcom_glink_channel_release); - - return ret; -} - -static struct rpmsg_endpoint *qcom_glink_create_ept(struct rpmsg_device *rpdev, - rpmsg_rx_cb_t cb, - void *priv, - struct rpmsg_channel_info - chinfo) -{ - struct glink_channel *parent = to_glink_channel(rpdev->ept); - struct glink_channel *channel; - struct qcom_glink *glink = parent->glink; - struct rpmsg_endpoint *ept; - const char *name = chinfo.name; - int cid; - int ret; - - idr_for_each_entry(&glink->rcids, channel, cid) { - if (!strcmp(channel->name, name)) - break; - } - - if (!channel) { - channel = qcom_glink_create_local(glink, name); - if (IS_ERR(channel)) - return NULL; - } else { - ret = qcom_glink_create_remote(glink, channel); - if (ret) - return NULL; - } - - ept = &channel->ept; - ept->rpdev = rpdev; - ept->cb = cb; - ept->priv = priv; - ept->ops = &glink_endpoint_ops; - - return ept; -} - -static void qcom_glink_destroy_ept(struct rpmsg_endpoint *ept) -{ - struct glink_channel *channel = to_glink_channel(ept); - struct qcom_glink *glink = channel->glink; - unsigned long flags; - - spin_lock_irqsave(&channel->recv_lock, flags); - channel->ept.cb = NULL; - spin_unlock_irqrestore(&channel->recv_lock, flags); - - /* Decouple the potential rpdev from the channel */ - channel->rpdev = NULL; - - qcom_glink_send_close_req(glink, channel); -} - -static int __qcom_glink_send(struct glink_channel *channel, - void *data, int len, bool wait) -{ - struct qcom_glink *glink = channel->glink; - struct { - struct glink_msg msg; - __le32 chunk_size; - __le32 left_size; - } __packed req; - - if (WARN(len % 8, "RPM GLINK expects 8 byte aligned messages\n")) - return -EINVAL; - - req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA); - req.msg.param1 = cpu_to_le16(channel->lcid); - req.msg.param2 = cpu_to_le32(channel->rcid); - req.chunk_size = cpu_to_le32(len); - req.left_size = cpu_to_le32(0); - - return qcom_glink_tx(glink, &req, sizeof(req), data, len, wait); -} - -static int qcom_glink_send(struct rpmsg_endpoint *ept, void *data, int len) -{ - struct glink_channel *channel = to_glink_channel(ept); - - return __qcom_glink_send(channel, data, len, true); -} - -static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len) -{ - struct glink_channel *channel = to_glink_channel(ept); - - return __qcom_glink_send(channel, data, len, false); -} - -/* - * Finds the device_node for the glink child interested in this channel. - */ -static struct device_node *qcom_glink_match_channel(struct device_node *node, - const char *channel) -{ - struct device_node *child; - const char *name; - const char *key; - int ret; - - for_each_available_child_of_node(node, child) { - key = "qcom,glink-channels"; - ret = of_property_read_string(child, key, &name); - if (ret) - continue; - - if (strcmp(name, channel) == 0) - return child; - } - - return NULL; -} - -static const struct rpmsg_device_ops glink_device_ops = { - .create_ept = qcom_glink_create_ept, -}; - -static const struct rpmsg_endpoint_ops glink_endpoint_ops = { - .destroy_ept = qcom_glink_destroy_ept, - .send = qcom_glink_send, - .trysend = qcom_glink_trysend, -}; - -static void qcom_glink_rpdev_release(struct device *dev) -{ - struct rpmsg_device *rpdev = to_rpmsg_device(dev); - struct glink_channel *channel = to_glink_channel(rpdev->ept); - - channel->rpdev = NULL; - kfree(rpdev); -} - -static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid, - char *name) -{ - struct glink_channel *channel; - struct rpmsg_device *rpdev; - bool create_device = false; - int lcid; - int ret; - struct device_node *node; - - idr_for_each_entry(&glink->lcids, channel, lcid) { - if (!strcmp(channel->name, name)) - break; - } - - if (!channel) { - channel = qcom_glink_alloc_channel(glink, name); - if (IS_ERR(channel)) - return PTR_ERR(channel); - - /* The opening dance was initiated by the remote */ - create_device = true; - } - - mutex_lock(&glink->idr_lock); - ret = idr_alloc(&glink->rcids, channel, rcid, rcid + 1, GFP_KERNEL); - if (ret < 0) { - dev_err(glink->dev, "Unable to insert channel into rcid list\n"); - mutex_unlock(&glink->idr_lock); - goto free_channel; - } - channel->rcid = ret; - mutex_unlock(&glink->idr_lock); - - complete(&channel->open_req); - - if (create_device) { - rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL); - if (!rpdev) { - ret = -ENOMEM; - goto rcid_remove; - } - - rpdev->ept = &channel->ept; - strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE); - rpdev->src = RPMSG_ADDR_ANY; - rpdev->dst = RPMSG_ADDR_ANY; - rpdev->ops = &glink_device_ops; - - node = qcom_glink_match_channel(glink->dev->of_node, name); - rpdev->dev.of_node = node; - rpdev->dev.parent = glink->dev; - rpdev->dev.release = qcom_glink_rpdev_release; - - ret = rpmsg_register_device(rpdev); - if (ret) - goto free_rpdev; - - channel->rpdev = rpdev; - } - - return 0; - -free_rpdev: - kfree(rpdev); -rcid_remove: - mutex_lock(&glink->idr_lock); - idr_remove(&glink->rcids, channel->rcid); - channel->rcid = 0; - mutex_unlock(&glink->idr_lock); -free_channel: - /* Release the reference, iff we took it */ - if (create_device) - kref_put(&channel->refcount, qcom_glink_channel_release); - - return ret; -} - -static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid) -{ - struct rpmsg_channel_info chinfo; - struct glink_channel *channel; - - channel = idr_find(&glink->rcids, rcid); - if (WARN(!channel, "close request on unknown channel\n")) - return; - - if (channel->rpdev) { - strncpy(chinfo.name, channel->name, sizeof(chinfo.name)); - chinfo.src = RPMSG_ADDR_ANY; - chinfo.dst = RPMSG_ADDR_ANY; - - rpmsg_unregister_device(glink->dev, &chinfo); - } - - qcom_glink_send_close_ack(glink, channel->rcid); - - mutex_lock(&glink->idr_lock); - idr_remove(&glink->rcids, channel->rcid); - channel->rcid = 0; - mutex_unlock(&glink->idr_lock); - - kref_put(&channel->refcount, qcom_glink_channel_release); -} - -static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid) -{ - struct glink_channel *channel; - - channel = idr_find(&glink->lcids, lcid); - if (WARN(!channel, "close ack on unknown channel\n")) - return; - - mutex_lock(&glink->idr_lock); - idr_remove(&glink->lcids, channel->lcid); - channel->lcid = 0; - mutex_unlock(&glink->idr_lock); - - kref_put(&channel->refcount, qcom_glink_channel_release); -} - -static void qcom_glink_work(struct work_struct *work) -{ - struct qcom_glink *glink = container_of(work, struct qcom_glink, - rx_work); - struct glink_defer_cmd *dcmd; - struct glink_msg *msg; - unsigned long flags; - unsigned int param1; - unsigned int param2; - unsigned int cmd; - - for (;;) { - spin_lock_irqsave(&glink->rx_lock, flags); - if (list_empty(&glink->rx_queue)) { - spin_unlock_irqrestore(&glink->rx_lock, flags); - break; - } - dcmd = list_first_entry(&glink->rx_queue, struct glink_defer_cmd, node); - list_del(&dcmd->node); - spin_unlock_irqrestore(&glink->rx_lock, flags); - - msg = &dcmd->msg; - cmd = le16_to_cpu(msg->cmd); - param1 = le16_to_cpu(msg->param1); - param2 = le32_to_cpu(msg->param2); - - switch (cmd) { - case RPM_CMD_VERSION: - qcom_glink_send_version_ack(glink); - break; - case RPM_CMD_VERSION_ACK: - break; - case RPM_CMD_OPEN: - qcom_glink_rx_open(glink, param1, msg->data); - break; - case RPM_CMD_CLOSE: - qcom_glink_rx_close(glink, param1); - break; - case RPM_CMD_CLOSE_ACK: - qcom_glink_rx_close_ack(glink, param1); - break; - default: - WARN(1, "Unknown defer object %d\n", cmd); - break; - } - - kfree(dcmd); - } -} - static int glink_rpm_parse_toc(struct device *dev, void __iomem *msg_ram, size_t msg_ram_size, @@ -1156,56 +239,6 @@ static int glink_rpm_parse_toc(struct device *dev, return -EINVAL; } -struct qcom_glink *qcom_glink_native_probe(struct device *dev, - struct qcom_glink_pipe *rx, - struct qcom_glink_pipe *tx) -{ - int irq; - int ret; - struct qcom_glink *glink; - - glink = devm_kzalloc(dev, sizeof(*glink), GFP_KERNEL); - if (!glink) - return ERR_PTR(-ENOMEM); - - glink->dev = dev; - glink->tx_pipe = tx; - glink->rx_pipe = rx; - - mutex_init(&glink->tx_lock); - spin_lock_init(&glink->rx_lock); - INIT_LIST_HEAD(&glink->rx_queue); - INIT_WORK(&glink->rx_work, qcom_glink_work); - - mutex_init(&glink->idr_lock); - idr_init(&glink->lcids); - idr_init(&glink->rcids); - - glink->mbox_client.dev = dev; - glink->mbox_chan = mbox_request_channel(&glink->mbox_client, 0); - if (IS_ERR(glink->mbox_chan)) { - if (PTR_ERR(glink->mbox_chan) != -EPROBE_DEFER) - dev_err(dev, "failed to acquire IPC channel\n"); - return ERR_CAST(glink->mbox_chan); - } - - irq = of_irq_get(dev->of_node, 0); - ret = devm_request_irq(dev, irq, - qcom_glink_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, - "glink-native", glink); - if (ret) { - dev_err(dev, "failed to request IRQ\n"); - return ERR_PTR(ret); - } - - ret = qcom_glink_send_version(glink); - if (ret) - return ERR_PTR(ret); - - return glink; -} - static int glink_rpm_probe(struct platform_device *pdev) { struct qcom_glink *glink; @@ -1259,33 +292,11 @@ static int glink_rpm_probe(struct platform_device *pdev) return 0; } -static int glink_rpm_remove_device(struct device *dev, void *data) -{ - device_unregister(dev); - - return 0; -} - static int glink_rpm_remove(struct platform_device *pdev) { struct qcom_glink *glink = platform_get_drvdata(pdev); - struct glink_channel *channel; - int cid; - int ret; - - disable_irq(glink->irq); - cancel_work_sync(&glink->rx_work); - - ret = device_for_each_child(glink->dev, NULL, glink_rpm_remove_device); - if (ret) - dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); - - /* Release any defunct local channels, waiting for close-ack */ - idr_for_each_entry(&glink->lcids, channel, cid) - kref_put(&channel->refcount, qcom_glink_channel_release); - idr_destroy(&glink->lcids); - idr_destroy(&glink->rcids); + qcom_glink_native_remove(glink); return 0; } From patchwork Wed Aug 16 17:18:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 110265 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1066848qge; Wed, 16 Aug 2017 10:20:04 -0700 (PDT) X-Received: by 10.84.217.24 with SMTP id o24mr133593pli.218.1502904004586; Wed, 16 Aug 2017 10:20:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502904004; cv=none; d=google.com; s=arc-20160816; b=Ka5qRhXALf57xom1wccNfl9/vOEFcAE50Xw18C/S30qWcWuhRjcwBZK9XZHNnTW91L LZZaAcx6vjEGrQqENSeoNxb8L37mJZ1WkHp66/8uuiA27ahCyYTtoOHOjyYb9aUvAPzR 0eseU8ZZ3BjY5Fy2f9O0skPEkO9k1pZyv7c+8uVzduoXckAn9N+Pveik+rh6JhUBoy0d E2vEBm7zq5bMnoOKuXVWZ6ilm1iImjdAcT/XwGU2sDyd08lu/n5ruoiH3M/bLn1iFkHl pahWbzS/NRjnJ1fo0hXP7f5B7qWQIIouw9Bt5Yq1gbGy3MMk045pckgD00/spnX1msP0 VQUQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=ZQbsV1Gnl2dUNNOQ8qF7y0yQUn568Bwf7HQj9cyXgGc=; b=NglQhFgRgWWoiS9/Bgc0mD3Xlu6ms30u5Cj81l22dsGShZK+ScO26uyZuFWLDaZMpJ AbjMAo+dPZ26Ho9QwubA94beMT1lHWB1H0zsG7ON+ODZbVY2XIMRlKEcC3zZqIvtIpzd 10/G59DGYY8quP7TiaEw07LDDjkjQ8FD3y1q7aWZ8a7U8C2fFsUQ0Hipe9Bfu+fq0z7u 5B6qj1364zx+CKtkmlqcvWCn8LZmEAkawLCFsN+UrJO0aF7s3w+o2Xjx62AccK5tX+Cy AmQJnQVv28PySKzDrN6pvkf5ORJ1F1v9HAUYXN9tlcxtowtV1Q5HiDWaQS5xSqDp6yvW /GBg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=KsY/Ylbv; dkim=pass header.i=@codeaurora.org header.s=default header.b=IfZHq43l; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e28si733110pgn.916.2017.08.16.10.20.04; Wed, 16 Aug 2017 10:20:04 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=KsY/Ylbv; dkim=pass header.i=@codeaurora.org header.s=default header.b=IfZHq43l; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752732AbdHPRUA (ORCPT + 26 others); Wed, 16 Aug 2017 13:20:00 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:51512 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751969AbdHPRTz (ORCPT ); Wed, 16 Aug 2017 13:19:55 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id D9827606DC; Wed, 16 Aug 2017 17:19:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903994; bh=o1jj8dkET8+SXLJ2x8jXeKjbKkB1fWvz9RW/5fZ//9M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KsY/YlbvvmsWSy0WqH5lutJJZDYmAh0hBmiJFI2Z27NNDwTU82+1Q9RbMsp7xGYCd cowgvXMY0tCvFPlcNvTzqPNUPbUJyDo8CDlbL357GnmCLoWZUJ9+nTY+oY8oX3oboo k4qUb34lsn8RF4F2uJTts4enFloGyNAhNumtO9gY= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED, T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 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 8CBC660766; Wed, 16 Aug 2017 17:19:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502903983; bh=o1jj8dkET8+SXLJ2x8jXeKjbKkB1fWvz9RW/5fZ//9M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=IfZHq43lQliyw5WaXkHDdwIt5CBDwCQ9NN97WSOGgIj5pDVZM6/VHabDEE1dHOnxI hLg0g1tbcyMiCaVqwGjBReaBp/y37a/P5WxoA/a2BwUyHbOlExxhDk6vFbIDsW+0Rp aOj4Syc2FfYpCKwh8AJ7vO5ffjBkbQnPDM8aVVZo= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 8CBC660766 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 Cc: sricharan@codeaurora.org Subject: [PATCH 05/18] rpmsg: glink: Allow unaligned data access Date: Wed, 16 Aug 2017 22:48:58 +0530 Message-Id: <1502903951-5403-6-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> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bjorn Andersson Glink protocol requires that each message is aligned on a 8 byte offset. This is purely a restriction from glink, so in order to support clients which do not adher to this, allow data packets of any size, but align the head index accordingly, effectively removing the alignment restriction. Signed-off-by: Bjorn Andersson Signed-off-by: Sricharan R --- drivers/rpmsg/qcom_glink_native.c | 6 ------ drivers/rpmsg/qcom_glink_rpm.c | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 04afbb2..1aa92daf 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -226,9 +226,6 @@ static int qcom_glink_tx(struct qcom_glink *glink, if (tlen >= glink->tx_pipe->length) return -EINVAL; - if (WARN(tlen % 8, "Unaligned TX request")) - return -EINVAL; - ret = mutex_lock_interruptible(&glink->tx_lock); if (ret) return ret; @@ -694,9 +691,6 @@ static int __qcom_glink_send(struct glink_channel *channel, __le32 left_size; } __packed req; - if (WARN(len % 8, "RPM GLINK expects 8 byte aligned messages\n")) - return -EINVAL; - req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA); req.msg.param1 = cpu_to_le16(channel->lcid); req.msg.param2 = cpu_to_le32(channel->rcid); diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 33daa32..cc73af0 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -156,11 +156,31 @@ static void glink_rpm_tx_write(struct qcom_glink_pipe *glink_pipe, const void *data, size_t dlen) { struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); + size_t tlen = hlen + dlen; + size_t aligned_dlen; unsigned int head; + char padding[8] = {0}; + size_t pad; + + /* Header length comes from glink native and is always 4 byte aligned */ + if (WARN(hlen % 4, "Glink Header length must be 4 bytes aligned\n")) + return; + + /* + * Move the unaligned tail of the message to the padding chunk, to + * ensure word aligned accesses + */ + aligned_dlen = ALIGN_DOWN(dlen, 4); + if (aligned_dlen != dlen) + memcpy(padding, data + aligned_dlen, dlen - aligned_dlen); head = readl(pipe->head); head = glink_rpm_tx_write_one(pipe, head, hdr, hlen); - head = glink_rpm_tx_write_one(pipe, head, data, dlen); + head = glink_rpm_tx_write_one(pipe, head, data, aligned_dlen); + + pad = ALIGN(tlen, 8) - ALIGN_DOWN(tlen, 4); + if (pad) + head = glink_rpm_tx_write_one(pipe, head, padding, pad); writel(head, pipe->head); } From patchwork Wed Aug 16 17:19:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sricharan Ramabadhran X-Patchwork-Id: 110266 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp1069665qge; Wed, 16 Aug 2017 10:22:37 -0700 (PDT) X-Received: by 10.98.20.197 with SMTP id 188mr2428847pfu.306.1502904157490; Wed, 16 Aug 2017 10:22:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502904157; cv=none; d=google.com; s=arc-20160816; b=eL6t/IQlC8ONrMENS6KouWFX6bM3+oWTPcM++snaEblb0Ix3Ojh6ZUSHU31I8nF3R7 wNep9JCwOPJsQupKVW1w+ekQA8Dsu1tyOEaUBdW6GZz8R2qNMUa0fmzdQMcXegArPNKC WGssTHk720vnLIOTNHZW5+ntSayhxKtnShQhgWbM0vZDUpWpAYaUhUAJUiaWgbxrRdrX Ox/gruyzB60WMgfsUlxO8LB5tfB8o3QLlDkD+wigikdH8Top8NjbJ7178eQV+REBgPva VfmjFpFjUq1sw4VQ5sVsGah5zKVVlJbMQOdfYoenPH72VFDLIE1aeiOTq3mG+fJiuE35 n+og== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=YGdSmuItWa2y7YlwPv6Ew/xpw6KU9FsyOnahKa/3ITU=; b=RvV/uKh7K+mwpvFLElonmZuhhES4KFId35PN8nC3qudRIUo7svBKqD+EiiePcAAKop vRmjRtnZhFKFkD+dg7HeLpK7RHRjpo+EbVEk1W2LgcYF58DpKrIYFj39mmK8Lk2DuOid MsXZIUUyrqXMIxpXF+Vh3335UgS01aAWBCmF2m8DaDiY4Y6I7LRBTNYUcZNFotY3Kin/ IHpDmeii07cYI4AuhvUKSDVPvD1ad5kMn72WB2TlH36pSZr+S5fyB+k5ncx6GrRZWjXt n86w2g2c1pFnpx9kZOaq+tnszcgXfICdyVLT1jsvCDsUL/ctVlKTf+hrPCdYOFWcEZSB uKDQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=hw7vdT5x; dkim=pass header.i=@codeaurora.org header.s=default header.b=b1NGJGrk; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h127si787919pfe.357.2017.08.16.10.22.37; Wed, 16 Aug 2017 10:22:37 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=hw7vdT5x; dkim=pass header.i=@codeaurora.org header.s=default header.b=b1NGJGrk; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752614AbdHPRWf (ORCPT + 26 others); Wed, 16 Aug 2017 13:22:35 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:54700 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752805AbdHPRUb (ORCPT ); Wed, 16 Aug 2017 13:20:31 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 0818260398; Wed, 16 Aug 2017 17:20:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1502904031; bh=w0fvrEqwLkd9X2X7hlbHnAoOymkawlhoQVKw/zJOSJo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hw7vdT5xP0zbs43/xL1DjEFm6VzroHVhE8xM0zJ1AIGVsQiz6RmbMrEDVtudJPmBL iGNBbee/vwaVtchGeS64tVPArba6X7X61EVzNzbZJn83+iuCr8r4/Z4xjrRZziqn6a /MkLn4FKIWoDRAdbTZxh5NZdoHh6ZHpXO2zE9OPc= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED, T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 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 0B9CD607E1; 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=1502904004; bh=w0fvrEqwLkd9X2X7hlbHnAoOymkawlhoQVKw/zJOSJo=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=b1NGJGrkLwEPmWNRggDkXhndddo/X27bSb9u6l5maj0YK8KBoo5Lo6aI+X6Eo+5Az RZjUihoQyZp41iErzY1okiZjTbThdFk17HgHO0bPHaXXE0e3HEAbgBw9ZevNnBg01H Yeg+rytMt9/tOMv7hqM12vhcK6bXuobnZS1lrwZc= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 0B9CD607E1 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 Cc: sricharan@codeaurora.org Subject: [PATCH 12/18] rpmsg: glink: Make RX FIFO peak accessor to take an offset Date: Wed, 16 Aug 2017 22:49:05 +0530 Message-Id: <1502903951-5403-13-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> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Bjorn Andersson To fully read the received rx data from FIFO both the command and data has to be read. Currently we read command, data separately and process them. By adding an offset parameter to RX FIFO peak accessor, command and data can be read together, simplifying things. So introduce this. Signed-off-by: Bjorn Andersson Signed-off-by: Sricharan R --- drivers/rpmsg/qcom_glink_native.c | 15 +++++++-------- drivers/rpmsg/qcom_glink_native.h | 2 +- drivers/rpmsg/qcom_glink_rpm.c | 5 ++++- drivers/rpmsg/qcom_glink_smem.c | 5 ++++- 4 files changed, 16 insertions(+), 11 deletions(-) -- QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index d6aa589..b2a583a 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -226,9 +226,9 @@ static size_t qcom_glink_rx_avail(struct qcom_glink *glink) } static void qcom_glink_rx_peak(struct qcom_glink *glink, - void *data, size_t count) + void *data, unsigned int offset, size_t count) { - glink->rx_pipe->peak(glink->rx_pipe, data, count); + glink->rx_pipe->peak(glink->rx_pipe, data, offset, count); } static void qcom_glink_rx_advance(struct qcom_glink *glink, size_t count) @@ -593,7 +593,7 @@ static int qcom_glink_rx_defer(struct qcom_glink *glink, size_t extra) INIT_LIST_HEAD(&dcmd->node); - qcom_glink_rx_peak(glink, &dcmd->msg, sizeof(dcmd->msg) + extra); + qcom_glink_rx_peak(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra); spin_lock(&glink->rx_lock); list_add_tail(&dcmd->node, &glink->rx_queue); @@ -626,7 +626,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) return -EAGAIN; } - qcom_glink_rx_peak(glink, &hdr, sizeof(hdr)); + qcom_glink_rx_peak(glink, &hdr, 0, sizeof(hdr)); chunk_size = le32_to_cpu(hdr.chunk_size); left_size = le32_to_cpu(hdr.left_size); @@ -693,9 +693,8 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) goto advance_rx; } - qcom_glink_rx_advance(glink, ALIGN(sizeof(hdr), 8)); qcom_glink_rx_peak(glink, intent->data + intent->offset, - chunk_size); + sizeof(hdr), chunk_size); intent->offset += chunk_size; /* Handle message when no fragments remain to be received */ @@ -715,7 +714,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail) } advance_rx: - qcom_glink_rx_advance(glink, ALIGN(chunk_size, 8)); + qcom_glink_rx_advance(glink, ALIGN(sizeof(hdr) + chunk_size, 8)); return ret; } @@ -752,7 +751,7 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data) if (avail < sizeof(msg)) break; - qcom_glink_rx_peak(glink, &msg, sizeof(msg)); + qcom_glink_rx_peak(glink, &msg, 0, sizeof(msg)); cmd = le16_to_cpu(msg.cmd); param1 = le16_to_cpu(msg.param1); diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h index d7538c3..0e1e420 100644 --- a/drivers/rpmsg/qcom_glink_native.h +++ b/drivers/rpmsg/qcom_glink_native.h @@ -24,7 +24,7 @@ struct qcom_glink_pipe { size_t (*avail)(struct qcom_glink_pipe *glink_pipe); void (*peak)(struct qcom_glink_pipe *glink_pipe, void *data, - size_t count); + unsigned int offset, size_t count); void (*advance)(struct qcom_glink_pipe *glink_pipe, size_t count); void (*write)(struct qcom_glink_pipe *glink_pipe, diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c index 5a86e08..69b25d1 100644 --- a/drivers/rpmsg/qcom_glink_rpm.c +++ b/drivers/rpmsg/qcom_glink_rpm.c @@ -77,13 +77,16 @@ static size_t glink_rpm_rx_avail(struct qcom_glink_pipe *glink_pipe) } static void glink_rpm_rx_peak(struct qcom_glink_pipe *glink_pipe, - void *data, size_t count) + void *data, unsigned int offset, size_t count) { struct glink_rpm_pipe *pipe = to_rpm_pipe(glink_pipe); unsigned int tail; size_t len; tail = readl(pipe->tail); + tail += offset; + if (tail >= pipe->native.length) + tail -= pipe->native.length; len = min_t(size_t, count, pipe->native.length - tail); if (len) { diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c index e792895..6d8f41f 100644 --- a/drivers/rpmsg/qcom_glink_smem.c +++ b/drivers/rpmsg/qcom_glink_smem.c @@ -87,13 +87,16 @@ static size_t glink_smem_rx_avail(struct qcom_glink_pipe *np) } static void glink_smem_rx_peak(struct qcom_glink_pipe *np, - void *data, size_t count) + void *data, unsigned int offset, size_t count) { struct glink_smem_pipe *pipe = to_smem_pipe(np); size_t len; u32 tail; tail = le32_to_cpu(*pipe->tail); + tail += offset; + if (tail >= pipe->native.length) + tail -= pipe->native.length; len = min_t(size_t, count, pipe->native.length - tail); if (len) {