Skip to content

Commit

Permalink
[S390] smp: rework sigp code
Browse files Browse the repository at this point in the history
Rename signal_processor* functions to sigp*.
Add raw variants of each version, so we can get rid of the hacks played
in smp code which establish temporary cpu logical mappings so they could
call the sigp functions.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Heiko Carstens authored and Martin Schwidefsky committed Feb 26, 2010
1 parent 2c2df11 commit a93b8ec
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 82 deletions.
100 changes: 49 additions & 51 deletions arch/s390/include/asm/sigp.h
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
/*
* include/asm-s390/sigp.h
* Routines and structures for signalling other processors.
*
* S390 version
* Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
* Martin Schwidefsky (schwidefsky@de.ibm.com)
* Heiko Carstens (heiko.carstens@de.ibm.com)
*
* sigp.h by D.J. Barrow (c) IBM 1999
* contains routines / structures for signalling other S/390 processors in an
* SMP configuration.
* Copyright IBM Corp. 1999,2010
* Author(s): Denis Joseph Barrow,
* Martin Schwidefsky <schwidefsky@de.ibm.com>,
* Heiko Carstens <heiko.carstens@de.ibm.com>,
*/

#ifndef __SIGP__
#define __SIGP__
#ifndef __ASM_SIGP_H
#define __ASM_SIGP_H

#include <asm/system.h>

/* get real cpu address from logical cpu number */
extern int __cpu_logical_map[];
/* Get real cpu address from logical cpu number. */
extern unsigned short __cpu_logical_map[];

static inline int cpu_logical_map(int cpu)
{
Expand All @@ -29,8 +24,7 @@ static inline int cpu_logical_map(int cpu)
#endif
}

typedef enum
{
enum {
sigp_unassigned=0x0,
sigp_sense,
sigp_external_call,
Expand All @@ -47,89 +41,93 @@ typedef enum
sigp_set_prefix,
sigp_store_status_at_address,
sigp_store_extended_status_at_address
} sigp_order_code;

typedef __u32 sigp_status_word;
};

typedef enum
{
enum {
sigp_order_code_accepted=0,
sigp_status_stored,
sigp_busy,
sigp_not_operational
} sigp_ccode;

};

/*
* Definitions for the external call
* Definitions for external call.
*/

/* 'Bit' signals, asynchronous */
typedef enum
{
ec_schedule=0,
enum {
ec_schedule = 0,
ec_call_function,
ec_call_function_single,
ec_bit_last
} ec_bit_sig;
};

/*
* Signal processor
* Signal processor.
*/
static inline sigp_ccode
signal_processor(__u16 cpu_addr, sigp_order_code order_code)
static inline int raw_sigp(u16 cpu, int order)
{
register unsigned long reg1 asm ("1") = 0;
sigp_ccode ccode;
int ccode;

asm volatile(
" sigp %1,%2,0(%3)\n"
" ipm %0\n"
" srl %0,28\n"
: "=d" (ccode)
: "d" (reg1), "d" (cpu_logical_map(cpu_addr)),
"a" (order_code) : "cc" , "memory");
: "d" (reg1), "d" (cpu),
"a" (order) : "cc" , "memory");
return ccode;
}

/*
* Signal processor with parameter
* Signal processor with parameter.
*/
static inline sigp_ccode
signal_processor_p(__u32 parameter, __u16 cpu_addr, sigp_order_code order_code)
static inline int raw_sigp_p(u32 parameter, u16 cpu, int order)
{
register unsigned int reg1 asm ("1") = parameter;
sigp_ccode ccode;
int ccode;

asm volatile(
" sigp %1,%2,0(%3)\n"
" ipm %0\n"
" srl %0,28\n"
: "=d" (ccode)
: "d" (reg1), "d" (cpu_logical_map(cpu_addr)),
"a" (order_code) : "cc" , "memory");
: "d" (reg1), "d" (cpu),
"a" (order) : "cc" , "memory");
return ccode;
}

