qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] usb: cancel async packets on unplug
Date: Mon, 23 May 2011 19:34:20 +0200	[thread overview]
Message-ID: <4DDA9A9C.30300@redhat.com> (raw)
In-Reply-To: <1306165234-6999-1-git-send-email-kraxel@redhat.com>

Hi,

Looks good to me, good way to fix this!

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans

On 05/23/2011 05:40 PM, Gerd Hoffmann wrote:
> This patch adds USBBusOps struct with (for now) only a single callback
> which is called when a device is about to be destroyed.  The USB Host
> adapters are implementing this callback and use it to cancel any async
> requests which might be in flight before the device actually goes away.
>
> Signed-off-by: Gerd Hoffmann<kraxel@redhat.com>
> ---
>   hw/usb-bus.c  |    5 ++++-
>   hw/usb-ehci.c |   25 ++++++++++++++++++++++++-
>   hw/usb-musb.c |   23 ++++++++++++++++++++++-
>   hw/usb-ohci.c |   16 +++++++++++++++-
>   hw/usb-uhci.c |   26 +++++++++++++++++++++++++-
>   hw/usb.h      |    8 +++++++-
>   6 files changed, 97 insertions(+), 6 deletions(-)
>
> diff --git a/hw/usb-bus.c b/hw/usb-bus.c
> index abc7e61..874c253 100644
> --- a/hw/usb-bus.c
> +++ b/hw/usb-bus.c
> @@ -39,9 +39,10 @@ const VMStateDescription vmstate_usb_device = {
>       }
>   };
>
> -void usb_bus_new(USBBus *bus, DeviceState *host)
> +void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host)
>   {
>       qbus_create_inplace(&bus->qbus,&usb_bus_info, host, NULL);
> +    bus->ops = ops;
>       bus->busnr = next_usb_bus++;
>       bus->qbus.allow_hotplug = 1; /* Yes, we can */
>       QTAILQ_INIT(&bus->free);
> @@ -81,8 +82,10 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
>   static int usb_qdev_exit(DeviceState *qdev)
>   {
>       USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
> +    USBBus *bus = usb_bus_from_device(dev);
>
>       usb_device_detach(dev);
> +    bus->ops->device_destroy(bus, dev);
>       if (dev->info->handle_destroy) {
>           dev->info->handle_destroy(dev);
>       }
> diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
> index ac9763f..e8bcb93 100644
> --- a/hw/usb-ehci.c
> +++ b/hw/usb-ehci.c
> @@ -687,6 +687,18 @@ static void ehci_queues_rip_unused(EHCIState *ehci)
>       }
>   }
>
> +static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev)
> +{
> +    EHCIQueue *q, *tmp;
> +
> +    QTAILQ_FOREACH_SAFE(q,&ehci->queues, next, tmp) {
> +        if (q->packet.owner != dev) {
> +            continue;
> +        }
> +        ehci_free_queue(q);
> +    }
> +}
> +
>   static void ehci_queues_rip_all(EHCIState *ehci)
>   {
>       EHCIQueue *q, *tmp;
> @@ -2087,6 +2099,13 @@ static void ehci_map(PCIDevice *pci_dev, int region_num,
>       cpu_register_physical_memory(addr, size, s->mem);
>   }
>
> +static void ehci_device_destroy(USBBus *bus, USBDevice *dev)
> +{
> +    EHCIState *s = container_of(bus, EHCIState, bus);
> +
> +    ehci_queues_rip_device(s, dev);
> +}
> +
>   static int usb_ehci_initfn(PCIDevice *dev);
>
>   static USBPortOps ehci_port_ops = {
> @@ -2095,6 +2114,10 @@ static USBPortOps ehci_port_ops = {
>       .complete = ehci_async_complete_packet,
>   };
>
> +static USBBusOps ehci_bus_ops = {
> +    .device_destroy = ehci_device_destroy,
> +};
> +
>   static PCIDeviceInfo ehci_info = {
>       .qdev.name    = "usb-ehci",
>       .qdev.size    = sizeof(EHCIState),
> @@ -2157,7 +2180,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
>
>       s->irq = s->dev.irq[3];
>
> -    usb_bus_new(&s->bus,&s->dev.qdev);
> +    usb_bus_new(&s->bus,&ehci_bus_ops,&s->dev.qdev);
>       for(i = 0; i<  NB_PORTS; i++) {
>           usb_register_port(&s->bus,&s->ports[i], s, i,&ehci_port_ops,
>                             USB_SPEED_MASK_HIGH);
> diff --git a/hw/usb-musb.c b/hw/usb-musb.c
> index 6037193..21f35af 100644
> --- a/hw/usb-musb.c
> +++ b/hw/usb-musb.c
> @@ -262,6 +262,7 @@
>   static void musb_attach(USBPort *port);
>   static void musb_detach(USBPort *port);
>   static void musb_schedule_cb(USBDevice *dev, USBPacket *p);
> +static void musb_device_destroy(USBBus *bus, USBDevice *dev);
>
>   static USBPortOps musb_port_ops = {
>       .attach = musb_attach,
> @@ -269,6 +270,10 @@ static USBPortOps musb_port_ops = {
>       .complete = musb_schedule_cb,
>   };
>
> +static USBBusOps musb_bus_ops = {
> +    .device_destroy = musb_device_destroy,
> +};
> +
>   typedef struct MUSBPacket MUSBPacket;
>   typedef struct MUSBEndPoint MUSBEndPoint;
>
> @@ -361,7 +366,7 @@ struct MUSBState *musb_init(qemu_irq *irqs)
>           s->ep[i].epnum = i;
>       }
>
> -    usb_bus_new(&s->bus, NULL /* FIXME */);
> +    usb_bus_new(&s->bus,&musb_bus_ops, NULL /* FIXME */);
>       usb_register_port(&s->bus,&s->port, s, 0,&musb_port_ops,
>                         USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
>       usb_port_location(&s->port, NULL, 1);
> @@ -778,6 +783,22 @@ static void musb_rx_packet_complete(USBPacket *packey, void *opaque)
>       musb_rx_intr_set(s, epnum, 1);
>   }
>
> +static void musb_device_destroy(USBBus *bus, USBDevice *dev)
> +{
> +    MUSBState *s = container_of(bus, MUSBState, bus);
> +    int ep, dir;
> +
> +    for (ep = 0; ep<  16; ep++) {
> +        for (dir = 0; dir<  2; dir++) {
> +            if (s->ep[ep].packey[dir].p.owner != dev) {
> +                continue;
> +            }
> +            usb_cancel_packet(&s->ep[ep].packey[dir].p);
> +            /* status updates needed here? */
> +        }
> +    }
> +}
> +
>   static void musb_tx_rdy(MUSBState *s, int epnum)
>   {
>       MUSBEndPoint *ep = s->ep + epnum;
> diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
> index 8b966f7..401045a 100644
> --- a/hw/usb-ohci.c
> +++ b/hw/usb-ohci.c
> @@ -1644,6 +1644,16 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
>       }
>   }
>
> +static void ohci_device_destroy(USBBus *bus, USBDevice *dev)
> +{
> +    OHCIState *ohci = container_of(bus, OHCIState, bus);
> +
> +    if (ohci->async_td&&  ohci->usb_packet.owner == dev) {
> +        usb_cancel_packet(&ohci->usb_packet);
> +        ohci->async_td = 0;
> +    }
> +}
> +
>   /* Only dword reads are defined on OHCI register space */
>   static CPUReadMemoryFunc * const ohci_readfn[3]={
>       ohci_mem_read,
> @@ -1664,6 +1674,10 @@ static USBPortOps ohci_port_ops = {
>       .complete = ohci_async_complete_packet,
>   };
>
> +static USBBusOps ohci_bus_ops = {
> +    .device_destroy = ohci_device_destroy,
> +};
> +
>   static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
>                             int num_ports, uint32_t localmem_base)
>   {
> @@ -1691,7 +1705,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
>
>       ohci->name = dev->info->name;
>
> -    usb_bus_new(&ohci->bus, dev);
> +    usb_bus_new(&ohci->bus,&ohci_bus_ops, dev);
>       ohci->num_ports = num_ports;
>       for (i = 0; i<  num_ports; i++) {
>           usb_register_port(&ohci->bus,&ohci->rhport[i].port, ohci, i,&ohci_port_ops,
> diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
> index bc31850..e9993a7 100644
> --- a/hw/usb-uhci.c
> +++ b/hw/usb-uhci.c
> @@ -234,6 +234,19 @@ static void uhci_async_validate_end(UHCIState *s)
>       }
>   }
>
> +static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
> +{
> +    UHCIAsync *curr, *n;
> +
> +    QTAILQ_FOREACH_SAFE(curr,&s->async_pending, next, n) {
> +        if (curr->packet.owner != dev) {
> +            continue;
> +        }
> +        uhci_async_unlink(s, curr);
> +        uhci_async_cancel(s, curr);
> +    }
> +}
> +
>   static void uhci_async_cancel_all(UHCIState *s)
>   {
>       UHCIAsync *curr, *n;
> @@ -1097,6 +1110,13 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
>       register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
>   }
>
> +static void uhci_device_destroy(USBBus *bus, USBDevice *dev)
> +{
> +    UHCIState *s = container_of(bus, UHCIState, bus);
> +
> +    uhci_async_cancel_device(s, dev);
> +}
> +
>   static USBPortOps uhci_port_ops = {
>       .attach = uhci_attach,
>       .detach = uhci_detach,
> @@ -1104,6 +1124,10 @@ static USBPortOps uhci_port_ops = {
>       .complete = uhci_async_complete,
>   };
>
> +static USBBusOps uhci_bus_ops = {
> +    .device_destroy = uhci_device_destroy,
> +};
> +
>   static int usb_uhci_common_initfn(UHCIState *s)
>   {
>       uint8_t *pci_conf = s->dev.config;
> @@ -1116,7 +1140,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
>       pci_conf[PCI_INTERRUPT_PIN] = 4; // interrupt pin 3
>       pci_conf[0x60] = 0x10; // release number
>
> -    usb_bus_new(&s->bus,&s->dev.qdev);
> +    usb_bus_new(&s->bus,&uhci_bus_ops,&s->dev.qdev);
>       for(i = 0; i<  NB_PORTS; i++) {
>           usb_register_port(&s->bus,&s->ports[i].port, s, i,&uhci_port_ops,
>                             USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
> diff --git a/hw/usb.h b/hw/usb.h
> index 0fa86a3..097d789 100644
> --- a/hw/usb.h
> +++ b/hw/usb.h
> @@ -139,6 +139,7 @@
>   #define USB_ENDPOINT_XFER_INT		3
>
>   typedef struct USBBus USBBus;
> +typedef struct USBBusOps USBBusOps;
>   typedef struct USBPort USBPort;
>   typedef struct USBDevice USBDevice;
>   typedef struct USBDeviceInfo USBDeviceInfo;
> @@ -330,6 +331,7 @@ void musb_set_size(MUSBState *s, int epnum, int size, int is_tx);
>
>   struct USBBus {
>       BusState qbus;
> +    USBBusOps *ops;
>       int busnr;
>       int nfree;
>       int nused;
> @@ -338,7 +340,11 @@ struct USBBus {
>       QTAILQ_ENTRY(USBBus) next;
>   };
>
> -void usb_bus_new(USBBus *bus, DeviceState *host);
> +struct USBBusOps {
> +    void (*device_destroy)(USBBus *bus, USBDevice *dev);
> +};
> +
> +void usb_bus_new(USBBus *bus, USBBusOps *ops, DeviceState *host);
>   USBBus *usb_bus_find(int busnr);
>   void usb_qdev_register(USBDeviceInfo *info);
>   void usb_qdev_register_many(USBDeviceInfo *info);

      reply	other threads:[~2011-05-23 17:34 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-23 15:40 [Qemu-devel] [PATCH] usb: cancel async packets on unplug Gerd Hoffmann
2011-05-23 17:34 ` Hans de Goede [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4DDA9A9C.30300@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).