[S390] cio: allow enable_facility from outside init functions

Prepare chsc_enable_facility to be used from outside init functions.
Use static memory for the chsc call and protect its access by a
spinlock (although there is no concurrent usage).

Cc: <stable@kernel.org>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Sebastian Ott 2010-04-22 17:17:03 +02:00 коммит произвёл Martin Schwidefsky
Родитель 6a5176c474
Коммит 818c272bd7
2 изменённых файлов: 17 добавлений и 23 удалений

Просмотреть файл

@ -29,6 +29,7 @@
#include "chsc.h" #include "chsc.h"
static void *sei_page; static void *sei_page;
static DEFINE_SPINLOCK(sda_lock);
/** /**
* chsc_error_from_response() - convert a chsc response to an error * 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); kfree(sei_page);
} }
int __init int chsc_enable_facility(int operation_code)
chsc_enable_facility(int operation_code)
{ {
int ret; int ret;
struct { static struct {
struct chsc_header request; struct chsc_header request;
u8 reserved1:4; u8 reserved1:4;
u8 format:4; u8 format:4;
@ -849,33 +849,32 @@ chsc_enable_facility(int operation_code)
u32 reserved5:4; u32 reserved5:4;
u32 format2:4; u32 format2:4;
u32 reserved6:24; u32 reserved6:24;
} __attribute__ ((packed)) *sda_area; } __attribute__ ((packed, aligned(4096))) sda_area;
sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); spin_lock(&sda_lock);
if (!sda_area) memset(&sda_area, 0, sizeof(sda_area));
return -ENOMEM; sda_area.request.length = 0x0400;
sda_area->request.length = 0x0400; sda_area.request.code = 0x0031;
sda_area->request.code = 0x0031; sda_area.operation_code = operation_code;
sda_area->operation_code = operation_code;
ret = chsc(sda_area); ret = chsc(&sda_area);
if (ret > 0) { if (ret > 0) {
ret = (ret == 3) ? -ENODEV : -EBUSY; ret = (ret == 3) ? -ENODEV : -EBUSY;
goto out; goto out;
} }
switch (sda_area->response.code) { switch (sda_area.response.code) {
case 0x0101: case 0x0101:
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
break; break;
default: default:
ret = chsc_error_from_response(sda_area->response.code); ret = chsc_error_from_response(sda_area.response.code);
} }
if (ret != 0) if (ret != 0)
CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n", 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: out:
free_page((unsigned long)sda_area); spin_unlock(&sda_lock);
return ret; return ret;
} }

Просмотреть файл

@ -870,15 +870,10 @@ static int __init css_bus_init(void)
/* Try to enable MSS. */ /* Try to enable MSS. */
ret = chsc_enable_facility(CHSC_SDA_OC_MSS); ret = chsc_enable_facility(CHSC_SDA_OC_MSS);
switch (ret) { if (ret)
case 0: /* Success. */
max_ssid = __MAX_SSID;
break;
case -ENOMEM:
goto out;
default:
max_ssid = 0; max_ssid = 0;
} else /* Success. */
max_ssid = __MAX_SSID;
ret = slow_subchannel_init(); ret = slow_subchannel_init();
if (ret) if (ret)