|
@@ -67,17 +67,28 @@ static inline void desc_set_label(struct gpio_desc *d, const char *label)
|
|
* when setting direction, and otherwise illegal. Until board setup code
|
|
* when setting direction, and otherwise illegal. Until board setup code
|
|
* and drivers use explicit requests everywhere (which won't happen when
|
|
* and drivers use explicit requests everywhere (which won't happen when
|
|
* those calls have no teeth) we can't avoid autorequesting. This nag
|
|
* those calls have no teeth) we can't avoid autorequesting. This nag
|
|
- * message should motivate switching to explicit requests...
|
|
|
|
|
|
+ * message should motivate switching to explicit requests... so should
|
|
|
|
+ * the weaker cleanup after faults, compared to gpio_request().
|
|
*/
|
|
*/
|
|
-static void gpio_ensure_requested(struct gpio_desc *desc)
|
|
|
|
|
|
+static int gpio_ensure_requested(struct gpio_desc *desc, unsigned offset)
|
|
{
|
|
{
|
|
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
|
|
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
|
|
- pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
|
|
|
|
|
|
+ struct gpio_chip *chip = desc->chip;
|
|
|
|
+ int gpio = chip->base + offset;
|
|
|
|
+
|
|
|
|
+ if (!try_module_get(chip->owner)) {
|
|
|
|
+ pr_err("GPIO-%d: module can't be gotten \n", gpio);
|
|
|
|
+ clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
|
|
+ /* lose */
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
|
|
+ pr_warning("GPIO-%d autorequested\n", gpio);
|
|
desc_set_label(desc, "[auto]");
|
|
desc_set_label(desc, "[auto]");
|
|
- if (!try_module_get(desc->chip->owner))
|
|
|
|
- pr_err("GPIO-%d: module can't be gotten \n",
|
|
|
|
- (int)(desc - gpio_desc));
|
|
|
|
|
|
+ /* caller must chip->request() w/o spinlock */
|
|
|
|
+ if (chip->request)
|
|
|
|
+ return 1;
|
|
}
|
|
}
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* caller holds gpio_lock *OR* gpio is marked as requested */
|
|
/* caller holds gpio_lock *OR* gpio is marked as requested */
|
|
@@ -752,6 +763,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove);
|
|
int gpio_request(unsigned gpio, const char *label)
|
|
int gpio_request(unsigned gpio, const char *label)
|
|
{
|
|
{
|
|
struct gpio_desc *desc;
|
|
struct gpio_desc *desc;
|
|
|
|
+ struct gpio_chip *chip;
|
|
int status = -EINVAL;
|
|
int status = -EINVAL;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
@@ -760,14 +772,15 @@ int gpio_request(unsigned gpio, const char *label)
|
|
if (!gpio_is_valid(gpio))
|
|
if (!gpio_is_valid(gpio))
|
|
goto done;
|
|
goto done;
|
|
desc = &gpio_desc[gpio];
|
|
desc = &gpio_desc[gpio];
|
|
- if (desc->chip == NULL)
|
|
|
|
|
|
+ chip = desc->chip;
|
|
|
|
+ if (chip == NULL)
|
|
goto done;
|
|
goto done;
|
|
|
|
|
|
- if (!try_module_get(desc->chip->owner))
|
|
|
|
|
|
+ if (!try_module_get(chip->owner))
|
|
goto done;
|
|
goto done;
|
|
|
|
|
|
/* NOTE: gpio_request() can be called in early boot,
|
|
/* NOTE: gpio_request() can be called in early boot,
|
|
- * before IRQs are enabled.
|
|
|
|
|
|
+ * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
|
|
*/
|
|
*/
|
|
|
|
|
|
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
|
|
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
|
|
@@ -775,7 +788,20 @@ int gpio_request(unsigned gpio, const char *label)
|
|
status = 0;
|
|
status = 0;
|
|
} else {
|
|
} else {
|
|
status = -EBUSY;
|
|
status = -EBUSY;
|
|
- module_put(desc->chip->owner);
|
|
|
|
|
|
+ module_put(chip->owner);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (chip->request) {
|
|
|
|
+ /* chip->request may sleep */
|
|
|
|
+ spin_unlock_irqrestore(&gpio_lock, flags);
|
|
|
|
+ status = chip->request(chip, gpio - chip->base);
|
|
|
|
+ spin_lock_irqsave(&gpio_lock, flags);
|
|
|
|
+
|
|
|
|
+ if (status < 0) {
|
|
|
|
+ desc_set_label(desc, NULL);
|
|
|
|
+ module_put(chip->owner);
|
|
|
|
+ clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
done:
|
|
done:
|
|
@@ -791,6 +817,7 @@ void gpio_free(unsigned gpio)
|
|
{
|
|
{
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
struct gpio_desc *desc;
|
|
struct gpio_desc *desc;
|
|
|
|
+ struct gpio_chip *chip;
|
|
|
|
|
|
might_sleep();
|
|
might_sleep();
|
|
|
|
|
|
@@ -804,9 +831,17 @@ void gpio_free(unsigned gpio)
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
spin_lock_irqsave(&gpio_lock, flags);
|
|
|
|
|
|
desc = &gpio_desc[gpio];
|
|
desc = &gpio_desc[gpio];
|
|
- if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags)) {
|
|
|
|
|
|
+ chip = desc->chip;
|
|
|
|
+ if (chip && test_bit(FLAG_REQUESTED, &desc->flags)) {
|
|
|
|
+ if (chip->free) {
|
|
|
|
+ spin_unlock_irqrestore(&gpio_lock, flags);
|
|
|
|
+ might_sleep_if(extra_checks && chip->can_sleep);
|
|
|
|
+ chip->free(chip, gpio - chip->base);
|
|
|
|
+ spin_lock_irqsave(&gpio_lock, flags);
|
|
|
|
+ }
|
|
desc_set_label(desc, NULL);
|
|
desc_set_label(desc, NULL);
|
|
module_put(desc->chip->owner);
|
|
module_put(desc->chip->owner);
|
|
|
|
+ clear_bit(FLAG_REQUESTED, &desc->flags);
|
|
} else
|
|
} else
|
|
WARN_ON(extra_checks);
|
|
WARN_ON(extra_checks);
|
|
|
|
|
|
@@ -871,7 +906,9 @@ int gpio_direction_input(unsigned gpio)
|
|
gpio -= chip->base;
|
|
gpio -= chip->base;
|
|
if (gpio >= chip->ngpio)
|
|
if (gpio >= chip->ngpio)
|
|
goto fail;
|
|
goto fail;
|
|
- gpio_ensure_requested(desc);
|
|
|
|
|
|
+ status = gpio_ensure_requested(desc, gpio);
|
|
|
|
+ if (status < 0)
|
|
|
|
+ goto fail;
|
|
|
|
|
|
/* now we know the gpio is valid and chip won't vanish */
|
|
/* now we know the gpio is valid and chip won't vanish */
|
|
|
|
|
|
@@ -879,9 +916,22 @@ int gpio_direction_input(unsigned gpio)
|
|
|
|
|
|
might_sleep_if(extra_checks && chip->can_sleep);
|
|
might_sleep_if(extra_checks && chip->can_sleep);
|
|
|
|
|
|
|
|
+ if (status) {
|
|
|
|
+ status = chip->request(chip, gpio);
|
|
|
|
+ if (status < 0) {
|
|
|
|
+ pr_debug("GPIO-%d: chip request fail, %d\n",
|
|
|
|
+ chip->base + gpio, status);
|
|
|
|
+ /* and it's not available to anyone else ...
|
|
|
|
+ * gpio_request() is the fully clean solution.
|
|
|
|
+ */
|
|
|
|
+ goto lose;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
status = chip->direction_input(chip, gpio);
|
|
status = chip->direction_input(chip, gpio);
|
|
if (status == 0)
|
|
if (status == 0)
|
|
clear_bit(FLAG_IS_OUT, &desc->flags);
|
|
clear_bit(FLAG_IS_OUT, &desc->flags);
|
|
|
|
+lose:
|
|
return status;
|
|
return status;
|
|
fail:
|
|
fail:
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
|
@@ -909,7 +959,9 @@ int gpio_direction_output(unsigned gpio, int value)
|
|
gpio -= chip->base;
|
|
gpio -= chip->base;
|
|
if (gpio >= chip->ngpio)
|
|
if (gpio >= chip->ngpio)
|
|
goto fail;
|
|
goto fail;
|
|
- gpio_ensure_requested(desc);
|
|
|
|
|
|
+ status = gpio_ensure_requested(desc, gpio);
|
|
|
|
+ if (status < 0)
|
|
|
|
+ goto fail;
|
|
|
|
|
|
/* now we know the gpio is valid and chip won't vanish */
|
|
/* now we know the gpio is valid and chip won't vanish */
|
|
|
|
|
|
@@ -917,9 +969,22 @@ int gpio_direction_output(unsigned gpio, int value)
|
|
|
|
|
|
might_sleep_if(extra_checks && chip->can_sleep);
|
|
might_sleep_if(extra_checks && chip->can_sleep);
|
|
|
|
|
|
|
|
+ if (status) {
|
|
|
|
+ status = chip->request(chip, gpio);
|
|
|
|
+ if (status < 0) {
|
|
|
|
+ pr_debug("GPIO-%d: chip request fail, %d\n",
|
|
|
|
+ chip->base + gpio, status);
|
|
|
|
+ /* and it's not available to anyone else ...
|
|
|
|
+ * gpio_request() is the fully clean solution.
|
|
|
|
+ */
|
|
|
|
+ goto lose;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
status = chip->direction_output(chip, gpio, value);
|
|
status = chip->direction_output(chip, gpio, value);
|
|
if (status == 0)
|
|
if (status == 0)
|
|
set_bit(FLAG_IS_OUT, &desc->flags);
|
|
set_bit(FLAG_IS_OUT, &desc->flags);
|
|
|
|
+lose:
|
|
return status;
|
|
return status;
|
|
fail:
|
|
fail:
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|
|
spin_unlock_irqrestore(&gpio_lock, flags);
|