[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 1/3] PVUSB update and bugfix: frontend part



Signed-off-by: Noboru Iwamatsu <n_iwamatsu@xxxxxxxxxxxxxx>

diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbfront/usbfront-dbg.c
--- a/drivers/xen/usbfront/usbfront-dbg.c       Tue Sep 29 11:23:06 2009 +0100
+++ b/drivers/xen/usbfront/usbfront-dbg.c       Tue Oct 06 15:18:27 2009 +0900
@@ -60,7 +60,7 @@
 
        spin_lock_irqsave(&info->lock, flags);
 
-       temp = scnprintf (next, size,
+       temp = scnprintf(next, size,
                        "bus %s, device %s\n"
                        "%s\n"
                        "xenhcd, hcd state %d\n",
@@ -74,7 +74,8 @@
 #ifdef XENHCD_STATS
        temp = scnprintf(next, size,
                "complete %ld unlink %ld ring_full %ld\n",
-               info->stats.complete, info->stats.unlink, 
info->stats.ring_full);
+               info->stats.complete, info->stats.unlink,
+               info->stats.ring_full);
        size -= temp;
        next += temp;
 #endif
diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbfront/usbfront-hcd.c
--- a/drivers/xen/usbfront/usbfront-hcd.c       Tue Sep 29 11:23:06 2009 +0100
+++ b/drivers/xen/usbfront/usbfront-hcd.c       Tue Oct 06 15:18:27 2009 +0900
@@ -54,7 +54,7 @@
        unsigned long flags;
 
        spin_lock_irqsave(&info->lock, flags);
-       if (HC_IS_RUNNING(info_to_hcd(info)->state)) {
+       if (likely(HC_IS_RUNNING(info_to_hcd(info)->state))) {
                timer_action_done(info, TIMER_RING_WATCHDOG);
                xenhcd_giveback_unlinked_urbs(info);
                xenhcd_kick_pending_urbs(info);
@@ -70,9 +70,10 @@
        struct usbfront_info *info = hcd_to_info(hcd);
 
        spin_lock_init(&info->lock);
-       INIT_LIST_HEAD(&info->pending_urbs);
-       INIT_LIST_HEAD(&info->inprogress_urbs);
-       INIT_LIST_HEAD(&info->unlinked_urbs);
+       INIT_LIST_HEAD(&info->pending_submit_list);
+       INIT_LIST_HEAD(&info->pending_unlink_list);
+       INIT_LIST_HEAD(&info->in_progress_list);
+       INIT_LIST_HEAD(&info->giveback_waiting_list);
        init_timer(&info->watchdog);
        info->watchdog.function = xenhcd_watchdog;
        info->watchdog.data = (unsigned long) info;
@@ -101,70 +102,14 @@
        del_timer_sync(&info->watchdog);
        remove_debug_file(info);
        spin_lock_irq(&info->lock);
-       /*
-        * TODO: port power off, cancel all urbs.
-        */
-
-       if (HC_IS_RUNNING(hcd->state))
-               hcd->state = HC_STATE_HALT;
+       /* cancel all urbs */
+       hcd->state = HC_STATE_HALT;
+       xenhcd_cancel_all_enqueued_urbs(info);
+       xenhcd_giveback_unlinked_urbs(info);
        spin_unlock_irq(&info->lock);
 }
 
 /*
- * TODO: incomplete suspend/resume functions!
- */
-#if 0
-#ifdef CONFIG_PM
-/*
- * suspend running HC
- */
-static int xenhcd_suspend(struct usb_hcd *hcd, pm_message_t message)
-{
-       struct usbfront_info *info = hcd_to_info(hcd);
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&info->lock, flags);
-       if (hcd->state != HC_STATE_SUSPENDED) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * TODO:
-        *      canceling all transfer, clear all hc queue,
-        *      stop kthread,
-        */
-
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-done:
-       spin_unlock_irqrestore(&info->lock, flags);
-
-       return ret;
-}
-
-/*
- * resume HC
- */
-static int xenhcd_resume(struct usb_hcd *hcd)
-{
-       struct usbfront_info *info = hcd_to_info(hcd);
-       int ret = -EINVAL;
-
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
-       /*
-        * TODO:
-        *      re-init HC.
-        *      resume all roothub ports.
-        */
-
-       return ret;
-}
-#endif
-#endif
-
-/*
  * called as .urb_enqueue()
  * non-error returns are promise to giveback the urb later
  */
@@ -197,11 +142,6 @@
 
 /*
  * called as .urb_dequeue()
- *
- * just mark the urb as unlinked
- * if the urb is in pending_urbs, move to unlinked_urbs
- * TODO:
- *     canceling the urb transfer in backend
  */
 static int xenhcd_urb_dequeue(struct usb_hcd *hcd,
                                    struct urb *urb)
@@ -234,46 +174,54 @@
        return 0;
 }
 
-/*
- * TODO:
- * suspend/resume whole hcd and roothub
- */
 static const char hcd_name[] = "xen_hcd";
 
