Merge branch '2020-05-15-kconfig-migrations'
[oweals/u-boot.git] / common / usb_storage.c
index 03171f74cb02849571eaee69561c12d1957c6161..b291ac55d14542fa47af0c941d67598082adfbe7 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Most of this source has been derived from the Linux USB
  * project:
@@ -17,8 +18,6 @@
  *
  * BBB support based on /sys/dev/usb/umass.c from
  * FreeBSD.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /* Note:
@@ -37,7 +36,6 @@
 #include <command.h>
 #include <dm.h>
 #include <errno.h>
-#include <inttypes.h>
 #include <mapmem.h>
 #include <memalign.h>
 #include <asm/byteorder.h>
@@ -63,17 +61,17 @@ static const unsigned char us_direction[256/8] = {
 };
 #define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
 
-static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
+static struct scsi_cmd usb_ccb __aligned(ARCH_DMA_MINALIGN);
 static __u32 CBWTag;
 
 static int usb_max_devs; /* number of highest available usb device */
 
-#ifndef CONFIG_BLK
+#if !CONFIG_IS_ENABLED(BLK)
 static struct blk_desc usb_dev_desc[USB_MAX_STOR_DEV];
 #endif
 
 struct us_data;
-typedef int (*trans_cmnd)(ccb *cb, struct us_data *data);
+typedef int (*trans_cmnd)(struct scsi_cmd *cb, struct us_data *data);
 typedef int (*trans_reset)(struct us_data *data);
 
 struct us_data {
@@ -95,23 +93,13 @@ struct us_data {
        unsigned int    irqpipe;                /* pipe for release_irq */
        unsigned char   irqmaxp;                /* max packed for irq Pipe */
        unsigned char   irqinterval;            /* Intervall for IRQ Pipe */
-       ccb             *srb;                   /* current srb */
+       struct scsi_cmd *srb;                   /* current srb */
        trans_reset     transport_reset;        /* reset routine */
        trans_cmnd      transport;              /* transport routine */
+       unsigned short  max_xfer_blk;           /* maximum transfer blocks */
 };
 
-#ifdef CONFIG_USB_EHCI_HCD
-/*
- * The U-Boot EHCI driver can handle any transfer length as long as there is
- * enough free heap space left, but the SCSI READ(10) and WRITE(10) commands are
- * limited to 65535 blocks.
- */
-#define USB_MAX_XFER_BLK       65535
-#else
-#define USB_MAX_XFER_BLK       20
-#endif
-
-#ifndef CONFIG_BLK
+#if !CONFIG_IS_ENABLED(BLK)
 static struct us_data usb_stor[USB_MAX_STOR_DEV];
 #endif
 
@@ -123,7 +111,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
                      struct blk_desc *dev_desc);
 int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
                      struct us_data *ss);
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
                                   lbaint_t blkcnt, void *buffer);
 static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
