aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x')
-rw-r--r--hw/s390x/css.c84
-rw-r--r--hw/s390x/s390-ccw.c11
2 files changed, 29 insertions, 66 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 4f964b7691..c87c1aecc0 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -1181,12 +1181,11 @@ static void sch_handle_start_func_virtual(SubchDev *sch)
}
-static int sch_handle_start_func_passthrough(SubchDev *sch)
+static IOInstEnding sch_handle_start_func_passthrough(SubchDev *sch)
{
PMCW *p = &sch->curr_status.pmcw;
SCSW *s = &sch->curr_status.scsw;
- int ret;
ORB *orb = &sch->orb;
if (!(s->ctrl & SCSW_ACTL_SUSP)) {
@@ -1200,31 +1199,12 @@ static int sch_handle_start_func_passthrough(SubchDev *sch)
*/
if (!(orb->ctrl0 & ORB_CTRL0_MASK_PFCH) ||
!(orb->ctrl0 & ORB_CTRL0_MASK_C64)) {
- return -EINVAL;
+ warn_report("vfio-ccw requires PFCH and C64 flags set");
+ sch_gen_unit_exception(sch);
+ css_inject_io_interrupt(sch);
+ return IOINST_CC_EXPECTED;
}
-
- ret = s390_ccw_cmd_request(orb, s, sch->driver_data);
- switch (ret) {
- /* Currently we don't update control block and just return the cc code. */
- case 0:
- break;
- case -EBUSY:
- break;
- case -ENODEV:
- break;
- case -EACCES:
- /* Let's reflect an inaccessible host device by cc 3. */
- ret = -ENODEV;
- break;
- default:
- /*
- * All other return codes will trigger a program check,
- * or set cc to 1.
- */
- break;
- };
-
- return ret;
+ return s390_ccw_cmd_request(sch);
}
/*
@@ -1233,7 +1213,7 @@ static int sch_handle_start_func_passthrough(SubchDev *sch)
* read/writes) asynchronous later on if we start supporting more than
* our current very simple devices.
*/
-int do_subchannel_work_virtual(SubchDev *sch)
+IOInstEnding do_subchannel_work_virtual(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
@@ -1247,12 +1227,12 @@ int do_subchannel_work_virtual(SubchDev *sch)
sch_handle_start_func_virtual(sch);
}
css_inject_io_interrupt(sch);
- return 0;
+ /* inst must succeed if this func is called */
+ return IOINST_CC_EXPECTED;
}
-int do_subchannel_work_passthrough(SubchDev *sch)
+IOInstEnding do_subchannel_work_passthrough(SubchDev *sch)
{
- int ret = 0;
SCSW *s = &sch->curr_status.scsw;
if (s->ctrl & SCSW_FCTL_CLEAR_FUNC) {
@@ -1262,16 +1242,15 @@ int do_subchannel_work_passthrough(SubchDev *sch)
/* TODO: Halt handling */
sch_handle_halt_func(sch);
} else if (s->ctrl & SCSW_FCTL_START_FUNC) {
- ret = sch_handle_start_func_passthrough(sch);
+ return sch_handle_start_func_passthrough(sch);
}
-
- return ret;
+ return IOINST_CC_EXPECTED;
}
-static int do_subchannel_work(SubchDev *sch)
+static IOInstEnding do_subchannel_work(SubchDev *sch)
{
if (!sch->do_subchannel_work) {
- return -EINVAL;
+ return IOINST_CC_STATUS_PRESENT;
}
g_assert(sch->curr_status.scsw.ctrl & SCSW_CTRL_MASK_FCTL);
return sch->do_subchannel_work(sch);
@@ -1561,27 +1540,23 @@ static void css_update_chnmon(SubchDev *sch)
}
}
-int css_do_ssch(SubchDev *sch, ORB *orb)
+IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (s->ctrl & (SCSW_FCTL_START_FUNC |
SCSW_FCTL_HALT_FUNC |
SCSW_FCTL_CLEAR_FUNC)) {
- ret = -EBUSY;
- goto out;
+ return IOINST_CC_BUSY;
}
/* If monitoring is active, update counter. */
@@ -1594,10 +1569,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
s->ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND);
s->flags &= ~SCSW_FLAGS_MASK_PNO;
- ret = do_subchannel_work(sch);
-
-out:
- return ret;
+ return do_subchannel_work(sch);
}
static void copy_irb_to_guest(IRB *dest, const IRB *src, PMCW *pmcw,
@@ -1844,27 +1816,23 @@ void css_do_schm(uint8_t mbk, int update, int dct, uint64_t mbo)
}
}
-int css_do_rsch(SubchDev *sch)
+IOInstEnding css_do_rsch(SubchDev *sch)
{
SCSW *s = &sch->curr_status.scsw;
PMCW *p = &sch->curr_status.pmcw;
- int ret;
if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
- ret = -ENODEV;
- goto out;
+ return IOINST_CC_NOT_OPERATIONAL;
}
if (s->ctrl & SCSW_STCTL_STATUS_PEND) {
- ret = -EINPROGRESS;
- goto out;
+ return IOINST_CC_STATUS_PRESENT;
}
if (((s->ctrl & SCSW_CTRL_MASK_FCTL) != SCSW_FCTL_START_FUNC) ||
(s->ctrl & SCSW_ACTL_RESUME_PEND) ||
(!(s->ctrl & SCSW_ACTL_SUSP))) {
- ret = -EINVAL;
- goto out;
+ return IOINST_CC_BUSY;
}
/* If monitoring is active, update counter. */
@@ -1873,11 +1841,7 @@ int css_do_rsch(SubchDev *sch)
}
s->ctrl |= SCSW_ACTL_RESUME_PEND;
- do_subchannel_work(sch);
- ret = 0;
-
-out:
- return ret;
+ return do_subchannel_work(sch);
}
int css_do_rchp(uint8_t cssid, uint8_t chpid)
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 8614dda6f8..0ef232ec27 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -18,15 +18,14 @@
#include "hw/s390x/css-bridge.h"
#include "hw/s390x/s390-ccw.h"
-int s390_ccw_cmd_request(ORB *orb, SCSW *scsw, void *data)
+IOInstEnding s390_ccw_cmd_request(SubchDev *sch)
{
- S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(data);
+ S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(sch->driver_data);
- if (cdc->handle_request) {
- return cdc->handle_request(orb, scsw, data);
- } else {
- return -ENOSYS;
+ if (!cdc->handle_request) {
+ return IOINST_CC_STATUS_PRESENT;
}
+ return cdc->handle_request(sch);
}
static void s390_ccw_get_dev_info(S390CCWDevice *cdev,