diff options
Diffstat (limited to 'drivers/gpio/gpiolib-sysfs.c')
-rw-r--r-- | drivers/gpio/gpiolib-sysfs.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 7722ed53bd65..af3bc7a8033b 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c | |||
@@ -551,6 +551,7 @@ static struct class gpio_class = { | |||
551 | */ | 551 | */ |
552 | int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | 552 | int gpiod_export(struct gpio_desc *desc, bool direction_may_change) |
553 | { | 553 | { |
554 | struct gpio_chip *chip; | ||
554 | unsigned long flags; | 555 | unsigned long flags; |
555 | int status; | 556 | int status; |
556 | const char *ioname = NULL; | 557 | const char *ioname = NULL; |
@@ -568,8 +569,16 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | |||
568 | return -EINVAL; | 569 | return -EINVAL; |
569 | } | 570 | } |
570 | 571 | ||
572 | chip = desc->chip; | ||
573 | |||
571 | mutex_lock(&sysfs_lock); | 574 | mutex_lock(&sysfs_lock); |
572 | 575 | ||
576 | /* check if chip is being removed */ | ||
577 | if (!chip || !chip->exported) { | ||
578 | status = -ENODEV; | ||
579 | goto fail_unlock; | ||
580 | } | ||
581 | |||
573 | spin_lock_irqsave(&gpio_lock, flags); | 582 | spin_lock_irqsave(&gpio_lock, flags); |
574 | if (!test_bit(FLAG_REQUESTED, &desc->flags) || | 583 | if (!test_bit(FLAG_REQUESTED, &desc->flags) || |
575 | test_bit(FLAG_EXPORT, &desc->flags)) { | 584 | test_bit(FLAG_EXPORT, &desc->flags)) { |
@@ -783,12 +792,15 @@ void gpiochip_unexport(struct gpio_chip *chip) | |||
783 | { | 792 | { |
784 | int status; | 793 | int status; |
785 | struct device *dev; | 794 | struct device *dev; |
795 | struct gpio_desc *desc; | ||
796 | unsigned int i; | ||
786 | 797 | ||
787 | mutex_lock(&sysfs_lock); | 798 | mutex_lock(&sysfs_lock); |
788 | dev = class_find_device(&gpio_class, NULL, chip, match_export); | 799 | dev = class_find_device(&gpio_class, NULL, chip, match_export); |
789 | if (dev) { | 800 | if (dev) { |
790 | put_device(dev); | 801 | put_device(dev); |
791 | device_unregister(dev); | 802 | device_unregister(dev); |
803 | /* prevent further gpiod exports */ | ||
792 | chip->exported = false; | 804 | chip->exported = false; |
793 | status = 0; | 805 | status = 0; |
794 | } else | 806 | } else |
@@ -797,6 +809,13 @@ void gpiochip_unexport(struct gpio_chip *chip) | |||
797 | 809 | ||
798 | if (status) | 810 | if (status) |
799 | chip_dbg(chip, "%s: status %d\n", __func__, status); | 811 | chip_dbg(chip, "%s: status %d\n", __func__, status); |
812 | |||
813 | /* unregister gpiod class devices owned by sysfs */ | ||
814 | for (i = 0; i < chip->ngpio; i++) { | ||
815 | desc = &chip->desc[i]; | ||
816 | if (test_and_clear_bit(FLAG_SYSFS, &desc->flags)) | ||
817 | gpiod_free(desc); | ||
818 | } | ||
800 | } | 819 | } |
801 | 820 | ||
802 | static int __init gpiolib_sysfs_init(void) | 821 | static int __init gpiolib_sysfs_init(void) |