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>
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;