On 04/13/2014 08:42 PM, Alexey Kardashevskiy wrote: > This adds migration support for OHCI. > > This defines a descriptor for OHCIState. > This changes some OHCIState field types to be migration compatible. > This adds a descriptor for OHCIPort. > This migrates the EOF timer if the USB was started at the time of > migration. > > Cc: Gerd Hoffmann <kra...@redhat.com> > Cc: Peter Maydell <peter.mayd...@linaro.org> > Signed-off-by: Alexey Kardashevskiy <a...@ozlabs.ru>
Ping, anyone, please? Is it bad/good/ugly? Thanks. > --- > Changes: > v2: > * added OHCIState migration (previously only PCI state was migrated). > > To test this patch, the guest booted from USB disk on a OHCI bus was > migrated from one physical host to another (with another patch to > correctly migrate timebase on POWERPC). The disk image was on > an NFS share. The guest was executing "fdisk -l" in a loop. Without > the patch, this was happening (other disk-related commands failed too): > [root@localhost ~]# fdisk -l > usb-ohci: HCCA read error at 0 > ohci_die: DMA error > > This is the QEMU command line from the test: > /home/aik/qemu-system-ppc64 \ > -enable-kvm \ > -m 1024 \ > -machine pseries \ > -nographic \ > -vga none \ > -device pci-ohci,id=id0 \ > -drive id=id1,if=none,readonly=off,werror=stop,rerror=stop,\ > discard=on,file=ka1/fc19_16GB.qcow2,format=qcow2 \ > -device usb-storage,id=id2,drive=id1 \ > > > > As I am lacking knowledge of USB, please comment, especially the EOF timer > part. > Thanks! > > > --- > hw/usb/hcd-ohci.c | 119 > ++++++++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 111 insertions(+), 8 deletions(-) > > diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c > index 93f186f..cd87074 100644 > --- a/hw/usb/hcd-ohci.c > +++ b/hw/usb/hcd-ohci.c > @@ -80,13 +80,13 @@ typedef struct { > uint32_t bulk_head, bulk_cur; > uint32_t per_cur; > uint32_t done; > - int done_count; > + int32_t done_count; > > /* Frame counter partition */ > - uint32_t fsmps:15; > - uint32_t fit:1; > - uint32_t fi:14; > - uint32_t frt:1; > + uint16_t fsmps; > + uint8_t fit; > + uint16_t fi; > + uint8_t frt; > uint16_t frame_number; > uint16_t padding; > uint32_t pstart; > @@ -111,7 +111,7 @@ typedef struct { > USBPacket usb_packet; > uint8_t usb_buf[8192]; > uint32_t async_td; > - int async_complete; > + bool async_complete; > > } OHCIState; > > @@ -693,7 +693,7 @@ static void ohci_async_complete_packet(USBPort *port, > USBPacket *packet) > #ifdef DEBUG_PACKET > DPRINTF("Async packet complete\n"); > #endif > - ohci->async_complete = 1; > + ohci->async_complete = true; > ohci_process_lists(ohci, 1); > } > > @@ -1058,7 +1058,7 @@ static int ohci_service_td(OHCIState *ohci, struct > ohci_ed *ed) > #endif > if (completion) { > ohci->async_td = 0; > - ohci->async_complete = 0; > + ohci->async_complete = false; > } else { > if (ohci->async_td) { > /* ??? The hardware should allow one active packet per > @@ -1984,6 +1984,108 @@ static Property ohci_pci_properties[] = { > DEFINE_PROP_END_OF_LIST(), > }; > > +static const VMStateDescription vmstate_ohci_state_port = { > + .name = "ohci-core/port", > + .version_id = 1, > + .minimum_version_id = 1, > + .minimum_version_id_old = 1, > + .fields = (VMStateField []) { > + VMSTATE_UINT32(ctrl, OHCIPort), > + VMSTATE_END_OF_LIST() > + }, > +}; > + > +static bool ohci_eof_timer_needed(void *opaque) > +{ > + OHCIState *ohci = opaque; > + > + return ohci->eof_timer != NULL; > +} > + > +static int ohci_eof_timer_pre_load(void *opaque) > +{ > + OHCIState *ohci = opaque; > + > + ohci_bus_start(ohci); > + > + return 0; > +} > + > +static const VMStateDescription vmstate_ohci_eof_timer = { > + .name = "ohci-core/eof-timer", > + .version_id = 1, > + .minimum_version_id = 1, > + .minimum_version_id_old = 1, > + .pre_load = ohci_eof_timer_pre_load, > + .fields = (VMStateField []) { > + VMSTATE_TIMER(eof_timer, OHCIState), > + VMSTATE_END_OF_LIST() > + }, > +}; > + > +const VMStateDescription vmstate_ohci_state = { > + .name = "ohci-core", > + .version_id = 1, > + .minimum_version_id = 1, > + .fields = (VMStateField[]) { > + VMSTATE_INT64(sof_time, OHCIState), > + VMSTATE_UINT32(ctl, OHCIState), > + VMSTATE_UINT32(status, OHCIState), > + VMSTATE_UINT32(intr_status, OHCIState), > + VMSTATE_UINT32(intr, OHCIState), > + VMSTATE_UINT32(hcca, OHCIState), > + VMSTATE_UINT32(ctrl_head, OHCIState), > + VMSTATE_UINT32(ctrl_cur, OHCIState), > + VMSTATE_UINT32(bulk_head, OHCIState), > + VMSTATE_UINT32(bulk_cur, OHCIState), > + VMSTATE_UINT32(per_cur, OHCIState), > + VMSTATE_UINT32(done, OHCIState), > + VMSTATE_INT32(done_count, OHCIState), > + VMSTATE_UINT16(fsmps, OHCIState), > + VMSTATE_UINT8(fit, OHCIState), > + VMSTATE_UINT16(fi, OHCIState), > + VMSTATE_UINT8(frt, OHCIState), > + VMSTATE_UINT16(frame_number, OHCIState), > + VMSTATE_UINT16(padding, OHCIState), > + VMSTATE_UINT32(pstart, OHCIState), > + VMSTATE_UINT32(lst, OHCIState), > + VMSTATE_UINT32(rhdesc_a, OHCIState), > + VMSTATE_UINT32(rhdesc_b, OHCIState), > + VMSTATE_UINT32(rhstatus, OHCIState), > + VMSTATE_STRUCT_ARRAY(rhport, OHCIState, OHCI_MAX_PORTS, 0, > + vmstate_ohci_state_port, OHCIPort), > + VMSTATE_UINT32(hstatus, OHCIState), > + VMSTATE_UINT32(hmask, OHCIState), > + VMSTATE_UINT32(hreset, OHCIState), > + VMSTATE_UINT32(htest, OHCIState), > + VMSTATE_UINT32(old_ctl, OHCIState), > + VMSTATE_UINT8_ARRAY(usb_buf, OHCIState, 8192), > + VMSTATE_UINT32(async_td, OHCIState), > + VMSTATE_BOOL(async_complete, OHCIState), > + VMSTATE_END_OF_LIST() > + }, > + .subsections = (VMStateSubsection []) { > + { > + .vmsd = &vmstate_ohci_eof_timer, > + .needed = ohci_eof_timer_needed, > + } , { > + /* empty */ > + } > + } > +}; > + > +static const VMStateDescription vmstate_ohci = { > + .name = "ohci", > + .version_id = 1, > + .minimum_version_id = 1, > + .minimum_version_id_old = 1, > + .fields = (VMStateField[]) { > + VMSTATE_PCI_DEVICE(parent_obj, OHCIPCIState), > + VMSTATE_STRUCT(state, OHCIPCIState, 1, vmstate_ohci_state, > OHCIState), > + VMSTATE_END_OF_LIST() > + } > +}; > + > static void ohci_pci_class_init(ObjectClass *klass, void *data) > { > DeviceClass *dc = DEVICE_CLASS(klass); > @@ -1997,6 +2099,7 @@ static void ohci_pci_class_init(ObjectClass *klass, > void *data) > dc->desc = "Apple USB Controller"; > dc->props = ohci_pci_properties; > dc->hotpluggable = false; > + dc->vmsd = &vmstate_ohci; > } > > static const TypeInfo ohci_pci_info = { > -- Alexey