Commit 4c1f683a authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (28 commits)
  MAINTAINERS: add a maintainer to Gadget Framework
  USB: serial: add another 4N-GALAXY.DE PID to ftdi_sio driver
  Revert "USB: option: add ID for ZTE MF 330"
  drivers/usb/host/ohci-pxa27x.c: add missing clk_put
  USB: CONFIG_USB_GADGET_DUALSPEED is not user-configurable
  USB: dummy-hcd needs the has_tt flag
  usb-storage: redo incorrect reads
  usb/renesas_usbhs: free uep on removal
  usb/s3c-hsudc: fix error path
  usb/pxa25x_udc: cleanup the LUBBOCK err path
  usb/mv_udc_core: fix compile
  usb: gadget: include <linux/prefetch.h> to fix compiling error
  USB: s3c-hsotg: Tone down debugging
  usb: remove bad dput after dentry_unhash
  USB: core: Tolerate protocol stall during hub and port status read
  musb: fix prefetch build failure
  USB: cdc-acm: Adding second ACM channel support for Nokia E7 and C7
  usb-gadget: unlock data->lock mutex on error path in ep_write()
  USB: option Add blacklist for ZTE K3765-Z (19d2:2002)
  option: add Prolink PH300 modem IDs
  ...
parents 365a13a5 d6d0f665
...@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. ...@@ -2598,6 +2598,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
unlock ejectable media); unlock ejectable media);
m = MAX_SECTORS_64 (don't transfer more m = MAX_SECTORS_64 (don't transfer more
than 64 sectors = 32 KB at a time); than 64 sectors = 32 KB at a time);
n = INITIAL_READ10 (force a retry of the
initial READ(10) command);
o = CAPACITY_OK (accept the capacity o = CAPACITY_OK (accept the capacity
reported by the device); reported by the device);
r = IGNORE_RESIDUE (the device reports r = IGNORE_RESIDUE (the device reports
......
...@@ -6444,9 +6444,11 @@ S: Maintained ...@@ -6444,9 +6444,11 @@ S: Maintained
F: drivers/media/video/et61x251/ F: drivers/media/video/et61x251/
USB GADGET/PERIPHERAL SUBSYSTEM USB GADGET/PERIPHERAL SUBSYSTEM
M: Felipe Balbi <balbi@ti.com>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org/gadget W: http://www.linux-usb.org/gadget
S: Orphan T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/gadget/ F: drivers/usb/gadget/
F: include/linux/usb/gadget* F: include/linux/usb/gadget*
......
...@@ -1530,6 +1530,8 @@ static const struct usb_device_id acm_ids[] = { ...@@ -1530,6 +1530,8 @@ static const struct usb_device_id acm_ids[] = {
{ NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */ { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */
{ NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */ { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */
{ NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */ { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */
{ NOKIA_PCSUITE_ACM_INFO(0x0335), }, /* Nokia E7 */
{ NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */
{ SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */ { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
......
...@@ -339,7 +339,8 @@ static int get_hub_status(struct usb_device *hdev, ...@@ -339,7 +339,8 @@ static int get_hub_status(struct usb_device *hdev,
{ {
int i, status = -ETIMEDOUT; int i, status = -ETIMEDOUT;
for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { for (i = 0; i < USB_STS_RETRIES &&
(status == -ETIMEDOUT || status == -EPIPE); i++) {
status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
data, sizeof(*data), USB_STS_TIMEOUT); data, sizeof(*data), USB_STS_TIMEOUT);
...@@ -355,7 +356,8 @@ static int get_port_status(struct usb_device *hdev, int port1, ...@@ -355,7 +356,8 @@ static int get_port_status(struct usb_device *hdev, int port1,
{ {
int i, status = -ETIMEDOUT; int i, status = -ETIMEDOUT;
for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { for (i = 0; i < USB_STS_RETRIES &&
(status == -ETIMEDOUT || status == -EPIPE); i++) {
status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1, USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
data, sizeof(*data), USB_STS_TIMEOUT); data, sizeof(*data), USB_STS_TIMEOUT);
......
...@@ -632,13 +632,10 @@ config USB_DUMMY_HCD ...@@ -632,13 +632,10 @@ config USB_DUMMY_HCD
endchoice endchoice
# Selected by UDC drivers that support high-speed operation.
config USB_GADGET_DUALSPEED config USB_GADGET_DUALSPEED
bool bool
depends on USB_GADGET depends on USB_GADGET
default n
help
Means that gadget drivers should include extra descriptors
and code to handle dual-speed controllers.
# #
# USB Gadget Drivers # USB Gadget Drivers
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/prefetch.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/system.h> #include <asm/system.h>
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/prefetch.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <mach/hardware.h> #include <mach/hardware.h>
......
...@@ -1906,6 +1906,7 @@ static int dummy_hcd_probe(struct platform_device *pdev) ...@@ -1906,6 +1906,7 @@ static int dummy_hcd_probe(struct platform_device *pdev)
if (!hcd) if (!hcd)
return -ENOMEM; return -ENOMEM;
the_controller = hcd_to_dummy (hcd); the_controller = hcd_to_dummy (hcd);
hcd->has_tt = 1;
retval = usb_add_hcd(hcd, 0, 0); retval = usb_add_hcd(hcd, 0, 0);
if (retval != 0) { if (retval != 0) {
......
...@@ -431,8 +431,10 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) ...@@ -431,8 +431,10 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
/* halt any endpoint by doing a "wrong direction" i/o call */ /* halt any endpoint by doing a "wrong direction" i/o call */
if (!usb_endpoint_dir_in(&data->desc)) { if (!usb_endpoint_dir_in(&data->desc)) {
if (usb_endpoint_xfer_isoc(&data->desc)) if (usb_endpoint_xfer_isoc(&data->desc)) {
mutex_unlock(&data->lock);
return -EINVAL; return -EINVAL;
}
DBG (data->dev, "%s halt\n", data->name); DBG (data->dev, "%s halt\n", data->name);
spin_lock_irq (&data->dev->lock); spin_lock_irq (&data->dev->lock);
if (likely (data->ep != NULL)) if (likely (data->ep != NULL))
......
...@@ -2083,7 +2083,7 @@ int mv_udc_probe(struct platform_device *dev) ...@@ -2083,7 +2083,7 @@ int mv_udc_probe(struct platform_device *dev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state) static int mv_udc_suspend(struct device *_dev)
{ {
struct mv_udc *udc = the_controller; struct mv_udc *udc = the_controller;
...@@ -2092,7 +2092,7 @@ static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state) ...@@ -2092,7 +2092,7 @@ static int mv_udc_suspend(struct platform_device *_dev, pm_message_t state)
return 0; return 0;
} }
static int mv_udc_resume(struct platform_device *_dev) static int mv_udc_resume(struct device *_dev)
{ {
struct mv_udc *udc = the_controller; struct mv_udc *udc = the_controller;
int retval; int retval;
...@@ -2100,7 +2100,7 @@ static int mv_udc_resume(struct platform_device *_dev) ...@@ -2100,7 +2100,7 @@ static int mv_udc_resume(struct platform_device *_dev)
retval = mv_udc_phy_init(udc->phy_regs); retval = mv_udc_phy_init(udc->phy_regs);
if (retval) { if (retval) {
dev_err(_dev, "phy initialization error %d\n", retval); dev_err(_dev, "phy initialization error %d\n", retval);
goto error; return retval;
} }
udc_reset(udc); udc_reset(udc);
ep0_reset(udc); ep0_reset(udc);
...@@ -2122,7 +2122,7 @@ static struct platform_driver udc_driver = { ...@@ -2122,7 +2122,7 @@ static struct platform_driver udc_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "pxa-u2o", .name = "pxa-u2o",
#ifdef CONFIG_PM #ifdef CONFIG_PM
.pm = mv_udc_pm_ops, .pm = &mv_udc_pm_ops,
#endif #endif
}, },
}; };
......
...@@ -63,6 +63,7 @@ ...@@ -63,6 +63,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/prefetch.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -2216,7 +2216,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) ...@@ -2216,7 +2216,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
if (retval != 0) { if (retval != 0) {
pr_err("%s: can't get irq %i, err %d\n", pr_err("%s: can't get irq %i, err %d\n",
driver_name, LUBBOCK_USB_DISC_IRQ, retval); driver_name, LUBBOCK_USB_DISC_IRQ, retval);
lubbock_fail0:
goto err_irq_lub; goto err_irq_lub;
} }
retval = request_irq(LUBBOCK_USB_IRQ, retval = request_irq(LUBBOCK_USB_IRQ,
...@@ -2226,7 +2225,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) ...@@ -2226,7 +2225,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
if (retval != 0) { if (retval != 0) {
pr_err("%s: can't get irq %i, err %d\n", pr_err("%s: can't get irq %i, err %d\n",
driver_name, LUBBOCK_USB_IRQ, retval); driver_name, LUBBOCK_USB_IRQ, retval);
free_irq(LUBBOCK_USB_DISC_IRQ, dev);
goto lubbock_fail0; goto lubbock_fail0;
} }
} else } else
...@@ -2236,10 +2234,11 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) ...@@ -2236,10 +2234,11 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
return 0; return 0;
#ifdef CONFIG_ARCH_LUBBOCK #ifdef CONFIG_ARCH_LUBBOCK
lubbock_fail0:
free_irq(LUBBOCK_USB_DISC_IRQ, dev); free_irq(LUBBOCK_USB_DISC_IRQ, dev);
err_irq_lub: err_irq_lub:
#endif
free_irq(irq, dev); free_irq(irq, dev);
#endif
err_irq1: err_irq1:
if (gpio_is_valid(dev->mach->gpio_pullup)) if (gpio_is_valid(dev->mach->gpio_pullup))
gpio_free(dev->mach->gpio_pullup); gpio_free(dev->mach->gpio_pullup);
......
...@@ -2680,7 +2680,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -2680,7 +2680,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
writel(0, hsotg->regs + S3C_DAINTMSK); writel(0, hsotg->regs + S3C_DAINTMSK);
dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
readl(hsotg->regs + S3C_DIEPCTL0), readl(hsotg->regs + S3C_DIEPCTL0),
readl(hsotg->regs + S3C_DOEPCTL0)); readl(hsotg->regs + S3C_DOEPCTL0));
...@@ -2701,7 +2701,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -2701,7 +2701,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
udelay(10); /* see openiboot */ udelay(10); /* see openiboot */
__bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone);
dev_info(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL));
/* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by
writing to the EPCTL register.. */ writing to the EPCTL register.. */
...@@ -2721,7 +2721,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -2721,7 +2721,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
s3c_hsotg_enqueue_setup(hsotg); s3c_hsotg_enqueue_setup(hsotg);
dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
readl(hsotg->regs + S3C_DIEPCTL0), readl(hsotg->regs + S3C_DIEPCTL0),
readl(hsotg->regs + S3C_DOEPCTL0)); readl(hsotg->regs + S3C_DOEPCTL0));
...@@ -2921,7 +2921,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) ...@@ -2921,7 +2921,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
/* setup fifos */ /* setup fifos */
dev_info(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
readl(hsotg->regs + S3C_GRXFSIZ), readl(hsotg->regs + S3C_GRXFSIZ),
readl(hsotg->regs + S3C_GNPTXFSIZ)); readl(hsotg->regs + S3C_GNPTXFSIZ));
...@@ -2945,6 +2945,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg) ...@@ -2945,6 +2945,7 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
{ {
#ifdef DEBUG
struct device *dev = hsotg->dev; struct device *dev = hsotg->dev;
void __iomem *regs = hsotg->regs; void __iomem *regs = hsotg->regs;
u32 val; u32 val;
...@@ -2987,6 +2988,7 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg) ...@@ -2987,6 +2988,7 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE)); readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE));
#endif
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/prefetch.h>
#include <mach/regs-s3c2443-clock.h> #include <mach/regs-s3c2443-clock.h>
#include <plat/udc.h> #include <plat/udc.h>
...@@ -1301,7 +1302,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) ...@@ -1301,7 +1302,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
hsudc->uclk = clk_get(&pdev->dev, "usb-device"); hsudc->uclk = clk_get(&pdev->dev, "usb-device");
if (IS_ERR(hsudc->uclk)) { if (IS_ERR(hsudc->uclk)) {
dev_err(dev, "failed to find usb-device clock source\n"); dev_err(dev, "failed to find usb-device clock source\n");
return PTR_ERR(hsudc->uclk); ret = PTR_ERR(hsudc->uclk);
goto err_clk;
} }
clk_enable(hsudc->uclk); clk_enable(hsudc->uclk);
...@@ -1310,7 +1312,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev) ...@@ -1310,7 +1312,8 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
disable_irq(hsudc->irq); disable_irq(hsudc->irq);
local_irq_enable(); local_irq_enable();
return 0; return 0;
err_clk:
free_irq(hsudc->irq, hsudc);
err_irq: err_irq:
iounmap(hsudc->regs); iounmap(hsudc->regs);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/prefetch.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
......
...@@ -312,8 +312,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device ...@@ -312,8 +312,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
return PTR_ERR(usb_clk); return PTR_ERR(usb_clk);
hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x");
if (!hcd) if (!hcd) {
return -ENOMEM; retval = -ENOMEM;
goto err0;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) { if (!r) {
...@@ -368,6 +370,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device ...@@ -368,6 +370,7 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device
release_mem_region(hcd->rsrc_start, hcd->rsrc_len); release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err1: err1:
usb_put_hcd(hcd); usb_put_hcd(hcd);
err0:
clk_put(usb_clk); clk_put(usb_clk);
return retval; return retval;
} }
......
...@@ -438,13 +438,13 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci, ...@@ -438,13 +438,13 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) { switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
case 0: case SLOT_STATE_ENABLED:
return "enabled/disabled"; return "enabled/disabled";
case 1: case SLOT_STATE_DEFAULT:
return "default"; return "default";
case 2: case SLOT_STATE_ADDRESSED:
return "addressed"; return "addressed";
case 3: case SLOT_STATE_CONFIGURED:
return "configured"; return "configured";
default: default:
return "reserved"; return "reserved";
......
...@@ -985,9 +985,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev, ...@@ -985,9 +985,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
interval = clamp_val(ep->desc.bInterval, 1, 16) - 1; interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
if (interval != ep->desc.bInterval - 1) if (interval != ep->desc.bInterval - 1)
dev_warn(&udev->dev, dev_warn(&udev->dev,
"ep %#x - rounding interval to %d microframes\n", "ep %#x - rounding interval to %d %sframes\n",
ep->desc.bEndpointAddress, ep->desc.bEndpointAddress,
1 << interval); 1 << interval,
udev->speed == USB_SPEED_FULL ? "" : "micro");
if (udev->speed == USB_SPEED_FULL) {
/*
* Full speed isoc endpoints specify interval in frames,
* not microframes. We are using microframes everywhere,
* so adjust accordingly.
*/
interval += 3; /* 1 frame = 2^3 uframes */
}
return interval; return interval;
} }
......
...@@ -106,12 +106,22 @@ static int xhci_pci_setup(struct usb_hcd *hcd) ...@@ -106,12 +106,22 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
/* Look for vendor-specific quirks */ /* Look for vendor-specific quirks */
if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
pdev->revision == 0x0) { if (pdev->revision == 0x0) {
xhci->quirks |= XHCI_RESET_EP_QUIRK; xhci->quirks |= XHCI_RESET_EP_QUIRK;
xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
" endpoint cmd after reset endpoint\n"); " endpoint cmd after reset endpoint\n");
} }
/* Fresco Logic confirms: all revisions of this chip do not
* support MSI, even though some of them claim to in their PCI
* capabilities.
*/
xhci->quirks |= XHCI_BROKEN_MSI;
xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
"has broken MSI implementation\n",
pdev->revision);
}
if (pdev->vendor == PCI_VENDOR_ID_NEC) if (pdev->vendor == PCI_VENDOR_ID_NEC)
xhci->quirks |= XHCI_NEC_HOST; xhci->quirks |= XHCI_NEC_HOST;
......
...@@ -1782,7 +1782,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, ...@@ -1782,7 +1782,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
struct usb_iso_packet_descriptor *frame; struct usb_iso_packet_descriptor *frame;
int idx; int idx;
ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer); ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
urb_priv = td->urb->hcpriv; urb_priv = td->urb->hcpriv;
idx = urb_priv->td_cnt; idx = urb_priv->td_cnt;
frame = &td->urb->iso_frame_desc[idx]; frame = &td->urb->iso_frame_desc[idx];
......
...@@ -430,12 +430,19 @@ int xhci_run(struct usb_hcd *hcd) ...@@ -430,12 +430,19 @@ int xhci_run(struct usb_hcd *hcd)
free_irq(hcd->irq, hcd); free_irq(hcd->irq, hcd);
hcd->irq = -1; hcd->irq = -1;
/* Some Fresco Logic host controllers advertise MSI, but fail to
* generate interrupts. Don't even try to enable MSI.
*/
if (xhci->quirks & XHCI_BROKEN_MSI)
goto legacy_irq;
ret = xhci_setup_msix(xhci); ret = xhci_setup_msix(xhci);
if (ret) if (ret)
/* fall back to msi*/ /* fall back to msi*/
ret = xhci_setup_msi(xhci); ret = xhci_setup_msi(xhci);
if (ret) { if (ret) {
legacy_irq:
/* fall back to legacy interrupt*/ /* fall back to legacy interrupt*/
ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
hcd->irq_descr, hcd); hcd->irq_descr, hcd);
...@@ -1849,8 +1856,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -1849,8 +1856,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
/* Free any rings that were dropped, but not changed. */ /* Free any rings that were dropped, but not changed. */
for (i = 1; i < 31; ++i) { for (i = 1; i < 31; ++i) {
if ((ctrl_ctx->drop_flags & (1 << (i + 1))) && if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
!(ctrl_ctx->add_flags & (1 << (i + 1)))) !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1))))
xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i); xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
} }
xhci_zero_in_ctx(xhci, virt_dev); xhci_zero_in_ctx(xhci, virt_dev);
...@@ -2467,6 +2474,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -2467,6 +2474,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
struct xhci_command *reset_device_cmd; struct xhci_command *reset_device_cmd;
int timeleft; int timeleft;
int last_freed_endpoint; int last_freed_endpoint;
struct xhci_slot_ctx *slot_ctx;
ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__); ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__);
if (ret <= 0) if (ret <= 0)
...@@ -2499,6 +2507,12 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -2499,6 +2507,12 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
return -EINVAL; return -EINVAL;
} }
/* If device is not setup, there is no point in resetting it */
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
SLOT_STATE_DISABLED)
return 0;
xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id); xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
/* Allocate the command structure that holds the struct completion. /* Allocate the command structure that holds the struct completion.
* Assume we're in process context, since the normal device reset * Assume we're in process context, since the normal device reset
......
...@@ -560,6 +560,11 @@ struct xhci_slot_ctx { ...@@ -560,6 +560,11 @@ struct xhci_slot_ctx {
#define SLOT_STATE (0x1f << 27) #define SLOT_STATE (0x1f << 27)
#define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27) #define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27)
#define SLOT_STATE_DISABLED 0
#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED
#define SLOT_STATE_DEFAULT 1
#define SLOT_STATE_ADDRESSED 2
#define SLOT_STATE_CONFIGURED 3
/** /**
* struct xhci_ep_ctx * struct xhci_ep_ctx
...@@ -1302,6 +1307,7 @@ struct xhci_hcd { ...@@ -1302,6 +1307,7 @@ struct xhci_hcd {
* commands. * commands.
*/ */
#define XHCI_EP_LIMIT_QUIRK (1 << 5) #define XHCI_EP_LIMIT_QUIRK (1 << 5)
#define XHCI_BROKEN_MSI (1 << 6)
unsigned int num_active_eps; unsigned int num_active_eps;
unsigned int limit_active_eps; unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */ /* There are two roothubs to keep track of bus suspend info for */
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/prefetch.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -1380,5 +1380,6 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv) ...@@ -1380,5 +1380,6 @@ void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
{ {
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv); struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
kfree(gpriv->uep);
kfree(gpriv); kfree(gpriv);
} }
...@@ -647,6 +647,7 @@ static struct usb_device_id id_table_combined [] = { ...@@ -647,6 +647,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) }, { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
{ USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
......
...@@ -351,6 +351,7 @@ ...@@ -351,6 +351,7 @@
*/ */
#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 #define FTDI_4N_GALAXY_DE_1_PID 0xF3C0
#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 #define FTDI_4N_GALAXY_DE_2_PID 0xF3C1
#define FTDI_4N_GALAXY_DE_3_PID 0xF3C2
/* /*
* Linx Technologies product ids * Linx Technologies product ids
......
...@@ -311,10 +311,6 @@ static void option_instat_callback(struct urb *urb); ...@@ -311,10 +311,6 @@ static void option_instat_callback(struct urb *urb);
#define ZTE_PRODUCT_AC2726 0xfff5 #define ZTE_PRODUCT_AC2726 0xfff5
#define ZTE_PRODUCT_AC8710T 0xffff #define ZTE_PRODUCT_AC8710T 0xffff
/* ZTE PRODUCTS -- alternate vendor ID */
#define ZTE_VENDOR_ID2 0x1d6b
#define ZTE_PRODUCT_MF_330 0x0002
#define BENQ_VENDOR_ID 0x04a5 #define BENQ_VENDOR_ID 0x04a5
#define BENQ_PRODUCT_H10 0x4068 #define BENQ_PRODUCT_H10 0x4068
...@@ -340,11 +336,12 @@ static void option_instat_callback(struct urb *urb); ...@@ -340,11 +336,12 @@ static void option_instat_callback(struct urb *urb);
#define TOSHIBA_PRODUCT_G450 0x0d45 #define TOSHIBA_PRODUCT_G450 0x0d45
#define ALINK_VENDOR_ID 0x1e0e #define ALINK_VENDOR_ID 0x1e0e
#define ALINK_PRODUCT_PH300 0x9100
#define ALINK_PRODUCT_3GU 0x9200 #define ALINK_PRODUCT_3GU 0x9200
/* ALCATEL PRODUCTS */ /* ALCATEL PRODUCTS */
#define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S 0x0000 #define ALCATEL_PRODUCT_X060S_X200 0x0000
#define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_VENDOR_ID 0x1266
#define PIRELLI_PRODUCT_C100_1 0x1002 #define PIRELLI_PRODUCT_C100_1 0x1002
...@@ -379,6 +376,9 @@ static void option_instat_callback(struct urb *urb); ...@@ -379,6 +376,9 @@ static void option_instat_callback(struct urb *urb);
* It seems to contain a Qualcomm QSC6240/6290 chipset */ * It seems to contain a Qualcomm QSC6240/6290 chipset */
#define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603 #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603
/* Zoom */
#define ZOOM_PRODUCT_4597 0x9607
/* Haier products */ /* Haier products */
#define HAIER_VENDOR_ID 0x201e #define HAIER_VENDOR_ID 0x201e
#define HAIER_PRODUCT_CE100 0x2009 #define HAIER_PRODUCT_CE100 0x2009
...@@ -432,6 +432,20 @@ static const struct option_blacklist_info four_g_w14_blacklist = { ...@@ -432,6 +432,20 @@ static const struct option_blacklist_info four_g_w14_blacklist = {
.reason = OPTION_BLACKLIST_SENDSETUP .reason = OPTION_BLACKLIST_SENDSETUP
}; };
static const u8 alcatel_x200_no_sendsetup[] = { 0, 1 };
static const struct option_blacklist_info alcatel_x200_blacklist = {
.infolen = ARRAY_SIZE(alcatel_x200_no_sendsetup),
.ifaceinfo = alcatel_x200_no_sendsetup,
.reason = OPTION_BLACKLIST_SENDSETUP
};
static const u8 zte_k3765_z_no_sendsetup[] = { 0, 1, 2 };
static const struct option_blacklist_info zte_k3765_z_blacklist = {
.infolen = ARRAY_SIZE(zte_k3765_z_no_sendsetup),
.ifaceinfo = zte_k3765_z_no_sendsetup,
.reason = OPTION_BLACKLIST_SENDSETUP
};
static const struct usb_device_id option_ids[] = { static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
...@@ -916,13 +930,13 @@ static const struct usb_device_id option_ids[] = { ...@@ -916,13 +930,13 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ZTE_VENDOR_ID2, ZTE_PRODUCT_MF_330) },
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
{ USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
{ USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
...@@ -935,13 +949,17 @@ static const struct usb_device_id option_ids[] = { ...@@ -935,13 +949,17 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) }, { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
{ USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
.driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
},
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
.driver_info = (kernel_ulong_t)&four_g_w14_blacklist .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
}, },
{ USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
{ USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
/* Pirelli */ /* Pirelli */
{ USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
......
...@@ -819,6 +819,35 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -819,6 +819,35 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
} }
} }
/*
* Some devices don't work or return incorrect data the first
* time they get a READ(10) command, or for the first READ(10)
* after a media change. If the INITIAL_READ10 flag is set,
* keep track of whether READ(10) commands succeed. If the
* previous one succeeded and this one failed, set the REDO_READ10
* flag to force a retry.
*/
if (unlikely((us->fflags & US_FL_INITIAL_READ10) &&
srb->cmnd[0] == READ_10)) {
if (srb->result == SAM_STAT_GOOD) {
set_bit(US_FLIDX_READ10_WORKED, &us->dflags);
} else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) {
clear_bit(US_FLIDX_READ10_WORKED, &us->dflags);
set_bit(US_FLIDX_REDO_READ10, &us->dflags);
}
/*
* Next, if the REDO_READ10 flag is set, return a result
* code that will cause the SCSI core to retry the READ(10)
* command immediately.
*/
if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) {
clear_bit(US_FLIDX_REDO_READ10, &us->dflags);
srb->result = DID_IMM_RETRY << 16;
srb->sense_buffer[0] = 0;
}
}
/* Did we transfer less than the minimum amount required? */ /* Did we transfer less than the minimum amount required? */
if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) && if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow) scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
......
...@@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, ...@@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ), US_FL_FIX_CAPACITY ),
/* Reported by Paul Hartman <paul.hartman+linux@gmail.com>
* This card reader returns "Illegal Request, Logical Block Address
* Out of Range" for the first READ(10) after a new card is inserted.
*/
UNUSUAL_DEV( 0x090c, 0x6000, 0x0100, 0x0100,
"Feiya",
"SD/SDHC Card Reader",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_INITIAL_READ10 ),
/* This Pentax still camera is not conformant /* This Pentax still camera is not conformant
* to the USB storage specification: - * to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command * - It does not like the INQUIRY command. So we must handle this command
...@@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, ...@@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
USB_SC_DEVICE, USB_PR_DEVICE, NULL, USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_READ_DISC_INFO ), US_FL_NO_READ_DISC_INFO ),
/* Reported by Sven Geggus <sven-usbst@geggus.net>
* This encrypted pen drive returns bogus data for the initial READ(10).
*/
UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200,
"Corsair",
"Padlock v2",
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_INITIAL_READ10 ),
/* Patch by Richard Schtz <r.schtz@t-online.de> /* Patch by Richard Schtz <r.schtz@t-online.de>
* This external hard drive enclosure uses a JMicron chip which * This external hard drive enclosure uses a JMicron chip which
* needs the US_FL_IGNORE_RESIDUE flag to work properly. */ * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
......
...@@ -440,7 +440,8 @@ static void adjust_quirks(struct us_data *us) ...@@ -440,7 +440,8 @@ static void adjust_quirks(struct us_data *us)
US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT | US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16); US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
US_FL_INITIAL_READ10);
p = quirks; p = quirks;
while (*p) { while (*p) {
...@@ -490,6 +491,9 @@ static void adjust_quirks(struct us_data *us) ...@@ -490,6 +491,9 @@ static void adjust_quirks(struct us_data *us)
case 'm': case 'm':
f |= US_FL_MAX_SECTORS_64; f |= US_FL_MAX_SECTORS_64;
break; break;
case 'n':
f |= US_FL_INITIAL_READ10;
break;
case 'o': case 'o':
f |= US_FL_CAPACITY_OK; f |= US_FL_CAPACITY_OK;
break; break;
...@@ -953,6 +957,13 @@ int usb_stor_probe2(struct us_data *us) ...@@ -953,6 +957,13 @@ int usb_stor_probe2(struct us_data *us)
if (result) if (result)
goto BadDevice; goto BadDevice;
/*
* If the device returns invalid data for the first READ(10)
* command, indicate the command should be retried.
*/
if (us->fflags & US_FL_INITIAL_READ10)
set_bit(US_FLIDX_REDO_READ10, &us->dflags);
/* Acquire all the other resources and add the host */ /* Acquire all the other resources and add the host */
result = usb_stor_acquire_resources(us); result = usb_stor_acquire_resources(us);
if (result) if (result)
......
...@@ -73,6 +73,8 @@ struct us_unusual_dev { ...@@ -73,6 +73,8 @@ struct us_unusual_dev {
#define US_FLIDX_RESETTING 4 /* device reset in progress */ #define US_FLIDX_RESETTING 4 /* device reset in progress */
#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */ #define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */ #define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
#define USB_STOR_STRING_LEN 32 #define USB_STOR_STRING_LEN 32
......
...@@ -62,7 +62,9 @@ ...@@ -62,7 +62,9 @@
US_FLAG(NO_READ_DISC_INFO, 0x00040000) \ US_FLAG(NO_READ_DISC_INFO, 0x00040000) \
/* cannot handle READ_DISC_INFO */ \ /* cannot handle READ_DISC_INFO */ \
US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \ US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \
/* cannot handle READ_CAPACITY_16 */ /* cannot handle READ_CAPACITY_16 */ \
US_FLAG(INITIAL_READ10, 0x00100000) \
/* Initial READ(10) (and others) must be retried */
#define US_FLAG(name, value) US_FL_##name = value , #define US_FLAG(name, value) US_FL_##name = value ,
enum { US_DO_ALL_FLAGS }; enum { US_DO_ALL_FLAGS };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment