[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |