Skip to content

Instantly share code, notes, and snippets.

@rfs613
Last active July 8, 2021 19:47
Show Gist options
  • Save rfs613/5b09a35553573bd8facda7f368bbcd90 to your computer and use it in GitHub Desktop.
Save rfs613/5b09a35553573bd8facda7f368bbcd90 to your computer and use it in GitHub Desktop.
u-boot dm_remove serial
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 0f565c397f2..3e699f3747b 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -119,7 +119,9 @@ static void announce_and_cleanup(int fake)
* This may be useful for last-stage operations, like cancelling
* of DMA operation or releasing device internal buffers.
*/
+ printf("RFS: %s:%d before\n", __func__, __LINE__);
dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
+ printf("RFS: %s:%d after\n", __func__, __LINE__);
cleanup_before_linux();
}
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index efdb0f29058..611102e2760 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -163,6 +163,8 @@ int device_remove(struct udevice *dev, uint flags)
const struct driver *drv;
int ret;
+ printk("RFS: %s:%d flags=%08x drv->flags=%08x name=<%s>\n", __func__, __LINE__, flags, dev->flags, dev->name);
+
if (!dev)
return -EINVAL;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 7d257ea887d..767ef4859f0 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -176,7 +176,9 @@ int dm_uninit(void)
#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
int dm_remove_devices_flags(uint flags)
{
- device_remove(dm_root(), flags);
+ int ret = device_remove(dm_root(), flags);
+
+ printf("RFS: %s:%d device_remove() returned %d\n", __func__, __LINE__, ret);
return 0;
}
---------------------------------------------------
Loading: ####
6.3 MiB/s
done
Bytes transferred = 46388 (b534 hex)
## Flattened Device Tree blob at 81000000
Booting using the fdt blob at 0x81000000
Loading Device Tree to 879f1000, end 879ff533 ... OK
Starting kernel ...
RFS: announce_and_cleanup:122 before
RFS: device_remove:166 flags=00000600 drv->flags=00001041 name=<root_driver>
RFS: device_remove:166 flags=00000600 drv->flags=00000040 name=<mod_exp_sw>
RFS: device_remove:166 flags=00000600 drv->flags=00001051 name=<bus>
RFS: device_remove:166 flags=00000600 drv->flags=00001043 name=<spi@40005000>
RFS: device_remove:166 flags=00000600 drv->flags=00000048 name=<spi_flash@0:0>
RFS: device_remove:166 flags=00000600 drv->flags=00001043 name=<serial@40060000>
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 5.10.47-00084-gf8299fd8dfc2 (ralphs@maple) (arm-dip-linux-gnueabi-gcc (GCC) 9.2.1 20191025, GNU ld (GNU Binutils) 2.34.
0.20200220) #6 SMP Tue Jul 6 13:46:59 EDT 2021
-----
If I exclude the uart from device_remove,
if (strcmp(dev->name, "serial@40060000") == 0)
return 0;
then all prints show up as expected:
Starting kernel ...
RFS: announce_and_cleanup:122 before
RFS: device_remove:166 flags=00000600 drv->flags=00001041 name=<root_driver>
RFS: device_remove:166 flags=00000600 drv->flags=00000040 name=<mod_exp_sw>
RFS: device_remove:166 flags=00000600 drv->flags=00001051 name=<bus>
RFS: device_remove:166 flags=00000600 drv->flags=00000048 name=<spi_flash@0:0>
RFS: device_remove:166 flags=00000600 drv->flags=00001043 name=<serial@40060000>
RFS: device_remove:166 flags=00000600 drv->flags=00001043 name=<sdhci@40100000>
RFS: device_remove:166 flags=00000600 drv->flags=000000d0 name=<sdhci@40100000.blk>
RFS: device_remove:166 flags=00000600 drv->flags=00001043 name=<ethernet@44002000>
RFS: device_remove:166 flags=00000600 drv->flags=00000040 name=<gpio@5000b000>
RFS: device_remove:166 flags=00000600 drv->flags=00001041 name=<gpio@5000d000>
RFS: device_remove:166 flags=00000600 drv->flags=00001041 name=<gpio2a>
RFS: device_remove:166 flags=00000600 drv->flags=00000040 name=<gpio2b>
RFS: dm_remove_devices_flags:181 device_remove() returned 0
RFS: announce_and_cleanup:124 after
Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 5.10.47-00084-gf8299fd8dfc2 (ralphs@maple) (arm-dip-linux-gnueabi-gcc (GCC) 9.2.1 20191025, GNU ld (GNU Binutils) 2.34.
0.20200220) #6 SMP Tue Jul 6 13:46:59 EDT 2021
---------------
After more debugging, the culprit is CONFIG_SYS_STDIO_DEREGISTER=y,
which is enabled because I have CONFIG_USB_KEYBOARD=y
This sets up a pre_remove hook for the serial device, so that
dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
`- device_remove("serial@40060000")
`- uclass_pre_remove_device()
`- serial_pre_remove()
`- stdio_deregister_dev() -> uart stops printing
----------------
And there is a fix upstream, c51d2e704a1c89d504b3
dm: core: Avoid partially removing devices
At present if device_remove() decides that the device should not actually
be removed, it still calls the uclass pre_remove() method and powers the
device down.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment