ia64/xen-unstable
changeset 4077:4baf30dc2398
bitkeeper revision 1.1236.24.1 (42307336-2YsfyDrGECB7J1MGcn3zg)
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@cl.cam.ac.uk>
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@cl.cam.ac.uk>
author | mwilli2@equilibrium.research |
---|---|
date | Thu Mar 10 16:17:58 2005 +0000 (2005-03-10) |
parents | 254b6cc19f34 |
children | c5afd0448d79 |
files | linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h |
line diff
1.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c Thu Mar 10 02:20:43 2005 +0000 1.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c Thu Mar 10 16:17:58 2005 +0000 1.3 @@ -203,6 +203,7 @@ static int xhci_construct_isoc(usbif_req 1.4 */ 1.5 static int xhci_queue_req(struct urb *urb) 1.6 { 1.7 + unsigned long flags; 1.8 usbif_request_t *req; 1.9 usbif_front_ring_t *usb_ring = &xhci->usb_ring; 1.10 1.11 @@ -213,11 +214,13 @@ static int xhci_queue_req(struct urb *ur 1.12 usbif->resp_prod, xhci->usb_resp_cons); 1.13 #endif 1.14 1.15 + spin_lock_irqsave(&xhci->ring_lock, flags); 1.16 1.17 if ( RING_FULL(usb_ring) ) 1.18 { 1.19 printk(KERN_WARNING 1.20 "xhci_queue_req(): USB ring full, not queuing request\n"); 1.21 + spin_unlock_irqrestore(&xhci->ring_lock, flags); 1.22 return -ENOBUFS; 1.23 } 1.24 1.25 @@ -253,6 +256,8 @@ static int xhci_queue_req(struct urb *ur 1.26 usb_ring->req_prod_pvt++; 1.27 RING_PUSH_REQUESTS(usb_ring); 1.28 1.29 + spin_unlock_irqrestore(&xhci->ring_lock, flags); 1.30 + 1.31 notify_via_evtchn(xhci->evtchn); 1.32 1.33 DPRINTK("Queued request for an URB.\n"); 1.34 @@ -276,11 +281,15 @@ static inline usbif_request_t *xhci_queu 1.35 virt_to_machine(&usbif->req_prod), 1.36 usbif->resp_prod, xhci->usb_resp_cons); 1.37 #endif 1.38 - 1.39 + 1.40 + /* This is always called from the timer interrupt. */ 1.41 + spin_lock(&xhci->ring_lock); 1.42 + 1.43 if ( RING_FULL(usb_ring) ) 1.44 { 1.45 printk(KERN_WARNING 1.46 "xhci_queue_probe(): ring full, not queuing request\n"); 1.47 + spin_unlock(&xhci->ring_lock); 1.48 return NULL; 1.49 } 1.50 1.51 @@ -295,6 +304,8 @@ static inline usbif_request_t *xhci_queu 1.52 usb_ring->req_prod_pvt++; 1.53 RING_PUSH_REQUESTS(usb_ring); 1.54 1.55 + spin_unlock(&xhci->ring_lock); 1.56 + 1.57 notify_via_evtchn(xhci->evtchn); 1.58 1.59 return req; 1.60 @@ -308,6 +319,17 @@ static int xhci_port_reset(usbif_vdev_t 1.61 usbif_request_t *req; 1.62 usbif_front_ring_t *usb_ring = &xhci->usb_ring; 1.63 1.64 + /* Only ever happens from process context (hub thread). */ 1.65 + spin_lock_irq(&xhci->ring_lock); 1.66 + 1.67 + if ( RING_FULL(usb_ring) ) 1.68 + { 1.69 + printk(KERN_WARNING 1.70 + "xhci_port_reset(): ring full, not queuing request\n"); 1.71 + spin_unlock_irq(&xhci->ring_lock); 1.72 + return -ENOBUFS; 1.73 + } 1.74 + 1.75 /* We only reset one port at a time, so we only need one variable per 1.76 * hub. */ 1.77 xhci->awaiting_reset = 1; 1.78 @@ -323,6 +345,8 @@ static int xhci_port_reset(usbif_vdev_t 1.79 usb_ring->req_prod_pvt++; 1.80 RING_PUSH_REQUESTS(usb_ring); 1.81 1.82 + spin_unlock_irq(&xhci->ring_lock); 1.83 + 1.84 notify_via_evtchn(xhci->evtchn); 1.85 1.86 while ( xhci->awaiting_reset > 0 ) 1.87 @@ -1529,6 +1553,10 @@ static void usbif_status_change(usbif_fe 1.88 xhci->rh.numports = status->num_ports; 1.89 1.90 xhci->rh.ports = kmalloc (sizeof(xhci_port_t) * xhci->rh.numports, GFP_KERNEL); 1.91 + 1.92 + if ( xhci->rh.ports == NULL ) 1.93 + goto alloc_ports_nomem; 1.94 + 1.95 memset(xhci->rh.ports, 0, sizeof(xhci_port_t) * xhci->rh.numports); 1.96 1.97 usb_connect(xhci->rh.dev); 1.98 @@ -1553,7 +1581,7 @@ static void usbif_status_change(usbif_fe 1.99 xhci->evtchn, xhci->irq); 1.100 1.101 xhci->state = USBIF_STATE_CONNECTED; 1.102 - 1.103 + 1.104 break; 1.105 1.106 default: 1.107 @@ -1561,6 +1589,12 @@ static void usbif_status_change(usbif_fe 1.108 status->status); 1.109 break; 1.110 } 1.111 + 1.112 + return; 1.113 + 1.114 + alloc_ports_nomem: 1.115 + printk(KERN_WARNING "Failed to allocate port memory, XHCI failed to connect.\n"); 1.116 + return; 1.117 } 1.118 1.119 /**
2.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h Thu Mar 10 02:20:43 2005 +0000 2.2 +++ b/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h Thu Mar 10 16:17:58 2005 +0000 2.3 @@ -74,6 +74,7 @@ struct xhci { 2.4 2.5 struct virt_root_hub rh; /* private data of the virtual root hub */ 2.6 2.7 + spinlock_t ring_lock; 2.8 usbif_front_ring_t usb_ring; 2.9 2.10 int awaiting_reset;