mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
devfreq: wmark: active: add wmark margin attrs
Add configurable high and low watermark margins to wmark_active governor. As the names suggested, they represent the margins of a given watermark. A smaller margin means a tighter load threshold to trigger the frequency adjustment and vice versa. Bug 200493763 Change-Id: Ie41e311dd483a1ad2f917ac7296f392262b5fd1f Signed-off-by: Andrew Chen <andrewc@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2819287 Reviewed-by: svcacv <svcacv@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: David Ung <davidu@nvidia.com> Reviewed-by: Bitan Biswas <bbiswas@nvidia.com> GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
committed by
Laxman Dewangan
parent
219d548fd4
commit
24d4fa2e60
@@ -33,6 +33,8 @@ struct wmark_gov_param {
|
|||||||
unsigned int load_target;
|
unsigned int load_target;
|
||||||
unsigned int load_max;
|
unsigned int load_max;
|
||||||
unsigned int smooth;
|
unsigned int smooth;
|
||||||
|
unsigned int high_wmark_margin;
|
||||||
|
unsigned int low_wmark_margin;
|
||||||
bool freq_boost_en;
|
bool freq_boost_en;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -48,6 +50,8 @@ struct wmark_gov_info {
|
|||||||
struct kobj_attribute load_target_attr;
|
struct kobj_attribute load_target_attr;
|
||||||
struct kobj_attribute load_max_attr;
|
struct kobj_attribute load_max_attr;
|
||||||
struct kobj_attribute smooth_attr;
|
struct kobj_attribute smooth_attr;
|
||||||
|
struct kobj_attribute high_wmark_margin_attr;
|
||||||
|
struct kobj_attribute low_wmark_margin_attr;
|
||||||
struct kobj_attribute freq_boost_en_attr;
|
struct kobj_attribute freq_boost_en_attr;
|
||||||
|
|
||||||
spinlock_t param_lock;
|
spinlock_t param_lock;
|
||||||
@@ -70,13 +74,22 @@ struct wmark_gov_info {
|
|||||||
static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo,
|
static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo,
|
||||||
unsigned long curr_freq)
|
unsigned long curr_freq)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int i, pos;
|
int i, pos;
|
||||||
|
int margin;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wmarkinfo->param_lock, flags);
|
||||||
|
if (wmarkinfo->param.high_wmark_margin > INT_MAX)
|
||||||
|
margin = wmarkinfo->freq_count - 1;
|
||||||
|
else
|
||||||
|
margin = wmarkinfo->param.high_wmark_margin;
|
||||||
|
spin_unlock_irqrestore(&wmarkinfo->param_lock, flags);
|
||||||
|
|
||||||
for (i = 0; i < wmarkinfo->freq_count; i++)
|
for (i = 0; i < wmarkinfo->freq_count; i++)
|
||||||
if (wmarkinfo->freqlist[i] > curr_freq)
|
if (wmarkinfo->freqlist[i] > curr_freq)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pos = min(wmarkinfo->freq_count - 1, i);
|
pos = min(wmarkinfo->freq_count - 1, i + margin);
|
||||||
|
|
||||||
return wmarkinfo->freqlist[pos];
|
return wmarkinfo->freqlist[pos];
|
||||||
}
|
}
|
||||||
@@ -84,13 +97,22 @@ static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo,
|
|||||||
static unsigned long freqlist_down(struct wmark_gov_info *wmarkinfo,
|
static unsigned long freqlist_down(struct wmark_gov_info *wmarkinfo,
|
||||||
unsigned long curr_freq)
|
unsigned long curr_freq)
|
||||||
{
|
{
|
||||||
|
unsigned long flags;
|
||||||
int i, pos;
|
int i, pos;
|
||||||
|
int margin;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wmarkinfo->param_lock, flags);
|
||||||
|
if (wmarkinfo->param.low_wmark_margin > INT_MAX)
|
||||||
|
margin = wmarkinfo->freq_count - 1;
|
||||||
|
else
|
||||||
|
margin = wmarkinfo->param.low_wmark_margin;
|
||||||
|
spin_unlock_irqrestore(&wmarkinfo->param_lock, flags);
|
||||||
|
|
||||||
for (i = wmarkinfo->freq_count - 1; i >= 0; i--)
|
for (i = wmarkinfo->freq_count - 1; i >= 0; i--)
|
||||||
if (wmarkinfo->freqlist[i] < curr_freq)
|
if (wmarkinfo->freqlist[i] < curr_freq)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pos = max(0, i);
|
pos = max(0, i - margin);
|
||||||
return wmarkinfo->freqlist[pos];
|
return wmarkinfo->freqlist[pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +440,99 @@ static ssize_t smooth_store(struct kobject *kobj,
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t high_wmark_margin_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct wmark_gov_info *wmarkinfo = NULL;
|
||||||
|
ssize_t res;
|
||||||
|
unsigned int val;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
wmarkinfo = container_of(attr,
|
||||||
|
struct wmark_gov_info,
|
||||||
|
high_wmark_margin_attr);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wmarkinfo->param_lock, flags);
|
||||||
|
val = wmarkinfo->param.high_wmark_margin;
|
||||||
|
spin_unlock_irqrestore(&wmarkinfo->param_lock, flags);
|
||||||
|
|
||||||
|
res = snprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||||
|
if (res >= PAGE_SIZE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t high_wmark_margin_store(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct wmark_gov_info *wmarkinfo = NULL;
|
||||||
|
unsigned int val = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
wmarkinfo = container_of(attr,
|
||||||
|
struct wmark_gov_info,
|
||||||
|
high_wmark_margin_attr);
|
||||||
|
|
||||||
|
if (kstrtou32(buf, 0, &val) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wmarkinfo->param_lock, flags);
|
||||||
|
wmarkinfo->param.high_wmark_margin = val;
|
||||||
|
spin_unlock_irqrestore(&wmarkinfo->param_lock, flags);
|
||||||
|
|
||||||
|
return count <= INT_MAX ? count : -EINVAL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t low_wmark_margin_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct wmark_gov_info *wmarkinfo = NULL;
|
||||||
|
ssize_t res;
|
||||||
|
unsigned int val;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
wmarkinfo = container_of(attr,
|
||||||
|
struct wmark_gov_info,
|
||||||
|
low_wmark_margin_attr);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wmarkinfo->param_lock, flags);
|
||||||
|
val = wmarkinfo->param.low_wmark_margin;
|
||||||
|
spin_unlock_irqrestore(&wmarkinfo->param_lock, flags);
|
||||||
|
|
||||||
|
res = snprintf(buf, PAGE_SIZE, "%u\n", val);
|
||||||
|
if (res >= PAGE_SIZE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t low_wmark_margin_store(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct wmark_gov_info *wmarkinfo = NULL;
|
||||||
|
unsigned int val = 0;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
wmarkinfo = container_of(attr,
|
||||||
|
struct wmark_gov_info,
|
||||||
|
low_wmark_margin_attr);
|
||||||
|
|
||||||
|
if (kstrtou32(buf, 0, &val) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&wmarkinfo->param_lock, flags);
|
||||||
|
wmarkinfo->param.low_wmark_margin = val;
|
||||||
|
spin_unlock_irqrestore(&wmarkinfo->param_lock, flags);
|
||||||
|
|
||||||
|
return count <= INT_MAX ? count : -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t freq_boost_en_show(struct kobject *kobj,
|
static ssize_t freq_boost_en_show(struct kobject *kobj,
|
||||||
struct kobj_attribute *attr,
|
struct kobj_attribute *attr,
|
||||||
char *buf)
|
char *buf)
|
||||||
@@ -501,6 +616,16 @@ static int devfreq_watermark_debug_start(struct devfreq *df)
|
|||||||
if (sysfs_create_file(&df->dev.parent->kobj, &attr->attr))
|
if (sysfs_create_file(&df->dev.parent->kobj, &attr->attr))
|
||||||
goto err_create_smooth_sysfs_entry;
|
goto err_create_smooth_sysfs_entry;
|
||||||
|
|
||||||
|
attr = &wmarkinfo->high_wmark_margin_attr;
|
||||||
|
INIT_SYSFS_ATTR_RW(high_wmark_margin);
|
||||||
|
if (sysfs_create_file(&df->dev.parent->kobj, &attr->attr))
|
||||||
|
goto err_create_high_wmark_margin_sysfs_entry;
|
||||||
|
|
||||||
|
attr = &wmarkinfo->low_wmark_margin_attr;
|
||||||
|
INIT_SYSFS_ATTR_RW(low_wmark_margin);
|
||||||
|
if (sysfs_create_file(&df->dev.parent->kobj, &attr->attr))
|
||||||
|
goto err_create_low_wmark_margin_sysfs_entry;
|
||||||
|
|
||||||
attr = &wmarkinfo->freq_boost_en_attr;
|
attr = &wmarkinfo->freq_boost_en_attr;
|
||||||
INIT_SYSFS_ATTR_RW(freq_boost_en);
|
INIT_SYSFS_ATTR_RW(freq_boost_en);
|
||||||
if (sysfs_create_file(&df->dev.parent->kobj, &attr->attr))
|
if (sysfs_create_file(&df->dev.parent->kobj, &attr->attr))
|
||||||
@@ -509,6 +634,12 @@ static int devfreq_watermark_debug_start(struct devfreq *df)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_create_freq_boost_en_sysfs_entry:
|
err_create_freq_boost_en_sysfs_entry:
|
||||||
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
|
&wmarkinfo->low_wmark_margin_attr.attr);
|
||||||
|
err_create_low_wmark_margin_sysfs_entry:
|
||||||
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
|
&wmarkinfo->high_wmark_margin_attr.attr);
|
||||||
|
err_create_high_wmark_margin_sysfs_entry:
|
||||||
sysfs_remove_file(&df->dev.parent->kobj,
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
&wmarkinfo->smooth_attr.attr);
|
&wmarkinfo->smooth_attr.attr);
|
||||||
err_create_smooth_sysfs_entry:
|
err_create_smooth_sysfs_entry:
|
||||||
@@ -531,6 +662,10 @@ static void devfreq_watermark_debug_stop(struct devfreq *df)
|
|||||||
|
|
||||||
sysfs_remove_file(&df->dev.parent->kobj,
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
&wmarkinfo->freq_boost_en_attr.attr);
|
&wmarkinfo->freq_boost_en_attr.attr);
|
||||||
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
|
&wmarkinfo->high_wmark_margin_attr.attr);
|
||||||
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
|
&wmarkinfo->low_wmark_margin_attr.attr);
|
||||||
sysfs_remove_file(&df->dev.parent->kobj,
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
&wmarkinfo->smooth_attr.attr);
|
&wmarkinfo->smooth_attr.attr);
|
||||||
sysfs_remove_file(&df->dev.parent->kobj,
|
sysfs_remove_file(&df->dev.parent->kobj,
|
||||||
|
|||||||
Reference in New Issue
Block a user