[Pdbg] [PATCH 06/17] libsbefifo: Refactor protocol marshalling for memory chip-ops

Amitay Isaacs amitay at ozlabs.org
Thu Oct 31 17:34:17 AEDT 2019


Signed-off-by: Amitay Isaacs <amitay at ozlabs.org>
---
 libsbefifo/cmd_memory.c | 311 ++++++++++++++++++++++++++++------------
 libsbefifo/libsbefifo.h |  12 ++
 2 files changed, 230 insertions(+), 93 deletions(-)

diff --git a/libsbefifo/cmd_memory.c b/libsbefifo/cmd_memory.c
index e6fa579..9d23a4c 100644
--- a/libsbefifo/cmd_memory.c
+++ b/libsbefifo/cmd_memory.c
@@ -24,77 +24,76 @@
 #include "libsbefifo.h"
 #include "sbefifo_private.h"
 
-int sbefifo_mem_get(struct sbefifo_context *sctx, uint64_t addr, uint32_t size, uint16_t flags, uint8_t **data)
+int sbefifo_mem_get_push(uint64_t addr, uint32_t size, uint16_t flags, uint8_t **buf, uint32_t *buflen)
 {
-	uint8_t *out;
+	uint32_t *msg;
 	uint64_t start_addr, end_addr;
-	uint32_t msg[6];
-	uint32_t cmd, out_len;
-	uint32_t align, offset, len, extra_bytes, i, j;
-	int rc;
-	bool do_tag = false, do_ecc = false;
+	uint32_t nwords, cmd;
+	uint32_t align, len;
 
-	if (flags & SBEFIFO_MEMORY_FLAG_PROC) {
+	if (flags & SBEFIFO_MEMORY_FLAG_PROC)
 		align = 8;
-
-		if (flags & SBEFIFO_MEMORY_FLAG_ECC_REQ)
-			do_ecc = true;
-
-		if (flags & SBEFIFO_MEMORY_FLAG_TAG_REQ)
-			do_tag = true;
-
-	} else if (flags & SBEFIFO_MEMORY_FLAG_PBA) {
+	else if (flags & SBEFIFO_MEMORY_FLAG_PBA)
 		align = 128;
-	} else {
+	else
 		return EINVAL;
-	}
 
 	start_addr = addr & (~(uint64_t)(align-1));
 	end_addr = (addr + size + (align-1)) & (~(uint64_t)(align-1));
 
-	if (end_addr - start_addr > 0xffffffff)
+	if (end_addr - start_addr > UINT32_MAX)
 		return EINVAL;
 
-	offset = addr - start_addr;
-	len = end_addr - start_addr;
-
-	extra_bytes = 0;
-	if (do_tag)
-		extra_bytes = len / 8;
+	nwords = 6;
+	*buflen = nwords * sizeof(uint32_t);
+	msg = malloc(*buflen);
+	if (!msg)
+		return ENOMEM;
 
-	if (do_ecc)
-		extra_bytes = len / 8;
+	len = end_addr - start_addr;
 
 	cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_GET_MEMORY;
 
-	msg[0] = htobe32(6);	// number of words
+	msg[0] = htobe32(nwords);
 	msg[1] = htobe32(cmd);
 	msg[2] = htobe32(flags);
 	msg[3] = htobe32(start_addr >> 32);
 	msg[4] = htobe32(start_addr & 0xffffffff);
 	msg[5] = htobe32(len);
 
-	out_len = len + extra_bytes + 4;
-	rc = sbefifo_operation(sctx, (uint8_t *)msg, 6 * 4, &out, &out_len);
-	if (rc)
-		return rc;
+	*buf = (uint8_t *)msg;
+	return 0;
+}
 
-	if (out_len != len + extra_bytes + 4) {
-		free(out);
+int sbefifo_mem_get_pull(uint8_t *buf, uint32_t buflen, uint64_t addr, uint32_t size, uint32_t flags, uint8_t **data)
+{
+	uint64_t start_addr, offset;
+	uint32_t align, len, i, j;
+	bool do_tag = false, do_ecc = false;
+
+	if (buflen < 4)
 		return EPROTO;
-	}
 
-	len = be32toh(*(uint32_t *) &out[out_len-4]);
+	len = be32toh(*(uint32_t *) &buf[buflen-4]);
 	*data = malloc(len);
-	if (! *data) {
-		free(out);
+	if (! *data)
 		return ENOMEM;
-	}
+
+	if (flags & SBEFIFO_MEMORY_FLAG_ECC_REQ)
+		do_ecc = true;
+
+	if (flags & SBEFIFO_MEMORY_FLAG_TAG_REQ)
+		do_tag = true;
+
+	if (flags & SBEFIFO_MEMORY_FLAG_PROC)
+		align = 8;
+	else if (flags & SBEFIFO_MEMORY_FLAG_PBA)
+		align = 128;
 
 	i = 0;
 	j = 0;
 	while (i < len) {
-		memcpy((void *)&(*data)[j], (void *)&out[i], 8);
+		memcpy((void *)&(*data)[j], (void *)&buf[i], 8);
 		i += 8;
 		j += 8;
 
@@ -104,24 +103,56 @@ int sbefifo_mem_get(struct sbefifo_context *sctx, uint64_t addr, uint32_t size,
 		if (do_ecc)
 			i++;
 	}
-	if (i < len)
-		memcpy((void *)&(*data)[j], (void *)&out[i], len - i);
 
-	memmove(*data, *data + offset, size);
+	start_addr = addr & (~(uint64_t)(align-1));
+	offset = addr - start_addr;
+	if (offset)
+		memmove(*data, *data + offset, size);
 
-	free(out);
 	return 0;
 }
 
-int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data, uint32_t data_len, uint16_t flags)
+int sbefifo_mem_get(struct sbefifo_context *sctx, uint64_t addr, uint32_t size, uint16_t flags, uint8_t **data)
 {
-	uint8_t *out;
-	uint32_t nwords = (data_len+3)/4;
-	uint32_t msg[6+nwords];
-	uint32_t cmd, out_len;
-	uint32_t align;
+	uint8_t *msg, *out;
+	uint32_t msg_len, out_len;
+	uint32_t len, extra_bytes;
 	int rc;
 
+	rc = sbefifo_mem_get_push(addr, size, flags, &msg, &msg_len);
+	if (rc)
+		return rc;
+
+	/* length is 6th word in the request */
+	len = be32toh(*(uint32_t *)(msg + 20));
+	extra_bytes = 0;
+
+	if (flags & SBEFIFO_MEMORY_FLAG_ECC_REQ)
+		extra_bytes = len / 8;
+
+	if (flags & SBEFIFO_MEMORY_FLAG_TAG_REQ)
+		extra_bytes = len / 8;
+
+	out_len = len + extra_bytes + 4;
+	rc = sbefifo_operation(sctx, msg, msg_len, &out, &out_len);
+	free(msg);
+	if (rc)
+		return rc;
+
+
+	rc = sbefifo_mem_get_pull(out, out_len, addr, size, flags, data);
+	if (out)
+		free(out);
+
+	return rc;
+}
+
+int sbefifo_mem_put_push(uint64_t addr, uint8_t *data, uint32_t data_len, uint16_t flags, uint8_t **buf, uint32_t *buflen)
+{
+	uint32_t *msg;
+	uint32_t nwords, cmd;
+	uint32_t align;
+
 	if (flags & SBEFIFO_MEMORY_FLAG_PROC)
 		align = 8;
 	else if (flags & SBEFIFO_MEMORY_FLAG_PBA)
@@ -132,9 +163,18 @@ int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data,
 	if (addr & (align-1))
 		return EINVAL;
 
+	if (data_len & (align-1))
+		return EINVAL;
+
+	nwords = 6 + data_len/4;
+	*buflen = nwords * sizeof(uint32_t);
+	msg = malloc(*buflen);
+	if (!msg)
+		return ENOMEM;
+
 	cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_PUT_MEMORY;
 
-	msg[0] = htobe32(6 + nwords); // number of words
+	msg[0] = htobe32(nwords);
 	msg[1] = htobe32(cmd);
 	msg[2] = htobe32(flags);
 	msg[3] = htobe32(addr >> 32);
@@ -142,75 +182,133 @@ int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data,
 	msg[5] = htobe32(data_len);
 	memcpy(&msg[6], data, data_len);
 
+	*buf = (uint8_t *)msg;
+	return 0;
+}
+
+int sbefifo_mem_put_pull(uint8_t *buf, uint32_t buflen)
+{
+	if (buflen != sizeof(uint32_t))
+		return EPROTO;
+
+	return 0;
+}
+
+int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data, uint32_t data_len, uint16_t flags)
+{
+	uint8_t *msg, *out;
+	uint32_t msg_len, out_len;
+	int rc;
+
+	rc = sbefifo_mem_put_push(addr, data, data_len, flags, &msg, &msg_len);
+	if (rc)
+		return rc;
+
 	out_len = 1 * 4;
-	rc = sbefifo_operation(sctx, (uint8_t *)msg, (6+nwords) * 4, &out, &out_len);
+	rc = sbefifo_operation(sctx, msg, msg_len, &out, &out_len);
+	free(msg);
 	if (rc)
 		return rc;
 
-	if (out_len != 4) {
+	rc = sbefifo_mem_put_pull(out, out_len);
+	if (out)
 		free(out);
-		return EPROTO;
-	}
 
-	free(out);
-	return 0;
+	return rc;
 }
 
-int sbefifo_occsram_get(struct sbefifo_context *sctx, uint32_t addr, uint32_t size, uint8_t mode, uint8_t **data, uint32_t *data_len)
+int sbefifo_occsram_get_push(uint32_t addr, uint32_t size, uint8_t mode, uint8_t **buf, uint32_t *buflen)
 {
-	uint8_t *out;
+	uint32_t *msg;
+	uint32_t nwords, cmd;
 	uint32_t start_addr, end_addr;
-	uint32_t msg[5];
-	uint32_t cmd, out_len;
-	uint32_t align, offset, len;
-	int rc;
+	uint32_t align, len;
 
 	align = 8;
 	start_addr = addr & (~(uint32_t)(align-1));
 	end_addr = (addr + size + (align-1)) & (~(uint32_t)(align-1));
 
-	offset = addr - start_addr;
+	if (end_addr < start_addr)
+		return EINVAL;
+
+	nwords = 5;
+	*buflen = nwords * sizeof(uint32_t);
+	msg = malloc(*buflen);
+	if (!msg)
+		return ENOMEM;
+
 	len = end_addr - start_addr;
 
 	cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_GET_OCCSRAM;
 
-	msg[0] = htobe32(5);	// number of words
+	msg[0] = htobe32(nwords);
 	msg[1] = htobe32(cmd);
 	msg[2] = htobe32(mode);
 	msg[3] = htobe32(start_addr);
 	msg[4] = htobe32(len);
 
-	out_len = len + 4;
-	rc = sbefifo_operation(sctx, (uint8_t *)msg, 5 * 4, &out, &out_len);
-	if (rc)
-		return rc;
+	*buf = (uint8_t *)msg;
+	return 0;
+}
 
-	if (out_len != len + 4) {
-		free(out);
+int sbefifo_occsram_get_pull(uint8_t *buf, uint32_t buflen, uint32_t addr, uint32_t size, uint8_t **data, uint32_t *data_len)
+{
+	uint32_t start_addr;
+	uint32_t align, offset;
+
+	if (buflen < 4)
 		return EPROTO;
-	}
 
-	*data_len = be32toh(*(uint32_t *) &out[out_len-4]);
-	*data = malloc(*data_len);
-	if (! *data) {
-		free(out);
+	*data_len = be32toh(*(uint32_t *) &buf[buflen-4]);
+	if (*data_len < size)
+		return EPROTO;
+
+	*data = malloc(size);
+	if (! *data)
 		return ENOMEM;
-	}
-	memcpy(*data, out + offset, size);
 
-	free(out);
+	align = 8;
+	start_addr = addr & (~(uint32_t)(align-1));
+	offset = addr - start_addr;
+
+	memcpy(*data, buf + offset, size);
+
 	return 0;
 }
 
-int sbefifo_occsram_put(struct sbefifo_context *sctx, uint32_t addr, uint8_t *data, uint32_t data_len, uint8_t mode)
+int sbefifo_occsram_get(struct sbefifo_context *sctx, uint32_t addr, uint32_t size, uint8_t mode, uint8_t **data, uint32_t *data_len)
 {
-	uint8_t *out;
-	uint32_t nwords = (data_len+3)/4;
-	uint32_t msg[5+nwords];
-	uint32_t cmd, out_len;
-	uint32_t align;
+	uint8_t *msg, *out;
+	uint32_t msg_len, out_len;
+	uint32_t len;
 	int rc;
 
+	rc = sbefifo_occsram_get_push(addr, size, mode, &msg, &msg_len);
+	if (rc)
+		return rc;
+
+	/* length is 5th word in the request */
+	len = be32toh(*(uint32_t *)(msg + 16));
+
+	out_len = len + 4;
+	rc = sbefifo_operation(sctx, msg, msg_len, &out, &out_len);
+	free(msg);
+	if (rc)
+		return rc;
+
+	rc = sbefifo_occsram_get_pull(out, out_len, addr, size, data, data_len);
+	if (out)
+		free(out);
+
+	return rc;
+}
+
+int sbefifo_occsram_put_push(uint32_t addr, uint8_t *data, uint32_t data_len, uint8_t mode, uint8_t **buf, uint32_t *buflen)
+{
+	uint32_t *msg;
+	uint32_t nwords, cmd;
+	uint32_t align;
+
 	align = 8;
 
 	if (addr & (align-1))
@@ -219,25 +317,52 @@ int sbefifo_occsram_put(struct sbefifo_context *sctx, uint32_t addr, uint8_t *da
 	if (data_len & (align-1))
 		return EINVAL;
 
+	nwords = 5 + data_len/4;
+	*buflen = nwords * sizeof(uint32_t);
+	msg = malloc(*buflen);
+	if (!msg)
+		return ENOMEM;
+
 	cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_PUT_OCCSRAM;
 
-	msg[0] = htobe32(5 + nwords); // number of words
+	msg[0] = htobe32(nwords);
 	msg[1] = htobe32(cmd);
 	msg[2] = htobe32(mode);
 	msg[3] = htobe32(addr);
 	msg[4] = htobe32(data_len);
-	memcpy(&msg[6], data, data_len);
+	memcpy(&msg[5], data, data_len);
+
+	*buf = (uint8_t *)msg;
+	return 0;
+}
+
+int sbefifo_occsram_put_pull(uint8_t *buf, uint32_t buflen)
+{
+	if (buflen != sizeof(uint32_t))
+		return EPROTO;
+
+	return 0;
+}
+
+int sbefifo_occsram_put(struct sbefifo_context *sctx, uint32_t addr, uint8_t *data, uint32_t data_len, uint8_t mode)
+{
+	uint8_t *msg, *out;
+	uint32_t msg_len, out_len;
+	int rc;
+
+	rc = sbefifo_occsram_put_push(addr, data, data_len, mode, &msg, &msg_len);
+	if (rc)
+		return rc;
 
 	out_len = 4;
-	rc = sbefifo_operation(sctx, (uint8_t *)msg, (5+nwords) * 4, &out, &out_len);
+	rc = sbefifo_operation(sctx, msg, msg_len, &out, &out_len);
+	free(msg);
 	if (rc)
 		return rc;
 
-	if (out_len != 4) {
+	rc = sbefifo_occsram_put_pull(out, out_len);
+	if (out)
 		free(out);
-		return EPROTO;
-	}
 
-	free(out);
-	return 0;
+	return rc;
 }
diff --git a/libsbefifo/libsbefifo.h b/libsbefifo/libsbefifo.h
index d17dd71..3922d74 100644
--- a/libsbefifo/libsbefifo.h
+++ b/libsbefifo/libsbefifo.h
@@ -105,6 +105,18 @@ int sbefifo_ring_put_from_image(struct sbefifo_context *sctx, uint16_t target, u
 #define SBEFIFO_MEMORY_FLAG_PASSTHRU     0x0100
 #define SBEFIFO_MEMORY_FLAG_CACHEINJECT  0x0200 // only for mem_put
 
+int sbefifo_mem_get_push(uint64_t addr, uint32_t size, uint16_t flags, uint8_t **buf, uint32_t *buflen);
+int sbefifo_mem_get_pull(uint8_t *buf, uint32_t buflen, uint64_t addr, uint32_t size, uint32_t flags, uint8_t **data);
+
+int sbefifo_mem_put_push(uint64_t addr, uint8_t *data, uint32_t data_len, uint16_t flags, uint8_t **buf, uint32_t *buflen);
+int sbefifo_mem_put_pull(uint8_t *buf, uint32_t buflen);
+
+int sbefifo_occsram_get_push(uint32_t addr, uint32_t size, uint8_t mode, uint8_t **buf, uint32_t *buflen);
+int sbefifo_occsram_get_pull(uint8_t *buf, uint32_t buflen, uint32_t addr, uint32_t size, uint8_t **data, uint32_t *data_len);
+
+int sbefifo_occsram_put_push(uint32_t addr, uint8_t *data, uint32_t data_len, uint8_t mode, uint8_t **buf, uint32_t *buflen);
+int sbefifo_occsram_put_pull(uint8_t *buf, uint32_t buflen);
+
 int sbefifo_mem_get(struct sbefifo_context *sctx, uint64_t addr, uint32_t size, uint16_t flags, uint8_t **data);
 int sbefifo_mem_put(struct sbefifo_context *sctx, uint64_t addr, uint8_t *data, uint32_t len, uint16_t flags);
 int sbefifo_occsram_get(struct sbefifo_context *sctx, uint32_t addr, uint32_t size, uint8_t mode, uint8_t **data, uint32_t *data_len);
-- 
2.21.0



More information about the Pdbg mailing list