From patchwork Fri May 1 05:02:17 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 466808 X-Patchwork-Delegate: benh@kernel.crashing.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 884A1140320 for ; Fri, 1 May 2015 15:03:51 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 6384A1A0D64 for ; Fri, 1 May 2015 15:03:51 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e23smtp06.au.ibm.com (e23smtp06.au.ibm.com [202.81.31.148]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 07EDF1A0D15 for ; Fri, 1 May 2015 15:03:33 +1000 (AEST) Received: from /spool/local by e23smtp06.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 1 May 2015 15:03:32 +1000 Received: from d23dlp02.au.ibm.com (202.81.31.213) by e23smtp06.au.ibm.com (202.81.31.212) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 1 May 2015 15:03:29 +1000 Received: from d23relay06.au.ibm.com (d23relay06.au.ibm.com [9.185.63.219]) by d23dlp02.au.ibm.com (Postfix) with ESMTP id 7D5762BB0054 for ; Fri, 1 May 2015 15:03:29 +1000 (EST) Received: from d23av04.au.ibm.com (d23av04.au.ibm.com [9.190.235.139]) by d23relay06.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t4153LrC44630114 for ; Fri, 1 May 2015 15:03:29 +1000 Received: from d23av04.au.ibm.com (localhost [127.0.0.1]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t4152u5o011275 for ; Fri, 1 May 2015 15:02:56 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av04.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t4152tAk010775; Fri, 1 May 2015 15:02:55 +1000 Received: from bran.ozlabs.ibm.com (haven.au.ibm.com [9.192.253.15]) by ozlabs.au.ibm.com (Postfix) with ESMTP id CC169A02C7; Fri, 1 May 2015 15:02:32 +1000 (AEST) Received: from gwshan (shangw.ozlabs.ibm.com [10.61.2.199]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id 0D57A16AA05; Fri, 1 May 2015 15:02:31 +1000 (AEST) Received: by gwshan (Postfix, from userid 1000) id C39D1942197; Fri, 1 May 2015 15:02:31 +1000 (AEST) From: Gavin Shan To: skiboot@lists.ozlabs.org Date: Fri, 1 May 2015 15:02:17 +1000 Message-Id: <1430456549-21090-5-git-send-email-gwshan@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1430456549-21090-1-git-send-email-gwshan@linux.vnet.ibm.com> References: <1430456549-21090-1-git-send-email-gwshan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15050105-0021-0000-0000-0000012CC8B9 Subject: [Skiboot] [PATCH v6 04/16] core/fdt: Refactor FDT X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" The patch refactors FDT in order support PCI hotplug, which requires the module to support the capability of creating FDT blob for the subordinate device nodes of the specified one. * Current implementation assumes that the FDT blob is pointed by global variable "fdt", which won't be true when create FDT blob for PCI sub-device-tree during hotplug. Adding one additional parameter "void *fdt" to individual functions for the operated FDT blob. * Refactoring dt_flatten_node() so that it can be used to build FDT blob from root device node at bootup time, or the indicated one during PCI hotplug time. * Export create_dbt(), which can be used to create FDT blob during bootup or PCI hotplug time. Signed-off-by: Gavin Shan --- core/fdt.c | 131 ++++++++++++++++++++++++++++++++------------------ core/init.c | 2 +- include/device_tree.h | 5 -- include/skiboot.h | 2 +- 4 files changed, 86 insertions(+), 54 deletions(-) diff --git a/core/fdt.c b/core/fdt.c index 7abebba..c92dac8 100644 --- a/core/fdt.c +++ b/core/fdt.c @@ -27,7 +27,6 @@ #include static int fdt_error; -static void *fdt; #undef DEBUG_FDT @@ -44,12 +43,12 @@ static void __save_err(int err, const char *str) #define save_err(...) __save_err(__VA_ARGS__, #__VA_ARGS__) -static void dt_property_cell(const char *name, u32 cell) +static void dt_property_cell(void *fdt, const char *name, u32 cell) { save_err(fdt_property_cell(fdt, name, cell)); } -static void dt_begin_node(const char *name, uint32_t phandle) +static void dt_begin_node(void *fdt, const char *name, uint32_t phandle) { save_err(fdt_begin_node(fdt, name)); @@ -57,23 +56,23 @@ static void dt_begin_node(const char *name, uint32_t phandle) * We add both the new style "phandle" and the legacy * "linux,phandle" properties */ - dt_property_cell("linux,phandle", phandle); - dt_property_cell("phandle", phandle); + dt_property_cell(fdt, "linux,phandle", phandle); + dt_property_cell(fdt, "phandle", phandle); } -static void dt_property(const char *name, const void *val, size_t size) +static void dt_property(void *fdt, const char *name, const void *val, size_t size) { save_err(fdt_property(fdt, name, val, size)); } -static void dt_end_node(void) +static void dt_end_node(void *fdt) { save_err(fdt_end_node(fdt)); } -static void dump_fdt(void) -{ #ifdef DEBUG_FDT +static void dump_fdt(void *fdt) +{ int i, off, depth, err; printf("Device tree %u@%p\n", fdt_totalsize(fdt), fdt); @@ -110,35 +109,47 @@ static void dump_fdt(void) } printf("name: %s [%u]\n", name, off); } -#endif } +#else +#define dump_fdt(x...) +#endif -static void flatten_dt_node(const struct dt_node *root) +static void dt_flatten_properties(void *fdt, const struct dt_node *dn) { - const struct dt_node *i; - const struct dt_property *p; + struct dt_property *p; -#ifdef DEBUG_FDT - printf("FDT: node: %s\n", root->name); -#endif - - list_for_each(&root->properties, p, list) { + list_for_each(&dn->properties, p, list) { if (strstarts(p->name, DT_PRIVATE)) continue; #ifdef DEBUG_FDT printf("FDT: prop: %s size: %ld\n", p->name, p->len); #endif - dt_property(p->name, p->prop, p->len); + dt_property(fdt, p->name, p->prop, p->len); } +} - list_for_each(&root->children, i, list) { - dt_begin_node(i->name, i->phandle); - flatten_dt_node(i); - dt_end_node(); +static void dt_flatten_node(void *fdt, const struct dt_node *dn, bool inclusive) +{ + const struct dt_node *child; + +#ifdef DEBUG_FDT + printf("FDT: node: %s\n", dn->name); +#endif + + if (inclusive) { + dt_begin_node(fdt, dn->name, dn->phandle); + dt_flatten_properties(fdt, dn); } + + list_for_each(&dn->children, child, list) + dt_flatten_node(fdt, child, true); + + /* Note that we have open ending pattern */ + if (inclusive) + dt_end_node(fdt); } -static void create_dtb_reservemap(const struct dt_node *root) +static void create_dtb_reservemap(void *fdt, const struct dt_node *root) { uint64_t base, size; const uint64_t *ranges; @@ -160,38 +171,61 @@ static void create_dtb_reservemap(const struct dt_node *root) save_err(fdt_finish_reservemap(fdt)); } -void *create_dtb(const struct dt_node *root) +static int __create_dtb(const struct dt_node *root, size_t len, + bool inclusive, void **pblob) { - size_t len = DEVICE_TREE_MAX_SIZE; - uint32_t old_last_phandle = last_phandle; + void *fdt; - do { - if (fdt) - free(fdt); - last_phandle = old_last_phandle; - fdt_error = 0; - fdt = malloc(len); - if (!fdt) { - prerror("dtb: could not malloc %lu\n", (long)len); - return NULL; - } + /* Clear cached error */ + fdt_error = 0; - fdt_create(fdt, len); + /* Allocate memory chunk */ + fdt = malloc(len); + if (!fdt) { + *pblob = NULL; + prerror("dtb: cannot alloc %lu\n", (long)len); + return 0; + } - create_dtb_reservemap(root); + /* FDT header */ + fdt_create(fdt, len); - /* Open root node */ - dt_begin_node(root->name, root->phandle); + /* Reserved memory chunks */ + if (root == dt_root && inclusive) + create_dtb_reservemap(fdt, root); - /* Unflatten our live tree */ - flatten_dt_node(root); + /* Unflatten our live tree */ + dt_flatten_node(fdt, root, inclusive); - /* Close root node */ - dt_end_node(); + save_err(fdt_finish(fdt)); + if (fdt_error) { + free(fdt); + return fdt_error; + } - save_err(fdt_finish(fdt)); + *pblob = fdt; + return 0; +} - if (!fdt_error) +void *create_dtb(const struct dt_node *root, size_t *size, bool inclusive) +{ + size_t len; + uint32_t old_last_phandle = last_phandle; + void *fdt = NULL; + int ret; + + /* Get the initial length */ + if (size) { + len = *size; + *size = 0; + } else { + len = DEVICE_TREE_MAX_SIZE; + } + + do { + last_phandle = old_last_phandle; + ret = __create_dtb(root, len, inclusive, &fdt); + if (!ret) break; len *= 2; @@ -203,5 +237,8 @@ void *create_dtb(const struct dt_node *root) prerror("dtb: error %s\n", fdt_strerror(fdt_error)); return NULL; } + + if (size) + *size = len; return fdt; } diff --git a/core/init.c b/core/init.c index 445272a..2836ae3 100644 --- a/core/init.c +++ b/core/init.c @@ -414,7 +414,7 @@ void __noreturn load_and_boot_kernel(bool is_reboot) op_display(OP_LOG, OP_MOD_INIT, 0x000B); /* Create the device tree blob to boot OS. */ - fdt = create_dtb(dt_root); + fdt = create_dtb(dt_root, NULL, true); if (!fdt) { op_display(OP_FATAL, OP_MOD_INIT, 2); abort(); diff --git a/include/device_tree.h b/include/device_tree.h index d04f20a..a32821c 100644 --- a/include/device_tree.h +++ b/include/device_tree.h @@ -18,11 +18,6 @@ #define __DEVICE_TREE_H #include -/* Note: Device tree creation has no locks. It's assumed to be done - * by a single processor in a non racy way - */ -void *create_dtb(const struct dt_node *root); - /* Helpers to cache errors in fdt; use this instead of fdt_* */ uint32_t dt_begin_node(const char *name); /* returns phandle */ void dt_property_string(const char *name, const char *value); diff --git a/include/skiboot.h b/include/skiboot.h index fc5bc1d..19b77b3 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -235,7 +235,7 @@ extern void prd_occ_reset(uint32_t proc); extern void prd_init(void); /* Flatten device-tree */ -extern void *create_dtb(const struct dt_node *root); +void *create_dtb(const struct dt_node *root, size_t *size, bool inclusive); /* SLW reinit function for switching core settings */ extern int64_t slw_reinit(uint64_t flags);