diff options
Diffstat (limited to 'drivers/s390/char/sclp_cmd.c')
| -rw-r--r-- | drivers/s390/char/sclp_cmd.c | 202 | 
1 files changed, 27 insertions, 175 deletions
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 8cd34bf644b..6e14999f9e8 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -28,166 +28,6 @@  #include "sclp.h" -#define SCLP_CMDW_READ_SCP_INFO		0x00020001 -#define SCLP_CMDW_READ_SCP_INFO_FORCED	0x00120001 - -struct read_info_sccb { -	struct	sccb_header header;	/* 0-7 */ -	u16	rnmax;			/* 8-9 */ -	u8	rnsize;			/* 10 */ -	u8	_reserved0[24 - 11];	/* 11-15 */ -	u8	loadparm[8];		/* 24-31 */ -	u8	_reserved1[48 - 32];	/* 32-47 */ -	u64	facilities;		/* 48-55 */ -	u8	_reserved2[84 - 56];	/* 56-83 */ -	u8	fac84;			/* 84 */ -	u8	fac85;			/* 85 */ -	u8	_reserved3[91 - 86];	/* 86-90 */ -	u8	flags;			/* 91 */ -	u8	_reserved4[100 - 92];	/* 92-99 */ -	u32	rnsize2;		/* 100-103 */ -	u64	rnmax2;			/* 104-111 */ -	u8	_reserved5[4096 - 112];	/* 112-4095 */ -} __attribute__((packed, aligned(PAGE_SIZE))); - -static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE); -static struct read_info_sccb __initdata early_read_info_sccb; -static int __initdata early_read_info_sccb_valid; - -u64 sclp_facilities; -static u8 sclp_fac84; -static unsigned long long rzm; -static unsigned long long rnmax; - -static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) -{ -	int rc; - -	__ctl_set_bit(0, 9); -	rc = sclp_service_call(cmd, sccb); -	if (rc) -		goto out; -	__load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | -			PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); -	local_irq_disable(); -out: -	/* Contents of the sccb might have changed. */ -	barrier(); -	__ctl_clear_bit(0, 9); -	return rc; -} - -static void __init sclp_read_info_early(void) -{ -	int rc; -	int i; -	struct read_info_sccb *sccb; -	sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, -				  SCLP_CMDW_READ_SCP_INFO}; - -	sccb = &early_read_info_sccb; -	for (i = 0; i < ARRAY_SIZE(commands); i++) { -		do { -			memset(sccb, 0, sizeof(*sccb)); -			sccb->header.length = sizeof(*sccb); -			sccb->header.function_code = 0x80; -			sccb->header.control_mask[2] = 0x80; -			rc = sclp_cmd_sync_early(commands[i], sccb); -		} while (rc == -EBUSY); - -		if (rc) -			break; -		if (sccb->header.response_code == 0x10) { -			early_read_info_sccb_valid = 1; -			break; -		} -		if (sccb->header.response_code != 0x1f0) -			break; -	} -} - -static void __init sclp_event_mask_early(void) -{ -	struct init_sccb *sccb = &early_event_mask_sccb; -	int rc; - -	do { -		memset(sccb, 0, sizeof(*sccb)); -		sccb->header.length = sizeof(*sccb); -		sccb->mask_length = sizeof(sccb_mask_t); -		rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); -	} while (rc == -EBUSY); -} - -void __init sclp_facilities_detect(void) -{ -	struct read_info_sccb *sccb; - -	sclp_read_info_early(); -	if (!early_read_info_sccb_valid) -		return; - -	sccb = &early_read_info_sccb; -	sclp_facilities = sccb->facilities; -	sclp_fac84 = sccb->fac84; -	if (sccb->fac85 & 0x02) -		S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; -	rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; -	rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; -	rzm <<= 20; - -	sclp_event_mask_early(); -} - -bool __init sclp_has_linemode(void) -{ -	struct init_sccb *sccb = &early_event_mask_sccb; - -	if (sccb->header.response_code != 0x20) -		return 0; -	if (sccb->sclp_send_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK)) -		return 1; -	return 0; -} - -bool __init sclp_has_vt220(void) -{ -	struct init_sccb *sccb = &early_event_mask_sccb; - -	if (sccb->header.response_code != 0x20) -		return 0; -	if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) -		return 1; -	return 0; -} - -unsigned long long sclp_get_rnmax(void) -{ -	return rnmax; -} - -unsigned long long sclp_get_rzm(void) -{ -	return rzm; -} - -/* - * This function will be called after sclp_facilities_detect(), which gets - * called from early.c code. Therefore the sccb should have valid contents. - */ -void __init sclp_get_ipl_info(struct sclp_ipl_info *info) -{ -	struct read_info_sccb *sccb; - -	if (!early_read_info_sccb_valid) -		return; -	sccb = &early_read_info_sccb; -	info->is_valid = 1; -	if (sccb->flags & 0x2) -		info->has_dump = 1; -	memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); -} -  static void sclp_sync_callback(struct sclp_req *req, void *data)  {  	struct completion *completion = data; @@ -197,6 +37,11 @@ static void sclp_sync_callback(struct sclp_req *req, void *data)  int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)  { +	return sclp_sync_request_timeout(cmd, sccb, 0); +} + +int sclp_sync_request_timeout(sclp_cmdw_t cmd, void *sccb, int timeout) +{  	struct completion completion;  	struct sclp_req *request;  	int rc; @@ -204,6 +49,8 @@ int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)  	request = kzalloc(sizeof(*request), GFP_KERNEL);  	if (!request)  		return -ENOMEM; +	if (timeout) +		request->queue_timeout = timeout;  	request->command = cmd;  	request->sccb = sccb;  	request->status = SCLP_REQ_FILLED; @@ -270,7 +117,8 @@ int sclp_get_cpu_info(struct sclp_cpu_info *info)  	if (!sccb)  		return -ENOMEM;  	sccb->header.length = sizeof(*sccb); -	rc = sclp_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb); +	rc = sclp_sync_request_timeout(SCLP_CMDW_READ_CPU_INFO, sccb, +				       SCLP_QUEUE_INTERVAL);  	if (rc)  		goto out;  	if (sccb->header.response_code != 0x0010) { @@ -304,7 +152,7 @@ static int do_cpu_configure(sclp_cmdw_t cmd)  	if (!sccb)  		return -ENOMEM;  	sccb->header.length = sizeof(*sccb); -	rc = sclp_sync_request(cmd, sccb); +	rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);  	if (rc)  		goto out;  	switch (sccb->header.response_code) { @@ -354,14 +202,14 @@ struct assign_storage_sccb {  int arch_get_memory_phys_device(unsigned long start_pfn)  { -	if (!rzm) +	if (!sclp_rzm)  		return 0; -	return PFN_PHYS(start_pfn) >> ilog2(rzm); +	return PFN_PHYS(start_pfn) >> ilog2(sclp_rzm);  }  static unsigned long long rn2addr(u16 rn)  { -	return (unsigned long long) (rn - 1) * rzm; +	return (unsigned long long) (rn - 1) * sclp_rzm;  }  static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) @@ -374,7 +222,7 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)  		return -ENOMEM;  	sccb->header.length = PAGE_SIZE;  	sccb->rn = rn; -	rc = sclp_sync_request(cmd, sccb); +	rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);  	if (rc)  		goto out;  	switch (sccb->header.response_code) { @@ -402,7 +250,7 @@ static int sclp_assign_storage(u16 rn)  	if (rc)  		return rc;  	start = rn2addr(rn); -	storage_key_init_range(start, start + rzm); +	storage_key_init_range(start, start + sclp_rzm);  	return 0;  } @@ -429,7 +277,8 @@ static int sclp_attach_storage(u8 id)  	if (!sccb)  		return -ENOMEM;  	sccb->header.length = PAGE_SIZE; -	rc = sclp_sync_request(0x00080001 | id << 8, sccb); +	rc = sclp_sync_request_timeout(0x00080001 | id << 8, sccb, +				       SCLP_QUEUE_INTERVAL);  	if (rc)  		goto out;  	switch (sccb->header.response_code) { @@ -460,7 +309,7 @@ static int sclp_mem_change_state(unsigned long start, unsigned long size,  		istart = rn2addr(incr->rn);  		if (start + size - 1 < istart)  			break; -		if (start > istart + rzm - 1) +		if (start > istart + sclp_rzm - 1)  			continue;  		if (online)  			rc |= sclp_assign_storage(incr->rn); @@ -524,7 +373,7 @@ static void __init add_memory_merged(u16 rn)  	if (!first_rn)  		goto skip_add;  	start = rn2addr(first_rn); -	size = (unsigned long long ) num * rzm; +	size = (unsigned long long) num * sclp_rzm;  	if (start >= VMEM_MAX_PHYS)  		goto skip_add;  	if (start + size > VMEM_MAX_PHYS) @@ -572,7 +421,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned)  	}  	if (!assigned)  		new_incr->rn = last_rn + 1; -	if (new_incr->rn > rnmax) { +	if (new_incr->rn > sclp_rnmax) {  		kfree(new_incr);  		return;  	} @@ -615,8 +464,6 @@ static int __init sclp_detect_standby_memory(void)  	if (OLDMEM_BASE) /* No standby memory in kdump mode */  		return 0; -	if (!early_read_info_sccb_valid) -		return 0;  	if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL)  		return 0;  	rc = -ENOMEM; @@ -659,7 +506,7 @@ static int __init sclp_detect_standby_memory(void)  	}  	if (rc || list_empty(&sclp_mem_list))  		goto out; -	for (i = 1; i <= rnmax - assigned; i++) +	for (i = 1; i <= sclp_rnmax - assigned; i++)  		insert_increment(0, 1, 0);  	rc = register_memory_notifier(&sclp_mem_nb);  	if (rc) @@ -668,7 +515,7 @@ static int __init sclp_detect_standby_memory(void)  	if (rc)  		goto out;  	sclp_pdev = platform_device_register_simple("sclp_mem", -1, NULL, 0); -	rc = PTR_RET(sclp_pdev); +	rc = PTR_ERR_OR_ZERO(sclp_pdev);  	if (rc)  		goto out_driver;  	sclp_add_standby_memory(); @@ -862,3 +709,8 @@ out:  	free_page((unsigned long) sccb);  	return rc;  } + +bool sclp_has_sprp(void) +{ +	return !!(sclp_fac84 & 0x2); +}  | 
