Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp601016ybt; Wed, 1 Jul 2020 06:03:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxQJJK3sSqPWa25qczFgnFEBmj3ROQJMSJY0RWcB6bJrv8INkyYKQ5q8E5OkYRp6g8xzrBK X-Received: by 2002:a17:906:f101:: with SMTP id gv1mr18032963ejb.327.1593608583070; Wed, 01 Jul 2020 06:03:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1593608583; cv=none; d=google.com; s=arc-20160816; b=HRQZcSOqMif5q4nACxMWCI/0Eh/4ImdteV0gxgoJCjY8g+LLeBdh2rT0Acaee9VRoH 3TqYvRmqns2dj2p/fp/UUBX8ahKw6QgGEp0euP6QJvrCTUNd2TRKs07PUb2CPVTJvt1f PGQjeO1CDT2Ewr7OuYBHZs9Oz74GOo+o0wbfeZpfTJJDOzGagSUiHcqsdnX7iJBSGb04 PRSF54rtc4GVn7vSRuAZWUlEKMuw6wLZIcO6jUK2fsYqZNA+Irpo358f4Lf9PRT+xd7B a8s+44WQSP3zxegLN9ZfO64X6lA8zXErdewChO5UWx0KJjbemZqDpK+xQt7K+BRH4C7H 9+7g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=Io/xIwvPlzgTUZBNydeV0zeJ7opdV/UYH9UZpq0FPPg=; b=VlVhzKkgweHrhmWMSZ3LM1zs5jqmAaDfhFAgoDZyf0K26O634i7Z6XOlc8nuv9bL/a eFuBIyOOeoA1afB+QRF4FBcNOhGEMTZ4UKyY7g8osLMH5yWhcpwb9zLJIc5k4+PxgefJ KtE+K9OoFa7ylhsFf5GwpcIO46brWteI56vjvc0A3kXE2S3169WUj7qgv6mDSMr2GOrT Pqhd1H2gyq6IMFrRike4tRurn4XZoqBEE7AVurfNL4idYTn7Mr6E67VjJh8oTFmw1VUX pGCDe2W73fuLtRyAYrdXorX06zYBPPY6deUqrDHcgDxJ5TKj4HbpWTqB7BPtxdU/dmiv JHTQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@st.com header.s=STMicroelectronics header.b=BQAL6nV5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=st.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g15si102235edy.200.2020.07.01.06.02.38; Wed, 01 Jul 2020 06:03:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@st.com header.s=STMicroelectronics header.b=BQAL6nV5; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=st.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730833AbgGANB4 (ORCPT + 99 others); Wed, 1 Jul 2020 09:01:56 -0400 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:49384 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730556AbgGANBp (ORCPT ); Wed, 1 Jul 2020 09:01:45 -0400 Received: from pps.filterd (m0046668.ppops.net [127.0.0.1]) by mx07-00178001.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 061CrtDW021936; Wed, 1 Jul 2020 15:01:36 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=st.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=STMicroelectronics; bh=Io/xIwvPlzgTUZBNydeV0zeJ7opdV/UYH9UZpq0FPPg=; b=BQAL6nV556PhRwpC0iWa+SEy+9SaEjfO2/Gods394u9c942XSaOSrlm2xshBtgwDpnch 9jXU+2fO5cyUyxeL8Or36JkOdiUC/c1I2GRDQsgDTd5DjcARFddZpulopxMZftBLvqXZ jQOcMLKozoicZQaFbNyOuZZSptl1neohXC+LRq2DjiDE37LTkd1TUgo3tUmsfm+vdlUq N995FufAhckwNox0IOxR19HOtBmEjUT4qKQkKrrh9xMTuh4pZXyxBAUIEnY/5axfowqq Sbsy1zm54fptkPzjSCUM8qebWfBP6xDyQXzY0wWP/wS85wyaikoF3yzWQAovoOnllWEE dg== Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-00178001.pphosted.com with ESMTP id 31wuk1j45h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 01 Jul 2020 15:01:35 +0200 Received: from euls16034.sgp.st.com (euls16034.sgp.st.com [10.75.44.20]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 7FA1510003D; Wed, 1 Jul 2020 15:01:35 +0200 (CEST) Received: from Webmail-eu.st.com (sfhdag3node3.st.com [10.75.127.9]) by euls16034.sgp.st.com (STMicroelectronics) with ESMTP id 6564A2B66E1; Wed, 1 Jul 2020 15:01:35 +0200 (CEST) Received: from localhost (10.75.127.50) by SFHDAG3NODE3.st.com (10.75.127.9) with Microsoft SMTP Server (TLS) id 15.0.1347.2; Wed, 1 Jul 2020 15:01:34 +0200 From: Benjamin Gaignard To: , , , , CC: , , , , , , , , Benjamin Gaignard Subject: [PATCH v7 2/3] media: stm32-dcmi: Set minimum cpufreq requirement Date: Wed, 1 Jul 2020 15:01:28 +0200 Message-ID: <20200701130129.30961-3-benjamin.gaignard@st.com> X-Mailer: git-send-email 2.15.0 In-Reply-To: <20200701130129.30961-1-benjamin.gaignard@st.com> References: <20200701130129.30961-1-benjamin.gaignard@st.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.75.127.50] X-ClientProxiedBy: SFHDAG5NODE2.st.com (10.75.127.14) To SFHDAG3NODE3.st.com (10.75.127.9) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.235,18.0.687 definitions=2020-07-01_08:2020-07-01,2020-07-01 signatures=0 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Before start streaming set cpufreq minimum frequency requirement. The cpufreq governor will adapt the frequencies and we will have no latency for handling interrupts. The frequency requirement is retrieved from the device-tree node. Signed-off-by: Benjamin Gaignard Reviewed-by: Valentin Schneider Acked-by: Hugues Fruchet --- version 7: - rebase on v5.8-rc3 - add reviewed and ack-by - fix test condition drivers/media/platform/stm32/stm32-dcmi.c | 138 ++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c index b8931490b83b..2b7b60ba1d4d 100644 --- a/drivers/media/platform/stm32/stm32-dcmi.c +++ b/drivers/media/platform/stm32/stm32-dcmi.c @@ -13,10 +13,13 @@ #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -99,6 +102,8 @@ enum state { #define OVERRUN_ERROR_THRESHOLD 3 +static DEFINE_PER_CPU(struct freq_qos_request, qos_req); + struct dcmi_graph_entity { struct v4l2_async_subdev asd; @@ -133,6 +138,7 @@ struct stm32_dcmi { struct resource *res; struct reset_control *rstc; int sequence; + int irq; struct list_head buffers; struct dcmi_buf *active; @@ -173,6 +179,11 @@ struct stm32_dcmi { struct media_device mdev; struct media_pad vid_cap_pad; struct media_pipeline pipeline; + + struct mutex freq_lock; + u32 min_frequency; + cpumask_var_t boosted; + struct irq_affinity_notify notify; }; static inline struct stm32_dcmi *notifier_to_dcmi(struct v4l2_async_notifier *n) @@ -722,6 +733,99 @@ static void dcmi_pipeline_stop(struct stm32_dcmi *dcmi) dcmi_pipeline_s_stream(dcmi, 0); } +static void dcmi_get_min_frequency(struct stm32_dcmi *dcmi) +{ + struct device_node *np = dcmi->mdev.dev->of_node; + + dcmi->min_frequency = FREQ_QOS_MIN_DEFAULT_VALUE; + + of_property_read_u32(np, "st,stm32-dcmi-min-frequency", + &dcmi->min_frequency); +} + +static void dcmi_irq_notifier_notify(struct irq_affinity_notify *notify, + const cpumask_t *mask) +{ + struct stm32_dcmi *dcmi = container_of(notify, + struct stm32_dcmi, + notify); + struct cpufreq_policy *p; + int cpu; + + mutex_lock(&dcmi->freq_lock); + /* + * For all boosted CPUs check if it is still the case + * if not remove the request + */ + for_each_cpu(cpu, dcmi->boosted) { + if (cpumask_test_cpu(cpu, mask)) + continue; + + p = cpufreq_cpu_get(cpu); + if (!p) + continue; + + freq_qos_remove_request(&per_cpu(qos_req, cpu)); + cpumask_andnot(dcmi->boosted, dcmi->boosted, p->cpus); + + cpufreq_cpu_put(p); + } + + /* + * For CPUs in the mask check if they are boosted if not add + * a request + */ + for_each_cpu(cpu, mask) { + if (cpumask_test_cpu(cpu, dcmi->boosted)) + continue; + + p = cpufreq_cpu_get(cpu); + if (!p) + continue; + + freq_qos_add_request(&p->constraints, &per_cpu(qos_req, cpu), + FREQ_QOS_MIN, dcmi->min_frequency); + cpumask_or(dcmi->boosted, dcmi->boosted, p->cpus); + cpufreq_cpu_put(p); + } + + mutex_unlock(&dcmi->freq_lock); +} + +static void dcmi_irq_notifier_release(struct kref *ref) +{ + /* + * This is required by affinity notifier. We don't have anything to + * free here. + */ +} + +static void dcmi_set_min_frequency(struct stm32_dcmi *dcmi, s32 freq) +{ + struct irq_affinity_notify *notify = &dcmi->notify; + struct cpumask clear; + + if (freq != FREQ_QOS_MIN_DEFAULT_VALUE) { + /* + * Register the notifier before doing any change, so the + * callback can be queued if an affinity change happens *while* + * we are requesting the boosts. + */ + irq_set_affinity_notifier(dcmi->irq, notify); + dcmi_irq_notifier_notify(notify, + irq_get_affinity_mask(dcmi->irq)); + } else { + /* + * Unregister the notifier before clearing the boost requests, + * as we don't want to boost again if an affinity change happens + * *while* we are clearing the requests + */ + irq_set_affinity_notifier(dcmi->irq, NULL); + cpumask_clear(&clear); + dcmi_irq_notifier_notify(notify, &clear); + } +} + static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) { struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq); @@ -736,11 +840,13 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) goto err_release_buffers; } + dcmi_set_min_frequency(dcmi, dcmi->min_frequency); + ret = media_pipeline_start(&dcmi->vdev->entity, &dcmi->pipeline); if (ret < 0) { dev_err(dcmi->dev, "%s: Failed to start streaming, media pipeline start error (%d)\n", __func__, ret); - goto err_pm_put; + goto err_drop_qos; } ret = dcmi_pipeline_start(dcmi); @@ -835,7 +941,8 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count) err_media_pipeline_stop: media_pipeline_stop(&dcmi->vdev->entity); -err_pm_put: +err_drop_qos: + dcmi_set_min_frequency(dcmi, FREQ_QOS_MIN_DEFAULT_VALUE); pm_runtime_put(dcmi->dev); err_release_buffers: @@ -863,6 +970,8 @@ static void dcmi_stop_streaming(struct vb2_queue *vq) media_pipeline_stop(&dcmi->vdev->entity); + dcmi_set_min_frequency(dcmi, FREQ_QOS_MIN_DEFAULT_VALUE); + spin_lock_irq(&dcmi->irqlock); /* Disable interruptions */ @@ -1834,11 +1943,11 @@ static int dcmi_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; const struct of_device_id *match = NULL; struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; + struct irq_affinity_notify *notify; struct stm32_dcmi *dcmi; struct vb2_queue *q; struct dma_chan *chan; struct clk *mclk; - int irq; int ret = 0; match = of_match_device(of_match_ptr(stm32_dcmi_of_match), &pdev->dev); @@ -1879,9 +1988,9 @@ static int dcmi_probe(struct platform_device *pdev) dcmi->bus.bus_width = ep.bus.parallel.bus_width; dcmi->bus.data_shift = ep.bus.parallel.data_shift; - irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return irq ? irq : -ENXIO; + dcmi->irq = platform_get_irq(pdev, 0); + if (dcmi->irq <= 0) + return dcmi->irq ? dcmi->irq : -ENXIO; dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!dcmi->res) { @@ -1895,11 +2004,12 @@ static int dcmi_probe(struct platform_device *pdev) return PTR_ERR(dcmi->regs); } - ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback, + ret = devm_request_threaded_irq(&pdev->dev, dcmi->irq, + dcmi_irq_callback, dcmi_irq_thread, IRQF_ONESHOT, dev_name(&pdev->dev), dcmi); if (ret) { - dev_err(&pdev->dev, "Unable to request irq %d\n", irq); + dev_err(&pdev->dev, "Unable to request irq %d\n", dcmi->irq); return ret; } @@ -1922,6 +2032,7 @@ static int dcmi_probe(struct platform_device *pdev) spin_lock_init(&dcmi->irqlock); mutex_init(&dcmi->lock); mutex_init(&dcmi->dma_lock); + mutex_init(&dcmi->freq_lock); init_completion(&dcmi->complete); INIT_LIST_HEAD(&dcmi->buffers); @@ -1930,6 +2041,13 @@ static int dcmi_probe(struct platform_device *pdev) dcmi->state = STOPPED; dcmi->dma_chan = chan; + if (!alloc_cpumask_var(&dcmi->boosted, GFP_KERNEL)) + return -ENODEV; + + notify = &dcmi->notify; + notify->notify = dcmi_irq_notifier_notify; + notify->release = dcmi_irq_notifier_release; + q = &dcmi->queue; dcmi->v4l2_dev.mdev = &dcmi->mdev; @@ -2022,6 +2140,8 @@ static int dcmi_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Probe done\n"); + dcmi_get_min_frequency(dcmi); + platform_set_drvdata(pdev, dcmi); pm_runtime_enable(&pdev->dev); @@ -2049,6 +2169,8 @@ static int dcmi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); + free_cpumask_var(dcmi->boosted); + v4l2_async_notifier_unregister(&dcmi->notifier); v4l2_async_notifier_cleanup(&dcmi->notifier); media_entity_cleanup(&dcmi->vdev->entity); -- 2.15.0