diff mbox series

usb: dwc3: qcom: Make sure core device is fully initialized before it is used

Message ID 20200616133734.1.I1902d0d48e4f3d4c5b5f1a2008108a4cd3c5ddb5@changeid
State New
Headers show
Series usb: dwc3: qcom: Make sure core device is fully initialized before it is used | expand

Commit Message

Matthias Kaehlcke June 16, 2020, 8:37 p.m. UTC
dwc3_qcom_of_register_core() uses of_platform_populate() to add
the dwc3 core device. The driver core will try to probe the device,
however this might fail (e.g. due to deferred probing) and
of_platform_populate() would still return 0 if the device was
successully added to the platform bus. Verify that the core device
is actually bound to its driver before using it, defer probing of the
dwc3_qcom device if the core device isn't ready (yet).

Fixes: a4333c3a6ba9 ("usb: dwc3: Add Qualcomm DWC3 glue driver").
Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
---
depends on:
  https://lore.kernel.org/patchwork/patch/1251661/ ("driver core:Export
    the symbol device_is_bound")

 drivers/usb/dwc3/dwc3-qcom.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Stephen Boyd June 17, 2020, 7:49 p.m. UTC | #1
Quoting Matthias Kaehlcke (2020-06-16 13:37:37)
> dwc3_qcom_of_register_core() uses of_platform_populate() to add

> the dwc3 core device. The driver core will try to probe the device,

> however this might fail (e.g. due to deferred probing) and

> of_platform_populate() would still return 0 if the device was

> successully added to the platform bus. Verify that the core device

> is actually bound to its driver before using it, defer probing of the

> dwc3_qcom device if the core device isn't ready (yet).

> 

> Fixes: a4333c3a6ba9 ("usb: dwc3: Add Qualcomm DWC3 glue driver").

> Signed-off-by: Matthias Kaehlcke <mka@chromium.org>

> ---

> depends on:

>   https://lore.kernel.org/patchwork/patch/1251661/ ("driver core:Export

>     the symbol device_is_bound")

> 

>  drivers/usb/dwc3/dwc3-qcom.c | 10 ++++++++++

>  1 file changed, 10 insertions(+)

> 

> diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c

> index 1dfd024cd06b..5a9036b050c6 100644

> --- a/drivers/usb/dwc3/dwc3-qcom.c

> +++ b/drivers/usb/dwc3/dwc3-qcom.c

> @@ -537,6 +537,16 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)

>                 return -ENODEV;

>         }

>  

> +       /*

> +        * A successful return from of_platform_populate() only guarantees that

> +        * the core device was added to the platform bus, however it might not

> +        * be bound to its driver (e.g. due to deferred probing). This driver

> +        * requires the core device to be fully initialized, so defer probing

> +        * if it isn't ready (yet).

> +        */

> +       if (!device_is_bound(&qcom->dwc3->dev))

> +               return -EPROBE_DEFER;


Isn't this still broken? i.e. the dwc3 core driver may bind much later
and then device_is_bound() will return an error here and then we'll
return to the caller, dwc3_qcom_probe(), and that will depopulate the
device with of_platform_depopulate(). It seems like we need to run some
sort of wait for driver to be bound function instead of a one-shot check
for the driver being bound.

> +

>         return 0;


Also, what about acpi? That has the same problem but it isn't covered by
the dwc3_qcom_of_register_core() function.
Matthias Kaehlcke June 17, 2020, 9:24 p.m. UTC | #2
Hi Stephen,

On Wed, Jun 17, 2020 at 12:49:13PM -0700, Stephen Boyd wrote:
> Quoting Matthias Kaehlcke (2020-06-16 13:37:37)

> > dwc3_qcom_of_register_core() uses of_platform_populate() to add

> > the dwc3 core device. The driver core will try to probe the device,

> > however this might fail (e.g. due to deferred probing) and

> > of_platform_populate() would still return 0 if the device was

> > successully added to the platform bus. Verify that the core device

> > is actually bound to its driver before using it, defer probing of the

> > dwc3_qcom device if the core device isn't ready (yet).

> > 

> > Fixes: a4333c3a6ba9 ("usb: dwc3: Add Qualcomm DWC3 glue driver").

> > Signed-off-by: Matthias Kaehlcke <mka@chromium.org>

> > ---

> > depends on:

> >   https://lore.kernel.org/patchwork/patch/1251661/ ("driver core:Export

> >     the symbol device_is_bound")

> > 

> >  drivers/usb/dwc3/dwc3-qcom.c | 10 ++++++++++

> >  1 file changed, 10 insertions(+)

> > 

> > diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c

> > index 1dfd024cd06b..5a9036b050c6 100644

> > --- a/drivers/usb/dwc3/dwc3-qcom.c

> > +++ b/drivers/usb/dwc3/dwc3-qcom.c

> > @@ -537,6 +537,16 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev)

> >                 return -ENODEV;

> >         }

> >  

> > +       /*

> > +        * A successful return from of_platform_populate() only guarantees that

> > +        * the core device was added to the platform bus, however it might not

> > +        * be bound to its driver (e.g. due to deferred probing). This driver

> > +        * requires the core device to be fully initialized, so defer probing

> > +        * if it isn't ready (yet).

> > +        */

> > +       if (!device_is_bound(&qcom->dwc3->dev))

> > +               return -EPROBE_DEFER;

> 

> Isn't this still broken? i.e. the dwc3 core driver may bind much later

> and then device_is_bound() will return an error here and then we'll

> return to the caller, dwc3_qcom_probe(), and that will depopulate the

> device with of_platform_depopulate(). It seems like we need to run some

> sort of wait for driver to be bound function instead of a one-shot check

> for the driver being bound.


My understanding is that the probing is done synchronously and either done,
failed or deferred when returning from of_platform_populate(). Ideally we
would be able to differentiate between a failure and deferral, and not defer
probing in case of an error, however I'm not aware of a way to do this with
the current driver framework.

The call flow is:

  of_platform_populate
    of_platform_bus_create
      of_platform_device_create_pdata
        of_device_add
	  device_add
	    bus_probe_device
	      device_initial_probe
	        __device_attach
	          __device_attach_driver
	            driver_probe_device
                      really_probe
                        ->probe()


> Also, what about acpi? That has the same problem but it isn't covered by

> the dwc3_qcom_of_register_core() function.


I wouldn't be surprised if it had the same problem. I'm not familiar with ACPI
though and don't have a device for testing, hence I limited the patch to the
platform device.
kernel test robot June 21, 2020, 5:50 a.m. UTC | #3
Hi Matthias,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on balbi-usb/testing/next]
[cannot apply to agross-msm/qcom/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use  as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Matthias-Kaehlcke/usb-dwc3-qcom-Make-sure-core-device-is-fully-initialized-before-it-is-used/20200617-043856
base:   https://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git testing/next
config: riscv-allmodconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "device_is_bound" [drivers/usb/dwc3/dwc3-qcom.ko] undefined!


---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 1dfd024cd06b..5a9036b050c6 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -537,6 +537,16 @@  static int dwc3_qcom_of_register_core(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	/*
+	 * A successful return from of_platform_populate() only guarantees that
+	 * the core device was added to the platform bus, however it might not
+	 * be bound to its driver (e.g. due to deferred probing). This driver
+	 * requires the core device to be fully initialized, so defer probing
+	 * if it isn't ready (yet).
+	 */
+	if (!device_is_bound(&qcom->dwc3->dev))
+		return -EPROBE_DEFER;
+
 	return 0;
 }