mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
devfreq: pod v2: build as ext module for kstable
governor_pod_scaling_v2 will be provided as a kernel module in future NVIDIA software deliverables for Linux platforms. As of this moment, the function that returns the range of the device's scaling frequency hasn't been exposed from Linux kernel for modules to call. A similar function is implemented in the governor_pod_scaling_v2, but this function cannot get the frequency constraints put through the PM QOS interface due to the same reason, lack of kernel API function. An upstream kernel patch has been proposed by the power management maintainer to provide the function needed by governor_pod_scaling_v2, but it's not in any release kernel yet. For now, PM QOS support is removed from governor_pod_scaling_v2 and it will be added back when the upstream kernel patch is available in kernel releases. drivers_devfreq_governor_5_14.h is a copy of drivers/devfreq/governor.h of Linux kernel 5.14. Having this copy is to avoid introducing the dependency on Linux source for building the podgov as external module. JIRA ID: LS-418 Signed-off-by: Peng Liu <pengliu@nvidia.com> Change-Id: I0c70acf5679fed53f30bc3ba7c01ea571036cc5e Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2638232 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Vijayakumar Subbu <vsubbu@nvidia.com> Reviewed-by: Jonathan Hunter <jonathanh@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
97ff547e3c
commit
8a2d6e1b54
@@ -1,5 +1,16 @@
|
||||
ccflags-y += -I$(srctree)/drivers/devfreq
|
||||
obj-$(CONFIG_DEVFREQ_GOV_POD_SCALING) += governor_pod_scaling.o
|
||||
obj-$(CONFIG_DEVFREQ_GOV_POD_SCALING_V2) += governor_pod_scaling_v2.o
|
||||
|
||||
obj-$(CONFIG_DEVFREQ_GOV_WMARK_SIMPLE) += governor_wmark_simple.o
|
||||
obj-$(CONFIG_DEVFREQ_GOV_WMARK_ACTIVE) += governor_wmark_active.o
|
||||
|
||||
ifneq ($(findstring 4.9,$(NV_BUILD_KERNEL_OPTIONS)),)
|
||||
obj-$(CONFIG_DEVFREQ_GOV_POD_SCALING) += governor_pod_scaling.o
|
||||
obj-$(CONFIG_DEVFREQ_GOV_POD_SCALING_V2) += governor_pod_scaling_v2.o
|
||||
else ifneq ($(findstring 5.10,$(NV_BUILD_KERNEL_OPTIONS)),)
|
||||
obj-$(CONFIG_DEVFREQ_GOV_POD_SCALING) += governor_pod_scaling.o
|
||||
obj-$(CONFIG_DEVFREQ_GOV_POD_SCALING_V2) += governor_pod_scaling_v2.o
|
||||
else ifneq ($(findstring stable,$(NV_BUILD_KERNEL_OPTIONS)),)
|
||||
ccflags-y += -I$(srctree.nvidia)/include
|
||||
ccflags-y += -DGOVERNOR_POD_SCALING_V2_MODULE
|
||||
obj-m += governor_pod_scaling_v2.o
|
||||
endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2012-2022, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -32,11 +32,15 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/version.h>
|
||||
#define CREATE_TRACE_POINTS
|
||||
#include <trace/events/nvhost_podgov.h>
|
||||
|
||||
#ifndef GOVERNOR_POD_SCALING_V2_MODULE
|
||||
#include "governor.h"
|
||||
#else
|
||||
#include "governor_v2.h"
|
||||
#endif // GOVERNOR_POD_SCALING_V2_MODULE
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
@@ -121,6 +125,45 @@ enum podgov_adjustment_type {
|
||||
|
||||
#define HZ_PER_KHZ 1000
|
||||
|
||||
#ifdef GOVERNOR_POD_SCALING_V2_MODULE
|
||||
static void get_freq_range(struct devfreq *devfreq,
|
||||
unsigned long *min_freq,
|
||||
unsigned long *max_freq)
|
||||
{
|
||||
unsigned long *freq_table = devfreq->profile->freq_table;
|
||||
|
||||
lockdep_assert_held(&devfreq->lock);
|
||||
|
||||
if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
|
||||
*min_freq = freq_table[0];
|
||||
*max_freq = freq_table[devfreq->profile->max_state - 1];
|
||||
} else {
|
||||
*min_freq = freq_table[devfreq->profile->max_state - 1];
|
||||
*max_freq = freq_table[0];
|
||||
}
|
||||
|
||||
/* Apply constraints from OPP interface */
|
||||
*min_freq = max(*min_freq, devfreq->scaling_min_freq);
|
||||
*max_freq = min(*max_freq, devfreq->scaling_max_freq);
|
||||
|
||||
if (*min_freq > *max_freq)
|
||||
*min_freq = *max_freq;
|
||||
}
|
||||
|
||||
static void get_min_freq_limit(struct devfreq *df, unsigned long *min_freq_hz)
|
||||
{
|
||||
unsigned long max_freq_hz;
|
||||
|
||||
get_freq_range(df, min_freq_hz, &max_freq_hz);
|
||||
}
|
||||
|
||||
static void get_max_freq_limit(struct devfreq *df, unsigned long *max_freq_hz)
|
||||
{
|
||||
unsigned long min_freq_hz;
|
||||
|
||||
get_freq_range(df, &min_freq_hz, max_freq_hz);
|
||||
}
|
||||
#else
|
||||
static void get_min_freq_limit(struct devfreq *df, unsigned long *min_freq_hz)
|
||||
{
|
||||
s32 qos_min_freq = 0;
|
||||
@@ -142,6 +185,7 @@ static void get_max_freq_limit(struct devfreq *df, unsigned long *max_freq_hz)
|
||||
|
||||
*max_freq_hz = (unsigned long)HZ_PER_KHZ * qos_max_freq;
|
||||
}
|
||||
#endif // GOVERNOR_POD_SCALING_V2_MODULE
|
||||
|
||||
/*******************************************************************************
|
||||
* scaling_limit(df, freq)
|
||||
|
||||
100
drivers/devfreq/governor_v2.h
Normal file
100
drivers/devfreq/governor_v2.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* governor.h - internal header for devfreq governors.
|
||||
*
|
||||
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (C) 2011 Samsung Electronics
|
||||
* MyungJoo Ham <myungjoo.ham@samsung.com>
|
||||
*
|
||||
* This header is for devfreq governors in drivers/devfreq/
|
||||
*/
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0)
|
||||
#ifndef _GOVERNOR_H
|
||||
#define _GOVERNOR_H
|
||||
#include <linux/devfreq.h>
|
||||
|
||||
#define DEVFREQ_NAME_LEN 16
|
||||
|
||||
#define to_devfreq(DEV) container_of((DEV), struct devfreq, dev)
|
||||
|
||||
/* Devfreq events */
|
||||
#define DEVFREQ_GOV_START 0x1
|
||||
#define DEVFREQ_GOV_STOP 0x2
|
||||
#define DEVFREQ_GOV_UPDATE_INTERVAL 0x3
|
||||
#define DEVFREQ_GOV_SUSPEND 0x4
|
||||
#define DEVFREQ_GOV_RESUME 0x5
|
||||
|
||||
#define DEVFREQ_MIN_FREQ 0
|
||||
#define DEVFREQ_MAX_FREQ ULONG_MAX
|
||||
|
||||
/*
|
||||
* Definition of the governor feature flags
|
||||
* - DEVFREQ_GOV_FLAG_IMMUTABLE
|
||||
* : This governor is never changeable to other governors.
|
||||
* - DEVFREQ_GOV_FLAG_IRQ_DRIVEN
|
||||
* : The devfreq won't schedule the work for this governor.
|
||||
*/
|
||||
#define DEVFREQ_GOV_FLAG_IMMUTABLE BIT(0)
|
||||
#define DEVFREQ_GOV_FLAG_IRQ_DRIVEN BIT(1)
|
||||
|
||||
/*
|
||||
* Definition of governor attribute flags except for common sysfs attributes
|
||||
* - DEVFREQ_GOV_ATTR_POLLING_INTERVAL
|
||||
* : Indicate polling_interval sysfs attribute
|
||||
* - DEVFREQ_GOV_ATTR_TIMER
|
||||
* : Indicate timer sysfs attribute
|
||||
*/
|
||||
#define DEVFREQ_GOV_ATTR_POLLING_INTERVAL BIT(0)
|
||||
#define DEVFREQ_GOV_ATTR_TIMER BIT(1)
|
||||
|
||||
/**
|
||||
* struct devfreq_governor - Devfreq policy governor
|
||||
* @node: list node - contains registered devfreq governors
|
||||
* @name: Governor's name
|
||||
* @attrs: Governor's sysfs attribute flags
|
||||
* @flags: Governor's feature flags
|
||||
* @get_target_freq: Returns desired operating frequency for the device.
|
||||
* Basically, get_target_freq will run
|
||||
* devfreq_dev_profile.get_dev_status() to get the
|
||||
* status of the device (load = busy_time / total_time).
|
||||
* @event_handler: Callback for devfreq core framework to notify events
|
||||
* to governors. Events include per device governor
|
||||
* init and exit, opp changes out of devfreq, suspend
|
||||
* and resume of per device devfreq during device idle.
|
||||
*
|
||||
* Note that the callbacks are called with devfreq->lock locked by devfreq.
|
||||
*/
|
||||
struct devfreq_governor {
|
||||
struct list_head node;
|
||||
|
||||
const char name[DEVFREQ_NAME_LEN];
|
||||
const u64 attrs;
|
||||
const u64 flags;
|
||||
int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
|
||||
int (*event_handler)(struct devfreq *devfreq,
|
||||
unsigned int event, void *data);
|
||||
};
|
||||
|
||||
void devfreq_monitor_start(struct devfreq *devfreq);
|
||||
void devfreq_monitor_stop(struct devfreq *devfreq);
|
||||
void devfreq_monitor_suspend(struct devfreq *devfreq);
|
||||
void devfreq_monitor_resume(struct devfreq *devfreq);
|
||||
void devfreq_update_interval(struct devfreq *devfreq, unsigned int *delay);
|
||||
|
||||
int devfreq_add_governor(struct devfreq_governor *governor);
|
||||
int devfreq_remove_governor(struct devfreq_governor *governor);
|
||||
|
||||
int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
|
||||
int devfreq_update_target(struct devfreq *devfreq, unsigned long freq);
|
||||
void devfreq_get_freq_range(struct devfreq *devfreq, unsigned long *min_freq,
|
||||
unsigned long *max_freq);
|
||||
|
||||
static inline int devfreq_update_stats(struct devfreq *df)
|
||||
{
|
||||
if (!df->profile->get_dev_status)
|
||||
return -EINVAL;
|
||||
|
||||
return df->profile->get_dev_status(df->dev.parent, &df->last_status);
|
||||
}
|
||||
#endif /* _GOVERNOR_H */
|
||||
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) */
|
||||
Reference in New Issue
Block a user