From patchwork Mon Aug 26 13:44:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Leonard Crestez X-Patchwork-Id: 11114661 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 21A02174A for ; Mon, 26 Aug 2019 13:46:54 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F30B3206B7 for ; Mon, 26 Aug 2019 13:46:53 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="B8LweLVA" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org F30B3206B7 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=nxp.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org 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=S2AhzI8x+r1YIUCp4nbjpWwyD1Zzn9Ta/JbQrFzek9c=; b=B8LweLVAAeJQ9+r57Izz5hs45I zb/mol8omZvMplduismpSUK3j8A3PGWX0FtlFMlDUTt0ttEKS/HPd5frfXZ4qfC1E3DaYi5b8WhLc 0YPJ8uAzQTyKY6XeHYY2FAr36/eqP3YA6fic4PmHZVbksQ67WGcYPw7KWaVsQB0JMLA+0+L6jojOJ jiNGkAGAgTvjPdahcOH47e1lZWdr9P2j2h1U7+iWpUcvDPiJComMMbDRUJbG7Z0hDeQLE0tuk4td2 9oR2m/Duo8U4RqR4eKkxCIjvPdQpQCACIgwXG+XCMy+b2ZpF0xJCCldIm8HTdY+UeAwUTiY6OsP1t V1EGDRtg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92 #3 (Red Hat Linux)) id 1i2FKf-0001iL-2Z; Mon, 26 Aug 2019 13:46:53 +0000 Received: from inva020.nxp.com ([92.121.34.13]) by bombadil.infradead.org with esmtps (Exim 4.92 #3 (Red Hat Linux)) id 1i2FIY-0007Tn-Kq for linux-arm-kernel@lists.infradead.org; Mon, 26 Aug 2019 13:44:44 +0000 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 1C2A91A0292; Mon, 26 Aug 2019 15:44:39 +0200 (CEST) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 0DE1A1A0191; Mon, 26 Aug 2019 15:44:39 +0200 (CEST) Received: from fsr-ub1864-112.ea.freescale.net (fsr-ub1864-112.ea.freescale.net [10.171.82.98]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id 7769C20605; Mon, 26 Aug 2019 15:44:38 +0200 (CEST) From: Leonard Crestez To: Chanwoo Choi , MyungJoo Ham Subject: [PATCH v4 4/6] PM / devfreq: Add dev_pm_qos support Date: Mon, 26 Aug 2019 16:44:31 +0300 Message-Id: X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190826_064443_169390_70BF7B12 X-CRM114-Status: GOOD ( 13.97 ) X-Spam-Score: -2.3 (--) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-2.3 points) pts rule name description ---- ---------------------- -------------------------------------------------- -2.3 RCVD_IN_DNSWL_MED RBL: Sender listed at https://www.dnswl.org/, medium trust [92.121.34.13 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?b?QXJ0dXIgxZp3aWdvxYQ=?= , Abel Vesa , Saravana Kannan , linux-pm@vger.kernel.org, Viresh Kumar , Krzysztof Kozlowski , Kyungmin Park , Alexandre Bailon , Georgi Djakov , linux-arm-kernel@lists.infradead.org, Jacky Bai MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Register notifiers with the pm_qos framework in order to respond to requests for MIN_FREQUENCY and MAX_FREQUENCY. Signed-off-by: Leonard Crestez --- drivers/devfreq/devfreq.c | 70 +++++++++++++++++++++++++++++++++++++++ include/linux/devfreq.h | 5 +++ 2 files changed, 75 insertions(+) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 96e218b07771..42c10b8b239e 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -22,17 +22,20 @@ #include #include #include #include #include +#include #include "governor.h" #define HZ_PER_KHZ 1000 #define CREATE_TRACE_POINTS #include +#define HZ_PER_KHZ 1000 + static struct class *devfreq_class; /* * devfreq core provides delayed work based load monitoring helper * functions. Governors can use these or can implement their own @@ -123,10 +126,16 @@ static void devfreq_get_freq_range(struct devfreq *devfreq, } else { *min_freq = freq_table[devfreq->profile->max_state - 1]; *max_freq = freq_table[0]; } + /* constraints from dev_pm_qos: */ + *min_freq = max(*min_freq, HZ_PER_KHZ * (unsigned long)dev_pm_qos_read_value( + devfreq->dev.parent, DEV_PM_QOS_MIN_FREQUENCY)); + *max_freq = min(*max_freq, HZ_PER_KHZ * (unsigned long)dev_pm_qos_read_value( + devfreq->dev.parent, DEV_PM_QOS_MAX_FREQUENCY)); + /* constraints from sysfs: */ *min_freq = max(*min_freq, devfreq->min_freq); *max_freq = min(*max_freq, devfreq->max_freq); /* constraints from opp interface: */ @@ -604,10 +613,49 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type, mutex_unlock(&devfreq->lock); return ret; } +/** + * devfreq_qos_notifier_call() - Common handler for qos freq changes. + * @devfreq: the devfreq instance. + */ +static int devfreq_qos_notifier_call(struct devfreq *devfreq) +{ + int ret; + + mutex_lock(&devfreq->lock); + ret = update_devfreq(devfreq); + mutex_unlock(&devfreq->lock); + + return ret; +} + +/** + * devfreq_qos_min_notifier_call() - Callback for qos min_freq changes. + * @nb: Should to be devfreq->nb_min + */ +static int devfreq_qos_min_notifier_call(struct notifier_block *nb, + unsigned long val, void *ptr) +{ + struct devfreq *devfreq = container_of(nb, struct devfreq, nb_min); + + return devfreq_qos_notifier_call(devfreq); +} + +/** + * devfreq_qos_max_notifier_call() - Callback for qos min_freq changes. + * @nb: Should to be devfreq->nb_max + */ +static int devfreq_qos_max_notifier_call(struct notifier_block *nb, + unsigned long val, void *ptr) +{ + struct devfreq *devfreq = container_of(nb, struct devfreq, nb_max); + + return devfreq_qos_notifier_call(devfreq); +} + /** * devfreq_dev_release() - Callback for struct device to release the device. * @dev: the devfreq device * * Remove devfreq from the list and release its resources. @@ -623,10 +671,15 @@ static void devfreq_dev_release(struct device *dev) return; } list_del(&devfreq->node); mutex_unlock(&devfreq_list_lock); + dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max, + DEV_PM_QOS_MAX_FREQUENCY); + dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min, + DEV_PM_QOS_MIN_FREQUENCY); + if (devfreq->profile->exit) devfreq->profile->exit(devfreq->dev.parent); mutex_destroy(&devfreq->lock); kfree(devfreq); @@ -739,10 +792,27 @@ struct devfreq *devfreq_add_device(struct device *dev, devfreq->last_stat_updated = jiffies; srcu_init_notifier_head(&devfreq->transition_notifier_list); + /* + * Register notifiers for updates to min_freq/max_freq after device is + * initialized (and we can handle notifications) but before the governor + * is started (which should do an initial enforcement of constraints) + */ + devfreq->nb_min.notifier_call = devfreq_qos_min_notifier_call; + err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_min, + DEV_PM_QOS_MIN_FREQUENCY); + if (err) + goto err_devfreq; + + devfreq->nb_max.notifier_call = devfreq_qos_max_notifier_call; + err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_max, + DEV_PM_QOS_MAX_FREQUENCY); + if (err) + goto err_devfreq; + mutex_lock(&devfreq_list_lock); governor = try_then_request_governor(devfreq->governor_name); if (IS_ERR(governor)) { dev_err(dev, "%s: Unable to find governor for the device\n", diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index c3cbc15fdf08..dac0dffeabb4 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -134,10 +134,12 @@ struct devfreq_dev_profile { * @total_trans: Number of devfreq transitions * @trans_table: Statistics of devfreq transitions * @time_in_state: Statistics of devfreq states * @last_stat_updated: The last time stat updated * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier + * @nb_min: Notifier block for DEV_PM_QOS_MIN_FREQUENCY + * @nb_max: Notifier block for DEV_PM_QOS_MAX_FREQUENCY * * This structure stores the devfreq information for a give device. * * Note that when a governor accesses entries in struct devfreq in its * functions except for the context of callbacks defined in struct @@ -176,10 +178,13 @@ struct devfreq { unsigned int *trans_table; unsigned long *time_in_state; unsigned long last_stat_updated; struct srcu_notifier_head transition_notifier_list; + + struct notifier_block nb_min; + struct notifier_block nb_max; }; struct devfreq_freqs { unsigned long old; unsigned long new;