Hi Hans,

On 2017-07-18 17:06:15 +0200, Hans Verkuil wrote:
> On 18/07/17 16:47, Niklas Söderlund wrote:
> >>>  void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
> >>>  {
> >>> - struct v4l2_subdev *sd, *tmp;
> >>> + struct v4l2_subdev *sd, *tmp, **subdev;
> >>>   unsigned int notif_n_subdev = notifier->num_subdevs;
> >>>   unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS);
> >>>   struct device **dev;
> >>> @@ -217,6 +293,12 @@ void v4l2_async_notifier_unregister(struct 
> >>> v4l2_async_notifier *notifier)
> >>>                   "Failed to allocate device cache!\n");
> >>>   }
> >>>  
> >>> + subdev = kvmalloc_array(n_subdev, sizeof(*subdev), GFP_KERNEL);
> >>> + if (!dev) {
> >>> +         dev_err(notifier->v4l2_dev->dev,
> >>> +                 "Failed to allocate subdevice cache!\n");
> >>> + }
> >>> +
> >>
> >> How about making a little struct:
> >>
> >>    struct whatever {
> >>            struct device *dev;
> >>            struct v4l2_subdev *sd;
> >>    };
> >>
> >> and allocate an array of that. Only need to call kvmalloc_array once.
> > 
> > Neat idea, will do so for next version.
> > 
> >>
> >> Some comments after the dev_err of why you ignore the failed memory 
> >> allocation
> >> and what the consequences of that are would be helpful. It is unexpected 
> >> code,
> >> and that needs documentation.
> > 
> > I agree that it's unexpected and I don't know the reason for it, I was 
> > just mimic the existing behavior. If you are OK with it I be more then 
> > happy to add patch to this series returning -ENOMEM if the allocation 
> > failed as Geert pointed out if this allocation fails I think we are in a 
> > lot of trouble anyhow...
> > 
> > Let me know what you think, but I don't think I can add a comment 
> > explaining why the function don't simply abort on failure since I don't 
> > understand it myself.
> 
> So you don't understand the device_release_driver/device_attach reprobing bit 
> either?
> 
> I did some digging and found this thread:
> 
> http://lkml.iu.edu/hypermail/linux/kernel/1210.2/00713.html
> 
> It explains the reason for this.

Nice, thanks for digging this out.

> 
> I'm pretty sure Greg K-H never saw this code :-)
> 
> Looking in drivers/base/bus.c I see this function: device_reprobe().
> 
> I think we need to use that instead.

I have now looked at device_reprobe() and unfortunately it can't be used 
in v4l2_async_notifier_unregister(). This is because some v4l2 drivers 
call v4l2_async_notifier_unregister() in there remove functions leading 
to call chains similar to this:

SyS_delete_module()
  rcar_vin_driver_exit()
    platform_driver_unregister()
      driver_unregister()
        bus_remove_driver()
          driver_detach()
            device_lock(dev->parent); <- Here the lock is taken
            device_release_driver_internal()
              platform_drv_remove()
                rcar_vin_remove()
                  v4l2_async_notifier_unregister()
                    device_reprobe()
                      device_lock(dev->parent); <- Here we dead lock

So we are stuck with calling device_release_driver() and device_attach() 
directly from v4l2-async.

> 
> Regards,
> 
>       Hans

-- 
Regards,
Niklas Söderlund

Reply via email to