ChangeSet 1.1307.2.1, 2005/03/10 16:17:58+00:00, mwilli2@xxxxxxxxxxxxxxxxxxxx
Fix malloc / ring full checking (thanks to Harry Butterworth for
spotting these).
Add more locking (fixes a potential race on 2.4, also needed for safety
now we
can do SMP).
Signed-off-by: <mark.williamson@xxxxxxxxxxxx>
usbfront.c | 38 ++++++++++++++++++++++++++++++++++++--
xhci.h | 1 +
2 files changed, 37 insertions(+), 2 deletions(-)
diff -Nru a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c
b/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c
--- a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c 2005-03-18
05:03:42 -05:00
+++ b/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c 2005-03-18
05:03:42 -05:00
@@ -203,6 +203,7 @@
*/
static int xhci_queue_req(struct urb *urb)
{
+ unsigned long flags;
usbif_request_t *req;
usbif_front_ring_t *usb_ring = &xhci->usb_ring;
@@ -213,11 +214,13 @@
usbif->resp_prod, xhci->usb_resp_cons);
#endif
+ spin_lock_irqsave(&xhci->ring_lock, flags);
if ( RING_FULL(usb_ring) )
{
printk(KERN_WARNING
"xhci_queue_req(): USB ring full, not queuing
request\n");
+ spin_unlock_irqrestore(&xhci->ring_lock, flags);
return -ENOBUFS;
}
@@ -253,6 +256,8 @@
usb_ring->req_prod_pvt++;
RING_PUSH_REQUESTS(usb_ring);
+ spin_unlock_irqrestore(&xhci->ring_lock, flags);
+
notify_via_evtchn(xhci->evtchn);
DPRINTK("Queued request for an URB.\n");
@@ -276,11 +281,15 @@
virt_to_machine(&usbif->req_prod),
usbif->resp_prod, xhci->usb_resp_cons);
#endif
-
+
+ /* This is always called from the timer interrupt. */
+ spin_lock(&xhci->ring_lock);
+
if ( RING_FULL(usb_ring) )
{
printk(KERN_WARNING
"xhci_queue_probe(): ring full, not queuing request\n");
+ spin_unlock(&xhci->ring_lock);
return NULL;
}
@@ -295,6 +304,8 @@
usb_ring->req_prod_pvt++;
RING_PUSH_REQUESTS(usb_ring);
+ spin_unlock(&xhci->ring_lock);
+
notify_via_evtchn(xhci->evtchn);
return req;
@@ -308,6 +319,17 @@
usbif_request_t *req;
usbif_front_ring_t *usb_ring = &xhci->usb_ring;
+ /* Only ever happens from process context (hub thread). */
+ spin_lock_irq(&xhci->ring_lock);
+
+ if ( RING_FULL(usb_ring) )
+ {
+ printk(KERN_WARNING
+ "xhci_port_reset(): ring full, not queuing request\n");
+ spin_unlock_irq(&xhci->ring_lock);
+ return -ENOBUFS;
+ }
+
/* We only reset one port at a time, so we only need one variable per
* hub. */
xhci->awaiting_reset = 1;
@@ -323,6 +345,8 @@
usb_ring->req_prod_pvt++;
RING_PUSH_REQUESTS(usb_ring);
+ spin_unlock_irq(&xhci->ring_lock);
+
notify_via_evtchn(xhci->evtchn);
while ( xhci->awaiting_reset > 0 )
@@ -1529,6 +1553,10 @@
xhci->rh.numports = status->num_ports;
xhci->rh.ports = kmalloc (sizeof(xhci_port_t) * xhci->rh.numports,
GFP_KERNEL);
+
+ if ( xhci->rh.ports == NULL )
+ goto alloc_ports_nomem;
+
memset(xhci->rh.ports, 0, sizeof(xhci_port_t) * xhci->rh.numports);
usb_connect(xhci->rh.dev);
@@ -1553,7 +1581,7 @@
xhci->evtchn, xhci->irq);
xhci->state = USBIF_STATE_CONNECTED;
-
+
break;
default:
@@ -1561,6 +1589,12 @@
status->status);
break;
}
+
+ return;
+
+ alloc_ports_nomem:
+ printk(KERN_WARNING "Failed to allocate port memory, XHCI failed to
connect.\n");
+ return;
}
/**
diff -Nru a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h
b/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h
--- a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h 2005-03-18
05:03:42 -05:00
+++ b/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h 2005-03-18
05:03:42 -05:00
@@ -74,6 +74,7 @@
struct virt_root_hub rh; /* private data of the virtual root hub
*/
+ spinlock_t ring_lock;
usbif_front_ring_t usb_ring;
int awaiting_reset;
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/xen-changelog
|