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 <[email protected]>
> ---
>   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

Reply via email to