--- /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