diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2012-03-29 08:39:46 +1100 |
---|---|---|
committer | Andreas Färber <afaerber@suse.de> | 2012-04-15 17:07:19 +0200 |
commit | 8e01f355db4c7e54b0877a6d9508e83d0afbc4b6 (patch) | |
tree | 575b675caf78fcc6f2f223d065f8b8ef9524e6a4 /hw/spapr_vio.c | |
parent | d9599c9205089805cd6ef55985beeb06aef0c819 (diff) |
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 <david@gibson.dropbear.id.au>
[AF: Updated hcall_dprintf()s to not duplicate the function name]
Signed-off-by: Andreas Färber <afaerber@suse.de>
Diffstat (limited to 'hw/spapr_vio.c')
-rw-r--r-- | hw/spapr_vio.c | 33 |
1 files changed, 25 insertions, 8 deletions
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); } |