From 9b920cf4495225bfd44f1078d3683287bacd727b Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Tue, 7 Aug 2018 22:49:19 +0930 Subject: protocol: Add flush Change-Id: Ic5be69f534c9ff277cc3f7e5a85a0eae5bc41716 Signed-off-by: Andrew Jeffery --- protocol.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ protocol.h | 9 ++++++ transport_mbox.c | 86 ++++-------------------------------------------- 3 files changed, 115 insertions(+), 79 deletions(-) diff --git a/protocol.c b/protocol.c index 88e91b2..6622cd4 100644 --- a/protocol.c +++ b/protocol.c @@ -169,6 +169,93 @@ int protocol_v1_mark_dirty(struct mbox_context *context, 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 @@ int protocol_v2_erase(struct mbox_context *context, 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 @@ static const struct protocol_ops protocol_ops_v1 = { .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 @@ static const struct protocol_ops protocol_ops_v2 = { .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 @@ struct protocol_erase { } 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 @@ struct protocol_ops { 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 @@ int protocol_v1_create_window(struct mbox_context *context, 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 @@ int protocol_v2_mark_dirty(struct mbox_context *context, 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_erase_window(struct mbox_context *context, 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; - - 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; - } - - /* - * 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; - } + struct protocol_flush io = { 0 }; + int rc; - if (prev != WINDOW_CLEAN) { /* Still the last streak to write */ - rc = window_flush(context, offset, count, prev); - if (rc < 0) { - return rc; - } + if (context->version == API_VERSION_1) { + io.req.offset = get_u16(&req->msg.args[0]); + io.req.size = get_u32(&req->msg.args[2]); } - /* 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; -- cgit v1.2.1