Commit 4c6d6f25 authored by Federico Vaga's avatar Federico Vaga

sw:*: update firmware framework buffer feature

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 6ebae692
......@@ -49,10 +49,11 @@ static int rt_version_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_
/**
* This is an @ref trtl_fw_action_t function type. Accorind the message request,
* it copies one of the declared data structure to the output payload.
* it get/set one of the declared buffers
*/
static int trtl_fw_buffer_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_o)
static int trtl_fw_buffer(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_o)
{
struct trtl_fw_buffer *buf;
unsigned int offset = 0, index, size;
uint32_t *din;
uint32_t *dout;
......@@ -62,83 +63,52 @@ static int trtl_fw_buffer_getter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *
}
/* Only synchronous */
if (!(msg_i->header->flags & TRTL_HMQ_HEADER_FLAG_SYNC))
if (msg_i->header->msg_id == TRTL_MSG_ID_VAR_GET &&
!(msg_i->header->flags & TRTL_HMQ_HEADER_FLAG_SYNC))
return -EINVAL;
msg_o->header->msg_id = TRTL_MSG_ID_BUF_GET;
din = msg_i->payload;
dout = msg_o->payload;
if (msg_o) {
dout = msg_o->payload;
msg_o->header->msg_id = TRTL_MSG_ID_BUF_GET;
msg_o->header->len = msg_i->header->len;
}
while (offset < msg_i->header->len) {
pr_debug("%s: offset %d/%d\n\r", __func__,
offset, msg_i->header->len);
index = din[offset];
dout[offset++] = index;
size = din[offset];
dout[offset++] = size;
pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__,
index, size, app.buffers[index].buf);
if (app.buffers[index].len == size) {
memcpy(&dout[offset],
(uint32_t *)app.buffers[index].buf,
size);
} else {
pr_error("%s: structure %d len not correct %"PRId32" != %d\n\r",
__func__, index, app.buffers[index].len, size);
index = din[offset + 0];
size = din[offset + 1];
if (index >= app.n_buffers) {
pr_error("%s: TLV %d buffer unknown %d\n\r",
__func__, index, index);
return -EINVAL;
}
buf = &app.buffers[index];
offset += (size / 4); /* Next TLV record */
}
return 0;
}
/**
* This is an @ref trtl_fw_action_t function type. Accorind the message request,
* it overwrite a data structure with the one contained in the input
* payload. If the message is syncrnous it will copy back the data structure.
*/
static int trtl_fw_buffer_setter(struct trtl_fw_msg *msg_i, struct trtl_fw_msg *msg_o)
{
unsigned int offset = 0, index, size;
uint32_t *din;
if (!HAS_MOCKTURTLE_FRAMEWORK_BUFFER_ENABLE) {
return -EPERM;
}
if (size > buf->len) {
pr_error("%s: buffer %d len %d not correct max %"PRId32"\n\r",
__func__, index, size, buf->len);
return -EINVAL;
}
din = msg_i->payload;
pr_debug("%s buffer %d len %d (%ld) Addr 0x%p\n\r", __func__,
index, size, buf->len, buf->buf);
while (offset < msg_i->header->len) {
pr_debug("%s: offset %d/%d\n\r", __func__,
offset, msg_i->header->len);
index = din[offset++];
size = din[offset++];
pr_debug("%s Type %d Len %d Addr 0x%p\n\r", __func__,
index, size, app.buffers[index].buf);
if (app.buffers[index].len == size) {
memcpy((uint32_t *)app.buffers[index].buf,
&din[offset], size);
} else {
pr_error("%s:%d structure %d len not correct %"PRId32" != %d\n\r",
__func__, __LINE__, index,
app.buffers[index].len, size);
switch (msg_i->header->msg_id) {
case TRTL_MSG_ID_BUF_SET:
memcpy(buf->buf, &din[offset + 2], size);
/* After a set we always read back => get */
case TRTL_MSG_ID_BUF_GET:
dout[offset + 0] = index;
dout[offset + 1] = size;
memcpy(&dout[offset + 2], buf->buf, size);
break;
default:
return -EINVAL;
}
offset += (size / 4); /* Next TLV record */
offset += (2 + (size / 4)); /* Next TLV record */
}
/* Return back new values. Host can compare with what it sent
to spot errors */
if (msg_i->header->flags & TRTL_HMQ_HEADER_FLAG_SYNC)
return trtl_fw_buffer_getter(msg_i, msg_o);
return 0;
}
......@@ -228,8 +198,8 @@ static trtl_fw_action_t *trtl_actions_in[] = {
[TRTL_MSG_ID_VER - __TRTL_MSG_ID_MAX_USER] = rt_version_getter,
[TRTL_MSG_ID_VAR_SET - __TRTL_MSG_ID_MAX_USER] = trtl_fw_variable,
[TRTL_MSG_ID_VAR_GET - __TRTL_MSG_ID_MAX_USER] = trtl_fw_variable,
[TRTL_MSG_ID_BUF_SET - __TRTL_MSG_ID_MAX_USER] = trtl_fw_buffer_setter,
[TRTL_MSG_ID_BUF_GET - __TRTL_MSG_ID_MAX_USER] = trtl_fw_buffer_getter,
[TRTL_MSG_ID_BUF_SET - __TRTL_MSG_ID_MAX_USER] = trtl_fw_buffer,
[TRTL_MSG_ID_BUF_GET - __TRTL_MSG_ID_MAX_USER] = trtl_fw_buffer,
};
......
......@@ -88,7 +88,7 @@ static int __trtl_fw_variable(struct trtl_dev *trtl,
unsigned int idx_hmq,
uint32_t *variables,
unsigned int n_variables,
unsigned int msg_id)
uint8_t msg_id)
{
struct trtl_desc *wdesc = (struct trtl_desc *)trtl;
struct trtl_msg msg;
......@@ -200,21 +200,13 @@ int trtl_fw_variable_get(struct trtl_dev *trtl,
}
/**
* It sends/receives a set of structures within TLV records.
* This function will change the header content, in particular it will change
* the following fields: msg_id, len
* @param[in] trtl device token
* @param[in] idx_cpu CPU index
* @param[in] idx_hmq HMQ index
* @param[in] tlv the complete buffer
* @param[in] n_tlv number of tlv structures
*/
int trtl_fw_buffer_set(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_tlv *tlv,
unsigned int n_tlv)
static int __trtl_fw_buffer(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_tlv *tlv,
unsigned int n_tlv,
uint8_t msg_id)
{
struct trtl_msg msg;
struct trtl_desc *wdesc = (struct trtl_desc *)trtl;
......@@ -225,32 +217,72 @@ int trtl_fw_buffer_set(struct trtl_dev *trtl,
/* Validate */
for (i = 0; i < n_tlv; ++i) {
total_size += 8; /* 32bit for type and size */
total_size += (sizeof(uint32_t) * 2); /* 32bit for type and size */
total_size += tlv->size;
sizes = wdesc->cfgrom.hmq[idx_cpu][idx_hmq].sizes;
if (total_size > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes) * 4) {
if (total_size > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes) * 4 ||
tlv->size > TRTL_MAX_PAYLOAD_SIZE * 4) {
errno = EINVAL;
return -1;
}
}
memset(&msg, 0, sizeof(struct trtl_msg));
msg.hdr.msg_id = msg_id;
msg.hdr.seq = wdesc->seq;
msg.hdr.sync_id = msg.hdr.seq;
msg.hdr.flags = TRTL_HMQ_HEADER_FLAG_RPC;
msg.hdr.len = total_size / sizeof(uint32_t);
/* Copy buffers */
for (offset = 0, i = 0; i < n_tlv; ++i) {
msg.data[offset + 0] = tlv[i].type;
msg.data[offset + 1] = tlv[i].size;
memcpy(&msg.data[offset + 2], tlv[i].buf, tlv[i].size);
offset += (2 + (tlv->size / 4));
msg.data[offset++] = tlv[i].type;
msg.data[offset++] = tlv[i].size;
memcpy(&msg.data[offset], tlv[i].buf, tlv[i].size);
offset += (tlv->size / sizeof(uint32_t));
}
err = trtl_msg_sync(trtl, idx_cpu, idx_hmq, &msg, &msg,
trtl_default_timeout_ms);
if (err <= 0)
if (err < 0)
return -1;
if (msg.hdr.msg_id != TRTL_MSG_ID_BUF_GET) {
/* Yes, it answers with GET even on SET */
errno = ETRTL_INVALID_MESSAGE;
return -1;
}
/* Copy back buffers */
for (offset = 0, i = 0; i < n_tlv; ++i) {
tlv[i].type = msg.data[offset++];
tlv[i].size = msg.data[offset++];
memcpy(tlv[i].buf, &msg.data[offset], tlv[i].size);
offset += (tlv->size / sizeof(uint32_t));
}
return 0;
}
/**
* It sends/receives a set of structures within TLV records.
* This function will change the header content, in particular it will change
* the following fields: msg_id, len
* @param[in] trtl device token
* @param[in] idx_cpu CPU index
* @param[in] idx_hmq HMQ index
* @param[in] tlv the complete buffer
* @param[in] n_tlv number of tlv structures
*/
int trtl_fw_buffer_set(struct trtl_dev *trtl,
unsigned int idx_cpu,
unsigned int idx_hmq,
struct trtl_tlv *tlv,
unsigned int n_tlv)
{
return __trtl_fw_buffer(trtl, idx_cpu, idx_hmq, tlv, n_tlv,
TRTL_MSG_ID_BUF_SET);
}
/**
* It receives a set of structures within TLV records.
......@@ -269,46 +301,8 @@ int trtl_fw_buffer_get(struct trtl_dev *trtl,
struct trtl_tlv *tlv,
unsigned int n_tlv)
{
struct trtl_msg msg;
struct trtl_desc *wdesc = (struct trtl_desc *)trtl;
unsigned int offset;
unsigned int total_size = 0;
uint32_t sizes;
int err, i;
/* Validate */
for (i = 0; i < n_tlv; ++i) {
total_size += 8; /* 32bit for type and size */
total_size += tlv->size;
sizes = wdesc->cfgrom.hmq[idx_cpu][idx_hmq].sizes;
if (total_size > TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(sizes) * 4) {
errno = EINVAL;
return -1;
}
}
/* Copy buffers - only Type and Length */
for (offset = 0, i = 0; i < n_tlv; ++i) {
msg.data[offset + 0] = tlv[i].type;
msg.data[offset + 1] = tlv[i].size;
offset += (2 + (tlv->size / 4));
}
err = trtl_msg_sync(trtl, idx_cpu, idx_hmq, &msg, &msg,
trtl_default_timeout_ms);
if (err <= 0)
return -1;
/* Copy back buffers - only Type and Length */
for (offset = 0, i = 0; i < n_tlv; ++i) {
tlv[i].type = msg.data[offset + 0];
tlv[i].size = msg.data[offset + 1];
memcpy(&tlv[i].buf, &msg.data[offset + 2], tlv[i].size);
offset += (2 + (tlv->size / 4));
}
return 0;
return __trtl_fw_buffer(trtl, idx_cpu, idx_hmq, tlv, n_tlv,
TRTL_MSG_ID_BUF_GET);
}
......
......@@ -25,12 +25,12 @@ static void help(char *name)
{
fprintf(stderr, "\n");
fprintf(stderr,
"%s -D 0x<hex-number> -i <number> -o <number> -s <number> [read <idx> <size> <idx> <size> ...] [write <idx> <size> <value> ... <value>]\n\n",
"%s -D 0x<hex-number> -i <number> -c <number> -q <number> [read <idx> <size> <idx> <size> ...] [write <idx> <size> <value> ... <value>]\n\n",
name);
fprintf(stderr, "It reads/writes variables on a HMQ\n\n");
fprintf(stderr, "-D device identificator in hexadecimal format\n");
fprintf(stderr, "-i slot index where send\n");
fprintf(stderr, "-o slot index where receive\n");
fprintf(stderr, "-c CPU core index\n");
fprintf(stderr, "-q HMQ index\n");
fprintf(stderr, "-h show this help\n");
fprintf(stderr, "\n");
fprintf(stderr, "write mode accept only 1 buffer\n");
......@@ -180,6 +180,18 @@ int main(int argc, char *argv[])
trtl_strerror(errno));
break;
}
for (i = 0; i < n_tlv; ++i) {
fprintf(stdout, "Buffer index: %d\n", tlv[i].type);
fprintf(stdout, "Buffer size : %zd\n", tlv[i].size);
fprintf(stdout, "Buffer data :");
data = tlv[i].buf;
for (k = 0; k < tlv[i].size / 4; ++k) {
fprintf(stdout, " %08x", data[k]);
if ((k & 0x3) == 0x3)
fprintf(stdout, "\n ");
}
fprintf(stdout, "\n");
}
/* trtl_print_payload(&hdr, tlv); */
break;
case OP_WRITE:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment