Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp3916686rdh; Tue, 28 Nov 2023 07:11:36 -0800 (PST) X-Google-Smtp-Source: AGHT+IGfd4ipU2a73r1mAY3VXeGwQuSv84Cfnyy9SmMngpFeA447BqY2ESj2uSYEQ7uESDGi3LGg X-Received: by 2002:a17:90b:3e86:b0:285:93ef:ec6f with SMTP id rj6-20020a17090b3e8600b0028593efec6fmr14746863pjb.32.1701184295704; Tue, 28 Nov 2023 07:11:35 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701184295; cv=none; d=google.com; s=arc-20160816; b=MnPxtbny1vfq5oLwLWBBWnBF66IzKNiMNJiD3/mQ516nxkiMZwbJFvQo3T7SdWFhWT yrEhhrOAjT/EkwSeWwueoEW9Nf+mTo7aMdOjypWqoJ3V18YKD0J3pV/KcaPAtax7qxUa FzzfydlK8vWetrxgbxq+SgOBC90EocP2BSNBj790pN0VbAHSlyhCnU+Hz0P29O17J10I 10zRelQvjJC4155LQ9CsGKrbNkCOveGx/KAJuv3G4S3+wU+ZpQlk7/ZlMD0MhBDbUw67 ErU6PPDpssI+Y19lNFxh7zlODh3+64ZCIwg2QzBLJ6fmy78+KWAm9Hs7ZVkY+Hc7AyX4 PVAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:in-reply-to:from :references:cc:to:content-language:subject:user-agent:mime-version :date:message-id:dkim-signature; bh=dmMcfZ2vQwr7XNsPkozZRbeqygYRYNvMoDPHFgX1EUs=; fh=hU76Ixc44NDFo0hzv1clQGJ0lDxwjIfhHVHdoat7LUY=; b=zEhdrB7A0FbZ4yU2Zbz8TEyTT5P1QMfHBX60CeIl4s9fbgDrAPJu7Ri6zngcGjLjM3 5C7hJMIiskwBotBJHb2NueYCGYMTyFQCsRIKVEVhZyZiv8agOhpfRXH9ecLu4t4YHRaU B5VVrggETmfvCLsdMiD5pR1cgoPmXwbHUwYIdyIpN247v65vXa0y2H+cINe3EH/vaqBO Pz5OA+TCsi9+bl2lVdVh+Gn2ovA1oR0wO8QmA9hVdQuUa+IUkeipRpiNCyut7XLir6kx eO4UEcS7BAy338gP0q2TP/lYNtLd68Lv4llx4bToLoOD/aTRg0/u4JdiMGZOyvJuDPPm 3FbQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@collabora.com header.s=mail header.b=e4y0V+bd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=collabora.com Return-Path: Received: from groat.vger.email (groat.vger.email. [2620:137:e000::3:5]) by mx.google.com with ESMTPS id pd9-20020a17090b1dc900b002859ad34f7bsi9790997pjb.92.2023.11.28.07.11.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 28 Nov 2023 07:11:35 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) client-ip=2620:137:e000::3:5; Authentication-Results: mx.google.com; dkim=pass header.i=@collabora.com header.s=mail header.b=e4y0V+bd; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=collabora.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by groat.vger.email (Postfix) with ESMTP id 826A780A3664; Tue, 28 Nov 2023 07:11:29 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at groat.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345978AbjK1PKv (ORCPT + 99 others); Tue, 28 Nov 2023 10:10:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346681AbjK1PKo (ORCPT ); Tue, 28 Nov 2023 10:10:44 -0500 Received: from madras.collabora.co.uk (madras.collabora.co.uk [IPv6:2a00:1098:0:82:1000:25:2eeb:e5ab]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 30A02D63 for ; Tue, 28 Nov 2023 07:10:50 -0800 (PST) Received: from [100.107.97.3] (cola.collaboradmins.com [195.201.22.229]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: kholk11) by madras.collabora.co.uk (Postfix) with ESMTPSA id E08E966072A7; Tue, 28 Nov 2023 15:10:47 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=collabora.com; s=mail; t=1701184249; bh=P0zKHqNYhlsO/fSoMbalAnUND4Va3nLOgJIguSGs5CM=; h=Date:Subject:To:Cc:References:From:In-Reply-To:From; b=e4y0V+bdZCUfsXGIZzAkBSHHMLTaoV/jQtYsjSFQ7cHARcCeouJ3ZNzeUjFsoLXNE //GMl2ICcM/PVoazcqe/kfQXYHzx2E2FFwvt/17AkkibTJRwJEuxf8M+kExkJyQ45c UbfQx9RoQt7utdPlLDneh8w7lUAXJZdM/tqWSkcJoJQwGgym95DkiHn+hRpq2WYBab kv9428UmTIxmQNQ6N32tf4YABolijHA7mU992B6+BkEgFKkT/A/juMgKZWBOfgIqow JzH3v07UpZG1OgD6BUgIo8WS1Slo7QmI3tqFdm4dN1QYtzGp/qMTbPYhql0zAnFHwm 5d0EhHXvZf5sg== Message-ID: Date: Tue, 28 Nov 2023 16:10:45 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v2 3/3] drm/panfrost: Synchronize and disable interrupts before powering off Content-Language: en-US To: Boris Brezillon Cc: robh@kernel.org, steven.price@arm.com, maarten.lankhorst@linux.intel.com, mripard@kernel.org, tzimmermann@suse.de, airlied@gmail.com, daniel@ffwll.ch, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, kernel@collabora.com, m.szyprowski@samsung.com, krzysztof.kozlowski@linaro.org References: <20231128124510.391007-1-angelogioacchino.delregno@collabora.com> <20231128124510.391007-4-angelogioacchino.delregno@collabora.com> <20231128145712.3f4d3f74@collabora.com> From: AngeloGioacchino Del Regno In-Reply-To: <20231128145712.3f4d3f74@collabora.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on groat.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (groat.vger.email [0.0.0.0]); Tue, 28 Nov 2023 07:11:29 -0800 (PST) Il 28/11/23 14:57, Boris Brezillon ha scritto: > On Tue, 28 Nov 2023 13:45:10 +0100 > AngeloGioacchino Del Regno > wrote: > >> To make sure that we don't unintentionally perform any unclocked and/or >> unpowered R/W operation on GPU registers, before turning off clocks and >> regulators we must make sure that no GPU, JOB or MMU ISR execution is >> pending: doing that required to add a mechanism to synchronize the >> interrupts on suspend. >> >> Add functions panfrost_{gpu,job,mmu}_suspend_irq() which will perform >> interrupts masking and ISR execution synchronization, and then call >> those in the panfrost_device_runtime_suspend() handler in the exact >> sequence of job (may require mmu!) -> mmu -> gpu. >> >> As a side note, JOB and MMU suspend_irq functions needed some special >> treatment: as their interrupt handlers will unmask interrupts, it was >> necessary to add a bitmap for "is_suspending" which is used to address >> the possible corner case of unintentional IRQ unmasking because of ISR >> execution after a call to synchronize_irq(). >> >> Of course, unmasking the interrupts is being done as part of the reset >> happening during runtime_resume(): since we're anyway resuming all of >> GPU, JOB, MMU, the only additional action is to zero out the newly >> introduced `is_suspending` bitmap directly in the resume handler, as >> to avoid adding panfrost_{job,mmu}_resume_irq() function just for >> clearing own bits, especially because it currently makes way more sense >> to just zero out the bitmap. >> >> Signed-off-by: AngeloGioacchino Del Regno >> --- >> drivers/gpu/drm/panfrost/panfrost_device.c | 4 ++++ >> drivers/gpu/drm/panfrost/panfrost_device.h | 7 +++++++ >> drivers/gpu/drm/panfrost/panfrost_gpu.c | 7 +++++++ >> drivers/gpu/drm/panfrost/panfrost_gpu.h | 1 + >> drivers/gpu/drm/panfrost/panfrost_job.c | 18 +++++++++++++++--- >> drivers/gpu/drm/panfrost/panfrost_job.h | 1 + >> drivers/gpu/drm/panfrost/panfrost_mmu.c | 17 ++++++++++++++--- >> drivers/gpu/drm/panfrost/panfrost_mmu.h | 1 + >> 8 files changed, 50 insertions(+), 6 deletions(-) >> >> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c >> index c90ad5ee34e7..ed34aa55a7da 100644 >> --- a/drivers/gpu/drm/panfrost/panfrost_device.c >> +++ b/drivers/gpu/drm/panfrost/panfrost_device.c >> @@ -407,6 +407,7 @@ static int panfrost_device_runtime_resume(struct device *dev) >> { >> struct panfrost_device *pfdev = dev_get_drvdata(dev); >> >> + bitmap_zero(pfdev->is_suspending, PANFROST_COMP_BIT_MAX); >> panfrost_device_reset(pfdev); >> panfrost_devfreq_resume(pfdev); >> >> @@ -421,6 +422,9 @@ static int panfrost_device_runtime_suspend(struct device *dev) >> return -EBUSY; >> >> panfrost_devfreq_suspend(pfdev); >> + panfrost_job_suspend_irq(pfdev); >> + panfrost_mmu_suspend_irq(pfdev); >> + panfrost_gpu_suspend_irq(pfdev); >> panfrost_gpu_power_off(pfdev); >> >> return 0; >> diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h >> index 54a8aad54259..29f89f2d3679 100644 >> --- a/drivers/gpu/drm/panfrost/panfrost_device.h >> +++ b/drivers/gpu/drm/panfrost/panfrost_device.h >> @@ -25,6 +25,12 @@ struct panfrost_perfcnt; >> #define NUM_JOB_SLOTS 3 >> #define MAX_PM_DOMAINS 5 >> >> +enum panfrost_drv_comp_bits { >> + PANFROST_COMP_BIT_MMU, >> + PANFROST_COMP_BIT_JOB, >> + PANFROST_COMP_BIT_MAX >> +}; >> + >> /** >> * enum panfrost_gpu_pm - Supported kernel power management features >> * @GPU_PM_CLK_DIS: Allow disabling clocks during system suspend >> @@ -109,6 +115,7 @@ struct panfrost_device { >> >> struct panfrost_features features; >> const struct panfrost_compatible *comp; >> + DECLARE_BITMAP(is_suspending, PANFROST_COMP_BIT_MAX); >> >> spinlock_t as_lock; >> unsigned long as_in_use_mask; >> diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c >> index 7adc4441fa14..2bf645993ab4 100644 >> --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c >> +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c >> @@ -452,6 +452,13 @@ void panfrost_gpu_power_off(struct panfrost_device *pfdev) >> dev_err(pfdev->dev, "l2 power transition timeout"); >> } >> >> +void panfrost_gpu_suspend_irq(struct panfrost_device *pfdev) >> +{ >> + gpu_write(pfdev, GPU_INT_MASK, 0); >> + gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_MASK_ALL); > > Shouldn't the synchronize_irq() guarantee that all monitored interrupts > are cleared before you return? > Yeah, right - even though we're writing GPU_INT_STAT in CLEAR, there's no reason why INT_STAT would "contain less bits" than the ones that we *want to* clear. Effectively, I can remove that INT_CLEAR write, as it makes little sense - thanks for catching that! >> + synchronize_irq(pfdev->gpu_irq); >> +} >> + >> int panfrost_gpu_init(struct panfrost_device *pfdev) >> { >> int err; >> diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.h b/drivers/gpu/drm/panfrost/panfrost_gpu.h >> index 876fdad9f721..d841b86504ea 100644 >> --- a/drivers/gpu/drm/panfrost/panfrost_gpu.h >> +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.h >> @@ -15,6 +15,7 @@ u32 panfrost_gpu_get_latest_flush_id(struct panfrost_device *pfdev); >> int panfrost_gpu_soft_reset(struct panfrost_device *pfdev); >> void panfrost_gpu_power_on(struct panfrost_device *pfdev); >> void panfrost_gpu_power_off(struct panfrost_device *pfdev); >> +void panfrost_gpu_suspend_irq(struct panfrost_device *pfdev); >> >> void panfrost_cycle_counter_get(struct panfrost_device *pfdev); >> void panfrost_cycle_counter_put(struct panfrost_device *pfdev); >> diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c >> index f9446e197428..e8de44cc56e2 100644 >> --- a/drivers/gpu/drm/panfrost/panfrost_job.c >> +++ b/drivers/gpu/drm/panfrost/panfrost_job.c >> @@ -413,6 +413,14 @@ void panfrost_job_enable_interrupts(struct panfrost_device *pfdev) >> job_write(pfdev, JOB_INT_MASK, irq_mask); >> } >> >> +void panfrost_job_suspend_irq(struct panfrost_device *pfdev) >> +{ >> + set_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspending); >> + >> + job_write(pfdev, JOB_INT_MASK, 0); >> + synchronize_irq(pfdev->js->irq); >> +} >> + >> static void panfrost_job_handle_err(struct panfrost_device *pfdev, >> struct panfrost_job *job, >> unsigned int js) >> @@ -792,9 +800,13 @@ static irqreturn_t panfrost_job_irq_handler_thread(int irq, void *data) >> struct panfrost_device *pfdev = data; >> >> panfrost_job_handle_irqs(pfdev); >> - job_write(pfdev, JOB_INT_MASK, >> - GENMASK(16 + NUM_JOB_SLOTS - 1, 16) | >> - GENMASK(NUM_JOB_SLOTS - 1, 0)); >> + >> + /* Enable interrupts only if we're not about to get suspended */ >> + if (!test_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspending)) > > The irq-line is requested with IRQF_SHARED, meaning the line might be > shared between all three GPU IRQs, but also with other devices. I think > if we want to be totally safe, we need to also check this is_suspending > field in the hard irq handlers before accessing the xxx_INT_yyy > registers. > This would mean that we would have to force canceling jobs in the suspend handler, but if the IRQ never fired, would we still be able to find the right bits flipped in JOB_INT_RAWSTAT? From what I understand, are you suggesting to call, in job_suspend_irq() something like void panfrost_job_suspend_irq(struct panfrost_device *pfdev) { u32 status; set_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspending); job_write(pfdev, JOB_INT_MASK, 0); synchronize_irq(pfdev->js->irq); status = job_read(pfdev, JOB_INT_STAT); if (status) panfrost_job_irq_handler_thread(pfdev->js->irq, (void*)pfdev); } and then while still retaining the check in the IRQ thread handler, also check it in the hardirq handler like static irqreturn_t panfrost_job_irq_handler(int irq, void *data) { struct panfrost_device *pfdev = data; u32 status; if (!test_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspending)) return IRQ_NONE; status = job_read(pfdev, JOB_INT_STAT); if (!status) return IRQ_NONE; job_write(pfdev, JOB_INT_MASK, 0); return IRQ_WAKE_THREAD; } (rinse and repeat for panfrost_mmu) ..or am I misunderstanding you? Cheers, Angelo