[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:
Родитель
6a5176c474
Коммит
818c272bd7
|
@ -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)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче