+++ /dev/null
-The generic rwsem implementation of down_read() and down_write() does not\r
-save and restore interrupt state. This causes powerdomain code to\r
-inadvertently enable interrupts early in the boot process, causing\r
-init/main.c to complain. This patch converts powerdomain locking to\r
-r-w spinlocks instead.\r
-\r
-I'm also curious to know if this fixes the BeagleBoard boot problem.\r
-\r
-Signed-off-by: Paul Walmsley <paul@pwsan.com>\r
----\r
-\r
- arch/arm/mach-omap2/powerdomain.c | 46 ++++++++++++++++++++++---------------\r
- 1 files changed, 27 insertions(+), 19 deletions(-)\r
-\r
-\r
-diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c\r
-index 939efe4..0a6caaf 100644\r
---- a/arch/arm/mach-omap2/powerdomain.c\r
-+++ b/arch/arm/mach-omap2/powerdomain.c\r
-@@ -18,7 +18,7 @@\r
- #include <linux/module.h>\r
- #include <linux/types.h>\r
- #include <linux/delay.h>\r
--#include <linux/rwsem.h>\r
-+#include <linux/spinlock.h>\r
- #include <linux/list.h>\r
- #include <linux/errno.h>\r
- #include <linux/err.h>\r
-@@ -38,10 +38,10 @@\r
- static LIST_HEAD(pwrdm_list);\r
- \r
- /*\r
-- * pwrdm_rwsem protects pwrdm_list add and del ops - also reused to\r
-+ * pwrdm_rwlock protects pwrdm_list add and del ops - also reused to\r
- * protect pwrdm_clkdms[] during clkdm add/del ops\r
- */\r
--static DECLARE_RWSEM(pwrdm_rwsem);\r
-+static DEFINE_RWLOCK(pwrdm_rwlock);\r
- \r
- \r
- /* Private functions */\r
-@@ -131,6 +131,7 @@ void pwrdm_init(struct powerdomain **pwrdm_list)\r
- */\r
- int pwrdm_register(struct powerdomain *pwrdm)\r
- {\r
-+ unsigned long flags;\r
- int ret = -EINVAL;\r
- \r
- if (!pwrdm)\r
-@@ -139,7 +140,7 @@ int pwrdm_register(struct powerdomain *pwrdm)\r
- if (!omap_chip_is(pwrdm->omap_chip))\r
- return -EINVAL;\r
- \r
-- down_write(&pwrdm_rwsem);\r
-+ write_lock_irqsave(&pwrdm_rwlock, flags);\r
- if (_pwrdm_lookup(pwrdm->name)) {\r
- ret = -EEXIST;\r
- goto pr_unlock;\r
-@@ -151,7 +152,7 @@ int pwrdm_register(struct powerdomain *pwrdm)\r
- ret = 0;\r
- \r
- pr_unlock:\r
-- up_write(&pwrdm_rwsem);\r
-+ write_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- return ret;\r
- }\r
-@@ -165,12 +166,14 @@ pr_unlock:\r
- */\r
- int pwrdm_unregister(struct powerdomain *pwrdm)\r
- {\r
-+ unsigned long flags;\r
-+\r
- if (!pwrdm)\r
- return -EINVAL;\r
- \r
-- down_write(&pwrdm_rwsem);\r
-+ write_lock_irqsave(&pwrdm_rwlock, flags);\r
- list_del(&pwrdm->node);\r
-- up_write(&pwrdm_rwsem);\r
-+ write_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- pr_debug("powerdomain: unregistered %s\n", pwrdm->name);\r
- \r
-@@ -187,13 +190,14 @@ int pwrdm_unregister(struct powerdomain *pwrdm)\r
- struct powerdomain *pwrdm_lookup(const char *name)\r
- {\r
- struct powerdomain *pwrdm;\r
-+ unsigned long flags;\r
- \r
- if (!name)\r
- return NULL;\r
- \r
-- down_read(&pwrdm_rwsem);\r
-+ read_lock_irqsave(&pwrdm_rwlock, flags);\r
- pwrdm = _pwrdm_lookup(name);\r
-- up_read(&pwrdm_rwsem);\r
-+ read_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- return pwrdm;\r
- }\r
-@@ -204,7 +208,7 @@ struct powerdomain *pwrdm_lookup(const char *name)\r
- *\r
- * Call the supplied function for each registered powerdomain. The\r
- * callback function can return anything but 0 to bail out early from\r
-- * the iterator. The callback function is called with the pwrdm_rwsem\r
-+ * the iterator. The callback function is called with the pwrdm_rwlock\r
- * held for reading, so no powerdomain structure manipulation\r
- * functions should be called from the callback, although hardware\r
- * powerdomain control functions are fine. Returns the last return\r
-@@ -215,18 +219,19 @@ struct powerdomain *pwrdm_lookup(const char *name)\r
- int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))\r
- {\r
- struct powerdomain *temp_pwrdm;\r
-+ unsigned long flags;\r
- int ret = 0;\r
- \r
- if (!fn)\r
- return -EINVAL;\r
- \r
-- down_read(&pwrdm_rwsem);\r
-+ read_lock_irqsave(&pwrdm_rwlock, flags);\r
- list_for_each_entry(temp_pwrdm, &pwrdm_list, node) {\r
- ret = (*fn)(temp_pwrdm);\r
- if (ret)\r
- break;\r
- }\r
-- up_read(&pwrdm_rwsem);\r
-+ read_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- return ret;\r
- }\r
-@@ -243,6 +248,7 @@ int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm))\r
- */\r
- int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)\r
- {\r
-+ unsigned long flags;\r
- int i;\r
- int ret = -EINVAL;\r
- \r
-@@ -252,7 +258,7 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)\r
- pr_debug("powerdomain: associating clockdomain %s with powerdomain "\r
- "%s\n", clkdm->name, pwrdm->name);\r
- \r
-- down_write(&pwrdm_rwsem);\r
-+ write_lock_irqsave(&pwrdm_rwlock, flags);\r
- \r
- for (i = 0; i < PWRDM_MAX_CLKDMS; i++) {\r
- if (!pwrdm->pwrdm_clkdms[i])\r
-@@ -278,7 +284,7 @@ int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)\r
- ret = 0;\r
- \r
- pac_exit:\r
-- up_write(&pwrdm_rwsem);\r
-+ write_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- return ret;\r
- }\r
-@@ -295,6 +301,7 @@ pac_exit:\r
- */\r
- int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)\r
- {\r
-+ unsigned long flags;\r
- int ret = -EINVAL;\r
- int i;\r
- \r
-@@ -304,7 +311,7 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)\r
- pr_debug("powerdomain: dissociating clockdomain %s from powerdomain "\r
- "%s\n", clkdm->name, pwrdm->name);\r
- \r
-- down_write(&pwrdm_rwsem);\r
-+ write_lock_irqsave(&pwrdm_rwlock, flags);\r
- \r
- for (i = 0; i < PWRDM_MAX_CLKDMS; i++)\r
- if (pwrdm->pwrdm_clkdms[i] == clkdm)\r
-@@ -322,7 +329,7 @@ int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm)\r
- ret = 0;\r
- \r
- pdc_exit:\r
-- up_write(&pwrdm_rwsem);\r
-+ write_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- return ret;\r
- }\r
-@@ -335,7 +342,7 @@ pdc_exit:\r
- * Call the supplied function for each clockdomain in the powerdomain\r
- * 'pwrdm'. The callback function can return anything but 0 to bail\r
- * out early from the iterator. The callback function is called with\r
-- * the pwrdm_rwsem held for reading, so no powerdomain structure\r
-+ * the pwrdm_rwlock held for reading, so no powerdomain structure\r
- * manipulation functions should be called from the callback, although\r
- * hardware powerdomain control functions are fine. Returns -EINVAL\r
- * if presented with invalid pointers; or passes along the last return\r
-@@ -346,18 +353,19 @@ int pwrdm_for_each_clkdm(struct powerdomain *pwrdm,\r
- int (*fn)(struct powerdomain *pwrdm,\r
- struct clockdomain *clkdm))\r
- {\r
-+ unsigned long flags;\r
- int ret = 0;\r
- int i;\r
- \r
- if (!fn)\r
- return -EINVAL;\r
- \r
-- down_read(&pwrdm_rwsem);\r
-+ read_lock_irqsave(&pwrdm_rwlock, flags);\r
- \r
- for (i = 0; i < PWRDM_MAX_CLKDMS && !ret; i++)\r
- ret = (*fn)(pwrdm, pwrdm->pwrdm_clkdms[i]);\r
- \r
-- up_read(&pwrdm_rwsem);\r
-+ read_unlock_irqrestore(&pwrdm_rwlock, flags);\r
- \r
- return ret;\r
- }\r
---\r
-To unsubscribe from this list: send the line "unsubscribe linux-omap" in\r
-the body of a message to majordomo@vger.kernel.org\r
-More majordomo info at http://vger.kernel.org/majordomo-info.html\r
-\r