summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig37
-rw-r--r--common/Makefile2
-rw-r--r--common/boot_fit.c6
-rw-r--r--common/common_fit.c20
-rw-r--r--common/dfu.c6
-rw-r--r--common/fb_mmc.c36
-rw-r--r--common/fb_nand.c12
-rw-r--r--common/spl/Kconfig1
-rw-r--r--common/spl/spl_dfu.c4
-rw-r--r--common/spl/spl_mmc.c5
-rw-r--r--common/spl/spl_sdp.c4
-rw-r--r--common/update.c2
-rw-r--r--common/usb.c45
-rw-r--r--common/usb_hub.c16
-rw-r--r--common/usb_storage.c64
15 files changed, 166 insertions, 94 deletions
diff --git a/common/Kconfig b/common/Kconfig
index 540cc9999bc..f96a25f582b 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -241,6 +241,27 @@ config IDENT_STRING
help
This options adds the board specific name to u-boot version.
+config LOGLEVEL
+ int "loglevel"
+ default 4
+ range 0 8
+ help
+ All Messages with a loglevel smaller than the console loglevel will
+ be compiled in. The loglevels are defined as follows:
+
+ 0 (KERN_EMERG) system is unusable
+ 1 (KERN_ALERT) action must be taken immediately
+ 2 (KERN_CRIT) critical conditions
+ 3 (KERN_ERR) error conditions
+ 4 (KERN_WARNING) warning conditions
+ 5 (KERN_NOTICE) normal but significant condition
+ 6 (KERN_INFO) informational
+ 7 (KERN_DEBUG) debug-level messages
+
+config SPL_LOGLEVEL
+ int
+ default LOGLEVEL
+
config SILENT_CONSOLE
bool "Support a silent console"
help
@@ -382,22 +403,6 @@ config SYS_STDIO_DEREGISTER
endmenu
-config DTB_RESELECT
- bool "Support swapping dtbs at a later point in boot"
- depends on FIT_EMBED
- help
- It is possible during initial boot you may need to use a generic
- dtb until you can fully determine the board your running on. This
- config allows boards to implement a function at a later point
- during boot to switch to the "correct" dtb.
-
-config FIT_EMBED
- bool "Support a FIT image embedded in the U-boot image"
- help
- This option provides hooks to allow U-boot to parse an
- appended FIT image and enable board specific code to then select
- the correct DTB to be used.
-
config DEFAULT_FDT_FILE
string "Default fdt file"
help
diff --git a/common/Makefile b/common/Makefile
index 801ea3191f6..cec506fe3e1 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -103,7 +103,7 @@ obj-y += image.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
-obj-$(CONFIG_FIT_EMBED) += boot_fit.o common_fit.o
+obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += image-sig.o
obj-$(CONFIG_IO_TRACE) += iotrace.o
obj-y += memsize.o
diff --git a/common/boot_fit.c b/common/boot_fit.c
index 0a723150b58..add65c4baed 100644
--- a/common/boot_fit.c
+++ b/common/boot_fit.c
@@ -13,7 +13,7 @@
#include <image.h>
#include <libfdt.h>
-int fdt_offset(void *fit)
+static int fdt_offset(const void *fit)
{
int images, node, fdt_len, fdt_node, fdt_offset;
const char *fdt_name;
@@ -55,7 +55,7 @@ int fdt_offset(void *fit)
return fdt_offset;
}
-void *locate_dtb_in_fit(void *fit)
+void *locate_dtb_in_fit(const void *fit)
{
struct image_header *header;
int size;
@@ -73,7 +73,7 @@ void *locate_dtb_in_fit(void *fit)
ret = fdt_offset(fit);
- if (ret <= 0)
+ if (ret < 0)
return NULL;
else
return (void *)fit+size+ret;
diff --git a/common/common_fit.c b/common/common_fit.c
index 5f5f3f9a447..85b33d8c3bc 100644
--- a/common/common_fit.c
+++ b/common/common_fit.c
@@ -32,6 +32,9 @@ int fit_find_config_node(const void *fdt)
{
const char *name;
int conf, node, len;
+ const char *dflt_conf_name;
+ const char *dflt_conf_desc = NULL;
+ int dflt_conf_node = -ENOENT;
conf = fdt_path_offset(fdt, FIT_CONFS_PATH);
if (conf < 0) {
@@ -39,6 +42,9 @@ int fit_find_config_node(const void *fdt)
conf);
return -EINVAL;
}
+
+ dflt_conf_name = fdt_getprop(fdt, conf, "default", &len);
+
for (node = fdt_first_subnode(fdt, conf);
node >= 0;
node = fdt_next_subnode(fdt, node)) {
@@ -50,6 +56,15 @@ int fit_find_config_node(const void *fdt)
#endif
return -EINVAL;
}
+
+ if (dflt_conf_name) {
+ const char *node_name = fdt_get_name(fdt, node, NULL);
+ if (strcmp(dflt_conf_name, node_name) == 0) {
+ dflt_conf_node = node;
+ dflt_conf_desc = name;
+ }
+ }
+
if (board_fit_config_name_match(name))
continue;
@@ -58,5 +73,10 @@ int fit_find_config_node(const void *fdt)
return node;
}
+ if (dflt_conf_node != -ENOENT) {
+ debug("Selecting default config '%s'", dflt_conf_desc);
+ return dflt_conf_node;
+ }
+
return -ENOENT;
}
diff --git a/common/dfu.c b/common/dfu.c
index 546a1ab9b4c..07dff317a6c 100644
--- a/common/dfu.c
+++ b/common/dfu.c
@@ -26,13 +26,13 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
if (ret) {
- error("board usb init failed\n");
+ pr_err("board usb init failed\n");
return CMD_RET_FAILURE;
}
g_dnl_clear_detach();
ret = g_dnl_register(usb_dnl_gadget);
if (ret) {
- error("g_dnl_register failed");
+ pr_err("g_dnl_register failed");
return CMD_RET_FAILURE;
}
@@ -75,7 +75,7 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0);
dfu_set_defer_flush(NULL);
if (ret) {
- error("Deferred dfu_flush() failed!");
+ pr_err("Deferred dfu_flush() failed!");
goto exit;
}
}
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index 26d60b88d0c..cf5b77ca287 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -84,7 +84,7 @@ static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
blkcnt = lldiv(blkcnt, info->blksz);
if (blkcnt > info->size) {
- error("too large for partition: '%s'\n", part_name);
+ pr_err("too large for partition: '%s'\n", part_name);
fastboot_fail("too large for partition");
return;
}
@@ -93,7 +93,7 @@ static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info,
blks = blk_dwrite(dev_desc, info->start, blkcnt, buffer);
if (blks != blkcnt) {
- error("failed writing to device %d\n", dev_desc->devnum);
+ pr_err("failed writing to device %d\n", dev_desc->devnum);
fastboot_fail("failed writing to device");
return;
}
@@ -125,7 +125,7 @@ static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
sector_size = info->blksz;
hdr_sectors = DIV_ROUND_UP(sizeof(struct andr_img_hdr), sector_size);
if (hdr_sectors == 0) {
- error("invalid number of boot sectors: 0");
+ pr_err("invalid number of boot sectors: 0");
fastboot_fail("invalid number of boot sectors: 0");
return 0;
}
@@ -133,7 +133,7 @@ static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
/* Read the boot image header */
res = blk_dread(dev_desc, info->start, hdr_sectors, (void *)hdr);
if (res != hdr_sectors) {
- error("cannot read header from boot partition");
+ pr_err("cannot read header from boot partition");
fastboot_fail("cannot read header from boot partition");
return 0;
}
@@ -141,7 +141,7 @@ static lbaint_t fb_mmc_get_boot_header(struct blk_desc *dev_desc,
/* Check boot header magic string */
res = android_image_check_header(hdr);
if (res != 0) {
- error("bad boot image magic");
+ pr_err("bad boot image magic");
fastboot_fail("boot partition not initialized");
return 0;
}
@@ -179,7 +179,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
/* Get boot partition info */
res = part_get_info_by_name(dev_desc, BOOT_PARTITION_NAME, &info);
if (res < 0) {
- error("cannot find boot partition");
+ pr_err("cannot find boot partition");
fastboot_fail("cannot find boot partition");
return -1;
}
@@ -191,14 +191,14 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
/* Read boot image header */
hdr_sectors = fb_mmc_get_boot_header(dev_desc, &info, hdr);
if (hdr_sectors == 0) {
- error("unable to read boot image header");
+ pr_err("unable to read boot image header");
fastboot_fail("unable to read boot image header");
return -1;
}
/* Check if boot image has second stage in it (we don't support it) */
if (hdr->second_size > 0) {
- error("moving second stage is not supported yet");
+ pr_err("moving second stage is not supported yet");
fastboot_fail("moving second stage is not supported yet");
return -1;
}
@@ -216,7 +216,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
res = blk_dread(dev_desc, ramdisk_sector_start, ramdisk_sectors,
ramdisk_buffer);
if (res != ramdisk_sectors) {
- error("cannot read ramdisk from boot partition");
+ pr_err("cannot read ramdisk from boot partition");
fastboot_fail("cannot read ramdisk from boot partition");
return -1;
}
@@ -225,7 +225,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
hdr->kernel_size = download_bytes;
res = blk_dwrite(dev_desc, info.start, hdr_sectors, (void *)hdr);
if (res == 0) {
- error("cannot writeback boot image header");
+ pr_err("cannot writeback boot image header");
fastboot_fail("cannot write back boot image header");
return -1;
}
@@ -237,7 +237,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
res = blk_dwrite(dev_desc, kernel_sector_start, kernel_sectors,
download_buffer);
if (res == 0) {
- error("cannot write new kernel");
+ pr_err("cannot write new kernel");
fastboot_fail("cannot write new kernel");
return -1;
}
@@ -249,7 +249,7 @@ static int fb_mmc_update_zimage(struct blk_desc *dev_desc,
res = blk_dwrite(dev_desc, ramdisk_sector_start, ramdisk_sectors,
ramdisk_buffer);
if (res == 0) {
- error("cannot write back original ramdisk");
+ pr_err("cannot write back original ramdisk");
fastboot_fail("cannot write back original ramdisk");
return -1;
}
@@ -268,7 +268,7 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer,
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
- error("invalid mmc device\n");
+ pr_err("invalid mmc device\n");
fastboot_fail("invalid mmc device");
return;
}
@@ -322,7 +322,7 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer,
#endif
if (part_get_info_by_name_or_alias(dev_desc, cmd, &info) < 0) {
- error("cannot find partition: '%s'\n", cmd);
+ pr_err("cannot find partition: '%s'\n", cmd);
fastboot_fail("cannot find partition");
return;
}
@@ -360,21 +360,21 @@ void fb_mmc_erase(const char *cmd)
struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (mmc == NULL) {
- error("invalid mmc device");
+ pr_err("invalid mmc device");
fastboot_fail("invalid mmc device");
return;
}
dev_desc = blk_get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV);
if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) {
- error("invalid mmc device");
+ pr_err("invalid mmc device");
fastboot_fail("invalid mmc device");
return;
}
ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info);
if (ret < 0) {
- error("cannot find partition: '%s'", cmd);
+ pr_err("cannot find partition: '%s'", cmd);
fastboot_fail("cannot find partition");
return;
}
@@ -393,7 +393,7 @@ void fb_mmc_erase(const char *cmd)
blks = blk_derase(dev_desc, blks_start, blks_size);
if (blks != blks_size) {
- error("failed erasing from device %d", dev_desc->devnum);
+ pr_err("failed erasing from device %d", dev_desc->devnum);
fastboot_fail("failed erasing from device");
return;
}
diff --git a/common/fb_nand.c b/common/fb_nand.c
index 3d027d43755..aa28046cbd8 100644
--- a/common/fb_nand.c
+++ b/common/fb_nand.c
@@ -40,20 +40,20 @@ static int fb_nand_lookup(const char *partname,
ret = mtdparts_init();
if (ret) {
- error("Cannot initialize MTD partitions\n");
+ pr_err("Cannot initialize MTD partitions\n");
fastboot_fail("cannot init mtdparts");
return ret;
}
ret = find_dev_and_part(partname, &dev, &pnum, part);
if (ret) {
- error("cannot find partition: '%s'", partname);
+ pr_err("cannot find partition: '%s'", partname);
fastboot_fail("cannot find partition");
return ret;
}
if (dev->id->type != MTD_DEV_TYPE_NAND) {
- error("partition '%s' is not stored on a NAND device",
+ pr_err("partition '%s' is not stored on a NAND device",
partname);
fastboot_fail("not a NAND device");
return -EINVAL;
@@ -154,7 +154,7 @@ void fb_nand_flash_write(const char *cmd, void *download_buffer,
ret = fb_nand_lookup(cmd, &mtd, &part);
if (ret) {
- error("invalid NAND device");
+ pr_err("invalid NAND device");
fastboot_fail("invalid NAND device");
return;
}
@@ -209,7 +209,7 @@ void fb_nand_erase(const char *cmd)
ret = fb_nand_lookup(cmd, &mtd, &part);
if (ret) {
- error("invalid NAND device");
+ pr_err("invalid NAND device");
fastboot_fail("invalid NAND device");
return;
}
@@ -220,7 +220,7 @@ void fb_nand_erase(const char *cmd)
ret = _fb_nand_erase(mtd, part);
if (ret) {
- error("failed erasing from device %s", mtd->name);
+ pr_err("failed erasing from device %s", mtd->name);
fastboot_fail("failed erasing from device");
return;
}
diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index b05ec21ed62..0bd8370337b 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -94,6 +94,7 @@ config SPL_STACK_R
config SPL_STACK_R_ADDR
depends on SPL_STACK_R
hex "SDRAM location for SPL stack"
+ default 0x82000000 if ARCH_OMAP2PLUS
help
Specify the address in SDRAM for the SPL stack. This will be set up
before board_init_r() is called.
diff --git a/common/spl/spl_dfu.c b/common/spl/spl_dfu.c
index 2c974735b11..05bb21035df 100644
--- a/common/spl/spl_dfu.c
+++ b/common/spl/spl_dfu.c
@@ -42,13 +42,13 @@ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr)
set_default_env(0);
str_env = env_get(dfu_alt_info);
if (!str_env) {
- error("\"dfu_alt_info\" env variable not defined!\n");
+ pr_err("\"dfu_alt_info\" env variable not defined!\n");
return -EINVAL;
}
ret = env_set("dfu_alt_info", str_env);
if (ret) {
- error("unable to set env variable \"dfu_alt_info\"!\n");
+ pr_err("unable to set env variable \"dfu_alt_info\"!\n");
return -EINVAL;
}
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index b2cccc6c6e4..b57e0b04e46 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -52,8 +52,9 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf);
}
-static int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
- struct mmc *mmc, unsigned long sector)
+static __maybe_unused
+int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
+ struct mmc *mmc, unsigned long sector)
{
unsigned long count;
struct image_header *header;
diff --git a/common/spl/spl_sdp.c b/common/spl/spl_sdp.c
index 350bcdb0569..333d518f4d6 100644
--- a/common/spl/spl_sdp.c
+++ b/common/spl/spl_sdp.c
@@ -24,13 +24,13 @@ static int spl_sdp_load_image(struct spl_image_info *spl_image,
ret = sdp_init(controller_index);
if (ret) {
- error("SDP init failed: %d", ret);
+ pr_err("SDP init failed: %d", ret);
return -ENODEV;
}
/* This command typically does not return but jumps to an image */
sdp_handle(controller_index);
- error("SDP ended");
+ pr_err("SDP ended");
return -EINVAL;
}
diff --git a/common/update.c b/common/update.c
index 974f4655e7e..33bffaa89ec 100644
--- a/common/update.c
+++ b/common/update.c
@@ -242,7 +242,7 @@ int update_tftp(ulong addr, char *interface, char *devstring)
} else if (interface && devstring) {
update_tftp_dfu = true;
} else {
- error("Interface: %s and devstring: %s not supported!\n",
+ pr_err("Interface: %s and devstring: %s not supported!\n",
interface, devstring);
return -EINVAL;
}
diff --git a/common/usb.c b/common/usb.c
index 09042597573..8d27bc70607 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -437,12 +437,13 @@ static int usb_parse_config(struct usb_device *dev,
}
break;
case USB_DT_ENDPOINT:
- if (head->bLength != USB_DT_ENDPOINT_SIZE) {
+ if (head->bLength != USB_DT_ENDPOINT_SIZE &&
+ head->bLength != USB_DT_ENDPOINT_AUDIO_SIZE) {
printf("ERROR: Invalid USB EP length (%d)\n",
head->bLength);
break;
}
- if (index + USB_DT_ENDPOINT_SIZE >
+ if (index + head->bLength >
dev->config.desc.wTotalLength) {
puts("USB EP descriptor overflowed buffer!\n");
break;
@@ -969,23 +970,24 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read)
dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
- if (do_read) {
+ if (do_read && dev->speed == USB_SPEED_FULL) {
int err;
/*
- * Validate we've received only at least 8 bytes, not that we've
- * received the entire descriptor. The reasoning is:
- * - The code only uses fields in the first 8 bytes, so that's all we
- * need to have fetched at this stage.
- * - The smallest maxpacket size is 8 bytes. Before we know the actual
- * maxpacket the device uses, the USB controller may only accept a
- * single packet. Consequently we are only guaranteed to receive 1
- * packet (at least 8 bytes) even in a non-error case.
+ * Validate we've received only at least 8 bytes, not that
+ * we've received the entire descriptor. The reasoning is:
+ * - The code only uses fields in the first 8 bytes, so
+ * that's all we need to have fetched at this stage.
+ * - The smallest maxpacket size is 8 bytes. Before we know
+ * the actual maxpacket the device uses, the USB controller
+ * may only accept a single packet. Consequently we are only
+ * guaranteed to receive 1 packet (at least 8 bytes) even in
+ * a non-error case.
*
- * At least the DWC2 controller needs to be programmed with the number
- * of packets in addition to the number of bytes. A request for 64
- * bytes of data with the maxpacket guessed as 64 (above) yields a
- * request for 1 packet.
+ * At least the DWC2 controller needs to be programmed with
+ * the number of packets in addition to the number of bytes.
+ * A request for 64 bytes of data with the maxpacket guessed
+ * as 64 (above) yields a request for 1 packet.
*/
err = get_descriptor_len(dev, 64, 8);
if (err)
@@ -1008,7 +1010,7 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read)
dev->maxpacketsize = PACKET_SIZE_64;
break;
default:
- printf("usb_new_device: invalid max packet size\n");
+ printf("%s: invalid max packet size\n", __func__);
return -EIO;
}
@@ -1050,6 +1052,17 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
mdelay(10); /* Let the SET_ADDRESS settle */
+ /*
+ * If we haven't read device descriptor before, read it here
+ * after device is assigned an address. This is only applicable
+ * to xHCI so far.
+ */
+ if (!do_read) {
+ err = usb_setup_descriptor(dev, true);
+ if (err)
+ return err;
+ }
+
return 0;
}
diff --git a/common/usb_hub.c b/common/usb_hub.c
index 86a34776643..325d16dfc86 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -489,6 +489,17 @@ static int usb_scan_port(struct usb_device_scan *usb_scan)
return 0;
}
+ if (portchange & USB_PORT_STAT_C_RESET) {
+ debug("port %d reset change\n", i + 1);
+ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
+ }
+
+ if ((portchange & USB_SS_PORT_STAT_C_BH_RESET) &&
+ usb_hub_is_superspeed(dev)) {
+ debug("port %d BH reset change\n", i + 1);
+ usb_clear_port_feature(dev, i + 1, USB_SS_PORT_FEAT_C_BH_RESET);
+ }
+
/* A new USB device is ready at this point */
debug("devnum=%d port=%d: USB dev found\n", dev->devnum, i + 1);
@@ -543,11 +554,6 @@ static int usb_scan_port(struct usb_device_scan *usb_scan)
hub->overcurrent_count[i]);
}
- if (portchange & USB_PORT_STAT_C_RESET) {
- debug("port %d reset change\n", i + 1);
- usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
- }
-
/*
* We're done with this device, so let's remove this device from
* scanning list
diff --git a/common/usb_storage.c b/common/usb_storage.c
index df0b0573087..a91b1c0d2f9 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -98,19 +98,9 @@ struct us_data {
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
static struct us_data usb_stor[USB_MAX_STOR_DEV];
#endif
@@ -949,6 +939,38 @@ do_retry:
return USB_STOR_TRANSPORT_FAILED;
}
+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
+ * there is enough free heap space left, but the SCSI READ(10) and
+ * WRITE(10) commands are limited to 65535 blocks.
+ */
+ blk = USHRT_MAX;
+#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)
+ size = USHRT_MAX * 512;
+ blk = size / 512;
+ }
+#endif
+
+ us->max_xfer_blk = blk;
+}
static int usb_inquiry(struct scsi_cmd *srb, struct us_data *ss)
{
@@ -1150,12 +1172,12 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
/* 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;
@@ -1178,7 +1200,7 @@ retry_it:
start, smallblks, buf_addr);
usb_disable_asynch(0); /* asynch transfer allowed */
- if (blkcnt >= USB_MAX_XFER_BLK)
+ if (blkcnt >= ss->max_xfer_blk)
debug("\n");
return blkcnt;
}
@@ -1236,12 +1258,12 @@ 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;
@@ -1263,7 +1285,7 @@ retry_it:
PRIxPTR "\n", start, smallblks, buf_addr);
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;
}