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) |
