msm: dcvs: remove core name.
Currently core_name is used to identify which core the dcvs operates on.
Instead use a type and the type num while registration with dcvs and
return an id (dcvs_core_id) upon successfull registration.
The dcvs_core_id is used by the clients of msm_dcvs to call upon its
apis viz. freq_start, freq_stop, msm_dcvs_idle etc.
The dcvs inturn uses the type num passed in at registration time to
invoke apis on the clients viz. set_freq, get_freq, idle_enable.
This further cleans up the internal dcvs add_core and get_core
implementation. One need not pass around the core_name and use the type
instead.
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
(cherry picked from commit 1bbc0321a6871e018c17da6f244b9df442faead6)
Signed-off-by: Ram Kumar Chakravarthy Chebathini <rcheba@codeaurora.org>
(cherry picked from commit 09456d7d7618e6d0fc6b907b7af75268ea08a942)
Change-Id: Id27751a8ec8f5d3d386bbe7c7625ed56757b8bd7
Signed-off-by: Sudhir Sharma <sudsha@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/msm_dcvs.h b/arch/arm/mach-msm/include/mach/msm_dcvs.h
index 3a1789f..9b0d0c9 100644
--- a/arch/arm/mach-msm/include/mach/msm_dcvs.h
+++ b/arch/arm/mach-msm/include/mach/msm_dcvs.h
@@ -19,6 +19,10 @@
#define CORES_MAX (10)
#define CPU_OFFSET 1 /* used to notify TZ the core number */
+#define GPU_OFFSET (CORES_MAX * 2/3) /* there will be more cpus than gpus,
+ * let the GPU be assigned fewer core
+ * elements and start later
+ */
enum msm_core_idle_state {
MSM_DCVS_IDLE_ENTER,
@@ -32,56 +36,14 @@
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES,
};
-/**
- * struct msm_dcvs_idle
- *
- * API for idle code to register and send idle enter/exit
- * notifications to msm_dcvs driver.
- */
-struct msm_dcvs_idle {
- const char *core_name;
-};
-
struct msm_gov_platform_data {
struct msm_dcvs_core_info *info;
int latency;
};
/**
- * struct msm_dcvs_freq
- *
- * API for clock driver code to register and receive frequency change
- * request for the core from the msm_dcvs driver.
- */
-struct msm_dcvs_freq {
- const char *core_name;
- /* Callback from msm_dcvs to set the core frequency */
-};
-
-/**
- * msm_dcvs_idle_source_register
- * @drv: Pointer to the source driver
- * @return: Handle to be used for sending idle state notifications.
- *
- * Register the idle driver with the msm_dcvs driver to send idle
- * state notifications for the core.
- */
-extern int msm_dcvs_idle_source_register(struct msm_dcvs_idle *drv);
-
-/**
- * msm_dcvs_idle_source_unregister
- * @drv: Pointer to the source driver
- * @return:
- * 0 on success
- * -EINVAL
- *
- * Description: Unregister the idle driver with the msm_dcvs driver
- */
-extern int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv);
-
-/**
* msm_dcvs_idle
- * @handle: Handle provided back at registration
+ * @dcvs_core_id: The id returned by msm_dcvs_register_core
* @state: The enter/exit idle state the core is in
* @iowaited: iowait in us
* on iMSM_DCVS_IDLE_EXIT.
@@ -93,7 +55,7 @@
*
* Send idle state notifications to the msm_dcvs driver
*/
-int msm_dcvs_idle(int handle, enum msm_core_idle_state state,
+int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state,
uint32_t iowaited);
/**
@@ -114,7 +76,8 @@
/**
* msm_dcvs_register_core
- * @core_name: Unique name identifier for the core.
+ * @type: whether this is a CPU or a GPU
+ * @type_core_num: The number of the core for a type
* @info: The core specific algorithm parameters.
* @sensor: The thermal sensor number of the core in question
* @return :
@@ -127,12 +90,13 @@
* Cores that need to run synchronously must share the same group id.
*/
extern int msm_dcvs_register_core(
- const char *core_name,
+ enum msm_dcvs_core_type type,
+ int type_core_num,
struct msm_dcvs_core_info *info,
- int (*set_frequency)(struct msm_dcvs_freq *self, unsigned int freq),
- unsigned int (*get_frequency)(struct msm_dcvs_freq *self),
- int (*idle_enable)(struct msm_dcvs_idle *self,
- enum msm_core_control_event event),
+ int (*set_frequency)(int type_core_num, unsigned int freq),
+ unsigned int (*get_frequency)(int type_core_num),
+ int (*idle_enable)(int type_core_num,
+ enum msm_core_control_event event),
int sensor);
/**
@@ -143,7 +107,7 @@
* Register the clock driver code with the msm_dvs driver to get notified about
* frequency change requests.
*/
-extern int msm_dcvs_freq_sink_start(struct msm_dcvs_freq *drv);
+extern int msm_dcvs_freq_sink_start(int dcvs_core_id);
/**
* msm_dcvs_freq_sink_stop
@@ -155,7 +119,7 @@
* Unregister the sink driver for the core. This will cause the source driver
* for the core to stop sending idle pulses.
*/
-extern int msm_dcvs_freq_sink_stop(struct msm_dcvs_freq *drv);
+extern int msm_dcvs_freq_sink_stop(int dcvs_core_id);
/**
* msm_dcvs_update_limits
@@ -163,5 +127,5 @@
*
* Update the frequency known to dcvs when the limits are changed.
*/
-extern void msm_dcvs_update_limits(struct msm_dcvs_freq *drv);
+extern void msm_dcvs_update_limits(int dcvs_core_id);
#endif
diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c
index bd60824..17adb7c 100644
--- a/arch/arm/mach-msm/msm_dcvs.c
+++ b/arch/arm/mach-msm/msm_dcvs.c
@@ -73,6 +73,9 @@
};
struct dcvs_core {
+ enum msm_dcvs_core_type type;
+ /* this is the number in each type for example cpu 0,1,2 and gpu 0,1 */
+ int type_core_num;
char core_name[CORE_NAME_MAX];
uint32_t actual_freq;
uint32_t freq_change_us;
@@ -81,8 +84,6 @@
struct msm_dcvs_algo_param algo_param;
struct msm_dcvs_energy_curve_coeffs coeffs;
- struct msm_dcvs_idle *idle_driver;
- struct msm_dcvs_freq *freq_driver;
/* private */
int64_t time_start;
@@ -90,16 +91,17 @@
spinlock_t cpu_lock;
struct task_struct *task;
struct core_attribs attrib;
- uint32_t handle;
+ uint32_t dcvs_core_id;
struct hrtimer timer;
int32_t timer_disabled;
struct msm_dcvs_core_info *info;
int sensor;
int pending_freq;
wait_queue_head_t wait_q;
- int (*set_frequency)(struct msm_dcvs_freq *self, unsigned int freq);
- unsigned int (*get_frequency)(struct msm_dcvs_freq *self);
- int (*idle_enable)(struct msm_dcvs_idle *self,
+
+ int (*set_frequency)(int type_core_num, unsigned int freq);
+ unsigned int (*get_frequency)(int type_core_num);
+ int (*idle_enable)(int type_core_num,
enum msm_core_control_event event);
};
@@ -110,10 +112,8 @@
static struct dentry *debugfs_base;
static struct dcvs_core core_list[CORES_MAX];
-static DEFINE_MUTEX(core_list_lock);
static struct kobject *cores_kobj;
-static struct dcvs_core *core_handles[CORES_MAX];
/* Change core frequency, called with core mutex locked */
static int __msm_dcvs_change_freq(struct dcvs_core *core)
@@ -127,7 +127,7 @@
uint32_t slack_us = 0;
uint32_t ret1 = 0;
- if (!core->freq_driver || !core->set_frequency) {
+ if (!core->set_frequency) {
/* Core may have unregistered or hotplugged */
return -ENODEV;
}
@@ -155,7 +155,7 @@
* We will need to get back the actual frequency in KHz and
* the record the time taken to change it.
*/
- ret = core->set_frequency(core->freq_driver, requested_freq);
+ ret = core->set_frequency(core->type_core_num, requested_freq);
if (ret <= 0) {
__err("Core %s failed to set freq %u\n",
core->core_name, requested_freq);
@@ -177,15 +177,14 @@
* Disable low power modes if the actual frequency is >
* disable_pc_threshold.
*/
- if (core->actual_freq >
- core->algo_param.disable_pc_threshold) {
- core->idle_enable(core->idle_driver,
+ if (core->actual_freq > core->algo_param.disable_pc_threshold) {
+ core->idle_enable(core->type_core_num,
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES);
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
__info("Disabling LPM for %s\n", core->core_name);
} else if (core->actual_freq <=
core->algo_param.disable_pc_threshold) {
- core->idle_enable(core->idle_driver,
+ core->idle_enable(core->type_core_num,
MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
__info("Enabling LPM for %s\n", core->core_name);
@@ -196,8 +195,10 @@
* to this frequency and that will get us the new slack
* timer
*/
- ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
- core->actual_freq, (uint32_t)time_end, &slack_us, &ret1);
+ ret = msm_dcvs_scm_event(core->dcvs_core_id,
+ MSM_DCVS_SCM_CLOCK_FREQ_UPDATE,
+ core->actual_freq, (uint32_t)time_end,
+ &slack_us, &ret1);
if (!ret) {
/* Reset the slack timer */
if (slack_us) {
@@ -253,7 +254,8 @@
return -ENODEV;
}
- ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id,
+ &info->power_param,
&info->freq_tbl[0], &core->coeffs);
return ret;
}
@@ -291,7 +293,7 @@
uint32_t new_freq = 0;
spin_lock_irqsave(&core->cpu_lock, flags);
- ret = msm_dcvs_scm_event(core->handle, event, param0,
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, event, param0,
core->actual_freq, &new_freq, ret1);
if (ret) {
if (ret == -13)
@@ -374,7 +376,7 @@
} else { \
uint32_t old_val = core->algo_param._name; \
core->algo_param._name = val; \
- ret = msm_dcvs_scm_set_algo_params(core->handle, \
+ ret = msm_dcvs_scm_set_algo_params(core->dcvs_core_id, \
&core->algo_param); \
if (ret) { \
core->algo_param._name = old_val; \
@@ -406,7 +408,7 @@
} else { \
int32_t old_val = core->coeffs._name; \
core->coeffs._name = val; \
- ret = msm_dcvs_scm_set_power_params(core->handle, \
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id, \
&core->info->power_param, &core->info->freq_tbl[0], \
&core->coeffs); \
if (ret) { \
@@ -437,9 +439,9 @@
* Function declarations for different attributes.
* Gets used when setting the attribute show and store parameters.
*/
-DCVS_PARAM_SHOW(core_id, core->handle)
-DCVS_PARAM_SHOW(idle_enabled, (core->idle_driver != NULL))
-DCVS_PARAM_SHOW(freq_change_enabled, (core->freq_driver != NULL))
+DCVS_PARAM_SHOW(core_id, core->dcvs_core_id)
+DCVS_PARAM_SHOW(idle_enabled, (core->idle_enable != NULL))
+DCVS_PARAM_SHOW(freq_change_enabled, (core->set_frequency != NULL))
DCVS_PARAM_SHOW(actual_freq, (core->actual_freq))
DCVS_PARAM_SHOW(freq_change_us, (core->freq_change_us))
@@ -535,107 +537,71 @@
return ret;
}
-/* Return the core if found or add to list if @add_to_list is true */
-static struct dcvs_core *msm_dcvs_add_core(const char *name, int *pos)
+/* Return the core and initialize non platform data specific numbers in it */
+static struct dcvs_core *msm_dcvs_add_core(enum msm_dcvs_core_type type,
+ int num)
{
struct dcvs_core *core = NULL;
int i;
- int empty = -1;
+ char name[CORE_NAME_MAX];
- if (!name[0] ||
- (strnlen(name, CORE_NAME_MAX - 1) == CORE_NAME_MAX - 1))
- return core;
-
- mutex_lock(&core_list_lock);
- for (i = 0; i < CORES_MAX; i++) {
- core = &core_list[i];
- if ((empty < 0) && !core->core_name[0]) {
- empty = i;
- continue;
- }
- if (!strncmp(name, core->core_name, CORE_NAME_MAX)) {
- if (pos != NULL)
- *pos = i;
- /*
- * found a core with the same name, return NULL and
- * set pos
- */
- core = NULL;
- goto out;
- }
+ switch (type) {
+ case MSM_DCVS_CORE_TYPE_CPU:
+ i = CPU_OFFSET + num;
+ BUG_ON(i >= GPU_OFFSET);
+ snprintf(name, CORE_NAME_MAX, "cpu%d", num);
+ break;
+ case MSM_DCVS_CORE_TYPE_GPU:
+ i = GPU_OFFSET + num;
+ BUG_ON(i >= CORES_MAX);
+ snprintf(name, CORE_NAME_MAX, "gpu%d", num);
+ break;
+ default:
+ return NULL;
}
- /* Check for core_list full */
- if (empty < 0) {
- *pos = 0;
- core = NULL;
- goto out;
- }
-
- core = &core_list[empty];
+ core = &core_list[i];
+ core->dcvs_core_id = i;
strlcpy(core->core_name, name, CORE_NAME_MAX);
mutex_init(&core->lock);
spin_lock_init(&core->cpu_lock);
- core->handle = empty + CORE_HANDLE_OFFSET;
- hrtimer_init(&core->timer,
- CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+ hrtimer_init(&core->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
core->timer.function = msm_dcvs_core_slack_timer;
- if (pos != NULL)
- *pos = empty;
-
-out:
- mutex_unlock(&core_list_lock);
return core;
}
/* Return the core if found or add to list if @add_to_list is true */
-static struct dcvs_core *msm_dcvs_get_core(const char *name, int *pos)
+static struct dcvs_core *msm_dcvs_get_core(int offset)
{
- struct dcvs_core *core = NULL;
- int i;
-
- if (!name[0] ||
- (strnlen(name, CORE_NAME_MAX - 1) == CORE_NAME_MAX - 1))
- return core;
-
- mutex_lock(&core_list_lock);
- for (i = 0; i < CORES_MAX; i++) {
- core = &core_list[i];
- if (!strncmp(name, core->core_name, CORE_NAME_MAX)) {
- if (pos != NULL)
- *pos = i;
- break;
- }
- }
-
- mutex_unlock(&core_list_lock);
-
- return core;
+ /* if the handle is still not set bug */
+ BUG_ON(core_list[offset].dcvs_core_id == -1);
+ return &core_list[offset];
}
-int msm_dcvs_register_core(const char *core_name,
+
+int msm_dcvs_register_core(
+ enum msm_dcvs_core_type type,
+ int type_core_num,
struct msm_dcvs_core_info *info,
- int (*set_frequency)(struct msm_dcvs_freq *self, unsigned int freq),
- unsigned int (*get_frequency)(struct msm_dcvs_freq *self),
- int (*idle_enable)(struct msm_dcvs_idle *self,
+ int (*set_frequency)(int type_core_num, unsigned int freq),
+ unsigned int (*get_frequency)(int type_core_num),
+ int (*idle_enable)(int type_core_num,
enum msm_core_control_event event),
int sensor)
{
int ret = -EINVAL;
- int pos = 0;
struct dcvs_core *core = NULL;
uint32_t ret1;
uint32_t ret2;
- if (!core_name || !core_name[0])
- return ret;
-
- core = msm_dcvs_add_core(core_name, &pos);
+ core = msm_dcvs_add_core(type, type_core_num);
if (!core)
return ret;
mutex_lock(&core->lock);
+ core->type = type;
+ core->type_core_num = type_core_num;
core->set_frequency = set_frequency;
core->get_frequency = get_frequency;
core->idle_enable = idle_enable;
@@ -647,24 +613,39 @@
memcpy(&core->coeffs, &info->energy_coeffs,
sizeof(struct msm_dcvs_energy_curve_coeffs));
- info->core_param.core_bitmask_id = 1 << pos;
- pr_debug("registering core with sensor %d\n", sensor);
+ /*
+ * The tz expects cpu0 to represent bit 0 in the mask, however the
+ * dcvs_core_id needs to start from 1, dcvs_core_id = 0 is used to
+ * indicate that this request is not associated with any core.
+ * mpdecision
+ */
+ info->core_param.core_bitmask_id
+ = 1 << (core->dcvs_core_id - CPU_OFFSET);
core->sensor = sensor;
- ret = msm_dcvs_scm_register_core(core->handle, &info->core_param);
- if (ret)
+ ret = msm_dcvs_scm_register_core(core->dcvs_core_id, &info->core_param);
+ if (ret) {
+ __err("%s: scm register core fail handle = %d ret = %d\n",
+ __func__, core->dcvs_core_id, ret);
goto bail;
+ }
- ret = msm_dcvs_scm_set_algo_params(core->handle, &info->algo_param);
- if (ret)
+ ret = msm_dcvs_scm_set_algo_params(core->dcvs_core_id,
+ &info->algo_param);
+ if (ret) {
+ __err("%s: scm algo params failed ret = %d\n", __func__, ret);
goto bail;
+ }
- ret = msm_dcvs_scm_set_power_params(core->handle, &info->power_param,
+ ret = msm_dcvs_scm_set_power_params(core->dcvs_core_id,
+ &info->power_param,
&info->freq_tbl[0], &core->coeffs);
- if (ret)
+ if (ret) {
+ __err("%s: scm power params failed ret = %d\n", __func__, ret);
goto bail;
+ }
- ret = msm_dcvs_scm_event(core->handle, MSM_DCVS_SCM_CORE_ONLINE,
+ ret = msm_dcvs_scm_event(core->dcvs_core_id, MSM_DCVS_SCM_CORE_ONLINE,
core->actual_freq, 0, &ret1, &ret2);
if (ret)
goto bail;
@@ -672,48 +653,53 @@
ret = msm_dcvs_setup_core_sysfs(core);
if (ret) {
__err("Unable to setup core %s sysfs\n", core->core_name);
- core_handles[core->handle - CORE_HANDLE_OFFSET] = NULL;
goto bail;
}
init_waitqueue_head(&core->wait_q);
core->task = kthread_run(msm_dcvs_do_freq, (void *)core,
- "msm_dcvs/%d", core->handle);
-bail:
+ "msm_dcvs/%d", core->dcvs_core_id);
+ ret = core->dcvs_core_id;
mutex_unlock(&core->lock);
return ret;
+bail:
+ mutex_unlock(&core->lock);
+ core->dcvs_core_id = -1;
+ return -EINVAL;
}
EXPORT_SYMBOL(msm_dcvs_register_core);
-void msm_dcvs_update_limits(struct msm_dcvs_freq *drv)
+void msm_dcvs_update_limits(int dcvs_core_id)
{
struct dcvs_core *core;
- if (!drv || !drv->core_name)
+ if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) {
+ __err("%s invalid dcvs_core_id = %d returning -EINVAL\n",
+ __func__, dcvs_core_id);
return;
+ }
- core = msm_dcvs_get_core(drv->core_name, NULL);
- core->actual_freq = core->get_frequency(drv);
+ core = msm_dcvs_get_core(dcvs_core_id);
+ core->actual_freq = core->get_frequency(core->type_core_num);
}
-int msm_dcvs_freq_sink_start(struct msm_dcvs_freq *drv)
+int msm_dcvs_freq_sink_start(int dcvs_core_id)
{
int ret = -EINVAL;
struct dcvs_core *core = NULL;
uint32_t ret1;
uint32_t ret2;
- if (!drv || !drv->core_name)
- return ret;
+ if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) {
+ __err("%s invalid dcvs_core_id = %d returning -EINVAL\n",
+ __func__, dcvs_core_id);
+ return -EINVAL;
+ }
- core = msm_dcvs_get_core(drv->core_name, NULL);
+ core = msm_dcvs_get_core(dcvs_core_id);
if (!core)
return ret;
mutex_lock(&core->lock);
- if (core->freq_driver && (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER))
- __info("Frequency notifier for %s being replaced\n",
- core->core_name);
- core->freq_driver = drv;
if (IS_ERR(core->task)) {
mutex_unlock(&core->lock);
return -EFAULT;
@@ -722,101 +708,56 @@
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
__info("Enabling idle pulse for %s\n", core->core_name);
- if (core->idle_driver) {
- core->actual_freq = core->get_frequency(drv);
- /* Notify TZ to start receiving idle info for the core */
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1,
+ core->actual_freq = core->get_frequency(core->type_core_num);
+ /* Notify TZ to start receiving idle info for the core */
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 1,
&ret1, &ret2);
- core->idle_enable(core->idle_driver,
- MSM_DCVS_ENABLE_IDLE_PULSE);
- }
+ core->idle_enable(core->type_core_num, MSM_DCVS_ENABLE_IDLE_PULSE);
mutex_unlock(&core->lock);
- return core->handle;
+ return core->dcvs_core_id;
}
EXPORT_SYMBOL(msm_dcvs_freq_sink_start);
-int msm_dcvs_freq_sink_stop(struct msm_dcvs_freq *drv)
+int msm_dcvs_freq_sink_stop(int dcvs_core_id)
{
int ret = -EINVAL;
struct dcvs_core *core = NULL;
uint32_t ret1;
uint32_t ret2;
- if (!drv || !drv->core_name)
- return ret;
+ if (dcvs_core_id < 0 || dcvs_core_id > CORES_MAX) {
+ pr_err("%s invalid dcvs_core_id = %d returning -EINVAL\n",
+ __func__, dcvs_core_id);
+ return -EINVAL;
+ }
- core = msm_dcvs_get_core(drv->core_name, NULL);
+ core = msm_dcvs_get_core(dcvs_core_id);
if (!core)
return ret;
mutex_lock(&core->lock);
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
__info("Disabling idle pulse for %s\n", core->core_name);
- if (core->idle_driver) {
- core->idle_enable(core->idle_driver,
- MSM_DCVS_DISABLE_IDLE_PULSE);
- /* Notify TZ to stop receiving idle info for the core */
- ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 0,
- &ret1, &ret2);
- hrtimer_cancel(&core->timer);
- core->idle_enable(core->idle_driver,
- MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
- if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
- __info("Enabling LPM for %s\n", core->core_name);
- }
- core->freq_driver = NULL;
+
+ core->idle_enable(core->type_core_num, MSM_DCVS_DISABLE_IDLE_PULSE);
+ /* Notify TZ to stop receiving idle info for the core */
+ ret = msm_dcvs_update_freq(core, MSM_DCVS_SCM_DCVS_ENABLE, 0,
+ &ret1, &ret2);
+ hrtimer_cancel(&core->timer);
+ core->idle_enable(core->type_core_num,
+ MSM_DCVS_ENABLE_HIGH_LATENCY_MODES);
+ if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
+ __info("Enabling LPM for %s\n", core->core_name);
mutex_unlock(&core->lock);
return 0;
}
EXPORT_SYMBOL(msm_dcvs_freq_sink_stop);
-int msm_dcvs_idle_source_register(struct msm_dcvs_idle *drv)
-{
- int ret = -EINVAL;
- struct dcvs_core *core = NULL;
-
- if (!drv || !drv->core_name)
- return ret;
-
- core = msm_dcvs_get_core(drv->core_name, NULL);
- if (!core)
- return ret;
-
- mutex_lock(&core->lock);
- if (core->idle_driver && (msm_dcvs_debug & MSM_DCVS_DEBUG_NOTIFIER))
- __info("Idle notifier for %s being replaced\n",
- core->core_name);
- core->idle_driver = drv;
- mutex_unlock(&core->lock);
-
- return core->handle;
-}
-EXPORT_SYMBOL(msm_dcvs_idle_source_register);
-
-int msm_dcvs_idle_source_unregister(struct msm_dcvs_idle *drv)
-{
- int ret = -EINVAL;
- struct dcvs_core *core = NULL;
-
- if (!drv || !drv->core_name)
- return ret;
-
- core = msm_dcvs_get_core(drv->core_name, NULL);
- if (!core)
- return ret;
-
- mutex_lock(&core->lock);
- core->idle_driver = NULL;
- mutex_unlock(&core->lock);
-
- return 0;
-}
-EXPORT_SYMBOL(msm_dcvs_idle_source_unregister);
-
-int msm_dcvs_idle(int handle, enum msm_core_idle_state state, uint32_t iowaited)
+int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state,
+ uint32_t iowaited)
{
int ret = 0;
struct dcvs_core *core = NULL;
@@ -824,11 +765,12 @@
uint32_t r0, r1;
uint32_t freq_changed = 0;
- if (handle >= CORE_HANDLE_OFFSET &&
- (handle - CORE_HANDLE_OFFSET) < CORES_MAX)
- core = &core_list[handle - CORE_HANDLE_OFFSET];
+ if (dcvs_core_id < CPU_OFFSET || dcvs_core_id > CORES_MAX) {
+ pr_err("invalid dcvs_core_id = %d ret -EINVAL\n", dcvs_core_id);
+ return -EINVAL;
+ }
- BUG_ON(!core);
+ core = msm_dcvs_get_core(dcvs_core_id);
if (msm_dcvs_debug & MSM_DCVS_DEBUG_IDLE_PULSE)
__info("Core %s idle state %d\n", core->core_name, state);
@@ -836,7 +778,7 @@
switch (state) {
case MSM_DCVS_IDLE_ENTER:
hrtimer_cancel(&core->timer);
- ret = msm_dcvs_scm_event(core->handle,
+ ret = msm_dcvs_scm_event(core->dcvs_core_id,
MSM_DCVS_SCM_IDLE_ENTER, 0, 0, &r0, &r1);
if (ret)
__err("Error (%d) sending idle enter for %s\n",
@@ -917,6 +859,7 @@
static int __init msm_dcvs_early_init(void)
{
int ret = 0;
+ int i;
if (!msm_dcvs_enabled) {
__info("Not enabled (%d)\n", msm_dcvs_enabled);
@@ -927,6 +870,8 @@
if (ret)
__err("Unable to initialize DCVS err=%d\n", ret);
+ for (i = 0; i < CORES_MAX; i++)
+ core_list[i].dcvs_core_id = -1;
return ret;
}
postcore_initcall(msm_dcvs_early_init);
diff --git a/drivers/cpufreq/cpufreq_gov_msm.c b/drivers/cpufreq/cpufreq_gov_msm.c
index 2b68d2a..6ddbf4e 100644
--- a/drivers/cpufreq/cpufreq_gov_msm.c
+++ b/drivers/cpufreq/cpufreq_gov_msm.c
@@ -25,23 +25,19 @@
#include <mach/msm_dcvs.h>
struct cpu_idle_info {
- int cpu;
- int enabled;
- int handle;
- struct msm_dcvs_idle dcvs_notifier;
- struct pm_qos_request pm_qos_req;
+ int enabled;
+ int dcvs_core_id;
+ struct pm_qos_request pm_qos_req;
};
static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_idle_info, cpu_idle_info);
static DEFINE_PER_CPU_SHARED_ALIGNED(u64, iowait_on_cpu);
-static char core_name[NR_CPUS][10];
static uint32_t latency;
-static int msm_dcvs_idle_notifier(struct msm_dcvs_idle *self,
+static int msm_dcvs_idle_notifier(int core_num,
enum msm_core_control_event event)
{
- struct cpu_idle_info *info = container_of(self,
- struct cpu_idle_info, dcvs_notifier);
+ struct cpu_idle_info *info = &per_cpu(cpu_idle_info, core_num);
switch (event) {
case MSM_DCVS_ENABLE_IDLE_PULSE:
@@ -86,7 +82,7 @@
if (val == (u64)-1)
val = 0;
per_cpu(iowait_on_cpu, smp_processor_id()) = val;
- msm_dcvs_idle(info->handle, MSM_DCVS_IDLE_ENTER, 0);
+ msm_dcvs_idle(info->dcvs_core_id, MSM_DCVS_IDLE_ENTER, 0);
break;
case CPU_PM_EXIT:
@@ -97,7 +93,7 @@
val = 0;
io_wait_us = val;
iowaited = (io_wait_us - prev_io_wait_us);
- msm_dcvs_idle(info->handle, MSM_DCVS_IDLE_EXIT, iowaited);
+ msm_dcvs_idle(info->dcvs_core_id, MSM_DCVS_IDLE_EXIT, iowaited);
break;
}
@@ -108,52 +104,32 @@
.notifier_call = msm_cpuidle_notifier,
};
-static void msm_gov_idle_source_init(int cpu)
+static void msm_gov_idle_source_init(int cpu, int dcvs_core_id)
{
struct cpu_idle_info *info = NULL;
- struct msm_dcvs_idle *inotify = NULL;
info = &per_cpu(cpu_idle_info, cpu);
- info->cpu = cpu;
- inotify = &info->dcvs_notifier;
- snprintf(core_name[cpu], 10, "cpu%d", cpu);
- inotify->core_name = core_name[cpu];
- info->handle = msm_dcvs_idle_source_register(inotify);
- BUG_ON(info->handle < 0);
+ info->dcvs_core_id = dcvs_core_id;
pm_qos_add_request(&info->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
}
-static int msm_gov_idle_source_uninit(int cpu)
-{
- struct cpu_idle_info *info = NULL;
- struct msm_dcvs_idle *inotify = NULL;
-
- info = &per_cpu(cpu_idle_info, cpu);
- info->cpu = cpu;
- inotify = &info->dcvs_notifier;
- return msm_dcvs_idle_source_unregister(inotify);
-}
-
struct msm_gov {
- int cpu;
- unsigned int cur_freq;
- unsigned int min_freq;
- unsigned int max_freq;
- struct msm_dcvs_freq gov_notifier;
- struct cpufreq_policy *policy;
+ int cpu;
+ unsigned int cur_freq;
+ unsigned int min_freq;
+ unsigned int max_freq;
+ struct cpufreq_policy *policy;
+ int dcvs_core_id;
};
static DEFINE_PER_CPU_SHARED_ALIGNED(struct mutex, gov_mutex);
static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_gov, msm_gov_info);
-static char core_name[NR_CPUS][10];
static void msm_gov_check_limits(struct cpufreq_policy *policy)
{
struct msm_gov *gov = &per_cpu(msm_gov_info, policy->cpu);
- struct msm_dcvs_freq *dcvs_notifier =
- &(per_cpu(msm_gov_info, policy->cpu).gov_notifier);
if (policy->max < gov->cur_freq)
__cpufreq_driver_target(policy, policy->max,
@@ -168,15 +144,14 @@
gov->cur_freq = policy->cur;
gov->min_freq = policy->min;
gov->max_freq = policy->max;
- msm_dcvs_update_limits(dcvs_notifier);
+ msm_dcvs_update_limits(gov->dcvs_core_id);
}
-static int msm_dcvs_freq_set(struct msm_dcvs_freq *self,
+static int msm_dcvs_freq_set(int core_num,
unsigned int freq)
{
int ret = -EINVAL;
- struct msm_gov *gov =
- container_of(self, struct msm_gov, gov_notifier);
+ struct msm_gov *gov = &per_cpu(msm_gov_info, core_num);
mutex_lock(&per_cpu(gov_mutex, gov->cpu));
@@ -200,11 +175,9 @@
return ret;
}
-static unsigned int msm_dcvs_freq_get(struct msm_dcvs_freq *self)
+static unsigned int msm_dcvs_freq_get(int core_num)
{
- struct msm_gov *gov =
- container_of(self, struct msm_gov, gov_notifier);
-
+ struct msm_gov *gov = &per_cpu(msm_gov_info, core_num);
/*
* the rw_sem in cpufreq is always held when this is called.
* The policy->cur won't be updated in this case - so it is safe to
@@ -220,8 +193,6 @@
int ret = 0;
int handle = 0;
struct msm_gov *gov = &per_cpu(msm_gov_info, policy->cpu);
- struct msm_dcvs_freq *dcvs_notifier =
- &(per_cpu(msm_gov_info, cpu).gov_notifier);
switch (event) {
case CPUFREQ_GOV_START:
@@ -231,15 +202,14 @@
mutex_lock(&per_cpu(gov_mutex, cpu));
per_cpu(msm_gov_info, cpu).cpu = cpu;
gov->policy = policy;
- dcvs_notifier->core_name = core_name[cpu];
- handle = msm_dcvs_freq_sink_start(dcvs_notifier);
+ handle = msm_dcvs_freq_sink_start(gov->dcvs_core_id);
BUG_ON(handle < 0);
msm_gov_check_limits(policy);
mutex_unlock(&per_cpu(gov_mutex, cpu));
break;
case CPUFREQ_GOV_STOP:
- msm_dcvs_freq_sink_stop(dcvs_notifier);
+ msm_dcvs_freq_sink_stop(gov->dcvs_core_id);
break;
case CPUFREQ_GOV_LIMITS:
@@ -260,7 +230,6 @@
static int __devinit msm_gov_probe(struct platform_device *pdev)
{
- int ret = 0;
int cpu;
struct msm_dcvs_core_info *core = NULL;
struct msm_dcvs_core_info *core_info = NULL;
@@ -272,19 +241,25 @@
latency = pdata->latency;
for_each_possible_cpu(cpu) {
+ struct msm_gov *gov = &per_cpu(msm_gov_info, cpu);
+
mutex_init(&per_cpu(gov_mutex, cpu));
- snprintf(core_name[cpu], 10, "cpu%d", cpu);
if (cpu < core->num_cores)
sensor = core_info->sensors[cpu];
- ret = msm_dcvs_register_core(core_name[cpu], core_info,
+ gov->dcvs_core_id = msm_dcvs_register_core(
+ MSM_DCVS_CORE_TYPE_CPU,
+ cpu,
+ core_info,
msm_dcvs_freq_set,
msm_dcvs_freq_get,
msm_dcvs_idle_notifier,
sensor);
- if (ret)
+ if (gov->dcvs_core_id < 0) {
pr_err("Unable to register core for %d\n", cpu);
+ return -EINVAL;
+ }
- msm_gov_idle_source_init(cpu);
+ msm_gov_idle_source_init(cpu, gov->dcvs_core_id);
}
cpu_pm_register_notifier(&idle_nb);
@@ -294,11 +269,6 @@
static int __devexit msm_gov_remove(struct platform_device *pdev)
{
- int cpu;
-
- for_each_possible_cpu(cpu) {
- msm_gov_idle_source_uninit(cpu);
- }
platform_set_drvdata(pdev, NULL);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
index d6a39b0..19d1f1b 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_msm.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -20,21 +20,21 @@
#include "kgsl_trace.h"
struct msm_priv {
- struct kgsl_device *device;
- int enabled;
- int handle;
- unsigned int cur_freq;
- struct msm_dcvs_idle idle_source;
- struct msm_dcvs_freq freq_sink;
- struct msm_dcvs_core_info *core_info;
- int gpu_busy;
+ struct kgsl_device *device;
+ int enabled;
+ unsigned int cur_freq;
+ struct msm_dcvs_core_info *core_info;
+ int gpu_busy;
+ int dcvs_core_id;
};
-static int msm_idle_enable(struct msm_dcvs_idle *self,
- enum msm_core_control_event event)
+/* reference to be used in idle and freq callbacks */
+static struct msm_priv *the_msm_priv;
+
+static int msm_idle_enable(int type_core_num,
+ enum msm_core_control_event event)
{
- struct msm_priv *priv = container_of(self, struct msm_priv,
- idle_source);
+ struct msm_priv *priv = the_msm_priv;
switch (event) {
case MSM_DCVS_ENABLE_IDLE_PULSE:
@@ -53,12 +53,10 @@
/* Set the requested frequency if it is within 5MHz (delta) of a
* supported frequency.
*/
-static int msm_set_freq(struct msm_dcvs_freq *self,
- unsigned int freq)
+static int msm_set_freq(int core_num, unsigned int freq)
{
int i, delta = 5000000;
- struct msm_priv *priv = container_of(self, struct msm_priv,
- freq_sink);
+ struct msm_priv *priv = the_msm_priv;
struct kgsl_device *device = priv->device;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
@@ -79,10 +77,10 @@
return priv->cur_freq / 1000;
}
-static unsigned int msm_get_freq(struct msm_dcvs_freq *self)
+static unsigned int msm_get_freq(int core_num)
{
- struct msm_priv *priv = container_of(self, struct msm_priv,
- freq_sink);
+ struct msm_priv *priv = the_msm_priv;
+
/* return current frequency in kHz */
return priv->cur_freq / 1000;
}
@@ -92,7 +90,7 @@
{
struct msm_priv *priv = pwrscale->priv;
if (priv->enabled && !priv->gpu_busy) {
- msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_EXIT, 0);
+ msm_dcvs_idle(priv->dcvs_core_id, MSM_DCVS_IDLE_EXIT, 0);
trace_kgsl_mpdcvs(device, 1);
priv->gpu_busy = 1;
}
@@ -106,7 +104,8 @@
if (priv->enabled && priv->gpu_busy)
if (device->ftbl->isidle(device)) {
- msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+ msm_dcvs_idle(priv->dcvs_core_id,
+ MSM_DCVS_IDLE_ENTER, 0);
trace_kgsl_mpdcvs(device, 0);
priv->gpu_busy = 0;
}
@@ -119,7 +118,7 @@
struct msm_priv *priv = pwrscale->priv;
if (priv->enabled && priv->gpu_busy) {
- msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+ msm_dcvs_idle(priv->dcvs_core_id, MSM_DCVS_IDLE_ENTER, 0);
trace_kgsl_mpdcvs(device, 0);
priv->gpu_busy = 0;
}
@@ -132,7 +131,7 @@
{
struct msm_priv *priv;
struct msm_dcvs_freq_entry *tbl;
- int i, ret, low_level;
+ int i, ret = -EINVAL, low_level;
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
struct platform_device *pdev =
container_of(device->parentdev, struct platform_device, dev);
@@ -149,29 +148,24 @@
low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
for (i = 0; i <= low_level; i++)
tbl[i].freq = pwr->pwrlevels[low_level - i].gpu_freq / 1000;
- ret = msm_dcvs_register_core(device->name, priv->core_info,
- msm_set_freq, msm_get_freq, msm_idle_enable,
- priv->core_info->sensors[0]);
- if (ret) {
+ priv->dcvs_core_id = msm_dcvs_register_core(MSM_DCVS_CORE_TYPE_GPU, 0,
+ priv->core_info,
+ msm_set_freq, msm_get_freq, msm_idle_enable,
+ priv->core_info->sensors[0]);
+ if (priv->dcvs_core_id < 0) {
KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
goto err;
}
priv->device = device;
- priv->idle_source.core_name = device->name;
- priv->handle = msm_dcvs_idle_source_register(&priv->idle_source);
- if (priv->handle < 0) {
- ret = priv->handle;
- KGSL_PWR_ERR(device, "msm_dcvs_idle_source_register failed\n");
- goto err;
- }
- priv->freq_sink.core_name = device->name;
- ret = msm_dcvs_freq_sink_start(&priv->freq_sink);
+ the_msm_priv = priv;
+ ret = msm_dcvs_freq_sink_start(priv->dcvs_core_id);
if (ret >= 0) {
if (device->ftbl->isidle(device)) {
priv->gpu_busy = 0;
- msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+ msm_dcvs_idle(priv->dcvs_core_id,
+ MSM_DCVS_IDLE_ENTER, 0);
} else {
priv->gpu_busy = 1;
}
@@ -179,7 +173,6 @@
}
KGSL_PWR_ERR(device, "msm_dcvs_freq_sink_register failed\n");
- msm_dcvs_idle_source_unregister(&priv->idle_source);
err:
kfree(pwrscale->priv);
@@ -195,8 +188,7 @@
if (pwrscale->priv == NULL)
return;
- msm_dcvs_idle_source_unregister(&priv->idle_source);
- msm_dcvs_freq_sink_stop(&priv->freq_sink);
+ msm_dcvs_freq_sink_stop(priv->dcvs_core_id);
kfree(pwrscale->priv);
pwrscale->priv = NULL;
}