diff options
Diffstat (limited to 'drivers/s390/cio/chsc.c')
-rw-r--r-- | drivers/s390/cio/chsc.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 11674698b36d..7b0b295b2313 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -1131,6 +1131,52 @@ int chsc_enable_facility(int operation_code) return ret; } +int __init chsc_get_cssid(int idx) +{ + struct { + struct chsc_header request; + u8 atype; + u32 : 24; + u32 reserved1[6]; + struct chsc_header response; + u32 reserved2[3]; + struct { + u8 cssid; + u32 : 24; + } list[0]; + } __packed *sdcal_area; + int ret; + + spin_lock_irq(&chsc_page_lock); + memset(chsc_page, 0, PAGE_SIZE); + sdcal_area = chsc_page; + sdcal_area->request.length = 0x0020; + sdcal_area->request.code = 0x0034; + sdcal_area->atype = 4; + + ret = chsc(sdcal_area); + if (ret) { + ret = (ret == 3) ? -ENODEV : -EBUSY; + goto exit; + } + + ret = chsc_error_from_response(sdcal_area->response.code); + if (ret) { + CIO_CRW_EVENT(2, "chsc: sdcal failed (rc=%04x)\n", + sdcal_area->response.code); + goto exit; + } + + if ((addr_t) &sdcal_area->list[idx] < + (addr_t) &sdcal_area->response + sdcal_area->response.length) + ret = sdcal_area->list[idx].cssid; + else + ret = -ENODEV; +exit: + spin_unlock_irq(&chsc_page_lock); + return ret; +} + struct css_general_char css_general_characteristics; struct css_chsc_char css_chsc_characteristics; @@ -1216,7 +1262,7 @@ int chsc_sstpi(void *page, void *result, size_t size) struct chsc_header request; unsigned int rsvd0[3]; struct chsc_header response; - char data[size]; + char data[]; } __attribute__ ((packed)) *rr; int rc; |