diff --git a/ChangeLog b/ChangeLog index e08ce2653ba..9be16a33a64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5522,4 +5522,8 @@ (2013-9-6). * drivers/usbdev/usbmsc_desc.c: Fix a warning when USB MSC is compiled for a high-speed device (2013-9-7). + * drivers/usbhost/usbhost_storage.c: If device is returning fatal + transfer errors while attempt to initialize, don't bother with + the startup retries; abort immediately so that the device will + be reset and we can try again (2013-9-9). diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c index 08bc9df8bf7..fc4f4e92c7a 100644 --- a/arch/arm/src/lpc17xx/lpc17_usbhost.c +++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c @@ -1304,7 +1304,7 @@ static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid, else { uvdbg("Bad TD completion status: %d\n", EDCTRL->tdstatus); - ret = -EIO; + ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO; } } diff --git a/arch/arm/src/sama5/sam_ohci.c b/arch/arm/src/sama5/sam_ohci.c index d943d01d904..a59d441b072 100644 --- a/arch/arm/src/sama5/sam_ohci.c +++ b/arch/arm/src/sama5/sam_ohci.c @@ -2991,7 +2991,7 @@ static int sam_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep, else { udbg("ERROR: Bad TD completion status: %d\n", ed->tdstatus); - ret = -EIO; + ret = ed->tdstatus == TD_CC_STALL ? -EPERM : -EIO; } } diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c index d72203bdf15..c6126131f9b 100644 --- a/drivers/usbhost/usbhost_storage.c +++ b/drivers/usbhost/usbhost_storage.c @@ -1248,6 +1248,19 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv) uvdbg("Request sense\n"); ret = usbhost_requestsense(priv); } + + /* It is acceptable for a mass storage device to respond to the + * Test Unit Ready and Request Sense commands with a stall if it is + * unable to respond. But other failures mean that something is + * wrong and a device reset is in order. The transfer functions will + * return -EPERM if the transfer failed due to a stall. + */ + + if (ret < 0 && ret != -EPERM) + { + udbg("ERROR: DRVR_TRANSFER returned: %d\n", ret); + break; + } } /* Did the unit become ready? Did an error occur? Or did we time out? */ @@ -1569,6 +1582,7 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv) priv->tbuffer = NULL; priv->tbuflen = 0; } + return result; }