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>
This commit is contained in:
parent
d9599c9205
commit
8e01f355db
@ -431,12 +431,13 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
|
|||||||
|
|
||||||
/* Check if device supports CRQs */
|
/* Check if device supports CRQs */
|
||||||
if (!dev->crq.SendFunc) {
|
if (!dev->crq.SendFunc) {
|
||||||
|
hcall_dprintf("Device does not support CRQ\n");
|
||||||
return H_NOT_FOUND;
|
return H_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Already a queue ? */
|
/* Already a queue ? */
|
||||||
if (dev->crq.qsize) {
|
if (dev->crq.qsize) {
|
||||||
|
hcall_dprintf("CRQ already registered\n");
|
||||||
return H_RESOURCE;
|
return H_RESOURCE;
|
||||||
}
|
}
|
||||||
dev->crq.qladdr = queue_addr;
|
dev->crq.qladdr = queue_addr;
|
||||||
@ -449,6 +450,17 @@ static target_ulong h_reg_crq(CPUPPCState *env, sPAPREnvironment *spapr,
|
|||||||
return H_SUCCESS;
|
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,
|
static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
|
||||||
target_ulong opcode, target_ulong *args)
|
target_ulong opcode, target_ulong *args)
|
||||||
{
|
{
|
||||||
@ -460,13 +472,7 @@ static target_ulong h_free_crq(CPUPPCState *env, sPAPREnvironment *spapr,
|
|||||||
return H_PARAMETER;
|
return H_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->crq.qladdr = 0;
|
return free_crq(dev);
|
||||||
dev->crq.qsize = 0;
|
|
||||||
dev->crq.qnext = 0;
|
|
||||||
|
|
||||||
dprintf("CRQ for dev 0x" TARGET_FMT_lx " freed\n", reg);
|
|
||||||
|
|
||||||
return H_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
|
static target_ulong h_send_crq(CPUPPCState *env, sPAPREnvironment *spapr,
|
||||||
@ -642,6 +648,15 @@ static int spapr_vio_check_reg(VIOsPAPRDevice *sdev)
|
|||||||
return 0;
|
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)
|
static int spapr_vio_busdev_init(DeviceState *qdev)
|
||||||
{
|
{
|
||||||
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
|
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
|
||||||
@ -670,6 +685,8 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
|
|||||||
|
|
||||||
rtce_init(dev);
|
rtce_init(dev);
|
||||||
|
|
||||||
|
qemu_register_reset(spapr_vio_busdev_reset, dev);
|
||||||
|
|
||||||
return pc->init(dev);
|
return pc->init(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user