From c1d6f91952d0761f61b0f0f96e4c7aa32eee2788 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Wed, 15 Apr 2015 13:07:17 +0200 Subject: dm: core: add internal functions for getting the device without probe This commit extends the uclass-internal functions by: - uclass_find_first_device() - uclass_find_next_device() For both functions, the returned device is not probed. After some cleanup, the above functions are called by: - uclass_first_device() - uclass_next_device() for which, the returned device is probed. Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Acked-by: Simon Glass --- drivers/core/uclass.c | 59 +++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'drivers/core/uclass.c') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 98c15e585df..21ab0d52452 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -156,6 +156,36 @@ int uclass_find_device(enum uclass_id id, int index, struct udevice **devp) return -ENODEV; } +int uclass_find_first_device(enum uclass_id id, struct udevice **devp) +{ + struct uclass *uc; + int ret; + + *devp = NULL; + ret = uclass_get(id, &uc); + if (ret) + return ret; + if (list_empty(&uc->dev_head)) + return 0; + + *devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node); + + return 0; +} + +int uclass_find_next_device(struct udevice **devp) +{ + struct udevice *dev = *devp; + + *devp = NULL; + if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head)) + return 0; + + *devp = list_entry(dev->uclass_node.next, struct udevice, uclass_node); + + return 0; +} + int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, bool find_req_seq, struct udevice **devp) { @@ -274,24 +304,12 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node, int uclass_first_device(enum uclass_id id, struct udevice **devp) { - struct uclass *uc; struct udevice *dev; int ret; *devp = NULL; - ret = uclass_get(id, &uc); - if (ret) - return ret; - if (list_empty(&uc->dev_head)) - return 0; - - dev = list_first_entry(&uc->dev_head, struct udevice, uclass_node); - ret = device_probe(dev); - if (ret) - return ret; - *devp = dev; - - return 0; + ret = uclass_find_first_device(id, &dev); + return uclass_get_device_tail(dev, ret, devp); } int uclass_next_device(struct udevice **devp) @@ -300,17 +318,8 @@ int uclass_next_device(struct udevice **devp) int ret; *devp = NULL; - if (list_is_last(&dev->uclass_node, &dev->uclass->dev_head)) - return 0; - - dev = list_entry(dev->uclass_node.next, struct udevice, - uclass_node); - ret = device_probe(dev); - if (ret) - return ret; - *devp = dev; - - return 0; + ret = uclass_find_next_device(&dev); + return uclass_get_device_tail(dev, ret, devp); } int uclass_bind_device(struct udevice *dev) -- cgit v1.2.3 From e0735a4c60577fafdaed71c5ef046f04b0f53f09 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Wed, 15 Apr 2015 13:07:22 +0200 Subject: dm: core: uclass: add function: uclass_find_device_by_name() This commit extends the driver model uclass's API by function: - uclass_find_device_by_name() And this function returns the device if: - uclass with given ID, exists, - device with exactly given name(dev->name), exists. The returned device is not activated - need to be probed before use. Note: This function returns the first device, which name is equal to the given one. This means, that using this function you must assume, that the device name is unique in the given uclass's ID device list. uclass-internal.h: cleanup - move the uclass_find_device_by_seq() declaration and description, near the other uclass_find*() functions. Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Acked-by: Simon Glass --- drivers/core/uclass.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/core/uclass.c') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 21ab0d52452..61e96e9a427 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -186,6 +186,30 @@ int uclass_find_next_device(struct udevice **devp) return 0; } +int uclass_find_device_by_name(enum uclass_id id, const char *name, + struct udevice **devp) +{ + struct uclass *uc; + struct udevice *dev; + int ret; + + *devp = NULL; + if (!name) + return -EINVAL; + ret = uclass_get(id, &uc); + if (ret) + return ret; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + if (!strncmp(dev->name, name, strlen(name))) { + *devp = dev; + return 0; + } + } + + return -ENODEV; +} + int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, bool find_req_seq, struct udevice **devp) { -- cgit v1.2.3 From b7af1a2da767c0dd283ffce3d50efd36af32df14 Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Wed, 15 Apr 2015 13:07:23 +0200 Subject: dm: core: uclass: add function: uclass_get_device_by_name() This commit extends the driver model uclass's API by function: - uclass_get_device_by_name() And this function returns the device if: - uclass with given ID, exists, - device with exactly given name(dev->name), exists, - device probe, doesn't return an error. The returned device is activated and ready to use. Note: This function returns the first device, which name is equal to the given one. This means, that using this function you must assume, that the device name is unique in the given uclass's ID device list. Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Acked-by: Simon Glass --- drivers/core/uclass.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/core/uclass.c') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 61e96e9a427..c1ebee77f01 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -298,6 +298,17 @@ int uclass_get_device(enum uclass_id id, int index, struct udevice **devp) return uclass_get_device_tail(dev, ret, devp); } +int uclass_get_device_by_name(enum uclass_id id, const char *name, + struct udevice **devp) +{ + struct udevice *dev; + int ret; + + *devp = NULL; + ret = uclass_find_device_by_name(id, name, &dev); + return uclass_get_device_tail(dev, ret, devp); +} + int uclass_get_device_by_seq(enum uclass_id id, int seq, struct udevice **devp) { struct udevice *dev; -- cgit v1.2.3 From 794d521917eab07651248174a81ba51cd265d9dc Mon Sep 17 00:00:00 2001 From: Przemyslaw Marczak Date: Mon, 20 Apr 2015 13:32:32 +0200 Subject: dm: core: remove type 'static' of function uclass_get_device_tail() Uclass API provides a few functions for get/find the device. To provide a complete function set of uclass-internal functions, for use by the drivers, the function uclass_get_device_tail() should be non-static. Signed-off-by: Przemyslaw Marczak Cc: Simon Glass Acked-by: Simon Glass --- drivers/core/uclass.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/core/uclass.c') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index c1ebee77f01..7627ad141b5 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -263,17 +263,7 @@ static int uclass_find_device_by_of_offset(enum uclass_id id, int node, return -ENODEV; } -/** - * uclass_get_device_tail() - handle the end of a get_device call - * - * This handles returning an error or probing a device as needed. - * - * @dev: Device that needs to be probed - * @ret: Error to return. If non-zero then the device is not probed - * @devp: Returns the value of 'dev' if there is no error - * @return ret, if non-zero, else the result of the device_probe() call - */ -static int uclass_get_device_tail(struct udevice *dev, int ret, +int uclass_get_device_tail(struct udevice *dev, int ret, struct udevice **devp) { if (ret) -- cgit v1.2.3 From 07d260e047680971d926bc9a573f9291f39fc988 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 19 Apr 2015 07:20:58 -0600 Subject: dm: core: Handle recursive unbinding of uclass devices Since a device can have children in the same uclass as itself, we need to handle unbinding carefully: we must allow that unbinding a device in a uclass may cause another device in the same uclass to be unbound. Adjust the code to cope. Signed-off-by: Simon Glass Reviewed-by: Joe Hershberger Tested-by: Joe Hershberger --- drivers/core/uclass.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/core/uclass.c') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 7627ad141b5..9fec8c9c7ad 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -99,10 +99,18 @@ fail_mem: int uclass_destroy(struct uclass *uc) { struct uclass_driver *uc_drv; - struct udevice *dev, *tmp; + struct udevice *dev; int ret; - list_for_each_entry_safe(dev, tmp, &uc->dev_head, uclass_node) { + /* + * We cannot use list_for_each_entry_safe() here. If a device in this + * uclass has a child device also in this uclass, it will be also be + * unbound (by the recursion in the call to device_unbind() below). + * We can loop until the list is empty. + */ + while (!list_empty(&uc->dev_head)) { + dev = list_first_entry(&uc->dev_head, struct udevice, + uclass_node); ret = device_remove(dev); if (ret) return ret; -- cgit v1.2.3 From 7f9875e733b79556ade508b88f88ac1f8a2c7e3c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 27 Feb 2015 22:06:31 -0700 Subject: dm: core: Remove unbind operations when not required The CONFIG_DM_DEVICE_REMOVE option takes out code related to removing devices. It should also remove the 'unbind' code since if we cannot remove we probably don't need to unbind. Signed-off-by: Simon Glass --- drivers/core/uclass.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/core/uclass.c') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 9fec8c9c7ad..04e939d6c13 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -386,6 +386,7 @@ err: return ret; } +#ifdef CONFIG_DM_DEVICE_REMOVE int uclass_unbind_device(struct udevice *dev) { struct uclass *uc; @@ -401,6 +402,7 @@ int uclass_unbind_device(struct udevice *dev) list_del(&dev->uclass_node); return 0; } +#endif int uclass_resolve_seq(struct udevice *dev) { @@ -464,6 +466,7 @@ int uclass_post_probe_device(struct udevice *dev) return 0; } +#ifdef CONFIG_DM_DEVICE_REMOVE int uclass_pre_remove_device(struct udevice *dev) { struct uclass_driver *uc_drv; @@ -485,3 +488,4 @@ int uclass_pre_remove_device(struct udevice *dev) return 0; } +#endif -- cgit v1.2.3