/* 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 */
                list_add(&req->list, &dev->rx_reqs);
                break;
        }
+
+       wake_up_interruptible(&dev->rx_wait);
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
        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)
 {
         */
        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;
 
                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(¤t_rx_req->list, &dev->rx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
 
                /* 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;
        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);
 
        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);
        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);
 }