diff mbox series

[v2] ARM: Add sanity check for dev->periphid in amba_probe()

Message ID 20220830065413.638-1-thunder.leizhen@huawei.com (mailing list archive)
State New, archived
Headers show
Series [v2] ARM: Add sanity check for dev->periphid in amba_probe() | expand

Commit Message

Leizhen (ThunderTown) Aug. 30, 2022, 6:54 a.m. UTC
Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
forcibly invokes device_add() even if dev->periphid is not ready. Although
it will be remedied in amba_match(): dev->periphid will be initialized
if everything is in place; Otherwise, return -EPROBE_DEFER to block
__driver_attach() from further execution. But not all drivers have .match
hook, such as pl031, the dev->bus->probe will be called directly in
__driver_attach(). Unfortunately, if dev->periphid is still not
initialized, the following exception will be triggered.

8<--- cut here ---
Unable to handle kernel NULL pointer dereference at virtual address 00000008
[00000008] *pgd=00000000
Internal error: Oops: 5 [#1] SMP ARM
Modules linked in:
CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
Hardware name: ARM-Versatile Express
PC is at pl031_probe+0x8/0x208
LR is at amba_probe+0xf0/0x160
pc : 80698df8  lr : 8050eb54  psr: 80000013
sp : c0825df8  ip : 00000000  fp : 811fda38
r10: 00000000  r9 : 80d72470  r8 : fffffdfb
r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 10c5387d  Table: 6000406a  DAC: 00000051
... ...
 pl031_probe from amba_probe+0xf0/0x160
 amba_probe from really_probe+0x118/0x290
 really_probe from __driver_probe_device+0x84/0xe4
 __driver_probe_device from driver_probe_device+0x30/0xd0
 driver_probe_device from __driver_attach+0x8c/0xfc
 __driver_attach from bus_for_each_dev+0x70/0xb0
 bus_for_each_dev from bus_add_driver+0x168/0x1f4
 bus_add_driver from driver_register+0x7c/0x118
 driver_register from do_one_initcall+0x44/0x1ec
 do_one_initcall from kernel_init_freeable+0x238/0x288
 kernel_init_freeable from kernel_init+0x18/0x12c
 kernel_init from ret_from_fork+0x14/0x2c
... ...
---[ end trace 0000000000000000 ]---

Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
if dev->periphid is not ready in amba_probe().

Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
---
KernelVersion: v6.0-rc3
 drivers/amba/bus.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

v1 --> v2:
1. Update this patch based on:
   https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
2. Move the operations of sanity checking and reading dev->periphid,
   updating uevent into new function amba_prepare_periphid().

Comments

Saravana Kannan Aug. 30, 2022, 7:20 a.m. UTC | #1
On Mon, Aug 29, 2022 at 11:59 PM Zhen Lei <thunder.leizhen@huawei.com> wrote:
>
> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> forcibly invokes device_add() even if dev->periphid is not ready. Although
> it will be remedied in amba_match(): dev->periphid will be initialized
> if everything is in place; Otherwise, return -EPROBE_DEFER to block
> __driver_attach() from further execution. But not all drivers have .match
> hook, such as pl031, the dev->bus->probe will be called directly in
> __driver_attach(). Unfortunately, if dev->periphid is still not
> initialized, the following exception will be triggered.
>
> 8<--- cut here ---
> Unable to handle kernel NULL pointer dereference at virtual address 00000008
> [00000008] *pgd=00000000
> Internal error: Oops: 5 [#1] SMP ARM
> Modules linked in:
> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
> Hardware name: ARM-Versatile Express
> PC is at pl031_probe+0x8/0x208
> LR is at amba_probe+0xf0/0x160
> pc : 80698df8  lr : 8050eb54  psr: 80000013
> sp : c0825df8  ip : 00000000  fp : 811fda38
> r10: 00000000  r9 : 80d72470  r8 : fffffdfb
> r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
> r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
> Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> Control: 10c5387d  Table: 6000406a  DAC: 00000051
> ... ...
>  pl031_probe from amba_probe+0xf0/0x160
>  amba_probe from really_probe+0x118/0x290
>  really_probe from __driver_probe_device+0x84/0xe4
>  __driver_probe_device from driver_probe_device+0x30/0xd0
>  driver_probe_device from __driver_attach+0x8c/0xfc
>  __driver_attach from bus_for_each_dev+0x70/0xb0
>  bus_for_each_dev from bus_add_driver+0x168/0x1f4
>  bus_add_driver from driver_register+0x7c/0x118
>  driver_register from do_one_initcall+0x44/0x1ec
>  do_one_initcall from kernel_init_freeable+0x238/0x288
>  kernel_init_freeable from kernel_init+0x18/0x12c
>  kernel_init from ret_from_fork+0x14/0x2c
> ... ...
> ---[ end trace 0000000000000000 ]---
>
> Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
> if dev->periphid is not ready in amba_probe().
>
> Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
> ---
> KernelVersion: v6.0-rc3
>  drivers/amba/bus.c | 24 +++++++++++++++++++++---
>  1 file changed, 21 insertions(+), 3 deletions(-)
>
> v1 --> v2:
> 1. Update this patch based on:
>    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
> 2. Move the operations of sanity checking and reading dev->periphid,
>    updating uevent into new function amba_prepare_periphid().
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 110a535648d2e1f..8e4c7e190880206 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
>         return ret;
>  }
>
> -static int amba_match(struct device *dev, struct device_driver *drv)
> +static int amba_prepare_periphid(struct device *dev)
>  {
>         struct amba_device *pcdev = to_amba_device(dev);
> -       struct amba_driver *pcdrv = to_amba_driver(drv);
>
>         mutex_lock(&pcdev->periphid_lock);
>         if (!pcdev->periphid) {
> @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
>         }
>         mutex_unlock(&pcdev->periphid_lock);
>
> +       return 0;
> +}
> +
> +static int amba_match(struct device *dev, struct device_driver *drv)
> +{
> +       struct amba_device *pcdev = to_amba_device(dev);
> +       struct amba_driver *pcdrv = to_amba_driver(drv);
> +       int ret;
> +
> +       ret = amba_prepare_periphid(dev);
> +       if (ret)
> +               return ret;
> +
>         /* When driver_override is set, only bind to the matching driver */
>         if (pcdev->driver_override)
>                 return !strcmp(pcdev->driver_override, drv->name);
> @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
>  {
>         struct amba_device *pcdev = to_amba_device(dev);
>         struct amba_driver *pcdrv = to_amba_driver(dev->driver);
> -       const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
> +       const struct amba_id *id;
>         int ret;
>
> +       ret = amba_prepare_periphid(dev);
> +       if (ret)
> +               return ret;
> +
> +       id = amba_lookup(pcdrv->id_table, pcdev);
> +
>         do {
>                 ret = of_amba_device_decode_irq(pcdev);
>                 if (ret)

Let's wait for Isaac to review this. He has been looking at the
locking issue for a bit and there were some tricky cases.

-Saravana
Russell King (Oracle) Aug. 30, 2022, 9:47 a.m. UTC | #2
On Tue, Aug 30, 2022 at 12:20:00AM -0700, Saravana Kannan wrote:
> On Mon, Aug 29, 2022 at 11:59 PM Zhen Lei <thunder.leizhen@huawei.com> wrote:
> >
> > Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> > forcibly invokes device_add() even if dev->periphid is not ready. Although
> > it will be remedied in amba_match(): dev->periphid will be initialized
> > if everything is in place; Otherwise, return -EPROBE_DEFER to block
> > __driver_attach() from further execution. But not all drivers have .match
> > hook, such as pl031, the dev->bus->probe will be called directly in
> > __driver_attach(). Unfortunately, if dev->periphid is still not
> > initialized, the following exception will be triggered.
> >
> > 8<--- cut here ---
> > Unable to handle kernel NULL pointer dereference at virtual address 00000008
> > [00000008] *pgd=00000000
> > Internal error: Oops: 5 [#1] SMP ARM
> > Modules linked in:
> > CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
> > Hardware name: ARM-Versatile Express
> > PC is at pl031_probe+0x8/0x208
> > LR is at amba_probe+0xf0/0x160
> > pc : 80698df8  lr : 8050eb54  psr: 80000013
> > sp : c0825df8  ip : 00000000  fp : 811fda38
> > r10: 00000000  r9 : 80d72470  r8 : fffffdfb
> > r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
> > r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
> > Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> > Control: 10c5387d  Table: 6000406a  DAC: 00000051
> > ... ...
> >  pl031_probe from amba_probe+0xf0/0x160
> >  amba_probe from really_probe+0x118/0x290
> >  really_probe from __driver_probe_device+0x84/0xe4
> >  __driver_probe_device from driver_probe_device+0x30/0xd0
> >  driver_probe_device from __driver_attach+0x8c/0xfc
> >  __driver_attach from bus_for_each_dev+0x70/0xb0
> >  bus_for_each_dev from bus_add_driver+0x168/0x1f4
> >  bus_add_driver from driver_register+0x7c/0x118
> >  driver_register from do_one_initcall+0x44/0x1ec
> >  do_one_initcall from kernel_init_freeable+0x238/0x288
> >  kernel_init_freeable from kernel_init+0x18/0x12c
> >  kernel_init from ret_from_fork+0x14/0x2c
> > ... ...
> > ---[ end trace 0000000000000000 ]---
> >
> > Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
> > if dev->periphid is not ready in amba_probe().
> >
> > Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> > Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
> > ---
> > KernelVersion: v6.0-rc3
> >  drivers/amba/bus.c | 24 +++++++++++++++++++++---
> >  1 file changed, 21 insertions(+), 3 deletions(-)
> >
> > v1 --> v2:
> > 1. Update this patch based on:
> >    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
> > 2. Move the operations of sanity checking and reading dev->periphid,
> >    updating uevent into new function amba_prepare_periphid().
> >
> > diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> > index 110a535648d2e1f..8e4c7e190880206 100644
> > --- a/drivers/amba/bus.c
> > +++ b/drivers/amba/bus.c
> > @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
> >         return ret;
> >  }
> >
> > -static int amba_match(struct device *dev, struct device_driver *drv)
> > +static int amba_prepare_periphid(struct device *dev)
> >  {
> >         struct amba_device *pcdev = to_amba_device(dev);
> > -       struct amba_driver *pcdrv = to_amba_driver(drv);
> >
> >         mutex_lock(&pcdev->periphid_lock);
> >         if (!pcdev->periphid) {
> > @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
> >         }
> >         mutex_unlock(&pcdev->periphid_lock);
> >
> > +       return 0;
> > +}
> > +
> > +static int amba_match(struct device *dev, struct device_driver *drv)
> > +{
> > +       struct amba_device *pcdev = to_amba_device(dev);
> > +       struct amba_driver *pcdrv = to_amba_driver(drv);
> > +       int ret;
> > +
> > +       ret = amba_prepare_periphid(dev);
> > +       if (ret)
> > +               return ret;
> > +
> >         /* When driver_override is set, only bind to the matching driver */
> >         if (pcdev->driver_override)
> >                 return !strcmp(pcdev->driver_override, drv->name);
> > @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
> >  {
> >         struct amba_device *pcdev = to_amba_device(dev);
> >         struct amba_driver *pcdrv = to_amba_driver(dev->driver);
> > -       const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
> > +       const struct amba_id *id;
> >         int ret;
> >
> > +       ret = amba_prepare_periphid(dev);
> > +       if (ret)
> > +               return ret;
> > +
> > +       id = amba_lookup(pcdrv->id_table, pcdev);
> > +
> >         do {
> >                 ret = of_amba_device_decode_irq(pcdev);
> >                 if (ret)
> 
> Let's wait for Isaac to review this. He has been looking at the
> locking issue for a bit and there were some tricky cases.

How can we get to amba_probe() if amba_match() has not returned a
positive match for an ID? Surely if that happens, the driver model
is failed - since a probe function should not be called unless the
driver matches the device.

This patch, and 9229/1 both feel like they're working around some
brokenness elsewhere in the kernel.

The description in 9229/1, specifically "But not all drivers have .match
hook, such as pl031, the dev->bus->probe will be called directly in
__driver_attach()." AMBA drivers do not have a .match hook - the bus
does, which all AMBA drivers must be a member of. If amba_match fails,
there is no way that amba_probe() should ever be called.
Russell King (Oracle) Aug. 30, 2022, 9:48 a.m. UTC | #3
On Tue, Aug 30, 2022 at 10:47:31AM +0100, Russell King (Oracle) wrote:
> How can we get to amba_probe() if amba_match() has not returned a
> positive match for an ID? Surely if that happens, the driver model
> is failed - since a probe function should not be called unless the
> driver matches the device.
> 
> This patch, and 9229/1 both feel like they're working around some
> brokenness elsewhere in the kernel.
> 
> The description in 9229/1, specifically "But not all drivers have .match

Sorry, meant 9238/1.

> hook, such as pl031, the dev->bus->probe will be called directly in
> __driver_attach()." AMBA drivers do not have a .match hook - the bus
> does, which all AMBA drivers must be a member of. If amba_match fails,
> there is no way that amba_probe() should ever be called.
Russell King (Oracle) Aug. 30, 2022, 9:50 a.m. UTC | #4
Please don't send the patch system patches that have not had any chance
of review. The patch system is supposed to be for patches that are to
be applied.

Sending patches that are yet to be reviewed makes extra work for me.

Thanks.

On Tue, Aug 30, 2022 at 02:54:13PM +0800, Zhen Lei wrote:
> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> forcibly invokes device_add() even if dev->periphid is not ready. Although
> it will be remedied in amba_match(): dev->periphid will be initialized
> if everything is in place; Otherwise, return -EPROBE_DEFER to block
> __driver_attach() from further execution. But not all drivers have .match
> hook, such as pl031, the dev->bus->probe will be called directly in
> __driver_attach(). Unfortunately, if dev->periphid is still not
> initialized, the following exception will be triggered.
> 
> 8<--- cut here ---
> Unable to handle kernel NULL pointer dereference at virtual address 00000008
> [00000008] *pgd=00000000
> Internal error: Oops: 5 [#1] SMP ARM
> Modules linked in:
> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
> Hardware name: ARM-Versatile Express
> PC is at pl031_probe+0x8/0x208
> LR is at amba_probe+0xf0/0x160
> pc : 80698df8  lr : 8050eb54  psr: 80000013
> sp : c0825df8  ip : 00000000  fp : 811fda38
> r10: 00000000  r9 : 80d72470  r8 : fffffdfb
> r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
> r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
> Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> Control: 10c5387d  Table: 6000406a  DAC: 00000051
> ... ...
>  pl031_probe from amba_probe+0xf0/0x160
>  amba_probe from really_probe+0x118/0x290
>  really_probe from __driver_probe_device+0x84/0xe4
>  __driver_probe_device from driver_probe_device+0x30/0xd0
>  driver_probe_device from __driver_attach+0x8c/0xfc
>  __driver_attach from bus_for_each_dev+0x70/0xb0
>  bus_for_each_dev from bus_add_driver+0x168/0x1f4
>  bus_add_driver from driver_register+0x7c/0x118
>  driver_register from do_one_initcall+0x44/0x1ec
>  do_one_initcall from kernel_init_freeable+0x238/0x288
>  kernel_init_freeable from kernel_init+0x18/0x12c
>  kernel_init from ret_from_fork+0x14/0x2c
> ... ...
> ---[ end trace 0000000000000000 ]---
> 
> Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
> if dev->periphid is not ready in amba_probe().
> 
> Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
> ---
> KernelVersion: v6.0-rc3
>  drivers/amba/bus.c | 24 +++++++++++++++++++++---
>  1 file changed, 21 insertions(+), 3 deletions(-)
> 
> v1 --> v2:
> 1. Update this patch based on:
>    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
> 2. Move the operations of sanity checking and reading dev->periphid,
>    updating uevent into new function amba_prepare_periphid().
> 
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index 110a535648d2e1f..8e4c7e190880206 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
>  	return ret;
>  }
>  
> -static int amba_match(struct device *dev, struct device_driver *drv)
> +static int amba_prepare_periphid(struct device *dev)
>  {
>  	struct amba_device *pcdev = to_amba_device(dev);
> -	struct amba_driver *pcdrv = to_amba_driver(drv);
>  
>  	mutex_lock(&pcdev->periphid_lock);
>  	if (!pcdev->periphid) {
> @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
>  	}
>  	mutex_unlock(&pcdev->periphid_lock);
>  
> +	return 0;
> +}
> +
> +static int amba_match(struct device *dev, struct device_driver *drv)
> +{
> +	struct amba_device *pcdev = to_amba_device(dev);
> +	struct amba_driver *pcdrv = to_amba_driver(drv);
> +	int ret;
> +
> +	ret = amba_prepare_periphid(dev);
> +	if (ret)
> +		return ret;
> +
>  	/* When driver_override is set, only bind to the matching driver */
>  	if (pcdev->driver_override)
>  		return !strcmp(pcdev->driver_override, drv->name);
> @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
>  {
>  	struct amba_device *pcdev = to_amba_device(dev);
>  	struct amba_driver *pcdrv = to_amba_driver(dev->driver);
> -	const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
> +	const struct amba_id *id;
>  	int ret;
>  
> +	ret = amba_prepare_periphid(dev);
> +	if (ret)
> +		return ret;
> +
> +	id = amba_lookup(pcdrv->id_table, pcdev);
> +
>  	do {
>  		ret = of_amba_device_decode_irq(pcdev);
>  		if (ret)
> -- 
> 2.25.1
> 
>
Leizhen (ThunderTown) Aug. 30, 2022, 10:03 a.m. UTC | #5
On 2022/8/30 17:47, Russell King (Oracle) wrote:
> On Tue, Aug 30, 2022 at 12:20:00AM -0700, Saravana Kannan wrote:
>> On Mon, Aug 29, 2022 at 11:59 PM Zhen Lei <thunder.leizhen@huawei.com> wrote:
>>>
>>> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
>>> forcibly invokes device_add() even if dev->periphid is not ready. Although
>>> it will be remedied in amba_match(): dev->periphid will be initialized
>>> if everything is in place; Otherwise, return -EPROBE_DEFER to block
>>> __driver_attach() from further execution. But not all drivers have .match
>>> hook, such as pl031, the dev->bus->probe will be called directly in
>>> __driver_attach(). Unfortunately, if dev->periphid is still not
>>> initialized, the following exception will be triggered.
>>>
>>> 8<--- cut here ---
>>> Unable to handle kernel NULL pointer dereference at virtual address 00000008
>>> [00000008] *pgd=00000000
>>> Internal error: Oops: 5 [#1] SMP ARM
>>> Modules linked in:
>>> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
>>> Hardware name: ARM-Versatile Express
>>> PC is at pl031_probe+0x8/0x208
>>> LR is at amba_probe+0xf0/0x160
>>> pc : 80698df8  lr : 8050eb54  psr: 80000013
>>> sp : c0825df8  ip : 00000000  fp : 811fda38
>>> r10: 00000000  r9 : 80d72470  r8 : fffffdfb
>>> r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
>>> r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
>>> Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>>> Control: 10c5387d  Table: 6000406a  DAC: 00000051
>>> ... ...
>>>  pl031_probe from amba_probe+0xf0/0x160
>>>  amba_probe from really_probe+0x118/0x290
>>>  really_probe from __driver_probe_device+0x84/0xe4
>>>  __driver_probe_device from driver_probe_device+0x30/0xd0
>>>  driver_probe_device from __driver_attach+0x8c/0xfc
>>>  __driver_attach from bus_for_each_dev+0x70/0xb0
>>>  bus_for_each_dev from bus_add_driver+0x168/0x1f4
>>>  bus_add_driver from driver_register+0x7c/0x118
>>>  driver_register from do_one_initcall+0x44/0x1ec
>>>  do_one_initcall from kernel_init_freeable+0x238/0x288
>>>  kernel_init_freeable from kernel_init+0x18/0x12c
>>>  kernel_init from ret_from_fork+0x14/0x2c
>>> ... ...
>>> ---[ end trace 0000000000000000 ]---
>>>
>>> Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
>>> if dev->periphid is not ready in amba_probe().
>>>
>>> Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
>>> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
>>> ---
>>> KernelVersion: v6.0-rc3
>>>  drivers/amba/bus.c | 24 +++++++++++++++++++++---
>>>  1 file changed, 21 insertions(+), 3 deletions(-)
>>>
>>> v1 --> v2:
>>> 1. Update this patch based on:
>>>    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
>>> 2. Move the operations of sanity checking and reading dev->periphid,
>>>    updating uevent into new function amba_prepare_periphid().
>>>
>>> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
>>> index 110a535648d2e1f..8e4c7e190880206 100644
>>> --- a/drivers/amba/bus.c
>>> +++ b/drivers/amba/bus.c
>>> @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
>>>         return ret;
>>>  }
>>>
>>> -static int amba_match(struct device *dev, struct device_driver *drv)
>>> +static int amba_prepare_periphid(struct device *dev)
>>>  {
>>>         struct amba_device *pcdev = to_amba_device(dev);
>>> -       struct amba_driver *pcdrv = to_amba_driver(drv);
>>>
>>>         mutex_lock(&pcdev->periphid_lock);
>>>         if (!pcdev->periphid) {
>>> @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
>>>         }
>>>         mutex_unlock(&pcdev->periphid_lock);
>>>
>>> +       return 0;
>>> +}
>>> +
>>> +static int amba_match(struct device *dev, struct device_driver *drv)
>>> +{
>>> +       struct amba_device *pcdev = to_amba_device(dev);
>>> +       struct amba_driver *pcdrv = to_amba_driver(drv);
>>> +       int ret;
>>> +
>>> +       ret = amba_prepare_periphid(dev);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>>         /* When driver_override is set, only bind to the matching driver */
>>>         if (pcdev->driver_override)
>>>                 return !strcmp(pcdev->driver_override, drv->name);
>>> @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
>>>  {
>>>         struct amba_device *pcdev = to_amba_device(dev);
>>>         struct amba_driver *pcdrv = to_amba_driver(dev->driver);
>>> -       const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
>>> +       const struct amba_id *id;
>>>         int ret;
>>>
>>> +       ret = amba_prepare_periphid(dev);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       id = amba_lookup(pcdrv->id_table, pcdev);
>>> +
>>>         do {
>>>                 ret = of_amba_device_decode_irq(pcdev);
>>>                 if (ret)
>>
>> Let's wait for Isaac to review this. He has been looking at the
>> locking issue for a bit and there were some tricky cases.
> 
> How can we get to amba_probe() if amba_match() has not returned a
> positive match for an ID? Surely if that happens, the driver model

Always return true.

__driver_attach
    driver_match_device

static inline int driver_match_device(struct device_driver *drv,
                                      struct device *dev)
{
        return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}

> is failed - since a probe function should not be called unless the
> driver matches the device.
> 
> This patch, and 9229/1 both feel like they're working around some
> brokenness elsewhere in the kernel.
> 
> The description in 9229/1, specifically "But not all drivers have .match
> hook, such as pl031, the dev->bus->probe will be called directly in
> __driver_attach()." AMBA drivers do not have a .match hook - the bus
> does, which all AMBA drivers must be a member of. If amba_match fails,
> there is no way that amba_probe() should ever be called.
>
Leizhen (ThunderTown) Aug. 30, 2022, 10:07 a.m. UTC | #6
On 2022/8/30 17:50, Russell King (Oracle) wrote:
> Please don't send the patch system patches that have not had any chance
> of review. The patch system is supposed to be for patches that are to
> be applied.

Okay, I get it now.

> 
> Sending patches that are yet to be reviewed makes extra work for me.

I'm so sorry.

> 
> Thanks.
> 
> On Tue, Aug 30, 2022 at 02:54:13PM +0800, Zhen Lei wrote:
>> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
>> forcibly invokes device_add() even if dev->periphid is not ready. Although
>> it will be remedied in amba_match(): dev->periphid will be initialized
>> if everything is in place; Otherwise, return -EPROBE_DEFER to block
>> __driver_attach() from further execution. But not all drivers have .match
>> hook, such as pl031, the dev->bus->probe will be called directly in
>> __driver_attach(). Unfortunately, if dev->periphid is still not
>> initialized, the following exception will be triggered.
>>
>> 8<--- cut here ---
>> Unable to handle kernel NULL pointer dereference at virtual address 00000008
>> [00000008] *pgd=00000000
>> Internal error: Oops: 5 [#1] SMP ARM
>> Modules linked in:
>> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
>> Hardware name: ARM-Versatile Express
>> PC is at pl031_probe+0x8/0x208
>> LR is at amba_probe+0xf0/0x160
>> pc : 80698df8  lr : 8050eb54  psr: 80000013
>> sp : c0825df8  ip : 00000000  fp : 811fda38
>> r10: 00000000  r9 : 80d72470  r8 : fffffdfb
>> r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
>> r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
>> Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>> Control: 10c5387d  Table: 6000406a  DAC: 00000051
>> ... ...
>>  pl031_probe from amba_probe+0xf0/0x160
>>  amba_probe from really_probe+0x118/0x290
>>  really_probe from __driver_probe_device+0x84/0xe4
>>  __driver_probe_device from driver_probe_device+0x30/0xd0
>>  driver_probe_device from __driver_attach+0x8c/0xfc
>>  __driver_attach from bus_for_each_dev+0x70/0xb0
>>  bus_for_each_dev from bus_add_driver+0x168/0x1f4
>>  bus_add_driver from driver_register+0x7c/0x118
>>  driver_register from do_one_initcall+0x44/0x1ec
>>  do_one_initcall from kernel_init_freeable+0x238/0x288
>>  kernel_init_freeable from kernel_init+0x18/0x12c
>>  kernel_init from ret_from_fork+0x14/0x2c
>> ... ...
>> ---[ end trace 0000000000000000 ]---
>>
>> Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
>> if dev->periphid is not ready in amba_probe().
>>
>> Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
>> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
>> ---
>> KernelVersion: v6.0-rc3
>>  drivers/amba/bus.c | 24 +++++++++++++++++++++---
>>  1 file changed, 21 insertions(+), 3 deletions(-)
>>
>> v1 --> v2:
>> 1. Update this patch based on:
>>    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
>> 2. Move the operations of sanity checking and reading dev->periphid,
>>    updating uevent into new function amba_prepare_periphid().
>>
>> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
>> index 110a535648d2e1f..8e4c7e190880206 100644
>> --- a/drivers/amba/bus.c
>> +++ b/drivers/amba/bus.c
>> @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
>>  	return ret;
>>  }
>>  
>> -static int amba_match(struct device *dev, struct device_driver *drv)
>> +static int amba_prepare_periphid(struct device *dev)
>>  {
>>  	struct amba_device *pcdev = to_amba_device(dev);
>> -	struct amba_driver *pcdrv = to_amba_driver(drv);
>>  
>>  	mutex_lock(&pcdev->periphid_lock);
>>  	if (!pcdev->periphid) {
>> @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
>>  	}
>>  	mutex_unlock(&pcdev->periphid_lock);
>>  
>> +	return 0;
>> +}
>> +
>> +static int amba_match(struct device *dev, struct device_driver *drv)
>> +{
>> +	struct amba_device *pcdev = to_amba_device(dev);
>> +	struct amba_driver *pcdrv = to_amba_driver(drv);
>> +	int ret;
>> +
>> +	ret = amba_prepare_periphid(dev);
>> +	if (ret)
>> +		return ret;
>> +
>>  	/* When driver_override is set, only bind to the matching driver */
>>  	if (pcdev->driver_override)
>>  		return !strcmp(pcdev->driver_override, drv->name);
>> @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
>>  {
>>  	struct amba_device *pcdev = to_amba_device(dev);
>>  	struct amba_driver *pcdrv = to_amba_driver(dev->driver);
>> -	const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
>> +	const struct amba_id *id;
>>  	int ret;
>>  
>> +	ret = amba_prepare_periphid(dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	id = amba_lookup(pcdrv->id_table, pcdev);
>> +
>>  	do {
>>  		ret = of_amba_device_decode_irq(pcdev);
>>  		if (ret)
>> -- 
>> 2.25.1
>>
>>
>
Russell King (Oracle) Aug. 30, 2022, 10:07 a.m. UTC | #7
On Tue, Aug 30, 2022 at 06:03:31PM +0800, Leizhen (ThunderTown) wrote:
> 
> 
> On 2022/8/30 17:47, Russell King (Oracle) wrote:
> > On Tue, Aug 30, 2022 at 12:20:00AM -0700, Saravana Kannan wrote:
> >> On Mon, Aug 29, 2022 at 11:59 PM Zhen Lei <thunder.leizhen@huawei.com> wrote:
> >>>
> >>> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> >>> forcibly invokes device_add() even if dev->periphid is not ready. Although
> >>> it will be remedied in amba_match(): dev->periphid will be initialized
> >>> if everything is in place; Otherwise, return -EPROBE_DEFER to block
> >>> __driver_attach() from further execution. But not all drivers have .match
> >>> hook, such as pl031, the dev->bus->probe will be called directly in
> >>> __driver_attach(). Unfortunately, if dev->periphid is still not
> >>> initialized, the following exception will be triggered.
> >>>
> >>> 8<--- cut here ---
> >>> Unable to handle kernel NULL pointer dereference at virtual address 00000008
> >>> [00000008] *pgd=00000000
> >>> Internal error: Oops: 5 [#1] SMP ARM
> >>> Modules linked in:
> >>> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
> >>> Hardware name: ARM-Versatile Express
> >>> PC is at pl031_probe+0x8/0x208
> >>> LR is at amba_probe+0xf0/0x160
> >>> pc : 80698df8  lr : 8050eb54  psr: 80000013
> >>> sp : c0825df8  ip : 00000000  fp : 811fda38
> >>> r10: 00000000  r9 : 80d72470  r8 : fffffdfb
> >>> r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
> >>> r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
> >>> Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
> >>> Control: 10c5387d  Table: 6000406a  DAC: 00000051
> >>> ... ...
> >>>  pl031_probe from amba_probe+0xf0/0x160
> >>>  amba_probe from really_probe+0x118/0x290
> >>>  really_probe from __driver_probe_device+0x84/0xe4
> >>>  __driver_probe_device from driver_probe_device+0x30/0xd0
> >>>  driver_probe_device from __driver_attach+0x8c/0xfc
> >>>  __driver_attach from bus_for_each_dev+0x70/0xb0
> >>>  bus_for_each_dev from bus_add_driver+0x168/0x1f4
> >>>  bus_add_driver from driver_register+0x7c/0x118
> >>>  driver_register from do_one_initcall+0x44/0x1ec
> >>>  do_one_initcall from kernel_init_freeable+0x238/0x288
> >>>  kernel_init_freeable from kernel_init+0x18/0x12c
> >>>  kernel_init from ret_from_fork+0x14/0x2c
> >>> ... ...
> >>> ---[ end trace 0000000000000000 ]---
> >>>
> >>> Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
> >>> if dev->periphid is not ready in amba_probe().
> >>>
> >>> Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> >>> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
> >>> ---
> >>> KernelVersion: v6.0-rc3
> >>>  drivers/amba/bus.c | 24 +++++++++++++++++++++---
> >>>  1 file changed, 21 insertions(+), 3 deletions(-)
> >>>
> >>> v1 --> v2:
> >>> 1. Update this patch based on:
> >>>    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
> >>> 2. Move the operations of sanity checking and reading dev->periphid,
> >>>    updating uevent into new function amba_prepare_periphid().
> >>>
> >>> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> >>> index 110a535648d2e1f..8e4c7e190880206 100644
> >>> --- a/drivers/amba/bus.c
> >>> +++ b/drivers/amba/bus.c
> >>> @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
> >>>         return ret;
> >>>  }
> >>>
> >>> -static int amba_match(struct device *dev, struct device_driver *drv)
> >>> +static int amba_prepare_periphid(struct device *dev)
> >>>  {
> >>>         struct amba_device *pcdev = to_amba_device(dev);
> >>> -       struct amba_driver *pcdrv = to_amba_driver(drv);
> >>>
> >>>         mutex_lock(&pcdev->periphid_lock);
> >>>         if (!pcdev->periphid) {
> >>> @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
> >>>         }
> >>>         mutex_unlock(&pcdev->periphid_lock);
> >>>
> >>> +       return 0;
> >>> +}
> >>> +
> >>> +static int amba_match(struct device *dev, struct device_driver *drv)
> >>> +{
> >>> +       struct amba_device *pcdev = to_amba_device(dev);
> >>> +       struct amba_driver *pcdrv = to_amba_driver(drv);
> >>> +       int ret;
> >>> +
> >>> +       ret = amba_prepare_periphid(dev);
> >>> +       if (ret)
> >>> +               return ret;
> >>> +
> >>>         /* When driver_override is set, only bind to the matching driver */
> >>>         if (pcdev->driver_override)
> >>>                 return !strcmp(pcdev->driver_override, drv->name);
> >>> @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
> >>>  {
> >>>         struct amba_device *pcdev = to_amba_device(dev);
> >>>         struct amba_driver *pcdrv = to_amba_driver(dev->driver);
> >>> -       const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
> >>> +       const struct amba_id *id;
> >>>         int ret;
> >>>
> >>> +       ret = amba_prepare_periphid(dev);
> >>> +       if (ret)
> >>> +               return ret;
> >>> +
> >>> +       id = amba_lookup(pcdrv->id_table, pcdev);
> >>> +
> >>>         do {
> >>>                 ret = of_amba_device_decode_irq(pcdev);
> >>>                 if (ret)
> >>
> >> Let's wait for Isaac to review this. He has been looking at the
> >> locking issue for a bit and there were some tricky cases.
> > 
> > How can we get to amba_probe() if amba_match() has not returned a
> > positive match for an ID? Surely if that happens, the driver model
> 
> Always return true.
> 
> __driver_attach
>     driver_match_device
> 
> static inline int driver_match_device(struct device_driver *drv,
>                                       struct device *dev)
> {
>         return drv->bus->match ? drv->bus->match(dev, drv) : 1;
> }

You seem to be misunderstanding something rather fundamental here.

For an amba driver, drv->bus will always be pointing at amba_bustype.
That always has a "match" operation. Therefore, the default of '1'
above will *never* be used for an AMBA driver.

If drv->bus does not point at amba_bustype, then amba_probe() will
not be called for "drv".

Therefore, amba_match() must always be called before amba_probe().
Russell King (Oracle) Aug. 30, 2022, 10:28 a.m. UTC | #8
On Tue, Aug 30, 2022 at 02:54:13PM +0800, Zhen Lei wrote:
> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
> forcibly invokes device_add() even if dev->periphid is not ready. Although
> it will be remedied in amba_match(): dev->periphid will be initialized
> if everything is in place; Otherwise, return -EPROBE_DEFER to block
> __driver_attach() from further execution. But not all drivers have .match
> hook, such as pl031, the dev->bus->probe will be called directly in
> __driver_attach(). Unfortunately, if dev->periphid is still not
> initialized, the following exception will be triggered.

Please check whether 9229/1 fixes this issue for you.

http://www.armlinux.org.uk/developer/patches/download.php?id=9229/1

Thanks.
Leizhen (ThunderTown) Aug. 30, 2022, 10:31 a.m. UTC | #9
On 2022/8/30 18:07, Russell King (Oracle) wrote:
> On Tue, Aug 30, 2022 at 06:03:31PM +0800, Leizhen (ThunderTown) wrote:
>>
>>
>> On 2022/8/30 17:47, Russell King (Oracle) wrote:
>>> On Tue, Aug 30, 2022 at 12:20:00AM -0700, Saravana Kannan wrote:
>>>> On Mon, Aug 29, 2022 at 11:59 PM Zhen Lei <thunder.leizhen@huawei.com> wrote:
>>>>>
>>>>> Commit f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
>>>>> forcibly invokes device_add() even if dev->periphid is not ready. Although
>>>>> it will be remedied in amba_match(): dev->periphid will be initialized
>>>>> if everything is in place; Otherwise, return -EPROBE_DEFER to block
>>>>> __driver_attach() from further execution. But not all drivers have .match
>>>>> hook, such as pl031, the dev->bus->probe will be called directly in
>>>>> __driver_attach(). Unfortunately, if dev->periphid is still not
>>>>> initialized, the following exception will be triggered.
>>>>>
>>>>> 8<--- cut here ---
>>>>> Unable to handle kernel NULL pointer dereference at virtual address 00000008
>>>>> [00000008] *pgd=00000000
>>>>> Internal error: Oops: 5 [#1] SMP ARM
>>>>> Modules linked in:
>>>>> CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.0.0-rc2+ #7
>>>>> Hardware name: ARM-Versatile Express
>>>>> PC is at pl031_probe+0x8/0x208
>>>>> LR is at amba_probe+0xf0/0x160
>>>>> pc : 80698df8  lr : 8050eb54  psr: 80000013
>>>>> sp : c0825df8  ip : 00000000  fp : 811fda38
>>>>> r10: 00000000  r9 : 80d72470  r8 : fffffdfb
>>>>> r7 : 811fd800  r6 : be7eb330  r5 : 00000000  r4 : 811fd900
>>>>> r3 : 80698df0  r2 : 37000000  r1 : 00000000  r0 : 811fd800
>>>>> Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
>>>>> Control: 10c5387d  Table: 6000406a  DAC: 00000051
>>>>> ... ...
>>>>>  pl031_probe from amba_probe+0xf0/0x160
>>>>>  amba_probe from really_probe+0x118/0x290
>>>>>  really_probe from __driver_probe_device+0x84/0xe4
>>>>>  __driver_probe_device from driver_probe_device+0x30/0xd0
>>>>>  driver_probe_device from __driver_attach+0x8c/0xfc
>>>>>  __driver_attach from bus_for_each_dev+0x70/0xb0
>>>>>  bus_for_each_dev from bus_add_driver+0x168/0x1f4
>>>>>  bus_add_driver from driver_register+0x7c/0x118
>>>>>  driver_register from do_one_initcall+0x44/0x1ec
>>>>>  do_one_initcall from kernel_init_freeable+0x238/0x288
>>>>>  kernel_init_freeable from kernel_init+0x18/0x12c
>>>>>  kernel_init from ret_from_fork+0x14/0x2c
>>>>> ... ...
>>>>> ---[ end trace 0000000000000000 ]---
>>>>>
>>>>> Therefore, take the same action as in amba_match(): return -EPROBE_DEFER
>>>>> if dev->periphid is not ready in amba_probe().
>>>>>
>>>>> Fixes: f2d3b9a46e0e ("ARM: 9220/1: amba: Remove deferred device addition")
>>>>> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
>>>>> ---
>>>>> KernelVersion: v6.0-rc3
>>>>>  drivers/amba/bus.c | 24 +++++++++++++++++++++---
>>>>>  1 file changed, 21 insertions(+), 3 deletions(-)
>>>>>
>>>>> v1 --> v2:
>>>>> 1. Update this patch based on:
>>>>>    https://lore.kernel.org/lkml/20220818172852.3548-1-isaacmanjarres@google.com/
>>>>> 2. Move the operations of sanity checking and reading dev->periphid,
>>>>>    updating uevent into new function amba_prepare_periphid().
>>>>>
>>>>> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
>>>>> index 110a535648d2e1f..8e4c7e190880206 100644
>>>>> --- a/drivers/amba/bus.c
>>>>> +++ b/drivers/amba/bus.c
>>>>> @@ -204,10 +204,9 @@ static int amba_read_periphid(struct amba_device *dev)
>>>>>         return ret;
>>>>>  }
>>>>>
>>>>> -static int amba_match(struct device *dev, struct device_driver *drv)
>>>>> +static int amba_prepare_periphid(struct device *dev)
>>>>>  {
>>>>>         struct amba_device *pcdev = to_amba_device(dev);
>>>>> -       struct amba_driver *pcdrv = to_amba_driver(drv);
>>>>>
>>>>>         mutex_lock(&pcdev->periphid_lock);
>>>>>         if (!pcdev->periphid) {
>>>>> @@ -228,6 +227,19 @@ static int amba_match(struct device *dev, struct device_driver *drv)
>>>>>         }
>>>>>         mutex_unlock(&pcdev->periphid_lock);
>>>>>
>>>>> +       return 0;
>>>>> +}
>>>>> +
>>>>> +static int amba_match(struct device *dev, struct device_driver *drv)
>>>>> +{
>>>>> +       struct amba_device *pcdev = to_amba_device(dev);
>>>>> +       struct amba_driver *pcdrv = to_amba_driver(drv);
>>>>> +       int ret;
>>>>> +
>>>>> +       ret = amba_prepare_periphid(dev);
>>>>> +       if (ret)
>>>>> +               return ret;
>>>>> +
>>>>>         /* When driver_override is set, only bind to the matching driver */
>>>>>         if (pcdev->driver_override)
>>>>>                 return !strcmp(pcdev->driver_override, drv->name);
>>>>> @@ -278,9 +290,15 @@ static int amba_probe(struct device *dev)
>>>>>  {
>>>>>         struct amba_device *pcdev = to_amba_device(dev);
>>>>>         struct amba_driver *pcdrv = to_amba_driver(dev->driver);
>>>>> -       const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
>>>>> +       const struct amba_id *id;
>>>>>         int ret;
>>>>>
>>>>> +       ret = amba_prepare_periphid(dev);
>>>>> +       if (ret)
>>>>> +               return ret;
>>>>> +
>>>>> +       id = amba_lookup(pcdrv->id_table, pcdev);
>>>>> +
>>>>>         do {
>>>>>                 ret = of_amba_device_decode_irq(pcdev);
>>>>>                 if (ret)
>>>>
>>>> Let's wait for Isaac to review this. He has been looking at the
>>>> locking issue for a bit and there were some tricky cases.
>>>
>>> How can we get to amba_probe() if amba_match() has not returned a
>>> positive match for an ID? Surely if that happens, the driver model
>>
>> Always return true.
>>
>> __driver_attach
>>     driver_match_device
>>
>> static inline int driver_match_device(struct device_driver *drv,
>>                                       struct device *dev)
>> {
>>         return drv->bus->match ? drv->bus->match(dev, drv) : 1;
>> }
> 
> You seem to be misunderstanding something rather fundamental here.
> 
> For an amba driver, drv->bus will always be pointing at amba_bustype.
> That always has a "match" operation. Therefore, the default of '1'
> above will *never* be used for an AMBA driver.
> 
> If drv->bus does not point at amba_bustype, then amba_probe() will
> not be called for "drv".
> 
> Therefore, amba_match() must always be called before amba_probe().

Oh, I was careless. I think it's drv->match. But the processing flow
will continue to go to "dev->bus->probe".

__driver_attach():
        ret = driver_match_device(drv, dev);
        if (ret == 0) {
                /* no match */
                return 0;
        } else if (ret == -EPROBE_DEFER) {               <------no return in this branch
                dev_dbg(dev, "Device match requests probe deferral\n");
                dev->can_match = true;
                driver_deferred_probe_add(dev);
        } else if (ret < 0) {
                dev_dbg(dev, "Bus failed to match device: %d\n", ret);
                return ret;
        } /* ret > 0 means positive match */

        ... ...
        driver_probe_device(drv, dev);
             ......
                  dev->bus->probe


>
Russell King (Oracle) Aug. 30, 2022, 10:36 a.m. UTC | #10
On Tue, Aug 30, 2022 at 06:31:14PM +0800, Leizhen (ThunderTown) wrote:
> On 2022/8/30 18:07, Russell King (Oracle) wrote:
> > For an amba driver, drv->bus will always be pointing at amba_bustype.
> > That always has a "match" operation. Therefore, the default of '1'
> > above will *never* be used for an AMBA driver.
> > 
> > If drv->bus does not point at amba_bustype, then amba_probe() will
> > not be called for "drv".
> > 
> > Therefore, amba_match() must always be called before amba_probe().
> 
> Oh, I was careless. I think it's drv->match. But the processing flow
> will continue to go to "dev->bus->probe".
> 
> __driver_attach():
>         ret = driver_match_device(drv, dev);
>         if (ret == 0) {
>                 /* no match */
>                 return 0;
>         } else if (ret == -EPROBE_DEFER) {               <------no return in this branch
>                 dev_dbg(dev, "Device match requests probe deferral\n");
>                 dev->can_match = true;
>                 driver_deferred_probe_add(dev);
>         } else if (ret < 0) {
>                 dev_dbg(dev, "Bus failed to match device: %d\n", ret);
>                 return ret;
>         } /* ret > 0 means positive match */
> 
>         ... ...
>         driver_probe_device(drv, dev);
>              ......
>                   dev->bus->probe

And that makes no sense, is an already known issue, and there is a patch
to fix it:

https://lore.kernel.org/all/20220817184026.3468620-1-isaacmanjarres@google.com/
Linus Walleij Aug. 30, 2022, 11:19 a.m. UTC | #11
On Tue, Aug 30, 2022 at 12:37 PM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:

> >         ... ...
> >         driver_probe_device(drv, dev);
> >              ......
> >                   dev->bus->probe
>
> And that makes no sense, is an already known issue, and there is a patch
> to fix it:
>
> https://lore.kernel.org/all/20220817184026.3468620-1-isaacmanjarres@google.com/

This patch to the driver core fixes my QEMU issue as well, I'll try
to reply in-thread. Thanks for pointing this out Russell!

Yours,
Linus Walleij
Leizhen (ThunderTown) Aug. 30, 2022, 11:49 a.m. UTC | #12
On 2022/8/30 19:19, Linus Walleij wrote:
> On Tue, Aug 30, 2022 at 12:37 PM Russell King (Oracle)
> <linux@armlinux.org.uk> wrote:
> 
>>>         ... ...
>>>         driver_probe_device(drv, dev);
>>>              ......
>>>                   dev->bus->probe
>>
>> And that makes no sense, is an already known issue, and there is a patch
>> to fix it:
>>
>> https://lore.kernel.org/all/20220817184026.3468620-1-isaacmanjarres@google.com/
> 
> This patch to the driver core fixes my QEMU issue as well, I'll try
> to reply in-thread. Thanks for pointing this out Russell!

OK, so that my patch can be dropped.

> 
> Yours,
> Linus Walleij
> .
>
Leizhen (ThunderTown) Aug. 30, 2022, 12:11 p.m. UTC | #13
On 2022/8/30 18:07, Leizhen (ThunderTown) wrote:
> 
> On 2022/8/30 17:50, Russell King (Oracle) wrote:
>> Please don't send the patch system patches that have not had any chance
>> of review. The patch system is supposed to be for patches that are to
>> be applied.
> Okay, I get it now.
> 
>> Sending patches that are yet to be reviewed makes extra work for me.
> I'm so sorry.
> 
Hi, Russell:
  Do you have time to look at these two patches?
  https://lkml.org/lkml/2022/8/3/140
  https://lkml.org/lkml/2022/8/11/1266
Saravana Kannan Aug. 30, 2022, 5:34 p.m. UTC | #14
On Tue, Aug 30, 2022 at 3:36 AM Russell King (Oracle)
<linux@armlinux.org.uk> wrote:
>
> On Tue, Aug 30, 2022 at 06:31:14PM +0800, Leizhen (ThunderTown) wrote:
> > On 2022/8/30 18:07, Russell King (Oracle) wrote:
> > > For an amba driver, drv->bus will always be pointing at amba_bustype.
> > > That always has a "match" operation. Therefore, the default of '1'
> > > above will *never* be used for an AMBA driver.
> > >
> > > If drv->bus does not point at amba_bustype, then amba_probe() will
> > > not be called for "drv".
> > >
> > > Therefore, amba_match() must always be called before amba_probe().
> >
> > Oh, I was careless. I think it's drv->match. But the processing flow
> > will continue to go to "dev->bus->probe".
> >
> > __driver_attach():
> >         ret = driver_match_device(drv, dev);
> >         if (ret == 0) {
> >                 /* no match */
> >                 return 0;
> >         } else if (ret == -EPROBE_DEFER) {               <------no return in this branch
> >                 dev_dbg(dev, "Device match requests probe deferral\n");
> >                 dev->can_match = true;
> >                 driver_deferred_probe_add(dev);
> >         } else if (ret < 0) {
> >                 dev_dbg(dev, "Bus failed to match device: %d\n", ret);
> >                 return ret;
> >         } /* ret > 0 means positive match */
> >
> >         ... ...
> >         driver_probe_device(drv, dev);
> >              ......
> >                   dev->bus->probe
>
> And that makes no sense, is an already known issue, and there is a patch
> to fix it:
>
> https://lore.kernel.org/all/20220817184026.3468620-1-isaacmanjarres@google.com/

Russell,

Thanks for discussing this further and pointing out the other fix. I
assumed Leizhen was talking about an instance of
device_driver_attach() which allows probe to be called without match.
Thankfully that function is used only by some specific
frameworks/buses types. I did a cursory check and I don't see any
intersection with we amba.

-Saravana
P.S: I hate that function exists, as it just throws a wrench in the
whole driver core design and adds corner cases to a lot of generic
driver core design.
Saravana Kannan Aug. 30, 2022, 11:48 p.m. UTC | #15
On Tue, Aug 30, 2022 at 10:34 AM Saravana Kannan <saravanak@google.com> wrote:
>
> On Tue, Aug 30, 2022 at 3:36 AM Russell King (Oracle)
> <linux@armlinux.org.uk> wrote:
> >
> > On Tue, Aug 30, 2022 at 06:31:14PM +0800, Leizhen (ThunderTown) wrote:
> > > On 2022/8/30 18:07, Russell King (Oracle) wrote:
> > > > For an amba driver, drv->bus will always be pointing at amba_bustype.
> > > > That always has a "match" operation. Therefore, the default of '1'
> > > > above will *never* be used for an AMBA driver.
> > > >
> > > > If drv->bus does not point at amba_bustype, then amba_probe() will
> > > > not be called for "drv".
> > > >
> > > > Therefore, amba_match() must always be called before amba_probe().
> > >
> > > Oh, I was careless. I think it's drv->match. But the processing flow
> > > will continue to go to "dev->bus->probe".
> > >
> > > __driver_attach():
> > >         ret = driver_match_device(drv, dev);
> > >         if (ret == 0) {
> > >                 /* no match */
> > >                 return 0;
> > >         } else if (ret == -EPROBE_DEFER) {               <------no return in this branch
> > >                 dev_dbg(dev, "Device match requests probe deferral\n");
> > >                 dev->can_match = true;
> > >                 driver_deferred_probe_add(dev);
> > >         } else if (ret < 0) {
> > >                 dev_dbg(dev, "Bus failed to match device: %d\n", ret);
> > >                 return ret;
> > >         } /* ret > 0 means positive match */
> > >
> > >         ... ...
> > >         driver_probe_device(drv, dev);
> > >              ......
> > >                   dev->bus->probe
> >
> > And that makes no sense, is an already known issue, and there is a patch
> > to fix it:
> >
> > https://lore.kernel.org/all/20220817184026.3468620-1-isaacmanjarres@google.com/
>
> Russell,
>
> Thanks for discussing this further and pointing out the other fix. I
> assumed Leizhen was talking about an instance of
> device_driver_attach() which allows probe to be called without match.
> Thankfully that function is used only by some specific
> frameworks/buses types. I did a cursory check and I don't see any
> intersection with we amba.
>
> -Saravana
> P.S: I hate that function exists, as it just throws a wrench in the
> whole driver core design and adds corner cases to a lot of generic
> driver core design.

Oops, meant to say device_bind_driver().

So through out my email:
s/device_driver_attach/device_bind_driver/

-Saravana
diff mbox series

Patch

diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 110a535648d2e1f..8e4c7e190880206 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -204,10 +204,9 @@  static int amba_read_periphid(struct amba_device *dev)
 	return ret;
 }
 
-static int amba_match(struct device *dev, struct device_driver *drv)
+static int amba_prepare_periphid(struct device *dev)
 {
 	struct amba_device *pcdev = to_amba_device(dev);
-	struct amba_driver *pcdrv = to_amba_driver(drv);
 
 	mutex_lock(&pcdev->periphid_lock);
 	if (!pcdev->periphid) {
@@ -228,6 +227,19 @@  static int amba_match(struct device *dev, struct device_driver *drv)
 	}
 	mutex_unlock(&pcdev->periphid_lock);
 
+	return 0;
+}
+
+static int amba_match(struct device *dev, struct device_driver *drv)
+{
+	struct amba_device *pcdev = to_amba_device(dev);
+	struct amba_driver *pcdrv = to_amba_driver(drv);
+	int ret;
+
+	ret = amba_prepare_periphid(dev);
+	if (ret)
+		return ret;
+
 	/* When driver_override is set, only bind to the matching driver */
 	if (pcdev->driver_override)
 		return !strcmp(pcdev->driver_override, drv->name);
@@ -278,9 +290,15 @@  static int amba_probe(struct device *dev)
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 	struct amba_driver *pcdrv = to_amba_driver(dev->driver);
-	const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
+	const struct amba_id *id;
 	int ret;
 
+	ret = amba_prepare_periphid(dev);
+	if (ret)
+		return ret;
+
+	id = amba_lookup(pcdrv->id_table, pcdev);
+
 	do {
 		ret = of_amba_device_decode_irq(pcdev);
 		if (ret)