/*
* Signal processor with parameter and return status
* Signal processor with parameter and return status.
*/
static inline sigp_ccode
signal_processor_ps(__u32 *statusptr, __u32 parameter, __u16 cpu_addr,
sigp_order_code order_code)
static inline int raw_sigp_ps(u32 *status, u32 parm, u16 cpu, int order)
{
register unsigned int reg1 asm ("1") = parameter;
sigp_ccode ccode;
register unsigned int reg1 asm ("1") = parm;
int ccode;

asm volatile(
" sigp %1,%2,0(%3)\n"
" ipm %0\n"
" srl %0,28\n"
: "=d" (ccode), "+d" (reg1)
: "d" (cpu_logical_map(cpu_addr)), "a" (order_code)
: "d" (cpu), "a" (order)
: "cc" , "memory");
*statusptr = reg1;
*status = reg1;
return ccode;
}

#endif /* __SIGP__ */
static inline int sigp(int cpu, int order)
{
return raw_sigp(cpu_logical_map(cpu), order);
}

static inline int sigp_p(u32 parameter, int cpu, int order)
{
return raw_sigp_p(parameter, cpu_logical_map(cpu), order);
}

static inline int sigp_ps(u32 *status, u32 parm, int cpu, int order)
{
return raw_sigp_ps(status, parm, cpu_logical_map(cpu), order);
}

#endif /* __ASM_SIGP_H */
2 changes: 1 addition & 1 deletion arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1610,7 +1610,7 @@ static void stop_run(struct shutdown_trigger *trigger)
{
if (strcmp(trigger->name, ON_PANIC_STR) == 0)
disabled_wait((unsigned long) __builtin_return_address(0));
while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
cpu_relax();
for (;;);
}
Expand Down
54 changes: 24 additions & 30 deletions arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
#include "entry.h"

/* logical cpu to cpu address */
int __cpu_logical_map[NR_CPUS];
unsigned short __cpu_logical_map[NR_CPUS];

static struct task_struct *current_set[NR_CPUS];

Expand All @@ -72,13 +72,13 @@ static int cpu_management;

static DEFINE_PER_CPU(struct cpu, cpu_devices);

static void smp_ext_bitcall(int, ec_bit_sig);
static void smp_ext_bitcall(int, int);