@@ -148,7 +136,7 @@ static void usb_show_progress(void)
 int usb_stor_info(void)
 {
        int count = 0;
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
        struct udevice *dev;
 
        for (blk_first_device(IF_TYPE_USB, &dev);
@@ -198,7 +186,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
 {
        int lun, max_lun;
 
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
        struct us_data *data;
        int ret;
 #else
@@ -209,7 +197,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
 #endif
 
        debug("\n\nProbing for storage\n");
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
        /*
         * We store the us_data in the mass storage device's platdata. It
         * is shared by all LUNs (block devices) attached to this mass storage
@@ -238,9 +226,7 @@ static int usb_stor_probe_device(struct usb_device *udev)
                blkdev->lun = lun;
 
                ret = usb_stor_get_info(udev, data, blkdev);
-               if (ret == 1)
-                       ret = blk_prepare_device(dev);
-               if (!ret) {
+               if (ret == 1) {
                        usb_max_devs++;
                        debug("%s: Found device %p\n", __func__, udev);
                } else {
@@ -313,7 +299,7 @@ int usb_stor_scan(int mode)
        if (mode == 1)
                printf("       scanning usb for storage devices... ");
 
-#ifndef CONFIG_DM_USB
+#if !CONFIG_IS_ENABLED(DM_USB)
        unsigned char i;
 
        usb_disable_asynch(1); /* asynch transfer not allowed */
@@ -349,7 +335,7 @@ static int usb_stor_irq(struct usb_device *dev)
 
 #ifdef DEBUG
 
-static void usb_show_srb(ccb *pccb)
+static void usb_show_srb(struct scsi_cmd *pccb)
 {
        int i;
        printf("SRB: len %d datalen 0x%lX\n ", pccb->cmdlen, pccb->datalen);
@@ -541,7 +527,7 @@ static int usb_stor_CB_reset(struct us_data *us)
  * Set up the command for a BBB device. Note that the actual SCSI
  * command is copied into cbw.CBWCDB.
  */
-static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
+static int usb_stor_BBB_comdat(struct scsi_cmd *srb, struct us_data *us)
 {
        int result;
        int actlen;
@@ -590,7 +576,7 @@ static int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
 /* FIXME: we also need a CBI_command which sets up the completion
  * interrupt, and waits for it
  */
-static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
+static int usb_stor_CB_comdat(struct scsi_cmd *srb, struct us_data *us)
 {
        int result = 0;
        int dir_in, retry;
@@ -659,13 +645,13 @@ static int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
 }
 
 
-static int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
+static int usb_stor_CBI_get_status(struct scsi_cmd *srb, struct us_data *us)
 {
        int timeout;
 
        us->ip_wanted = 1;
-       submit_int_msg(us->pusb_dev, us->irqpipe,
-                       (void *) &us->ip_data, us->irqmaxp, us->irqinterval);
+       usb_int_msg(us->pusb_dev, us->irqpipe,
+                   (void *)&us->ip_data, us->irqmaxp, us->irqinterval, false);
        timeout = 1000;
        while (timeout--) {
                if (us->ip_wanted == 0)
@@ -714,7 +700,7 @@ static int usb_stor_BBB_clear_endpt_stall(struct us_data *us, __u8 endpt)
                               endpt, NULL, 0, USB_CNTL_TIMEOUT * 5);
 }
 
-static int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
+static int usb_stor_BBB_transport(struct scsi_cmd *srb, struct us_data *us)
 {
        int result, retry;
        int dir_in;
@@ -837,11 +823,11 @@ again:
        return result;
 }
 
-static int usb_stor_CB_transport(ccb *srb, struct us_data *us)
+static int usb_stor_CB_transport(struct scsi_cmd *srb, struct us_data *us)
 {
        int result, status;
-       ccb *psrb;
-       ccb reqsrb;
+       struct scsi_cmd *psrb;
+       struct scsi_cmd reqsrb;
        int retry, notready;
 
        psrb = &reqsrb;
@@ -949,8 +935,41 @@ do_retry:
        return USB_STOR_TRANSPORT_FAILED;
 }
 
+static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
+                                     struct us_data *us)
+{
+       /*
+        * Limit the total size of a transfer to 120 KB.
+        *
+        * Some devices are known to choke with anything larger. It seems like
+        * the problem stems from the fact that original IDE controllers had
+        * only an 8-bit register to hold the number of sectors in one transfer
+        * and even those couldn't handle a full 256 sectors.
+        *
+        * Because we want to make sure we interoperate with as many devices as
+        * possible, we will maintain a 240 sector transfer size limit for USB
+        * Mass Storage devices.
+        *
+        * Tests show that other operating have similar limits with Microsoft
+        * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
+        * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
+        * and 2048 for USB3 devices.
+        */
+       unsigned short blk = 240;
+
+#if CONFIG_IS_ENABLED(DM_USB)
+       size_t size;
+       int ret;
+
+       ret = usb_get_max_xfer_size(udev, (size_t *)&size);
+       if ((ret >= 0) && (size < blk * 512))
+               blk = size / 512;
+#endif
 
-static int usb_inquiry(ccb *srb, struct us_data *ss)
+       us->max_xfer_blk = blk;
+}
+
+static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
 {
        int retry, i;
        retry = 5;
@@ -974,7 +993,7 @@ static int usb_inquiry(ccb *srb, struct us_data *ss)
        return 0;
 }
 
-static int usb_request_sense(ccb *srb, struct us_data *ss)
+static int usb_request_sense(struct scsi_cmd *srb, struct us_data *ss)
 {
        char *ptr;
 
@@ -994,7 +1013,7 @@ static int usb_request_sense(ccb *srb, struct us_data *ss)
        return 0;
 }
 
-static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
+static int usb_test_unit_ready(struct scsi_cmd *srb, struct us_data *ss)
 {
        int retries = 10;
 
@@ -1025,7 +1044,7 @@ static int usb_test_unit_ready(ccb *srb, struct us_data *ss)
        return -1;
 }
 
-static int usb_read_capacity(ccb *srb, struct us_data *ss)
+static int usb_read_capacity(struct scsi_cmd *srb, struct us_data *ss)
 {
        int retry;
        /* XXX retries */
@@ -1043,8 +1062,8 @@ static int usb_read_capacity(ccb *srb, struct us_data *ss)
        return -1;
 }
 
-static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
-                      unsigned short blocks)
+static int usb_read_10(struct scsi_cmd *srb, struct us_data *ss,
+                      unsigned long start, unsigned short blocks)
 {
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_READ10;
@@ -1060,8 +1079,8 @@ static int usb_read_10(ccb *srb, struct us_data *ss, unsigned long start,
        return ss->transport(srb, ss);
 }
 
-static int usb_write_10(ccb *srb, struct us_data *ss, unsigned long start,
-                       unsigned short blocks)
+static int usb_write_10(struct scsi_cmd *srb, struct us_data *ss,
+                       unsigned long start, unsigned short blocks)
 {
        memset(&srb->cmd[0], 0, 12);
        srb->cmd[0] = SCSI_WRITE10;
@@ -1101,7 +1120,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
 }
 #endif /* CONFIG_USB_BIN_FIXUP */
 
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 static unsigned long usb_stor_read(struct udevice *dev, lbaint_t blknr,
                                   lbaint_t blkcnt, void *buffer)
 #else
@@ -1115,15 +1134,15 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
        struct usb_device *udev;
        struct us_data *ss;
        int retry;
-       ccb *srb = &usb_ccb;
-#ifdef CONFIG_BLK
+       struct scsi_cmd *srb = &usb_ccb;
+#if CONFIG_IS_ENABLED(BLK)
        struct blk_desc *block_dev;
 #endif
 
        if (blkcnt == 0)
                return 0;
        /* Setup  device */
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
        block_dev = dev_get_uclass_platdata(dev);
        udev = dev_get_parent_priv(dev_get_parent(dev));
        debug("\nusb_read: udev %d\n", block_dev->devnum);
@@ -1138,29 +1157,31 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
        ss = (struct us_data *)udev->privptr;
 
        usb_disable_asynch(1); /* asynch transfer not allowed */
+       usb_lock_async(udev, 1);
        srb->lun = block_dev->lun;
        buf_addr = (uintptr_t)buffer;
        start = blknr;
        blks = blkcnt;
 
-       debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
-             PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
+       debug("\nusb_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
+             block_dev->devnum, start, blks, buf_addr);
 
        do {
                /* XXX need some comment here */
                retry = 2;
                srb->pdata = (unsigned char *)buf_addr;
-               if (blks > USB_MAX_XFER_BLK)
-                       smallblks = USB_MAX_XFER_BLK;
+               if (blks > ss->max_xfer_blk)
+                       smallblks = ss->max_xfer_blk;
                else
                        smallblks = (unsigned short) blks;
 retry_it:
-               if (smallblks == USB_MAX_XFER_BLK)
+               if (smallblks == ss->max_xfer_blk)
                        usb_show_progress();
                srb->datalen = block_dev->blksz * smallblks;
                srb->pdata = (unsigned char *)buf_addr;
                if (usb_read_10(srb, ss, start, smallblks)) {
                        debug("Read ERROR\n");
+                       ss->flags &= ~USB_READY;
                        usb_request_sense(srb, ss);
                        if (retry--)
                                goto retry_it;
@@ -1171,19 +1192,18 @@ retry_it:
                blks -= smallblks;
                buf_addr += srb->datalen;
        } while (blks != 0);
-       ss->flags &= ~USB_READY;
 
-       debug("usb_read: end startblk " LBAF
-             ", blccnt %x buffer %" PRIxPTR "\n",
+       debug("usb_read: end startblk " LBAF ", blccnt %x buffer %lx\n",
              start, smallblks, buf_addr);
 
+       usb_lock_async(udev, 0);
        usb_disable_asynch(0); /* asynch transfer allowed */
-       if (blkcnt >= USB_MAX_XFER_BLK)
+       if (blkcnt >= ss->max_xfer_blk)
                debug("\n");
        return blkcnt;
 }
 
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 static unsigned long usb_stor_write(struct udevice *dev, lbaint_t blknr,
                                    lbaint_t blkcnt, const void *buffer)
 #else
@@ -1197,8 +1217,8 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
        struct usb_device *udev;
        struct us_data *ss;
        int retry;
-       ccb *srb = &usb_ccb;
-#ifdef CONFIG_BLK
+       struct scsi_cmd *srb = &usb_ccb;
+#if CONFIG_IS_ENABLED(BLK)
        struct blk_desc *block_dev;
 #endif
 
@@ -1206,7 +1226,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
                return 0;
 
        /* Setup  device */
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
        block_dev = dev_get_uclass_platdata(dev);
        udev = dev_get_parent_priv(dev_get_parent(dev));
        debug("\nusb_read: udev %d\n", block_dev->devnum);
@@ -1221,14 +1241,15 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
        ss = (struct us_data *)udev->privptr;
 
        usb_disable_asynch(1); /* asynch transfer not allowed */
+       usb_lock_async(udev, 1);
 
        srb->lun = block_dev->lun;
        buf_addr = (uintptr_t)buffer;
        start = blknr;
        blks = blkcnt;
 
-       debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %"
-             PRIxPTR "\n", block_dev->devnum, start, blks, buf_addr);
+       debug("\nusb_write: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n",
+             block_dev->devnum, start, blks, buf_addr);
 
        do {
                /* If write fails retry for max retry count else
@@ -1236,17 +1257,18 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
                 */
                retry = 2;
                srb->pdata = (unsigned char *)buf_addr;
-               if (blks > USB_MAX_XFER_BLK)
-                       smallblks = USB_MAX_XFER_BLK;
+               if (blks > ss->max_xfer_blk)
+                       smallblks = ss->max_xfer_blk;
                else
                        smallblks = (unsigned short) blks;
 retry_it:
-               if (smallblks == USB_MAX_XFER_BLK)
+               if (smallblks == ss->max_xfer_blk)
                        usb_show_progress();
                srb->datalen = block_dev->blksz * smallblks;
                srb->pdata = (unsigned char *)buf_addr;
                if (usb_write_10(srb, ss, start, smallblks)) {
                        debug("Write ERROR\n");
+                       ss->flags &= ~USB_READY;
                        usb_request_sense(srb, ss);
                        if (retry--)
                                goto retry_it;
@@ -1257,13 +1279,13 @@ retry_it:
                blks -= smallblks;
                buf_addr += srb->datalen;
        } while (blks != 0);
-       ss->flags &= ~USB_READY;
 
-       debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
-             PRIxPTR "\n", start, smallblks, buf_addr);
+       debug("usb_write: end startblk " LBAF ", blccnt %x buffer %lx\n",
+             start, smallblks, buf_addr);
 
+       usb_lock_async(udev, 0);
        usb_disable_asynch(0); /* asynch transfer allowed */
-       if (blkcnt >= USB_MAX_XFER_BLK)
+       if (blkcnt >= ss->max_xfer_blk)
                debug("\n");
        return blkcnt;
 
@@ -1384,6 +1406,10 @@ int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
                ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
                dev->irq_handle = usb_stor_irq;
        }
+
+       /* Set the maximum transfer size per host controller setting */
+       usb_stor_set_max_xfer_blk(dev, ss);
+
        dev->privptr = (void *)ss;
        return 1;
 }
@@ -1395,7 +1421,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
        ALLOC_CACHE_ALIGN_BUFFER(u32, cap, 2);
        ALLOC_CACHE_ALIGN_BUFFER(u8, usb_stor_buf, 36);
        u32 capacity, blksz;
-       ccb *pccb = &usb_ccb;
+       struct scsi_cmd *pccb = &usb_ccb;
 
        pccb->pdata = usb_stor_buf;
 
@@ -1448,10 +1474,10 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
        memset(pccb->pdata, 0, 8);
        if (usb_read_capacity(pccb, ss) != 0) {
                printf("READ_CAP ERROR\n");
+               ss->flags &= ~USB_READY;
                cap[0] = 2880;
                cap[1] = 0x200;
        }
-       ss->flags &= ~USB_READY;
        debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
 #if 0
        if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
@@ -1474,7 +1500,7 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
        return 1;
 }
 
-#ifdef CONFIG_DM_USB
+#if CONFIG_IS_ENABLED(DM_USB)
 
 static int usb_mass_storage_probe(struct udevice *dev)
 {
@@ -1498,7 +1524,7 @@ U_BOOT_DRIVER(usb_mass_storage) = {
        .id     = UCLASS_MASS_STORAGE,
        .of_match = usb_mass_storage_ids,
        .probe = usb_mass_storage_probe,
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
        .platdata_auto_alloc_size       = sizeof(struct us_data),
 #endif
 };
@@ -1519,7 +1545,7 @@ static const struct usb_device_id mass_storage_id_table[] = {
 U_BOOT_USB_DEVICE(usb_mass_storage, mass_storage_id_table);
 #endif
 
-#ifdef CONFIG_BLK
+#if CONFIG_IS_ENABLED(BLK)
 static const struct blk_ops usb_storage_ops = {
        .read   = usb_stor_read,
        .write  = usb_stor_write,