From patchwork Mon May 18 20:03:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhaumik Bhatt X-Patchwork-Id: 189095 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8FDE3C433E1 for ; Mon, 18 May 2020 20:04:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6A3D7206D4 for ; Mon, 18 May 2020 20:04:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="mSixlheT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726643AbgERUEL (ORCPT ); Mon, 18 May 2020 16:04:11 -0400 Received: from mail27.static.mailgun.info ([104.130.122.27]:56393 "EHLO mail27.static.mailgun.info" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726977AbgERUEK (ORCPT ); Mon, 18 May 2020 16:04:10 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1589832250; h=References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=j1u5QBULuJKFUyNxaQAkdzuQVerFj62srXNJ8V0Lrak=; b=mSixlheT/ZnceK4/8Yvu+Lt0uc9yIhMf0hAwudJa9MUTc133Jufj/b2ovvyQyXBRSWKPtASE HkTB9SZ9fCpXXh01yIEutPc7/x4NRcfk32rkqVMGHMfZihdwzqwr579z6LtRmIhBWgaHu1wB bkB5xqsVyuDd3x94KQe85DTa3u0= X-Mailgun-Sending-Ip: 104.130.122.27 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by mxa.mailgun.org with ESMTP id 5ec2ea38.7efd1e647110-smtp-out-n02; Mon, 18 May 2020 20:04:08 -0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 0B1C6C433D2; Mon, 18 May 2020 20:04:08 +0000 (UTC) Received: from bbhatt-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: bbhatt) by smtp.codeaurora.org (Postfix) with ESMTPSA id 656E0C433F2; Mon, 18 May 2020 20:04:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 656E0C433F2 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=none smtp.mailfrom=bbhatt@codeaurora.org From: Bhaumik Bhatt To: manivannan.sadhasivam@linaro.org Cc: linux-arm-msm@vger.kernel.org, hemantk@codeaurora.org, jhugo@codeaurora.org, linux-kernel@vger.kernel.org, Bhaumik Bhatt Subject: [PATCH v3 1/7] bus: mhi: core: Abort suspends due to outgoing pending packets Date: Mon, 18 May 2020 13:03:55 -0700 Message-Id: <1589832241-13867-2-git-send-email-bbhatt@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> References: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add the missing check to abort suspends if a client has pending outgoing packets to send to the device. This allows better utilization of the MHI bus wherein clients on the host are not left waiting for longer suspend or resume cycles to finish for data transfers. Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/core/pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c index 7960980..661d704 100644 --- a/drivers/bus/mhi/core/pm.c +++ b/drivers/bus/mhi/core/pm.c @@ -686,7 +686,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) return -EIO; /* Return busy if there are any pending resources */ - if (atomic_read(&mhi_cntrl->dev_wake)) + if (atomic_read(&mhi_cntrl->dev_wake) || + atomic_read(&mhi_cntrl->pending_pkts)) return -EBUSY; /* Take MHI out of M2 state */ @@ -712,7 +713,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) write_lock_irq(&mhi_cntrl->pm_lock); - if (atomic_read(&mhi_cntrl->dev_wake)) { + if (atomic_read(&mhi_cntrl->dev_wake) || + atomic_read(&mhi_cntrl->pending_pkts)) { write_unlock_irq(&mhi_cntrl->pm_lock); return -EBUSY; } From patchwork Mon May 18 20:03:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhaumik Bhatt X-Patchwork-Id: 189093 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F38BC433E1 for ; Mon, 18 May 2020 20:04:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DAF3320758 for ; Mon, 18 May 2020 20:04:25 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="HYag6CAE" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726944AbgERUEZ (ORCPT ); Mon, 18 May 2020 16:04:25 -0400 Received: from mail26.static.mailgun.info ([104.130.122.26]:23747 "EHLO mail26.static.mailgun.info" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727097AbgERUEL (ORCPT ); Mon, 18 May 2020 16:04:11 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1589832250; h=References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=VSrAsJl4eIdVmCgK111TLxHorgMNPuXYMXrr4jRpcks=; b=HYag6CAEkPfptBdSzddi9RDyd7s7pQ3ZfhFuxllh92CRQa1nIx4QrJmp6bsQ93XG075cNV4Q UVQaU89ILteegSqxzdAr/4wo2CxCNUJWifPG3uNlrIWKCeop5WgDR5WqsHbZjN6qKycZGfBN bmwwGjqp8F57r9k9NHnVlCAkL54= X-Mailgun-Sending-Ip: 104.130.122.26 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by mxa.mailgun.org with ESMTP id 5ec2ea39.7f1ff0ba8f48-smtp-out-n05; Mon, 18 May 2020 20:04:09 -0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1001) id B438EC433F2; Mon, 18 May 2020 20:04:09 +0000 (UTC) Received: from bbhatt-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: bbhatt) by smtp.codeaurora.org (Postfix) with ESMTPSA id D5588C43637; Mon, 18 May 2020 20:04:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org D5588C43637 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=none smtp.mailfrom=bbhatt@codeaurora.org From: Bhaumik Bhatt To: manivannan.sadhasivam@linaro.org Cc: linux-arm-msm@vger.kernel.org, hemantk@codeaurora.org, jhugo@codeaurora.org, linux-kernel@vger.kernel.org, Bhaumik Bhatt Subject: [PATCH v3 2/7] bus: mhi: core: Introduce independent voting mechanism Date: Mon, 18 May 2020 13:03:56 -0700 Message-Id: <1589832241-13867-3-git-send-email-bbhatt@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> References: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Allow independent votes from clients such that they can choose to vote for either the device or the bus or both. This helps in cases where the device supports autonomous low power mode wherein it can move to M2 state without the need to notify the host. Clients can also vote only to keep the underlying bus active without having the device in M0 state to support offload use cases. Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/core/init.c | 15 ++++++---- drivers/bus/mhi/core/pm.c | 73 +++++++++++++++++++++++++++++++++------------ include/linux/mhi.h | 21 ++++++++----- 3 files changed, 77 insertions(+), 32 deletions(-) diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c index e43a190..b7b5f7f 100644 --- a/drivers/bus/mhi/core/init.c +++ b/drivers/bus/mhi/core/init.c @@ -1062,7 +1062,8 @@ struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl) dev->release = mhi_release_device; dev->parent = mhi_cntrl->cntrl_dev; mhi_dev->mhi_cntrl = mhi_cntrl; - mhi_dev->dev_wake = 0; + atomic_set(&mhi_dev->dev_vote, 0); + atomic_set(&mhi_dev->bus_vote, 0); return mhi_dev; } @@ -1079,7 +1080,7 @@ static int mhi_driver_probe(struct device *dev) int ret; /* Bring device out of LPM */ - ret = mhi_device_get_sync(mhi_dev); + ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_DEVICE); if (ret) return ret; @@ -1139,14 +1140,14 @@ static int mhi_driver_probe(struct device *dev) if (dl_chan && dl_chan->auto_start) mhi_prepare_channel(mhi_cntrl, dl_chan); - mhi_device_put(mhi_dev); + mhi_device_put(mhi_dev, MHI_VOTE_DEVICE); return ret; exit_probe: mhi_unprepare_from_transfer(mhi_dev); - mhi_device_put(mhi_dev); + mhi_device_put(mhi_dev, MHI_VOTE_DEVICE); return ret; } @@ -1215,8 +1216,10 @@ static int mhi_driver_remove(struct device *dev) } read_lock_bh(&mhi_cntrl->pm_lock); - while (mhi_dev->dev_wake) - mhi_device_put(mhi_dev); + while (atomic_read(&mhi_dev->dev_vote)) + mhi_device_put(mhi_dev, MHI_VOTE_DEVICE); + while (atomic_read(&mhi_dev->bus_vote)) + mhi_device_put(mhi_dev, MHI_VOTE_BUS); read_unlock_bh(&mhi_cntrl->pm_lock); return 0; diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c index 661d704..4c9812a 100644 --- a/drivers/bus/mhi/core/pm.c +++ b/drivers/bus/mhi/core/pm.c @@ -675,7 +675,8 @@ void mhi_pm_st_worker(struct work_struct *work) int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) { struct mhi_chan *itr, *tmp; - struct device *dev = &mhi_cntrl->mhi_dev->dev; + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + struct device *dev = &mhi_dev->dev; enum mhi_pm_state new_state; int ret; @@ -687,7 +688,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) /* Return busy if there are any pending resources */ if (atomic_read(&mhi_cntrl->dev_wake) || - atomic_read(&mhi_cntrl->pending_pkts)) + atomic_read(&mhi_cntrl->pending_pkts) || + atomic_read(&mhi_dev->bus_vote)) return -EBUSY; /* Take MHI out of M2 state */ @@ -714,7 +716,8 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) write_lock_irq(&mhi_cntrl->pm_lock); if (atomic_read(&mhi_cntrl->dev_wake) || - atomic_read(&mhi_cntrl->pending_pkts)) { + atomic_read(&mhi_cntrl->pending_pkts) || + atomic_read(&mhi_dev->bus_vote)) { write_unlock_irq(&mhi_cntrl->pm_lock); return -EBUSY; } @@ -1109,42 +1112,74 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) } EXPORT_SYMBOL_GPL(mhi_force_rddm_mode); -void mhi_device_get(struct mhi_device *mhi_dev) +void mhi_device_get(struct mhi_device *mhi_dev, int vote) { struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - mhi_dev->dev_wake++; - read_lock_bh(&mhi_cntrl->pm_lock); - mhi_cntrl->wake_get(mhi_cntrl, true); - read_unlock_bh(&mhi_cntrl->pm_lock); + if (vote & MHI_VOTE_DEVICE) { + atomic_inc(&mhi_dev->dev_vote); + read_lock_bh(&mhi_cntrl->pm_lock); + mhi_cntrl->wake_get(mhi_cntrl, true); + read_unlock_bh(&mhi_cntrl->pm_lock); + } + + if (vote & MHI_VOTE_BUS) { + atomic_inc(&mhi_dev->bus_vote); + mhi_cntrl->runtime_get(mhi_cntrl); + } } EXPORT_SYMBOL_GPL(mhi_device_get); -int mhi_device_get_sync(struct mhi_device *mhi_dev) +int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote) { struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; int ret; + /* bring device out of low power modes regardless of the type of vote */ ret = __mhi_device_get_sync(mhi_cntrl); - if (!ret) - mhi_dev->dev_wake++; + if (ret) + return ret; + + if (vote & MHI_VOTE_DEVICE) { + atomic_inc(&mhi_dev->dev_vote); + } else { + /* remove device vote as it was not requested */ + read_lock_bh(&mhi_cntrl->pm_lock); + mhi_cntrl->wake_put(mhi_cntrl, false); + read_unlock_bh(&mhi_cntrl->pm_lock); + } + + if (vote & MHI_VOTE_BUS) { + atomic_inc(&mhi_dev->bus_vote); + mhi_cntrl->runtime_get(mhi_cntrl); + } return ret; } EXPORT_SYMBOL_GPL(mhi_device_get_sync); -void mhi_device_put(struct mhi_device *mhi_dev) +void mhi_device_put(struct mhi_device *mhi_dev, int vote) { struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl; - mhi_dev->dev_wake--; - read_lock_bh(&mhi_cntrl->pm_lock); - if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { - mhi_cntrl->runtime_get(mhi_cntrl); - mhi_cntrl->runtime_put(mhi_cntrl); + if (vote & MHI_VOTE_DEVICE) { + atomic_dec(&mhi_dev->dev_vote); + read_lock_bh(&mhi_cntrl->pm_lock); + if (MHI_PM_IN_SUSPEND_STATE(mhi_cntrl->pm_state)) { + mhi_cntrl->runtime_get(mhi_cntrl); + mhi_cntrl->runtime_put(mhi_cntrl); + } + mhi_cntrl->wake_put(mhi_cntrl, false); + read_unlock_bh(&mhi_cntrl->pm_lock); } - mhi_cntrl->wake_put(mhi_cntrl, false); - read_unlock_bh(&mhi_cntrl->pm_lock); + if (vote & MHI_VOTE_BUS) { + atomic_dec(&mhi_dev->bus_vote); + mhi_cntrl->runtime_put(mhi_cntrl); + + /* notify controller that all bus votes are removed */ + if (!atomic_read(&mhi_dev->bus_vote)) + mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_IDLE); + } } EXPORT_SYMBOL_GPL(mhi_device_put); diff --git a/include/linux/mhi.h b/include/linux/mhi.h index b008914..10fcb52 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -16,6 +16,9 @@ #include #include +#define MHI_VOTE_BUS BIT(0) /* do not disable the mhi bus */ +#define MHI_VOTE_DEVICE BIT(1) /* prevent mhi device from entering lpm */ + struct mhi_chan; struct mhi_event; struct mhi_ctxt; @@ -459,7 +462,8 @@ struct mhi_device { enum mhi_device_type dev_type; int ul_chan_id; int dl_chan_id; - u32 dev_wake; + atomic_t dev_vote; + atomic_t bus_vote; }; /** @@ -644,23 +648,26 @@ void mhi_set_mhi_state(struct mhi_controller *mhi_cntrl, enum mhi_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl); /** - * mhi_device_get - Disable device low power mode + * mhi_device_get - Disable device and/or bus low power mode * @mhi_dev: Device associated with the channel + * @vote: requested vote (bus, device or both) */ -void mhi_device_get(struct mhi_device *mhi_dev); +void mhi_device_get(struct mhi_device *mhi_dev, int vote); /** - * mhi_device_get_sync - Disable device low power mode. Synchronously + * mhi_device_get_sync - Disable device and/or bus low power mode. Synchronously * take the controller out of suspended state * @mhi_dev: Device associated with the channel + * @vote: requested vote (bus, device or both) */ -int mhi_device_get_sync(struct mhi_device *mhi_dev); +int mhi_device_get_sync(struct mhi_device *mhi_dev, int vote); /** - * mhi_device_put - Re-enable device low power mode + * mhi_device_put - Re-enable device and/or bus low power mode * @mhi_dev: Device associated with the channel + * @vote: vote(s) to remove (bus, device or both) */ -void mhi_device_put(struct mhi_device *mhi_dev); +void mhi_device_put(struct mhi_device *mhi_dev, int vote); /** * mhi_prepare_for_transfer - Setup channel for data transfer From patchwork Mon May 18 20:03:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhaumik Bhatt X-Patchwork-Id: 189094 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8371FC433E1 for ; Mon, 18 May 2020 20:04:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 558FC206D4 for ; Mon, 18 May 2020 20:04:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="e9tGY0Xh" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727885AbgERUEO (ORCPT ); Mon, 18 May 2020 16:04:14 -0400 Received: from mail27.static.mailgun.info ([104.130.122.27]:56393 "EHLO mail27.static.mailgun.info" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727779AbgERUEN (ORCPT ); Mon, 18 May 2020 16:04:13 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1589832251; h=References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=/SUfSPUoqn6OnyjDAHMI6DuHAZBY/StGSsAcg7IZHw4=; b=e9tGY0Xhp33Pveq88RzIl8+n8eJGu2zK8rcT4TP7WFrOodbya22pXrVNi5l4FGHOrIGXLMwc 2jqXmcvZbF9icPy8azNGP/8R1fBqeNqBvXk3WWqbwvkAAFCYoUrFv+2eKrrYJ1L8AwhRybQE FGaBd6nvdGVcrogqIJyv6KXHcbM= X-Mailgun-Sending-Ip: 104.130.122.27 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by mxa.mailgun.org with ESMTP id 5ec2ea3b.7f006810e378-smtp-out-n02; Mon, 18 May 2020 20:04:11 -0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 0BCA0C433D2; Mon, 18 May 2020 20:04:11 +0000 (UTC) Received: from bbhatt-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: bbhatt) by smtp.codeaurora.org (Postfix) with ESMTPSA id 2F83DC44792; Mon, 18 May 2020 20:04:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 2F83DC44792 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=none smtp.mailfrom=bbhatt@codeaurora.org From: Bhaumik Bhatt To: manivannan.sadhasivam@linaro.org Cc: linux-arm-msm@vger.kernel.org, hemantk@codeaurora.org, jhugo@codeaurora.org, linux-kernel@vger.kernel.org, Bhaumik Bhatt Subject: [PATCH v3 5/7] bus: mhi: core: Introduce debugfs entries and counters for MHI Date: Mon, 18 May 2020 13:03:59 -0700 Message-Id: <1589832241-13867-6-git-send-email-bbhatt@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> References: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Introduce debugfs entries to show state, register, channel, and event ring information. Add MHI state counters to keep track of the state changes on the device. Also, allow the host to trigger a device reset, issue bus or device votes, and change the MHI timeout to help in debug. Signed-off-by: Bhaumik Bhatt --- drivers/bus/mhi/Kconfig | 8 + drivers/bus/mhi/core/Makefile | 5 +- drivers/bus/mhi/core/debugfs.c | 501 ++++++++++++++++++++++++++++++++++++++++ drivers/bus/mhi/core/init.c | 7 + drivers/bus/mhi/core/internal.h | 24 ++ drivers/bus/mhi/core/pm.c | 4 + include/linux/mhi.h | 4 + 7 files changed, 550 insertions(+), 3 deletions(-) create mode 100644 drivers/bus/mhi/core/debugfs.c diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig index a8bd9bd..6a217ff 100644 --- a/drivers/bus/mhi/Kconfig +++ b/drivers/bus/mhi/Kconfig @@ -12,3 +12,11 @@ config MHI_BUS communication protocol used by the host processors to control and communicate with modem devices over a high speed peripheral bus or shared memory. + +config MHI_BUS_DEBUG + bool "Debugfs support for the MHI bus" + depends on MHI_BUS && DEBUG_FS + help + Enable debugfs support for use with the MHI transport. Allows + reading and/or modifying some values within the MHI controller + for debug and test purposes. diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/core/Makefile index 66e2700..460a548 100644 --- a/drivers/bus/mhi/core/Makefile +++ b/drivers/bus/mhi/core/Makefile @@ -1,3 +1,2 @@ -obj-$(CONFIG_MHI_BUS) := mhi.o - -mhi-y := init.o main.o pm.o boot.o +obj-$(CONFIG_MHI_BUS) := init.o main.o pm.o boot.o +obj-$(CONFIG_MHI_BUS_DEBUG) += debugfs.o diff --git a/drivers/bus/mhi/core/debugfs.c b/drivers/bus/mhi/core/debugfs.c new file mode 100644 index 0000000..b37de83 --- /dev/null +++ b/drivers/bus/mhi/core/debugfs.c @@ -0,0 +1,501 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include "internal.h" + +static int mhi_debugfs_states_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + + /* states */ + seq_printf(m, "PM state:%s Device:%s MHI state:%s EE:%s wake:%s\n", + to_mhi_pm_state_str(mhi_cntrl->pm_state), + mhi_is_active(mhi_cntrl) ? "Active" : "Inactive", + TO_MHI_STATE_STR(mhi_cntrl->dev_state), + TO_MHI_EXEC_STR(mhi_cntrl->ee), + mhi_cntrl->wake_set ? "true" : "false"); + + /* counters */ + seq_printf(m, "M0:%u M2:%u M3:%u M3_Fast:%u", mhi_cntrl->M0, + mhi_cntrl->M2, mhi_cntrl->M3, mhi_cntrl->M3_fast); + + seq_printf(m, " device wake:%u pending packets:%u\n", + atomic_read(&mhi_cntrl->dev_wake), + atomic_read(&mhi_cntrl->pending_pkts)); + + return 0; +} + +static int mhi_debugfs_events_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + struct mhi_event *mhi_event; + struct mhi_event_ctxt *er_ctxt; + int i; + + if (!mhi_is_active(mhi_cntrl)) { + seq_puts(m, "Device not ready\n"); + return -ENODEV; + } + + er_ctxt = mhi_cntrl->mhi_ctxt->er_ctxt; + mhi_event = mhi_cntrl->mhi_event; + for (i = 0; i < mhi_cntrl->total_ev_rings; + i++, er_ctxt++, mhi_event++) { + struct mhi_ring *ring = &mhi_event->ring; + + if (mhi_event->offload_ev) { + seq_printf(m, "Index:%d is an offload event ring\n", i); + continue; + } + + seq_printf(m, "Index:%d intmod count:%lu time:%lu", + i, (er_ctxt->intmod & EV_CTX_INTMODC_MASK) >> + EV_CTX_INTMODC_SHIFT, + (er_ctxt->intmod & EV_CTX_INTMODT_MASK) >> + EV_CTX_INTMODT_SHIFT); + + seq_printf(m, " base:0x%0llx len:0x%llx", er_ctxt->rbase, + er_ctxt->rlen); + + seq_printf(m, + " rp:0x%llx wp:0x%llx local rp:0x%llx db:0x%llx\n", + er_ctxt->rp, er_ctxt->wp, (u64)ring->rp, + mhi_event->db_cfg.db_val); + } + + return 0; +} + +static int mhi_debugfs_channels_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + struct mhi_chan *mhi_chan; + struct mhi_chan_ctxt *chan_ctxt; + int i; + + if (!mhi_is_active(mhi_cntrl)) { + seq_puts(m, "Device not ready\n"); + return -ENODEV; + } + + mhi_chan = mhi_cntrl->mhi_chan; + chan_ctxt = mhi_cntrl->mhi_ctxt->chan_ctxt; + for (i = 0; i < mhi_cntrl->max_chan; i++, chan_ctxt++, mhi_chan++) { + struct mhi_ring *ring = &mhi_chan->tre_ring; + + if (mhi_chan->offload_ch) { + seq_printf(m, "%s(%u) is an offload channel\n", + mhi_chan->name, mhi_chan->chan); + continue; + } + + if (!mhi_chan->mhi_dev) + continue; + + seq_printf(m, + "%s(%u) state:0x%lx brstmode:0x%lx pollcfg:0x%lx", + mhi_chan->name, mhi_chan->chan, (chan_ctxt->chcfg & + CHAN_CTX_CHSTATE_MASK) >> CHAN_CTX_CHSTATE_SHIFT, + (chan_ctxt->chcfg & CHAN_CTX_BRSTMODE_MASK) >> + CHAN_CTX_BRSTMODE_SHIFT, (chan_ctxt->chcfg & + CHAN_CTX_POLLCFG_MASK) >> CHAN_CTX_POLLCFG_SHIFT); + + seq_printf(m, " type:0x%x event ring:%u", chan_ctxt->chtype, + chan_ctxt->erindex); + + seq_printf(m, " base:0x%llx len:0x%llx wp:0x%llx", + chan_ctxt->rbase, chan_ctxt->rlen, chan_ctxt->wp); + + seq_printf(m, " local rp:0x%llx local wp:0x%llx db:0x%llx\n", + (u64)ring->rp, (u64)ring->wp, + mhi_chan->db_cfg.db_val); + } + + return 0; +} + +static int mhi_device_votes_show(struct device *dev, void *data) +{ + struct mhi_device *mhi_dev; + + if (dev->bus != &mhi_bus_type) + return 0; + + mhi_dev = to_mhi_device(dev); + + seq_printf((struct seq_file *)data, "%s: device:%u, bus:%u\n", + mhi_dev->name, atomic_read(&mhi_dev->dev_vote), + atomic_read(&mhi_dev->bus_vote)); + + return 0; +} + +static int mhi_debugfs_votes_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + + if (!mhi_is_active(mhi_cntrl)) { + seq_puts(m, "Device not ready\n"); + return -ENODEV; + } + + device_for_each_child(mhi_cntrl->cntrl_dev, m, mhi_device_votes_show); + + return 0; +} + +static int mhi_debugfs_regdump_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + enum mhi_state state; + enum mhi_ee_type ee; + int i, ret = -EIO; + u32 val; + void __iomem *mhi_base = mhi_cntrl->regs; + void __iomem *bhi_base = mhi_cntrl->bhi; + void __iomem *bhie_base = mhi_cntrl->bhie; + void __iomem *wake_db = mhi_cntrl->wake_db; + struct { + const char *name; + int offset; + void __iomem *base; + } debug_regs[] = { + { "MHI_CTRL", MHICTRL, mhi_base}, + { "MHI_STATUS", MHISTATUS, mhi_base}, + { "MHI_WAKE_DB", 0, wake_db}, + { "BHI_EXECENV", BHI_EXECENV, bhi_base}, + { "BHI_STATUS", BHI_STATUS, bhi_base}, + { "BHI_ERRCODE", BHI_ERRCODE, bhi_base}, + { "BHI_ERRDBG1", BHI_ERRDBG1, bhi_base}, + { "BHI_ERRDBG2", BHI_ERRDBG2, bhi_base}, + { "BHI_ERRDBG3", BHI_ERRDBG3, bhi_base}, + { "BHIE_TXVEC_DB", BHIE_TXVECDB_OFFS, bhie_base}, + { "BHIE_TXVEC_STATUS", BHIE_TXVECSTATUS_OFFS, bhie_base}, + { "BHIE_RXVEC_DB", BHIE_RXVECDB_OFFS, bhie_base}, + { "BHIE_RXVEC_STATUS", BHIE_RXVECSTATUS_OFFS, bhie_base}, + { NULL }, + }; + + if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) + return ret; + + seq_printf(m, "Host PM state:%s Device state:%s EE:%s\n", + to_mhi_pm_state_str(mhi_cntrl->pm_state), + TO_MHI_STATE_STR(mhi_cntrl->dev_state), + TO_MHI_EXEC_STR(mhi_cntrl->ee)); + + state = mhi_get_mhi_state(mhi_cntrl); + ee = mhi_get_exec_env(mhi_cntrl); + seq_printf(m, "Device EE:%s state:%s\n", TO_MHI_EXEC_STR(ee), + TO_MHI_STATE_STR(state)); + + for (i = 0; debug_regs[i].name; i++) { + ret = mhi_read_reg(mhi_cntrl, debug_regs[i].base, + debug_regs[i].offset, &val); + if (ret) + continue; + + seq_printf(m, "%s:0x%x\n", debug_regs[i].name, val); + } + + return 0; +} + +static int mhi_debugfs_bus_vote_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + + if (!mhi_is_active(mhi_cntrl)) { + seq_puts(m, "Device not ready\n"); + return -ENODEV; + } + + seq_printf(m, "Votes: %d\n%s\n", atomic_read(&mhi_dev->bus_vote), + "Usage: echo get/put > bus_vote for vote/unvote"); + + return 0; +} + +static ssize_t mhi_debugfs_bus_vote_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = file->private_data; + struct mhi_controller *mhi_cntrl = m->private; + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + char buf[32]; + int ret = -EINVAL; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "get", 3)) { + ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_BUS); + } else if (!strncmp(buf, "put", 3)) { + mhi_device_put(mhi_dev, MHI_VOTE_BUS); + ret = 0; + } + + return ret ? ret : count; +} + +static int mhi_debugfs_device_vote_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + + if (!mhi_is_active(mhi_cntrl)) { + seq_puts(m, "Device not ready\n"); + return -ENODEV; + } + + seq_printf(m, + "Votes: %d\n%s\n", atomic_read(&mhi_dev->dev_vote), + "Usage: echo get/put > device_vote for vote/unvote"); + + return 0; +} + +static ssize_t mhi_debugfs_device_vote_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = file->private_data; + struct mhi_controller *mhi_cntrl = m->private; + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + char buf[32]; + int ret = -EINVAL; + + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) + return -EFAULT; + + if (!strncmp(buf, "get", 3)) { + ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_DEVICE); + } else if (!strncmp(buf, "put", 3)) { + mhi_device_put(mhi_dev, MHI_VOTE_DEVICE); + ret = 0; + } + + return ret ? ret : count; +} + +static int mhi_debugfs_timeout_ms_show(struct seq_file *m, void *d) +{ + struct mhi_controller *mhi_cntrl = m->private; + + seq_printf(m, "%u ms\n", mhi_cntrl->timeout_ms); + + return 0; +} + +static ssize_t mhi_debugfs_timeout_ms_write(struct file *file, + const char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct seq_file *m = file->private_data; + struct mhi_controller *mhi_cntrl = m->private; + u32 timeout_ms; + + if (kstrtou32_from_user(ubuf, count, 0, &timeout_ms)) + return -EINVAL; + + mhi_cntrl->timeout_ms = timeout_ms; + + return count; +} + +static int mhi_debugfs_trigger_reset(void *data, u64 val) +{ + struct mhi_controller *mhi_cntrl = data; + struct mhi_device *mhi_dev = mhi_cntrl->mhi_dev; + struct device *dev = &mhi_dev->dev; + enum mhi_pm_state cur_state; + int ret = -EIO; + + if (!mhi_is_active(mhi_cntrl)) + return -ENODEV; + + if (!val) + return -EINVAL; + + ret = mhi_device_get_sync(mhi_dev, MHI_VOTE_DEVICE); + if (ret) { + dev_err(dev, "Device did not enter M0 state, MHI:%s, PM:%s\n", + TO_MHI_STATE_STR(mhi_cntrl->dev_state), + to_mhi_pm_state_str(mhi_cntrl->pm_state)); + return ret; + } + + if (mhi_cntrl->rddm_image) { + ret = mhi_force_rddm_mode(mhi_cntrl); + goto exit_mhi_trigger_reset; + } + + write_lock_irq(&mhi_cntrl->pm_lock); + cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_SYS_ERR_DETECT); + write_unlock_irq(&mhi_cntrl->pm_lock); + + if (cur_state != MHI_PM_SYS_ERR_DETECT) + goto exit_mhi_trigger_reset; + + mhi_pm_sys_err_handler(mhi_cntrl); + ret = 0; + +exit_mhi_trigger_reset: + mhi_device_put(mhi_dev, MHI_VOTE_DEVICE); + + return ret; +} + +static int mhi_debugfs_states_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_states_show, inode->i_private); +} + +static int mhi_debugfs_events_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_events_show, inode->i_private); +} + +static int mhi_debugfs_channels_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_channels_show, inode->i_private); +} + +static int mhi_debugfs_votes_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_votes_show, inode->i_private); +} + +static int mhi_debugfs_regdump_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_regdump_show, inode->i_private); +} + +static int mhi_debugfs_bus_vote_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_bus_vote_show, inode->i_private); +} + +static int mhi_debugfs_device_vote_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_device_vote_show, inode->i_private); +} + +static int mhi_debugfs_timeout_ms_open(struct inode *inode, struct file *fp) +{ + return single_open(fp, mhi_debugfs_timeout_ms_show, inode->i_private); +} + +static const struct file_operations debugfs_states_fops = { + .open = mhi_debugfs_states_open, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_events_fops = { + .open = mhi_debugfs_events_open, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_channels_fops = { + .open = mhi_debugfs_channels_open, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_votes_fops = { + .open = mhi_debugfs_votes_open, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_regdump_fops = { + .open = mhi_debugfs_regdump_open, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_bus_vote_fops = { + .open = mhi_debugfs_bus_vote_open, + .write = mhi_debugfs_bus_vote_write, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_device_vote_fops = { + .open = mhi_debugfs_device_vote_open, + .write = mhi_debugfs_device_vote_write, + .release = single_release, + .read = seq_read, +}; + +static const struct file_operations debugfs_timeout_ms_fops = { + .open = mhi_debugfs_timeout_ms_open, + .write = mhi_debugfs_timeout_ms_write, + .release = single_release, + .read = seq_read, +}; + +DEFINE_DEBUGFS_ATTRIBUTE(debugfs_reset_fops, NULL, + mhi_debugfs_trigger_reset, "%llu\n"); + +static struct dentry *mhi_debugfs_root; + +void mhi_create_debugfs(struct mhi_controller *mhi_cntrl) +{ + if (IS_ERR_OR_NULL(mhi_debugfs_root)) + return; + + mhi_cntrl->debugfs_dentry = + debugfs_create_dir(dev_name(mhi_cntrl->cntrl_dev), + mhi_debugfs_root); + if (IS_ERR_OR_NULL(mhi_cntrl->debugfs_dentry)) + return; + + debugfs_create_file("states", 0444, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_states_fops); + debugfs_create_file("events", 0444, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_events_fops); + debugfs_create_file("channels", 0444, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_channels_fops); + debugfs_create_file("votes", 0444, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_votes_fops); + debugfs_create_file("regdump", 0444, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_regdump_fops); + debugfs_create_file("bus_vote", 0644, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_bus_vote_fops); + debugfs_create_file("device_vote", 0644, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_device_vote_fops); + debugfs_create_file("timeout_ms", 0644, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_timeout_ms_fops); + debugfs_create_file("reset", 0444, mhi_cntrl->debugfs_dentry, + mhi_cntrl, &debugfs_reset_fops); +} + +void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl) +{ + debugfs_remove_recursive(mhi_cntrl->debugfs_dentry); + mhi_cntrl->debugfs_dentry = NULL; +} + +void mhi_debugfs_init(void) +{ + mhi_debugfs_root = debugfs_create_dir(mhi_bus_type.name, NULL); +} + +void mhi_debugfs_exit(void) +{ + debugfs_remove_recursive(mhi_debugfs_root); +} diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c index 0d39779..83ad544 100644 --- a/drivers/bus/mhi/core/init.c +++ b/drivers/bus/mhi/core/init.c @@ -4,6 +4,7 @@ * */ +#include #include #include #include @@ -915,6 +916,8 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, mhi_cntrl->mhi_dev = mhi_dev; + mhi_create_debugfs(mhi_cntrl); + return 0; error_add_dev: @@ -937,6 +940,8 @@ void mhi_unregister_controller(struct mhi_controller *mhi_cntrl) struct mhi_chan *mhi_chan = mhi_cntrl->mhi_chan; unsigned int i; + mhi_destroy_debugfs(mhi_cntrl); + kfree(mhi_cntrl->mhi_cmd); kfree(mhi_cntrl->mhi_event); @@ -1287,11 +1292,13 @@ struct bus_type mhi_bus_type = { static int __init mhi_init(void) { + mhi_debugfs_init(); return bus_register(&mhi_bus_type); } static void __exit mhi_exit(void) { + mhi_debugfs_exit(); bus_unregister(&mhi_bus_type); } diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/core/internal.h index 2f18be7..798aa483 100644 --- a/drivers/bus/mhi/core/internal.h +++ b/drivers/bus/mhi/core/internal.h @@ -570,6 +570,30 @@ struct mhi_chan { /* Default MHI timeout */ #define MHI_TIMEOUT_MS (1000) +/* debugfs related functions */ +#ifdef CONFIG_MHI_BUS_DEBUG +void mhi_create_debugfs(struct mhi_controller *mhi_cntrl); +void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl); +void mhi_debugfs_init(void); +void mhi_debugfs_exit(void); +#else +static inline void mhi_create_debugfs(struct mhi_controller *mhi_cntrl) +{ +} + +static inline void mhi_destroy_debugfs(struct mhi_controller *mhi_cntrl) +{ +} + +static inline void mhi_debugfs_init(void) +{ +} + +static inline void mhi_debugfs_exit(void) +{ +} +#endif + struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl); int mhi_destroy_device(struct device *dev, void *data); diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c index 4c9812a..783e3d5 100644 --- a/drivers/bus/mhi/core/pm.c +++ b/drivers/bus/mhi/core/pm.c @@ -256,6 +256,7 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl) dev_err(dev, "Unable to transition to M0 state\n"); return -EIO; } + mhi_cntrl->M0++; /* Wake up the device */ read_lock_bh(&mhi_cntrl->pm_lock); @@ -326,6 +327,8 @@ void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) mhi_cntrl->dev_state = MHI_STATE_M2; write_unlock_irq(&mhi_cntrl->pm_lock); + + mhi_cntrl->M2++; wake_up_all(&mhi_cntrl->state_event); /* If there are any pending resources, exit M2 immediately */ @@ -362,6 +365,7 @@ int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl) return -EIO; } + mhi_cntrl->M3++; wake_up_all(&mhi_cntrl->state_event); return 0; diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 9b7bf28..026a624 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -291,6 +291,7 @@ struct mhi_controller_config { * @cntrl_dev: Pointer to the struct device of physical bus acting as the MHI * controller (required) * @mhi_dev: MHI device instance for the controller + * @debugfs_dentry: MHI controller debugfs directory * @regs: Base address of MHI MMIO register space (required) * @bhi: Points to base of MHI BHI register space * @bhie: Points to base of MHI BHIe register space @@ -329,6 +330,7 @@ struct mhi_controller_config { * @dev_state: MHI device state * @dev_wake: Device wakeup count * @pending_pkts: Pending packets for the controller + * @M0, M2, M3, M3_fast: Counters to track number of device MHI state changes * @transition_list: List of MHI state transitions * @transition_lock: Lock for protecting MHI state transition list * @wlock: Lock for protecting device wakeup @@ -367,6 +369,7 @@ struct mhi_controller_config { struct mhi_controller { struct device *cntrl_dev; struct mhi_device *mhi_dev; + struct dentry *debugfs_dentry; void __iomem *regs; void __iomem *bhi; void __iomem *bhie; @@ -408,6 +411,7 @@ struct mhi_controller { enum mhi_state dev_state; atomic_t dev_wake; atomic_t pending_pkts; + u32 M0, M2, M3, M3_fast; struct list_head transition_list; spinlock_t transition_lock; spinlock_t wlock; From patchwork Mon May 18 20:04:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhaumik Bhatt X-Patchwork-Id: 189092 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A04EBC433DF for ; Mon, 18 May 2020 20:04:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7853820758 for ; Mon, 18 May 2020 20:04:36 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=mg.codeaurora.org header.i=@mg.codeaurora.org header.b="UJ/c2lXl" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728174AbgERUEf (ORCPT ); Mon, 18 May 2020 16:04:35 -0400 Received: from mail27.static.mailgun.info ([104.130.122.27]:23565 "EHLO mail27.static.mailgun.info" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726916AbgERUEb (ORCPT ); Mon, 18 May 2020 16:04:31 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.codeaurora.org; q=dns/txt; s=smtp; t=1589832271; h=References: In-Reply-To: Message-Id: Date: Subject: Cc: To: From: Sender; bh=V94ZBtElrYKPuW5itFPhUi9hnQTxAz3rOMgMz//e1VI=; b=UJ/c2lXlTe/8nBbFdE85rorGt3X6VxnPpSF3Am9TvlUJSvM4Vj6ZNZBnJK09tBrB5iJAoGIs ebmcsHZuEjqE5S3OHGNp0f5nBKuJdhV79tn+TwVL65VTAfOhwUYtB7N4/0ObgDQRYvNJraqt zOnd4d/oN4BsxIUaAYicpW5lVwk= X-Mailgun-Sending-Ip: 104.130.122.27 X-Mailgun-Sid: WyI1MzIzYiIsICJsaW51eC1hcm0tbXNtQHZnZXIua2VybmVsLm9yZyIsICJiZTllNGEiXQ== Received: from smtp.codeaurora.org (ec2-35-166-182-171.us-west-2.compute.amazonaws.com [35.166.182.171]) by mxa.mailgun.org with ESMTP id 5ec2ea3b.7fdc5f16c538-smtp-out-n05; Mon, 18 May 2020 20:04:11 -0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1001) id 18405C432C2; Mon, 18 May 2020 20:04:11 +0000 (UTC) Received: from bbhatt-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: bbhatt) by smtp.codeaurora.org (Postfix) with ESMTPSA id 9D9BFC432C2; Mon, 18 May 2020 20:04:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 9D9BFC432C2 Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: aws-us-west-2-caf-mail-1.web.codeaurora.org; spf=none smtp.mailfrom=bbhatt@codeaurora.org From: Bhaumik Bhatt To: manivannan.sadhasivam@linaro.org Cc: linux-arm-msm@vger.kernel.org, hemantk@codeaurora.org, jhugo@codeaurora.org, linux-kernel@vger.kernel.org, Bhaumik Bhatt Subject: [PATCH v3 6/7] bus: mhi: core: Read and save device hardware information from BHI Date: Mon, 18 May 2020 13:04:00 -0700 Message-Id: <1589832241-13867-7-git-send-email-bbhatt@codeaurora.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> References: <1589832241-13867-1-git-send-email-bbhatt@codeaurora.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Device hardware specific information such as serial number and the OEM PK hash can be read using BHI and saved on host to identify the endpoint. Signed-off-by: Bhaumik Bhatt Reviewed-by: Jeffrey Hugo --- drivers/bus/mhi/core/boot.c | 17 ++++++++++++++++- include/linux/mhi.h | 6 ++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/bus/mhi/core/boot.c b/drivers/bus/mhi/core/boot.c index 0b38014..24422f5 100644 --- a/drivers/bus/mhi/core/boot.c +++ b/drivers/bus/mhi/core/boot.c @@ -392,13 +392,28 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl) void *buf; dma_addr_t dma_addr; size_t size; - int ret; + int i, ret; if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) { dev_err(dev, "Device MHI is not in valid state\n"); return; } + /* save hardware info from BHI */ + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_SERIALNU, + &mhi_cntrl->serial_number); + if (ret) + dev_err(dev, "Could not capture serial number via BHI\n"); + + for (i = 0; i < ARRAY_SIZE(mhi_cntrl->oem_pk_hash); i++) { + ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->bhi, BHI_OEMPKHASH(i), + &mhi_cntrl->oem_pk_hash[i]); + if (ret) { + dev_err(dev, "Could not capture OEM PK HASH via BHI\n"); + break; + } + } + /* If device is in pass through, do reset to ready state transition */ if (mhi_cntrl->ee == MHI_EE_PTHRU) goto fw_load_ee_pthru; diff --git a/include/linux/mhi.h b/include/linux/mhi.h index 026a624..42e4d1e 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -19,6 +19,8 @@ #define MHI_VOTE_BUS BIT(0) /* do not disable the mhi bus */ #define MHI_VOTE_DEVICE BIT(1) /* prevent mhi device from entering lpm */ +#define MHI_MAX_OEM_PK_HASH_SEGMENTS 16 + struct mhi_chan; struct mhi_event; struct mhi_ctxt; @@ -318,6 +320,8 @@ struct mhi_controller_config { * @device_number: MHI controller device number * @major_version: MHI controller major revision number * @minor_version: MHI controller minor revision number + * @serial_number: MHI controller serial number obtained from BHI + * @oem_pk_hash: MHI controller OEM PK Hash obtained from BHI * @mhi_event: MHI event ring configurations table * @mhi_cmd: MHI command ring configurations table * @mhi_ctxt: MHI device context, shared memory between host and device @@ -397,6 +401,8 @@ struct mhi_controller { u32 device_number; u32 major_version; u32 minor_version; + u32 serial_number; + u32 oem_pk_hash[MHI_MAX_OEM_PK_HASH_SEGMENTS]; struct mhi_event *mhi_event; struct mhi_cmd *mhi_cmd;