dm: device_remove: Don't return in device_chld_remove() upon error
PATCH 1/4 dm: device_remove: Don't return in device_chld_remove() upon error
On my x86 platform I've noticed, that calling dm_uninit() or the new function dm_remove_devices_flags() does not remove the desired device at all. Debugging showed, that the serial uclass returns -EPERM in serial_pre_remove() and this leads to a complete stop of the device removal pretty early, as the serial device is one of the first ones in the DM. Here the dm tree output:
=> dm tree
Class Probed Name
----------------------------------------
root [ + ] root_driver rsa_mod_exp [ ] |-- mod_exp_sw serial [ + ] |-- serial rtc [ ] |-- rtc timer [ + ] |-- tsc-timer syscon [ + ] |-- pch_pinctrl
...
In this example, device_remove(root) will stop directly after trying to remove the "serial" device.
To solve this problem, this patch removes the return upon error check in the device_remove() call in device_chld_remove(). This leads to device_chld_remove() continuing with the device_remove() call to the following child devices.
--- drivers/core/device-remove.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/core/device-remove.c +2 -6
@@ -52,15 +52,11 @@ static int device_chld_unbind(struct udevice *dev)static int device_chld_remove (struct udevice *dev,uint flags) {struct udevice *pos, *n; -int ret;assert (dev); -list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { - ret =device_remove (pos, flags); -if (ret) -return ret; - } +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) +device_remove (pos, flags);return 0 ; }
Signature · 1 line
2.12.2
PATCH 2/4 dm: core: Add DM_FLAG_PRE_OS_FINALIZE flag
This new flag can be added to DM device drivers, which need to do some final configuration before U-Boot exits and the OS (e.g. Linux) is started. The remove functions of those drivers will get called at this stage to do these last-stage configuration steps.
--- drivers/core/device-remove.c | 17 ++++++++++++----- include/dm/device.h | 11 ++++++++++- 2 files changed, 22 insertions(+), 6 deletions(-)
drivers/core/device-remove.c +12 -5
@@ -148,6 +148,16 @@ void device_free(struct udevice *dev)devres_release_probe (dev); } +static int flags_remove (uint flags,uint drv_flags) +{ +if ((flags &DM_REMOVE_NORMAL ) || + (flags & (drv_flags & + (DM_FLAG_ACTIVE_DMA |DM_FLAG_PRE_OS_FINALIZE )))) +return 1 ; + +return 0 ; +} +int device_remove (struct udevice *dev,uint flags) {const struct driver *drv;
@@ -174,9 +184,7 @@ int device_remove(struct udevice *dev, uint flags)* Remove the device if called with the "normal" remove flag set, * or if the remove flag matches any of the drivers remove flags */ -if (drv->remove && - ((flags &DM_REMOVE_NORMAL ) || - (flags & (drv->flags &DM_FLAG_ACTIVE_DMA )))) { +if (drv->remove &&flags_remove (flags, drv->flags)) { ret = drv->remove (dev);if (ret) goto err_remove;
@@ -190,8 +198,7 @@ int device_remove(struct udevice *dev, uint flags) } } -if ((flags &DM_REMOVE_NORMAL ) || - (flags & (drv->flags &DM_FLAG_ACTIVE_DMA ))) { +if (flags_remove (flags, drv->flags)) {device_free (dev); dev->seq =-1 ;
include/dm/device.h +10 -1
@@ -55,6 +55,12 @@ struct driver_info;#define DM_FLAG_ACTIVE_DMA (1 << 9)/* +* Call driver remove function to do some final configuration, before +* U-Boot exits and the OS is started +*/ +#define DM_FLAG_PRE_OS_FINALIZE (1 << 10) + +/* * One or multiple of these flags are passed to device_remove() so that * a selective device removal as specified by the remove-stage and the * driver flags can be done.
@@ -66,10 +72,13 @@ enum {/* Remove devices with active DMA */ DM_REMOVE_ACTIVE_DMA =DM_FLAG_ACTIVE_DMA , +/* Remove devices which need some pre-OS finalization */ +DM_REMOVE_PRE_OS_FINALIZE =DM_FLAG_PRE_OS_FINALIZE , +/* Add more use cases here */ /* Remove devices with any active flag */ - DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA, + DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_PRE_OS_FINALIZE, };/**
Signature · 1 line
2.12.2
PATCH 2/4 dm: core: Add DM_FLAG_PRE_OS_FINALIZE flag
Hi Stefan,
Quoted 5 lines · Stefan Roese
This new flag can be added to DM device drivers, which need to do some final configuration before U-Boot exits and the OS (e.g. Linux) is started. The remove functions of those drivers will get called at this stage to do these last-stage configuration steps.
Quoted 7 lines
Signed-off-by Stefan Roese <[email protected]>Cc Simon Glass <[email protected]>Cc Bin Meng <[email protected]>--- drivers/core/device-remove.c | 17 ++++++++++++----- include/dm/device.h | 11 ++++++++++- 2 files changed, 22 insertions(+), 6 deletions(-)
You could perhaps have a separate patch to move the code into flags_remove(), but I suppose it isn't important.
nit below.
drivers/core/device-remove.c void device_free(struct udevice *dev) · line 151
Quoted 10 lines
drivers/core/device-remove.c +1
-0@@ -148,6 +148,16 @@ void device_free(struct udevice *dev)devres_release_probe (dev); } +static int flags_remove (uint flags,uint drv_flags)
Can this be bool, and return true/false?
drivers/core/device-remove.c void device_free(struct udevice *dev) · line 155
Quoted 4 lines
drivers/core/device-remove.c +4
-0+{ +if ((flags &DM_REMOVE_NORMAL ) || + (flags & (drv_flags & + (DM_FLAG_ACTIVE_DMA |DM_FLAG_PRE_OS_FINALIZE ))))
What do you think about OS_PREPARE instead? It doesn't really finalize the OS...
Quoted 62 lines
drivers/core/device-remove.c +7
-5+return 1 ; + +return 0 ; +} +int device_remove (struct udevice *dev,uint flags) {const struct driver *drv;@@ -174,9 +184,7 @@ int device_remove(struct udevice *dev, uint flags)* Remove the device if called with the "normal" remove flag set, * or if the remove flag matches any of the drivers remove flags */ -if (drv->remove && - ((flags &DM_REMOVE_NORMAL ) || - (flags & (drv->flags &DM_FLAG_ACTIVE_DMA )))) { +if (drv->remove &&flags_remove (flags, drv->flags)) { ret = drv->remove (dev);if (ret) goto err_remove;@@ -190,8 +198,7 @@ int device_remove(struct udevice *dev, uint flags) } } -if ((flags &DM_REMOVE_NORMAL ) || - (flags & (drv->flags &DM_FLAG_ACTIVE_DMA ))) { +if (flags_remove (flags, drv->flags)) {device_free (dev); dev->seq =-1 ;include/dm/device.h +10
-2@@ -55,6 +55,12 @@ struct driver_info;#define DM_FLAG_ACTIVE_DMA (1 << 9)/* +* Call driver remove function to do some final configuration, before +* U-Boot exits and the OS is started +*/ +#define DM_FLAG_PRE_OS_FINALIZE (1 << 10) + +/* * One or multiple of these flags are passed to device_remove() so that * a selective device removal as specified by the remove-stage and the * driver flags can be done. @@ -66,10 +72,13 @@ enum {/* Remove devices with active DMA */ DM_REMOVE_ACTIVE_DMA =DM_FLAG_ACTIVE_DMA , +/* Remove devices which need some pre-OS finalization */ +DM_REMOVE_PRE_OS_FINALIZE =DM_FLAG_PRE_OS_FINALIZE , +/* Add more use cases here */ /* Remove devices with any active flag */ - DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA, + DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_PRE_OS_FINALIZE, };/** --
Quoted 2 lines
2.12.2
Regards,
Simon
PATCH 2/4 dm: core: Add DM_FLAG_PRE_OS_FINALIZE flag
Hi Simon,
Quoted 32 lines · Simon Glass
Hi Stefan,
Quoted 5 lines · Stefan Roese
This new flag can be added to DM device drivers, which need to do some final configuration before U-Boot exits and the OS (e.g. Linux) is started. The remove functions of those drivers will get called at this stage to do these last-stage configuration steps.
Quoted 7 lines
Signed-off-by Stefan Roese <[email protected]>Cc Simon Glass <[email protected]>Cc Bin Meng <[email protected]>--- drivers/core/device-remove.c | 17 ++++++++++++----- include/dm/device.h | 11 ++++++++++- 2 files changed, 22 insertions(+), 6 deletions(-)Reviewed-by Simon Glass <[email protected]>You could perhaps have a separate patch to move the code into
flags_remove(), but I suppose it isn't important.nit below.
Quoted 9 lines
drivers/core/device-remove.c +0
-0@@ -148,6 +148,16 @@ void device_free(struct udevice *dev)devres_release_probe (dev); }
Quoted 3 lines
drivers/core/device-remove.c void device_free(struct udevice *dev) · line 151
Quoted 1 line
drivers/core/device-remove.c +1
-0+static int flags_remove (uint flags,uint drv_flags)Can this be bool, and return true/false?
I'm not a big fan of bool but I've no hard feelings here. I'll change this if you prefer it this way in v2.
Quoted 7 lines
drivers/core/device-remove.c void device_free(struct udevice *dev) · line 155
Quoted 4 lines
drivers/core/device-remove.c +4
-0+{ +if ((flags &DM_REMOVE_NORMAL ) || + (flags & (drv_flags & + (DM_FLAG_ACTIVE_DMA |DM_FLAG_PRE_OS_FINALIZE ))))What do you think about
OS_PREPAREinstead? It doesn't really finalize the OS...
Much better, thanks. Will change in v2.
Thanks,
Stefan
PATCH 3/4 x86: bootm: Add dm_remove_devices_flags() call to bootm_announce_and_cleanup()
In reply to Stefan RoeseThis patch adds a call to dm_remove_devices_flags() to bootm_announce_and_cleanup() so that drivers that have one of the removal flags set (e.g. DM_FLAG_ACTIVE_DMA_REMOVE) in their driver struct, may do some last-stage cleanup before the OS is started.
--- arch/x86/lib/bootm.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/x86/lib/bootm.c +9 -0
@@ -10,6 +10,8 @@#include <common.h> #include <command.h> +#include <dm/device.h> +#include <dm/root.h> #include <errno.h> #include <fdt_support.h> #include <image.h>
@@ -46,6 +48,13 @@ void bootm_announce_and_cleanup(void)#ifdef CONFIG_BOOTSTAGE_REPORT bootstage_report ();#endif + +/* +* Call remove function of all devices with a removal flag set. +* This may be useful for last-stage operations, like cancelling +* of DMA operation or releasing device internal buffers. +*/ +dm_remove_devices_flags (DM_REMOVE_ACTIVE_ALL ); }#if defined(CONFIG_OF_LIBFDT ) && !defined(CONFIG_OF_NO_KERNEL )
Signature · 1 line
2.12.2
PATCH 3/4 x86: bootm: Add dm_remove_devices_flags() call to bootm_announce_and_cleanup()
Quoted 11 lines · Stefan Roese
This patch adds a call to
dm_remove_devices_flags()tobootm_announce_and_cleanup()so that drivers that have one of the removal flags set (e.g.DM_FLAG_ACTIVE_DMA_REMOVE) in their driver struct, may do some last-stage cleanup before the OS is started.Signed-off-by Stefan Roese <[email protected]>Cc Bin Meng <[email protected]>Cc Simon Glass <[email protected]>--- arch/x86/lib/bootm.c | 9 +++++++++ 1 file changed, 9 insertions(+)
PATCH 4/4 spi: ich: Configure SPI BIOS parameters for Linux upon U-Boot exit
In reply to Stefan RoeseThis patch adds a remove function to the Intel ICH SPI driver, that will be called upon U-Boot exit, directly before the OS (Linux) is started. This function takes care of configuring the BIOS registers in the SPI controller (similar to what a "standard" BIOS or coreboot does), so that the Linux MTD device driver is able to correctly read/write to the SPI NOR chip. Without this, the chip is not detected at all.
--- drivers/spi/ich.c | 18 ++++++++++++++++++ drivers/spi/ich.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 7 deletions(-)
drivers/spi/ich.c +18 -0
@@ -617,6 +617,22 @@ static int ich_spi_probe(struct udevice *dev)return 0 ; } +static int ich_spi_remove (struct udevice *bus) +{ +struct ich_spi_priv *ctlr =dev_get_priv (bus); + +/* +* Configure SPI controller so that the Linux MTD driver can fully +* access the SPI NOR chip +*/ +ich_writew (ctlr,SPI_OPPREFIX , ctlr->preop); +ich_writew (ctlr,SPI_OPTYPE , ctlr->optype); +ich_writel (ctlr,SPI_OPMENU_LOWER , ctlr->opmenu); +ich_writel (ctlr,SPI_OPMENU_UPPER , ctlr->opmenu +sizeof (u32)); + +return 0 ; +} +static int ich_spi_set_speed (struct udevice *bus,uint speed) {struct ich_spi_priv *priv =dev_get_priv (bus);
@@ -700,4 +716,6 @@ U_BOOT_DRIVER(ich_spi) = { .priv_auto_alloc_size = sizeof(struct ich_spi_priv), .child_pre_probe = ich_spi_child_pre_probe, .probe = ich_spi_probe, + .remove = ich_spi_remove, + .flags = DM_FLAG_PRE_OS_FINALIZE, };
drivers/spi/ich.h +47 -7
68 lines not on this page · raw message
Signature · 1 line
2.12.2
PATCH 4/4 spi: ich: Configure SPI BIOS parameters for Linux upon U-Boot exit
Quoted 111 lines · Stefan Roese
This patch adds a remove function to the Intel ICH SPI driver, that will be called upon U-Boot exit, directly before the OS (Linux) is started. This function takes care of configuring the BIOS registers in the SPI controller (similar to what a "standard" BIOS or coreboot does), so that the Linux MTD device driver is able to correctly read/write to the SPI NOR chip. Without this, the chip is not detected at all.
Signed-off-by Stefan Roese <[email protected]>Cc Bin Meng <[email protected]>Cc Simon Glass <[email protected]>Cc Jagan Teki <[email protected]>--- drivers/spi/ich.c | 18 ++++++++++++++++++ drivers/spi/ich.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 7 deletions(-)drivers/spi/ich.c +18
-0@@ -617,6 +617,22 @@ static int ich_spi_probe(struct udevice *dev)return 0 ; } +static int ich_spi_remove (struct udevice *bus) +{ +struct ich_spi_priv *ctlr =dev_get_priv (bus); + +/* +* Configure SPI controller so that the Linux MTD driver can fully +* access the SPI NOR chip +*/ +ich_writew (ctlr,SPI_OPPREFIX , ctlr->preop); +ich_writew (ctlr,SPI_OPTYPE , ctlr->optype); +ich_writel (ctlr,SPI_OPMENU_LOWER , ctlr->opmenu); +ich_writel (ctlr,SPI_OPMENU_UPPER , ctlr->opmenu +sizeof (u32)); + +return 0 ; +} +static int ich_spi_set_speed (struct udevice *bus,uint speed) {struct ich_spi_priv *priv =dev_get_priv (bus);@@ -700,4 +716,6 @@ U_BOOT_DRIVER(ich_spi) = { .priv_auto_alloc_size = sizeof(struct ich_spi_priv), .child_pre_probe = ich_spi_child_pre_probe, .probe = ich_spi_probe, + .remove = ich_spi_remove, + .flags = DM_FLAG_PRE_OS_FINALIZE, };drivers/spi/ich.h +37
-7@@ -102,13 +102,6 @@ enum { };enum { -SPI_OPCODE_TYPE_READ_NO_ADDRESS =0 , -SPI_OPCODE_TYPE_WRITE_NO_ADDRESS =1 , -SPI_OPCODE_TYPE_READ_WITH_ADDRESS =2 , -SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS =3 -}; - -enum {ICH_MAX_CMD_LEN =5 , };@@ -124,8 +117,55 @@ struct spi_trans {uint32_t offset; }; +#define SPI_OPCODE_WRSR 0x01 +#define SPI_OPCODE_PAGE_PROGRAM 0x02 +#define SPI_OPCODE_READ 0x03 +#define SPI_OPCODE_WRDIS 0x04 +#define SPI_OPCODE_RDSR 0x05#define SPI_OPCODE_WREN 0x06#define SPI_OPCODE_FAST_READ 0x0b +#define SPI_OPCODE_ERASE_SECT 0x20 +#define SPI_OPCODE_READ_ID 0x9f +#define SPI_OPCODE_ERASE_BLOCK 0xd8 + +#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0 +#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1 +#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2 +#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3 + +#define SPI_OPMENU_0 SPI_OPCODE_WRSR +#define SPI_OPTYPE_0 SPI_OPCODE_TYPE_WRITE_NO_ADDRESS + +#define SPI_OPMENU_1 SPI_OPCODE_PAGE_PROGRAM +#define SPI_OPTYPE_1 SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS + +#define SPI_OPMENU_2 SPI_OPCODE_READ +#define SPI_OPTYPE_2 SPI_OPCODE_TYPE_READ_WITH_ADDRESS + +#define SPI_OPMENU_3 SPI_OPCODE_RDSR +#define SPI_OPTYPE_3 SPI_OPCODE_TYPE_READ_NO_ADDRESS + +#define SPI_OPMENU_4 SPI_OPCODE_ERASE_SECT +#define SPI_OPTYPE_4 SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS + +#define SPI_OPMENU_5 SPI_OPCODE_READ_ID +#define SPI_OPTYPE_5 SPI_OPCODE_TYPE_READ_NO_ADDRESS + +#define SPI_OPMENU_6 SPI_OPCODE_ERASE_BLOCK +#define SPI_OPTYPE_6 SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS + +#define SPI_OPMENU_7 SPI_OPCODE_FAST_READ +#define SPI_OPTYPE_7 SPI_OPCODE_TYPE_READ_WITH_ADDRESS
drivers/spi/ich.h struct spi_trans { · line 168
Quoted 10 lines
drivers/spi/ich.h +10
-0+ +#define SPI_OPPREFIX ((SPI_OPCODE_WREN << 8) | SPI_OPCODE_WREN) +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0 << 0)) +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | (SPI_OPMENU_4 << 0)) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | (SPI_OPMENU_0 << 0))
These look flash opcodes, shouldn't be part of spi
thanks!
Signature · 4 lines
Jagan Teki Free Software Engineer | www.openedev.com U-Boot, Linux | Upstream Maintainer Hyderabad, India.
PATCH 4/4 spi: ich: Configure SPI BIOS parameters for Linux upon U-Boot exit
In reply to Stefan RoeseQuoted 7 lines · Stefan Roese
This patch adds a remove function to the Intel ICH SPI driver, that will be called upon U-Boot exit, directly before the OS (Linux) is started. This function takes care of configuring the BIOS registers in the SPI controller (similar to what a "standard" BIOS or coreboot does), so that the Linux MTD device driver is able to correctly read/write to the SPI NOR chip. Without this, the chip is not detected at all.
Quoted 8 lines
Signed-off-by Stefan Roese <[email protected]>Cc Bin Meng <[email protected]>Cc Simon Glass <[email protected]>Cc Jagan Teki <[email protected]>--- drivers/spi/ich.c | 18 ++++++++++++++++++ drivers/spi/ich.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 65 insertions(+), 7 deletions(-)
PATCH 1/4 dm: device_remove: Don't return in device_chld_remove() upon error
In reply to Stefan RoeseHi Stefan,
Quoted 18 lines · Stefan Roese
On my x86 platform I've noticed, that calling
dm_uninit()or the new functiondm_remove_devices_flags()does not remove the desired device at all. Debugging showed, that the serial uclass returns-EPERMinserial_pre_remove()and this leads to a complete stop of the device removal pretty early, as the serial device is one of the first ones in the DM. Here the dm tree output:=> dm tree
Class Probed Name
----------------------------------------root [ + ] root_driver rsa_mod_exp [ ] |-- mod_exp_sw serial [ + ] |-- serial rtc [ ] |-- rtc timer [ + ] |-- tsc-timer syscon [ + ] |-- pch_pinctrl...
Quoted 7 lines
In this example,
device_remove(root)will stop directly after trying to remove the "serial" device.To solve this problem, this patch removes the return upon error check in the
device_remove()call indevice_chld_remove(). This leads todevice_chld_remove()continuing with thedevice_remove()call to the following child devices.
I think the right solution is to find out why stdio_deregister_dev() fails. It is probably because the device is in use within the stdio variables. Perhaps you need to remove it first?
Quoted 17 lines
Signed-off-by Stefan Roese <[email protected]>Cc Simon Glass <[email protected]>Cc Bin Meng <[email protected]>--- drivers/core/device-remove.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)drivers/core/device-remove.c +0
-1@@ -52,15 +52,11 @@ static int device_chld_unbind(struct udevice *dev)static int device_chld_remove (struct udevice *dev,uint flags) {struct udevice *pos, *n; -int ret;
drivers/core/device-remove.c static int device_chld_unbind(struct udevice *dev) · line 59
Quoted 10 lines
drivers/core/device-remove.c +2
-5assert (dev); -list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { - ret =device_remove (pos, flags); -if (ret) -return ret; - } +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) +device_remove (pos, flags);
I think we should keep the error checking here.
Quoted 6 lines
drivers/core/device-remove.c +0
-1return 0 ; } --2.12.2
Regards,
Simon
PATCH 1/4 dm: device_remove: Don't return in device_chld_remove() upon error
Hi Simon,
sorry for the late replay - just back from vacation....
Quoted 24 lines · Simon Glass
Hi Stefan,
Quoted 21 lines · Stefan Roese
On my x86 platform I've noticed, that calling
dm_uninit()or the new functiondm_remove_devices_flags()does not remove the desired device at all. Debugging showed, that the serial uclass returns-EPERMinserial_pre_remove()and this leads to a complete stop of the device removal pretty early, as the serial device is one of the first ones in the DM. Here the dm tree output:=> dm tree
Class Probed Name
----------------------------------------root [ + ] root_driver rsa_mod_exp [ ] |-- mod_exp_sw serial [ + ] |-- serial rtc [ ] |-- rtc timer [ + ] |-- tsc-timer syscon [ + ] |-- pch_pinctrl...
In this example,
device_remove(root)will stop directly after trying to remove the "serial" device.
Quoted 8 lines
Quoted 4 lines
To solve this problem, this patch removes the return upon error check in the
device_remove()call indevice_chld_remove(). This leads todevice_chld_remove()continuing with thedevice_remove()call to the following child devices.I think the right solution is to find out why
stdio_deregister_dev()fails. It is probably because the device is in use within the stdio variables.
This is most likely the case, yes.
Quoted 1 line
Perhaps you need to remove it first?
Not sure if this should / could be done in this general case of removal of all devices (or all devices matching a remove-flag)? Please think of dm_uninit() being called. This functions should have no internal knowledge of usage of devices. One thing I could do, probably best in a separate patch, is to use the force flag of stdio_deregister_dev() in serial_pre_remove() to force the serial device(s) to be removed in this case. What do you think?
Quoted 20 lines
Quoted 20 lines
Signed-off-by Stefan Roese <[email protected]>Cc Simon Glass <[email protected]>Cc Bin Meng <[email protected]>--- drivers/core/device-remove.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)drivers/core/device-remove.c +0
-1@@ -52,15 +52,11 @@ static int device_chld_unbind(struct udevice *dev)static int device_chld_remove (struct udevice *dev,uint flags) {struct udevice *pos, *n; -int ret;assert (dev);
Quoted 9 lines
drivers/core/device-remove.c static int device_chld_unbind(struct udevice *dev) · line 59
Quoted 7 lines
drivers/core/device-remove.c +2
-5-list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { - ret =device_remove (pos, flags); -if (ret) -return ret; - } +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) +device_remove (pos, flags);I think we should keep the error checking here.
The main fix with this patch is, that removing of child devices does not stop once an error is encountered. Even if an error occurs with one child-device of a parent, all other child-devices of this parent should still be removed - or at least tried to.
So what does this error code buy us here? Should I print a log message here in this error case?
Thanks,
Stefan
PATCH 1/4 dm: device_remove: Don't return in device_chld_remove() upon error
Hi Stefan,
Quoted 48 lines · Stefan Roese
Hi Simon,
sorry for the late replay - just back from vacation....
Quoted 32 lines · Simon Glass
Hi Stefan,
Quoted 19 lines · Stefan Roese
On my x86 platform I've noticed, that calling
dm_uninit()or the new functiondm_remove_devices_flags()does not remove the desired device at all. Debugging showed, that the serial uclass returns-EPERMinserial_pre_remove()and this leads to a complete stop of the device removal pretty early, as the serial device is one of the first ones in the DM. Here the dm tree output:=> dm tree
Class Probed Name
----------------------------------------root [ + ] root_driver rsa_mod_exp [ ] |-- mod_exp_sw serial [ + ] |-- serial rtc [ ] |-- rtc timer [ + ] |-- tsc-timer syscon [ + ] |-- pch_pinctrl...
Quoted 7 lines
In this example,
device_remove(root)will stop directly after trying to remove the "serial" device.To solve this problem, this patch removes the return upon error check in the
device_remove()call indevice_chld_remove(). This leads todevice_chld_remove()continuing with thedevice_remove()call to the following child devices.Quoted 3 lines
I think the right solution is to find out why
stdio_deregister_dev()fails. It is probably because the device is in use within the stdio variables.This is most likely the case, yes.
Quoted 1 line
Perhaps you need to remove it first?
Quoted 7 lines
Not sure if this should / could be done in this general case of removal of all devices (or all devices matching a remove-flag)? Please think of
dm_uninit()being called. This functions should have no internal knowledge of usage of devices. One thing I could do, probably best in a separate patch, is to use the force flag ofstdio_deregister_dev()inserial_pre_remove()to force the serial device(s) to be removed in this case. What do you think?
I think that sounds reasonable. I don't know this area very well though.
Quoted 34 lines
Quoted 21 lines
Quoted 21 lines
Signed-off-by Stefan Roese <[email protected]>Cc Simon Glass <[email protected]>Cc Bin Meng <[email protected]>--- drivers/core/device-remove.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)drivers/core/device-remove.c +0
-1@@ -52,15 +52,11 @@ static int device_chld_unbind(struct udevice *dev)static int device_chld_remove (struct udevice *dev,uint flags) {struct udevice *pos, *n; -int ret;assert (dev);Quoted 11 lines
drivers/core/device-remove.c static int device_chld_unbind(struct udevice *dev) · line 59
Quoted 8 lines
drivers/core/device-remove.c +2
-5-list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) { - ret =device_remove (pos, flags); -if (ret) -return ret; - } +list_for_each_entry_safe (pos, n, &dev->child_head, sibling_node) +device_remove (pos, flags);I think we should keep the error checking here.
Quoted 7 lines
The main fix with this patch is, that removing of child devices does not stop once an error is encountered. Even if an error occurs with one child-device of a parent, all other child-devices of this parent should still be removed - or at least tried to.
So what does this error code buy us here? Should I print a log message here in this error case?
Yes just a debug() will do. I see what you are saying, I'm just nervous of dropping error checking since devices really should remove cleanly. Hopefully as above you can fix the error?
Regards,
Simon