s390/sysinfo,stsi: change return code handling
Change return code handling of the stsi() function:
In case function code 0 was specified the return value is the
current configuration level (already shifted). That way all
the code that actually copied the stsi_0() function can go
away.
Otherwise the return value is 0 (success) or negative to
indicate an error (currently only -EOPNOTSUPP).
Also stsi() is no longer an inline function. The function is
not performance critical, but every caller would generate an
exception table entry for this function.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h
index 04e6e97..f92428e 100644
--- a/arch/s390/include/asm/sysinfo.h
+++ b/arch/s390/include/asm/sysinfo.h
@@ -153,21 +153,7 @@
union topology_entry tle[0];
};
-static inline int stsi(void *sysinfo, int fc, int sel1, int sel2)
-{
- register int r0 asm("0") = (fc << 28) | sel1;
- register int r1 asm("1") = sel2;
-
- asm volatile(
- " stsi 0(%2)\n"
- "0: jz 2f\n"
- "1: lhi %0,%3\n"
- "2:\n"
- EX_TABLE(0b, 1b)
- : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS)
- : "cc", "memory");
- return r0;
-}
+int stsi(void *sysinfo, int fc, int sel1, int sel2);
/*
* Service level reporting interface.
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index e8000d5..7f47176 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -222,12 +222,12 @@
struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page;
/* Check current-configuration-level */
- if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) {
+ if (stsi(NULL, 0, 0, 0) <= 2) {
S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR;
return;
}
/* Get virtual-machine cpu information. */
- if (stsi(vmms, 3, 2, 2) == -ENOSYS || !vmms->count)
+ if (stsi(vmms, 3, 2, 2) || !vmms->count)
return;
/* Running under KVM? If not we assume z/VM */
@@ -246,7 +246,7 @@
return;
S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY;
for (max_mnest = 6; max_mnest > 1; max_mnest--) {
- if (stsi(&sysinfo_page, 15, 1, max_mnest) != -ENOSYS)
+ if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0)
break;
}
topology_max_mnest = max_mnest;
diff --git a/arch/s390/kernel/lgr.c b/arch/s390/kernel/lgr.c
index eca94e7..6ea6d69 100644
--- a/arch/s390/kernel/lgr.c
+++ b/arch/s390/kernel/lgr.c
@@ -51,16 +51,6 @@
static struct debug_info *lgr_dbf;
/*
- * Return number of valid stsi levels
- */
-static inline int stsi_0(void)
-{
- int rc = stsi(NULL, 0, 0, 0);
-
- return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
-}
-
-/*
* Copy buffer and then convert it to ASCII
*/
static void cpascii(char *dst, char *src, int size)
@@ -76,7 +66,7 @@
{
struct sysinfo_1_1_1 *si = (void *) lgr_page;
- if (stsi(si, 1, 1, 1) == -ENOSYS)
+ if (stsi(si, 1, 1, 1))
return;
cpascii(lgr_info->manufacturer, si->manufacturer,
sizeof(si->manufacturer));
@@ -93,7 +83,7 @@
{
struct sysinfo_2_2_2 *si = (void *) lgr_page;
- if (stsi(si, 2, 2, 2) == -ENOSYS)
+ if (stsi(si, 2, 2, 2))
return;
cpascii(lgr_info->name, si->name, sizeof(si->name));
memcpy(&lgr_info->lpar_number, &si->lpar_number,
@@ -108,7 +98,7 @@
struct sysinfo_3_2_2 *si = (void *) lgr_page;
int i;
- if (stsi(si, 3, 2, 2) == -ENOSYS)
+ if (stsi(si, 3, 2, 2))
return;
for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) {
cpascii(lgr_info->vm[i].name, si->vm[i].name,
@@ -124,16 +114,17 @@
*/
static void lgr_info_get(struct lgr_info *lgr_info)
{
+ int level;
+
memset(lgr_info, 0, sizeof(*lgr_info));
stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list));
- lgr_info->level = stsi_0();
- if (lgr_info->level == -ENOSYS)
- return;
- if (lgr_info->level >= 1)
+ level = stsi(NULL, 0, 0, 0);
+ lgr_info->level = level;
+ if (level >= 1)
lgr_stsi_1_1_1(lgr_info);
- if (lgr_info->level >= 2)
+ if (level >= 2)
lgr_stsi_2_2_2(lgr_info);
- if (lgr_info->level >= 3)
+ if (level >= 3)
lgr_stsi_3_2_2(lgr_info);
}
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c
index 2af4ee6..62f89d9 100644
--- a/arch/s390/kernel/sysinfo.c
+++ b/arch/s390/kernel/sysinfo.c
@@ -24,18 +24,38 @@
int topology_max_mnest;
-static inline int stsi_0(void)
+/*
+ * stsi - store system information
+ *
+ * Returns the current configuration level if function code 0 was specified.
+ * Otherwise returns 0 on success or a negative value on error.
+ */
+int stsi(void *sysinfo, int fc, int sel1, int sel2)
{
- int rc = stsi(NULL, 0, 0, 0);
+ register int r0 asm("0") = (fc << 28) | sel1;
+ register int r1 asm("1") = sel2;
+ int rc = 0;
- return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28);
+ asm volatile(
+ " stsi 0(%3)\n"
+ "0: jz 2f\n"
+ "1: lhi %1,%4\n"
+ "2:\n"
+ EX_TABLE(0b, 1b)
+ : "+d" (r0), "+d" (rc)
+ : "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP)
+ : "cc", "memory");
+ if (rc)
+ return rc;
+ return fc ? 0 : ((unsigned int) r0) >> 28;
}
+EXPORT_SYMBOL(stsi);
static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info)
{
int i;
- if (stsi(info, 1, 1, 1) == -ENOSYS)
+ if (stsi(info, 1, 1, 1))
return;
EBCASC(info->manufacturer, sizeof(info->manufacturer));
EBCASC(info->type, sizeof(info->type));
@@ -97,7 +117,8 @@
seq_putc(m, '\n');
if (!MACHINE_HAS_TOPOLOGY)
return;
- stsi(info, 15, 1, topology_max_mnest);
+ if (stsi(info, 15, 1, topology_max_mnest))
+ return;
seq_printf(m, "CPU Topology HW: ");
for (i = 0; i < TOPOLOGY_NR_MAG; i++)
seq_printf(m, " %d", info->mag[i]);
@@ -116,7 +137,7 @@
struct sysinfo_1_2_2_extension *ext;
int i;
- if (stsi(info, 1, 2, 2) == -ENOSYS)
+ if (stsi(info, 1, 2, 2))
return;
ext = (struct sysinfo_1_2_2_extension *)
((unsigned long) info + info->acc_offset);
@@ -152,7 +173,7 @@
static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info)
{
- if (stsi(info, 2, 2, 2) == -ENOSYS)
+ if (stsi(info, 2, 2, 2))
return;
EBCASC(info->name, sizeof(info->name));
seq_putc(m, '\n');
@@ -179,7 +200,7 @@
{
int i;
- if (stsi(info, 3, 2, 2) == -ENOSYS)
+ if (stsi(info, 3, 2, 2))
return;
for (i = 0; i < info->count; i++) {
EBCASC(info->vm[i].name, sizeof(info->vm[i].name));
@@ -202,7 +223,7 @@
if (!info)
return 0;
- level = stsi_0();
+ level = stsi(NULL, 0, 0, 0);
if (level >= 1)
stsi_1_1_1(m, info);
if (level >= 1)
@@ -365,7 +386,7 @@
if (!info)
return;
- if (stsi(info, 1, 2, 2) != -ENOSYS) {
+ if (stsi(info, 1, 2, 2) == 0) {
/*
* Major sigh. The cpu capability encoding is "special".
* If the first 9 bits of info->capability are 0 then it
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 60da903..310be61 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -211,7 +211,7 @@
spin_unlock(&fi->lock);
/* deal with other level 3 hypervisors */
- if (stsi(mem, 3, 2, 2) == -ENOSYS)
+ if (stsi(mem, 3, 2, 2))
mem->count = 0;
if (mem->count < 8)
mem->count++;
@@ -259,7 +259,7 @@
mem = get_zeroed_page(GFP_KERNEL);
if (!mem)
goto out_fail;
- if (stsi((void *) mem, fc, sel1, sel2) == -ENOSYS)
+ if (stsi((void *) mem, fc, sel1, sel2))
goto out_mem;
break;
case 3: