If a vfio-ccw device is left in an error state (example: pending unit check) then it is possible for that state to persist for a vfio-ccw device even after the enable subchannel that we do to bring the device online. If this state is allowed to persist then even simple I/O operations will needlessly fail. A basic sense ccw is used to clear this error state for the boot device.
Signed-off-by: Jason J. Herne <jjhe...@linux.ibm.com> --- pc-bios/s390-ccw/cio.c | 13 +++++++++++++ pc-bios/s390-ccw/cio.h | 13 +++++++++++++ pc-bios/s390-ccw/main.c | 5 +++++ 3 files changed, 31 insertions(+) diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c index f440380..e77ec94 100644 --- a/pc-bios/s390-ccw/cio.c +++ b/pc-bios/s390-ccw/cio.c @@ -57,6 +57,19 @@ __u16 cu_type(SubChannelId schid) return senseData.cu_type; } +void basic_sense(SubChannelId schid, SenseData *sd) +{ + Ccw1 senseCcw; + + senseCcw.cmd_code = CCW_CMD_BASIC_SENSE; + senseCcw.cda = ptr2u32(sd); + senseCcw.count = sizeof(*sd); + + if (do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1)) { + panic("Failed to run Basic Sense CCW\n"); + } +} + static bool irb_error(Irb *irb) { /* We have to ignore Incorrect Length (cstat == 0x40) indicators because diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h index b5c9fd7..003524e 100644 --- a/pc-bios/s390-ccw/cio.h +++ b/pc-bios/s390-ccw/cio.h @@ -234,6 +234,18 @@ typedef struct senseid { struct ciw ciw[62]; } __attribute__ ((packed, aligned(4))) SenseId; +/* basic sense response buffer layout */ +typedef struct senseData { + uint8_t status[3]; + uint8_t res_count; + uint8_t phys_drive_id; + uint8_t low_cyl_addr; + uint8_t head_high_cyl_addr; + uint8_t fmt_msg; + uint8_t reserved[16]; + uint8_t reserved2[8]; +} __attribute__ ((packed, aligned(4))) SenseData; + /* interruption response block */ typedef struct irb { struct scsw scsw; @@ -260,6 +272,7 @@ int enable_mss_facility(void); void enable_subchannel(SubChannelId schid); __u16 cu_type(SubChannelId schid); void await_io_int(uint16_t sch_no); +void basic_sense(SubChannelId schid, SenseData *sd); int do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt); /* diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 2bccfa7..e0ce59b 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -201,12 +201,17 @@ static void virtio_setup(void) int main(void) { + SenseData sd; + sclp_setup(); cio_setup(); boot_setup(); find_boot_device(); enable_subchannel(blk_schid); + /* Clear any outstanding device error conditions */ + basic_sense(blk_schid, &sd); + switch (cu_type(blk_schid)) { case 0x3990: /* Real DASD device */ dasd_ipl(blk_schid); /* no return */ -- 2.7.4