Commit fddbaa5c authored by Vasily Gorbik's avatar Vasily Gorbik Committed by Martin Schwidefsky

s390/mem_detect: introduce SCLP storage info

SCLP storage info allows to detect continuous and non-continuous online
memory under LPAR, z/VM and KVM, when standby memory is defined.
Reviewed-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 251b72a4
...@@ -126,6 +126,12 @@ void detect_memory(void) ...@@ -126,6 +126,12 @@ void detect_memory(void)
unsigned long rzm; unsigned long rzm;
sclp_early_get_meminfo(&max_physmem_end, &rzm); sclp_early_get_meminfo(&max_physmem_end, &rzm);
if (!sclp_early_read_storage_info()) {
mem_detect.info_source = MEM_DETECT_SCLP_STOR_INFO;
return;
}
scan_memory(rzm); scan_memory(rzm);
mem_detect.info_source = MEM_DETECT_TPROT_LOOP; mem_detect.info_source = MEM_DETECT_TPROT_LOOP;
if (!max_physmem_end) if (!max_physmem_end)
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
enum mem_info_source { enum mem_info_source {
MEM_DETECT_NONE = 0, MEM_DETECT_NONE = 0,
MEM_DETECT_SCLP_STOR_INFO,
MEM_DETECT_TPROT_LOOP MEM_DETECT_TPROT_LOOP
}; };
...@@ -32,6 +33,8 @@ struct mem_detect_info { ...@@ -32,6 +33,8 @@ struct mem_detect_info {
}; };
extern struct mem_detect_info mem_detect; extern struct mem_detect_info mem_detect;
void add_mem_detect_block(u64 start, u64 end);
static inline int __get_mem_detect_block(u32 n, unsigned long *start, static inline int __get_mem_detect_block(u32 n, unsigned long *start,
unsigned long *end) unsigned long *end)
{ {
......
...@@ -106,6 +106,7 @@ struct zpci_report_error_header { ...@@ -106,6 +106,7 @@ struct zpci_report_error_header {
} __packed; } __packed;
int sclp_early_read_info(void); int sclp_early_read_info(void);
int sclp_early_read_storage_info(void);
int sclp_early_get_core_info(struct sclp_core_info *info); int sclp_early_get_core_info(struct sclp_core_info *info);
void sclp_early_get_ipl_info(struct sclp_ipl_info *info); void sclp_early_get_ipl_info(struct sclp_ipl_info *info);
void sclp_early_detect(void); void sclp_early_detect(void);
......
...@@ -64,6 +64,7 @@ typedef unsigned int sclp_cmdw_t; ...@@ -64,6 +64,7 @@ typedef unsigned int sclp_cmdw_t;
#define SCLP_CMDW_READ_CPU_INFO 0x00010001 #define SCLP_CMDW_READ_CPU_INFO 0x00010001
#define SCLP_CMDW_READ_SCP_INFO 0x00020001 #define SCLP_CMDW_READ_SCP_INFO 0x00020001
#define SCLP_CMDW_READ_STORAGE_INFO 0x00040001
#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
#define SCLP_CMDW_READ_EVENT_DATA 0x00770005 #define SCLP_CMDW_READ_EVENT_DATA 0x00770005
#define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005 #define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
...@@ -197,6 +198,15 @@ struct read_info_sccb { ...@@ -197,6 +198,15 @@ struct read_info_sccb {
u8 _pad_128[4096 - 128]; /* 128-4095 */ u8 _pad_128[4096 - 128]; /* 128-4095 */
} __packed __aligned(PAGE_SIZE); } __packed __aligned(PAGE_SIZE);
struct read_storage_sccb {
struct sccb_header header;
u16 max_id;
u16 assigned;
u16 standby;
u16 :16;
u32 entries[0];
} __packed;
static inline void sclp_fill_core_info(struct sclp_core_info *info, static inline void sclp_fill_core_info(struct sclp_core_info *info,
struct read_cpu_info_sccb *sccb) struct read_cpu_info_sccb *sccb)
{ {
......
...@@ -460,15 +460,6 @@ static int sclp_mem_freeze(struct device *dev) ...@@ -460,15 +460,6 @@ static int sclp_mem_freeze(struct device *dev)
return -EPERM; return -EPERM;
} }
struct read_storage_sccb {
struct sccb_header header;
u16 max_id;
u16 assigned;
u16 standby;
u16 :16;
u32 entries[0];
} __packed;
static const struct dev_pm_ops sclp_mem_pm_ops = { static const struct dev_pm_ops sclp_mem_pm_ops = {
.freeze = sclp_mem_freeze, .freeze = sclp_mem_freeze,
}; };
...@@ -498,7 +489,7 @@ static int __init sclp_detect_standby_memory(void) ...@@ -498,7 +489,7 @@ static int __init sclp_detect_standby_memory(void)
for (id = 0; id <= sclp_max_storage_id; id++) { for (id = 0; id <= sclp_max_storage_id; id++) {
memset(sccb, 0, PAGE_SIZE); memset(sccb, 0, PAGE_SIZE);
sccb->header.length = PAGE_SIZE; sccb->header.length = PAGE_SIZE;
rc = sclp_sync_request(0x00040001 | id << 8, sccb); rc = sclp_sync_request(SCLP_CMDW_READ_STORAGE_INFO | id << 8, sccb);
if (rc) if (rc)
goto out; goto out;
switch (sccb->header.response_code) { switch (sccb->header.response_code) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <asm/ebcdic.h> #include <asm/ebcdic.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/sections.h> #include <asm/sections.h>
#include <asm/mem_detect.h>
#include "sclp.h" #include "sclp.h"
#include "sclp_rw.h" #include "sclp_rw.h"
...@@ -287,3 +288,55 @@ int __init sclp_early_get_meminfo(unsigned long *mem, unsigned long *rzm) ...@@ -287,3 +288,55 @@ int __init sclp_early_get_meminfo(unsigned long *mem, unsigned long *rzm)
*rzm = rnsize; *rzm = rnsize;
return 0; return 0;
} }
#define SCLP_STORAGE_INFO_FACILITY 0x0000400000000000UL
void __weak __init add_mem_detect_block(u64 start, u64 end) {}
int __init sclp_early_read_storage_info(void)
{
struct read_storage_sccb *sccb = (struct read_storage_sccb *)&sclp_early_sccb;
int rc, id, max_id = 0;
unsigned long rn, rzm;
sclp_cmdw_t command;
u16 sn;
if (!sclp_info_sccb_valid)
return -EIO;
if (!(sclp_info_sccb.facilities & SCLP_STORAGE_INFO_FACILITY))
return -EOPNOTSUPP;
rzm = sclp_info_sccb.rnsize ?: sclp_info_sccb.rnsize2;
rzm <<= 20;
for (id = 0; id <= max_id; id++) {
memset(sclp_early_sccb, 0, sizeof(sclp_early_sccb));
sccb->header.length = sizeof(sclp_early_sccb);
command = SCLP_CMDW_READ_STORAGE_INFO | (id << 8);
rc = sclp_early_cmd(command, sccb);
if (rc)
goto fail;
max_id = sccb->max_id;
switch (sccb->header.response_code) {
case 0x0010:
for (sn = 0; sn < sccb->assigned; sn++) {
if (!sccb->entries[sn])
continue;
rn = sccb->entries[sn] >> 16;
add_mem_detect_block((rn - 1) * rzm, rn * rzm);
}
break;
case 0x0310:
case 0x0410:
break;
default:
goto fail;
}
}
return 0;
fail:
mem_detect.count = 0;
return -EIO;
}
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