[Skiboot] [PATCH v2 4/9] astbmc: asynchronous preloading of resources

Stewart Smith stewart at linux.vnet.ibm.com
Wed May 6 14:00:49 AEST 2015


Implement start_preload_resource and resource_loaded platform functions
for astbmc machines (palmetto, habanero, firestone).

This means we start loading kernel and initramfs from flash much earlier
in boot, doing things like PCI init concurrently so that by the time
we go to boot the payload, it's already loaded.

Implementation is a simple queue with a job running on another CPU doing
the libflash calls.

Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
---
 core/flash.c                 |  119 +++++++++++++++++++++++++++++++++++++++++-
 include/skiboot.h            |    5 +-
 platforms/astbmc/firestone.c |    3 +-
 platforms/astbmc/habanero.c  |    3 +-
 platforms/astbmc/palmetto.c  |    3 +-
 5 files changed, 126 insertions(+), 7 deletions(-)

diff --git a/core/flash.c b/core/flash.c
index 7d32c8d..092f8f2 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -15,6 +15,7 @@
  */
 
 #include <skiboot.h>
+#include <cpu.h>
 #include <lock.h>
 #include <opal.h>
 #include <opal-msg.h>
@@ -521,8 +522,8 @@ end:
  * load a resource from FLASH
  * buf and len shouldn't account for ECC even if partition is ECCed.
  */
-int flash_load_resource(enum resource_id id, uint32_t subid,
-				 void *buf, size_t *len)
+static int flash_load_resource(enum resource_id id, uint32_t subid,
+			       void *buf, size_t *len)
 {
 	int i, rc, part_num, part_size, part_start, size;
 	struct ffs_handle *ffs;
@@ -628,3 +629,117 @@ out_unlock:
 	unlock(&flash_lock);
 	return status ? OPAL_SUCCESS : rc;
 }
+
+
+struct flash_load_resource_item {
+	enum resource_id id;
+	uint32_t subid;
+	int result;
+	void *buf;
+	size_t *len;
+	struct list_node link;
+};
+
+static LIST_HEAD(flash_load_resource_queue);
+static LIST_HEAD(flash_loaded_resources);
+static struct lock flash_load_resource_lock = LOCK_UNLOCKED;
+static struct cpu_job *flash_load_job = NULL;
+
+int flash_resource_loaded(enum resource_id id, uint32_t subid)
+{
+	struct flash_load_resource_item *resource = NULL;
+	struct flash_load_resource_item *r;
+	int rc = OPAL_BUSY;
+
+	lock(&flash_load_resource_lock);
+	list_for_each(&flash_loaded_resources, r, link) {
+		if (r->id == id && r->subid == subid) {
+			resource = r;
+			break;
+		}
+	}
+
+	if (resource) {
+		rc = resource->result;
+		list_del(&resource->link);
+		free(resource);
+	}
+
+	if (list_empty(&flash_load_resource_queue) && flash_load_job) {
+		cpu_wait_job(flash_load_job, true);
+		flash_load_job = NULL;
+	}
+
+	unlock(&flash_load_resource_lock);
+
+	return rc;
+}
+
+static void flash_load_resources(void *data __unused)
+{
+	struct flash_load_resource_item *r;
+	int result;
+
+	do {
+		lock(&flash_load_resource_lock);
+		if (list_empty(&flash_load_resource_queue)) {
+			unlock(&flash_load_resource_lock);
+			break;
+		}
+		r = list_top(&flash_load_resource_queue,
+			     struct flash_load_resource_item, link);
+		assert(r->result == OPAL_EMPTY);
+		r->result = OPAL_BUSY;
+		unlock(&flash_load_resource_lock);
+
+		result = flash_load_resource(r->id, r->subid, r->buf, r->len);
+
+		lock(&flash_load_resource_lock);
+		r = list_pop(&flash_load_resource_queue,
+			     struct flash_load_resource_item, link);
+		r->result = result;
+		list_add_tail(&flash_loaded_resources, &r->link);
+		unlock(&flash_load_resource_lock);
+	} while(true);
+}
+
+static void start_flash_load_resource_job(void)
+{
+	if (flash_load_job)
+		cpu_wait_job(flash_load_job, true);
+
+	flash_load_job = cpu_queue_job(NULL, "flash_load_resources",
+				       flash_load_resources, NULL);
+
+	cpu_process_local_jobs();
+}
+
+int flash_start_preload_resource(enum resource_id id, uint32_t subid,
+				 void *buf, size_t *len)
+{
+	struct flash_load_resource_item *r;
+	bool start_thread = false;
+
+	r = malloc(sizeof(struct flash_load_resource_item));
+
+	assert(r != NULL);
+	r->id = id;
+	r->subid = subid;
+	r->buf = buf;
+	r->len = len;
+	r->result = OPAL_EMPTY;
+
+	printf("FLASH: Queueing preload of %x/%x\n", r->id, r->subid);
+
+	lock(&flash_load_resource_lock);
+	if (list_empty(&flash_load_resource_queue)) {
+		start_thread = true;
+	}
+	list_add_tail(&flash_load_resource_queue, &r->link);
+	unlock(&flash_load_resource_lock);
+
+	if (start_thread)
+		start_flash_load_resource_job();
+
+	return OPAL_SUCCESS;
+}
diff --git a/include/skiboot.h b/include/skiboot.h
index fc5bc1d..d021b33 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -199,8 +199,9 @@ extern void occ_fsp_init(void);
 /* flash support */
 struct flash_chip;
 extern int flash_register(struct flash_chip *chip, bool is_system_flash);
