return;
mutex_lock(&devfreq->lock);
- profile->last_event_type = busy ? DEVICE_BUSY : DEVICE_IDLE;
+ profile->dev_stat.busy = busy;
update_devfreq(devfreq);
mutex_unlock(&devfreq->lock);
}
update_load_estimate_gpmu(to_platform_device(dev));
/* Copy the contents of the current device status */
- profile->ext_stat.busy = profile->last_event_type;
*stat = profile->dev_stat;
/* Finally, clear out the local values */
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
struct nvhost_device_profile *profile;
struct nvhost_emc_params *emc_params;
+ int err;
if (pdata->power_profile)
return;
}
profile->pdev = pdev;
- profile->last_event_type = DEVICE_IDLE;
+ profile->dev_stat.busy = false;
profile->private_data = emc_params;
- /* Initialize devfreq related structures */
- profile->dev_stat.private_data = &profile->ext_stat;
- profile->ext_stat.min_freq = gk20a_clk_round_rate(g, 0);
- profile->ext_stat.max_freq = gk20a_clk_round_rate(g, UINT_MAX);
- profile->ext_stat.busy = DEVICE_IDLE;
-
- if (profile->ext_stat.min_freq == profile->ext_stat.max_freq) {
- dev_warn(&pdev->dev, "max rate = min rate (%lu), disabling scaling\n",
- profile->ext_stat.min_freq);
- goto err_fetch_clocks;
- }
+ /* Create frequency table */
+ err = nvhost_scale_make_freq_table(profile);
+ if (err || !profile->devfreq_profile.max_state)
+ goto err_get_freqs;
nvhost_scale3d_calibrate_emc(emc_params,
gk20a_clk_get(g), pdata->clk[2],
if (pdata->devfreq_governor) {
struct devfreq *devfreq;
- int err;
profile->devfreq_profile.initial_freq =
- profile->ext_stat.min_freq;
+ profile->devfreq_profile.freq_table[0];
profile->devfreq_profile.target = gk20a_scale_target;
profile->devfreq_profile.get_dev_status =
gk20a_scale_get_dev_status;
- err = nvhost_scale_make_freq_table(profile);
- if (err)
- goto err_get_freqs;
devfreq = devfreq_add_device(&pdev->dev,
&profile->devfreq_profile,
err_get_freqs:
device_remove_file(&pdev->dev, &dev_attr_load);
err_create_sysfs_entry:
-err_fetch_clocks:
kfree(pdata->power_profile);
pdata->power_profile = NULL;
}
return;
}
- if (podgov->last_event_type == DEVICE_IDLE &&
+ if (!podgov->last_event_type &&
df->previous_freq > df->min_freq &&
podgov->p_user == false)
notify_idle = 1;
{
struct podgov_info_rec *podgov = df->data;
struct devfreq_dev_status dev_stat;
- struct nvhost_devfreq_ext_stat *ext_stat;
- int current_event;
int stat;
ktime_t now;
return 0;
}
- current_event = DEVICE_IDLE;
stat = 0;
now = ktime_get();
return 0;
}
- /* Retrieve extended data */
- ext_stat = dev_stat.private_data;
- if (!ext_stat)
- return -EINVAL;
-
- current_event = ext_stat->busy;
*freq = dev_stat.current_frequency;
- df->min_freq = ext_stat->min_freq;
- df->max_freq = ext_stat->max_freq;
/* Sustain local variables */
- podgov->last_event_type = current_event;
+ podgov->last_event_type = dev_stat.busy;
podgov->idle = 1000 * (dev_stat.total_time - dev_stat.busy_time);
podgov->idle = podgov->idle / dev_stat.total_time;
podgov->idle_avg = (podgov->p_smooth * podgov->idle_avg) +
ktime_us_delta(now, podgov->last_throughput_hint) < 1000000)
return GET_TARGET_FREQ_DONTSCALE;
- switch (current_event) {
-
- case DEVICE_IDLE:
+ if (dev_stat.busy) {
+ cancel_delayed_work(&podgov->idle_timer);
+ *freq = scaling_state_check(df, now);
+ } else {
/* Launch a work to slowdown the gpu */
*freq = scaling_state_check(df, now);
schedule_delayed_work(&podgov->idle_timer,
msecs_to_jiffies(podgov->p_slowdown_delay));
- break;
- case DEVICE_BUSY:
- cancel_delayed_work(&podgov->idle_timer);
- *freq = scaling_state_check(df, now);
- break;
}
if (!(*freq) ||
enum tegra_chipid cid = tegra_get_chipid();
int error = 0;
- struct nvhost_devfreq_ext_stat *ext_stat;
struct devfreq_dev_status dev_stat;
int stat = 0;
/* Get the current status of the device */
stat = df->profile->get_dev_status(df->dev.parent, &dev_stat);
- if (!dev_stat.private_data) {
- pr_err("podgov: device does not support ext_stat.\n");
- goto err_get_current_status;
- }
- ext_stat = dev_stat.private_data;
-
- /* store the limits */
- df->min_freq = ext_stat->min_freq;
- df->max_freq = ext_stat->max_freq;
-
- podgov->p_freq_request = ext_stat->max_freq;
/* Create sysfs entries for controlling this governor */
error = device_create_file(&d->dev,
if (!podgov->freq_count || !podgov->freqlist)
goto err_get_freqs;
+ /* store the limits */
+ df->min_freq = podgov->freqlist[0];
+ df->max_freq = podgov->freqlist[podgov->freq_count - 1];
+ podgov->p_freq_request = df->max_freq;
+
podgov->idle_avg = 0;
podgov->freq_avg = 0;
podgov->hint_avg = 0;
device_remove_file(&d->dev, &dev_attr_freq_request);
err_create_sysfs_entry:
dev_err(&d->dev, "failed to create sysfs attributes");
-err_get_current_status:
err_unsupported_chip_id:
kfree(podgov);
err_alloc_podgov:
struct nvhost_device_profile *profile = pdata->power_profile;
if (!tegra_is_clk_enabled(profile->clk)) {
- *freq = profile->ext_stat.min_freq;
+ *freq = profile->devfreq_profile.freq_table[0];
return 0;
}
mutex_lock(&devfreq->lock);
if (!profile->actmon)
update_load_estimate(profile, busy);
- profile->last_event_type = busy ? DEVICE_BUSY : DEVICE_IDLE;
+ profile->dev_stat.busy = busy;
update_devfreq(devfreq);
mutex_unlock(&devfreq->lock);
}
update_load_estimate_actmon(profile);
/* Copy the contents of the current device status */
- profile->ext_stat.busy = profile->last_event_type;
*stat = profile->dev_stat;
/* Finally, clear out the local values */
{
struct nvhost_device_data *pdata = platform_get_drvdata(pdev);
struct nvhost_device_profile *profile;
+ int err;
if (pdata->power_profile)
return;
pdata->power_profile = profile;
profile->pdev = pdev;
profile->clk = pdata->clk[0];
- profile->last_event_type = DEVICE_IDLE;
-
- /* Initialize devfreq related structures */
- profile->dev_stat.private_data = &profile->ext_stat;
- profile->ext_stat.min_freq =
- clk_round_rate(clk_get_parent(profile->clk), 0);
- profile->ext_stat.max_freq =
- clk_round_rate(clk_get_parent(profile->clk), UINT_MAX);
- profile->ext_stat.busy = DEVICE_IDLE;
-
- if (profile->ext_stat.min_freq == profile->ext_stat.max_freq) {
- dev_warn(&pdev->dev, "max rate = min rate (%lu), disabling scaling\n",
- profile->ext_stat.min_freq);
- goto err_fetch_clocks;
- }
+ profile->dev_stat.busy = false;
+
+ /* Create frequency table */
+ err = nvhost_scale_make_freq_table(profile);
+ if (err || !profile->devfreq_profile.max_state)
+ goto err_get_freqs;
/* Initialize actmon */
if (pdata->actmon_enabled) {
if (pdata->devfreq_governor) {
struct devfreq *devfreq;
- int err;
profile->devfreq_profile.initial_freq =
- profile->ext_stat.min_freq;
+ profile->devfreq_profile.freq_table[0];
profile->devfreq_profile.target = nvhost_scale_target;
profile->devfreq_profile.get_dev_status =
nvhost_scale_get_dev_status;
- err = nvhost_scale_make_freq_table(profile);
- if (err)
- goto err_get_freqs;
devfreq = devfreq_add_device(&pdev->dev,
&profile->devfreq_profile,
err_allocate_actmon:
device_remove_file(&pdev->dev, &dev_attr_load);
err_create_sysfs_entry:
-err_fetch_clocks:
kfree(pdata->power_profile);
pdata->power_profile = NULL;
}
bool busy;
ktime_t last_event_time;
- enum nvhost_devfreq_busy last_event_type;
struct devfreq_dev_profile devfreq_profile;
struct devfreq_dev_status dev_stat;
- struct nvhost_devfreq_ext_stat ext_stat;
void *private_data;
struct notifier_block qos_notify_block;
return (struct nvhost_device_data *)platform_get_drvdata(pdev);
}
-enum nvhost_devfreq_busy {
- DEVICE_IDLE = 0,
- DEVICE_BUSY = 1
-};
-
-struct nvhost_devfreq_ext_stat {
- enum nvhost_devfreq_busy busy;
- unsigned long max_freq;
- unsigned long min_freq;
-};
-
struct nvhost_device_power_attr {
struct platform_device *ndev;
struct kobj_attribute power_attr[NVHOST_POWER_SYSFS_ATTRIB_MAX];