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

[Xen-changelog] Various bug fixes (thanks to Harry Butterworth for spotting these), including



ChangeSet 1.1391, 2005/03/30 00:13:26+00:00, mwilli2@xxxxxxxxxxxxxxxxxxxx

        Various bug fixes (thanks to Harry Butterworth for spotting these), 
including
        making disconnects behave correctly.  Hotplug seems to work well now.
        
        Also: experimental support for handling suspend / migration gracefully 
(can't
        test this until it works in the rest of the -unstable tree).



 arch/xen/kernel/reboot.c        |    9 ++++
 drivers/xen/usbfront/usbfront.c |   88 ++++++++++++++++++++++++++++++----------
 drivers/xen/usbfront/xhci.h     |   12 +++--
 3 files changed, 83 insertions(+), 26 deletions(-)


diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c 
b/linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c  2005-03-29 20:02:27 
-05:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c  2005-03-29 20:02:27 
-05:00
@@ -77,6 +77,13 @@
 #define netif_resume()  do{}while(0)
 #endif
 
+
+#ifdef CONFIG_XEN_USB_FRONTEND
+    extern void usbif_resume();
+#else
+#define usbif_resume() do{}while(0)
+#endif
+
     extern void time_suspend(void);
     extern void time_resume(void);
     extern unsigned long max_pfn;
@@ -144,6 +151,8 @@
     blkdev_resume();
 
     netif_resume();
+
+    usbif_resume();
 
     __sti();
 
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c 
b/linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c
--- a/linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c   2005-03-29 
20:02:27 -05:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c   2005-03-29 
20:02:27 -05:00
@@ -171,6 +171,8 @@
  * RING REQUEST HANDLING
  */
 
+#define RING_PLUGGED(_hc) ( RING_FULL(&_hc->usb_ring) || _hc->recovery )
+
 /**
  * xhci_construct_isoc - add isochronous information to a request
  */
@@ -216,10 +218,10 @@
         
         spin_lock_irqsave(&xhci->ring_lock, flags);
 
