checking return values for CSCH and HSCH for various configurations. Signed-off-by: Pierre Morel <pmorel@xxxxxxxxxxxxx> --- s390x/css.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 171 insertions(+), 1 deletion(-) diff --git a/s390x/css.c b/s390x/css.c index 1c891f8..ee02cdd 100644 --- a/s390x/css.c +++ b/s390x/css.c @@ -51,6 +51,175 @@ static void test_enable(void) report(cc == 0, "Enable subchannel %08x", test_device_sid); } +static void dummy_irq(void) +{ +} + +static int check_io_completion(int sid, uint32_t expected) +{ + struct irb irb; + int ret; + + report_prefix_push("IRQ flags"); + + ret = tsch(sid, &irb); + if (ret) + goto end; + + if (!expected) + goto end; + + if (!(expected & irb.scsw.ctrl)) { + report_info("expect: %s got: %s", + dump_scsw_flags(expected), + dump_scsw_flags(irb.scsw.ctrl)); + ret = -1; + } + +end: + report(!ret, "expectations"); + report_prefix_pop(); + return ret; +} + +static void test_csch(void) +{ + struct orb orb = { + .intparm = test_device_sid, + .ctrl = ORB_CTRL_ISIC | ORB_CTRL_FMT | ORB_LPM_DFLT, + }; + struct ccw1 *ccw; + + senseid = alloc_io_mem(sizeof(*senseid), 0); + assert(senseid); + ccw = ccw_alloc(CCW_CMD_SENSE_ID, senseid, sizeof(*senseid), CCW_F_SLI); + assert(ccw); + orb.cpa = (uint64_t)ccw; + + /* 1- Basic check for CSCH */ + report_prefix_push("CSCH on a quiet subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + report(csch(test_device_sid) == 0, "subchannel clear"); + + /* now we check the flags */ + report_prefix_push("IRQ flags"); + report(wait_and_check_io_completion(test_device_sid, SCSW_FC_CLEAR) == 0, "expected"); + report_prefix_pop(); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* For the following checks we need to execute tsch synchronously */ + assert(unregister_io_int_func(css_irq_io) == 0); + assert(register_io_int_func(dummy_irq) == 0); + + /* 2- We want to check if the IRQ flags of SSCH are erased by clear */ + report_prefix_push("CSCH on SSCH status pending subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + assert(ssch(test_device_sid, &orb) == 0); + report(csch(test_device_sid) == 0, "subchannel cleared"); + check_io_completion(test_device_sid, SCSW_FC_CLEAR); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* 3- Checking CSCH after HSCH */ + report_prefix_push("CSCH on a halted subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + assert(hsch(test_device_sid) == 0); + report(csch(test_device_sid) == 0, "subchannel cleared"); + check_io_completion(test_device_sid, SCSW_FC_CLEAR); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* 4- Checking CSCH after CSCH */ + report_prefix_push("CSCH on a cleared subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + assert(csch(test_device_sid) == 0); + report(csch(test_device_sid) == 0, "subchannel cleared"); + check_io_completion(test_device_sid, SCSW_FC_CLEAR); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* Reset the IRQ handler */ + assert(unregister_io_int_func(dummy_irq) == 0); + assert(register_io_int_func(css_irq_io) == 0); + + free_io_mem(senseid, sizeof(*senseid)); + free_io_mem(ccw, sizeof(*ccw)); +} + +static void test_hsch(void) +{ + struct orb orb = { + .intparm = test_device_sid, + .ctrl = ORB_CTRL_ISIC | ORB_CTRL_FMT | ORB_LPM_DFLT, + }; + struct ccw1 *ccw; + + senseid = alloc_io_mem(sizeof(*senseid), 0); + assert(senseid); + ccw = ccw_alloc(CCW_CMD_SENSE_ID, senseid, sizeof(*senseid), CCW_F_SLI); + assert(ccw); + orb.cpa = (uint64_t)ccw; + + /* 1- Basic HSCH */ + report_prefix_push("HSCH on a quiet subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + report(hsch(test_device_sid) == 0, "subchannel halted"); + + /* now we check the flags */ + report_prefix_push("IRQ flags"); + report(wait_and_check_io_completion(test_device_sid, SCSW_FC_HALT) == 0, "expected"); + report_prefix_pop(); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* For the following checks we need to execute tsch synchronously */ + assert(unregister_io_int_func(css_irq_io) == 0); + assert(register_io_int_func(dummy_irq) == 0); + + /* 2- Check HSCH after SSCH */ + report_prefix_push("HSCH on status pending subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + assert(ssch(test_device_sid, &orb) == 0); + report(hsch(test_device_sid) == 1, "Halt subchannel should fail with CC 1"); + check_io_completion(test_device_sid, SCSW_FC_START); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* 3- Check HSCH after CSCH */ + report_prefix_push("HSCH on busy on CSCH subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + assert(csch(test_device_sid) == 0); + report(hsch(test_device_sid) == 1, "Halt subchannel should fail with CC 1"); + check_io_completion(test_device_sid, SCSW_FC_CLEAR); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* 4- Check HSCH after HSCH */ + report_prefix_push("HSCH on busy on HSCH subchannel"); + assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); + assert(hsch(test_device_sid) == 0); + report(hsch(test_device_sid) == 1, "Halt subchannel should fail with CC 1"); + check_io_completion(test_device_sid, SCSW_FC_HALT); + + assert(css_disable(test_device_sid) == 0); + report_prefix_pop(); + + /* Reset the IRQ handler */ + assert(unregister_io_int_func(dummy_irq) == 0); + assert(register_io_int_func(css_irq_io) == 0); + + free_io_mem(senseid, sizeof(*senseid)); + free_io_mem(ccw, sizeof(*ccw)); +} + static void test_ssch(void) { struct orb orb = { @@ -61,7 +230,6 @@ static void test_ssch(void) phys_addr_t base, top; assert(css_enable(test_device_sid, IO_SCH_ISC) == 0); - assert(register_io_int_func(css_irq_io) == 0); /* ORB address should be aligned on 32 bits */ report_prefix_push("ORB alignment"); @@ -441,6 +609,8 @@ static struct { { "enumerate (stsch)", test_enumerate }, { "enable (msch)", test_enable }, { "start subchannel", test_ssch }, + { "halt subchannel", test_hsch }, + { "clear subchannel", test_csch }, { "sense (ssch/tsch)", test_sense }, { "measurement block (schm)", test_schm }, { "measurement block format0", test_schm_fmt0 }, -- 2.17.1