direct-io.hg

changeset 4374:817e74623cf4

bitkeeper revision 1.1236.1.155 (4249ef26A-jDjjXS9NBi965ZbQR7sA)

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).
author mwilli2@equilibrium.research
date Wed Mar 30 00:13:26 2005 +0000 (2005-03-30)
parents 8396f6da60b4
children c3e543f81772
files linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h
line diff
     1.1 --- a/linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c	Tue Mar 29 21:10:08 2005 +0000
     1.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c	Wed Mar 30 00:13:26 2005 +0000
     1.3 @@ -77,6 +77,13 @@ static void __do_suspend(void)
     1.4  #define netif_resume()  do{}while(0)
     1.5  #endif
     1.6  
     1.7 +
     1.8 +#ifdef CONFIG_XEN_USB_FRONTEND
     1.9 +    extern void usbif_resume();
    1.10 +#else
    1.11 +#define usbif_resume() do{}while(0)
    1.12 +#endif
    1.13 +
    1.14      extern void time_suspend(void);
    1.15      extern void time_resume(void);
    1.16      extern unsigned long max_pfn;
    1.17 @@ -145,6 +152,8 @@ static void __do_suspend(void)
    1.18  
    1.19      netif_resume();
    1.20  
    1.21 +    usbif_resume();
    1.22 +
    1.23      __sti();
    1.24  
    1.25   out:
     2.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c	Tue Mar 29 21:10:08 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c	Wed Mar 30 00:13:26 2005 +0000
     2.3 @@ -171,6 +171,8 @@ static void xhci_show_resp(usbif_respons
     2.4   * RING REQUEST HANDLING
     2.5   */
     2.6  
     2.7 +#define RING_PLUGGED(_hc) ( RING_FULL(&_hc->usb_ring) || _hc->recovery )
     2.8 +
     2.9  /**
    2.10   * xhci_construct_isoc - add isochronous information to a request
    2.11   */
    2.12 @@ -216,10 +218,10 @@ static int xhci_queue_req(struct urb *ur
    2.13          
    2.14          spin_lock_irqsave(&xhci->ring_lock, flags);
    2.15  
    2.16 -        if ( RING_FULL(usb_ring) )
    2.17 +        if ( RING_PLUGGED(xhci) )
    2.18          {
    2.19                  printk(KERN_WARNING
    2.20 -                       "xhci_queue_req(): USB ring full, not queuing request\n");
    2.21 +                       "xhci_queue_req(): USB ring plugged, not queuing request\n");
    2.22                  spin_unlock_irqrestore(&xhci->ring_lock, flags);
    2.23                  return -ENOBUFS;
    2.24          }
    2.25 @@ -285,7 +287,7 @@ static inline usbif_request_t *xhci_queu
    2.26          /* This is always called from the timer interrupt. */
    2.27          spin_lock(&xhci->ring_lock);
    2.28         
    2.29 -        if ( RING_FULL(usb_ring) )
    2.30 +        if ( RING_PLUGGED(xhci) )
    2.31          {
    2.32                  printk(KERN_WARNING
    2.33                         "xhci_queue_probe(): ring full, not queuing request\n");
    2.34 @@ -296,7 +298,7 @@ static inline usbif_request_t *xhci_queu
    2.35          /* Stick something in the shared communications ring. */
    2.36          req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
    2.37  
    2.38 -        memset(req, sizeof(*req), 0);
    2.39 +        memset(req, 0, sizeof(*req));
    2.40  
    2.41          req->operation       = USBIF_OP_PROBE;
    2.42          req->port            = port;
    2.43 @@ -322,10 +324,10 @@ static int xhci_port_reset(usbif_vdev_t 
    2.44          /* Only ever happens from process context (hub thread). */
    2.45          spin_lock_irq(&xhci->ring_lock);
    2.46  
    2.47 -        if ( RING_FULL(usb_ring) )
    2.48 +        if ( RING_PLUGGED(xhci) )
    2.49          {
    2.50                  printk(KERN_WARNING
    2.51 -                       "xhci_port_reset(): ring full, not queuing request\n");
    2.52 +                       "xhci_port_reset(): ring plugged, not queuing request\n");
    2.53                  spin_unlock_irq(&xhci->ring_lock);
    2.54                  return -ENOBUFS;
    2.55          }
    2.56 @@ -337,7 +339,7 @@ static int xhci_port_reset(usbif_vdev_t 
    2.57          /* Stick something in the shared communications ring. */
    2.58  	req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
    2.59  
    2.60 -        memset(req, sizeof(*req), 0);
    2.61 +        memset(req, 0, sizeof(*req));
    2.62  
    2.63          req->operation       = USBIF_OP_RESET;
    2.64          req->port            = port;
    2.65 @@ -377,7 +379,7 @@ static void receive_usb_probe(usbif_resp
    2.66  {
    2.67      spin_lock(&xhci->rh.port_state_lock);
    2.68  
    2.69 -    if ( resp->status > 0 )
    2.70 +    if ( resp->status >= 0 )
    2.71      {
    2.72          if ( resp->status == 1 )
    2.73          {
    2.74 @@ -386,10 +388,20 @@ static void receive_usb_probe(usbif_resp
    2.75              if( xhci->rh.ports[resp->data].cs == 0 )
    2.76  	    {
    2.77                  xhci->rh.ports[resp->data].cs = 1;
    2.78 -                xhci->rh.ports[resp->data].ccs = 1;
    2.79                  xhci->rh.ports[resp->data].cs_chg = 1;
    2.80  	    }
    2.81          }
    2.82 +        else if ( resp->status == 0 )
    2.83 +        {
    2.84 +            if(xhci->rh.ports[resp->data].cs == 1 )
    2.85 +            {
    2.86 +                xhci->rh.ports[resp->data].cs  = 0;
    2.87 +                xhci->rh.ports[resp->data].cs_chg = 1;
    2.88 +		xhci->rh.ports[resp->data].pe = 0;
    2.89 +		/* According to USB Spec v2.0, 11.24.2.7.2.2, we don't need
    2.90 +		 * to set pe_chg since an error has not occurred. */
    2.91 +            }
    2.92 +        }
    2.93          else
    2.94              printk(KERN_WARNING "receive_usb_probe(): unexpected status %d "
    2.95                     "for port %d\n", resp->status, resp->data);
    2.96 @@ -1283,10 +1295,9 @@ static int rh_submit_urb(struct urb *urb
    2.97  		cstatus = (status->cs_chg) |
    2.98  			(status->pe_chg << 1) |
    2.99  			(xhci->rh.c_p_r[wIndex - 1] << 4);
   2.100 -		retstatus = (status->ccs) |
   2.101 +		retstatus = (status->cs) |
   2.102  			(status->pe << 1) |
   2.103  			(status->susp << 2) |
   2.104 -			(status->pr << 8) |
   2.105  			(1 << 8) |      /* power on */
   2.106  			(status->lsda << 9);
   2.107  		*(__u16 *)data = cpu_to_le16(retstatus);
   2.108 @@ -1520,6 +1531,19 @@ static void usbif_status_change(usbif_fe
   2.109              break;
   2.110              /* Not bothering to do recovery here for now.  Keep things
   2.111               * simple. */
   2.112 +
   2.113 +            spin_lock_irq(&xhci->ring_lock);
   2.114 +            
   2.115 +            /* Clean up resources. */
   2.116 +            free_page((unsigned long)xhci->usb_ring.sring);
   2.117 +            free_irq(xhci->irq, xhci);
   2.118 +            unbind_evtchn_from_irq(xhci->evtchn);
   2.119 +
   2.120 +            /* Plug the ring. */
   2.121 +            xhci->recovery = 1;
   2.122 +            wmb();
   2.123 +            
   2.124 +            spin_unlock_irq(&xhci->ring_lock);
   2.125          }
   2.126  
   2.127          /* Move from CLOSED to DISCONNECTED state. */
   2.128 @@ -1624,12 +1648,40 @@ static void usbif_ctrlif_rx(ctrl_msg_t *
   2.129      ctrl_if_send_response(msg);
   2.130  }
   2.131  
   2.132 +static void send_driver_up(void)
   2.133 +{
   2.134 +        control_msg_t cmsg;
   2.135 +        usbif_fe_interface_status_changed_t st;
   2.136 +
   2.137 +        /* Send a driver-UP notification to the domain controller. */
   2.138 +        cmsg.type      = CMSG_USBIF_FE;
   2.139 +        cmsg.subtype   = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
   2.140 +        cmsg.length    = sizeof(usbif_fe_driver_status_changed_t);
   2.141 +        st.status      = USBIF_DRIVER_STATUS_UP;
   2.142 +        memcpy(cmsg.msg, &st, sizeof(st));
   2.143 +        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   2.144 +}
   2.145 +
   2.146 +void usbif_resume(void)
   2.147 +{
   2.148 +        int i;
   2.149 +        
   2.150 +        /* Fake disconnection on all virtual USB ports (suspending / migrating
   2.151 +         * will destroy hard state associated will the USB devices anyhow). */
   2.152 +        /* No need to lock here. */
   2.153 +        for ( i = 0; i < xhci->rh.numports; i++ )
   2.154 +        {
   2.155 +                xhci->rh.ports[i].cs = 0;
   2.156 +                xhci->rh.ports[i].cs_chg = 1;
   2.157 +		xhci->rh.ports[i].pe = 0;
   2.158 +        }
   2.159 +        
   2.160 +        send_driver_up();
   2.161 +}
   2.162  
   2.163  static int __init xhci_hcd_init(void)
   2.164  {
   2.165  	int retval = -ENOMEM, i;
   2.166 -        usbif_fe_interface_status_changed_t st;
   2.167 -        control_msg_t cmsg;
   2.168  
   2.169  	if ( (xen_start_info.flags & SIF_INITDOMAIN)
   2.170  	     || (xen_start_info.flags & SIF_USB_BE_DOMAIN) )
   2.171 @@ -1658,14 +1710,8 @@ static int __init xhci_hcd_init(void)
   2.172          
   2.173  	alloc_xhci();
   2.174  
   2.175 -        /* Send a driver-UP notification to the domain controller. */
   2.176 -        cmsg.type      = CMSG_USBIF_FE;
   2.177 -        cmsg.subtype   = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
   2.178 -        cmsg.length    = sizeof(usbif_fe_driver_status_changed_t);
   2.179 -        st.status      = USBIF_DRIVER_STATUS_UP;
   2.180 -        memcpy(cmsg.msg, &st, sizeof(st));
   2.181 -        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   2.182 -        
   2.183 +        send_driver_up();
   2.184 +
   2.185          /*
   2.186           * We should read 'nr_interfaces' from response message and wait
   2.187           * for notifications before proceeding. For now we assume that we
     3.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h	Tue Mar 29 21:10:08 2005 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h	Wed Mar 30 00:13:26 2005 +0000
     3.3 @@ -20,11 +20,10 @@
     3.4  
     3.5  /* xhci_port_t - current known state of a virtual hub ports */
     3.6  typedef struct {
     3.7 -        unsigned int cs     :1; /* Connection status.  do we really need this /and/ ccs? */
     3.8 +        unsigned int cs     :1; /* Connection status.         */
     3.9          unsigned int cs_chg :1; /* Connection status change.  */
    3.10          unsigned int pe     :1; /* Port enable.               */
    3.11          unsigned int pe_chg :1; /* Port enable change.        */
    3.12 -        unsigned int ccs    :1; /* Current connect status.    */
    3.13          unsigned int susp   :1; /* Suspended.                 */
    3.14          unsigned int lsda   :1; /* Low speed device attached. */
    3.15          unsigned int pr     :1; /* Port reset.                */
    3.16 @@ -56,10 +55,13 @@ struct xhci {
    3.17  
    3.18          int evtchn;                        /* Interdom channel to backend */
    3.19          int irq;                           /* Bound to evtchn */
    3.20 -        enum { USBIF_STATE_CONNECTED    = 2,
    3.21 -               USBIF_STATE_DISCONNECTED = 1,
    3.22 -               USBIF_STATE_CLOSED       = 0
    3.23 +        enum { 
    3.24 +                USBIF_STATE_CONNECTED    = 2,
    3.25 +                USBIF_STATE_DISCONNECTED = 1,
    3.26 +                USBIF_STATE_CLOSED       = 0
    3.27          } state; /* State of this USB interface */
    3.28 +        unsigned long recovery; /* boolean recovery in progress flag */
    3.29 +        
    3.30          unsigned long bandwidth;
    3.31  
    3.32  	struct usb_bus *bus;