-        if ( RING_FULL(usb_ring) )
+        if ( RING_PLUGGED(xhci) )
         {
                 printk(KERN_WARNING
-                       "xhci_queue_req(): USB ring full, not queuing 
request\n");
+                       "xhci_queue_req(): USB ring plugged, not queuing 
request\n");
                 spin_unlock_irqrestore(&xhci->ring_lock, flags);
                 return -ENOBUFS;
         }
@@ -285,7 +287,7 @@
         /* This is always called from the timer interrupt. */
         spin_lock(&xhci->ring_lock);
        
-        if ( RING_FULL(usb_ring) )
+        if ( RING_PLUGGED(xhci) )
         {
                 printk(KERN_WARNING
                        "xhci_queue_probe(): ring full, not queuing request\n");
@@ -296,7 +298,7 @@
         /* Stick something in the shared communications ring. */
         req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
 
-        memset(req, sizeof(*req), 0);
+        memset(req, 0, sizeof(*req));
 
         req->operation       = USBIF_OP_PROBE;
         req->port            = port;
@@ -322,10 +324,10 @@
         /* Only ever happens from process context (hub thread). */
         spin_lock_irq(&xhci->ring_lock);
 
-        if ( RING_FULL(usb_ring) )
+        if ( RING_PLUGGED(xhci) )
         {
                 printk(KERN_WARNING
-                       "xhci_port_reset(): ring full, not queuing request\n");
+                       "xhci_port_reset(): ring plugged, not queuing 
request\n");
                 spin_unlock_irq(&xhci->ring_lock);
                 return -ENOBUFS;
         }
@@ -337,7 +339,7 @@
         /* Stick something in the shared communications ring. */
        req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
 
-        memset(req, sizeof(*req), 0);
+        memset(req, 0, sizeof(*req));
 
         req->operation       = USBIF_OP_RESET;
         req->port            = port;
@@ -377,7 +379,7 @@
 {
     spin_lock(&xhci->rh.port_state_lock);
 
-    if ( resp->status > 0 )
+    if ( resp->status >= 0 )
     {
         if ( resp->status == 1 )
         {
@@ -386,10 +388,20 @@
             if( xhci->rh.ports[resp->data].cs == 0 )
            {
                 xhci->rh.ports[resp->data].cs = 1;
-                xhci->rh.ports[resp->data].ccs = 1;
                 xhci->rh.ports[resp->data].cs_chg = 1;
            }
         }
+        else if ( resp->status == 0 )
+        {
+            if(xhci->rh.ports[resp->data].cs == 1 )
+            {
+                xhci->rh.ports[resp->data].cs  = 0;
+                xhci->rh.ports[resp->data].cs_chg = 1;
+               xhci->rh.ports[resp->data].pe = 0;
+               /* According to USB Spec v2.0, 11.24.2.7.2.2, we don't need
+                * to set pe_chg since an error has not occurred. */
+            }
+        }
         else
             printk(KERN_WARNING "receive_usb_probe(): unexpected status %d "
                    "for port %d\n", resp->status, resp->data);
@@ -1283,10 +1295,9 @@
                cstatus = (status->cs_chg) |
                        (status->pe_chg << 1) |
                        (xhci->rh.c_p_r[wIndex - 1] << 4);
-               retstatus = (status->ccs) |
+               retstatus = (status->cs) |
                        (status->pe << 1) |
                        (status->susp << 2) |
-                       (status->pr << 8) |
                        (1 << 8) |      /* power on */
                        (status->lsda << 9);
                *(__u16 *)data = cpu_to_le16(retstatus);
@@ -1520,6 +1531,19 @@
             break;
             /* Not bothering to do recovery here for now.  Keep things
              * simple. */
+
+            spin_lock_irq(&xhci->ring_lock);
+            
+            /* Clean up resources. */
+            free_page((unsigned long)xhci->usb_ring.sring);
+            free_irq(xhci->irq, xhci);
+            unbind_evtchn_from_irq(xhci->evtchn);
+
+            /* Plug the ring. */
+            xhci->recovery = 1;
+            wmb();
+            
+            spin_unlock_irq(&xhci->ring_lock);
         }
 
         /* Move from CLOSED to DISCONNECTED state. */
@@ -1624,12 +1648,40 @@
     ctrl_if_send_response(msg);
 }
 
+static void send_driver_up(void)
+{
+        control_msg_t cmsg;
+        usbif_fe_interface_status_changed_t st;
+
+        /* Send a driver-UP notification to the domain controller. */
+        cmsg.type      = CMSG_USBIF_FE;
+        cmsg.subtype   = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
+        cmsg.length    = sizeof(usbif_fe_driver_status_changed_t);
+        st.status      = USBIF_DRIVER_STATUS_UP;
+        memcpy(cmsg.msg, &st, sizeof(st));
+        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
+}
+
+void usbif_resume(void)
+{
+        int i;
+        
+        /* Fake disconnection on all virtual USB ports (suspending / migrating
+         * will destroy hard state associated will the USB devices anyhow). */
+        /* No need to lock here. */
+        for ( i = 0; i < xhci->rh.numports; i++ )
+        {
+                xhci->rh.ports[i].cs = 0;
+                xhci->rh.ports[i].cs_chg = 1;
+               xhci->rh.ports[i].pe = 0;
+        }
+        
+        send_driver_up();
+}
 
 static int __init xhci_hcd_init(void)
 {
        int retval = -ENOMEM, i;
-        usbif_fe_interface_status_changed_t st;
-        control_msg_t cmsg;
 
        if ( (xen_start_info.flags & SIF_INITDOMAIN)
             || (xen_start_info.flags & SIF_USB_BE_DOMAIN) )
@@ -1658,14 +1710,8 @@
         
        alloc_xhci();
 
-        /* Send a driver-UP notification to the domain controller. */
-        cmsg.type      = CMSG_USBIF_FE;
-        cmsg.subtype   = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
-        cmsg.length    = sizeof(usbif_fe_driver_status_changed_t);
-        st.status      = USBIF_DRIVER_STATUS_UP;
-        memcpy(cmsg.msg, &st, sizeof(st));
-        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-        
+        send_driver_up();
+
         /*
          * We should read 'nr_interfaces' from response message and wait
          * for notifications before proceeding. For now we assume that we
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h 
b/linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h
--- a/linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h       2005-03-29 
20:02:27 -05:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h       2005-03-29 
20:02:27 -05:00
@@ -20,11 +20,10 @@
 
 /* xhci_port_t - current known state of a virtual hub ports */
 typedef struct {
-        unsigned int cs     :1; /* Connection status.  do we really need this 
/and/ ccs? */
+        unsigned int cs     :1; /* Connection status.         */
         unsigned int cs_chg :1; /* Connection status change.  */
         unsigned int pe     :1; /* Port enable.               */
         unsigned int pe_chg :1; /* Port enable change.        */
-        unsigned int ccs    :1; /* Current connect status.    */
         unsigned int susp   :1; /* Suspended.                 */
         unsigned int lsda   :1; /* Low speed device attached. */
         unsigned int pr     :1; /* Port reset.                */
@@ -56,10 +55,13 @@
 
         int evtchn;                        /* Interdom channel to backend */
         int irq;                           /* Bound to evtchn */
-        enum { USBIF_STATE_CONNECTED    = 2,
-               USBIF_STATE_DISCONNECTED = 1,
-               USBIF_STATE_CLOSED       = 0
+        enum { 
+                USBIF_STATE_CONNECTED    = 2,
+                USBIF_STATE_DISCONNECTED = 1,
+                USBIF_STATE_CLOSED       = 0
         } state; /* State of this USB interface */
+        unsigned long recovery; /* boolean recovery in progress flag */
+        
         unsigned long bandwidth;
 
        struct usb_bus *bus;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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