[PATCH 1/5] soc: mediatek: Add infracfg misc driver support

Daniel Kurtz djkurtz at chromium.org
Tue May 19 03:39:42 PDT 2015


On Tue, May 19, 2015 at 3:45 PM, Sascha Hauer <s.hauer at pengutronix.de> wrote:
> On Tue, May 19, 2015 at 02:54:41PM +0800, Daniel Kurtz wrote:
>> >> > +       while (1) {
>> >> > +               ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
>> >> > +               if (ret)
>> >> > +                       return ret;
>> >> > +
>> >> > +               if ((val & mask) == mask)
>> >> > +                       break;
>> >> > +
>> >> > +               cpu_relax();
>> >> > +               if (time_after(jiffies, expired))
>> >> > +                       return -EIO;
>> >>
>> >> I think we should check for timeout first, and then cpu_relax() if
>> >> there is still time left (here and in
>> >> mtk_infracfg_clear_bus_protection()).  Otherwise we end up doing one
>> >> final cpu_relax() without rechecking the register we are polling
>> >> (again, I have the same comment for the timeout loops in mtk-scpsys).
>> >
>> > I think cpu_relax() delays execution in the order of microseconds (I
>> > don't actually know, just a guess), so if the timeout is a second the
>> > order doesn't really matter. What can happen though is an interrupt
>> > after the (val & mask) test but before the timeout check. So to be
>> > truly correct we have to repeat the (val & mask) test after the
>> > time_after() check. Is that what you want?
>>
>> I'm not following, why would you need to repeat (val & mask) test
>> after time_after?
>> What does an interrupt have to do with it?
>> Can you show a code snippet with what exactly you are proposing?
>
> Consider you have this timeout loop:
>
>         while (1) {
>                 if (success())
>                         break;
>
>                 if (time_after(jiffies, expired))
>                         return -ETIMEDOUT;
>         }
>
> Now when an interupt comes in between success() and time_after() then it
> can happen that the delay caused by the interrupt makes the code timeout
> even though success() might have become true in the meantime. So to be
> correct you have to:

I agree - I was confused because you only mentioned repeating the
"(val & mask) test", not re-reading the register, which is the
important bit.
For other drivers, I've seen "wait_for()" macros, like below, which do
exactly as you suggest above:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/iommu/rockchip-iommu.c#n110

>
>         while (1) {
>                 if (success())
>                         break;
>
>                 if (time_after(jiffies, expired)) {
>                         if (success())
>                                 break;
>                         return -ETIMEDOUT;
>         }
>
> Or, if you don't want to repeat the termination condition:
>
>         bool timeout = false;
>
>         while (1) {
>                 if (success())
>                         break;
>
>                 if (timeout)
>                         return -ETIMEDOUT;
>
>                 if (time_after(jiffies, expired))
>                         timeout = true;
>         }
>
> Anyway, with the timeout of one second used here this is all academic.

I totally agree that this is academic for the loops here and in
SCPSYS, where the timeout is arbitrary and long.

-Dan

>
> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the linux-arm-kernel mailing list