aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/message.c41
-rw-r--r--drivers/usb/core/quirks.c22
2 files changed, 49 insertions, 14 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 25f63f1096b..b6bd05e3d43 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -18,9 +18,17 @@
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
+struct api_context {
+ struct completion done;
+ int status;
+};
+
static void usb_api_blocking_completion(struct urb *urb)
{
- complete((struct completion *)urb->context);
+ struct api_context *ctx = urb->context;
+
+ ctx->status = urb->status;
+ complete(&ctx->done);
}
@@ -32,20 +40,21 @@ static void usb_api_blocking_completion(struct urb *urb)
*/
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
{
- struct completion done;
+ struct api_context ctx;
unsigned long expire;
int retval;
- int status = urb->status;
- init_completion(&done);
- urb->context = &done;
+ init_completion(&ctx.done);
+ urb->context = &ctx;
urb->actual_length = 0;
retval = usb_submit_urb(urb, GFP_NOIO);
if (unlikely(retval))
goto out;
expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
- if (!wait_for_completion_timeout(&done, expire)) {
+ if (!wait_for_completion_timeout(&ctx.done, expire)) {
+ usb_kill_urb(urb);
+ retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
@@ -54,11 +63,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length);
-
- usb_kill_urb(urb);
- retval = status == -ENOENT ? -ETIMEDOUT : status;
} else
- retval = status;
+ retval = ctx.status;
out:
if (actual_length)
*actual_length = urb->actual_length;
@@ -411,15 +417,22 @@ int usb_sg_init (
* Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible. However this can only
- * work on systems without HIGHMEM, since DMA buffers located
- * in high memory are not directly addressable by the CPU for
- * PIO ... so when HIGHMEM is in use, transfer_buffer is NULL
+ * work on systems without:
+ *
+ * - HIGHMEM, since DMA buffers located in high memory are
+ * not directly addressable by the CPU for PIO;
+ *
+ * - IOMMU, since dma_map_sg() is allowed to use an IOMMU to
+ * make virtually discontiguous buffers be "dma-contiguous"
+ * so that PIO and DMA need diferent numbers of URBs.
+ *
+ * So when HIGHMEM or IOMMU are in use, transfer_buffer is NULL
* to prevent stale pointers and to help spot bugs.
*/
if (dma) {
io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
len = sg_dma_len (sg + i);
-#ifdef CONFIG_HIGHMEM
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)
io->urbs[i]->transfer_buffer = NULL;
#else
io->urbs[i]->transfer_buffer =
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index aa21b38a31c..b7917c5a3c6 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -30,18 +30,40 @@
static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
+ /* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
+ { USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Benq S2W 3300U */
{ USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Canon, Inc. CanoScan N1240U/LiDE30 */
+ { USB_DEVICE(0x04a9, 0x220e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Canon, Inc. CanoScan N650U/N656U */
+ { USB_DEVICE(0x04a9, 0x2206), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Canon, Inc. CanoScan 1220U */
+ { USB_DEVICE(0x04a9, 0x2207), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Canon, Inc. CanoScan N670U/N676U/LiDE 20 */
+ { USB_DEVICE(0x04a9, 0x220d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* old Cannon scanner */
+ { USB_DEVICE(0x04a9, 0x2220), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp. Perfection 1200 */
{ USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Seiko Epson Corp. Perfection 660 */
+ { USB_DEVICE(0x04b8, 0x0114), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Epson Perfection 1260 Photo */
+ { USB_DEVICE(0x04b8, 0x011d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp - Perfection 1670 */
{ USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* EPSON Perfection 2480 */
+ { USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Seiko Epson Corp.*/
+ { USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Samsung ML-2510 Series printer */
{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Elsa MicroLink 56k (V.250) */
{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Ultima Electronics Corp.*/
{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
+ /* Agfa Snapscan1212u */
+ { USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Umax [hex] Astra 3400U */
{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },