Compare commits

...

4 Commits
tesg ... eth2

Author SHA1 Message Date
Simon Glass
7b462ba6a1 dm: core: Rename dm_remove_devices_active()
This function doesn't have a great name, since we talk of devices being
active once they are probed.

Rename it to dm_remove_dma_devices().

Series-to: u-boot
Series-version: 2
Cover-letter:
dm: net: Assorted patches related to networking and DMA
This series collects together a few patches related to U-Boot leaving
DMA running when booting.
END

Signed-off-by: Simon Glass <sjg@chromium.org>
Suggested-by: Jonas Karlman <jonas@kwiboo.se>
2025-04-07 13:02:52 +12:00
Simon Glass
7a6af0e015 efi_loader: Move device-removal later in exit-boot-services
This removal should be the last thing done, so that U-Boot does no more
memory allocations afterwards, thus avoiding potentially allocating
memory which has been freed by a device that fails to de-activate its
DMA.

Of course, devices should be marked with DM_FLAG_ACTIVE_DMA or
DM_FLAG_OS_PREPARE but this change is good practice, in any case.

It also matches the code in announce_and_cleanup(), which we should at
some point unify with EFI_LOADER

So move the code and add a comment.

Note that the TCG2 log is updated after this call, but I cannot see any
allocations there.

Series-to: u-boot
Series-cc: trini, heinrich, ilias
Series-cc: neil.armstrong@linaro.org
Reported-by: Christian Kohlschütter <christian@kohlschutter.com>
Link: https://lore.kernel.org/u-boot/C101B675-EEE6-44CB-8A44-83F72182FBD6@kohlschutter.com/

Signed-off-by: Simon Glass <sjg@chromium.org>
2025-04-07 12:59:04 +12:00
Simon Glass
5b3de93283 net: designware: Mark drivers as having active DMA
Network devices which use this driver have DMA running while receiving
packages. Add the required flag to driver model so that they will be
removed before starting the OS.

Series-changes: 2
- Add a new patch to mark drivers as having active DMA

Signed-off-by: Simon Glass <sjg@chromium.org>
2025-04-07 10:43:45 +12:00
Simon Glass
483136795f designware: Use the remove() method with related drivers
Several drivers make use of the designware Ethernet driver but do not
implement the remove() method. Add this to keep things tidy.

Note that the Ethernet uclass calls each driver's stop() method on
removal, so there is no need to do that here.

Series-changes: 2
- Use the designware_eth_remove() method directly
- Add gmac_rockchip too
- Reword the commit message to mention the uclass' actions

Signed-off-by: Simon Glass <sjg@chromium.org>
Reported-by: Christian Kohlschütter <christian@kohlschutter.com>
2025-04-07 10:42:52 +12:00
13 changed files with 44 additions and 23 deletions

View File

@@ -74,10 +74,10 @@ static void announce_and_cleanup(int fake)
* 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_active() ensures that vital devices are removed in
* dm_remove_dma_devices() ensures that vital devices are removed in
* a second round.
*/
dm_remove_devices_active();
dm_remove_dma_devices();
cleanup_before_linux();
}

View File

@@ -57,7 +57,7 @@ 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.
*/
dm_remove_devices_active();
dm_remove_dma_devices();
cleanup_before_linux();
}

View File

@@ -50,7 +50,7 @@ void bootm_announce_and_cleanup(void)
* This may be useful for last-stage operations, like cancelling
* of DMA operation or releasing device internal buffers.
*/
dm_remove_devices_active();
dm_remove_dma_devices();
}
#if defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_OF_NO_KERNEL)

View File

