gpio: sysfs: fix gpio-chip device-attribute leak
[pandora-kernel.git] / drivers / gpio / gpiolib.c
index 36a2974..f4e4363 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/idr.h>
 #include <linux/slab.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/gpio.h>
 
 /* Optional implementation infrastructure for GPIO interfaces.
  *
@@ -585,16 +587,13 @@ static ssize_t chip_ngpio_show(struct device *dev,
 }
 static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL);
 
-static const struct attribute *gpiochip_attrs[] = {
+static struct attribute *gpiochip_attrs[] = {
        &dev_attr_base.attr,
        &dev_attr_label.attr,
        &dev_attr_ngpio.attr,
        NULL,
 };
-
-static const struct attribute_group gpiochip_attr_group = {
-       .attrs = (struct attribute **) gpiochip_attrs,
-};
+ATTRIBUTE_GROUPS(gpiochip);
 
 /*
  * /sys/class/gpio/export ... write-only
@@ -916,13 +915,13 @@ static int gpiochip_export(struct gpio_chip *chip)
 
        /* use chip->base for the ID; it's already known to be unique */
        mutex_lock(&sysfs_lock);
-       dev = device_create(&gpio_class, chip->dev, MKDEV(0, 0), chip,
-                               "gpiochip%d", chip->base);
-       if (!IS_ERR(dev)) {
-               status = sysfs_create_group(&dev->kobj,
-                               &gpiochip_attr_group);
-       } else
+       dev = device_create_with_groups(&gpio_class, chip->dev, MKDEV(0, 0),
+                                       chip, gpiochip_groups,
+                                       "gpiochip%d", chip->base);
+       if (IS_ERR(dev))
                status = PTR_ERR(dev);
+       else
+               status = 0;
        chip->exported = (status == 0);
        mutex_unlock(&sysfs_lock);
 
@@ -1073,9 +1072,9 @@ int gpiochip_add(struct gpio_chip *chip)
                                ? (1 << FLAG_IS_OUT)
                                : 0;
                }
-       }
 
-       of_gpiochip_add(chip);
+               of_gpiochip_add(chip);
+       }
 
 unlock:
        spin_unlock_irqrestore(&gpio_lock, flags);
@@ -1084,8 +1083,10 @@ unlock:
                goto fail;
 
        status = gpiochip_export(chip);
-       if (status)
+       if (status) {
+               of_gpiochip_remove(chip);
                goto fail;
+       }
 
        return 0;
 fail:
@@ -1165,6 +1166,7 @@ struct gpio_chip *gpiochip_find(void *data,
 
        return chip;
 }
+EXPORT_SYMBOL_GPL(gpiochip_find);
 
 /* These "optional" allocation calls help prevent drivers from stomping
  * on each other, and help provide better diagnostics in debugfs.
@@ -1293,7 +1295,7 @@ EXPORT_SYMBOL_GPL(gpio_request_one);
  * @array:     array of the 'struct gpio'
  * @num:       how many GPIOs in the array
  */
-int gpio_request_array(struct gpio *array, size_t num)
+int gpio_request_array(const struct gpio *array, size_t num)
 {
        int i, err;
 
@@ -1316,7 +1318,7 @@ EXPORT_SYMBOL_GPL(gpio_request_array);
  * @array:     array of the 'struct gpio'
  * @num:       how many GPIOs in the array
  */
-void gpio_free_array(struct gpio *array, size_t num)
+void gpio_free_array(const struct gpio *array, size_t num)
 {
        while (num--)
                gpio_free((array++)->gpio);
@@ -1404,6 +1406,8 @@ int gpio_direction_input(unsigned gpio)
        status = chip->direction_input(chip, gpio);
        if (status == 0)
                clear_bit(FLAG_IS_OUT, &desc->flags);
+
+       trace_gpio_direction(chip->base + gpio, 1, status);
 lose:
        return status;
 fail:
@@ -1457,6 +1461,8 @@ int gpio_direction_output(unsigned gpio, int value)
        status = chip->direction_output(chip, gpio, value);
        if (status == 0)
                set_bit(FLAG_IS_OUT, &desc->flags);
+       trace_gpio_value(chip->base + gpio, 0, value);
+       trace_gpio_direction(chip->base + gpio, 0, status);
 lose:
        return status;
 fail:
@@ -1546,10 +1552,13 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
 int __gpio_get_value(unsigned gpio)
 {
        struct gpio_chip        *chip;
+       int value;
 
        chip = gpio_to_chip(gpio);
        WARN_ON(chip->can_sleep);
-       return chip->get ? chip->get(chip, gpio - chip->base) : 0;
+       value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
+       trace_gpio_value(gpio, 1, value);
+       return value;
 }
 EXPORT_SYMBOL_GPL(__gpio_get_value);
 
@@ -1568,6 +1577,7 @@ void __gpio_set_value(unsigned gpio, int value)
 
        chip = gpio_to_chip(gpio);
        WARN_ON(chip->can_sleep);
+       trace_gpio_value(gpio, 0, value);
        chip->set(chip, gpio - chip->base, value);
 }
 EXPORT_SYMBOL_GPL(__gpio_set_value);
@@ -1618,10 +1628,13 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);
 int gpio_get_value_cansleep(unsigned gpio)
 {
        struct gpio_chip        *chip;
+       int value;
 
        might_sleep_if(extra_checks);
        chip = gpio_to_chip(gpio);
-       return chip->get ? chip->get(chip, gpio - chip->base) : 0;
+       value = chip->get ? chip->get(chip, gpio - chip->base) : 0;
+       trace_gpio_value(gpio, 1, value);
+       return value;
 }
 EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
 
@@ -1631,6 +1644,7 @@ void gpio_set_value_cansleep(unsigned gpio, int value)
 
        might_sleep_if(extra_checks);
        chip = gpio_to_chip(gpio);
+       trace_gpio_value(gpio, 0, value);
        chip->set(chip, gpio - chip->base, value);
 }
 EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);