Re: [PATCH 2/2] gpiolib: Defer gpio device setup until after gpiolib initialization

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 01, 2016 at 10:29:11AM +1000, Greg Ungerer wrote:
> Hi Guenter,
> 
> On 01/04/16 01:11, Guenter Roeck wrote:
> > Since commit ff2b13592299 ("gpio: make the gpiochip a real device"),
> > attempts to add a gpio chip prior to gpiolib initialization cause
> > the system to crash. This happens because gpio_bus_type has not been
> > registered yet. Defer creating gpio devices until after gpiolib has
> > been initialized to fix the problem.
> > 
> > Cc: Greg Ungerer <gerg@xxxxxxxxxxx>
> > Cc: Alexandre Courbot <gnurou@xxxxxxxxx>
> > Fixes: ff2b13592299 ("gpio: make the gpiochip a real device")
> > Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
> 
> Thanks for putting these patches together.
> I can now boot all my boards again with them applied :-)
> 
> But, I am seeing an issue on one of my targets during boot:
> 
> ...
> Mount-cache hash table entries: 2048 (order: 0, 8192 bytes)
> Mountpoint-cache hash table entries: 2048 (order: 0, 8192 bytes)
> clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 1 at fs/sysfs/dir.c:31 0x000da0e6
> sysfs: cannot create duplicate filename '/bus/gpio'
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.6.0-rc1-dirty #1
> Stack from 0383de38:
>         0383de38 0021f692 00027eb0 03841000 002134f2 038261b0 0382f688 00111c1e
>         00027efe 0021ccc4 0000001f 000da0e6 00000009 00000000 0383de74 0021cc91
>         0383de90 0383df8c 000da0e6 0021ccc4 0000001f 0021cc91 03841000 002134f2
>         038261b0 0382f688 00000000 000da1f0 038261b0 002134f2 0382f688 0382f688
>         00111d86 0382f688 00000000 0382f688 0382f688 0382f680 0024fe84 0002118e
>         0383df8c 0382f688 00112094 0382f688 00000000 0013f5dc 0382f680 00000001
> Call Trace:
>  ...
> ---[ end trace 013025e2024d8831 ]---
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 1 at lib/kobject.c:240 0x00111fc0
> kobject_add_internal failed for gpio with -EEXIST, don't try to register things with the same name in the same directory.
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper Tainted: G        W       4.6.0-rc1-dirty #1
> Stack from 0383de68:
>         0383de68 0021f692 00027eb0 ffffffef 0382f688 00000000 0382f688 00111a26
>         00027efe 0021f817 000000f0 00111fc0 00000009 00000000 0383dea4 0021f8cd
>         0383dec0 0383df8c 00111fc0 0021f817 000000f0 0021f8cd 002069e9 002134f2
>         0382f688 0382f680 0024fe84 0002118e 0383df8c 0382f688 00112094 0382f688
>         00000000 0013f5dc 0382f680 00000001 0000001f 002600de 00265950 0002118e
>         0383df8c 002600f2 0024fe84 00000001 002600de 00265950 0002118e 00021274
> Call Trace:
> ...
> ---[ end trace 013025e2024d8832 ]---
> gpiolib: could not register GPIO bus type
> NET: Registered protocol family 16

Probably coldfire ?

arch/m68k/coldfire/gpio.c:

static struct bus_type mcfgpio_subsys = {
        .name           = "gpio",
	.dev_name       = "gpio",
};

No idea what to do about that. Can that bus be renamed ?

> 
> The boot otherwise continues and is successful.
> 
Thanks for testing!

Guenter

