From d6fb45e3b29df30e30ac400cfb8b030719207213 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Thu, 29 Jan 2015 14:47:54 +1030 Subject: hw/ipmi: Disable flash access when requested BMC based systems contain a PNOR to provide flash storage. The host normally has exclusive access to the PNOR, however the BMC may use IPMI to request access to perform functions such as update the firmware. Indicate to users of the flash that the device is busy by taking the lock, and setting a per-flash busy flag, which causes flash operations to return OPAL_BUSY. Minor changes from Jeremy Kerr Signed-off-by: Joel Stanley Signed-off-by: Jeremy Kerr --- core/flash.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'core') diff --git a/core/flash.c b/core/flash.c index 3a06d1d..9912add 100644 --- a/core/flash.c +++ b/core/flash.c @@ -26,6 +26,7 @@ struct flash { bool registered; + bool busy; struct flash_chip *chip; uint32_t size; uint32_t block_size; @@ -42,12 +43,39 @@ static struct lock flash_lock; static struct flash *nvram_flash; static u32 nvram_offset, nvram_size; +bool flash_reserve(void) +{ + bool rc = false; + + if (!try_lock(&flash_lock)) + return false; + + if (!system_flash->busy) { + system_flash->busy = true; + rc = true; + } + unlock(&flash_lock); + + return rc; +} + +void flash_release(void) +{ + lock(&flash_lock); + system_flash->busy = false; + unlock(&flash_lock); +} + static int flash_nvram_info(uint32_t *total_size) { - int rc = OPAL_HARDWARE; + int rc; lock(&flash_lock); - if (nvram_flash) { + if (!nvram_flash) { + rc = OPAL_HARDWARE; + } else if (nvram_flash->busy) { + rc = OPAL_BUSY; + } else { *total_size = nvram_size; rc = OPAL_SUCCESS; } @@ -60,13 +88,19 @@ static int flash_nvram_start_read(void *dst, uint32_t src, uint32_t len) { int rc; - lock(&flash_lock); + if (!try_lock(&flash_lock)) + return OPAL_BUSY; if (!nvram_flash) { rc = OPAL_HARDWARE; goto out; } + if (nvram_flash->busy) { + rc = OPAL_BUSY; + goto out; + } + if ((src + len) > nvram_size) { prerror("FLASH_NVRAM: read out of bound (0x%x,0x%x)\n", src, len); @@ -87,7 +121,13 @@ static int flash_nvram_write(uint32_t dst, void *src, uint32_t len) { int rc; - lock(&flash_lock); + if (try_lock(&flash_lock)) + return OPAL_BUSY; + + if (nvram_flash->busy) { + rc = OPAL_BUSY; + goto out; + } /* TODO: When we have async jobs for PRD, turn this into one */ @@ -235,6 +275,7 @@ int flash_register(struct flash_chip *chip, bool is_system_flash) flash = &flashes[i]; flash->registered = true; + flash->busy = false; flash->chip = chip; flash->size = size; flash->block_size = block_size; @@ -286,6 +327,12 @@ static int64_t opal_flash_op(enum flash_op op, uint64_t id, uint64_t offset, return OPAL_BUSY; flash = &flashes[id]; + + if (flash->busy) { + rc = OPAL_BUSY; + goto err; + } + if (!flash->registered) { rc = OPAL_PARAMETER; goto err; @@ -493,6 +540,9 @@ bool flash_load_resource(enum resource_id id, uint32_t subid, flash = system_flash; + if (flash->busy) + goto out_unlock; + for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) { if (part_name_map[i].id == id) { name = part_name_map[i].name; -- cgit v1.1 From 573d0a9af9e46afbefc34cf95510f3d91bc778f6 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Nov 2014 00:02:02 +1100 Subject: hw/ipmi: Set firmware progress sensor We set the IPMI firmware progress sensor to indicate the boot progress of the system. The x86-centric IPMI names don't fit perfectly into what skiboot does, but they do give some indication of the system state. Signed-off-by: Joel Stanley --- core/init.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'core') diff --git a/core/init.c b/core/init.c index ac61c37..1fd8d2e 100644 --- a/core/init.c +++ b/core/init.c @@ -43,6 +43,7 @@ #include #include #include +#include #include @@ -374,6 +375,8 @@ void __noreturn load_and_boot_kernel(bool is_reboot) load_initramfs(); + ipmi_set_fw_progress_sensor(IPMI_FW_OS_BOOT); + if (!is_reboot) { /* We wait for the nvram read to complete here so we can * grab stuff from there such as the kernel arguments @@ -668,6 +671,8 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu) /* Add OPAL timer related properties */ late_init_timers(); + ipmi_set_fw_progress_sensor(IPMI_FW_PCI_INIT); + /* * These last few things must be done as late as possible * because they rely on various other things having been setup, -- cgit v1.1 From a736f60aaed6bb33047646949df7ab08697a896c Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Fri, 27 Feb 2015 16:12:01 +1030 Subject: hw/ipmi: Set boot count sensor The boot count sensor is a discrete sensor that is set once the system is up and running. On successful boot, the BMC expects the sensor to be set to 2. Signed-off-by: Joel Stanley --- core/ipmi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/ipmi.c b/core/ipmi.c index 6c1179f..78a54de 100644 --- a/core/ipmi.c +++ b/core/ipmi.c @@ -156,9 +156,14 @@ static void ipmi_get_message_flags_complete(struct ipmi_msg *msg) /* Once we see an interrupt we assume the payload has * booted. We disable the wdt and let the OS setup its own - * wdt. */ - if (flags & IPMI_MESSAGE_FLAGS_WATCHDOG_PRE_TIMEOUT) + * wdt. + * + * This is also where we consider the OS to be booted, so we set + * the boot count sensor */ + if (flags & IPMI_MESSAGE_FLAGS_WATCHDOG_PRE_TIMEOUT) { ipmi_wdt_stop(); + ipmi_set_boot_count(); + } /* Message available in the event buffer? Queue a Read Event command * to retrieve it. The flag is cleared by performing a read */ -- cgit v1.1 From 3955cd2be2067b5db1d9dcace986b88aeccf1f20 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Thu, 5 Mar 2015 09:25:31 +1100 Subject: core/flash: Fix invalid try_lock check in flash_nvram_write We have the logic inverted here. Signed-off-by: Jeremy Kerr --- core/flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/flash.c b/core/flash.c index 9912add..b0c5050 100644 --- a/core/flash.c +++ b/core/flash.c @@ -121,7 +121,7 @@ static int flash_nvram_write(uint32_t dst, void *src, uint32_t len) { int rc; - if (try_lock(&flash_lock)) + if (!try_lock(&flash_lock)) return OPAL_BUSY; if (nvram_flash->busy) { -- cgit v1.1