From patchwork Mon Nov 17 08:19:43 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahiro Yamada X-Patchwork-Id: 411423 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 1B2F814010C for ; Mon, 17 Nov 2014 19:20:13 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C09784B739; Mon, 17 Nov 2014 09:20:10 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vqsarjUonoK8; Mon, 17 Nov 2014 09:20:10 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 572FE4B725; Mon, 17 Nov 2014 09:20:10 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6B6004B746 for ; Mon, 17 Nov 2014 09:20:04 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tJRcsgZg2i3y for ; Mon, 17 Nov 2014 09:20:04 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from smtp.mei.co.jp (smtp.mei.co.jp [133.183.100.20]) by theia.denx.de (Postfix) with ESMTP id A83424B725 for ; Mon, 17 Nov 2014 09:19:58 +0100 (CET) Received: from mail-gw.jp.panasonic.com ([157.8.1.157]) by smtp.mei.co.jp (8.12.11.20060614/3.7W/kc-maile12) with ESMTP id sAH8JnkN000716; Mon, 17 Nov 2014 17:19:49 +0900 (JST) Received: from epochmail.jp.panasonic.com ([157.8.1.130]) by mail.jp.panasonic.com (8.11.6p2/3.7W/kc-maili16) with ESMTP id sAH8JnM07609; Mon, 17 Nov 2014 17:19:49 +0900 Received: by epochmail.jp.panasonic.com (8.12.11.20060308/3.7W/lomi14) id sAH8Jn6e018899; Mon, 17 Nov 2014 17:19:49 +0900 Received: from poodle by lomi14.jp.panasonic.com (8.12.11.20060308/3.7W) with ESMTP id sAH8JnUM018825; Mon, 17 Nov 2014 17:19:49 +0900 Received: from beagle.diag.org (beagle.diag.org [10.184.179.16]) by poodle (Postfix) with ESMTP id 862E92740043; Mon, 17 Nov 2014 17:19:49 +0900 (JST) From: Masahiro Yamada To: u-boot@lists.denx.de Date: Mon, 17 Nov 2014 17:19:43 +0900 Message-Id: <1416212385-23800-7-git-send-email-yamada.m@jp.panasonic.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1416212385-23800-1-git-send-email-yamada.m@jp.panasonic.com> References: <1416212385-23800-1-git-send-email-yamada.m@jp.panasonic.com> Cc: Tom Rini , Marek Vasut Subject: [U-Boot] [PATCH 6/8] dm: core: look up drivers more efficiently X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de The DM initialization function, dm_init_and_scan() is called twice, before and after relocation. In the first DM scan, only some of drivers are bound for the use in pre-reloc code (mostly UART drivers). In the second scan, all the drivers are bound. In the current implementation, all the drivers are collected into a single array. Every driver is searched through the array and then the DM_FLAG_PRE_RELOC flag is checked. In the pre-reloc DM scan, drivers without DM_FLAG_PRE_RELOC are ignored. This algorithm works enough, but is not very efficient. This commit aims to split drivers into two contiguous arrays, pre-reloc drivers and post-reloc drivers. The drivers in the former group are declared with U_BOOT_DRIVER_F. The others are declared with U_BOOT_DRIVER. pre post _____________________ reloc reloc .u_boot_list_2_driver1_1 | | || || | | || || | | || || | U_BOOT_DRIVER_F | || || | (driver1) | || || | | _||_ || | | \ / || .u_boot_list_2_driver1_3 |___________________| \/ || .u_boot_list_2_driver2_1 | | || | | || | | || | U_BOOT_DRIVER | || | (driver2) | || | | _||_ | | \ / .u_boot_list_2_driver2_3 |___________________| \/ The pre-reloc DM scan searches drivers from .u_boot_list_2_driver1_1 to .u_boot_list_2_driver1_3. The post-reloc scan searches ones from .u_boot_list_2_driver1_1 and .u_boot_list_2_driver2_3. Signed-off-by: Masahiro Yamada Acked-by: Simon Glass --- doc/driver-model/README.txt | 2 +- drivers/core/device.c | 4 +--- drivers/core/lists.c | 22 +++++++++++++--------- drivers/core/root.c | 3 ++- include/dm/device.h | 8 ++++++-- include/dm/lists.h | 16 ++++++++++++---- include/dm/root.h | 16 ++++++++-------- 7 files changed, 43 insertions(+), 28 deletions(-) diff --git a/doc/driver-model/README.txt b/doc/driver-model/README.txt index 0278dda..e4114d5 100644 --- a/doc/driver-model/README.txt +++ b/doc/driver-model/README.txt @@ -739,7 +739,7 @@ Pre-Relocation Support ---------------------- For pre-relocation we simply call the driver model init function. Only -drivers marked with DM_FLAG_PRE_RELOC or the device tree +drivers declared with U_BOOT_DRIVER_F or the device tree 'u-boot,dm-pre-reloc' flag are initialised prior to relocation. This helps to reduce the driver model overhead. diff --git a/drivers/core/device.c b/drivers/core/device.c index 49faa29..6fd2f07 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -157,11 +157,9 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only, { struct driver *drv; - drv = lists_driver_lookup_name(info->name); + drv = __lists_driver_lookup_name(info->name, pre_reloc_only); if (!drv) return -ENOENT; - if (pre_reloc_only && !(drv->flags & DM_FLAG_PRE_RELOC)) - return -EPERM; return device_bind(parent, drv, info->name, (void *)info->platdata, -1, devp); diff --git a/drivers/core/lists.c b/drivers/core/lists.c index 1476715..5b61ab5 100644 --- a/drivers/core/lists.c +++ b/drivers/core/lists.c @@ -18,10 +18,13 @@ #include #include -struct driver *lists_driver_lookup_name(const char *name) +#define driver_entry_end(p) (p) ? ll_entry_end(struct driver, driver1) : \ + ll_entry_end(struct driver, driver2); + +struct driver *__lists_driver_lookup_name(const char *name, bool pre_reloc_only) { - struct driver *entry = ll_entry_start(struct driver, driver); - struct driver *end = ll_entry_end(struct driver, driver); + struct driver *entry = ll_entry_start(struct driver, driver1); + struct driver *end = driver_entry_end(pre_reloc_only); for (; entry < end; entry++) { if (!strcmp(name, entry->name)) @@ -58,11 +61,12 @@ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only) for (; entry < end; entry++) { ret = device_bind_by_name(parent, pre_reloc_only, entry, &dev); - if (ret && ret != -EPERM) { + + if (!pre_reloc_only && ret == -ENOENT) dm_warn("No match for driver '%s'\n", entry->name); - if (!result || ret != -ENOENT) - result = ret; - } + + if (!result || ret != -ENOENT) + result = ret; } return result; @@ -105,8 +109,8 @@ static int driver_check_compatible(const void *blob, int offset, int lists_bind_fdt(struct udevice *parent, const void *blob, int offset, struct udevice **devp) { - struct driver *entry = ll_entry_start(struct driver, driver); - struct driver *end = ll_entry_end(struct driver, driver); + struct driver *entry = ll_entry_start(struct driver, driver1); + struct driver *end = ll_entry_end(struct driver, driver2); struct udevice *dev; bool found = false; const char *name; diff --git a/drivers/core/root.c b/drivers/core/root.c index 47b3acf..02970c8 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -70,7 +70,8 @@ int dm_scan_platdata(bool pre_reloc_only) ret = lists_bind_drivers(DM_ROOT_NON_CONST, pre_reloc_only); if (ret == -ENOENT) { - dm_warn("Some drivers were not found\n"); + if (!pre_reloc_only) + dm_warn("Some drivers were not found\n"); ret = 0; } diff --git a/include/dm/device.h b/include/dm/device.h index 9ce95a8..a2fd7b6 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -167,9 +167,13 @@ struct driver { uint32_t flags; }; -/* Declare a new U-Boot driver */ +/* Drivers bound before and after relocation */ +#define U_BOOT_DRIVER_F(__name) \ + ll_entry_declare(struct driver, __name, driver1) + +/* Drivers bound only after relocation */ #define U_BOOT_DRIVER(__name) \ - ll_entry_declare(struct driver, __name, driver) + ll_entry_declare(struct driver, __name, driver2) /** * dev_get_platdata() - Get the platform data for a device diff --git a/include/dm/lists.h b/include/dm/lists.h index 704e33e..fbd428d 100644 --- a/include/dm/lists.h +++ b/include/dm/lists.h @@ -13,15 +13,23 @@ #include /** - * lists_driver_lookup_name() - Return u_boot_driver corresponding to name + * __lists_driver_lookup_name() - Return u_boot_driver corresponding to name * * This function returns a pointer to a driver given its name. This is used * for binding a driver given its name and platdata. * * @name: Name of driver to look up + * @pre_reloc_only: If true, searches in drivers declared with U_BOOT_DRIVER_F. + * If false searches in all drivers. * @return pointer to driver, or NULL if not found */ -struct driver *lists_driver_lookup_name(const char *name); +struct driver *__lists_driver_lookup_name(const char *name, + bool pre_reloc_only); + +static inline struct driver *lists_driver_lookup_name(const char *name) +{ + return __lists_driver_lookup_name(name, false); +} /** * lists_uclass_lookup() - Return uclass_driver based on ID of the class @@ -39,8 +47,8 @@ struct uclass_driver *lists_uclass_lookup(enum uclass_id id); * each one. The devices will have @parent as their parent. * * @parent: parent device (root) - * @early_only: If true, bind only drivers with the DM_INIT_F flag. If false - * bind all drivers. + * @pre_reloc_only: If true, bind only drivers declared with U_BOOT_DRIVER_F. + * If false bind all drivers. */ int lists_bind_drivers(struct udevice *parent, bool pre_reloc_only); diff --git a/include/dm/root.h b/include/dm/root.h index c7f0c1d..61d1cd8 100644 --- a/include/dm/root.h +++ b/include/dm/root.h @@ -26,8 +26,8 @@ struct udevice *dm_root(void); * * This scans all available platdata and creates drivers for each * - * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC - * flag. If false bind all drivers. + * @pre_reloc_only: If true, bind only drivers declared with U_BOOT_DRIVER_F. + * If false bind all drivers. * @return 0 if OK, -ve on error */ int dm_scan_platdata(bool pre_reloc_only); @@ -54,8 +54,8 @@ int dm_scan_fdt(const void *blob, bool pre_reloc_only); * @parent: Parent device for the devices that will be created * @blob: Pointer to device tree blob * @offset: Offset of node to scan - * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC - * flag. If false bind all drivers. + * @pre_reloc_only: If true, bind only drivers declared with U_BOOT_DRIVER_F. + * If false bind all drivers. * @return 0 if OK, -ve on error */ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset, @@ -69,8 +69,8 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset, * programmaticaly. They should do this by calling device_bind() on each * device. * - * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC - * flag. If false bind all drivers. + * @pre_reloc_only: If true, bind only drivers declared with U_BOOT_DRIVER_F. + * If false bind all drivers. */ int dm_scan_other(bool pre_reloc_only); @@ -81,8 +81,8 @@ int dm_scan_other(bool pre_reloc_only); * then scans and binds available devices from platform data and the FDT. * This calls dm_init() to set up Driver Model structures. * - * @pre_reloc_only: If true, bind only drivers with the DM_FLAG_PRE_RELOC - * flag. If false bind all drivers. + * @pre_reloc_only: If true, bind only drivers declared with U_BOOT_DRIVER_F. + * If false bind all drivers. * @return 0 if OK, -ve on error */ int dm_init_and_scan(bool pre_reloc_only);