For some devices we use QoS to define the minimum required frequency.
As this mechanism bypasses totally devfreq and the usual device profile,
we need to trigger postscale callback also in these cases to ensure that
i.e. EMC is scaled correctly at the same time.
Bug
1441874
Change-Id: I33545101157b015db240bfe9bb8a5c404469803c
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/362487
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
#include <linux/clk/tegra.h>
#include <linux/tegra-soc.h>
#include <linux/platform_data/tegra_edp.h>
+#include <linux/pm_qos.h>
#include <governor.h>
nvhost_module_set_devfreq_rate(profile->pdev, 2, emc_target);
}
+/*
+ * nvhost_scale_qos_notify()
+ *
+ * This function is called when the minimum QoS requirement for the device
+ * has changed. The function calls postscaling callback if it is defined.
+ */
+
+static int nvhost_scale_qos_notify(struct notifier_block *nb,
+ unsigned long n, void *p)
+{
+ struct nvhost_device_profile *profile =
+ container_of(nb, struct nvhost_device_profile,
+ qos_notify_block);
+ struct nvhost_device_data *pdata = platform_get_drvdata(profile->pdev);
+ struct gk20a *g = get_gk20a(profile->pdev);
+ unsigned long freq;
+
+ if (!pdata->scaling_post_cb)
+ return NOTIFY_OK;
+
+ /* get the frequency requirement. if devfreq is enabled, check if it
+ * has higher demand than qos */
+ freq = gk20a_clk_round_rate(g, pm_qos_request(pdata->qos_id));
+ if (pdata->power_manager)
+ freq = max(pdata->power_manager->previous_freq, freq);
+
+ pdata->scaling_post_cb(profile, freq);
+
+ return NOTIFY_OK;
+}
+
/*
* nvhost_scale_make_freq_table(profile)
*
pdata->power_manager = devfreq;
}
+
+ /* Should we register QoS callback for this device? */
+ if (pdata->qos_id < PM_QOS_NUM_CLASSES &&
+ pdata->qos_id != PM_QOS_RESERVED) {
+ profile->qos_notify_block.notifier_call =
+ &nvhost_scale_qos_notify;
+ pm_qos_add_notifier(pdata->qos_id,
+ &profile->qos_notify_block);
+ }
+
return;
err_get_freqs:
.devfreq_governor = "nvhost_podgov",
.scaling_post_cb = nvhost_gk20a_scale_callback,
.gpu_edp_device = true,
+ .qos_id = PM_QOS_GPU_FREQ_MIN,
#endif
},
.probe = gk20a_tegra_probe,
#include <linux/clk/tegra.h>
#include <linux/platform_data/tegra_edp.h>
#include <linux/tegra-soc.h>
+#include <linux/tegra-soc.h>
+#include <linux/platform_data/tegra_edp.h>
+#include <linux/pm_qos.h>
#include <governor.h>
return 0;
}
+/*
+ * nvhost_scale_qos_notify()
+ *
+ * This function is called when the minimum QoS requirement for the device
+ * has changed. The function calls postscaling callback if it is defined.
+ */
+
+static int nvhost_scale_qos_notify(struct notifier_block *nb,
+ unsigned long n, void *p)
+{
+ struct nvhost_device_profile *profile =
+ container_of(nb, struct nvhost_device_profile,
+ qos_notify_block);
+ struct nvhost_device_data *pdata = platform_get_drvdata(profile->pdev);
+ unsigned long freq;
+
+ if (!pdata->scaling_post_cb)
+ return NOTIFY_OK;
+
+ /* get the frequency requirement. if devfreq is enabled, check if it
+ * has higher demand than qos */
+ freq = clk_round_rate(clk_get_parent(profile->clk),
+ pm_qos_request(pdata->qos_id));
+ if (pdata->power_manager)
+ freq = max(pdata->power_manager->previous_freq, freq);
+
+ pdata->scaling_post_cb(profile, freq);
+
+ return NOTIFY_OK;
+}
+
/*
* update_load_estimate(profile)
*
pdata->power_manager = devfreq;
}
+ /* Should we register QoS callback for this device? */
+ if (pdata->qos_id < PM_QOS_NUM_CLASSES &&
+ pdata->qos_id != PM_QOS_RESERVED) {
+ profile->qos_notify_block.notifier_call =
+ &nvhost_scale_qos_notify;
+ pm_qos_add_notifier(pdata->qos_id,
+ &profile->qos_notify_block);
+ }
+
return;
err_get_freqs:
*
* Tegra Graphics Host 3D Clock Scaling
*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2010-2014, 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,
struct nvhost_devfreq_ext_stat ext_stat;
void *private_data;
+ struct notifier_block qos_notify_block;
};
/* Initialization and de-initialization for module */
u32 nvhost_timeout_default;
+ /* QoS id that denotes minimum frequency */
+ unsigned int qos_id;
/* Data for devfreq usage */
struct devfreq *power_manager;
/* Private device profile data */