-extern int flash_load_resource(enum resource_id id, uint32_t subid,
-			       void *buf, size_t *len);
+extern int flash_start_preload_resource(enum resource_id id, uint32_t subid,
+					void *buf, size_t *len);
+extern int flash_resource_loaded(enum resource_id id, uint32_t idx);
 extern bool flash_reserve(void);
 extern void flash_release(void);
 
diff --git a/platforms/astbmc/firestone.c b/platforms/astbmc/firestone.c
index 03ecc2b..4d3be19 100644
--- a/platforms/astbmc/firestone.c
+++ b/platforms/astbmc/firestone.c
@@ -43,6 +43,7 @@ DECLARE_PLATFORM(firestone) = {
 	.cec_power_down         = astbmc_ipmi_power_down,
 	.cec_reboot             = astbmc_ipmi_reboot,
 	.elog_commit		= ipmi_elog_commit,
-	.start_preload_resource	= flash_load_resource,
+	.start_preload_resource	= flash_start_preload_resource,
+	.resource_loaded	= flash_resource_loaded,
 	.exit			= ipmi_wdt_final_reset,
 };
diff --git a/platforms/astbmc/habanero.c b/platforms/astbmc/habanero.c
index 2812b40..a2eec4a 100644
--- a/platforms/astbmc/habanero.c
+++ b/platforms/astbmc/habanero.c
@@ -53,6 +53,7 @@ DECLARE_PLATFORM(habanero) = {
 	.cec_power_down         = astbmc_ipmi_power_down,
 	.cec_reboot             = astbmc_ipmi_reboot,
 	.elog_commit		= ipmi_elog_commit,
-	.start_preload_resource	= flash_load_resource,
+	.start_preload_resource	= flash_start_preload_resource,
+	.resource_loaded	= flash_resource_loaded,
 	.exit			= ipmi_wdt_final_reset,
 };
diff --git a/platforms/astbmc/palmetto.c b/platforms/astbmc/palmetto.c
index 02b0649..803ca46 100644
--- a/platforms/astbmc/palmetto.c
+++ b/platforms/astbmc/palmetto.c
@@ -53,6 +53,7 @@ DECLARE_PLATFORM(palmetto) = {
 	.cec_power_down         = astbmc_ipmi_power_down,
 	.cec_reboot             = astbmc_ipmi_reboot,
 	.elog_commit		= ipmi_elog_commit,
-	.start_preload_resource	= flash_load_resource,
+	.start_preload_resource	= flash_start_preload_resource,
+	.resource_loaded	= flash_resource_loaded,
 	.exit			= ipmi_wdt_final_reset,
 };
-- 
1.7.10.4



More information about the Skiboot mailing list