diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2013-02-09 04:41:49 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2013-02-11 17:21:28 -0500 |
commit | 362432aed5e5b497a8cf7b20c268ba71df93c045 (patch) | |
tree | 4a87f9533b3310c0bbd2a87477bf52bb0286cf41 | |
parent | 6c0b4e6c85d085bd92966bc2b8da73e2d7f35929 (diff) |
gpiolib: Fix locking on gpio debugfs files
The debugfs files really need to hold the gpiolib spinlock before
accessing the list. Otherwise chip addition/removal will cause an oops.
Cc: Alexandre Courbot <acourbot@nvidia.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
-rw-r--r-- | drivers/gpio/gpiolib.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5050693dcc35..4b3f388bcc6d 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -2053,29 +2053,35 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip) | |||
2053 | 2053 | ||
2054 | static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos) | 2054 | static void *gpiolib_seq_start(struct seq_file *s, loff_t *pos) |
2055 | { | 2055 | { |
2056 | unsigned long flags; | ||
2056 | struct gpio_chip *chip = NULL; | 2057 | struct gpio_chip *chip = NULL; |
2057 | loff_t index = *pos; | 2058 | loff_t index = *pos; |
2058 | 2059 | ||
2059 | /* REVISIT this isn't locked against gpio_chip removal ... */ | ||
2060 | |||
2061 | s->private = ""; | 2060 | s->private = ""; |
2062 | 2061 | ||
2062 | spin_lock_irqsave(&gpio_lock, flags); | ||
2063 | list_for_each_entry(chip, &gpio_chips, list) | 2063 | list_for_each_entry(chip, &gpio_chips, list) |
2064 | if (index-- == 0) | 2064 | if (index-- == 0) { |
2065 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
2065 | return chip; | 2066 | return chip; |
2067 | } | ||
2068 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
2066 | 2069 | ||
2067 | return NULL; | 2070 | return NULL; |
2068 | } | 2071 | } |
2069 | 2072 | ||
2070 | static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos) | 2073 | static void *gpiolib_seq_next(struct seq_file *s, void *v, loff_t *pos) |
2071 | { | 2074 | { |
2075 | unsigned long flags; | ||
2072 | struct gpio_chip *chip = v; | 2076 | struct gpio_chip *chip = v; |
2073 | void *ret = NULL; | 2077 | void *ret = NULL; |
2074 | 2078 | ||
2079 | spin_lock_irqsave(&gpio_lock, flags); | ||
2075 | if (list_is_last(&chip->list, &gpio_chips)) | 2080 | if (list_is_last(&chip->list, &gpio_chips)) |
2076 | ret = NULL; | 2081 | ret = NULL; |
2077 | else | 2082 | else |
2078 | ret = list_entry(chip->list.next, struct gpio_chip, list); | 2083 | ret = list_entry(chip->list.next, struct gpio_chip, list); |
2084 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
2079 | 2085 | ||
2080 | s->private = "\n"; | 2086 | s->private = "\n"; |
2081 | ++*pos; | 2087 | ++*pos; |