From 3bb3f137d0b92e5f7ec596a07acd5eada0c09cc3 Mon Sep 17 00:00:00 2001 From: Suraj Jitindar Singh Date: Wed, 24 May 2017 16:37:19 +1000 Subject: libflash/mbox-flash: Implement MARK_WRITE_ERASED mbox call Version two of the mbox-flash protocol defines a new command: MARK_WRITE_ERASED. This command provides a simple way to mark a region of flash as all 0xff without the need to go and write all 0xff. This is an optimisation as there is no need for an erase before a write, it is the responsibility of the BMC to deal with the flash correctly, however in v1 it was ambiguous what a client should do if the flash should be erased but not actually written to. This allows of a optimal path to resolve this problem. Signed-off-by: Cyril Bur Signed-off-by: Suraj Jitindar Singh Acked-by: Cyril Bur Signed-off-by: Stewart Smith --- libflash/mbox-flash.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 4 deletions(-) (limited to 'libflash') diff --git a/libflash/mbox-flash.c b/libflash/mbox-flash.c index 5de743a..7491d3b 100644 --- a/libflash/mbox-flash.c +++ b/libflash/mbox-flash.c @@ -530,6 +530,18 @@ static int mbox_flash_dirty(struct mbox_flash_data *mbox_flash, uint64_t pos, MBOX_C_MARK_WRITE_DIRTY); } +static int mbox_flash_erase(struct mbox_flash_data *mbox_flash, uint64_t pos, + uint64_t len) +{ + if (!mbox_flash->write.open) { + prlog(PR_ERR, "Attempting to erase without an open write window\n"); + return FLASH_ERR_DEVICE_GONE; + } + + return mbox_flash_mark_write(mbox_flash, pos, len, + MBOX_C_MARK_WRITE_ERASED); +} + static int mbox_flash_flush(struct mbox_flash_data *mbox_flash) { struct bmc_mbox_msg *msg; @@ -782,8 +794,50 @@ out: return rc; } -static int mbox_flash_erase(struct blocklevel_device *bl __unused, - uint64_t pos __unused, uint64_t len __unused) +static int mbox_flash_erase_v2(struct blocklevel_device *bl, uint64_t pos, + uint64_t len) +{ + struct mbox_flash_data *mbox_flash; + + /* LPC is only 32bit */ + if (pos > UINT_MAX || len > UINT_MAX) + return FLASH_ERR_PARM_ERROR; + + mbox_flash = container_of(bl, struct mbox_flash_data, bl); + + prlog(PR_TRACE, "Flash erase at 0x%08x for 0x%08x\n", (u32) pos, (u32) len); + while (len > 0) { + uint64_t size; + int rc; + + /* Move window and get a new size to erase */ + rc = mbox_window_move(mbox_flash, &mbox_flash->write, + MBOX_C_CREATE_WRITE_WINDOW, pos, len, &size); + if (rc) + return rc; + + rc = mbox_flash_erase(mbox_flash, pos, size); + if (rc) + return rc; + + /* + * Flush directly, don't mark that region dirty otherwise it + * isn't clear if a write happened there or not + */ + + rc = mbox_flash_flush(mbox_flash); + if (rc) + return rc; + + len -= size; + pos += size; + } + + return 0; +} + +static int mbox_flash_erase_v1(struct blocklevel_device *bl __unused, + uint64_t pos __unused, uint64_t len __unused) { /* * We can probably get away with doing nothing. @@ -880,7 +934,7 @@ static int protocol_init(struct mbox_flash_data *mbox_flash) /* Assume V2 */ mbox_flash->bl.read = &mbox_flash_read; mbox_flash->bl.write = &mbox_flash_write; - mbox_flash->bl.erase = &mbox_flash_erase; + mbox_flash->bl.erase = &mbox_flash_erase_v2; mbox_flash->bl.get_info = &mbox_flash_get_info; /* Assume V2 */ @@ -934,6 +988,7 @@ static int protocol_init(struct mbox_flash_data *mbox_flash) prlog(PR_INFO, "Detected mbox protocol version %d\n", mbox_flash->version); if (mbox_flash->version == 1) { + mbox_flash->bl.erase = &mbox_flash_erase_v1; /* Not all handlers differ, update those which do */ mbox_flash->handlers[MBOX_C_GET_FLASH_INFO] = &mbox_flash_do_get_flash_info_v1; mbox_flash->handlers[MBOX_C_CREATE_READ_WINDOW] = @@ -976,7 +1031,7 @@ int mbox_flash_init(struct blocklevel_device **bl) /* Assume V2 */ mbox_flash->bl.read = &mbox_flash_read; mbox_flash->bl.write = &mbox_flash_write; - mbox_flash->bl.erase = &mbox_flash_erase; + mbox_flash->bl.erase = &mbox_flash_erase_v2; mbox_flash->bl.get_info = &mbox_flash_get_info; if (bmc_mbox_get_attn_reg() & MBOX_ATTN_BMC_REBOOT) -- cgit v1.1