diff mbox series

[v1] iopoll: Tweak readx_poll_timeout sleep range

Message ID c2e6af51-5676-3715-6666-c3f18df7b992@free.fr (mailing list archive)
State New, archived
Headers show
Series [v1] iopoll: Tweak readx_poll_timeout sleep range | expand

Commit Message

Marc Gonzalez June 13, 2019, 12:16 p.m. UTC
Chopping max delay in 4 seems excessive. Let's just cut it in half.

Signed-off-by: Marc Gonzalez <marc.w.gonzalez@free.fr>
---
When max_us=100, old_min was 26 us; new_min would be 50 us
Was there a good reason for the 1/4th?
Is new_min=0 a problem? (for max=1)
---
 include/linux/iopoll.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Arnd Bergmann June 13, 2019, 12:42 p.m. UTC | #1
On Thu, Jun 13, 2019 at 2:16 PM Marc Gonzalez <marc.w.gonzalez@free.fr> wrote:
>
> Chopping max delay in 4 seems excessive. Let's just cut it in half.
>
> Signed-off-by: Marc Gonzalez <marc.w.gonzalez@free.fr>
> ---
> When max_us=100, old_min was 26 us; new_min would be 50 us
> Was there a good reason for the 1/4th?
> Is new_min=0 a problem? (for max=1)

You normally want a large enough range between min and max. I don't
see anything wrong with a factor of four.

> @@ -47,7 +47,7 @@
>                         break; \
>                 } \
>                 if (__sleep_us) \
> -                       usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
> +                       usleep_range(__sleep_us / 2, __sleep_us); \
>         } \

You are also missing the '+1' now, so this breaks with __sleep_us=1.

        Arnd
Marc Gonzalez June 13, 2019, 4:04 p.m. UTC | #2
On 13/06/2019 14:42, Arnd Bergmann wrote:

> On Thu, Jun 13, 2019 at 2:16 PM Marc Gonzalez wrote:
>
>> Chopping max delay in 4 seems excessive. Let's just cut it in half.
>>
>> Signed-off-by: Marc Gonzalez <marc.w.gonzalez@free.fr>
>> ---
>> When max_us=100, old_min was 26 us; new_min would be 50 us
>> Was there a good reason for the 1/4th?
>> Is new_min=0 a problem? (for max=1)
> 
> You normally want a large enough range between min and max. I don't
> see anything wrong with a factor of four.

Hmmm, I expect the typical use-case to be:
"HW manual states operation X completes in 100 µs.
Let's call usleep_range(100, foo); before hitting the reg."

And foo needs to be a "reasonable" value: big enough to be able
to merge several requests, low enough not to wait too long after
the HW is ready.

In this case, I'd say usleep_range(100, 200); makes sense.

Come to think of it, I'm not sure min=26 (or min=50) makes sense...
Why wait *less* than what the user specified?

>> @@ -47,7 +47,7 @@
>>                         break; \
>>                 } \
>>                 if (__sleep_us) \
>> -                       usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
>> +                       usleep_range(__sleep_us / 2, __sleep_us); \
>>         } \
> 
> You are also missing the '+1' now, so this breaks with __sleep_us=1.

It was on purpose.

usleep_range(0, 1); is not well-defined?
(I tried looking at the source, got lost down the rabbit hole.)

Regards.
Doug Anderson June 13, 2019, 4:11 p.m. UTC | #3
Hi,

On Thu, Jun 13, 2019 at 9:04 AM Marc Gonzalez <marc.w.gonzalez@free.fr> wrote:
>
> On 13/06/2019 14:42, Arnd Bergmann wrote:
>
> > On Thu, Jun 13, 2019 at 2:16 PM Marc Gonzalez wrote:
> >
> >> Chopping max delay in 4 seems excessive. Let's just cut it in half.
> >>
> >> Signed-off-by: Marc Gonzalez <marc.w.gonzalez@free.fr>
> >> ---
> >> When max_us=100, old_min was 26 us; new_min would be 50 us
> >> Was there a good reason for the 1/4th?
> >> Is new_min=0 a problem? (for max=1)
> >
> > You normally want a large enough range between min and max. I don't
> > see anything wrong with a factor of four.
>
> Hmmm, I expect the typical use-case to be:
> "HW manual states operation X completes in 100 µs.
> Let's call usleep_range(100, foo); before hitting the reg."
>
> And foo needs to be a "reasonable" value: big enough to be able
> to merge several requests, low enough not to wait too long after
> the HW is ready.
>
> In this case, I'd say usleep_range(100, 200); makes sense.
>
> Come to think of it, I'm not sure min=26 (or min=50) makes sense...
> Why wait *less* than what the user specified?

