]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/gadget/printer.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
[linux-2.6-omap-h63xx.git] / drivers / usb / gadget / printer.c
index 2c32bd08ee7db2c6051df00de37f709de9041a10..76be75e3ab8fe4a051240b8c37e7f15c8558edba 100644 (file)
@@ -390,9 +390,12 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
 
        /* normal completion */
        case 0:
-               list_add_tail(&req->list, &dev->rx_buffers);
-               wake_up_interruptible(&dev->rx_wait);
-               DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               if (req->actual > 0) {
+                       list_add_tail(&req->list, &dev->rx_buffers);
+                       DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               } else {
+                       list_add(&req->list, &dev->rx_reqs);
+               }
                break;
 
        /* software-driven interface shutdown */
@@ -417,6 +420,8 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                list_add(&req->list, &dev->rx_reqs);
                break;
        }
+
+       wake_up_interruptible(&dev->rx_wait);
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
@@ -494,6 +499,39 @@ printer_close(struct inode *inode, struct file *fd)
        return 0;
 }
 
+/* This function must be called with interrupts turned off. */
+static void
+setup_rx_reqs(struct printer_dev *dev)
+{
+       struct usb_request              *req;
+
+       while (likely(!list_empty(&dev->rx_reqs))) {
+               int error;
+
+               req = container_of(dev->rx_reqs.next,
+                               struct usb_request, list);
+               list_del_init(&req->list);
+
+               /* The USB Host sends us whatever amount of data it wants to
+                * so we always set the length field to the full USB_BUFSIZE.
+                * If the amount of data is more than the read() caller asked
+                * for it will be stored in the request buffer until it is
+                * asked for by read().
+                */
+               req->length = USB_BUFSIZE;
+               req->complete = rx_complete;
+
+               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+               if (error) {
+                       DBG(dev, "rx submit --> %d\n", error);
+                       list_add(&req->list, &dev->rx_reqs);
+                       break;
+               } else {
+                       list_add(&req->list, &dev->rx_reqs_active);
+               }
+       }
+}
+
 static ssize_t
 printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 {
@@ -522,31 +560,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
         */
        dev->reset_printer = 0;
 
-       while (likely(!list_empty(&dev->rx_reqs))) {
-               int error;
-
-               req = container_of(dev->rx_reqs.next,
-                               struct usb_request, list);
-               list_del_init(&req->list);
-
-               /* The USB Host sends us whatever amount of data it wants to
-                * so we always set the length field to the full USB_BUFSIZE.
-                * If the amount of data is more than the read() caller asked
-                * for it will be stored in the request buffer until it is
-                * asked for by read().
-                */
-               req->length = USB_BUFSIZE;
-               req->complete = rx_complete;
-
-               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
-               if (error) {
-                       DBG(dev, "rx submit --> %d\n", error);
-                       list_add(&req->list, &dev->rx_reqs);
-                       break;
-               } else {
-                       list_add(&req->list, &dev->rx_reqs_active);
-               }
-       }
+       setup_rx_reqs(dev);
 
        bytes_copied = 0;
        current_rx_req = dev->current_rx_req;
@@ -615,9 +629,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 
                spin_lock_irqsave(&dev->lock, flags);
 
-               /* We've disconnected or reset free the req and buffer */
+               /* We've disconnected or reset so return. */
                if (dev->reset_printer) {
-                       printer_req_free(dev->out_ep, current_rx_req);
+                       list_add(&current_rx_req->list, &dev->rx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
@@ -735,7 +749,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
                /* We've disconnected or reset so free the req and buffer */
                if (dev->reset_printer) {
-                       printer_req_free(dev->in_ep, req);
+                       list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
@@ -791,6 +805,12 @@ printer_poll(struct file *fd, poll_table *wait)
        unsigned long           flags;
        int                     status = 0;
 
+       spin_lock(&dev->lock_printer_io);
+       spin_lock_irqsave(&dev->lock, flags);
+       setup_rx_reqs(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
+       spin_unlock(&dev->lock_printer_io);
+
        poll_wait(fd, &dev->rx_wait, wait);
        poll_wait(fd, &dev->tx_wait, wait);
 
@@ -798,7 +818,8 @@ printer_poll(struct file *fd, poll_table *wait)
        if (likely(!list_empty(&dev->tx_reqs)))
                status |= POLLOUT | POLLWRNORM;
 
-       if (likely(!list_empty(&dev->rx_buffers)))
+       if (likely(dev->current_rx_bytes) ||
+                       likely(!list_empty(&dev->rx_buffers)))
                status |= POLLIN | POLLRDNORM;
 
        spin_unlock_irqrestore(&dev->lock, flags);
@@ -894,7 +915,7 @@ static void printer_reset_interface(struct printer_dev *dev)
        if (dev->interface < 0)
                return;
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        if (dev->in)
                usb_ep_disable(dev->in_ep);
@@ -1084,6 +1105,7 @@ static void printer_soft_reset(struct printer_dev *dev)
        if (usb_ep_enable(dev->out_ep, dev->out))
                DBG(dev, "Failed to enable USB out_ep\n");
 
+       wake_up_interruptible(&dev->rx_wait);
        wake_up_interruptible(&dev->tx_wait);
        wake_up_interruptible(&dev->tx_flush_wait);
 }
@@ -1262,7 +1284,7 @@ printer_disconnect(struct usb_gadget *gadget)
        struct printer_dev      *dev = get_gadget_data(gadget);
        unsigned long           flags;
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        spin_lock_irqsave(&dev->lock, flags);
 
@@ -1278,7 +1300,7 @@ printer_unbind(struct usb_gadget *gadget)
        struct usb_request      *req;
 
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        /* Remove sysfs files */
        device_destroy(usb_gadget_class, g_printer_devno);