lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <201111070106.52411.rjw@sisk.pl>
Date:	Mon, 7 Nov 2011 01:06:52 +0100
From:	"Rafael J. Wysocki" <rjw@...k.pl>
To:	Linux PM list <linux-pm@...r.kernel.org>
Cc:	LKML <linux-kernel@...r.kernel.org>,
	"Linux-sh list" <linux-sh@...r.kernel.org>,
	Magnus Damm <magnus.damm@...il.com>,
	Guennadi Liakhovetski <g.liakhovetski@....de>,
	Kevin Hilman <khilman@...com>, jean.pihet@...oldbits.com
Subject: [PATCH 2/7] PM / Domains: Make it possible to use per-device .active_wakeup()

From: Rafael J. Wysocki <rjw@...k.pl>

The current generic PM domains code requires that the same
.active_wakeup() device callback routine be used for all devices in
the given domain, which is inflexible and may not cover some specific
use cases.  For this reason, make it possible to use device specific
.active_wakeup() callback routines by adding a corresponding callback
pointer to struct generic_pm_domain_data.  To reduce code duplication
use struct gpd_dev_ops to represent PM domain device callbacks as
well as device-specific ones and add a macro for defining routines
that will execute those callbacks.

Modify the shmobile's power domains code to allow drivers to use
their own .active_wakeup() callback routines.

Signed-off-by: Rafael J. Wysocki <rjw@...k.pl>
---
 arch/arm/mach-shmobile/pm-sh7372.c |   11 ++++---
 drivers/base/power/domain.c        |   54 ++++++++++++++++++-------------------
 include/linux/pm_domain.h          |   15 ++++------
 3 files changed, 41 insertions(+), 39 deletions(-)

Index: linux/include/linux/pm_domain.h
===================================================================
--- linux.orig/include/linux/pm_domain.h
+++ linux/include/linux/pm_domain.h
@@ -23,6 +23,12 @@ struct dev_power_governor {
 	bool (*power_down_ok)(struct dev_pm_domain *domain);
 };
 
