mirror of
https://github.com/linux-msm/qdl.git
synced 2026-02-25 13:12:25 -08:00
firehose: Improve startup time significantly
The firehose_read() at the start of firehose_run() serves the purpose of waiting for the programmer to show up and to consume any <log/> messages spat out, so that we're ready to invoke the <configure/>. On MSM8916 there are no <log/> entries, so this is a 5 second loop hitting -ETIMEDOUTs in firehose_read(). On other tested targets, it does drain the <log/> entries and then hits -ETIMEDOUTs for the remainder of 5 seconds. On the newer targets, we could perhaps determine when the programmer is up by looking for <log/> entries, but this doesn't help the MSM8916 model and it doesn't fit with the current implementation. If we instead tweak the timeouts and error handling of firehose_configure(), we can speculatively attempt to configure the programmer until success. This meets both the observed models, and shows savings between 4 and 4.5 seconds in startup time across the tested devices. Signed-off-by: Bjorn Andersson <bjorn.andersson@oss.qualcomm.com>
This commit is contained in:
committed by
Bjorn Andersson
parent
5449037f1c
commit
841a0a8e7f
56
firehose.c
56
firehose.c
@@ -305,7 +305,6 @@ static int firehose_send_configure(struct qdl_device *qdl, size_t payload_size,
|
||||
xmlNode *root;
|
||||
xmlNode *node;
|
||||
xmlDoc *doc;
|
||||
int ret;
|
||||
|
||||
doc = xmlNewDoc((xmlChar *)"1.0");
|
||||
root = xmlNewNode(NULL, (xmlChar *)"data");
|
||||
@@ -318,16 +317,14 @@ static int firehose_send_configure(struct qdl_device *qdl, size_t payload_size,
|
||||
xml_setpropf(node, "ZLPAwareHost", "%d", 1);
|
||||
xml_setpropf(node, "SkipStorageInit", "%d", skip_storage_init);
|
||||
|
||||
ret = firehose_write(qdl, doc);
|
||||
firehose_write(qdl, doc);
|
||||
xmlFreeDoc(doc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return firehose_read(qdl, 5000, firehose_configure_response_parser, max_payload_size);
|
||||
return firehose_read(qdl, 100, firehose_configure_response_parser, max_payload_size);
|
||||
}
|
||||
|
||||
static int firehose_configure(struct qdl_device *qdl, bool skip_storage_init,
|
||||
const char *storage)
|
||||
static int firehose_try_configure(struct qdl_device *qdl, bool skip_storage_init,
|
||||
const char *storage)
|
||||
{
|
||||
size_t max_sector_size;
|
||||
size_t sector_sizes[] = { 512, 4096 };
|
||||
@@ -339,10 +336,8 @@ static int firehose_configure(struct qdl_device *qdl, bool skip_storage_init,
|
||||
|
||||
ret = firehose_send_configure(qdl, qdl->max_payload_size, skip_storage_init,
|
||||
storage, &size);
|
||||
if (ret < 0) {
|
||||
ux_err("configure request failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* In simulateion mode "remote" target can't propose different size, so
|
||||
@@ -932,13 +927,42 @@ static int firehose_reset(struct qdl_device *qdl)
|
||||
return ret == FIREHOSE_ACK ? 0 : -1;
|
||||
}
|
||||
|
||||
static int firehose_detect_and_configure(struct qdl_device *qdl,
|
||||
bool skip_storage_init,
|
||||
const char *storage,
|
||||
unsigned int timeout_s)
|
||||
{
|
||||
struct timeval timeout = { .tv_sec = timeout_s };
|
||||
struct timeval now;
|
||||
int ret;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
timeradd(&now, &timeout, &timeout);
|
||||
for (;;) {
|
||||
ret = firehose_try_configure(qdl, false, storage);
|
||||
|
||||
if (ret == FIREHOSE_ACK) {
|
||||
break;
|
||||
} else if (ret != -ETIMEDOUT) {
|
||||
ux_err("configure request failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
if (timercmp(&now, &timeout, >)) {
|
||||
ux_err("failed to detect firehose programmer\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int firehose_provision(struct qdl_device *qdl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
firehose_read(qdl, 5000, firehose_generic_parser, NULL);
|
||||
|
||||
ret = firehose_configure(qdl, true, "ufs");
|
||||
ret = firehose_detect_and_configure(qdl, true, "ufs", 5);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -964,9 +988,7 @@ int firehose_run(struct qdl_device *qdl, const char *storage)
|
||||
|
||||
ux_info("waiting for programmer...\n");
|
||||
|
||||
firehose_read(qdl, 5000, firehose_generic_parser, NULL);
|
||||
|
||||
ret = firehose_configure(qdl, false, storage);
|
||||
ret = firehose_detect_and_configure(qdl, true, storage, 5);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
9
io.c
9
io.c
@@ -53,6 +53,15 @@ int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout
|
||||
return qdl->read(qdl, buf, len, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* qdl_write() - Write a message from the device
|
||||
* @qdl: device handle
|
||||
* @buf: buffer with data to be written
|
||||
* @len: length of data to be written
|
||||
*
|
||||
* Returns: number of bytes read
|
||||
* negative errno on failure (notably -ETIMEDOUT)
|
||||
*/
|
||||
int qdl_write(struct qdl_device *qdl, const void *buf, size_t len)
|
||||
{
|
||||
return qdl->write(qdl, buf, len);
|
||||
|
||||
9
usb.c
9
usb.c
@@ -262,11 +262,12 @@ static int usb_write(struct qdl_device *qdl, const void *buf, size_t len)
|
||||
|
||||
ret = libusb_bulk_transfer(qdl_usb->usb_handle, qdl_usb->out_ep, data,
|
||||
xfer, &actual, 1000);
|
||||
if ((ret != 0 && ret != LIBUSB_ERROR_TIMEOUT) ||
|
||||
(ret == LIBUSB_ERROR_TIMEOUT && actual == 0)) {
|
||||
if (ret != 0 && ret != LIBUSB_ERROR_TIMEOUT) {
|
||||
warnx("bulk write failed: %s", libusb_strerror(ret));
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
if (ret == LIBUSB_ERROR_TIMEOUT && actual == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
count += actual;
|
||||
len -= actual;
|
||||
@@ -277,7 +278,7 @@ static int usb_write(struct qdl_device *qdl, const void *buf, size_t len)
|
||||
ret = libusb_bulk_transfer(qdl_usb->usb_handle, qdl_usb->out_ep, NULL,
|
||||
0, &actual, 1000);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
Reference in New Issue
Block a user