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;
 }