static int cpu_stopped(int cpu)
static int raw_cpu_stopped(int cpu)
{
__u32 status;
u32 status;

switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
switch (raw_sigp_ps(&status, 0, cpu, sigp_sense)) {
case sigp_status_stored:
/* Check for stopped and check stop state */
if (status & 0x50)
Expand All @@ -90,6 +90,11 @@ static int cpu_stopped(int cpu)
return 0;
}

static inline int cpu_stopped(int cpu)
{
return raw_cpu_stopped(cpu_logical_map(cpu));
}

void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
{
struct _lowcore *lc, *current_lc;
Expand All @@ -110,7 +115,7 @@ void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
if (!cpu_online(0))
smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
while (signal_processor(0, sigp_stop_and_store_status) == sigp_busy)
while (sigp(0, sigp_stop_and_store_status) == sigp_busy)
cpu_relax();
sp = lc->panic_stack;
sp -= sizeof(struct pt_regs);
Expand All @@ -136,7 +141,7 @@ void smp_send_stop(void)
if (cpu == smp_processor_id())
continue;
do {
rc = signal_processor(cpu, sigp_stop);
rc = sigp(cpu, sigp_stop);
} while (rc == sigp_busy);

while (!cpu_stopped(cpu))
Expand Down Expand Up @@ -172,13 +177,13 @@ static void do_ext_call_interrupt(__u16 code)
* Send an external call sigp to another cpu and return without waiting
* for its completion.
*/
static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
static void smp_ext_bitcall(int cpu, int sig)
{
/*
* Set signaling bit in lowcore of target cpu and kick it
*/
set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
while (sigp(cpu, sigp_emergency_signal) == sigp_busy)
udelay(10);
}

Expand Down Expand Up @@ -272,13 +277,6 @@ void smp_ctl_clear_bit(int cr, int bit)
}
EXPORT_SYMBOL(smp_ctl_clear_bit);

/*
* In early ipl state a temp. logically cpu number is needed, so the sigp
* functions can be used to sense other cpus. Since NR_CPUS is >= 2 on
* CONFIG_SMP and the ipl cpu is logical cpu 0, it must be 1.
*/
#define CPU_INIT_NO 1

#ifdef CONFIG_ZFCPDUMP

static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
Expand All @@ -291,9 +289,7 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
return;
}
zfcpdump_save_areas[cpu] = kmalloc(sizeof(struct save_area), GFP_KERNEL);
__cpu_logical_map[CPU_INIT_NO] = (__u16) phy_cpu;
while (signal_processor(CPU_INIT_NO, sigp_stop_and_store_status) ==
sigp_busy)
while (raw_sigp(phy_cpu, sigp_stop_and_store_status) == sigp_busy)
cpu_relax();
memcpy(zfcpdump_save_areas[cpu],
(void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
Expand Down Expand Up @@ -409,8 +405,7 @@ static void __init smp_detect_cpus(void)
for (cpu = 0; cpu <= MAX_CPU_ADDRESS; cpu++) {
if (cpu == boot_cpu_addr)
continue;
__cpu_logical_map[CPU_INIT_NO] = cpu;
if (!cpu_stopped(CPU_INIT_NO))
if (!raw_cpu_stopped(cpu))
continue;
smp_get_save_area(c_cpus, cpu);
c_cpus++;
Expand All @@ -433,8 +428,7 @@ static void __init smp_detect_cpus(void)
cpu_addr = info->cpu[cpu].address;
if (cpu_addr == boot_cpu_addr)
continue;
__cpu_logical_map[CPU_INIT_NO] = cpu_addr;
if (!cpu_stopped(CPU_INIT_NO)) {
if (!raw_cpu_stopped(cpu_addr)) {
s_cpus++;
continue;
}
Expand Down Expand Up @@ -553,26 +547,26 @@ static void smp_free_lowcore(int cpu)
/* Upping and downing of CPUs */
int __cpuinit __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
struct _lowcore *cpu_lowcore;
struct task_struct *idle;
struct stack_frame *sf;
sigp_ccode ccode;
u32 lowcore;
int ccode;

if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED)
return -EIO;
if (smp_alloc_lowcore(cpu))
return -ENOMEM;
do {
ccode = signal_processor(cpu, sigp_initial_cpu_reset);
ccode = sigp(cpu, sigp_initial_cpu_reset);
if (ccode == sigp_busy)
udelay(10);
if (ccode == sigp_not_operational)
goto err_out;
} while (ccode == sigp_busy);

lowcore = (u32)(unsigned long)lowcore_ptr[cpu];
while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
while (sigp_p(lowcore, cpu, sigp_set_prefix) == sigp_busy)
udelay(10);

idle = current_set[cpu];
Expand All @@ -598,7 +592,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func;
eieio();

while (signal_processor(cpu, sigp_restart) == sigp_busy)
while (sigp(cpu, sigp_restart) == sigp_busy)
udelay(10);

while (!cpu_online(cpu))
Expand Down Expand Up @@ -660,7 +654,7 @@ void __cpu_die(unsigned int cpu)
/* Wait until target cpu is down */
while (!cpu_stopped(cpu))
cpu_relax();
while (signal_processor_p(0, cpu, sigp_set_prefix) == sigp_busy)
while (sigp_p(0, cpu, sigp_set_prefix) == sigp_busy)
udelay(10);
smp_free_lowcore(cpu);
pr_info("Processor %d stopped\n", cpu);
Expand All @@ -669,7 +663,7 @@ void __cpu_die(unsigned int cpu)
void cpu_die(void)
{
idle_task_exit();
while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
while (sigp(smp_processor_id(), sigp_stop) == sigp_busy)
cpu_relax();
for (;;);
}
Expand Down

0 comments on commit a93b8ec

Please sign in to comment.