+struct gpd_dev_ops {
+	int (*start)(struct device *dev);
+	int (*stop)(struct device *dev);
+	bool (*active_wakeup)(struct device *dev);
+};
+
 struct generic_pm_domain {
 	struct dev_pm_domain domain;	/* PM domain operations */
 	struct list_head gpd_list_node;	/* Node in the global PM domains list */
@@ -45,9 +51,7 @@ struct generic_pm_domain {
 	bool dev_irq_safe;	/* Device callbacks are IRQ-safe */
 	int (*power_off)(struct generic_pm_domain *domain);
 	int (*power_on)(struct generic_pm_domain *domain);
-	int (*start_device)(struct device *dev);
-	int (*stop_device)(struct device *dev);
-	bool (*active_wakeup)(struct device *dev);
+	struct gpd_dev_ops dev_ops;
 };
 
 static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
@@ -62,11 +66,6 @@ struct gpd_link {
 	struct list_head slave_node;
 };
 
-struct gpd_dev_ops {
-	int (*start)(struct device *dev);
-	int (*stop)(struct device *dev);
-};
-
 struct generic_pm_domain_data {
 	struct pm_domain_data base;
 	struct gpd_dev_ops ops;
Index: linux/drivers/base/power/domain.c
===================================================================
--- linux.orig/drivers/base/power/domain.c
+++ linux/drivers/base/power/domain.c
@@ -16,6 +16,22 @@
 #include <linux/sched.h>
 #include <linux/suspend.h>
 
+#define GENPD_DEV_CALLBACK(genpd, type, callback, dev)		\
+({								\
+	type (*__routine)(struct device *__d); 			\
+	type __ret = (type)0;					\
+								\
+	__routine = genpd->dev_ops.callback; 			\
+	if (__routine) {					\
+		__ret = __routine(dev); 			\
+	} else {						\
+		__routine = dev_gpd_data(dev)->ops.callback;	\
+		if (__routine) 					\
+			__ret = __routine(dev);			\
+	}							\
+	__ret;							\
+})
+
 static LIST_HEAD(gpd_list);
 static DEFINE_MUTEX(gpd_list_lock);
 
@@ -31,32 +47,12 @@ static struct generic_pm_domain *dev_to_
 
 static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-	int (*stop)(struct device *dev);
-
-	stop = genpd->stop_device;
-	if (stop)
-		return stop(dev);
-
-	stop = dev_gpd_data(dev)->ops.stop;
-	if (stop)
-		return stop(dev);
-
-	return 0;
+	return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
 }
 
 static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
 {
-	int (*start)(struct device *dev);
-
-	start = genpd->start_device;
-	if (start)
-		return start(dev);
-
-	start = dev_gpd_data(dev)->ops.start;
-	if (start)
-		return start(dev);
-
-	return 0;
+	return GENPD_DEV_CALLBACK(genpd, int, start, dev);
 }
 
 static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
@@ -554,6 +550,12 @@ static inline void genpd_power_off_work_
 
 #ifdef CONFIG_PM_SLEEP
 
+static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
+				    struct device *dev)
+{
+	return GENPD_DEV_CALLBACK(genpd, bool, active_wakeup, dev);
+}
+
 /**
  * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
  * @genpd: PM domain to power off, if possible.
@@ -610,7 +612,7 @@ static bool resume_needed(struct device
 	if (!device_can_wakeup(dev))
 		return false;
 
-	active_wakeup = genpd->active_wakeup && genpd->active_wakeup(dev);
+	active_wakeup = genpd_dev_active_wakeup(genpd, dev);
 	return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
 }
 
@@ -734,8 +736,7 @@ static int pm_genpd_suspend_noirq(struct
 	if (ret)
 		return ret;
 
-	if (dev->power.wakeup_path
-	    && genpd->active_wakeup && genpd->active_wakeup(dev))
+	if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
 		return 0;
 
 	genpd_stop_dev(genpd, dev);
@@ -954,8 +955,7 @@ static int pm_genpd_dev_poweroff_noirq(s
 	if (ret)
 		return ret;
 
-	if (dev->power.wakeup_path
-	    && genpd->active_wakeup && genpd->active_wakeup(dev))
+	if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))
 		return 0;
 
 	genpd_stop_dev(genpd, dev);
Index: linux/arch/arm/mach-shmobile/pm-sh7372.c
===================================================================
--- linux.orig/arch/arm/mach-shmobile/pm-sh7372.c
+++ linux/arch/arm/mach-shmobile/pm-sh7372.c
@@ -151,7 +151,10 @@ static void sh7372_a4r_suspend(void)
 
 static bool pd_active_wakeup(struct device *dev)
 {
-	return true;
+	bool (*active_wakeup)(struct device *dev);
+
+	active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
+	return active_wakeup ? active_wakeup(dev) : true;
 }
 
 static bool sh7372_power_down_forbidden(struct dev_pm_domain *domain)
@@ -197,10 +200,10 @@ void sh7372_init_pm_domain(struct sh7372
 	struct generic_pm_domain *genpd = &sh7372_pd->genpd;
 
 	pm_genpd_init(genpd, sh7372_pd->gov, false);
-	genpd->stop_device = sh7372_stop_dev;
-	genpd->start_device = sh7372_start_dev;
+	genpd->dev_ops.stop = sh7372_stop_dev;
+	genpd->dev_ops.start = sh7372_start_dev;
+	genpd->dev_ops.active_wakeup = pd_active_wakeup;
 	genpd->dev_irq_safe = true;
-	genpd->active_wakeup = pd_active_wakeup;
 	genpd->power_off = pd_power_down;
 	genpd->power_on = pd_power_up;
 	genpd->power_on(&sh7372_pd->genpd);

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