Re: [PATCH 3/3] driver core: platform: use bus_type functions

From: Marek Szyprowski
Date: Fri Dec 11 2020 - 11:14:16 EST


Hi Uwe,

On 19.11.2020 13:46, Uwe Kleine-König wrote:
> This works towards the goal mentioned in 2006 in commit 594c8281f905
> ("[PATCH] Add bus_type probe, remove, shutdown methods.").
>
> The functions are moved to where the other bus_type functions are
> defined and renamed to match the already established naming scheme.
>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
> ---
> drivers/base/platform.c | 132 ++++++++++++++++++++--------------------
> 1 file changed, 65 insertions(+), 67 deletions(-)
>
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index b847f5f8f992..8ad06daa2eaa 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -743,70 +743,6 @@ struct platform_device *platform_device_register_full(
> }
> EXPORT_SYMBOL_GPL(platform_device_register_full);
>
> -static int platform_probe_fail(struct platform_device *pdev);
> -
> -static int platform_drv_probe(struct device *_dev)
> -{
> - struct platform_driver *drv = to_platform_driver(_dev->driver);
> - struct platform_device *dev = to_platform_device(_dev);
> - int ret;
> -
> - /*
> - * A driver registered using platform_driver_probe() cannot be bound
> - * again later because the probe function usually lives in __init code
> - * and so is gone. For these drivers .probe is set to
> - * platform_probe_fail in __platform_driver_probe(). Don't even
> - * prepare clocks and PM domains for these to match the traditional
> - * behaviour.
> - */
> - if (unlikely(drv->probe == platform_probe_fail))
> - return -ENXIO;
> -
> - ret = of_clk_set_defaults(_dev->of_node, false);
> - if (ret < 0)
> - return ret;
> -
> - ret = dev_pm_domain_attach(_dev, true);
> - if (ret)
> - goto out;
> -
> - if (drv->probe) {
> - ret = drv->probe(dev);
> - if (ret)
> - dev_pm_domain_detach(_dev, true);
> - }
> -
> -out:
> - if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
> - dev_warn(_dev, "probe deferral not supported\n");
> - ret = -ENXIO;
> - }
> -
> - return ret;
> -}
> -
> -static int platform_drv_remove(struct device *_dev)
> -{
> - struct platform_driver *drv = to_platform_driver(_dev->driver);
> - struct platform_device *dev = to_platform_device(_dev);
> - int ret = 0;
> -
> - if (drv->remove)
> - ret = drv->remove(dev);
> - dev_pm_domain_detach(_dev, true);
> -
> - return ret;
> -}
> -
> -static void platform_drv_shutdown(struct device *_dev)
> -{
> - struct platform_driver *drv = to_platform_driver(_dev->driver);
> - struct platform_device *dev = to_platform_device(_dev);
> -
> - if (drv->shutdown)
> - drv->shutdown(dev);
> -}
> -
> /**
> * __platform_driver_register - register a driver for platform-level devices
> * @drv: platform driver structure
> @@ -817,9 +753,6 @@ int __platform_driver_register(struct platform_driver *drv,
> {
> drv->driver.owner = owner;
> drv->driver.bus = &platform_bus_type;
> - drv->driver.probe = platform_drv_probe;
> - drv->driver.remove = platform_drv_remove;
> - drv->driver.shutdown = platform_drv_shutdown;
>
> return driver_register(&drv->driver);
> }
> @@ -1349,6 +1282,68 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
> return 0;
> }
>
> +static int platform_probe(struct device *_dev)
> +{
> + struct platform_driver *drv = to_platform_driver(_dev->driver);
> + struct platform_device *dev = to_platform_device(_dev);
> + int ret;
> +
> + /*
> + * A driver registered using platform_driver_probe() cannot be bound
> + * again later because the probe function usually lives in __init code
> + * and so is gone. For these drivers .probe is set to
> + * platform_probe_fail in __platform_driver_probe(). Don't even prepare
> + * clocks and PM domains for these to match the traditional behaviour.
> + */
> + if (unlikely(drv->probe == platform_probe_fail))
> + return -ENXIO;
> +
> + ret = of_clk_set_defaults(_dev->of_node, false);
> + if (ret < 0)
> + return ret;
> +
> + ret = dev_pm_domain_attach(_dev, true);
> + if (ret)
> + goto out;
> +
> + if (drv->probe) {
> + ret = drv->probe(dev);
> + if (ret)
> + dev_pm_domain_detach(_dev, true);
> + }
> +
> +out:
> + if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
> + dev_warn(_dev, "probe deferral not supported\n");
> + ret = -ENXIO;
> + }
> +
> + return ret;
> +}
> +
> +static int platform_remove(struct device *_dev)
> +{
> + struct platform_driver *drv = to_platform_driver(_dev->driver);
> + struct platform_device *dev = to_platform_device(_dev);
> + int ret = 0;
> +
> + if (drv->remove)
> + ret = drv->remove(dev);
> + dev_pm_domain_detach(_dev, true);
> +
> + return ret;
> +}
> +
> +static void platform_shutdown(struct device *_dev)
> +{
> + struct platform_driver *drv = to_platform_driver(_dev->driver);
> + struct platform_device *dev = to_platform_device(_dev);
> +
> + if (drv->shutdown)
> + drv->shutdown(dev);
> +}

This will be called on unbound devices, what causes crash (observed on
today's linux-next):

Will now restart.
8<--- cut here ---
Unable to handle kernel paging request at virtual address fffffff4
pgd = 289f4b67
[fffffff4] *pgd=6ffff841, *pte=00000000, *ppte=00000000
Internal error: Oops: 27 [#1] SMP ARM
Modules linked in: usb_f_ecm g_ether usb_f_rndis u_ether libcomposite
brcmfmac sha256_generic libsha256 sha256_arm cfg80211 brcmutil
panel_samsung_s6e8aa0 s5p_csi
CPU: 0 PID: 1715 Comm: reboot Not tainted
5.10.0-rc7-next-20201211-00069-g1e8aa883315f #9935
Hardware name: Samsung Exynos (Flattened Device Tree)
PC is at platform_shutdown+0x8/0x18
LR is at device_shutdown+0x18c/0x25c
...
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 10c5387d  Table: 4348404a  DAC: 00000051
Process reboot (pid: 1715, stack limit = 0xd050391e)
Stack: (0xc3405e60 to 0xc3406000)
[<c0a38bfc>] (platform_shutdown) from [<c0a34f78>]
(device_shutdown+0x18c/0x25c)
[<c0a34f78>] (device_shutdown) from [<c036d3cc>] (kernel_restart+0xc/0x68)
[<c036d3cc>] (kernel_restart) from [<c036d680>]
(__do_sys_reboot+0x154/0x1f0)
[<c036d680>] (__do_sys_reboot) from [<c03000c0>] (ret_fast_syscall+0x0/0x58)
Exception stack(0xc3405fa8 to 0xc3405ff0)
...
---[ end trace f39e94d5d6fd45bf ]---


> +
> +
> int platform_dma_configure(struct device *dev)
> {
> enum dev_dma_attr attr;
> @@ -1375,6 +1370,9 @@ struct bus_type platform_bus_type = {
> .dev_groups = platform_dev_groups,
> .match = platform_match,
> .uevent = platform_uevent,
> + .probe = platform_probe,
> + .remove = platform_remove,
> + .shutdown = platform_shutdown,
> .dma_configure = platform_dma_configure,
> .pm = &platform_dev_pm_ops,
> };

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland