Commit 0d88b866 authored by David S. Miller's avatar David S. Miller

Merge branch 'sparc64-jump-to-boot-prom'

Vijay Kumar says:

====================
sparc64: Jump to boot prom from console on panic

V3 changes:
  - patch 02/04: Added SERIAL_SUNHV conditional group for
    sunhv_migrate_hvcons_irq in smp_send_stop().
V2 changes:
 -  Added cover letter patch

Currently Stop-A (L1A) does not make the kernel switch to OBP on panic. This
patchset addresses this issue. Also, now we can cause a jump to OBP by sending
'break' twice from sunhv console. On bare metal, one can send a break by
typing Esc + 'B' + Sysrq (or whatever). On LDOM, press Ctrl + ] in telnet,
and then "send break" at the telnet prompt.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f41e5461 4cfe1406
Steps for sending 'break' on sunhv console:
===========================================
On Baremetal:
1. press Esc + 'B'
On LDOM:
1. press Ctrl + ']'
2. telnet> send break
...@@ -59,8 +59,11 @@ extern atomic_t dcpage_flushes; ...@@ -59,8 +59,11 @@ extern atomic_t dcpage_flushes;
extern atomic_t dcpage_flushes_xcall; extern atomic_t dcpage_flushes_xcall;
extern int sysctl_tsb_ratio; extern int sysctl_tsb_ratio;
#endif
#ifdef CONFIG_SERIAL_SUNHV
void sunhv_migrate_hvcons_irq(int cpu);
#endif
#endif
void sun_do_break(void); void sun_do_break(void);
extern int stop_a_enabled; extern int stop_a_enabled;
extern int scons_pwroff; extern int scons_pwroff;
......
...@@ -1443,6 +1443,7 @@ void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) ...@@ -1443,6 +1443,7 @@ void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
static void stop_this_cpu(void *dummy) static void stop_this_cpu(void *dummy)
{ {
set_cpu_online(smp_processor_id(), false);
prom_stopself(); prom_stopself();
} }
...@@ -1451,9 +1452,15 @@ void smp_send_stop(void) ...@@ -1451,9 +1452,15 @@ void smp_send_stop(void)
int cpu; int cpu;
if (tlb_type == hypervisor) { if (tlb_type == hypervisor) {
int this_cpu = smp_processor_id();
#ifdef CONFIG_SERIAL_SUNHV
sunhv_migrate_hvcons_irq(this_cpu);
#endif
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
if (cpu == smp_processor_id()) if (cpu == this_cpu)
continue; continue;
set_cpu_online(cpu, false);
#ifdef CONFIG_SUN_LDOMS #ifdef CONFIG_SUN_LDOMS
if (ldom_domaining_enabled) { if (ldom_domaining_enabled) {
unsigned long hv_err; unsigned long hv_err;
......
...@@ -116,7 +116,7 @@ static int receive_chars_getchar(struct uart_port *port) ...@@ -116,7 +116,7 @@ static int receive_chars_getchar(struct uart_port *port)
static int receive_chars_read(struct uart_port *port) static int receive_chars_read(struct uart_port *port)
{ {
int saw_console_brk = 0; static int saw_console_brk;
int limit = 10000; int limit = 10000;
while (limit-- > 0) { while (limit-- > 0) {
...@@ -128,6 +128,9 @@ static int receive_chars_read(struct uart_port *port) ...@@ -128,6 +128,9 @@ static int receive_chars_read(struct uart_port *port)
bytes_read = 0; bytes_read = 0;
if (stat == CON_BREAK) { if (stat == CON_BREAK) {
if (saw_console_brk)
sun_do_break();
if (uart_handle_break(port)) if (uart_handle_break(port))
continue; continue;
saw_console_brk = 1; saw_console_brk = 1;
...@@ -151,6 +154,7 @@ static int receive_chars_read(struct uart_port *port) ...@@ -151,6 +154,7 @@ static int receive_chars_read(struct uart_port *port)
if (port->sysrq != 0 && *con_read_page) { if (port->sysrq != 0 && *con_read_page) {
for (i = 0; i < bytes_read; i++) for (i = 0; i < bytes_read; i++)
uart_handle_sysrq_char(port, con_read_page[i]); uart_handle_sysrq_char(port, con_read_page[i]);
saw_console_brk = 0;
} }
if (port->state == NULL) if (port->state == NULL)
...@@ -398,6 +402,12 @@ static struct uart_driver sunhv_reg = { ...@@ -398,6 +402,12 @@ static struct uart_driver sunhv_reg = {
static struct uart_port *sunhv_port; static struct uart_port *sunhv_port;
void sunhv_migrate_hvcons_irq(int cpu)
{
/* Migrate hvcons irq to param cpu */
irq_force_affinity(sunhv_port->irq, cpumask_of(cpu));
}
/* Copy 's' into the con_write_page, decoding "\n" into /* Copy 's' into the con_write_page, decoding "\n" into
* "\r\n" along the way. We have to return two lengths * "\r\n" along the way. We have to return two lengths
* because the caller needs to know how much to advance * because the caller needs to know how much to advance
......
...@@ -273,7 +273,8 @@ void panic(const char *fmt, ...) ...@@ -273,7 +273,8 @@ void panic(const char *fmt, ...)
extern int stop_a_enabled; extern int stop_a_enabled;
/* Make sure the user can actually press Stop-A (L1-A) */ /* Make sure the user can actually press Stop-A (L1-A) */
stop_a_enabled = 1; stop_a_enabled = 1;
pr_emerg("Press Stop-A (L1-A) to return to the boot prom\n"); pr_emerg("Press Stop-A (L1-A) from sun keyboard or send break\n"
"twice on console to return to the boot prom\n");
} }
#endif #endif
#if defined(CONFIG_S390) #if defined(CONFIG_S390)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment