summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ec/google/chromeec/crosec_proto.c23
-rw-r--r--src/ec/google/chromeec/ec.h21
-rw-r--r--src/ec/google/chromeec/ec_spi.c27
3 files changed, 55 insertions, 16 deletions
diff --git a/src/ec/google/chromeec/crosec_proto.c b/src/ec/google/chromeec/crosec_proto.c
index 42c7c2e35d..55a707db17 100644
--- a/src/ec/google/chromeec/crosec_proto.c
+++ b/src/ec/google/chromeec/crosec_proto.c
@@ -27,6 +27,11 @@
#include "ec_message.h"
/* Common utilities */
+void * __attribute__((weak)) crosec_get_buffer(size_t size, int req)
+{
+ printk(BIOS_DEBUG, "crosec_get_buffer() implementation required.\n");
+ return NULL;
+}
/* Dumps EC command / response data into debug output.
*
@@ -208,23 +213,27 @@ static int send_command_proto3(struct chromeec_command *cec_command,
{
int out_bytes, in_bytes;
int rv;
- struct ec_command_v3 cmd = { {0}, };
- struct ec_response_v3 resp = { {0}, };
+ struct ec_command_v3 *cmd;
+ struct ec_response_v3 *resp;
+
+ if ((cmd = crosec_get_buffer(sizeof(*cmd), 1)) == NULL)
+ return -EC_RES_ERROR;
+ if ((resp = crosec_get_buffer(sizeof(*resp), 0)) == NULL)
+ return -EC_RES_ERROR;
/* Create request packet */
- out_bytes = create_proto3_request(cec_command, &cmd);
+ out_bytes = create_proto3_request(cec_command, cmd);
if (out_bytes < 0) {
return out_bytes;
}
/* Prepare response buffer */
- in_bytes = prepare_proto3_response_buffer(cec_command, &resp);
+ in_bytes = prepare_proto3_response_buffer(cec_command, resp);
if (in_bytes < 0) {
return in_bytes;
}
- rv = crosec_io((uint8_t *)&cmd, out_bytes, (uint8_t *)&resp, in_bytes,
- context);
+ rv = crosec_io(out_bytes, in_bytes, context);
if (rv != 0) {
printk(BIOS_ERR, "%s: failed to complete I/O: Err = %#x.",
__func__, rv >= 0 ? rv : -rv);
@@ -232,7 +241,7 @@ static int send_command_proto3(struct chromeec_command *cec_command,
}
/* Process the response */
- return handle_proto3_response(&resp, cec_command);
+ return handle_proto3_response(resp, cec_command);
}
static int crosec_command_proto_v3(struct chromeec_command *cec_command,
diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h
index a1c59b8dc5..e0db8c17ee 100644
--- a/src/ec/google/chromeec/ec.h
+++ b/src/ec/google/chromeec/ec.h
@@ -69,10 +69,23 @@ struct chromeec_command {
* actual received size out */
};
-/* internal standard implementation for EC command protocols. */
-typedef int (*crosec_io_t)(uint8_t *write_bytes, size_t write_size,
- uint8_t *read_bytes, size_t read_size,
- void *context);
+/*
+ * There are transport level constraints for sending protov3 packets. Because
+ * of this provide a way for the generic protocol layer to request buffers
+ * so that there is zero copying being done through the layers.
+ *
+ * Request the buffer provided the size. If 'req' is non-zero then the
+ * buffer requested is for EC requests. Otherwise it's for responses. Return
+ * non-NULL on success, NULL on error.
+ */
+void *crosec_get_buffer(size_t size, int req);
+
+/*
+ * The lower level transport works on the buffers handed out to the
+ * upper level. Therefore, only the size of the request and response
+ * are required.
+ */
+typedef int (*crosec_io_t)(size_t req_size, size_t resp_size, void *context);
int crosec_command_proto(struct chromeec_command *cec_command,
crosec_io_t crosec_io, void *context);
diff --git a/src/ec/google/chromeec/ec_spi.c b/src/ec/google/chromeec/ec_spi.c
index f1bdd3caaa..6107836153 100644
--- a/src/ec/google/chromeec/ec_spi.c
+++ b/src/ec/google/chromeec/ec_spi.c
@@ -25,15 +25,32 @@
static const uint8_t EcFramingByte = 0xec;
-static int crosec_spi_io(uint8_t *write_bytes, size_t write_size,
- uint8_t *read_bytes, size_t read_size,
- void *context)
+#define PROTO3_MAX_PACKET_SIZE 268
+
+static uint8_t req_buf[PROTO3_MAX_PACKET_SIZE];
+static uint8_t resp_buf[PROTO3_MAX_PACKET_SIZE];
+
+void *crosec_get_buffer(size_t size, int req)
+{
+ if (size > PROTO3_MAX_PACKET_SIZE) {
+ printk(BIOS_DEBUG, "Proto v3 buffer request too large: %zu!\n",
+ size);
+ return NULL;
+ }
+
+ if (req)
+ return req_buf;
+ else
+ return resp_buf;
+}
+
+static int crosec_spi_io(size_t req_size, size_t resp_size, void *context)
{
struct spi_slave *slave = (struct spi_slave *)context;
spi_claim_bus(slave);
- if (spi_xfer(slave, write_bytes, write_size, NULL, 0)) {
+ if (spi_xfer(slave, req_buf, req_size, NULL, 0)) {
printk(BIOS_ERR, "%s: Failed to send request.\n", __func__);
spi_release_bus(slave);
return -1;
@@ -64,7 +81,7 @@ static int crosec_spi_io(uint8_t *write_bytes, size_t write_size,
}
}
- if (spi_xfer(slave, NULL, 0, read_bytes, read_size)) {
+ if (spi_xfer(slave, NULL, 0, resp_buf, resp_size)) {
printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__);
spi_release_bus(slave);
return -1;