protocol: Add flush
Change-Id: Ic5be69f534c9ff277cc3f7e5a85a0eae5bc41716
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/protocol.c b/protocol.c
index 88e91b2..6622cd4 100644
--- a/protocol.c
+++ b/protocol.c
@@ -169,6 +169,93 @@
WINDOW_DIRTY);
}
+static int generic_flush(struct mbox_context *context)
+{
+ int rc, i, offset, count;
+ uint8_t prev;
+
+ offset = 0;
+ count = 0;
+ prev = WINDOW_CLEAN;
+
+ MSG_INFO("Flush window @ %p for size 0x%.8x which maps flash @ 0x%.8x\n",
+ context->current->mem, context->current->size,
+ context->current->flash_offset);
+
+ /*
+ * We look for streaks of the same type and keep a count, when the type
+ * (dirty/erased) changes we perform the required action on the backing
+ * store and update the current streak-type
+ */
+ for (i = 0; i < (context->current->size >> context->block_size_shift);
+ i++) {
+ uint8_t cur = context->current->dirty_bmap[i];
+ if (cur != WINDOW_CLEAN) {
+ if (cur == prev) { /* Same as previous block, incrmnt */
+ count++;
+ } else if (prev == WINDOW_CLEAN) { /* Start of run */
+ offset = i;
+ count++;
+ } else { /* Change in streak type */
+ rc = window_flush(context, offset, count,
+ prev);
+ if (rc < 0) {
+ return rc;
+ }
+ offset = i;
+ count = 1;
+ }
+ } else {
+ if (prev != WINDOW_CLEAN) { /* End of a streak */
+ rc = window_flush(context, offset, count,
+ prev);
+ if (rc < 0) {
+ return rc;
+ }
+ offset = 0;
+ count = 0;
+ }
+ }
+ prev = cur;
+ }
+
+ if (prev != WINDOW_CLEAN) { /* Still the last streak to write */
+ rc = window_flush(context, offset, count, prev);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ /* Clear the dirty bytemap since we have written back all changes */
+ return window_set_bytemap(context, context->current, 0,
+ context->current->size >>
+ context->block_size_shift,
+ WINDOW_CLEAN);
+}
+
+int protocol_v1_flush(struct mbox_context *context, struct protocol_flush *io)
+{
+ int rc;
+
+ if (!(context->current && context->current_is_write)) {
+ MSG_ERR("Tried to call flush without open write window\n");
+ return -EPERM;
+ }
+
+ /*
+ * For V1 the Flush command acts much the same as the dirty command
+ * except with a flush as well. Only do this on an actual flush
+ * command not when we call flush because we've implicitly closed a
+ * window because we might not have the required args in req.
+ */
+ rc = protocol_v1_mark_dirty(context, (struct protocol_mark_dirty *)io);
+ if (rc < 0) {
+ return rc;
+ }
+
+ return generic_flush(context);
+}
+
/*
* get_suggested_timeout() - get the suggested timeout value in seconds
* @context: The mbox context pointer
@@ -294,6 +381,16 @@
return 0;
}
+int protocol_v2_flush(struct mbox_context *context, struct protocol_flush *io)
+{
+ if (!(context->current && context->current_is_write)) {
+ MSG_ERR("Tried to call flush without open write window\n");
+ return -EPERM;
+ }
+
+ return generic_flush(context);
+}
+
static const struct protocol_ops protocol_ops_v1 = {
.reset = protocol_v1_reset,
.get_info = protocol_v1_get_info,
@@ -301,6 +398,7 @@
.create_window = protocol_v1_create_window,
.mark_dirty = protocol_v1_mark_dirty,
.erase = NULL,
+ .flush = protocol_v1_flush,
};
static const struct protocol_ops protocol_ops_v2 = {
@@ -310,6 +408,7 @@
.create_window = protocol_v2_create_window,
.mark_dirty = protocol_v2_mark_dirty,
.erase = protocol_v2_erase,
+ .flush = protocol_v2_flush,
};
static const struct protocol_ops *protocol_ops_map[] = {
diff --git a/protocol.h b/protocol.h
index 9b652ef..c22f94b 100644
--- a/protocol.h
+++ b/protocol.h
@@ -80,6 +80,12 @@
} req;
};
+struct protocol_flush {
+ struct {
+ uint16_t offset;
+ uint32_t size;
+ } req;
+};
struct protocol_ops {
int (*reset)(struct mbox_context *context);
@@ -92,6 +98,7 @@
int (*mark_dirty)(struct mbox_context *context,
struct protocol_mark_dirty *io);
int (*erase)(struct mbox_context *context, struct protocol_erase *io);
+ int (*flush)(struct mbox_context *context, struct protocol_flush *io);
};
int protocol_init(struct mbox_context *context);
@@ -109,6 +116,7 @@
struct protocol_create_window *io);
int protocol_v1_mark_dirty(struct mbox_context *context,
struct protocol_mark_dirty *io);
+int protocol_v1_flush(struct mbox_context *context, struct protocol_flush *io);
/* Protocol v2 */
int protocol_v2_get_info(struct mbox_context *context,
@@ -121,5 +129,6 @@
struct protocol_mark_dirty *io);
int protocol_v2_erase(struct mbox_context *context,
struct protocol_erase *io);
+int protocol_v2_flush(struct mbox_context *context, struct protocol_flush *io);
#endif /* PROTOCOL_H */
diff --git a/transport_mbox.c b/transport_mbox.c
index 92b3609..825fed7 100644
--- a/transport_mbox.c
+++ b/transport_mbox.c
@@ -461,89 +461,17 @@
int mbox_handle_flush_window(struct mbox_context *context,
union mbox_regs *req, struct mbox_msg *resp)
{
- int rc, i, offset, count;
- uint8_t prev;
+ struct protocol_flush io = { 0 };
+ int rc;
- if (!(context->current && context->current_is_write)) {
- MSG_ERR("Tried to call flush without open write window\n");
- return context->version >= API_VERSION_2 ? -MBOX_R_WINDOW_ERROR
- : -MBOX_R_PARAM_ERROR;
+ if (context->version == API_VERSION_1) {
+ io.req.offset = get_u16(&req->msg.args[0]);
+ io.req.size = get_u32(&req->msg.args[2]);
}
- /*
- * For V1 the Flush command acts much the same as the dirty command
- * except with a flush as well. Only do this on an actual flush
- * command not when we call flush because we've implicitly closed a
- * window because we might not have the required args in req.
- */
- if (context->version == API_VERSION_1 && req &&
- req->msg.command == MBOX_C_WRITE_FLUSH) {
- rc = mbox_handle_dirty_window(context, req, NULL);
- if (rc < 0) {
- return rc;
- }
- }
-
- offset = 0;
- count = 0;
- prev = WINDOW_CLEAN;
-
- MSG_INFO("Flush window @ %p for size 0x%.8x which maps flash @ 0x%.8x\n",
- context->current->mem, context->current->size,
- context->current->flash_offset);
-
- /*
- * We look for streaks of the same type and keep a count, when the type
- * (dirty/erased) changes we perform the required action on the backing
- * store and update the current streak-type
- */
- for (i = 0; i < (context->current->size >> context->block_size_shift);
- i++) {
- uint8_t cur = context->current->dirty_bmap[i];
- if (cur != WINDOW_CLEAN) {
- if (cur == prev) { /* Same as previous block, incrmnt */
- count++;
- } else if (prev == WINDOW_CLEAN) { /* Start of run */
- offset = i;
- count++;
- } else { /* Change in streak type */
- rc = window_flush(context, offset, count,
- prev);
- if (rc < 0) {
- return rc;
- }
- offset = i;
- count = 1;
- }
- } else {
- if (prev != WINDOW_CLEAN) { /* End of a streak */
- rc = window_flush(context, offset, count,
- prev);
- if (rc < 0) {
- return rc;
- }
- offset = 0;
- count = 0;
- }
- }
- prev = cur;
- }
-
- if (prev != WINDOW_CLEAN) { /* Still the last streak to write */
- rc = window_flush(context, offset, count, prev);
- if (rc < 0) {
- return rc;
- }
- }
-
- /* Clear the dirty bytemap since we have written back all changes */
- rc = window_set_bytemap(context, context->current, 0,
- context->current->size >>
- context->block_size_shift,
- WINDOW_CLEAN);
+ rc = context->protocol->flush(context, &io);
if (rc < 0) {
- return (rc == -EACCES) ? -MBOX_R_PARAM_ERROR
- : -MBOX_R_SYSTEM_ERROR;
+ return mbox_xlate_errno(context, rc);
}
return rc;