ia64/xen-unstable
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).
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;