From patchwork Thu Apr 5 09:49:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enric Balletbo i Serra X-Patchwork-Id: 10324351 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3A66260208 for ; Thu, 5 Apr 2018 10:21:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 27A6D28F24 for ; Thu, 5 Apr 2018 10:21:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1AA8A29147; Thu, 5 Apr 2018 10:21:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 677F528F24 for ; Thu, 5 Apr 2018 10:21:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=uYL4tNemCFXDAhIPpWMXG+AgZCgne7bmgY09mcnc0zk=; b=X1PGbF1tyarSDAEyqW/hFWIhj4 RvPqxPclyfT9vddp86+SGkTlP2R9f7jxq+G1G+2Hj/My/pRYuOPUig/08jRiy5gYRRKp5/R+IjKjK 1PUuPBAV7RR01ijZooTAOb442ACTOt42MUKbPGhqQ3BYTvb7MetxZW68kPfd/uS7c8tY5+Qfff1B/ 4eXQ3+KpY2iKdtBpONXyWNQ+8RsM7RS/AcM0ff+0SPMI3UL6NFNCoV1j/wNQ5nLIcLDr2P9KKTpQg eQoHa4ZbdNZoYHxRR0Up2vfJ2juLc5jZU7/yg15T5apKWpT6mxB28UMqjaY2j6bha5WTHbtFhYPG2 p68AlnPQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1f420q-0006qd-Ok; Thu, 05 Apr 2018 10:21:00 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1f41om-0003FU-Hm; Thu, 05 Apr 2018 10:08:32 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=0QGt1FbeaxvBgIIgBVkRQU5gTSUz1j4WbiWEs+Lb+vI=; b=CuLlsJkwaogZ7YevBqSupHjsV 3fjy5geM+wlTo8KppZSox5pKSRloTuu9TDc06XLQVXiZP+cGwlgKh7w3Eyg3htbB9NsgWsS0aSMdc +vP0GQ3WDkht/PEI5UNr6yHbBcY7c+s7ZJMmupRyQpXDAtiEArwcNmm5DrThKBnT7Z3gFkEwK+PlV HgoN5JEO0kVoznO65QeBSp+PX+yokcB8dQ0TXUcY0A4AMgp1lHY2LIu74WzrK3JCRc6re0vmMXQq7 XnY4UWRfKrnQzOqgxz/g5zCO4NK7v2PFtyGERFWFMBFlGNenJpybQOJcT0/o4tbhgULSmFH8DuGK7 hf1WTTEsQ==; Received: from bhuna.collabora.co.uk ([2a00:1098:0:82:1000:25:2eeb:e3e3]) by casper.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1f41YB-00078F-7S; Thu, 05 Apr 2018 09:51:25 +0000 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: eballetbo) with ESMTPSA id B7A8D277A2A From: Enric Balletbo i Serra To: architt@codeaurora.org, inki.dae@samsung.com, thierry.reding@gmail.com, hjc@rock-chips.com, seanpaul@chromium.org, airlied@linux.ie, tfiga@chromium.org, heiko@sntech.de Subject: [PATCH v6 27/30] drm/rockchip: psr: Sanitize semantics of allow/disallow API Date: Thu, 5 Apr 2018 11:49:57 +0200 Message-Id: <20180405095000.9756-28-enric.balletbo@collabora.com> X-Mailer: git-send-email 2.16.3 In-Reply-To: <20180405095000.9756-1-enric.balletbo@collabora.com> References: <20180405095000.9756-1-enric.balletbo@collabora.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180405_105123_276897_52B68B0C X-CRM114-Status: GOOD ( 21.73 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, a.hajda@samsung.com, Laurent.pinchart@ideasonboard.com, ykk@rock-chips.com, kernel@collabora.com, m.szyprowski@samsung.com, linux-samsung-soc@vger.kernel.org, jy0922.shim@samsung.com, rydberg@bitmath.org, krzk@kernel.org, linux-rockchip@lists.infradead.org, kgene@kernel.org, linux-input@vger.kernel.org, orjan.eide@arm.com, wxt@rock-chips.com, jeffy.chen@rock-chips.com, linux-arm-kernel@lists.infradead.org, mark.yao@rock-chips.com, wzz@rock-chips.com, hl@rock-chips.com, jingoohan1@gmail.com, sw0312.kim@samsung.com, dianders@chromium.org, kyungmin.park@samsung.com, Enric Balletbo i Serra , kuankuan.y@gmail.com, hshi@chromium.org MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Tomasz Figa Currently both rockchip_drm_psr_activate() and _deactivate() only set the boolean "active" flag without actually making sure that hardware state complies with it. Since we are going to extend the usage of this API to properly lock PSR for the duration of atomic commits, we change the semantics in following way: - a counter is used to track the number of disallow requests, - PSR is actually disabled in hardware on first disallow request, - PSR enable work is scheduled on last disallow request. The above allows using the API as a way to deterministically synchronize PSR state changes with other DRM events, i.e. atomic commits and cursor updates. As a nice side effect, the naming is sorted out and we have "inhibit" for stopping the software logic and "enable" for hardware state. Signed-off-by: Tomasz Figa Signed-off-by: Thierry Escande Signed-off-by: Enric Balletbo i Serra Tested-by: Marek Szyprowski Reviewed-by: Andrzej Hajda --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 4 +- drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 57 ++++++++++++++++++------- drivers/gpu/drm/rockchip/rockchip_drm_psr.h | 4 +- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 6d45d62466b3..080f05352195 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -134,7 +134,7 @@ static int rockchip_dp_poweron_end(struct analogix_dp_plat_data *plat_data) { struct rockchip_dp_device *dp = to_dp(plat_data); - return rockchip_drm_psr_activate(&dp->encoder); + return rockchip_drm_psr_inhibit_put(&dp->encoder); } static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) @@ -142,7 +142,7 @@ static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) struct rockchip_dp_device *dp = to_dp(plat_data); int ret; - ret = rockchip_drm_psr_deactivate(&dp->encoder); + ret = rockchip_drm_psr_inhibit_get(&dp->encoder); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c index 448c5fde241c..e7e16d92d5a1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c @@ -27,7 +27,7 @@ struct psr_drv { struct drm_encoder *encoder; struct mutex lock; - bool active; + int inhibit_count; bool enabled; struct delayed_work flush_work; @@ -76,7 +76,7 @@ static int psr_set_state_locked(struct psr_drv *psr, bool enable) { int ret; - if (!psr->active) + if (psr->inhibit_count > 0) return -EINVAL; if (enable == psr->enabled) @@ -101,13 +101,18 @@ static void psr_flush_handler(struct work_struct *work) } /** - * rockchip_drm_psr_activate - activate PSR on the given pipe + * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder * @encoder: encoder to obtain the PSR encoder * + * Decrements PSR inhibit count on given encoder. Should be called only + * for a PSR inhibit count increment done before. If PSR inhibit counter + * reaches zero, PSR flush work is scheduled to make the hardware enter + * PSR mode in PSR_FLUSH_TIMEOUT_MS. + * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_psr_activate(struct drm_encoder *encoder) +int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder) { struct psr_drv *psr = find_psr_by_encoder(encoder); @@ -115,21 +120,29 @@ int rockchip_drm_psr_activate(struct drm_encoder *encoder) return PTR_ERR(psr); mutex_lock(&psr->lock); - psr->active = true; + --psr->inhibit_count; + if (!psr->inhibit_count) + mod_delayed_work(system_wq, &psr->flush_work, + PSR_FLUSH_TIMEOUT_MS); mutex_unlock(&psr->lock); return 0; } -EXPORT_SYMBOL(rockchip_drm_psr_activate); +EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put); /** - * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe + * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder * @encoder: encoder to obtain the PSR encoder * + * Increments PSR inhibit count on given encoder. This function guarantees + * that after it returns PSR is turned off on given encoder and no PSR-related + * hardware state change occurs at least until a matching call to + * rockchip_drm_psr_inhibit_put() is done. + * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_psr_deactivate(struct drm_encoder *encoder) +int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder) { struct psr_drv *psr = find_psr_by_encoder(encoder); @@ -137,15 +150,15 @@ int rockchip_drm_psr_deactivate(struct drm_encoder *encoder) return PTR_ERR(psr); mutex_lock(&psr->lock); - psr->active = false; - psr->enabled = false; + psr_set_state_locked(psr, false); + ++psr->inhibit_count; mutex_unlock(&psr->lock); cancel_delayed_work_sync(&psr->flush_work); cancel_work_sync(&psr->disable_work); return 0; } -EXPORT_SYMBOL(rockchip_drm_psr_deactivate); +EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get); static void rockchip_drm_do_flush(struct psr_drv *psr) { @@ -301,6 +314,11 @@ static const struct input_device_id psr_ids[] = { * @encoder: encoder that obtain the PSR function * @psr_set: call back to set PSR state * + * The function returns with PSR inhibit counter initialized with one + * and the caller (typically encoder driver) needs to call + * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR + * enable request. + * * Returns: * Zero on success, negative errno on failure. */ @@ -322,7 +340,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder, INIT_WORK(&psr->disable_work, psr_disable_handler); mutex_init(&psr->lock); - psr->active = false; + psr->inhibit_count = 1; psr->enabled = false; psr->encoder = encoder; psr->set = psr_set; @@ -362,6 +380,11 @@ EXPORT_SYMBOL(rockchip_drm_psr_register); * @encoder: encoder that obtain the PSR function * @psr_set: call back to set PSR state * + * It is expected that the PSR inhibit counter is 1 when this function is + * called, which corresponds to a state when related encoder has been + * disconnected from any CRTCs and its driver called + * rockchip_drm_psr_inhibit_get() to stop the PSR logic. + * * Returns: * Zero on success, negative errno on failure. */ @@ -373,10 +396,14 @@ void rockchip_drm_psr_unregister(struct drm_encoder *encoder) mutex_lock(&drm_drv->psr_list_lock); list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { if (psr->encoder == encoder) { - input_unregister_handler(&psr->input_handler); - cancel_delayed_work_sync(&psr->flush_work); - cancel_work_sync(&psr->disable_work); + /* + * Any other value would mean that the encoder + * is still in use. + */ + WARN_ON(psr->inhibit_count != 1); + list_del(&psr->list); + input_unregister_handler(&psr->input_handler); kfree(psr->input_handler.name); kfree(psr); } diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h index 06537ee27565..40e026c14168 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h @@ -18,8 +18,8 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev); int rockchip_drm_psr_flush(struct drm_crtc *crtc); -int rockchip_drm_psr_activate(struct drm_encoder *encoder); -int rockchip_drm_psr_deactivate(struct drm_encoder *encoder); +int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder); +int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder); int rockchip_drm_psr_register(struct drm_encoder *encoder, int (*psr_set)(struct drm_encoder *, bool enable));