Skip to content

Commit 2580547

Browse files
quic-bjorandeandersson
authored andcommitted
firehose: Unbreak db410c/msm8916 support
Somewhere along the road, we broke support for the programmer for msm8916 (and presumably other similar socs). Attempts to operate firehose against these boards would exclusively result in USB timeouts on write. The reason for this is that, in contrast to all other commonly used targets, the programmer for MSM8916 generates <log/> messages after the <response/> message and writes are not services until all the <log/> entries are consumed. Rework the read loop, to continue reading messages until a timeout or an error occurs, and then return the response status, if one was previously found. This cost us 100ms per attempt to read a response, but I've not found any other way to determine that we've consumed all responses. Naively doing this does however break <read/>, as immediately following the response with "rawmode=true" the device starts sending the data. Adding support for parsing out "rawmode" and immediately terminating the loop solves this, and reduces the impact of the 100ms penalty (as it no longer applies to either <program/> or <read/>. Signed-off-by: Bjorn Andersson <[email protected]>
1 parent d561ed5 commit 2580547

File tree

3 files changed

+70
-11
lines changed

3 files changed

+70
-11
lines changed

firehose.c

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static xmlNode *firehose_response_parse(const void *buf, size_t len, int *error)
8383
return node;
8484
}
8585

86-
static int firehose_generic_parser(xmlNode *node, void *data)
86+
static int firehose_generic_parser(xmlNode *node, void *data, bool *rawmode)
8787
{
8888
xmlChar *value;
8989
int ret = -EINVAL;
@@ -103,18 +103,27 @@ static int firehose_generic_parser(xmlNode *node, void *data)
103103

104104
xmlFree(value);
105105

106+
value = xmlGetProp(node, (xmlChar *)"rawmode");
107+
if (value) {
108+
if (xmlStrcmp(value, (xmlChar *)"true") == 0)
109+
*rawmode = true;
110+
xmlFree(value);
111+
}
112+
106113
return ret;
107114
}
108115

109116
static int firehose_read(struct qdl_device *qdl, int timeout_ms,
110-
int (*response_parser)(xmlNode *node, void *data),
117+
int (*response_parser)(xmlNode *node, void *data, bool *rawmode),
111118
void *data)
112119
{
113120
char buf[4096];
114121
xmlNode *node;
115122
int error;
123+
int resp = -EIO;
116124
int ret = -EAGAIN;
117125
int n;
126+
bool rawmode = false;
118127
struct timeval timeout;
119128
struct timeval now;
120129
struct timeval delta = { .tv_sec = timeout_ms / 1000,
@@ -127,9 +136,40 @@ static int firehose_read(struct qdl_device *qdl, int timeout_ms,
127136
if (qdl->dev_type == QDL_DEVICE_SIM)
128137
return 0;
129138

130-
do {
139+
/*
140+
* The goal of firehose_read() is to find a response to a request among
141+
* one or more incoming messages AND to consume all incoming messages
142+
* (otherwise subsequent writes will time out).
143+
* The messages can be one of:
144+
* - <log/>
145+
* - <response value=""/>
146+
* - <response value="" rawmode="true"/>
147+
*
148+
* Generally <log/> messages are coming prior to the <response/>, but
149+
* on MSM8916 (at least) it's been observed that <log/> messages can
150+
* arrive after the <response/>.
151+
*
152+
* We therefor need to consume messages until there are no more
153+
* (timeout) and we have been able to parse out a response (using
154+
* @response_parser).
155+
*
156+
* In the special case that the <response/> contain an attribute
157+
* "rawmode=true", the device signals that it has entered a mode where
158+
* it will not send/receive XML-formatted commands. So, (at least for
159+
* reads) we need to shortcircuit the logic and directly terminate the
160+
* consumption of incoming data.
161+
*/
162+
for (;;) {
131163
n = qdl_read(qdl, buf, sizeof(buf), 100);
132-
if (n <= 0) {
164+
165+
/* Timeout after seeing a response, we're done waiting for logs */
166+
if (n == -ETIMEDOUT && resp >= 0)
167+
break;
168+
/* We want to return resp on error, to not loose the reset resposne */
169+
else if (n == -EIO)
170+
break;
171+
172+
if (n == -ETIMEDOUT || n == 0) {
133173
gettimeofday(&now, NULL);
134174
if (timercmp(&now, &timeout, <))
135175
continue;
@@ -144,11 +184,17 @@ static int firehose_read(struct qdl_device *qdl, int timeout_ms,
144184
if (!node)
145185
return error;
146186

147-
ret = response_parser(node, data);
187+
ret = response_parser(node, data, &rawmode);
148188
xmlFreeDoc(node->doc);
149-
} while (ret == -EAGAIN);
150189

151-
return ret;
190+
if (ret >= 0)
191+
resp = ret;
192+
193+
if (rawmode)
194+
break;
195+
}
196+
197+
return resp;
152198
}
153199

154200
static int firehose_write(struct qdl_device *qdl, xmlDoc *doc)
@@ -208,7 +254,7 @@ static int firehose_write(struct qdl_device *qdl, xmlDoc *doc)
208254
*
209255
* Return: max size supported by the remote, or negative errno on failure
210256
*/
211-
static int firehose_configure_response_parser(xmlNode *node, void *data)
257+
static int firehose_configure_response_parser(xmlNode *node, void *data, bool *rawmode)
212258
{
213259
xmlChar *payload;
214260
xmlChar *value;

io.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ void qdl_close(struct qdl_device *qdl)
3838
qdl->close(qdl);
3939
}
4040

41+
/**
42+
* qdl_read() - Read a message from the device
43+
* @qdl: device handle
44+
* @buf: buffer to write the data into
45+
* @len: maximum length of data to be read
46+
* @timeout: timeout for the read, in milliseconds
47+
*
48+
* Returns: number of bytes read, might be zero for a ZLP
49+
* negative errno on failure (notably -ETIMEDOUT)
50+
*/
4151
int qdl_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int timeout)
4252
{
4353
return qdl->read(qdl, buf, len, timeout);

usb.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// SPDX-License-Identifier: BSD-3-Clause
22
#include <sys/types.h>
3+
#include <errno.h>
34
#include <fcntl.h>
45
#include <stdbool.h>
56
#include <stdio.h>
@@ -237,9 +238,11 @@ static int usb_read(struct qdl_device *qdl, void *buf, size_t len, unsigned int
237238
int ret;
238239

239240
ret = libusb_bulk_transfer(qdl_usb->usb_handle, qdl_usb->in_ep, buf, len, &actual, timeout);
240-
if ((ret != 0 && ret != LIBUSB_ERROR_TIMEOUT) ||
241-
(ret == LIBUSB_ERROR_TIMEOUT && actual == 0))
242-
return -1;
241+
if (ret != 0 && ret != LIBUSB_ERROR_TIMEOUT)
242+
return -EIO;
243+
244+
if (ret == LIBUSB_ERROR_TIMEOUT && actual == 0)
245+
return -ETIMEDOUT;
243246

244247
return actual;
245248
}

0 commit comments

Comments
 (0)