I have prepared an alternative version (v4) of this patch, and will
attach it below. (github is also updated, so you may retrieve the
patches from https://github.com/linux-sunxi/sunxi-tools/pull/35
alternatively)
progress_chunk_size() was renamed to get_chunk_size(), als I think that
makes the 'isolated' call in aw_write_buffer() easier to understand.
This patch also uses a new field "write_speed" in soc_sram_info,
eliminating the need to keep track of and update soc_id values in
get_chunk_size().
Regards, B. Nortmann
--
You received this message because you are subscribed to the Google Groups
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
>From 0048164c530839ed4845d9d5609a0115f4912699 Mon Sep 17 00:00:00 2001
From: Bernhard Nortmann <[email protected]>
Date: Mon, 16 Nov 2015 18:45:54 +0100
Subject: [PATCH v4 5/9] sunxi-tools: refine progress updates by adjusting
transfer chunk size
Signed-off-by: Bernhard Nortmann <[email protected]>
---
fel.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/fel.c b/fel.c
index aa30fa6..176aa1e 100644
--- a/fel.c
+++ b/fel.c
@@ -79,12 +79,18 @@ static void pr_info(const char *fmt, ...)
}
}
-static const int AW_USB_MAX_BULK_SEND = 4 * 1024 * 1024; // 4 MiB per bulk
request
+static const size_t AW_USB_MAX_BULK_SEND = 4 * 1024 * 1024; // 4 MiB per bulk
request
+static size_t get_chunk_size(libusb_device_handle *usb); /* forward
declaration */
void usb_bulk_send(libusb_device_handle *usb, int ep, const void *data,
size_t length, bool progress)
{
- size_t max_chunk = AW_USB_MAX_BULK_SEND; /* maximum chunk size */
+ /*
+ * With no progress notifications, we'll use the maximum chunk size.
+ * Otherwise, it's useful to lower the value (= have smaller chunks)
+ * to get more frequent status updates.
+ */
+ size_t max_chunk = progress ? get_chunk_size(usb) :
AW_USB_MAX_BULK_SEND;
size_t chunk, total = length;
int rc, sent;
@@ -295,6 +301,14 @@ double aw_write_buffer(libusb_device_handle *usb, void
*buf, uint32_t offset,
uboot_entry, uboot_entry + uboot_size);
exit(1);
}
+
+ /*
+ * Calculating chunk size may enforce an AW_FEL_VERSION request. If
needed,
+ * let's get that out of the way - so it doesn't interfere later.
+ */
+ if (progress)
+ get_chunk_size(usb); /* possibly calls aw_fel_get_sram_info() */
+
double start = gettime();
aw_send_fel_request(usb, AW_FEL_1_WRITE, offset, len);
aw_usb_write(usb, buf, len, progress);
@@ -424,6 +438,7 @@ typedef struct {
uint32_t thunk_addr; /* Address of the thunk code */
uint32_t thunk_size; /* Maximal size of the thunk code */
uint32_t needs_l2en; /* Set the L2EN bit */
+ uint32_t write_speed; /* approx. FEL write speed, in KiB/s */
sram_swap_buffers *swap_buffers;
} soc_sram_info;
@@ -461,6 +476,7 @@ soc_sram_info soc_sram_info_table[] = {
.thunk_addr = 0xAE00, .thunk_size = 0x200,
.swap_buffers = a10_a13_a20_sram_swap_buffers,
.needs_l2en = 1,
+ .write_speed = 512,
},
{
.soc_id = 0x1625, /* Allwinner A13 */
@@ -468,12 +484,14 @@ soc_sram_info soc_sram_info_table[] = {
.thunk_addr = 0xAE00, .thunk_size = 0x200,
.swap_buffers = a10_a13_a20_sram_swap_buffers,
.needs_l2en = 1,
+ .write_speed = 512,
},
{
.soc_id = 0x1651, /* Allwinner A20 */
.scratch_addr = 0x2000,
.thunk_addr = 0xAE00, .thunk_size = 0x200,
.swap_buffers = a10_a13_a20_sram_swap_buffers,
+ .write_speed = 512,
},
{
.soc_id = 0x1650, /* Allwinner A23 */
@@ -486,6 +504,7 @@ soc_sram_info soc_sram_info_table[] = {
.scratch_addr = 0x2000,
.thunk_addr = 0x46E00, .thunk_size = 0x200,
.swap_buffers = a31_sram_swap_buffers,
+ .write_speed = 512,
},
{
.soc_id = 0x1667, /* Allwinner A33 */
@@ -554,6 +573,32 @@ soc_sram_info *aw_fel_get_sram_info(libusb_device_handle
*usb)
return result;
}
+/*
+ * This function serves to determine a useful "progress chunk" size, based on
+ * the assumption that we aim for at least one update per second approximately.
+ *
+ * As of now, unfortunately this isn't a single, uniform value. Many SoCs have
+ * decent FEL write speeds - but a few experience shortcomings and poor
+ * performance, see https://linux-sunxi.org/FEL/USBBoot#SoC_support_status
+ *
+ * We therefore try to reasonably match the SoC's transfer rate, or fall back
+ * to a (relatively small) 'safe' chunk size. Currently the default assumes
+ * that slow FEL transfers are ~128 KiB/s.
+ */
+static size_t get_chunk_size(libusb_device_handle *usb)
+{
+ static size_t result = 0; /* determine value once, and cache it */
+
+ if (!result) {
+ soc_sram_info *sram_info = aw_fel_get_sram_info(usb);
+ if (sram_info->write_speed > 0)
+ result = sram_info->write_speed * 1024; /* expected
amount per second */
+ else /* slow or unknown SoC */
+ result = 128 * 1024; /* 128 KiB per request */
+ }
+ return result;
+}
+
static uint32_t fel_to_spl_thunk[] = {
#include "fel-to-spl-thunk.h"
};
--
2.4.6