diff --git a/drivers/cpuidle/cpuidle-haltpoll.c b/drivers/cpuidle/cpuidle-haltpoll.c
index fc351f093ce1afef947a4b164fdb0e0b91d28448..ae4f06f0507987c5db02a454b7886e764ef82806 100644
--- a/drivers/cpuidle/cpuidle-haltpoll.c
+++ b/drivers/cpuidle/cpuidle-haltpoll.c
@@ -117,7 +117,9 @@ static int __init haltpoll_init(void)
 		return -ENODEV;
 
 	ret = cpuidle_register_driver(drv);
-	if (ret < 0)
+	if (ret == 0)
+		haltpoll_switch_governor(drv);
+	else if (ret < 0)
 		return ret;
 
 	haltpoll_cpuidle_dev_wrap = alloc_percpu(struct cpuidle_device_wrapper);
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index b7a7125f1cded5113d2ae5ece55d2897a8985f26..42fc9477375335ff1d24f9874ed9344e5f0d22e5 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -330,15 +330,9 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index)
 u64 cpuidle_poll_time(struct cpuidle_driver *drv,
 		      struct cpuidle_device *dev)
 {
-	struct cpuidle_device_wrapper *devw =
-		container_of(dev, struct cpuidle_device_wrapper, dev);
+	u64 limit_ns = TICK_NSEC;
 	int i;
-	u64 limit_ns;
 
-	if (devw->poll_limit_ns)
-		return devw->poll_limit_ns;
-
-	limit_ns = TICK_NSEC;
 	for (i = 1; i < drv->state_count; i++) {
 		if (drv->states[i].disabled || dev->states_usage[i].disable)
 			continue;
@@ -348,7 +342,19 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv,
 		break;
 	}
 
-	devw->poll_limit_ns = limit_ns;
+	return limit_ns;
+}
+
+u64 cpuidle_haltpoll_time(struct cpuidle_driver *drv,
+			struct cpuidle_device *dev)
+{
+	struct cpuidle_device_wrapper *devw =
+		container_of(dev, struct cpuidle_device_wrapper, dev);
+
+	if (devw->poll_limit_ns)
+		return devw->poll_limit_ns;
+
+	devw->poll_limit_ns = cpuidle_poll_time(drv, dev);
 
 	return devw->poll_limit_ns;
 }
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index 47930a0ecb0f14cbbf8bbbc983ea1a49e66e9257..484d0e9655fcbfbf9027533078ea5a149ef02005 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -241,6 +241,25 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
 	__cpuidle_unset_driver(drv);
 }
 
+void haltpoll_switch_governor(struct cpuidle_driver *drv)
+{
+	struct cpuidle_governor *gov;
+	struct cpuidle_driver_wrapper *drvw;
+
+	drvw = container_of(drv, struct cpuidle_driver_wrapper, drv);
+	if (!strlen(param_governor) && drvw->governor &&
+	    (cpuidle_get_driver() == drv)) {
+		mutex_lock(&cpuidle_lock);
+		gov = cpuidle_find_governor(drvw->governor);
+		if (gov) {
+			cpuidle_prev_governor = cpuidle_curr_governor;
+			if (cpuidle_switch_governor(gov) < 0)
+				cpuidle_prev_governor = NULL;
+		}
+		mutex_unlock(&cpuidle_lock);
+	}
+}
+
 /**
  * cpuidle_register_driver - registers a driver
  * @drv: a pointer to a valid struct cpuidle_driver
@@ -253,29 +272,15 @@ static void __cpuidle_unregister_driver(struct cpuidle_driver *drv)
  */
 int cpuidle_register_driver(struct cpuidle_driver *drv)
 {
-	struct cpuidle_governor *gov;
-	struct cpuidle_driver_wrapper *drvw;
 	int ret;
 
 	spin_lock(&cpuidle_driver_lock);
 	ret = __cpuidle_register_driver(drv);
 	spin_unlock(&cpuidle_driver_lock);
-	drvw = container_of(drv, struct cpuidle_driver_wrapper, drv);
-
-	if (!ret && !strlen(param_governor) && drvw->governor &&
-	    (cpuidle_get_driver() == drv)) {
-		mutex_lock(&cpuidle_lock);
-		gov = cpuidle_find_governor(drvw->governor);
-		if (gov) {
-			cpuidle_prev_governor = cpuidle_curr_governor;
-			if (cpuidle_switch_governor(gov) < 0)
-				cpuidle_prev_governor = NULL;
-		}
-		mutex_unlock(&cpuidle_lock);
-	}
 
 	return ret;
 }
+
 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
 /**
diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c
index aa9842b1f1cc2317ee8eace94193d2bb2bbf0c60..a73c09464429f4c3a574c6813de26ae03c8f3aa3 100644
--- a/drivers/cpuidle/poll_state.c
+++ b/drivers/cpuidle/poll_state.c
@@ -26,7 +26,10 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
 		unsigned int loop_count = 0;
 		u64 limit;
 
-		limit = cpuidle_poll_time(drv, dev);
+		if (drv->name && !strcmp(drv->name, "haltpoll"))
+			limit = cpuidle_haltpoll_time(drv, dev);
+		else
+			limit = cpuidle_poll_time(drv, dev);
 
 		while (!need_resched()) {
 			cpu_relax();
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index f966a343daa71433b0e54c883dadd9a4f9e3d22e..4c8042f19a9601e38bbb8985d6c19adf946eca62 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -410,16 +410,10 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr,
 	struct cpuidle_state *state = kobj_to_state(kobj);
 	struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
 	struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
-	struct cpuidle_device *dev = kobj_to_device(kobj);
-	struct cpuidle_device_wrapper *devw =
-		container_of(dev, struct cpuidle_device_wrapper, dev);
 
 	if (cattr->store)
 		ret = cattr->store(state, state_usage, buf, size);
 
-	/* reset poll time cache */
-	devw->poll_limit_ns = 0;
-
 	return ret;
 }
 
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 364e28be3155f5f9f9d9f1de15af373abac9b459..e365f5dfe6e7dbdffb7b4f05d995e5daff7a5934 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -155,7 +155,10 @@ extern int cpuidle_enter(struct cpuidle_driver *drv,
 extern void cpuidle_reflect(struct cpuidle_device *dev, int index);
 extern u64 cpuidle_poll_time(struct cpuidle_driver *drv,
 			     struct cpuidle_device *dev);
+extern u64 cpuidle_haltpoll_time(struct cpuidle_driver *drv,
+				  struct cpuidle_device *dev);
 
+extern void haltpoll_switch_governor(struct cpuidle_driver *drv);
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
 extern struct cpuidle_driver *cpuidle_get_driver(void);
 extern struct cpuidle_driver *cpuidle_driver_ref(void);
@@ -192,8 +195,13 @@ static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { }
 static inline u64 cpuidle_poll_time(struct cpuidle_driver *drv,
 			     struct cpuidle_device *dev)
 {return 0; }
+static inline u64 cpuidle_haltpoll_time(struct cpuidle_driver *drv,
+					struct cpuidle_device *dev)
+{return 0; }
 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
 {return -ENODEV; }
+static inline void haltpoll_switch_governor(struct cpuidle_driver *drv)
+{return -ENODEV; }
 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
 static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; }
 static inline void cpuidle_driver_unref(void) {}