-struct hc_driver usbfront_hc_driver = {
+struct hc_driver xen_usb20_hc_driver = {
        .description = hcd_name,
-       .product_desc = DRIVER_DESC,
+       .product_desc = "Xen USB2.0 Virtual Host Controller",
        .hcd_priv_size = sizeof(struct usbfront_info),
        .flags = HCD_USB2,
 
-       /*
-        * basic HC lifecycle operations
-        */
+       /* basic HC lifecycle operations */
        .reset = xenhcd_setup,
        .start = xenhcd_run,
        .stop = xenhcd_stop,
-#if 0
-#ifdef CONFIG_PM
-       .suspend = xenhcd_suspend,
-       .resume = xenhcd_resume,
-#endif
-#endif
-       /*
-        * managing urb I/O
-        */
+
+       /* managing urb I/O */
        .urb_enqueue = xenhcd_urb_enqueue,
        .urb_dequeue = xenhcd_urb_dequeue,
        .get_frame_number = xenhcd_get_frame,
 
-       /*
-        * root hub operations
-        */
+       /* root hub operations */
        .hub_status_data = xenhcd_hub_status_data,
        .hub_control = xenhcd_hub_control,
-#if 0
 #ifdef CONFIG_PM
        .bus_suspend = xenhcd_bus_suspend,
        .bus_resume = xenhcd_bus_resume,
 #endif
+};
+
+struct hc_driver xen_usb11_hc_driver = {
+       .description = hcd_name,
+       .product_desc = "Xen USB1.1 Virtual Host Controller",
+       .hcd_priv_size = sizeof(struct usbfront_info),
+       .flags = HCD_USB11,
+
+       /* basic HC lifecycle operations */
+       .reset = xenhcd_setup,
+       .start = xenhcd_run,
+       .stop = xenhcd_stop,
+
+       /* managing urb I/O */
+       .urb_enqueue = xenhcd_urb_enqueue,
+       .urb_dequeue = xenhcd_urb_dequeue,
+       .get_frame_number = xenhcd_get_frame,
+
+       /* root hub operations */
+       .hub_status_data = xenhcd_hub_status_data,
+       .hub_control = xenhcd_hub_control,
+#ifdef CONFIG_PM
+       .bus_suspend = xenhcd_bus_suspend,
+       .bus_resume = xenhcd_bus_resume,
 #endif
 };
diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbfront/usbfront-hub.c
--- a/drivers/xen/usbfront/usbfront-hub.c       Tue Sep 29 11:23:06 2009 +0100
+++ b/drivers/xen/usbfront/usbfront-hub.c       Tue Oct 06 15:18:27 2009 +0900
@@ -50,15 +50,16 @@
 {
        int port;
 
-       port = portnum -1;
+       port = portnum - 1;
        if (info->ports[port].status & USB_PORT_STAT_POWER) {
                switch (info->devices[port].speed) {
                case USB_SPEED_UNKNOWN:
-                       info->ports[port].status &= ~(USB_PORT_STAT_CONNECTION |
-                                                       USB_PORT_STAT_ENABLE |
-                                                       USB_PORT_STAT_LOW_SPEED 
|
-                                                       
USB_PORT_STAT_HIGH_SPEED |
-                                                       USB_PORT_STAT_SUSPEND);
+                       info->ports[port].status &=
+                               ~(USB_PORT_STAT_CONNECTION |
+                                       USB_PORT_STAT_ENABLE |
+                                       USB_PORT_STAT_LOW_SPEED |
+                                       USB_PORT_STAT_HIGH_SPEED |
+                                       USB_PORT_STAT_SUSPEND);
                        break;
                case USB_SPEED_LOW:
                        info->ports[port].status |= USB_PORT_STAT_CONNECTION;
@@ -86,6 +87,9 @@
 {
        int port;
 
+       if (portnum < 1 || portnum > info->rh_numports)
+               return; /* invalid port number */
+
        port = portnum - 1;
        if (info->devices[port].speed != speed) {
                switch (speed) {
@@ -107,30 +111,6 @@
        }
 }
 
-void rhport_disconnect(struct usbfront_info *info, int portnum)
-{
-       rhport_connect(info, portnum, USB_SPEED_UNKNOWN);
-}
-
-void xenhcd_rhport_state_change(struct usbfront_info *info,
-                               int portnum, enum usb_device_speed speed)
-{
-       int changed = 0;
-       unsigned long flags;
-
-       if (portnum < 1 || portnum > info->rh_numports)
-               return; /* invalid port number */
-
-       spin_lock_irqsave(&info->lock, flags);
-       rhport_connect(info, portnum, speed);
-       if (info->ports[portnum-1].c_connection)
-               changed = 1;
-       spin_unlock_irqrestore(&info->lock, flags);
-
-       if (changed)
-               usb_hcd_poll_rh_status(info_to_hcd(info));
-}
-
 /*
  * SetPortFeature(PORT_SUSPENDED)
  */
@@ -214,7 +194,7 @@
 {
        int port;
 
-       port = portnum -1;
+       port = portnum - 1;
        info->ports[port].status &= ~(USB_PORT_STAT_ENABLE
                                        | USB_PORT_STAT_LOW_SPEED
                                        | USB_PORT_STAT_HIGH_SPEED);
@@ -227,57 +207,51 @@
        info->ports[port].timeout = jiffies + msecs_to_jiffies(10);
 }
 
-#if 0
 #ifdef CONFIG_PM
 static int xenhcd_bus_suspend(struct usb_hcd *hcd)
 {
        struct usbfront_info *info = hcd_to_info(hcd);
+       int ret = 0;
        int i, ports;
 
        ports = info->rh_numports;
 
        spin_lock_irq(&info->lock);
-
-       if (HC_IS_RUNNING(hcd->state)) {
-               /*
-                * TODO:
-                * clean queue,
-                * stop all transfers,
-                * ...
-                */
-               hcd->state = HC_STATE_QUIESCING;
+       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &info->flags))
+               ret = -ESHUTDOWN;
+       else if (!info->dead) {
+               /* suspend any active ports*/
+               for (i = 1; i <= ports; i++)
+                       rhport_suspend(info, i);
        }
-
-       /* suspend any active ports*/
-       for (i = 1; i <= ports; i++) {
-               rhport_suspend(info, i);
-       }
+       spin_unlock_irq(&info->lock);
 
        del_timer_sync(&info->watchdog);
 
-       spin_unlock_irq(&info->lock);
-
-       return 0;
+       return ret;
 }
 
 static int xenhcd_bus_resume(struct usb_hcd *hcd)
 {
        struct usbfront_info *info = hcd_to_info(hcd);
+       int ret = 0;
        int i, ports;
 
        ports = info->rh_numports;
 
        spin_lock_irq(&info->lock);
-       /* resume any suspended ports*/
-       for (i = 1; i <= ports; i++) {
-               rhport_resume(info, i);
+       if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &info->flags))
+               ret = -ESHUTDOWN;
+       else if (!info->dead) {
+               /* resume any suspended ports*/
+               for (i = 1; i <= ports; i++)
+                       rhport_resume(info, i);
        }
-       hcd->state = HC_STATE_RUNNING;
        spin_unlock_irq(&info->lock);
-       return 0;
+
+       return ret;
 }
 #endif
-#endif
 
 static void xenhcd_hub_descriptor(struct usbfront_info *info,
                                  struct usb_hub_descriptor *desc)
@@ -295,8 +269,8 @@
        desc->bDescLength = 7 + 2 * temp;
 
        /* bitmaps for DeviceRemovable and PortPwrCtrlMask */
-       memset (&desc->bitmap[0], 0, temp);
-       memset (&desc->bitmap[temp], 0xff, temp);
+       memset(&desc->bitmap[0], 0, temp);
+       memset(&desc->bitmap[temp], 0xff, temp);
 
        /* per-port over current reporting and no power switching */
        temp = 0x000a;
@@ -380,11 +354,6 @@
        int i;
        int changed = 0;
 
-#ifdef USBFRONT_DEBUG
-       WPRINTK("xenusb_hub_control(typeReq %x wValue %x wIndex %x)\n",
-              typeReq, wValue, wIndex);
-#endif
-
        spin_lock_irqsave(&info->lock, flags);
        switch (typeReq) {
        case ClearHubFeature:
@@ -394,7 +363,7 @@
                if (!wIndex || wIndex > ports)
                        goto error;
 
-               switch(wValue) {
+               switch (wValue) {
                case USB_PORT_FEAT_SUSPEND:
                        rhport_resume(info, wIndex);
                        break;
@@ -414,7 +383,7 @@
                break;
        case GetHubDescriptor:
                xenhcd_hub_descriptor(info,
-                                     (struct usb_hub_descriptor*) buf);
+                                     (struct usb_hub_descriptor *) buf);
                break;
        case GetHubStatus:
                /* always local power supply good and no over-current exists. */
@@ -444,7 +413,7 @@
                                info->devices[wIndex].status = 
USB_STATE_DEFAULT;
                        }
 
-                       switch(info->devices[wIndex].speed) {
+                       switch (info->devices[wIndex].speed) {
                        case USB_SPEED_LOW:
                                info->ports[wIndex].status |= 
USB_PORT_STAT_LOW_SPEED;
                                break;
@@ -466,7 +435,7 @@
                if (!wIndex || wIndex > ports)
                        goto error;
 
-               switch(wValue) {
+               switch (wValue) {
                case USB_PORT_FEAT_POWER:
                        rhport_power_on(info, wIndex);
                        break;
@@ -477,9 +446,8 @@
                        rhport_suspend(info, wIndex);
                        break;
                default:
-                       if ((info->ports[wIndex-1].status & 
USB_PORT_STAT_POWER) != 0) {
+                       if ((info->ports[wIndex-1].status & 
USB_PORT_STAT_POWER) != 0)
                                info->ports[wIndex-1].status |= (1 << wValue);
-                       }
                }
                break;
 
@@ -491,9 +459,8 @@
 
        /* check status for each port */
        for (i = 0; i < ports; i++) {
-               if (info->ports[i].status & PORT_C_MASK) {
+               if (info->ports[i].status & PORT_C_MASK)
                        changed = 1;
-               }
        }
        if (changed)
                usb_hcd_poll_rh_status(hcd);
diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbfront/usbfront-q.c
--- a/drivers/xen/usbfront/usbfront-q.c Tue Sep 29 11:23:06 2009 +0100
+++ b/drivers/xen/usbfront/usbfront-q.c Tue Oct 06 15:18:27 2009 +0900
@@ -50,13 +50,13 @@
        struct urb_priv *urbp;
 
        urbp = kmem_cache_zalloc(xenhcd_urbp_cachep, GFP_ATOMIC);
-       if (!urbp) {
+       if (!urbp)
                return NULL;
-       }
 
        urbp->urb = urb;
        urb->hcpriv = urbp;
        urbp->req_id = ~0;
+       urbp->unlink_req_id = ~0;
        INIT_LIST_HEAD(&urbp->list);
 
        return urbp;
@@ -73,7 +73,7 @@
 {
        unsigned long free;
        free = info->shadow_free;
-       BUG_ON(free > USB_RING_SIZE);
+       BUG_ON(free >= USB_URB_RING_SIZE);
        info->shadow_free = info->shadow[free].req.id;
        info->shadow[free].req.id = (unsigned int)0x0fff; /* debug */
        return free;
@@ -90,7 +90,7 @@
 static inline int count_pages(void *addr, int length)
 {
        unsigned long start = (unsigned long) addr >> PAGE_SHIFT;
-       unsigned long end = (unsigned long) (addr + length + PAGE_SIZE -1) >> 
PAGE_SHIFT;
+       unsigned long end = (unsigned long) (addr + length + PAGE_SIZE - 1) >> 
PAGE_SHIFT;
        return end - start;
 }
 
@@ -108,7 +108,7 @@
 
        len = length;
 
-       for(i = 0;i < nr_pages;i++){
+       for (i = 0; i < nr_pages; i++) {
                BUG_ON(!len);
 
                page = virt_to_page(addr);
@@ -116,7 +116,7 @@
                offset = offset_in_page(addr);
 
                bytes = PAGE_SIZE - offset;
-               if(bytes > len)
+               if (bytes > len)
                        bytes = len;
 
                ref = gnttab_claim_grant_reference(gref_head);
@@ -132,7 +132,7 @@
 }
 
 static int map_urb_for_request(struct usbfront_info *info, struct urb *urb,
-               usbif_request_t *req)
+               usbif_urb_request_t *req)
 {
        grant_ref_t gref_head;
        int nr_buff_pages = 0;
@@ -175,14 +175,12 @@
                req->u.isoc.start_frame = urb->start_frame;
                req->u.isoc.number_of_packets = urb->number_of_packets;
                req->u.isoc.nr_frame_desc_segs = nr_isodesc_pages;
-               /*
-                * urb->number_of_packets must be > 0
-                */
+               /* urb->number_of_packets must be > 0 */
                if (unlikely(urb->number_of_packets <= 0))
                        BUG();
                xenhcd_gnttab_map(info, &urb->iso_frame_desc[0],
-                               sizeof(struct usb_iso_packet_descriptor) * 
urb->number_of_packets,
-                               &gref_head, &req->seg[nr_buff_pages], 
nr_isodesc_pages, 0);
+                       sizeof(struct usb_iso_packet_descriptor) * 
urb->number_of_packets,
+                       &gref_head, &req->seg[nr_buff_pages], nr_isodesc_pages, 
0);
                gnttab_free_grant_references(gref_head);
                break;
        case PIPE_INTERRUPT:
@@ -213,9 +211,12 @@
 
        for (i = 0; i < nr_segs; i++)
                gnttab_end_foreign_access(shadow->req.seg[i].gref, 0UL);
+
+       shadow->req.nr_buffer_segs = 0;
+       shadow->req.u.isoc.nr_frame_desc_segs = 0;
 }
 
-static void xenhcd_giveback_urb(struct usbfront_info *info, struct urb *urb)
+static void xenhcd_giveback_urb(struct usbfront_info *info, struct urb *urb, 
int status)
 __releases(info->lock)
 __acquires(info->lock)
 {
@@ -228,6 +229,9 @@
        case -ENOENT:
                COUNT(info->stats.unlink);
                break;
+       case -EINPROGRESS:
+               urb->status = status;
+               /* falling through */
        default:
                COUNT(info->stats.complete);
        }
@@ -238,28 +242,35 @@
 
 static inline int xenhcd_do_request(struct usbfront_info *info, struct 
urb_priv *urbp)
 {
-       usbif_request_t *ring_req;
+       usbif_urb_request_t *req;
        struct urb *urb = urbp->urb;
        uint16_t id;
        int notify;
        int ret = 0;
 
-       ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
+       req = RING_GET_REQUEST(&info->urb_ring, info->urb_ring.req_prod_pvt);
        id = get_id_from_freelist(info);
-       ring_req->id = id;
+       req->id = id;
 
-       ret = map_urb_for_request(info, urb, ring_req);
-       if (ret < 0) {
-               add_id_to_freelist(info, id);
-               return ret;
+       if (unlikely(urbp->unlinked)) {
+               req->u.unlink.unlink_id = urbp->req_id;
+               req->pipe = usbif_setunlink_pipe(usbif_setportnum_pipe(
+                               urb->pipe, urb->dev->portnum));
+               urbp->unlink_req_id = id;
+       } else {
+               ret = map_urb_for_request(info, urb, req);
+               if (ret < 0) {
+                       add_id_to_freelist(info, id);
+                       return ret;
+               }
+               urbp->req_id = id;
        }
 
-       info->ring.req_prod_pvt++;
+       info->urb_ring.req_prod_pvt++;
        info->shadow[id].urb = urb;
-       info->shadow[id].req = *ring_req;
-       urbp->req_id = id;
+       info->shadow[id].req = *req;
 
-       RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->ring, notify);
+       RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->urb_ring, notify);
        if (notify)
                notify_remote_via_irq(info->irq);
 
@@ -271,19 +282,19 @@
        struct urb_priv *urbp;
        int ret;
 
-       while (!list_empty(&info->pending_urbs)) {
-               if (RING_FULL(&info->ring)) {
+       while (!list_empty(&info->pending_submit_list)) {
+               if (RING_FULL(&info->urb_ring)) {
                        COUNT(info->stats.ring_full);
                        timer_action(info, TIMER_RING_WATCHDOG);
                        goto done;
                }
 
-               urbp = list_entry(info->pending_urbs.next, struct urb_priv, 
list);
+               urbp = list_entry(info->pending_submit_list.next, struct 
urb_priv, list);
                ret = xenhcd_do_request(info, urbp);
                if (ret == 0)
-                       list_move_tail(&urbp->list, &info->inprogress_urbs);
+                       list_move_tail(&urbp->list, &info->in_progress_list);
                else
-                       xenhcd_giveback_urb(info, urbp->urb);
+                       xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
        }
        timer_action_done(info, TIMER_SCAN_PENDING_URBS);
 
@@ -291,12 +302,41 @@
        return;
 }
 
+/*
+ * caller must lock info->lock
+ */
+static void xenhcd_cancel_all_enqueued_urbs(struct usbfront_info *info)
+{
+       struct urb_priv *urbp, *tmp;
+
+       list_for_each_entry_safe(urbp, tmp, &info->in_progress_list, list) {
+               if (!urbp->unlinked) {
+                       xenhcd_gnttab_done(&info->shadow[urbp->req_id]);
+                       barrier();
+                       if (urbp->urb->status == -EINPROGRESS)  /* not dequeued 
*/
+                               xenhcd_giveback_urb(info, urbp->urb, 
-ESHUTDOWN);
+                       else                                    /* dequeued */
+                               xenhcd_giveback_urb(info, urbp->urb, 
urbp->urb->status);
+               }
+               info->shadow[urbp->req_id].urb = NULL;
+       }
+
+       list_for_each_entry_safe(urbp, tmp, &info->pending_submit_list, list) {
+               xenhcd_giveback_urb(info, urbp->urb, -ESHUTDOWN);
+       }
+
+       return;
+}
+
+/*
+ * caller must lock info->lock
+ */
 static void xenhcd_giveback_unlinked_urbs(struct usbfront_info *info)
 {
        struct urb_priv *urbp, *tmp;
 
-       list_for_each_entry_safe(urbp, tmp, &info->unlinked_urbs, list) {
-               xenhcd_giveback_urb(info, urbp->urb);
+       list_for_each_entry_safe(urbp, tmp, &info->giveback_waiting_list, list) 
{
+               xenhcd_giveback_urb(info, urbp->urb, urbp->urb->status);
        }
 }
 
@@ -304,22 +344,22 @@
 {
        int ret = 0;
 
-       if (RING_FULL(&info->ring)) {
-               list_add_tail(&urbp->list, &info->pending_urbs);
+       if (RING_FULL(&info->urb_ring)) {
+               list_add_tail(&urbp->list, &info->pending_submit_list);
                COUNT(info->stats.ring_full);
                timer_action(info, TIMER_RING_WATCHDOG);
                goto done;
        }
 
-       if (!list_empty(&info->pending_urbs)) {
-               list_add_tail(&urbp->list, &info->pending_urbs);
+       if (!list_empty(&info->pending_submit_list)) {
+               list_add_tail(&urbp->list, &info->pending_submit_list);
                timer_action(info, TIMER_SCAN_PENDING_URBS);
                goto done;
        }
 
        ret = xenhcd_do_request(info, urbp);
        if (ret == 0)
-               list_add_tail(&urbp->list, &info->inprogress_urbs);
+               list_add_tail(&urbp->list, &info->in_progress_list);
 
 done:
        return ret;
@@ -327,26 +367,47 @@
 
 static int xenhcd_unlink_urb(struct usbfront_info *info, struct urb_priv *urbp)
 {
+       int ret = 0;
+
+       /* already unlinked? */
        if (urbp->unlinked)
                return -EBUSY;
+
        urbp->unlinked = 1;
 
-       /* if the urb is in pending_urbs */
+       /* the urb is still in pending_submit queue */
        if (urbp->req_id == ~0) {
-               list_move_tail(&urbp->list, &info->unlinked_urbs);
+               list_move_tail(&urbp->list, &info->giveback_waiting_list);
                timer_action(info, TIMER_SCAN_PENDING_URBS);
+               goto done;
        }
 
-       /* TODO: send cancel request to backend */
+       /* send unlink request to backend */
+       if (RING_FULL(&info->urb_ring)) {
+               list_move_tail(&urbp->list, &info->pending_unlink_list);
+               COUNT(info->stats.ring_full);
+               timer_action(info, TIMER_RING_WATCHDOG);
+               goto done;
+       }
 
-       return 0;
+       if (!list_empty(&info->pending_unlink_list)) {
+               list_move_tail(&urbp->list, &info->pending_unlink_list);
+               timer_action(info, TIMER_SCAN_PENDING_URBS);
+               goto done;
+       }
+
+       ret = xenhcd_do_request(info, urbp);
+       if (ret == 0)
+               list_move_tail(&urbp->list, &info->in_progress_list);
+
+done:
+       return ret;
 }
 
-static int xenhcd_end_submit_urb(struct usbfront_info *info)
+static int xenhcd_urb_request_done(struct usbfront_info *info)
 {
-       usbif_response_t *ring_res;
+       usbif_urb_response_t *res;
        struct urb *urb;
-       struct urb_priv *urbp;
 
        RING_IDX i, rp;
        uint16_t id;
@@ -354,33 +415,35 @@
        unsigned long flags;
 
        spin_lock_irqsave(&info->lock, flags);
-       rp = info->ring.sring->rsp_prod;
+
+       rp = info->urb_ring.sring->rsp_prod;
        rmb(); /* ensure we see queued responses up to "rp" */
 
-       for (i = info->ring.rsp_cons; i != rp; i++) {
-               ring_res = RING_GET_RESPONSE(&info->ring, i);
-               id = ring_res->id;
-               xenhcd_gnttab_done(&info->shadow[id]);
-               urb = info->shadow[id].urb;
-               barrier();
+       for (i = info->urb_ring.rsp_cons; i != rp; i++) {
+               res = RING_GET_RESPONSE(&info->urb_ring, i);
+               id = res->id;
+
+               if (likely(usbif_pipesubmit(info->shadow[id].req.pipe))) {
+                       xenhcd_gnttab_done(&info->shadow[id]);
+                       urb = info->shadow[id].urb;
+                       barrier();
+                       if (likely(urb)) {
+                               urb->actual_length = res->actual_length;
+                               urb->error_count = res->error_count;
+                               urb->start_frame = res->start_frame;
+                               barrier();
+                               xenhcd_giveback_urb(info, urb, res->status);
+                       }
+               }
+
                add_id_to_freelist(info, id);
+       }
+       info->urb_ring.rsp_cons = i;
 
-               urbp = (struct urb_priv *)urb->hcpriv;
-               if (likely(!urbp->unlinked)) {
-                       urb->status = ring_res->status;
-                       urb->actual_length = ring_res->actual_length;
-                       urb->error_count = ring_res->error_count;
-                       urb->start_frame = ring_res->start_frame;
-               }
-               barrier();
-               xenhcd_giveback_urb(info, urb);
-       }
-       info->ring.rsp_cons = i;
-
-       if (i != info->ring.req_prod_pvt)
-               RING_FINAL_CHECK_FOR_RESPONSES(&info->ring, more_to_do);
+       if (i != info->urb_ring.req_prod_pvt)
+               RING_FINAL_CHECK_FOR_RESPONSES(&info->urb_ring, more_to_do);
        else
-               info->ring.sring->rsp_event = i + 1;
+               info->urb_ring.sring->rsp_event = i + 1;
 
        spin_unlock_irqrestore(&info->lock, flags);
 
@@ -389,6 +452,61 @@
        return more_to_do;
 }
 
+static int xenhcd_conn_notify(struct usbfront_info *info)
+{
+       usbif_conn_response_t *res;
+       usbif_conn_request_t *req;
+       RING_IDX rc, rp;
+       uint16_t id;
+       uint8_t portnum, speed;
+       int more_to_do = 0;
+       int notify;
+       int port_changed = 0;
+       unsigned long flags;
+
+       spin_lock_irqsave(&info->lock, flags);
+
+       rc = info->conn_ring.rsp_cons;
+       rp = info->conn_ring.sring->rsp_prod;
+       rmb(); /* ensure we see queued responses up to "rp" */
+
+       while (rc != rp) {
+               res = RING_GET_RESPONSE(&info->conn_ring, rc);
+               id = res->id;
+               portnum = res->portnum;
+               speed = res->speed;
+               info->conn_ring.rsp_cons = ++rc;
+
+               rhport_connect(info, portnum, speed);
+               if (info->ports[portnum-1].c_connection)
+                       port_changed = 1;
+
+               barrier();
+
+               req = RING_GET_REQUEST(&info->conn_ring, 
info->conn_ring.req_prod_pvt);
+               req->id = id;
+               info->conn_ring.req_prod_pvt++;
+       }
+
+       if (rc != info->conn_ring.req_prod_pvt)
+               RING_FINAL_CHECK_FOR_RESPONSES(&info->conn_ring, more_to_do);
+       else
+               info->conn_ring.sring->rsp_event = rc + 1;
+
+       RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify);
+       if (notify)
+               notify_remote_via_irq(info->irq);
+
+       spin_unlock_irqrestore(&info->lock, flags);
+
+       if (port_changed)
+               usb_hcd_poll_rh_status(info_to_hcd(info));
+
+       cond_resched();
+
+       return more_to_do;
+}
+
 int xenhcd_schedule(void *arg)
 {
        struct usbfront_info *info = (struct usbfront_info *) arg;
@@ -400,7 +518,10 @@
                info->waiting_resp = 0;
                smp_mb();
 
-               if (xenhcd_end_submit_urb(info))
+               if (xenhcd_urb_request_done(info))
+                       info->waiting_resp = 1;
+
+               if (xenhcd_conn_notify(info))
                        info->waiting_resp = 1;
        }
 
diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbfront/usbfront.h
--- a/drivers/xen/usbfront/usbfront.h   Tue Sep 29 11:23:06 2009 +0100
+++ b/drivers/xen/usbfront/usbfront.h   Tue Oct 06 15:18:27 2009 +0900
@@ -66,8 +66,6 @@
 #include "../../usb/core/hcd.h"
 #include "../../usb/core/hub.h"
 
-#define DRIVER_DESC "Xen USB2.0 Virtual Host Controller driver (usbfront)"
-
 static inline struct usbfront_info *hcd_to_info(struct usb_hcd *hcd)
 {
        return (struct usbfront_info *) (hcd->hcd_priv);
@@ -75,17 +73,16 @@
 
 static inline struct usb_hcd *info_to_hcd(struct usbfront_info *info)
 {
-       return container_of ((void *) info, struct usb_hcd, hcd_priv);
+       return container_of((void *) info, struct usb_hcd, hcd_priv);
 }
 
-/*
- * Private per-URB data
- */
+/* Private per-URB data */
 struct urb_priv {
        struct list_head list;
        struct urb *urb;
-       int req_id;     /* RING_REQUEST id */
-       unsigned unlinked:1; /* dequeued urb just marked */
+       int req_id;     /* RING_REQUEST id for submitting */
+       int unlink_req_id; /* RING_REQUEST id for unlinking */
+       unsigned unlinked:1; /* dequeued marker */
 };
 
 /* virtual roothub port status */
@@ -105,7 +102,7 @@
 
 /* RING request shadow */
 struct usb_shadow {
-       usbif_request_t req;
+       usbif_urb_request_t req;
        struct urb *urb;
 };
 
@@ -117,62 +114,46 @@
 };
 
 struct usbfront_info {
-       /*
-        * Virtual Host Controller has 3 queues.
-        *
-        * pending_urbs:
-        *      If xenhcd_urb_enqueue() called in RING_FULL state,
-        *      the enqueued urbs are added to this queue, and waits
-        *      to be sent to the backend.
-        *
-        * inprogress_urbs:
-        *      After xenhcd_urb_enqueue() called and RING_REQUEST sent,
-        *      the urbs are added to this queue and waits for RING_RESPONSE.
-        *
-        * unlinked_urbs:
-        *      When xenhcd_urb_dequeue() called, if the dequeued urb is
-        *      listed in pending_urbs, that urb is moved to this queue
-        *      and waits to be given back to the USB core.
-        */
-       struct list_head pending_urbs;
-       struct list_head inprogress_urbs;
-       struct list_head unlinked_urbs;
+       /* Virtual Host Controller has 4 urb queues */
+       struct list_head pending_submit_list;
+       struct list_head pending_unlink_list;
+       struct list_head in_progress_list;
+       struct list_head giveback_waiting_list;
+
        spinlock_t lock;
 
-       /*
-        * timer function that kick pending_urbs and unlink_urbs.
-        */
+       /* timer that kick pending and giveback waiting urbs */
+       struct timer_list watchdog;
        unsigned long actions;
-       struct timer_list watchdog;
 
-       /*
-        * Virtual roothub:
-        * Emulates the hub ports and the attached devices status.
-        * USB_MAXCHILDREN is defined (16) in include/linux/usb.h
-        */
+       /* virtual root hub */
        int rh_numports;
        struct rhport_status ports[USB_MAXCHILDREN];
        struct vdevice_status devices[USB_MAXCHILDREN];
 
+       /* Xen related staff */
+       struct xenbus_device *xbdev;
+       int urb_ring_ref;
+       int conn_ring_ref;
+       usbif_urb_front_ring_t urb_ring;
+       usbif_conn_front_ring_t conn_ring;
+
+       unsigned int irq; /* event channel */
+       struct usb_shadow shadow[USB_URB_RING_SIZE];
+       unsigned long shadow_free;
+
+       /* RING_RESPONSE thread */
+       struct task_struct *kthread;
+       wait_queue_head_t wq;
+       unsigned int waiting_resp;
+
+       /* xmit statistics */
 #ifdef XENHCD_STATS
        struct xenhcd_stats stats;
 #define COUNT(x) do { (x)++; } while (0)
 #else
 #define COUNT(x) do {} while (0)
 #endif
-
-       /* Xen related staff */
-       struct xenbus_device *xbdev;
-       int ring_ref;
-       usbif_front_ring_t ring;
-       unsigned int irq;
-       struct usb_shadow shadow[USB_RING_SIZE];
-       unsigned long shadow_free;
-
-       /* RING_RESPONSE thread */
-       struct task_struct *kthread;
-       wait_queue_head_t wq;
-       unsigned int waiting_resp;
 };
 
 #define XENHCD_RING_JIFFIES (HZ/200)
@@ -199,7 +180,7 @@
        if (!test_and_set_bit(action, &info->actions)) {
                unsigned long t;
 
-               switch(action) {
+               switch (action) {
                case TIMER_RING_WATCHDOG:
                        t = XENHCD_RING_JIFFIES;
                        break;
@@ -211,6 +192,12 @@
        }
 }
 
+extern struct kmem_cache *xenhcd_urbp_cachep;
+extern struct hc_driver xen_usb20_hc_driver;
+extern struct hc_driver xen_usb11_hc_driver;
 irqreturn_t xenhcd_int(int irq, void *dev_id, struct pt_regs *ptregs);
+void xenhcd_rhport_state_change(struct usbfront_info *info,
+                               int port, enum usb_device_speed speed);
+int xenhcd_schedule(void *arg);
 
 #endif /* __XEN_USBFRONT_H__ */
diff -r 4ac3e1d6605c -r 3be939975ad6 drivers/xen/usbfront/xenbus.c
--- a/drivers/xen/usbfront/xenbus.c     Tue Sep 29 11:23:06 2009 +0100
+++ b/drivers/xen/usbfront/xenbus.c     Tue Oct 06 15:18:27 2009 +0900
@@ -45,50 +45,70 @@
 
 #include "usbfront.h"
 
-extern struct hc_driver usbfront_hc_driver;
-extern struct kmem_cache *xenhcd_urbp_cachep;
-extern void xenhcd_rhport_state_change(struct usbfront_info *info,
-                                       int port, enum usb_device_speed speed);
-extern int xenhcd_schedule(void *arg);
-
 #define GRANT_INVALID_REF 0
 
-static void usbif_free(struct usbfront_info *info)
+static void destroy_rings(struct usbfront_info *info)
 {
-       if (info->ring_ref != GRANT_INVALID_REF) {
-               gnttab_end_foreign_access(info->ring_ref,
-                                         (unsigned long)info->ring.sring);
-               info->ring_ref = GRANT_INVALID_REF;
-               info->ring.sring = NULL;
-       }
        if (info->irq)
                unbind_from_irqhandler(info->irq, info);
        info->irq = 0;
+
+       if (info->urb_ring_ref != GRANT_INVALID_REF) {
+               gnttab_end_foreign_access(info->urb_ring_ref,
+                                         (unsigned long)info->urb_ring.sring);
+               info->urb_ring_ref = GRANT_INVALID_REF;
+       }
+       info->urb_ring.sring = NULL;
+
+       if (info->conn_ring_ref != GRANT_INVALID_REF) {
+               gnttab_end_foreign_access(info->conn_ring_ref,
+                                         (unsigned long)info->conn_ring.sring);
+               info->conn_ring_ref = GRANT_INVALID_REF;
+       }
+       info->conn_ring.sring = NULL;
 }
 
-static int setup_usbring(struct xenbus_device *dev,
+static int setup_rings(struct xenbus_device *dev,
                           struct usbfront_info *info)
 {
-       usbif_sring_t *sring;
+       usbif_urb_sring_t *urb_sring;
+       usbif_conn_sring_t *conn_sring;
        int err;
 
-       info->ring_ref= GRANT_INVALID_REF;
+       info->urb_ring_ref = GRANT_INVALID_REF;
+       info->conn_ring_ref = GRANT_INVALID_REF;
 
-       sring = (usbif_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
-       if (!sring) {
-               xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
+       urb_sring = (usbif_urb_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
+       if (!urb_sring) {
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating urb ring");
                return -ENOMEM;
        }
-       SHARED_RING_INIT(sring);
-       FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE);
+       SHARED_RING_INIT(urb_sring);
+       FRONT_RING_INIT(&info->urb_ring, urb_sring, PAGE_SIZE);
 
-       err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
+       err = xenbus_grant_ring(dev, virt_to_mfn(info->urb_ring.sring));
        if (err < 0) {
-               free_page((unsigned long)sring);
-               info->ring.sring = NULL;
+               free_page((unsigned long)urb_sring);
+               info->urb_ring.sring = NULL;
                goto fail;
        }
-       info->ring_ref = err;
+       info->urb_ring_ref = err;
+
+       conn_sring = (usbif_conn_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
+       if (!conn_sring) {
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating conn ring");
+               return -ENOMEM;
+       }
+       SHARED_RING_INIT(conn_sring);
+       FRONT_RING_INIT(&info->conn_ring, conn_sring, PAGE_SIZE);
+
+       err = xenbus_grant_ring(dev, virt_to_mfn(info->conn_ring.sring));
+       if (err < 0) {
+               free_page((unsigned long)conn_sring);
+               info->conn_ring.sring = NULL;
+               goto fail;
+       }
+       info->conn_ring_ref = err;
 
        err = bind_listening_port_to_irqhandler(
                dev->otherend_id, xenhcd_int, SA_SAMPLE_RANDOM, "usbif", info);
@@ -101,7 +121,7 @@
 
        return 0;
 fail:
-       usbif_free(info);
+       destroy_rings(info);
        return err;
 }
 
@@ -112,7 +132,7 @@
        struct xenbus_transaction xbt;
        int err;
 
-       err = setup_usbring(dev, info);
+       err = setup_rings(dev, info);
        if (err)
                goto out;
 
@@ -123,10 +143,17 @@
                goto destroy_ring;
        }
 
-       err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u",
-                           info->ring_ref);
+       err = xenbus_printf(xbt, dev->nodename, "urb-ring-ref", "%u",
+                           info->urb_ring_ref);
        if (err) {
-               message = "writing ring-ref";
+               message = "writing urb-ring-ref";
+               goto abort_transaction;
+       }
+
+       err = xenbus_printf(xbt, dev->nodename, "conn-ring-ref", "%u",
+                           info->conn_ring_ref);
+       if (err) {
+               message = "writing conn-ring-ref";
                goto abort_transaction;
        }
 
@@ -145,8 +172,6 @@
                goto destroy_ring;
        }
 
-       xenbus_switch_state(dev, XenbusStateInitialised);
-
        return 0;
 
 abort_transaction:
@@ -154,17 +179,45 @@
        xenbus_dev_fatal(dev, err, "%s", message);
 
 destroy_ring:
-       usbif_free(info);
+       destroy_rings(info);
 
 out:
        return err;
 }
 
+static int connect(struct xenbus_device *dev)
+{
+       struct usbfront_info *info = dev->dev.driver_data;
+
+       usbif_conn_request_t *req;
+       int i, idx, err;
+       int notify;
+
+       err = talk_to_backend(dev, info);
+       if (err)
+               return err;
+
+       /* prepare ring for hotplug notification */
+       for (idx = 0, i = 0; i < USB_CONN_RING_SIZE; i++) {
+               req = RING_GET_REQUEST(&info->conn_ring, idx);
+               req->id = idx;
+               idx++;
+       }
+       info->conn_ring.req_prod_pvt = idx;
+
+       RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->conn_ring, notify);
+       if (notify)
+               notify_remote_via_irq(info->irq);
+
+       return 0;
+}
+
 static struct usb_hcd *create_hcd(struct xenbus_device *dev)
 {
        int i;
        int err = 0;
        int num_ports;
+       int usb_ver;
        struct usb_hcd *hcd = NULL;
        struct usbfront_info *info = NULL;
 
@@ -179,20 +232,38 @@
                return ERR_PTR(-EINVAL);
        }
 
-       hcd = usb_create_hcd(&usbfront_hc_driver, &dev->dev, dev->dev.bus_id);
+       err = xenbus_scanf(XBT_NIL, dev->otherend,
+                                       "usb-ver", "%d", &usb_ver);
+       if (err != 1) {
+               xenbus_dev_fatal(dev, err, "reading usb-ver");
+               return ERR_PTR(-EINVAL);
+       }
+       switch (usb_ver) {
+       case USB_VER_USB11:
+               hcd = usb_create_hcd(&xen_usb11_hc_driver, &dev->dev, 
dev->dev.bus_id);
+               break;
+       case USB_VER_USB20:
+               hcd = usb_create_hcd(&xen_usb20_hc_driver, &dev->dev, 
dev->dev.bus_id);
+               break;
+       default:
+               xenbus_dev_fatal(dev, err, "invalid usb-ver");
+               return ERR_PTR(-EINVAL);
+       }
        if (!hcd) {
-               xenbus_dev_fatal(dev, err, "fail to allocate USB host 
controller");
+               xenbus_dev_fatal(dev, err,
+                               "fail to allocate USB host controller");
                return ERR_PTR(-ENOMEM);
        }
+
        info = hcd_to_info(hcd);
        info->xbdev = dev;
        info->rh_numports = num_ports;
 
-       for (i = 0; i < USB_RING_SIZE; i++) {
-               info->shadow[i].req.id = i+1;
+       for (i = 0; i < USB_URB_RING_SIZE; i++) {
+               info->shadow[i].req.id = i + 1;
                info->shadow[i].urb = NULL;
        }
-       info->shadow[USB_RING_SIZE-1].req.id = 0x0fff;
+       info->shadow[USB_URB_RING_SIZE-1].req.id = 0x0fff;
 
        return hcd;
 }
@@ -211,7 +282,8 @@
        hcd = create_hcd(dev);
        if (IS_ERR(hcd)) {
                err = PTR_ERR(hcd);
-               xenbus_dev_fatal(dev, err, "fail to create usb host 
controller");
+               xenbus_dev_fatal(dev, err,
+                               "fail to create usb host controller");
                goto fail;
        }
 
@@ -220,22 +292,19 @@
 
        err = usb_add_hcd(hcd, 0, 0);
        if (err != 0) {
-               xenbus_dev_fatal(dev, err, "fail to adding USB host 
controller");
+               xenbus_dev_fatal(dev, err,
+                               "fail to adding USB host controller");
                goto fail;
        }
 
        init_waitqueue_head(&info->wq);
        snprintf(name, TASK_COMM_LEN, "xenhcd.%d", hcd->self.busnum);
        info->kthread = kthread_run(xenhcd_schedule, info, name);
-        if (IS_ERR(info->kthread)) {
-                err = PTR_ERR(info->kthread);
-                info->kthread = NULL;
-                goto fail;
-        }
-
-       err = talk_to_backend(dev, info);
-       if (err)
+       if (IS_ERR(info->kthread)) {
+               err = PTR_ERR(info->kthread);
+               info->kthread = NULL;
                goto fail;
+       }
 
        return 0;
 
@@ -245,58 +314,41 @@
        return err;
 }
 
-/*
- * 0=disconnected, 1=low_speed, 2=full_speed, 3=high_speed
- */
-static void usbfront_do_hotplug(struct usbfront_info *info)
+static void usbfront_disconnect(struct xenbus_device *dev)
 {
-       char port_str[8];
-       int i;
-       int err;
-       int state;
+       struct usbfront_info *info = dev->dev.driver_data;
+       struct usb_hcd *hcd = info_to_hcd(info);
 
-       for (i = 1; i <= info->rh_numports; i++) {
-               sprintf(port_str, "port-%d", i);
-               err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-                                       port_str, "%d", &state);
-               if (err == 1)
-                       xenhcd_rhport_state_change(info, i, state);
+       usb_remove_hcd(hcd);
+       if (info->kthread) {
+               kthread_stop(info->kthread);
+               info->kthread = NULL;
        }
+       xenbus_frontend_closed(dev);
 }
 
 static void backend_changed(struct xenbus_device *dev,
                                     enum xenbus_state backend_state)
 {
-       struct usbfront_info *info = dev->dev.driver_data;
-
        switch (backend_state) {
        case XenbusStateInitialising:
-       case XenbusStateInitWait:
        case XenbusStateInitialised:
+       case XenbusStateConnected:
+       case XenbusStateReconfiguring:
+       case XenbusStateReconfigured:
        case XenbusStateUnknown:
        case XenbusStateClosed:
                break;
 
-       case XenbusStateConnected:
-               if (dev->state == XenbusStateConnected)
+       case XenbusStateInitWait:
+               if (dev->state != XenbusStateInitialising)
                        break;
-               if (dev->state == XenbusStateInitialised)
-                       usbfront_do_hotplug(info);
+               connect(dev);
                xenbus_switch_state(dev, XenbusStateConnected);
                break;
 
        case XenbusStateClosing:
-               xenbus_frontend_closed(dev);
-               break;
-
-       case XenbusStateReconfiguring:
-               if (dev->state == XenbusStateConnected)
-                       xenbus_switch_state(dev, XenbusStateReconfiguring);
-               break;
-
-       case XenbusStateReconfigured:
-               usbfront_do_hotplug(info);
-               xenbus_switch_state(dev, XenbusStateConnected);
+               usbfront_disconnect(dev);
                break;
 
        default:
@@ -311,12 +363,7 @@
        struct usbfront_info *info = dev->dev.driver_data;
        struct usb_hcd *hcd = info_to_hcd(info);
 
-       usb_remove_hcd(hcd);
-       if (info->kthread) {
-               kthread_stop(info->kthread);
-               info->kthread = NULL;
-       }
-       usbif_free(info);
+       destroy_rings(info);
        usb_put_hcd(hcd);
 
        return 0;
@@ -361,5 +408,5 @@
 module_exit(usbfront_exit);
 
 MODULE_AUTHOR("");
-MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_DESCRIPTION("Xen USB Virtual Host Controller driver (usbfront)");
 MODULE_LICENSE("Dual BSD/GPL");
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.