diff options
author | Bin Meng <bmeng.cn@gmail.com> | 2017-09-07 06:13:21 -0700 |
---|---|---|
committer | Marek Vasut <marek.vasut+renesas@gmail.com> | 2017-09-27 12:12:22 +0200 |
commit | ea7fad91019654fb21e6cd04f963e0482869dba5 (patch) | |
tree | fda467518c0097d2ccecdf60d4450b9020c32571 /common | |
parent | 6158d0b42411165d34635a2ddfea17e12dce3329 (diff) | |
download | u-boot-ea7fad91019654fb21e6cd04f963e0482869dba5.zip u-boot-ea7fad91019654fb21e6cd04f963e0482869dba5.tar.gz u-boot-ea7fad91019654fb21e6cd04f963e0482869dba5.tar.bz2 |
dm: usb: storage: Fix broken read/write when both EHCD and xHCD are enabled
When EHCD and xHCD are enabled at the same time, USB storage device
driver will fail to read/write from/to the storage device attached
to the xHCI interface, due to its transfer blocks exceeds the xHCD
driver limitation.
With driver model, we have an API to get the controller's maximum
transfer size and we can use that to determine the storage driver's
capability of read/write.
Note: the non-DM version driver is still broken with xHCD and the
intent here is not to fix the non-DM one, since the xHCD itself is
already broken in places like 3.0 hub support, etc.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'common')
-rw-r--r-- | common/usb_storage.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/common/usb_storage.c b/common/usb_storage.c index 957ccdb..a57570b 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -939,10 +939,14 @@ do_retry: return USB_STOR_TRANSPORT_FAILED; } -static void usb_stor_set_max_xfer_blk(struct us_data *us) +static void usb_stor_set_max_xfer_blk(struct usb_device *udev, + struct us_data *us) { unsigned short blk; + size_t __maybe_unused size; + int __maybe_unused ret; +#ifndef CONFIG_DM_USB #ifdef CONFIG_USB_EHCI_HCD /* * The U-Boot EHCI driver can handle any transfer length as long as @@ -953,6 +957,17 @@ static void usb_stor_set_max_xfer_blk(struct us_data *us) #else blk = 20; #endif +#else + ret = usb_get_max_xfer_size(udev, (size_t *)&size); + if (ret < 0) { + /* unimplemented, let's use default 20 */ + blk = 20; + } else { + if (size > USHRT_MAX * 512) + blk = USHRT_MAX; + blk = size / 512; + } +#endif us->max_xfer_blk = blk; } @@ -1393,7 +1408,7 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum, } /* Set the maximum transfer size per host controller setting */ - usb_stor_set_max_xfer_blk(ss); + usb_stor_set_max_xfer_blk(dev, ss); dev->privptr = (void *)ss; return 1; |