diff options
Diffstat (limited to 'drivers/s390/cio/chsc.c')
| -rw-r--r-- | drivers/s390/cio/chsc.c | 29 | 
1 files changed, 14 insertions, 15 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 4038f5b4f14..ce7cb87479f 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -29,6 +29,7 @@  #include "chsc.h"  static void *sei_page; +static DEFINE_SPINLOCK(sda_lock);  /**   * chsc_error_from_response() - convert a chsc response to an error @@ -832,11 +833,10 @@ void __init chsc_free_sei_area(void)  	kfree(sei_page);  } -int __init -chsc_enable_facility(int operation_code) +int chsc_enable_facility(int operation_code)  {  	int ret; -	struct { +	static struct {  		struct chsc_header request;  		u8 reserved1:4;  		u8 format:4; @@ -849,33 +849,32 @@ chsc_enable_facility(int operation_code)  		u32 reserved5:4;  		u32 format2:4;  		u32 reserved6:24; -	} __attribute__ ((packed)) *sda_area; +	} __attribute__ ((packed, aligned(4096))) sda_area; -	sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); -	if (!sda_area) -		return -ENOMEM; -	sda_area->request.length = 0x0400; -	sda_area->request.code = 0x0031; -	sda_area->operation_code = operation_code; +	spin_lock(&sda_lock); +	memset(&sda_area, 0, sizeof(sda_area)); +	sda_area.request.length = 0x0400; +	sda_area.request.code = 0x0031; +	sda_area.operation_code = operation_code; -	ret = chsc(sda_area); +	ret = chsc(&sda_area);  	if (ret > 0) {  		ret = (ret == 3) ? -ENODEV : -EBUSY;  		goto out;  	} -	switch (sda_area->response.code) { +	switch (sda_area.response.code) {  	case 0x0101:  		ret = -EOPNOTSUPP;  		break;  	default: -		ret = chsc_error_from_response(sda_area->response.code); +		ret = chsc_error_from_response(sda_area.response.code);  	}  	if (ret != 0)  		CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n", -			      operation_code, sda_area->response.code); +			      operation_code, sda_area.response.code);   out: -	free_page((unsigned long)sda_area); +	spin_unlock(&sda_lock);  	return ret;  }  |