|
@@ -40,7 +40,7 @@
|
|
|
#include <asm/atomic.h>
|
|
|
|
|
|
struct rtas_t rtas = {
|
|
|
- .lock = SPIN_LOCK_UNLOCKED
|
|
|
+ .lock = __RAW_SPIN_LOCK_UNLOCKED
|
|
|
};
|
|
|
EXPORT_SYMBOL(rtas);
|
|
|
|
|
@@ -67,6 +67,28 @@ unsigned long rtas_rmo_buf;
|
|
|
void (*rtas_flash_term_hook)(int);
|
|
|
EXPORT_SYMBOL(rtas_flash_term_hook);
|
|
|
|
|
|
+/* RTAS use home made raw locking instead of spin_lock_irqsave
|
|
|
+ * because those can be called from within really nasty contexts
|
|
|
+ * such as having the timebase stopped which would lockup with
|
|
|
+ * normal locks and spinlock debugging enabled
|
|
|
+ */
|
|
|
+static unsigned long lock_rtas(void)
|
|
|
+{
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ local_irq_save(flags);
|
|
|
+ preempt_disable();
|
|
|
+ __raw_spin_lock_flags(&rtas.lock, flags);
|
|
|
+ return flags;
|
|
|
+}
|
|
|
+
|
|
|
+static void unlock_rtas(unsigned long flags)
|
|
|
+{
|
|
|
+ __raw_spin_unlock(&rtas.lock);
|
|
|
+ local_irq_restore(flags);
|
|
|
+ preempt_enable();
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* call_rtas_display_status and call_rtas_display_status_delay
|
|
|
* are designed only for very early low-level debugging, which
|
|
@@ -79,7 +101,7 @@ static void call_rtas_display_status(char c)
|
|
|
|
|
|
if (!rtas.base)
|
|
|
return;
|
|
|
- spin_lock_irqsave(&rtas.lock, s);
|
|
|
+ s = lock_rtas();
|
|
|
|
|
|
args->token = 10;
|
|
|
args->nargs = 1;
|
|
@@ -89,7 +111,7 @@ static void call_rtas_display_status(char c)
|
|
|
|
|
|
enter_rtas(__pa(args));
|
|
|
|
|
|
- spin_unlock_irqrestore(&rtas.lock, s);
|
|
|
+ unlock_rtas(s);
|
|
|
}
|
|
|
|
|
|
static void call_rtas_display_status_delay(char c)
|
|
@@ -411,8 +433,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
|
|
|
if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
|
|
|
return -1;
|
|
|
|
|
|
- /* Gotta do something different here, use global lock for now... */
|
|
|
- spin_lock_irqsave(&rtas.lock, s);
|
|
|
+ s = lock_rtas();
|
|
|
rtas_args = &rtas.args;
|
|
|
|
|
|
rtas_args->token = token;
|
|
@@ -439,8 +460,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
|
|
|
outputs[i] = rtas_args->rets[i+1];
|
|
|
ret = (nret > 0)? rtas_args->rets[0]: 0;
|
|
|
|
|
|
- /* Gotta do something different here, use global lock for now... */
|
|
|
- spin_unlock_irqrestore(&rtas.lock, s);
|
|
|
+ unlock_rtas(s);
|
|
|
|
|
|
if (buff_copy) {
|
|
|
log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0);
|
|
@@ -837,7 +857,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
|
|
|
|
|
|
buff_copy = get_errorlog_buffer();
|
|
|
|
|
|
- spin_lock_irqsave(&rtas.lock, flags);
|
|
|
+ flags = lock_rtas();
|
|
|
|
|
|
rtas.args = args;
|
|
|
enter_rtas(__pa(&rtas.args));
|
|
@@ -848,7 +868,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
|
|
|
if (args.rets[0] == -1)
|
|
|
errbuf = __fetch_rtas_last_error(buff_copy);
|
|
|
|
|
|
- spin_unlock_irqrestore(&rtas.lock, flags);
|
|
|
+ unlock_rtas(flags);
|
|
|
|
|
|
if (buff_copy) {
|
|
|
if (errbuf)
|