> Regards
> Greg
> 
> 
> > ---
> >  drivers/gpio/gpiolib.c | 98 ++++++++++++++++++++++++++++++++++----------------
> >  1 file changed, 67 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> > index f1531070814d..8bb24dc8dc3d 100644
> > --- a/drivers/gpio/gpiolib.c
> > +++ b/drivers/gpio/gpiolib.c
> > @@ -68,6 +68,7 @@ LIST_HEAD(gpio_devices);
> >  static void gpiochip_free_hogs(struct gpio_chip *chip);
> >  static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip);
> >  
> > +static bool gpiolib_initialized;
> >  
> >  static inline void desc_set_label(struct gpio_desc *d, const char *label)
> >  {
> > @@ -445,6 +446,58 @@ static void gpiodevice_release(struct device *dev)
> >  	kfree(gdev);
> >  }
> >  
> > +static int gpiochip_setup_dev(struct gpio_device *gdev)
> > +{
> > +	int status;
> > +
> > +	cdev_init(&gdev->chrdev, &gpio_fileops);
> > +	gdev->chrdev.owner = THIS_MODULE;
> > +	gdev->chrdev.kobj.parent = &gdev->dev.kobj;
> > +	gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id);
> > +	status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1);
> > +	if (status < 0)
> > +		chip_warn(gdev->chip, "failed to add char device %d:%d\n",
> > +			  MAJOR(gpio_devt), gdev->id);
> > +	else
> > +		chip_dbg(gdev->chip, "added GPIO chardev (%d:%d)\n",
> > +			 MAJOR(gpio_devt), gdev->id);
> > +	status = device_add(&gdev->dev);
> > +	if (status)
> > +		goto err_remove_chardev;
> > +
> > +	status = gpiochip_sysfs_register(gdev);
> > +	if (status)
> > +		goto err_remove_device;
> > +
> > +	/* From this point, the .release() function cleans up gpio_device */
> > +	gdev->dev.release = gpiodevice_release;
> > +	get_device(&gdev->dev);
> > +	pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
> > +		 __func__, gdev->base, gdev->base + gdev->ngpio - 1,
> > +		 dev_name(&gdev->dev), gdev->chip->label ? : "generic");
> > +
> > +	return 0;
> > +
> > +err_remove_device:
> > +	device_del(&gdev->dev);
> > +err_remove_chardev:
> > +	cdev_del(&gdev->chrdev);
> > +	return status;
> > +}
> > +
> > +static void gpiochip_setup_devs(void)
> > +{
> > +	struct gpio_device *gdev;
> > +	int err;
> > +
> > +	list_for_each_entry(gdev, &gpio_devices, list) {
> > +		err = gpiochip_setup_dev(gdev);
> > +		if (err)
> > +			pr_err("%s: Failed to initialize gpio device (%d)\n",
> > +			       dev_name(&gdev->dev), err);
> > +	}
> > +}
> > +
> >  /**
> >   * gpiochip_add_data() - register a gpio_chip
> >   * @chip: the chip to register, with chip->base initialized
> > @@ -459,6 +512,9 @@ static void gpiodevice_release(struct device *dev)
> >   * the gpio framework's arch_initcall().  Otherwise sysfs initialization
> >   * for GPIOs will fail rudely.
> >   *
> > + * gpiochip_add_data() must only be called after gpiolib initialization,
> > + * ie after core_initcall().
> > + *
> >   * If chip->base is negative, this requests dynamic assignment of
> >   * a range of valid GPIOs.
> >   */
> > @@ -515,7 +571,7 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
> >  	if (chip->ngpio == 0) {
> >  		chip_err(chip, "tried to insert a GPIO chip with zero lines\n");
> >  		status = -EINVAL;
> > -		goto err_free_gdev;
> > +		goto err_free_descs;
> >  	}
> >  
> >  	if (chip->label)
> > @@ -597,39 +653,16 @@ int gpiochip_add_data(struct gpio_chip *chip, void *data)
> >  	 * we get a device node entry in sysfs under
> >  	 * /sys/bus/gpio/devices/gpiochipN/dev that can be used for
> >  	 * coldplug of device nodes and other udev business.
> > +	 * We can do this only if gpiolib has been initialized.
> > +	 * Otherwise, defer until later.
> >  	 */
> > -	cdev_init(&gdev->chrdev, &gpio_fileops);
> > -	gdev->chrdev.owner = THIS_MODULE;
> > -	gdev->chrdev.kobj.parent = &gdev->dev.kobj;
> > -	gdev->dev.devt = MKDEV(MAJOR(gpio_devt), gdev->id);
> > -	status = cdev_add(&gdev->chrdev, gdev->dev.devt, 1);
> > -	if (status < 0)
> > -		chip_warn(chip, "failed to add char device %d:%d\n",
> > -			  MAJOR(gpio_devt), gdev->id);
> > -	else
> > -		chip_dbg(chip, "added GPIO chardev (%d:%d)\n",
> > -			 MAJOR(gpio_devt), gdev->id);
> > -	status = device_add(&gdev->dev);
> > -	if (status)
> > -		goto err_remove_chardev;
> > -
> > -	status = gpiochip_sysfs_register(gdev);
> > -	if (status)
> > -		goto err_remove_device;
> > -
> > -	/* From this point, the .release() function cleans up gpio_device */
> > -	gdev->dev.release = gpiodevice_release;
> > -	get_device(&gdev->dev);
> > -	pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
> > -		 __func__, gdev->base, gdev->base + gdev->ngpio - 1,
> > -		 dev_name(&gdev->dev), chip->label ? : "generic");
> > -
> > +	if (gpiolib_initialized) {
> > +		status = gpiochip_setup_dev(gdev);
> > +		if (status)
> > +			goto err_remove_chip;
> > +	}
> >  	return 0;
> >  
> > -err_remove_device:
> > -	device_del(&gdev->dev);
> > -err_remove_chardev:
> > -	cdev_del(&gdev->chrdev);
> >  err_remove_chip:
> >  	acpi_gpiochip_remove(chip);
> >  	gpiochip_free_hogs(chip);
> > @@ -2834,6 +2867,9 @@ static int __init gpiolib_dev_init(void)
> >  	if (ret < 0) {
> >  		pr_err("gpiolib: failed to allocate char dev region\n");
> >  		bus_unregister(&gpio_bus_type);
> > +	} else {
> > +		gpiolib_initialized = true;
> > +		gpiochip_setup_devs();
> >  	}
> >  	return ret;
> >  }
> > 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux