From: David Gibson Date: Wed, 28 Mar 2012 21:39:46 +0000 (+1100) Subject: pseries: Fix bug with reset of VIO CRQs X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.1~1405^2~17^2~602^2~17 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8e01f355db4c7e54b0877a6d9508e83d0afbc4b6;p=sdk%2Femulator%2Fqemu.git pseries: Fix bug with reset of VIO CRQs PAPR specifies a Command Response Queue (CRQ) mechanism used for virtual IO, which we implement. However, we don't correctly clean up registered CRQs when we reset the system. This patch adds a reset handler to fix this bug. While we're at it, add in some of the extra debug messages that were used to track the problem down. Signed-off-by: David Gibson [AF: Updated hcall_dprintf()s to not duplicate the function name] Signed-off-by: Andreas Färber --- diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c index 1f67e64eb6..0bf2c3179c 100644 --- a/hw/spapr_vio.c +++ b/hw/spapr_vio.c @@ -431,12 +431,13 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr, /* Check if device supports CRQs */ if (!dev->crq.SendFunc) { + hcall_dprintf("Device does not support CRQ\n"); return H_NOT_FOUND; } - /* Already a queue ? */ if (dev->crq.qsize) { + hcall_dprintf("CRQ already registered\n"); return H_RESOURCE; } dev->crq.qladdr = queue_addr; @@ -449,6 +450,17 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr, return H_SUCCESS; } +static target_ulong free_crq(VIOsPAPRDevice *dev) +{ + dev->crq.qladdr = 0; + dev->crq.qsize = 0; + dev->crq.qnext = 0; + + dprintf("CRQ for dev 0x%" PRIx32 " freed\n", dev->reg); + + return H_SUCCESS; +} + static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr, target_ulong opcode, target_ulong *args) { @@ -460,13 +472,7 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr, return H_PARAMETER; } - dev->crq.qladdr = 0; - dev->crq.qsize = 0; - dev->crq.qnext = 0; - - dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg); - - return H_SUCCESS; + return free_crq(dev); } static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr, @@ -642,6 +648,15 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev) return 0; } +static void spapr_vio_busdev_reset(void *opaque) +{ + VIOsPAPRDevice *dev = (VIOsPAPRDevice *)opaque; + + if (dev->crq.qsize) { + free_crq(dev); + } +} + static int spapr_vio_busdev_init(DeviceState *qdev) { VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev; @@ -670,6 +685,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev) rtce_init(dev); + qemu_register_reset(spapr_vio_busdev_reset, dev); + return pc->init(dev); }