@@ -148,7 +148,7 @@ int dm_remove_devices_flags(uint flags)
return 0;
}
void dm_remove_devices_active(void)
void dm_remove_dma_devices(void)
{
/* Remove non-vital devices first */
device_remove(dm_root(), DM_REMOVE_ACTIVE_ALL | DM_REMOVE_NON_VITAL);

View File

@@ -805,7 +805,7 @@ clk_err:
return err;
}
static int designware_eth_remove(struct udevice *dev)
int designware_eth_remove(struct udevice *dev)
{
struct dw_eth_dev *priv = dev_get_priv(dev);
@@ -885,7 +885,7 @@ U_BOOT_DRIVER(eth_designware) = {
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dw_eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};
static struct pci_device_id supported[] = {

View File

@@ -247,6 +247,18 @@ struct dw_eth_dev {
int designware_eth_of_to_plat(struct udevice *dev);
int designware_eth_probe(struct udevice *dev);
/**
* designware_eth_remove() - Remove the device
*
* Disables DMA and marks the device as remove. This must be called before
* booting an OS, to ensure that DMA is inactive.
*
* @dev: Device to remove
* Return 0 if OK, -ve on error
*/
int designware_eth_remove(struct udevice *dev);
extern const struct eth_ops designware_eth_ops;
struct dw_eth_pdata {

View File

@@ -158,8 +158,9 @@ U_BOOT_DRIVER(dwmac_meson8b) = {
.of_match = dwmac_meson8b_ids,
.of_to_plat = dwmac_meson8b_of_to_plat,
.probe = dwmac_meson8b_probe,
.remove = designware_eth_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_meson8b_plat),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};

View File

@@ -60,8 +60,9 @@ U_BOOT_DRIVER(dwmac_s700) = {
.of_match = dwmac_s700_ids,
.of_to_plat = dwmac_s700_of_to_plat,
.probe = dwmac_s700_probe,
.remove = designware_eth_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct eth_pdata),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};

View File

@@ -141,8 +141,9 @@ U_BOOT_DRIVER(dwmac_socfpga) = {
.of_match = dwmac_socfpga_ids,
.of_to_plat = dwmac_socfpga_of_to_plat,
.probe = dwmac_socfpga_probe,
.remove = designware_eth_remove,
.ops = &designware_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct dwmac_socfpga_plat),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};

View File

@@ -756,8 +756,9 @@ U_BOOT_DRIVER(eth_gmac_rockchip) = {
.of_match = rockchip_gmac_ids,
.of_to_plat = gmac_rockchip_of_to_plat,
.probe = gmac_rockchip_probe,
.remove = designware_eth_remove,
.ops = &gmac_rockchip_eth_ops,
.priv_auto = sizeof(struct dw_eth_dev),
.plat_auto = sizeof(struct gmac_rockchip_plat),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
.flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_ACTIVE_DMA,
};

View File

@@ -169,16 +169,16 @@ int dm_uninit(void);
int dm_remove_devices_flags(uint flags);
/**
* dm_remove_devices_active - Call remove function of all active drivers heeding
* dm_remove_dma_devices - Call remove function of all active drivers heeding
* device dependencies as far as know, i.e. removing
* devices marked with DM_FLAG_VITAL last.
*
* All active devices will be removed
*/
void dm_remove_devices_active(void);
void dm_remove_dma_devices(void);
#else
static inline int dm_remove_devices_flags(uint flags) { return 0; }
static inline void dm_remove_devices_active(void) { }
static inline void dm_remove_dma_devices(void) { }
#endif
/**

View File

@@ -2250,14 +2250,6 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
list_del(&evt->link);
}
if (!efi_st_keep_devices) {
bootm_disable_interrupts();
if (IS_ENABLED(CONFIG_USB_DEVICE))
udc_disconnect();
board_quiesce_devices();
dm_remove_devices_active();
}
/* Patch out unsupported runtime function */
efi_runtime_detach();
@@ -2279,6 +2271,19 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
/* Give the payload some time to boot */
efi_set_watchdog(0);
schedule();
/*
* this should be the last thing done, to avoid memory allocations
* between removing devices and the OS taking over
*/
if (!efi_st_keep_devices) {
bootm_disable_interrupts();
if (IS_ENABLED(CONFIG_USB_DEVICE))
udc_disconnect();
board_quiesce_devices();
dm_remove_dma_devices();
}
out:
if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) {
if (ret != EFI_SUCCESS)

View File

@@ -1057,7 +1057,7 @@ static int dm_test_remove_active(struct unit_test_state *uts)
ut_asserteq(true, device_active(dma_vital));
/* Remove active devices in an ordered way */
dm_remove_devices_active();
dm_remove_dma_devices();
/* Check that all devices are inactive right now */
ut_asserteq(true, device_active(normal));