soc/intel/common: Add spinlock protection to fast SPI flash operations
Add spinlock synchronization to prevent concurrent SPI flash controller access from multiple CPUs in SMP environments. The spinlock serializes access to the SPI controller hardware in exec_sync_hwseq_xfer(). If SMP is not enabled, spinlock functions are no-ops, so this change is safe for both SMP and non-SMP configurations. This resolves an issue seen on the Starlabs Starfighter MTL where multiple SPI transaction errors occurred when reading option variables stored in SMMSTORE: [ERROR] SPI Transaction Error at Flash Offset 103002a HSFSTS = 0x01016022 [ERROR] SPI Transaction Error at Flash Offset 1030004 HSFSTS = 0x01006022 [ERROR] SPI Transaction Error at Flash Offset 1030000 HSFSTS = 0x3f006022 ... Change-Id: Ic3003b0a986b587622102b6f36714bcb16c3d976 Signed-off-by: Matt DeVillier <matt.devillier@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/90283 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Sean Rhodes <sean@starlabs.systems> Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com>
This commit is contained in:
parent
ceaa41c9e4
commit
5034f8629f
1 changed files with 19 additions and 2 deletions
|
|
@ -9,6 +9,7 @@
|
|||
#include <spi_flash.h>
|
||||
#include <string.h>
|
||||
#include <timer.h>
|
||||
#include <smp/spinlock.h>
|
||||
|
||||
/* Helper to create a FAST_SPI context on API entry. */
|
||||
#define BOILERPLATE_CREATE_CTX(ctx) \
|
||||
|
|
@ -32,6 +33,9 @@ struct fast_spi_flash_ctx {
|
|||
uintptr_t mmio_base;
|
||||
};
|
||||
|
||||
/* Spinlock to protect concurrent SPI flash controller access from multiple CPUs */
|
||||
DECLARE_SPIN_LOCK(fast_spi_lock);
|
||||
|
||||
static void _fast_spi_flash_get_ctx(struct fast_spi_flash_ctx *ctx)
|
||||
{
|
||||
ctx->mmio_base = (uintptr_t)fast_spi_get_bar();
|
||||
|
|
@ -160,15 +164,28 @@ static int exec_sync_hwseq_xfer(struct fast_spi_flash_ctx *ctx,
|
|||
uint32_t hsfsts_cycle, uint32_t flash_addr,
|
||||
size_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Protect SPI flash controller from concurrent access by multiple CPUs.
|
||||
* The spinlock serializes access to the SPI controller hardware.
|
||||
* If SMP is not enabled, spinlock functions are no-ops.
|
||||
*/
|
||||
spin_lock(&fast_spi_lock);
|
||||
|
||||
if (wait_for_hwseq_spi_cycle_complete(ctx) != SUCCESS) {
|
||||
printk(BIOS_ERR, "SPI Transaction Timeout (Exceeded %d ms) due to prior"
|
||||
" operation at Flash Offset %x\n",
|
||||
SPIBAR_HWSEQ_XFER_TIMEOUT_MS, flash_addr);
|
||||
return E_TIMEOUT;
|
||||
ret = E_TIMEOUT;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
start_hwseq_xfer(ctx, hsfsts_cycle, flash_addr, len);
|
||||
return wait_for_hwseq_xfer(ctx, flash_addr);
|
||||
ret = wait_for_hwseq_xfer(ctx, flash_addr);
|
||||
|
||||
unlock:
|
||||
spin_unlock(&fast_spi_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int fast_spi_cycle_in_progress(void)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue