diff options
Diffstat (limited to 'drivers/usb')
31 files changed, 262 insertions, 230 deletions
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 7580aa5da0f8..7a6499008b89 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -33,6 +33,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_LH7A404 default y if ARCH_S3C2410 default y if PXA27x + default y if PXA3xx default y if ARCH_EP93XX default y if ARCH_AT91 default y if ARCH_PNX4008 diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index c51f8e9312e0..7c3aaa9c5402 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -91,8 +91,8 @@ static int usb_create_newid_file(struct usb_driver *usb_drv) goto exit; if (usb_drv->probe != NULL) - error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj, - &driver_attr_new_id.attr); + error = driver_create_file(&usb_drv->drvwrap.driver, + &driver_attr_new_id); exit: return error; } @@ -103,8 +103,8 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv) return; if (usb_drv->probe != NULL) - sysfs_remove_file(&usb_drv->drvwrap.driver.kobj, - &driver_attr_new_id.attr); + driver_remove_file(&usb_drv->drvwrap.driver, + &driver_attr_new_id); } static void usb_free_dynids(struct usb_driver *usb_drv) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 5cf6d5f9acbd..3fb9af80cbf4 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -125,7 +125,7 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) pci_set_master (dev); - retval = usb_add_hcd (hcd, dev->irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; return retval; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 13b326a13377..b04d232d4c65 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -522,9 +522,9 @@ static void hub_quiesce(struct usb_hub *hub) /* (blocking) stop khubd and related activity */ usb_kill_urb(hub->urb); if (hub->has_indicators) - cancel_delayed_work(&hub->leds); - if (hub->has_indicators || hub->tt.hub) - flush_scheduled_work(); + cancel_delayed_work_sync(&hub->leds); + if (hub->tt.hub) + cancel_work_sync(&hub->tt.kevent); } static void hub_activate(struct usb_hub *hub) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index f81d08d6538b..77a3759d6fc7 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -308,7 +308,7 @@ config USB_S3C2410_DEBUG config USB_GADGET_AT91 boolean "AT91 USB Device Port" - depends on ARCH_AT91 && !ARCH_AT91SAM9RL + depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 select USB_GADGET_SELECTED help Many Atmel AT91 processors (such as the AT91RM2000) have a diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index a6adf7e0f6f8..cd62b029d176 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -887,6 +887,7 @@ static void pullup(struct at91_udc *udc, int is_on) if (is_on) { clk_on(udc); + at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); at91_udp_write(udc, AT91_UDP_TXVC, 0); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 1); @@ -904,6 +905,7 @@ static void pullup(struct at91_udc *udc, int is_on) } } else { stop_activity(udc); + at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); if (cpu_is_at91rm9200()) at91_set_gpio_value(udc->board.pullup_pin, 0); diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 9bb7f64a85cd..038e7d7b4da1 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1318,7 +1318,7 @@ static void setup_received_irq(struct fsl_udc *udc, | USB_TYPE_STANDARD)) { /* Note: The driver has not include OTG support yet. * This will be set when OTG support is added */ - if (!gadget_is_otg(udc->gadget)) + if (!gadget_is_otg(&udc->gadget)) break; else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) udc->gadget.b_hnp_enable = 1; diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 0689189550bc..7da7fcb05640 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -24,7 +24,6 @@ #include <linux/utsname.h> #include <linux/device.h> -#include <sound/driver.h> #include <sound/core.h> #include <sound/initval.h> #include <sound/rawmidi.h> diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b7b7bfbce527..430821cb95c8 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -122,7 +122,7 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, temp = in_le32(hcd->regs + 0x1a8); out_le32(hcd->regs + 0x1a8, temp | 0x3); - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; return retval; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 704f33fdd2f1..ddd4ee1f2413 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -732,24 +732,27 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) struct ohci_regs __iomem *regs = ohci->regs; int ints; - /* we can eliminate a (slow) ohci_readl() - * if _only_ WDH caused this irq + /* Read interrupt status (and flush pending writes). We ignore the + * optimization of checking the LSB of hcca->done_head; it doesn't + * work on all systems (edge triggering for OHCI can be a factor). */ - if ((ohci->hcca->done_head != 0) - && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head) - & 0x01)) { - ints = OHCI_INTR_WDH; + ints = ohci_readl(ohci, ®s->intrstatus); - /* cardbus/... hardware gone before remove() */ - } else if ((ints = ohci_readl (ohci, ®s->intrstatus)) == ~(u32)0) { + /* Check for an all 1's result which is a typical consequence + * of dead, unclocked, or unplugged (CardBus...) devices + */ + if (ints == ~(u32)0) { disable (ohci); ohci_dbg (ohci, "device removed!\n"); return IRQ_HANDLED; + } + + /* We only care about interrupts that are enabled */ + ints &= ohci_readl(ohci, ®s->intrenable); /* interrupt for some other device? */ - } else if ((ints &= ohci_readl (ohci, ®s->intrenable)) == 0) { + if (ints == 0) return IRQ_NOTMINE; - } if (ints & OHCI_INTR_UE) { // e.g. due to PCI Master/Target Abort @@ -994,7 +997,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_lh7a404_driver #endif -#ifdef CONFIG_PXA27x +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #include "ohci-pxa27x.c" #define PLATFORM_DRIVER ohci_hcd_pxa27x_driver #endif diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 5cfa3d1c4413..74e1f4be10bb 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -47,7 +47,7 @@ #endif #ifdef CONFIG_TPS65010 -#include <asm/arch/tps65010.h> +#include <linux/i2c/tps65010.h> #else #define LOW 0 diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index ca2a6abbc117..6c52c66b659f 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -112,9 +112,9 @@ static int isp1301_detach(struct i2c_client *client); static int isp1301_command(struct i2c_client *client, unsigned int cmd, void *arg); -static unsigned short normal_i2c[] = +static const unsigned short normal_i2c[] = { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END }; -static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; +static const unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END }; static struct i2c_client_address_data addr_data = { .normal_i2c = normal_i2c, @@ -123,7 +123,6 @@ static struct i2c_client_address_data addr_data = { }; struct i2c_driver isp1301_driver = { - .id = I2C_DRIVERID_I2CDEV, /* Fake Id */ .class = I2C_CLASS_HWMON, .attach_adapter = isp1301_probe, .detach_client = isp1301_detach, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 0a7426920150..a67252791223 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -136,13 +136,15 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match) ohci = hcd_to_ohci(hcd); if (is_bigendian) { ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC; + if (of_device_is_compatible(dn, "fsl,mpc5200-ohci")) + ohci->flags |= OHCI_QUIRK_FRAME_NO; if (of_device_is_compatible(dn, "mpc5200-ohci")) ohci->flags |= OHCI_QUIRK_FRAME_NO; } ohci_hcd_init(ohci); - rv = usb_add_hcd(hcd, irq, 0); + rv = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (rv == 0) return 0; diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 23d2fe5a62f4..ff9a79843471 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -22,6 +22,7 @@ #include <linux/device.h> #include <linux/signal.h> #include <linux/platform_device.h> +#include <linux/clk.h> #include <asm/mach-types.h> #include <asm/hardware.h> @@ -32,6 +33,8 @@ #define UHCRHPS(x) __REG2( 0x4C000050, (x)<<2 ) +static struct clk *usb_clk; + /* PMM_NPS_MODE -- PMM Non-power switching mode Ports are powered continuously. @@ -80,7 +83,7 @@ static int pxa27x_start_hc(struct device *dev) inf = dev->platform_data; - pxa_set_cken(CKEN_USBHOST, 1); + clk_enable(usb_clk); UHCHR |= UHCHR_FHR; udelay(11); @@ -123,7 +126,7 @@ static void pxa27x_stop_hc(struct device *dev) UHCCOMS |= 1; udelay(10); - pxa_set_cken(CKEN_USBHOST, 0); + clk_disable(usb_clk); } @@ -158,6 +161,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device return -ENOMEM; } + usb_clk = clk_get(&pdev->dev, "USBCLK"); + if (IS_ERR(usb_clk)) + return PTR_ERR(usb_clk); + hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); if (!hcd) return -ENOMEM; @@ -201,6 +208,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); + clk_put(usb_clk); return retval; } @@ -225,6 +233,7 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); + clk_put(usb_clk); } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index fe70e72340de..6e9c2d6db887 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -160,7 +160,7 @@ static int ssb_ohci_attach(struct ssb_device *dev) hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) goto err_put_hcd; - err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); + err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); if (err) goto err_iounmap; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index ae8ec4474eb8..0ce2fc5e396b 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2197,7 +2197,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) INIT_LIST_HEAD(&r8a66597->child_device); hcd->rsrc_start = res->start; - ret = usb_add_hcd(hcd, irq, 0); + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (ret != 0) { err("Failed to add hcd"); goto clean_up; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4db17f75f4f1..ec987897b8ed 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -378,7 +378,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned short status; - unsigned long flags; /* * Read the interrupt status, and write it back to clear the @@ -398,7 +397,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) dev_err(uhci_dev(uhci), "host controller process " "error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock_irqsave(&uhci->lock, flags); + spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), "host controller halted, " @@ -415,16 +414,16 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock_irqrestore(&uhci->lock, flags); + spin_unlock(&uhci->lock); } } if (status & USBSTS_RD) usb_hcd_poll_rh_status(hcd); else { - spin_lock_irqsave(&uhci->lock, flags); + spin_lock(&uhci->lock); uhci_scan_schedule(uhci); - spin_unlock_irqrestore(&uhci->lock, flags); + spin_unlock(&uhci->lock); } return IRQ_HANDLED; diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 3a83cb4c4bc2..22833589c4be 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -55,6 +55,7 @@ static int debug; static struct usb_device_id id_table [] = { { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ @@ -71,6 +72,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ @@ -98,8 +100,8 @@ static struct usb_serial_driver cp2101_device = { .usb_driver = &cp2101_driver, .id_table = id_table, .num_interrupt_in = 0, - .num_bulk_in = 0, - .num_bulk_out = 0, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, .num_ports = 1, .open = cp2101_open, .close = cp2101_close, diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index feba9679ace8..7c069a02c1dd 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -447,7 +447,7 @@ static void usa26_indat_callback(struct urb *urb) port = (struct usb_serial_port *) urb->context; tty = port->tty; - if (urb->actual_length) { + if (tty && urb->actual_length) { /* 0x80 bit is error flag */ if ((data[0] & 0x80) == 0) { /* no errors on individual bytes, only possible overrun err*/ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 4590124cf888..d1185f53447b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -158,8 +158,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_NETWORK) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220) }, - { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1100) }, /* Novatel Merlin XS620/S640 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1110) }, /* Novatel Merlin S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, 0x1120) }, /* Novatel Merlin EX720 */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index cf8add91de05..0da1df9c79bf 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -483,6 +483,13 @@ static void pl2303_set_termios(struct usb_serial_port *port, } spin_unlock_irqrestore(&priv->lock, flags); + /* The PL2303 is reported to lose bytes if you change + serial settings even to the same values as before. Thus + we actually need to filter in this specific case */ + + if (!tty_termios_hw_change(port->tty->termios, old_termios)) + return; + cflag = port->tty->termios->c_cflag; buf = kzalloc(7, GFP_KERNEL); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 605ebccdcd51..c295d0495f96 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -100,6 +100,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x0f30, 0x1b1d) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */ @@ -108,6 +109,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ + { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ @@ -137,7 +139,6 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ - { USB_DEVICE(0x1199, 0x0220) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U*/ @@ -146,6 +147,7 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 & AC 875U */ + { USB_DEVICE(0x1199, 0x6813) }, /* Sierra Wireless MC8775 (Thinkpad internal) */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { USB_DEVICE(0x1199, 0x6832) }, /* Sierra Wireless MC8780*/ { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781*/ diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 88aa59ab7563..f5a4e8d6a3b1 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -132,8 +132,7 @@ freecom_readdata (struct scsi_cmnd *srb, struct us_data *us, /* Now transfer all of our blocks. */ US_DEBUGP("Start of read\n"); - result = usb_stor_bulk_transfer_sg(us, ipipe, srb->request_buffer, - count, srb->use_sg, &srb->resid); + result = usb_stor_bulk_srb(us, ipipe, srb); US_DEBUGP("freecom_readdata done!\n"); if (result > USB_STOR_XFER_SHORT) @@ -166,8 +165,7 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us, /* Now transfer all of our blocks. */ US_DEBUGP("Start of write\n"); - result = usb_stor_bulk_transfer_sg(us, opipe, srb->request_buffer, - count, srb->use_sg, &srb->resid); + result = usb_stor_bulk_srb(us, opipe, srb); US_DEBUGP("freecom_writedata done!\n"); if (result > USB_STOR_XFER_SHORT) @@ -281,7 +279,7 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) * and such will hang. */ US_DEBUGP("Device indicates that it has %d bytes available\n", le16_to_cpu (fst->Count)); - US_DEBUGP("SCSI requested %d\n", srb->request_bufflen); + US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb)); /* Find the length we desire to read. */ switch (srb->cmnd[0]) { @@ -292,12 +290,12 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) length = le16_to_cpu(fst->Count); break; default: - length = srb->request_bufflen; + length = scsi_bufflen(srb); } /* verify that this amount is legal */ - if (length > srb->request_bufflen) { - length = srb->request_bufflen; + if (length > scsi_bufflen(srb)) { + length = scsi_bufflen(srb); US_DEBUGP("Truncating request to match buffer length: %d\n", length); } diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 49ba6c0ff1e8..0db488624ab1 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -49,6 +49,7 @@ #include <linux/slab.h> #include <linux/hdreg.h> #include <linux/ide.h> +#include <linux/scatterlist.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -287,6 +288,7 @@ struct isd200_info { /* maximum number of LUNs supported */ unsigned char MaxLUNs; struct scsi_cmnd srb; + struct scatterlist sg; }; @@ -398,6 +400,31 @@ static void isd200_build_sense(struct us_data *us, struct scsi_cmnd *srb) * Transport routines ***********************************************************************/ +/************************************************************************** + * isd200_set_srb(), isd200_srb_set_bufflen() + * + * Two helpers to facilitate in initialization of scsi_cmnd structure + * Will need to change when struct scsi_cmnd changes + */ +static void isd200_set_srb(struct isd200_info *info, + enum dma_data_direction dir, void* buff, unsigned bufflen) +{ + struct scsi_cmnd *srb = &info->srb; + + if (buff) + sg_init_one(&info->sg, buff, bufflen); + + srb->sc_data_direction = dir; + srb->sdb.table.sgl = buff ? &info->sg : NULL; + srb->sdb.length = bufflen; + srb->sdb.table.nents = buff ? 1 : 0; +} + +static void isd200_srb_set_bufflen(struct scsi_cmnd *srb, unsigned bufflen) +{ + srb->sdb.length = bufflen; +} + /************************************************************************** * isd200_action @@ -432,9 +459,7 @@ static int isd200_action( struct us_data *us, int action, ata.generic.RegisterSelect = REG_CYLINDER_LOW | REG_CYLINDER_HIGH | REG_STATUS | REG_ERROR; - srb->sc_data_direction = DMA_FROM_DEVICE; - srb->request_buffer = pointer; - srb->request_bufflen = value; + isd200_set_srb(info, DMA_FROM_DEVICE, pointer, value); break; case ACTION_ENUM: @@ -444,7 +469,7 @@ static int isd200_action( struct us_data *us, int action, ACTION_SELECT_5; ata.generic.RegisterSelect = REG_DEVICE_HEAD; ata.write.DeviceHeadByte = value; - srb->sc_data_direction = DMA_NONE; + isd200_set_srb(info, DMA_NONE, NULL, 0); break; case ACTION_RESET: @@ -453,7 +478,7 @@ static int isd200_action( struct us_data *us, int action, ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_RESET_CONTROLLER; - srb->sc_data_direction = DMA_NONE; + isd200_set_srb(info, DMA_NONE, NULL, 0); break; case ACTION_REENABLE: @@ -462,7 +487,7 @@ static int isd200_action( struct us_data *us, int action, ACTION_SELECT_3|ACTION_SELECT_4; ata.generic.RegisterSelect = REG_DEVICE_CONTROL; ata.write.DeviceControlByte = ATA_DC_REENABLE_CONTROLLER; - srb->sc_data_direction = DMA_NONE; + isd200_set_srb(info, DMA_NONE, NULL, 0); break; case ACTION_SOFT_RESET: @@ -471,21 +496,20 @@ static int isd200_action( struct us_data *us, int action, ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND; ata.write.DeviceHeadByte = info->DeviceHead; ata.write.CommandByte = WIN_SRST; - srb->sc_data_direction = DMA_NONE; + isd200_set_srb(info, DMA_NONE, NULL, 0); break; case ACTION_IDENTIFY: US_DEBUGP(" isd200_action(IDENTIFY)\n"); ata.generic.RegisterSelect = REG_COMMAND; ata.write.CommandByte = WIN_IDENTIFY; - srb->sc_data_direction = DMA_FROM_DEVICE; - srb->request_buffer = (void *) info->id; - srb->request_bufflen = sizeof(struct hd_driveid); + isd200_set_srb(info, DMA_FROM_DEVICE, info->id, + sizeof(struct hd_driveid)); break; default: US_DEBUGP("Error: Undefined action %d\n",action); - break; + return ISD200_ERROR; } memcpy(srb->cmnd, &ata, sizeof(ata.generic)); @@ -590,7 +614,7 @@ static void isd200_invoke_transport( struct us_data *us, return; } - if ((srb->resid > 0) && + if ((scsi_get_resid(srb) > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || @@ -1217,7 +1241,6 @@ static int isd200_get_inquiry_data( struct us_data *us ) return(retStatus); } - /************************************************************************** * isd200_scsi_to_ata * @@ -1266,7 +1289,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; - srb->request_bufflen = 0; + isd200_srb_set_bufflen(srb, 0); } else { US_DEBUGP(" Media Status not supported, just report okay\n"); srb->result = SAM_STAT_GOOD; @@ -1284,7 +1307,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; - srb->request_bufflen = 0; + isd200_srb_set_bufflen(srb, 0); } else { US_DEBUGP(" Media Status not supported, just report okay\n"); srb->result = SAM_STAT_GOOD; @@ -1390,7 +1413,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->write.CommandByte = (srb->cmnd[4] & 0x1) ? WIN_DOORLOCK : WIN_DOORUNLOCK; - srb->request_bufflen = 0; + isd200_srb_set_bufflen(srb, 0); } else { US_DEBUGP(" Not removeable media, just report okay\n"); srb->result = SAM_STAT_GOOD; @@ -1416,7 +1439,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us, ataCdb->generic.TransferBlockSize = 1; ataCdb->generic.RegisterSelect = REG_COMMAND; ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS; - srb->request_bufflen = 0; + isd200_srb_set_bufflen(srb, 0); } else { US_DEBUGP(" Nothing to do, just report okay\n"); srb->result = SAM_STAT_GOOD; @@ -1525,7 +1548,7 @@ int isd200_Initialization(struct us_data *us) void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) { - int sendToTransport = 1; + int sendToTransport = 1, orig_bufflen; union ata_cdb ataCdb; /* Make sure driver was initialized */ @@ -1533,11 +1556,14 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) if (us->extra == NULL) US_DEBUGP("ERROR Driver not initialized\n"); - /* Convert command */ - srb->resid = 0; + scsi_set_resid(srb, 0); + /* scsi_bufflen might change in protocol translation to ata */ + orig_bufflen = scsi_bufflen(srb); sendToTransport = isd200_scsi_to_ata(srb, us, &ataCdb); /* send the command to the transport layer */ if (sendToTransport) isd200_invoke_transport(us, srb, &ataCdb); + + isd200_srb_set_bufflen(srb, orig_bufflen); } diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 889622baac20..a41ce21c0697 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -149,11 +149,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, ***********************************************************************/ /* Copy a buffer of length buflen to/from the srb's transfer buffer. - * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer - * points to a list of s-g entries and we ignore srb->request_bufflen. - * For non-scatter-gather transfers, srb->request_buffer points to the - * transfer buffer itself and srb->request_bufflen is the buffer's length.) - * Update the *index and *offset variables so that the next copy will + * Update the **sgptr and *offset variables so that the next copy will * pick up from where this one left off. */ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, @@ -162,80 +158,64 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, { unsigned int cnt; - /* If not using scatter-gather, just transfer the data directly. - * Make certain it will fit in the available buffer space. */ - if (srb->use_sg == 0) { - if (*offset >= srb->request_bufflen) - return 0; - cnt = min(buflen, srb->request_bufflen - *offset); - if (dir == TO_XFER_BUF) - memcpy((unsigned char *) srb->request_buffer + *offset, - buffer, cnt); - else - memcpy(buffer, (unsigned char *) srb->request_buffer + - *offset, cnt); - *offset += cnt; - - /* Using scatter-gather. We have to go through the list one entry + /* We have to go through the list one entry * at a time. Each s-g entry contains some number of pages, and * each page has to be kmap()'ed separately. If the page is already * in kernel-addressable memory then kmap() will return its address. * If the page is not directly accessible -- such as a user buffer * located in high memory -- then kmap() will map it to a temporary * position in the kernel's virtual address space. */ - } else { - struct scatterlist *sg = *sgptr; - - if (!sg) - sg = (struct scatterlist *) srb->request_buffer; - - /* This loop handles a single s-g list entry, which may - * include multiple pages. Find the initial page structure - * and the starting offset within the page, and update - * the *offset and *index values for the next loop. */ - cnt = 0; - while (cnt < buflen) { - struct page *page = sg_page(sg) + - ((sg->offset + *offset) >> PAGE_SHIFT); - unsigned int poff = - (sg->offset + *offset) & (PAGE_SIZE-1); - unsigned int sglen = sg->length - *offset; - - if (sglen > buflen - cnt) { - - /* Transfer ends within this s-g entry */ - sglen = buflen - cnt; - *offset += sglen; - } else { - - /* Transfer continues to next s-g entry */ - *offset = 0; - sg = sg_next(sg); - } - - /* Transfer the data for all the pages in this - * s-g entry. For each page: call kmap(), do the - * transfer, and call kunmap() immediately after. */ - while (sglen > 0) { - unsigned int plen = min(sglen, (unsigned int) - PAGE_SIZE - poff); - unsigned char *ptr = kmap(page); - - if (dir == TO_XFER_BUF) - memcpy(ptr + poff, buffer + cnt, plen); - else - memcpy(buffer + cnt, ptr + poff, plen); - kunmap(page); - - /* Start at the beginning of the next page */ - poff = 0; - ++page; - cnt += plen; - sglen -= plen; - } + struct scatterlist *sg = *sgptr; + + if (!sg) + sg = scsi_sglist(srb); + + /* This loop handles a single s-g list entry, which may + * include multiple pages. Find the initial page structure + * and the starting offset within the page, and update + * the *offset and **sgptr values for the next loop. */ + cnt = 0; + while (cnt < buflen) { + struct page *page = sg_page(sg) + + ((sg->offset + *offset) >> PAGE_SHIFT); + unsigned int poff = + (sg->offset + *offset) & (PAGE_SIZE-1); + unsigned int sglen = sg->length - *offset; + + if (sglen > buflen - cnt) { + + /* Transfer ends within this s-g entry */ + sglen = buflen - cnt; + *offset += sglen; + } else { + + /* Transfer continues to next s-g entry */ + *offset = 0; + sg = sg_next(sg); + } + + /* Transfer the data for all the pages in this + * s-g entry. For each page: call kmap(), do the + * transfer, and call kunmap() immediately after. */ + while (sglen > 0) { + unsigned int plen = min(sglen, (unsigned int) + PAGE_SIZE - poff); + unsigned char *ptr = kmap(page); + + if (dir == TO_XFER_BUF) + memcpy(ptr + poff, buffer + cnt, plen); + else + memcpy(buffer + cnt, ptr + poff, plen); + kunmap(page); + + /* Start at the beginning of the next page */ + poff = 0; + ++page; + cnt += plen; + sglen -= plen; } - *sgptr = sg; } + *sgptr = sg; /* Return the amount actually transferred */ return cnt; @@ -251,6 +231,6 @@ void usb_stor_set_xfer_buf(unsigned char *buffer, usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset, TO_XFER_BUF); - if (buflen < srb->request_bufflen) - srb->resid = srb->request_bufflen - buflen; + if (buflen < scsi_bufflen(srb)) + scsi_set_resid(srb, scsi_bufflen(srb) - buflen); } diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 836a34ae6ec6..8c1e2954f3b9 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -81,6 +81,16 @@ static int slave_alloc (struct scsi_device *sdev) */ sdev->inquiry_len = 36; + /* Scatter-gather buffers (all but the last) must have a length + * divisible by the bulk maxpacket size. Otherwise a data packet + * would end up being short, causing a premature end to the data + * transfer. Since high-speed bulk pipes have a maxpacket size + * of 512, we'll use that as the scsi device queue's DMA alignment + * mask. Guaranteeing proper alignment of the first buffer will + * have the desired effect because, except at the beginning and + * the end, scatter-gather buffers follow page boundaries. */ + blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); + /* * The UFI spec treates the Peripheral Qualifier bits in an * INQUIRY result as reserved and requires devices to set them @@ -100,23 +110,19 @@ static int slave_configure(struct scsi_device *sdev) { struct us_data *us = host_to_us(sdev->host); - /* Scatter-gather buffers (all but the last) must have a length - * divisible by the bulk maxpacket size. Otherwise a data packet - * would end up being short, causing a premature end to the data - * transfer. Since high-speed bulk pipes have a maxpacket size - * of 512, we'll use that as the scsi device queue's DMA alignment - * mask. Guaranteeing proper alignment of the first buffer will - * have the desired effect because, except at the beginning and - * the end, scatter-gather buffers follow page boundaries. */ - blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); - /* Many devices have trouble transfering more than 32KB at a time, * while others have trouble with more than 64K. At this time we * are limiting both to 32K (64 sectores). */ - if ((us->flags & US_FL_MAX_SECTORS_64) && - sdev->request_queue->max_sectors > 64) - blk_queue_max_sectors(sdev->request_queue, 64); + if (us->flags & (US_FL_MAX_SECTORS_64 | US_FL_MAX_SECTORS_MIN)) { + unsigned int max_sectors = 64; + + if (us->flags & US_FL_MAX_SECTORS_MIN) + max_sectors = PAGE_CACHE_SIZE >> 9; + if (sdev->request_queue->max_sectors > max_sectors) + blk_queue_max_sectors(sdev->request_queue, + max_sectors); + } /* We can't put these settings in slave_alloc() because that gets * called before the device type is known. Consequently these @@ -181,6 +187,10 @@ static int slave_configure(struct scsi_device *sdev) * automatically, requiring a START-STOP UNIT command. */ sdev->allow_restart = 1; + /* Some USB cardreaders have trouble reading an sdcard's last + * sector in a larger then 1 sector read, since the performance + * impact is negible we set this flag for all USB disks */ + sdev->last_sector_bug = 1; } else { /* Non-disk-type devices don't need to blacklist any pages diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index b12202c5da2d..8972b17da843 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -1623,7 +1623,7 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_ERROR; } - if (srb->request_bufflen == 0) + if (scsi_bufflen(srb) == 0) return USB_STOR_TRANSPORT_GOOD; if (srb->sc_data_direction == DMA_TO_DEVICE || @@ -1634,12 +1634,9 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) US_DEBUGP("SDDR09: %s %d bytes\n", (srb->sc_data_direction == DMA_TO_DEVICE) ? "sending" : "receiving", - srb->request_bufflen); + scsi_bufflen(srb)); - result = usb_stor_bulk_transfer_sg(us, pipe, - srb->request_buffer, - srb->request_bufflen, - srb->use_sg, &srb->resid); + result = usb_stor_bulk_srb(us, pipe, srb); return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index cb22a9ad1694..570c1250f6f3 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -130,7 +130,7 @@ static int usbat_write(struct us_data *us, * Convenience function to perform a bulk read */ static int usbat_bulk_read(struct us_data *us, - unsigned char *data, + void* buf, unsigned int len, int use_sg) { @@ -138,14 +138,14 @@ static int usbat_bulk_read(struct us_data *us, return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_read: len = %d\n", len); - return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL); + return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, buf, len, use_sg, NULL); } /* * Convenience function to perform a bulk write */ static int usbat_bulk_write(struct us_data *us, - unsigned char *data, + void* buf, unsigned int len, int use_sg) { @@ -153,7 +153,7 @@ static int usbat_bulk_write(struct us_data *us, return USB_STOR_XFER_GOOD; US_DEBUGP("usbat_bulk_write: len = %d\n", len); - return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL); + return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, buf, len, use_sg, NULL); } /* @@ -314,7 +314,7 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes) * Read block data from the data register */ static int usbat_read_block(struct us_data *us, - unsigned char *content, + void* buf, unsigned short len, int use_sg) { @@ -337,7 +337,7 @@ static int usbat_read_block(struct us_data *us, if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_read(us, content, len, use_sg); + result = usbat_bulk_read(us, buf, len, use_sg); return (result == USB_STOR_XFER_GOOD ? USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR); } @@ -347,7 +347,7 @@ static int usbat_read_block(struct us_data *us, */ static int usbat_write_block(struct us_data *us, unsigned char access, - unsigned char *content, + void* buf, unsigned short len, int minutes, int use_sg) @@ -372,7 +372,7 @@ static int usbat_write_block(struct us_data *us, if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; - result = usbat_bulk_write(us, content, len, use_sg); + result = usbat_bulk_write(us, buf, len, use_sg); if (result != USB_STOR_XFER_GOOD) return USB_STOR_TRANSPORT_ERROR; @@ -392,7 +392,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, unsigned char timeout, unsigned char qualifier, int direction, - unsigned char *content, + void *buf, unsigned short len, int use_sg, int minutes) @@ -472,7 +472,7 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us, } result = usb_stor_bulk_transfer_sg(us, - pipe, content, len, use_sg, NULL); + pipe, buf, len, use_sg, NULL); /* * If we get a stall on the bulk download, we'll retry @@ -606,7 +606,7 @@ static int usbat_multiple_write(struct us_data *us, * other related details) are defined beforehand with _set_shuttle_features(). */ static int usbat_read_blocks(struct us_data *us, - unsigned char *buffer, + void* buffer, int len, int use_sg) { @@ -648,7 +648,7 @@ static int usbat_read_blocks(struct us_data *us, * other related details) are defined beforehand with _set_shuttle_features(). */ static int usbat_write_blocks(struct us_data *us, - unsigned char *buffer, + void* buffer, int len, int use_sg) { @@ -1170,15 +1170,15 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, US_DEBUGP("handle_read10: transfersize %d\n", srb->transfersize); - if (srb->request_bufflen < 0x10000) { + if (scsi_bufflen(srb) < 0x10000) { result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, registers, data, 19, USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD, (USBAT_QUAL_FCQ | USBAT_QUAL_ALQ), DMA_FROM_DEVICE, - srb->request_buffer, - srb->request_bufflen, srb->use_sg, 1); + scsi_sglist(srb), + scsi_bufflen(srb), scsi_sg_count(srb), 1); return result; } @@ -1196,7 +1196,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, len <<= 16; len |= data[7+7]; US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len); - srb->transfersize = srb->request_bufflen/len; + srb->transfersize = scsi_bufflen(srb)/len; } if (!srb->transfersize) { @@ -1213,7 +1213,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, len = (65535/srb->transfersize) * srb->transfersize; US_DEBUGP("Max read is %d bytes\n", len); - len = min(len, srb->request_bufflen); + len = min(len, scsi_bufflen(srb)); buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) /* bloody hell! */ return USB_STOR_TRANSPORT_FAILED; @@ -1222,10 +1222,10 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, sector |= short_pack(data[7+5], data[7+4]); transferred = 0; - while (transferred != srb->request_bufflen) { + while (transferred != scsi_bufflen(srb)) { - if (len > srb->request_bufflen - transferred) - len = srb->request_bufflen - transferred; + if (len > scsi_bufflen(srb) - transferred) + len = scsi_bufflen(srb) - transferred; data[3] = len&0xFF; /* (cylL) = expected length (L) */ data[4] = (len>>8)&0xFF; /* (cylH) = expected length (H) */ @@ -1261,7 +1261,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us, transferred += len; sector += len / srb->transfersize; - } /* while transferred != srb->request_bufflen */ + } /* while transferred != scsi_bufflen(srb) */ kfree(buffer); return result; @@ -1429,9 +1429,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) unsigned char data[32]; unsigned int len; int i; - char string[64]; - len = srb->request_bufflen; + len = scsi_bufflen(srb); /* Send A0 (ATA PACKET COMMAND). Note: I guess we're never going to get any of the ATA @@ -1472,8 +1471,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD, (USBAT_QUAL_FCQ | USBAT_QUAL_ALQ), DMA_TO_DEVICE, - srb->request_buffer, - len, srb->use_sg, 10); + scsi_sglist(srb), + len, scsi_sg_count(srb), 10); if (result == USB_STOR_TRANSPORT_GOOD) { transferred += len; @@ -1540,23 +1539,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us) len = *status; - result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg); - - /* Debug-print the first 32 bytes of the transfer */ - - if (!srb->use_sg) { - string[0] = 0; - for (i=0; i<len && i<32; i++) { - sprintf(string+strlen(string), "%02X ", - ((unsigned char *)srb->request_buffer)[i]); - if ((i%16)==15) { - US_DEBUGP("%s\n", string); - string[0] = 0; - } - } - if (string[0]!=0) - US_DEBUGP("%s\n", string); - } + result = usbat_read_block(us, scsi_sglist(srb), len, + scsi_sg_count(srb)); } return result; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c646750ccc30..d9f4912f873d 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -459,6 +459,22 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, } /* + * Common used function. Transfer a complete command + * via usb_stor_bulk_transfer_sglist() above. Set cmnd resid + */ +int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, + struct scsi_cmnd* srb) +{ + unsigned int partial; + int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb), + scsi_sg_count(srb), scsi_bufflen(srb), + &partial); + + scsi_set_resid(srb, scsi_bufflen(srb) - partial); + return result; +} + +/* * Transfer an entire SCSI command's worth of data payload over the bulk * pipe. * @@ -508,7 +524,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) int result; /* send the command to the transport layer */ - srb->resid = 0; + scsi_set_resid(srb, 0); result = us->transport(srb, us); /* if the command gets aborted by the higher layers, we need to @@ -568,7 +584,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) * A short transfer on a command where we don't expect it * is unusual, but it doesn't mean we need to auto-sense. */ - if ((srb->resid > 0) && + if ((scsi_get_resid(srb) > 0) && !((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY) || (srb->cmnd[0] == MODE_SENSE) || @@ -593,7 +609,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) srb->cmd_len = 12; /* issue the auto-sense command */ - srb->resid = 0; + scsi_set_resid(srb, 0); temp_result = us->transport(us->srb, us); /* let's clean up right away */ @@ -649,7 +665,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* Did we transfer less than the minimum amount required? */ if (srb->result == SAM_STAT_GOOD && - srb->request_bufflen - srb->resid < srb->underflow) + scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY << 24); return; @@ -708,7 +724,7 @@ void usb_stor_stop_transport(struct us_data *us) int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) { - unsigned int transfer_length = srb->request_bufflen; + unsigned int transfer_length = scsi_bufflen(srb); unsigned int pipe = 0; int result; @@ -737,9 +753,7 @@ int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) if (transfer_length) { pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; - result = usb_stor_bulk_transfer_sg(us, pipe, - srb->request_buffer, transfer_length, - srb->use_sg, &srb->resid); + result = usb_stor_bulk_srb(us, pipe, srb); US_DEBUGP("CBI data stage result is 0x%x\n", result); /* if we stalled the data transfer it means command failed */ @@ -808,7 +822,7 @@ int usb_stor_CBI_transport(struct scsi_cmnd *srb, struct us_data *us) */ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) { - unsigned int transfer_length = srb->request_bufflen; + unsigned int transfer_length = scsi_bufflen(srb); int result; /* COMMAND STAGE */ @@ -836,9 +850,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) if (transfer_length) { unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; - result = usb_stor_bulk_transfer_sg(us, pipe, - srb->request_buffer, transfer_length, - srb->use_sg, &srb->resid); + result = usb_stor_bulk_srb(us, pipe, srb); US_DEBUGP("CB data stage result is 0x%x\n", result); /* if we stalled the data transfer it means command failed */ @@ -904,7 +916,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) { struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf; struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf; - unsigned int transfer_length = srb->request_bufflen; + unsigned int transfer_length = scsi_bufflen(srb); unsigned int residue; int result; int fake_sense = 0; @@ -955,9 +967,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) if (transfer_length) { unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? us->recv_bulk_pipe : us->send_bulk_pipe; - result = usb_stor_bulk_transfer_sg(us, pipe, - srb->request_buffer, transfer_length, - srb->use_sg, &srb->resid); + result = usb_stor_bulk_srb(us, pipe, srb); US_DEBUGP("Bulk data transfer result 0x%x\n", result); if (result == USB_STOR_XFER_ERROR) return USB_STOR_TRANSPORT_ERROR; @@ -1036,7 +1046,8 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) if (residue) { if (!(us->flags & US_FL_IGNORE_RESIDUE)) { residue = min(residue, transfer_length); - srb->resid = max(srb->resid, (int) residue); + scsi_set_resid(srb, max(scsi_get_resid(srb), + (int) residue)); } } diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h index 633a715850a4..ada7c2f43f84 100644 --- a/drivers/usb/storage/transport.h +++ b/drivers/usb/storage/transport.h @@ -139,6 +139,8 @@ extern int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, void *buf, unsigned int length, unsigned int *act_len); extern int usb_stor_bulk_transfer_sg(struct us_data *us, unsigned int pipe, void *buf, unsigned int length, int use_sg, int *residual); +extern int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, + struct scsi_cmnd* srb); extern int usb_stor_port_reset(struct us_data *us); #endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 2c27721bd259..6d6108b3993b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -376,6 +376,13 @@ UNUSUAL_DEV( 0x04b0, 0x0417, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY), +/* Reported by Doug Maxey (dwm@austin.ibm.com) */ +UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, + "IBM", + "IBM RSA2", + US_SC_DEVICE, US_PR_CB, NULL, + US_FL_MAX_SECTORS_MIN), + /* BENQ DC5330 * Reported by Manuel Fombuena <mfombuena@ya.com> and * Frank Copeland <fjc@thingy.apana.org.au> */ @@ -1258,14 +1265,6 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), -/* SanDisk that has a second LUN for a driver ISO, reported by - * Ben Collins <bcollins@ubuntu.com> */ -UNUSUAL_DEV( 0x0781, 0x5406, 0x0000, 0xffff, - "SanDisk", - "U3 Cruzer Micro driver ISO", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN ), - #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", |