IIRC usleep_range() nearly always tries to sleep for the max.  My
recollection of the design is that you only end up with something less
than the max if the system was going to wake up anyway.  In such a
case it seems like it wouldn't be insane to go and check if the
condition is already true if 25% of the time has passed.  Maybe you'll
get lucky and you can return early.

Are you actually seeing problems with the / 4, or is this patch just a
result of code inspection?

-Doug
Marc Gonzalez June 13, 2019, 4:36 p.m. UTC | #4
On 13/06/2019 18:11, Doug Anderson wrote:

> On Thu, Jun 13, 2019 at 9:04 AM Marc Gonzalez wrote:
>
>> Hmmm, I expect the typical use-case to be:
>> "HW manual states operation X completes in 100 µs.
>> Let's call usleep_range(100, foo); before hitting the reg."
>>
>> And foo needs to be a "reasonable" value: big enough to be able
>> to merge several requests, low enough not to wait too long after
>> the HW is ready.
>>
>> In this case, I'd say usleep_range(100, 200); makes sense.
>>
>> Come to think of it, I'm not sure min=26 (or min=50) makes sense...
>> Why wait *less* than what the user specified?
> 
> IIRC usleep_range() nearly always tries to sleep for the max.  My
> recollection of the design is that you only end up with something less
> than the max if the system was going to wake up anyway.  In such a
> case it seems like it wouldn't be insane to go and check if the
> condition is already true if 25% of the time has passed.  Maybe you'll
> get lucky and you can return early.
> 
> Are you actually seeing problems with the / 4, or is this patch just a
> result of code inspection?

No actual issue. I just ran into a driver calling:

	readl_poll_timeout(status, val, val & mask, 1, 1000);

and it seemed... unwise(?) to call usleep_range(1, 1);

But if, as you say, usleep_range() aims for the max, then I guess it's
not a big deal to issue an early read or 3... Meh

Regards.
Doug Anderson June 13, 2019, 5:10 p.m. UTC | #5
Hi,


On Thu, Jun 13, 2019 at 9:37 AM Marc Gonzalez <marc.w.gonzalez@free.fr> wrote:
>
> On 13/06/2019 18:11, Doug Anderson wrote:
>
> > On Thu, Jun 13, 2019 at 9:04 AM Marc Gonzalez wrote:
> >
> >> Hmmm, I expect the typical use-case to be:
> >> "HW manual states operation X completes in 100 µs.
> >> Let's call usleep_range(100, foo); before hitting the reg."
> >>
> >> And foo needs to be a "reasonable" value: big enough to be able
> >> to merge several requests, low enough not to wait too long after
> >> the HW is ready.
> >>
> >> In this case, I'd say usleep_range(100, 200); makes sense.
> >>
> >> Come to think of it, I'm not sure min=26 (or min=50) makes sense...
> >> Why wait *less* than what the user specified?
> >
> > IIRC usleep_range() nearly always tries to sleep for the max.  My
> > recollection of the design is that you only end up with something less
> > than the max if the system was going to wake up anyway.  In such a
> > case it seems like it wouldn't be insane to go and check if the
> > condition is already true if 25% of the time has passed.  Maybe you'll
> > get lucky and you can return early.
> >
> > Are you actually seeing problems with the / 4, or is this patch just a
> > result of code inspection?
>
> No actual issue. I just ran into a driver calling:
>
>         readl_poll_timeout(status, val, val & mask, 1, 1000);
>
> and it seemed... unwise(?) to call usleep_range(1, 1);
>
> But if, as you say, usleep_range() aims for the max

It was certainly what we found in:

https://lkml.kernel.org/r/1444265321-16768-6-git-send-email-dianders@chromium.org

...in fact, at one point in time I had a patch cooked up that would
change the behavior during boot where (presumably) we'd rather boot
faster.  ...but after fixing dwc2 it didn't actually have much of an
impact elsewhere.


> then I guess it's
> not a big deal to issue an early read or 3... Meh

IMO it seems like the driver should be fixed.  It should either specify:

a) the (well defined) 0 for the delay, which means no delay.

b) a more sane delay


-Doug
diff mbox series

Patch

diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index 3908353deec6..24a00d923c15 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -47,7 +47,7 @@ 
 			break; \
 		} \
 		if (__sleep_us) \
-			usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
+			usleep_range(__sleep_us / 2, __sleep_us); \
 	} \
 	(cond) ? 0 : -ETIMEDOUT; \
 })