firehose: Negotiate max payload size

When the host propose a larger payload size than the device accepts the
device will respond with a NACK, containing the maximum payload size.
Similarily the ACK will contain the supported max if the host requests a
lower value than the device supports.

In both cases we pick the largest possible value and send a second
configure message to select this payload size.

Reported-by: Kirill Kapranov <c_kkapra@qti.qualcomm.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
Bjorn Andersson
2017-11-29 13:19:50 -08:00
parent 4a72fc8723
commit febbbcc32e

View File

@@ -229,22 +229,41 @@ static int firehose_nop(int fd)
static size_t max_payload_size = 1048576;
/**
* firehose_configure_response_parser() - parse a configure response
* @node: response xmlNode
*
* Return: max size supported by the remote, or negative errno on failure
*/
static int firehose_configure_response_parser(xmlNode *node)
{
xmlChar *payload;
xmlChar *value;
size_t max_size;
value = xmlGetProp(node, (xmlChar*)"value");
if (xmlStrcmp(value, (xmlChar*)"ACK"))
payload = xmlGetProp(node, (xmlChar*)"MaxPayloadSizeToTargetInBytes");
if (!value || !payload)
return -EINVAL;
value = xmlGetProp(node, (xmlChar*)"MaxPayloadSizeToTargetInBytes");
if (value)
max_payload_size = strtoul((char*)value, NULL, 10);
max_size = strtoul((char*)payload, NULL, 10);
return 0;
/*
* When receiving an ACK the remote may indicate that we should attempt
* a larger payload size
*/
if (!xmlStrcmp(value, (xmlChar*)"ACK")) {
payload = xmlGetProp(node, (xmlChar*)"MaxPayloadSizeToTargetInBytesSupported");
if (!payload)
return -EINVAL;
max_size = strtoul((char*)payload, NULL, 10);
}
return max_size;
}
static int firehose_configure(int fd)
static int firehose_send_configure(int fd, size_t payload_size)
{
xmlNode *root;
xmlNode *node;
@@ -257,7 +276,7 @@ static int firehose_configure(int fd)
node = xmlNewChild(root, NULL, (xmlChar*)"configure", NULL);
xml_setpropf(node, "MemoryName", "ufs");
xml_setpropf(node, "MaxPayloadSizeToTargetInBytes", "%d", max_payload_size);
xml_setpropf(node, "MaxPayloadSizeToTargetInBytes", "%d", payload_size);
xml_setpropf(node, "verbose", "%d", 0);
xml_setpropf(node, "ZLPAwareHost", "%d", 0);
@@ -268,6 +287,31 @@ static int firehose_configure(int fd)
return firehose_read(fd, -1, firehose_configure_response_parser);
}
static int firehose_configure(int fd)
{
int ret;
ret = firehose_send_configure(fd, max_payload_size);
if (ret < 0)
return ret;
/* Retry if remote proposed different size */
if (ret != max_payload_size) {
ret = firehose_send_configure(fd, ret);
if (ret < 0)
return ret;
max_payload_size = ret;
}
if (qdl_debug) {
fprintf(stderr, "[CONFIGURE] max payload size: %ld\n",
max_payload_size);
}
return 0;
}
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))