Received: by 2002:a05:6a10:1a4d:0:0:0:0 with SMTP id nk13csp5710440pxb; Mon, 14 Feb 2022 05:58:27 -0800 (PST) X-Google-Smtp-Source: ABdhPJyifa0tN1jasDuA+o2cT2Bnrl5i2h/xDJgL9dBCfoENK4MbXhqe4s3eAWMCQWp5TcQGG+47 X-Received: by 2002:a63:51:: with SMTP id 78mr11873439pga.518.1644847107298; Mon, 14 Feb 2022 05:58:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1644847107; cv=none; d=google.com; s=arc-20160816; b=iGHWVYUjSJTTUIAzbG4rAMdg3VY++drndb9AfNtQ1a02l5BrfyzELzuL/RbKaVE6D1 WD0fMZmF/H/EXpW7jrM6isDiODfFL5eKQU4h5ItD6Ze9NNDEkAdf3XTST9w+0j6HbSLi ZnIR/CmxxGehG1TzkMGi8w/7B4hOE+J9znp/BeoxfxU66uVP/n9vah3V1gsJfsQYaap5 z/bYGUfW/UoS5iJ/yxmN85b21HG1tC4XgE0xrZ0UFbO7MT8pxkhYPKn+YMUfHs0tYmO8 E0gxk6wKMdyLBBOK6XnFXcWBTMLQwTy3r4UDumW6ukayx4QxPOg9XzR5choFboEk2zR3 S8Kg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=2XD6GLOy1WeMbVJM+mE9l+D4GurGc+LL2vthiVaNWmY=; b=bFHJpd0cCO4tfqIWyCnQPXgN2LkR+dqj3IcHFlTvKeZ8nPUoIzDJPxgeUiCxRAyB2O xKnoTQrvf5ZyqsTnT2NNNzMOr0axzOh7KxRtbehS5YQLNpWbwbPF30QxpLf7cyvni2zW alPSzg7kzy+lp6YlwX7ZbicB9GaVcsfyaM7WxA3rPLdcQ+jSnQuUG/JL7o1ZjNu8A4hh Xkdsk+WGpx+QFiJsJpb9NwP2DgMr6MnZzMaPV04GUXWyJgnIU0Vf4bA5DFyXgLA8r0UO /CqiRV5LxxjYlQUFm5ucDIkKzp6hywB8FNyGHideGTxkW2QSqFsURtSbPQyCz87q4dTS B9QA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZQ8ws5ja; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id q15si28102161pgh.714.2022.02.14.05.58.11; Mon, 14 Feb 2022 05:58:27 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZQ8ws5ja; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229986AbiBLSXt (ORCPT + 99 others); Sat, 12 Feb 2022 13:23:49 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:48070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230049AbiBLSXo (ORCPT ); Sat, 12 Feb 2022 13:23:44 -0500 Received: from mail-pj1-x1033.google.com (mail-pj1-x1033.google.com [IPv6:2607:f8b0:4864:20::1033]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 23198606D7 for ; Sat, 12 Feb 2022 10:23:26 -0800 (PST) Received: by mail-pj1-x1033.google.com with SMTP id h14-20020a17090a130e00b001b88991a305so14992881pja.3 for ; Sat, 12 Feb 2022 10:23:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2XD6GLOy1WeMbVJM+mE9l+D4GurGc+LL2vthiVaNWmY=; b=ZQ8ws5jacEDY80ooN3Y1PtbbBoqTJx2pmlj5MsuJAXCvaiM79s35ZAmULMIe0fx4Rm pf3bgdmHLGxiscLlFkNTIi7l9U1dqxHMJtPohpxrgIpVdTpOgRu8d4BlclDpGEVfTgjG yjcZZ+wZy4hWcmqm7EBh3G0OWitkP038EK+sFkrcbiN8cSZsvFSRDh+Y3+tWTUWypZpO m4LEie7uvPtV601HIIOdGisINSq1GqL9Im5R6pNpBBlkFshu5MfPoeKsj28ubiA73S5Z 0rb/b6Qw2Cz/VSPiYZG7nqa7RSs5CgzaFbkfeTmZlDTmy4Xo/+WxO6j+DYKFlBcScnNp chaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2XD6GLOy1WeMbVJM+mE9l+D4GurGc+LL2vthiVaNWmY=; b=Qd4ABj5oJ5X++q5PFXvabAshsxQ5wOSWt3ronUGWh38IhZ6SYYwthDWteHQMCq94Ei FEWi10Po7XGCNoIbbQ7b0B4t9cvmwFL9R2cJmB6hUB92/6aXtqESiHNsJEtacAL9brfV NU3GduzLYHYDAVLap62E944gSjW8SY50I2DNHyLyLpMl+k57rSUsZL4ys6EQjqziN8IQ hzwVB0+6mk3uYehLplCtStM6S0A2u8msofAnd/3Vxg+bXxVfwNLS6P8sv7wlqI8uJXRS J/QviPpB2xNQ3L+eXdQQjRepjPQj7nHxGPVokMq+4Y+UiV6xuG8yD0ZrAm/A5NBcfL+Y 3osA== X-Gm-Message-State: AOAM533bxb7gvzmXgiCsS33evlWskt9raiMpAxX5uLw9BWZ2Ug3Iav1R T8bAegVTdPzuZDpYi3k9t62E X-Received: by 2002:a17:90b:3810:: with SMTP id mq16mr6452775pjb.26.1644690205278; Sat, 12 Feb 2022 10:23:25 -0800 (PST) Received: from localhost.localdomain ([27.111.75.57]) by smtp.gmail.com with ESMTPSA id g12sm14961987pfj.148.2022.02.12.10.23.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 12 Feb 2022 10:23:24 -0800 (PST) From: Manivannan Sadhasivam To: mhi@lists.linux.dev Cc: quic_hemantk@quicinc.com, quic_bbhatt@quicinc.com, quic_jhugo@quicinc.com, vinod.koul@linaro.org, bjorn.andersson@linaro.org, dmitry.baryshkov@linaro.org, quic_vbadigan@quicinc.com, quic_cang@quicinc.com, quic_skananth@quicinc.com, linux-arm-msm@vger.kernel.org, linux-kernel@vger.kernel.org, elder@linaro.org, Manivannan Sadhasivam Subject: [PATCH v3 21/25] bus: mhi: ep: Add support for reading from the host Date: Sat, 12 Feb 2022 23:51:13 +0530 Message-Id: <20220212182117.49438-22-manivannan.sadhasivam@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220212182117.49438-1-manivannan.sadhasivam@linaro.org> References: <20220212182117.49438-1-manivannan.sadhasivam@linaro.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Data transfer between host and the ep device happens over the transfer ring associated with each bi-directional channel pair. Host defines the transfer ring by allocating memory for it. The read and write pointer addresses of the transfer ring are stored in the channel context. Once host places the elements in the transfer ring, it increments the write pointer and rings the channel doorbell. Device will receive the doorbell interrupt and will process the transfer ring elements. This commit adds support for reading the transfer ring elements from the transfer ring till write pointer, incrementing the read pointer and finally sending the completion event to the host through corresponding event ring. Signed-off-by: Manivannan Sadhasivam --- drivers/bus/mhi/ep/main.c | 103 ++++++++++++++++++++++++++++++++++++++ include/linux/mhi_ep.h | 9 ++++ 2 files changed, 112 insertions(+) diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c index 4c2ee517832c..b937c6cda9ba 100644 --- a/drivers/bus/mhi/ep/main.c +++ b/drivers/bus/mhi/ep/main.c @@ -336,6 +336,109 @@ int mhi_ep_process_cmd_ring(struct mhi_ep_ring *ring, struct mhi_ep_ring_element return ret; } +bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_dev, enum dma_data_direction dir) +{ + struct mhi_ep_chan *mhi_chan = (dir == DMA_FROM_DEVICE) ? mhi_dev->dl_chan : + mhi_dev->ul_chan; + struct mhi_ep_cntrl *mhi_cntrl = mhi_dev->mhi_cntrl; + struct mhi_ep_ring *ring = &mhi_cntrl->mhi_chan[mhi_chan->chan].ring; + + return !!(ring->rd_offset == ring->wr_offset); +} +EXPORT_SYMBOL_GPL(mhi_ep_queue_is_empty); + +static int mhi_ep_read_channel(struct mhi_ep_cntrl *mhi_cntrl, + struct mhi_ep_ring *ring, + struct mhi_result *result, + u32 len) +{ + struct mhi_ep_chan *mhi_chan = &mhi_cntrl->mhi_chan[ring->ch_id]; + size_t bytes_to_read, read_offset, write_offset; + struct device *dev = &mhi_cntrl->mhi_dev->dev; + struct mhi_ep_ring_element *el; + bool td_done = false; + void *write_to_loc; + u64 read_from_loc; + u32 buf_remaining; + int ret; + + buf_remaining = len; + + do { + /* Don't process the transfer ring if the channel is not in RUNNING state */ + if (mhi_chan->state != MHI_CH_STATE_RUNNING) + return -ENODEV; + + el = &ring->ring_cache[ring->rd_offset]; + + /* Check if there is data pending to be read from previous read operation */ + if (mhi_chan->tre_bytes_left) { + dev_dbg(dev, "TRE bytes remaining: %d\n", mhi_chan->tre_bytes_left); + bytes_to_read = min(buf_remaining, mhi_chan->tre_bytes_left); + } else { + mhi_chan->tre_loc = MHI_EP_TRE_GET_PTR(el); + mhi_chan->tre_size = MHI_EP_TRE_GET_LEN(el); + mhi_chan->tre_bytes_left = mhi_chan->tre_size; + + bytes_to_read = min(buf_remaining, mhi_chan->tre_size); + } + + read_offset = mhi_chan->tre_size - mhi_chan->tre_bytes_left; + write_offset = len - buf_remaining; + read_from_loc = mhi_chan->tre_loc + read_offset; + write_to_loc = result->buf_addr + write_offset; + + dev_dbg(dev, "Reading %zd bytes from channel (%d)\n", bytes_to_read, ring->ch_id); + ret = mhi_cntrl->read_from_host(mhi_cntrl, read_from_loc, write_to_loc, + bytes_to_read); + if (ret < 0) + return ret; + + buf_remaining -= bytes_to_read; + mhi_chan->tre_bytes_left -= bytes_to_read; + + /* + * Once the TRE (Transfer Ring Element) of a TD (Transfer Descriptor) has been + * read completely: + * + * 1. Send completion event to the host based on the flags set in TRE. + * 2. Increment the local read offset of the transfer ring. + */ + if (!mhi_chan->tre_bytes_left) { + /* + * The host will split the data packet into multiple TREs if it can't fit + * the packet in a single TRE. In that case, CHAIN flag will be set by the + * host for all TREs except the last one. + */ + if (MHI_EP_TRE_GET_CHAIN(el)) { + /* + * IEOB (Interrupt on End of Block) flag will be set by the host if + * it expects the completion event for all TREs of a TD. + */ + if (MHI_EP_TRE_GET_IEOB(el)) + mhi_ep_send_completion_event(mhi_cntrl, + ring, MHI_EP_TRE_GET_LEN(el), MHI_EV_CC_EOB); + } else { + /* + * IEOT (Interrupt on End of Transfer) flag will be set by the host + * for the last TRE of the TD and expects the completion event for + * the same. + */ + if (MHI_EP_TRE_GET_IEOT(el)) + mhi_ep_send_completion_event(mhi_cntrl, + ring, MHI_EP_TRE_GET_LEN(el), MHI_EV_CC_EOT); + td_done = true; + } + + mhi_ep_ring_inc_index(ring); + } + + result->bytes_xferd += bytes_to_read; + } while (buf_remaining && !td_done); + + return 0; +} + static int mhi_ep_cache_host_cfg(struct mhi_ep_cntrl *mhi_cntrl) { struct device *dev = &mhi_cntrl->mhi_dev->dev; diff --git a/include/linux/mhi_ep.h b/include/linux/mhi_ep.h index 276d29fef465..aaf4b6942037 100644 --- a/include/linux/mhi_ep.h +++ b/include/linux/mhi_ep.h @@ -268,4 +268,13 @@ int mhi_ep_power_up(struct mhi_ep_cntrl *mhi_cntrl); */ void mhi_ep_power_down(struct mhi_ep_cntrl *mhi_cntrl); +/** + * mhi_ep_queue_is_empty - Determine whether the transfer queue is empty + * @mhi_dev: Device associated with the channels + * @dir: DMA direction for the channel + * + * Return: true if the queue is empty, false otherwise. + */ +bool mhi_ep_queue_is_empty(struct mhi_ep_device *mhi_dev, enum dma_data_direction dir); + #endif -- 2.25.1