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
|