[PATCH v6 17/25] gpio/omap: use pm-runtime framework
DebBarma, Tarun Kanti
tarun.kanti at ti.com
Wed Sep 7 01:04:43 EDT 2011
[...]
>> + /*
>> + * If this is the first gpio_request for the bank,
>> + * enable the bank module.
>> + */
>> + if (!bank->mod_usage)
>> + if (IS_ERR_VALUE(pm_runtime_get_sync(bank->dev) < 0)) {
>
> All of the IS_ERR_VALUE() usage is wrong here. You're checking if the
> result of IS_ERR_VALUE() is < 0 which will never happen.
No.
IS_ERR_VALUE is applied on the return value of pm_runtime_get_sync
which is < 0.
>
>> + dev_err(bank->dev, "%s: GPIO bank %d "
>> + "pm_runtime_get_sync failed\n",
>> + __func__, bank->id);
>> + spin_unlock_irqrestore(&bank->lock, flags);
>
> Rather than take the lock and have to unlock it here, just move the
> get_sync before the spinlock. There's no reason to hold the spinlock
> across the get_sync.
>
> In fact, holding the spinlock across a get sync means that the
> ->runtime_resume callback does not have proper locking around register
> access, which is also probably wrong.
>
> The locking in this driver is only around device register accesses, and
> should be kept minimal and to very small critical sections.
You are right! I will move *_get_sync() outside spinlock.
>
>> + return -EINVAL;
>> + }
>> +
>> /* Set trigger to none. You need to enable the desired trigger with
>> * request_irq() or set_irq_type().
>> */
>> @@ -530,6 +545,19 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset)
>> }
>>
>> _reset_gpio(bank, bank->chip.base + offset);
>> +
>> + /*
>> + * If this is the last gpio to be freed in the bank,
>> + * disable the bank module.
>> + */
>> + if (!bank->mod_usage) {
>> + if (IS_ERR_VALUE(pm_runtime_put_sync(bank->dev) < 0)) {
>> + dev_err(bank->dev, "%s: GPIO bank %d "
>> + "pm_runtime_put_sync failed\n",
>> + __func__, bank->id);
>> + }
>> + }
>> +
>
> same here, this should be after unlocking the spinlock, and register
> accesses inside the ->runtime_resume() callback need their own
> protection.
Ok.
>
>> spin_unlock_irqrestore(&bank->lock, flags);
>> }
>>
>> @@ -556,6 +584,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
>>
>> bank = irq_get_handler_data(irq);
>> isr_reg = bank->base + bank->regs->irqstatus;
>> + pm_runtime_get_sync(bank->dev);
>>
>> if (WARN_ON(!isr_reg))
>> goto exit;
>> @@ -617,6 +646,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
>> exit:
>> if (!unmasked)
>> chained_irq_exit(chip, desc);
>> + pm_runtime_put_sync_suspend(bank->dev);
>
> Why use _put_sync_suspend()?
>
> Why does this need to be synchronous? I think it should use the
> asynchronous pm_runtime_put().
I will change it to pm_runtime_put().
>
[...]
>>
>> @@ -1258,10 +1310,16 @@ static void omap_gpio_restore_context(struct gpio_bank *bank)
>> }
>> #endif
>>
>> +static const struct dev_pm_ops gpio_pm_ops = {
>> + .suspend = omap_gpio_suspend,
>> + .resume = omap_gpio_resume,
>> +};
>
> Please use SET_SYSTEM_SLEEP_PM_OPS(). See <linux/pm.h>
Ok.
>
>> static struct platform_driver omap_gpio_driver = {
>> .probe = omap_gpio_probe,
>> .driver = {
>> .name = "omap_gpio",
>> + .pm = &gpio_pm_ops,
>> },
>> };
>>
>> @@ -1275,16 +1333,3 @@ static int __init omap_gpio_drv_reg(void)
>> return platform_driver_register(&omap_gpio_driver);
>> }
>> postcore_initcall(omap_gpio_drv_reg);
>> -
>> -static int __init omap_gpio_sysinit(void)
>> -{
>> -
>> -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS)
>> - if (cpu_is_omap16xx() || cpu_class_is_omap2())
>> - register_syscore_ops(&omap_gpio_syscore_ops);
>> -#endif
>> -
>> - return 0;
>> -}
>> -
>> -arch_initcall(omap_gpio_sysinit);
>
> Kevin
>
More information about the linux-arm-kernel
mailing list