Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp4781949imm; Mon, 14 May 2018 13:00:03 -0700 (PDT) X-Google-Smtp-Source: AB8JxZp7KjP9Lq/2pEIzCnlrecTjp6NAmWkI3HjgL1dxFSfp1m/II30ri5D/sN0JzL9fSpb/NFcL X-Received: by 2002:a62:ca4a:: with SMTP id n71-v6mr11819656pfg.149.1526328003002; Mon, 14 May 2018 13:00:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526328002; cv=none; d=google.com; s=arc-20160816; b=OCfQsYopJHXD4vSW13EfQaNDckt2BQw2cfq8Y2iqc4N98vYkcbC0tjv5N8eNjhLhpp qzrrfb8KY/YMfbx/iZH0WByzcWy4Dy2s/sINwpS5nOhRuf3LsNd59vKWzFYRkwVRsBrM M/NVmOy+FZ4jOr+ol2LKPZUBY23jNFa+jOuUx+XZX73i388FJ3LUvF8P2IBsvpwPXL0w z6kJxG8pbrrse7ArzPLbEsJWufg08DKcL01EmuM7lioAvg6d8Tfuqgo4XCYpPzyb2iaa OLBcKt0AlbgvS4S2eiAngRt2hTMPnWiu12gvt3jrIdYCqFXqvkTYRYom+c0pCnfNy/Oc HXAg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=EJQavt29vXZEeASRCVyshngOO15+dq2ewCVw8MWTtf0=; b=lLyMKXB3LUnxSr4Fo/R1BnHwRpmFAx3oDJaisvESXU4ikP5UkyXNE7lwq1atlzvT5M 7g9dYhg63Kz2eJMTI0tjlhu5tjsz1FxZzfkNGDNprUhgvYve4upexDkFoOet38oZ2Kvf cu3lhtbSzBQfx3KSirTZuqREw69q3kv5yjxy0MrPnLVO2uCs8pj6GxQaIM1lG1Rri603 5ViuK0ZCOmFBmdMHSr5Qm8ZXenXIF1+maDbdXxSJRt2U36YiJs4pMrK0tpe/vfeL8+XK urjMR6bq7noO/EIINq7iZejPqaCjUXqAyHgnmWjSjHoY+jIOdnMwURqRlEIkSyhlSmCf Q7kw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=oASmpWB1; dkim=pass header.i=@codeaurora.org header.s=default header.b=fuiBG06Q; 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 e11-v6si2467817pgf.469.2018.05.14.12.59.47; Mon, 14 May 2018 13:00:02 -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=oASmpWB1; dkim=pass header.i=@codeaurora.org header.s=default header.b=fuiBG06Q; 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 S1752042AbeENT7e (ORCPT + 99 others); Mon, 14 May 2018 15:59:34 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:33606 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751422AbeENT7c (ORCPT ); Mon, 14 May 2018 15:59:32 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id B6F69601EA; Mon, 14 May 2018 19:59:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1526327971; bh=4ZOrQsE6sJnlyuf9lsy+1Z5PEtknlZcVLOhoIZuJ/uY=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=oASmpWB1wVGXrdj6zCQ8U+zWayEX1ocSPyVbDGAG2+hU4PzAMOKOMUJXS6c2R0P91 vA4rILWhRiv7X1Ix1mQc+UoAr9QtVc0S5VFN0ofCg9tuAMQAxjxatt+17vX9qXNx9M Ukm1+vkmkfXOid/bPzVJXXUl0Mna2+2zybO0U77A= 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 localhost (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: ilina@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 51FD1601EA; Mon, 14 May 2018 19:59:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1526327970; bh=4ZOrQsE6sJnlyuf9lsy+1Z5PEtknlZcVLOhoIZuJ/uY=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=fuiBG06Qqb/0tO7fDhrVQas5Fkuci8NQACEZ4UwCdd2AlCqSD0a9bLeKFS+P8ns/e RG6NWlSbvqijM8sFtxUpAepfuTvePTjqrkKkaxTm7q35F3wyZhdtl/XeoH8dG+cLHj JL16vUr9atoGYFKQuMWtzdOyZNyUfA6HA4V+nWe0= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 51FD1601EA 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=ilina@codeaurora.org Date: Mon, 14 May 2018 13:59:29 -0600 From: Lina Iyer To: Doug Anderson Cc: Andy Gross , David Brown , linux-arm-msm@vger.kernel.org, "open list:ARM/QUALCOMM SUPPORT" , Rajendra Nayak , Bjorn Andersson , LKML , Stephen Boyd , Evan Green , Matthias Kaehlcke , rplsssn@codeaurora.org Subject: Re: [PATCH v8 09/10] drivers: qcom: rpmh: add support for batch RPMH request Message-ID: <20180514195929.GA22950@codeaurora.org> References: <20180509170159.29682-1-ilina@codeaurora.org> <20180509170159.29682-10-ilina@codeaurora.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.5 (2018-04-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Doug, Will explain only the key points now. On Fri, May 11 2018 at 14:19 -0600, Doug Anderson wrote: >Hi, > >On Wed, May 9, 2018 at 10:01 AM, Lina Iyer wrote: >> /** >> @@ -77,12 +82,14 @@ struct rpmh_request { >> * @cache: the list of cached requests >> * @lock: synchronize access to the controller data >> * @dirty: was the cache updated since flush >> + * @batch_cache: Cache sleep and wake requests sent as batch >> */ >> struct rpmh_ctrlr { >> struct rsc_drv *drv; >> struct list_head cache; >> spinlock_t lock; >> bool dirty; >> + const struct rpmh_request *batch_cache[RPMH_MAX_BATCH_CACHE]; > >I'm pretty confused about why the "batch_cache" is separate from the >normal cache. As far as I can tell the purpose of the two is the same >but you have two totally separate code paths and data structures. > Due to a hardware limitation, requests made by bus drivers must be set up in the sleep and wake TCS first before setting up the requests from other drivers. Bus drivers use batch mode for any and all RPMH communication. Hence their request are the only ones in the batch_cache. >> }; >> >> static struct rpmh_ctrlr rpmh_rsc[RPMH_MAX_CTRLR]; >> @@ -133,6 +140,7 @@ void rpmh_tx_done(const struct tcs_request *msg, int r) >> struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, >> msg); >> struct completion *compl = rpm_msg->completion; >> + atomic_t *wc = rpm_msg->wait_count; >> >> rpm_msg->err = r; >> >> @@ -143,8 +151,13 @@ void rpmh_tx_done(const struct tcs_request *msg, int r) >> kfree(rpm_msg->free); >> >> /* Signal the blocking thread we are done */ >> - if (compl) >> - complete(compl); >> + if (!compl) >> + return; > >The comment above this "if" block no longer applies to the line next >to it after your patch. ...but below I suggest you get rid of >"wait_count", so maybe this part of the patch will go away. > > >> +static int cache_batch(struct rpmh_ctrlr *ctrlr, >> + struct rpmh_request **rpm_msg, int count) >> +{ >> + unsigned long flags; >> + int ret = 0; >> + int index = 0; >> + int i; >> + >> + spin_lock_irqsave(&ctrlr->lock, flags); >> + while (index < RPMH_MAX_BATCH_CACHE && ctrlr->batch_cache[index]) >> + index++; >> + if (index + count >= RPMH_MAX_BATCH_CACHE) { >> + ret = -ENOMEM; >> + goto fail; >> + } >> + >> + for (i = 0; i < count; i++) >> + ctrlr->batch_cache[index + i] = rpm_msg[i]; >> +fail: > >Nit: this label is for both failure and normal exit, so call it "exit". > > >> + spin_unlock_irqrestore(&ctrlr->lock, flags); >> + >> + return ret; >> +} > >As part of my overall confusion about why the batch cache is different >than the normal one: for the normal use case you still call >rpmh_rsc_write_ctrl_data() for things you put in your cache, but you >don't for the batch cache. I still haven't totally figured out what >rpmh_rsc_write_ctrl_data() does, but it seems strange that you don't >do it for the batch cache but you do for the other one. > > flush_batch does write to the controller using rpmh_rsc_write_ctrl_data() Thanks, Lina >> +/** >> + * rpmh_write_batch: Write multiple sets of RPMH commands and wait for the >> + * batch to finish. >> + * >> + * @dev: the device making the request >> + * @state: Active/sleep set >> + * @cmd: The payload data >> + * @n: The array of count of elements in each batch, 0 terminated. >> + * >> + * Write a request to the RSC controller without caching. If the request >> + * state is ACTIVE, then the requests are treated as completion request >> + * and sent to the controller immediately. The function waits until all the >> + * commands are complete. If the request was to SLEEP or WAKE_ONLY, then the >> + * request is sent as fire-n-forget and no ack is expected. >> + * >> + * May sleep. Do not call from atomic contexts for ACTIVE_ONLY requests. >> + */ >> +int rpmh_write_batch(const struct device *dev, enum rpmh_state state, >> + const struct tcs_cmd *cmd, u32 *n) >> +{ >> + struct rpmh_request *rpm_msg[RPMH_MAX_REQ_IN_BATCH] = { NULL }; >> + DECLARE_COMPLETION_ONSTACK(compl); >> + atomic_t wait_count = ATOMIC_INIT(0); >> + struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev); >> + int count = 0; >> + int ret, i; >> + >> + if (IS_ERR(ctrlr) || !cmd || !n) >> + return -EINVAL; >> + >> + while (n[count++] > 0) >> + ; >> + count--; >> + if (!count || count > RPMH_MAX_REQ_IN_BATCH) >> + return -EINVAL; >> + >> + for (i = 0; i < count; i++) { >> + rpm_msg[i] = __get_rpmh_msg_async(state, cmd, n[i]); >> + if (IS_ERR_OR_NULL(rpm_msg[i])) { > >Just "IS_ERR". It's never NULL. > >...also add a i-- somewhere in here or you're going to be kfree()ing >your error value, aren't you? > > >> + ret = PTR_ERR(rpm_msg[i]); >> + for (; i >= 0; i--) >> + kfree(rpm_msg[i]->free); >> + return ret; >> + } >> + cmd += n[i]; >> + } >> + >> + if (state != RPMH_ACTIVE_ONLY_STATE) >> + return cache_batch(ctrlr, rpm_msg, count); > >Don't you need to free rpm_msg items in this case? > > >> + >> + atomic_set(&wait_count, count); >> + >> + for (i = 0; i < count; i++) { >> + rpm_msg[i]->completion = &compl; >> + rpm_msg[i]->wait_count = &wait_count; >> + ret = rpmh_rsc_send_data(ctrlr->drv, &rpm_msg[i]->msg); >> + if (ret) { >> + int j; >> + >> + pr_err("Error(%d) sending RPMH message addr=%#x\n", >> + ret, rpm_msg[i]->msg.cmds[0].addr); >> + for (j = i; j < count; j++) >> + rpmh_tx_done(&rpm_msg[j]->msg, ret); > >You're just using rpmh_tx_done() to free memory? Note that you'll >probably do your error handling in this function a favor if you rename >__get_rpmh_msg_async() to __fill_rpmh_msg() and remove the memory >allocation from there. Then you can do one big allocation of the >whole array in rpmh_write_batch() and then you'll only have one free >at the end... > > > >> + break; > >"break" seems wrong here. You'll end up waiting for the completion, >then I guess timing out, then returning -ETIMEDOUT? > > >> + } >> + } >> + >> + ret = wait_for_completion_timeout(&compl, RPMH_TIMEOUT_MS); > >The "wait_count" abstraction is confusing and I believe it's not >needed. I think you can remove it and change the above to this >(untested) code: > >time_left = RPMH_TIMEOUT_MS; >for (i = 0; i < count; i++) { > time_left = wait_for_completion_timeout(&compl, time_left); > if (!time_left) > return -ETIMEDOUT; >} > >...specifically completions are additive, so just wait "count" times >and then the reader doesn't need to learn your new wait_count >abstraction and try to reason about it. > >...and, actually, I argue in other replies that this should't use a >timeout, so even cleaner: > >for (i = 0; i < count; i++) > wait_for_completion(&compl); > > >Once you do that, you can also get rid of the need to pre-count "n", >so all your loops turn into: > >for (i = 0; n[i]; i++) > > >I suppose you might want to get rid of "RPMH_MAX_REQ_IN_BATCH" and >dynamically allocate your array too, but that seems sane. As per >above it seems like you should just dynamically allocate a whole array >of "struct rpmh_request" items at once anyway. > >--- > >> + return (ret > 0) ? 0 : -ETIMEDOUT; >> + >> +} >> +EXPORT_SYMBOL(rpmh_write_batch); > >Perhaps an even simpler thing than taking all my advice above: can't >you just add a optional completion to rpmh_write_async()? That would >just be stuffed into rpm_msg. > >Now your batch code would just be a bunch of calls to >rpmh_write_async() with an equal number of wait_for_completion() calls >at the end. Is there a reason that wouldn't work? You'd get rid of >_a lot_ of code. > > >-Doug