2001-03-22 20:31:27

by Woller, Thomas

[permalink] [raw]
Subject: Incorrect mdelay() results on Power Managed Machines x86

Problem: Certain Laptops (IBM Thinkpads is where i see the issue) reduce the
CPU frequency based upon whether the unit is on battery power or direct
power. When the Linux kernel boots up, then the cpu_khz (time.c) value is
determined based upon the current cpu speed. But if the unit's power source
is subsequently changed (plugged into the power outlet from battery power;
or unplugged and moved to battery power), then the delay resulting from
mdelay() (i.e. udelay) is off by the same factor. cpu_khz is only
calculated
during init/boot time, and not on a change in the power source. This seems
to be a serious problem since the result is off by a factor of 4 in some
cases which impacts the mdelay() wait times in the same proportion (130 Mhz
cpu speed on battery and 500 Mhz CPU speed direct power, on an IBM
Thinkpad).

During resume the IBM thinkpad with the cs46xx driver needs to delay 700
milleseconds, so if the machine is booted up on battery power, then to
ensure that the delay is long enough, then a value of 3000 milleseconds is
must be programmed into the driver (3 seconds!). all the mdelay and udelay
wait times are incorrect by the same factor, resulting in some serious
problems when attempting to wait specific delay times in other parts of the
driver.

this issue seems like it would be a problem for quite a few drivers that are
used on laptops that need some fairly precise delays, but maybe this is only
an IBM Thinkpad issue. I know that there have been some DMA timeout errors
when resuming on IBM Thinkpads and maybe these errors that have been seen
are due to the invalid delay times generated.

solutions:
using schedule() during resume is not an option, as it causes an oops under
2.2, and causes a second resume to be entered in the pci_driver resume table
entry for some reason. also, schedule() is not fine enough granularity for
some of the micro second delays needed.

re-initing by reinvoking time_init() on each resume cycle doesn't seem to be
an option that i can see.

Appreciate any responses or thoughts on the subject,

Tom Woller
[email protected]
Cirrus Logic/Crystal Semiconductor
(512) 912-3920


2001-03-22 21:24:59

by Alan

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> Problem: Certain Laptops (IBM Thinkpads is where i see the issue) reduce the
> CPU frequency based upon whether the unit is on battery power or direct
> power. When the Linux kernel boots up, then the cpu_khz (time.c) value is

This is commonly done using the speedstep feature on intel cpus. Speedstep
can generate events so the OS knows about it but Intel are not telling
people about how this works.

> Appreciate any responses or thoughts on the subject,

Boot with the 'notsc' option is one approach. We certainly could recalibrate
the clock if we could get events out of ACPI, APM or some other source. Maybe
someone at IBM knows something on the thinkpad front here. If there is for
example an additional apm event or irq we can enable for the thinkpads to see
the speed change we can make it work

2001-03-22 22:56:29

by Andrew Grover

[permalink] [raw]
Subject: RE: Incorrect mdelay() results on Power Managed Machines x86

> During resume the IBM thinkpad with the cs46xx driver needs
> to delay 700
> milleseconds, so if the machine is booted up on battery power, then to
> ensure that the delay is long enough, then a value of 3000
> milleseconds is
> must be programmed into the driver (3 seconds!). all the
> mdelay and udelay
> wait times are incorrect by the same factor, resulting in some serious
> problems when attempting to wait specific delay times in
> other parts of the
> driver.

Well yes this is a problem, but only when starting out with a low effective
CPU freq and going high - the reverse is usually OK because longer than
anticipated waits are OK.

However, you can alleviate this problem by not using udelay (or mdelay) but
using a kernel timer. I would think you should be doing this anyway (700ms
is a LONG TIME) but this should also work regardless of effective CPU freq.

A grep of the kernel source shows cs46xx isn't even doing the biggest
mdelay. I can understand the use of spinning on a calibrated loop for less
than a clock tick, but I gotta think there are better ways for longer
periods.

I wonder if there is a way to modify mdelay to use a kernel timer if
interval > 10msec? I am not familiar with this section of the kernel, but I
do know that Microsoft's similar function KeStallExecutionProcessor is not
recommended for more than 50 *micro*seconds.

Regards -- Andy

2001-03-22 23:05:49

by Alan

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> I wonder if there is a way to modify mdelay to use a kernel timer if
> interval > 10msec? I am not familiar with this section of the kernel, but I
> do know that Microsoft's similar function KeStallExecutionProcessor is not
> recommended for more than 50 *micro*seconds.

Basically the same kind of recommendation applies. But as with all rules its
sometimes appropriate to break it

2001-03-22 23:29:39

by Woller, Thomas

[permalink] [raw]
Subject: RE: Incorrect mdelay() results on Power Managed Machines x86


> > I wonder if there is a way to modify mdelay to use a kernel timer if
> > interval > 10msec? I am not familiar with this section of the kernel,
> but I
> > do know that Microsoft's similar function KeStallExecutionProcessor is
> not
> > recommended for more than 50 *micro*seconds.
>
>>Basically the same kind of recommendation applies. But as with all
rules its
>>sometimes appropriate to break it

thanks, i just tested the "notsc" option (.config has CONFIG_X86_TSC
enabled=y, but CONFIG_M586TSC is not enabled.. if that's ok), but this time
I booted and kept the machine on battery power the ENTIRE time, i had not
tried this before. the MHZ value Detected in time.c is 132Mhz (down from
500Mhz if not on battery power). but the interesting thing that i just
noticed is that the mdelay() wait time, is STILL about 25% of what it should
delay. i use 10000 (for a 10 second delay) and get only about 2-3 seconds
out of it. this smaller delay occurs with or without "notsc" on the boot
line. now, i did not expect this behaviour if i did not plug in to get more
CPU speed, with the calculated cpu rate when on battery power. i expected
that mdelay() would function properly with the appropriate wait time if i
booted and stayed on battery power, at the same reduced CPU frequency.
Alan, you might have answered this in your first post but i don't under the
INTEL speedstep logic to understand if this is expected behaviour. but the
bottom line is that my delay of 700 milleseconds in the driver fails if i
boot and stay on battery power exclusively. did anyone else expect this
behaviour?

2001-03-22 23:35:49

by Alan

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> thanks, i just tested the "notsc" option (.config has CONFIG_X86_TSC
> enabled=y, but CONFIG_M586TSC is not enabled.. if that's ok), but this time
...
> boot and stay on battery power exclusively. did anyone else expect this
> behaviour?

Errmm no..

2001-03-23 11:47:50

by Pavel Machek

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

Hi!

> Problem: Certain Laptops (IBM Thinkpads is where i see the issue) reduce the
> CPU frequency based upon whether the unit is on battery power or direct
> power. When the Linux kernel boots up, then the cpu_khz (time.c)

This is issue with my toshiba sattelite, too. I even had a patch to
detect that speed changed and recalibrate (see archives), but
recalibrate may come too late.
Pavel
--
I'm [email protected]. "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents at [email protected]

2001-03-23 01:44:14

by Tim Wright

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

If it's a 500MHz Thinkpad, then I'm guessing it's something like a 600X.
That doesn't have Speedstep. The speed changes are done by some circuitry
in the laptop. I can try to find out more if this would help.
The newer machines are using Speedstep.

Tim

On Thu, Mar 22, 2001 at 11:37:43PM +0000, Alan Cox wrote:
> > thanks, i just tested the "notsc" option (.config has CONFIG_X86_TSC
> > enabled=y, but CONFIG_M586TSC is not enabled.. if that's ok), but this time
> ...
> > boot and stay on battery power exclusively. did anyone else expect this
> > behaviour?
>
> Errmm no..
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/

--
Tim Wright - [email protected] or [email protected] or [email protected]
IBM Linux Technology Center, Beaverton, Oregon
Interested in Linux scalability ? Look at http://lse.sourceforge.net/
"Nobody ever said I was charming, they said "Rimmer, you're a git!"" RD VI

2001-03-23 04:02:22

by Stephen Rothwell

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> Boot with the 'notsc' option is one approach. We certainly could recalibrate
> the clock if we could get events out of ACPI, APM or some other source. Maybe
> someone at IBM knows something on the thinkpad front here. If there is for
> example an additional apm event or irq we can enable for the thinkpads to see
> the speed change we can make it work

On the ThinkPad 600E (at least), we get a Power Status Change APM event.

Cheers,
Stephen Rothwell

P.S. We actually get two of these events each time we remove or insert the
power cord ...

2001-03-23 06:47:36

by Dave Zarzycki

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

On Thu, 22 Mar 2001, Alan Cox wrote:

> This is commonly done using the speedstep feature on intel cpus. Speedstep
> can generate events so the OS knows about it but Intel are not telling
> people about how this works.
<...snip...>
> We certainly could recalibrate the clock if we could get events out of
> ACPI, APM or some other source.

Specific events for Speedstep on/off would be nice, but in practice, can
we re-calibrate when ever there is a change in the power status (on
battery, charging, etc.)?

davez

--
Dave Zarzycki
http://thor.sbay.org/~dave/

2001-03-23 09:44:20

by Alan

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> If it's a 500MHz Thinkpad, then I'm guessing it's something like a 600X.
> That doesn't have Speedstep. The speed changes are done by some circuitry
> in the laptop. I can try to find out more if this would help.
> The newer machines are using Speedstep.

Ok

Any info on how the laptop wants to tell the OS about CPU speed changes that
we can hook into would be wonderful

2001-03-23 09:53:00

by Alan

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> On the ThinkPad 600E (at least), we get a Power Status Change APM event.

Any reason we couldn't recalibrate the bogomips on a power status change,
at least for laptops we know appear to need it (I can make the DMI code look
for matches there..)

2001-03-23 16:47:40

by Woller, Thomas

[permalink] [raw]
Subject: RE: Incorrect mdelay() results on Power Managed Machines x86

ok, results of additional testing are a little different than i anticipated.
here is some recent information using the IBM Thinkpad 600X. for testing
purposes I used an mdelay of 10000 (10 seconds) in the driver in the resume
code. the results are the same with or without booting with the "notsc"
boot option. ("linux notsc" used as command line to disable tsc). system
was suspended and then resumed, and the delay time noted. AC power was
removed/applied for both before APM action, as well as between suspend and
resume, no difference in the results below.

1) Boot on AC Power - BogoMips is ~992, cpu_khz is ~500
mdelay() functions as expected (10 sec delay) on AC power.
remove AC and go to battery, mdelay() ALSO functions as expected (10 sec
delay). this is good.
2) Boot on Battery - BogoMips is ~280, cpu_khz is ~132
Battery Power - mdelay() fails to delay properly (~2-3 second delay for
mdelay(10000))
apply AC Power - mdelay() fails to delay properly (~2-3 second delay for
mdelay(10000))

Note that apmd() detects a power status change. and indicates via message
that "Now using AC Power", or "Now using Battery Power". so as Pavel
mentioned there is an APM event that occurs if a recal wants to happen.

for now, I'll just look at why the mdelay() actual wait time is never
correct, if booted up on Battery. This fix might be all that is needed.
i'll also look into the archives and see if i can find Pavel's patch, but
until mdelay is working when booted up on battery the patch may not be
needed.


> -----Original Message-----
> From: Pavel Machek [SMTP:[email protected]]
> Sent: Thursday, March 22, 2001 5:29 PM
> To: Woller, Thomas; '[email protected]'
> Subject: Re: Incorrect mdelay() results on Power Managed Machines x86
>
> Hi!
>
> > Problem: Certain Laptops (IBM Thinkpads is where i see the issue) reduce
> the
> > CPU frequency based upon whether the unit is on battery power or direct
> > power. When the Linux kernel boots up, then the cpu_khz (time.c)
>
> This is issue with my toshiba sattelite, too. I even had a patch to
> detect that speed changed and recalibrate (see archives), but
> recalibrate may come too late.
> Pavel
> --
> I'm [email protected]. "In my country we have almost anarchy and I don't care."
> Panos Katsaloulis describing me w.r.t. patents at [email protected]

2001-03-24 03:56:24

by Stephen Rothwell

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

From: Alan Cox <[email protected]>
>
> > On the ThinkPad 600E (at least), we get a Power Status Change APM event.
>
> Any reason we couldn't recalibrate the bogomips on a power status change,
> at least for laptops we know appear to need it (I can make the DMI code look
> for matches there..)

No reason at all ... I'll have a look. I don't have my ThinkPad any more
(as of yesterday) so someone will have to supply the DMI info to match.
I will add another field to the apm_info structure that the DMI code can set
and then just test for it in the APM event loop.

Note, however, that there will still be a latency of up to a second
before we discover this situation as that is how often we poll the
BIOS for events.

Cheers,
Stephen Rothwell
[email protected]

2001-03-28 23:15:37

by Andrew Grover

[permalink] [raw]
Subject: RE: Incorrect mdelay() results on Power Managed Machines x86

Sounds like the TSC makes a lousy calibration method ;-)

I know on ACPI systems you are guaranteed a PM timer running at ~3.57 Mhz.
Could udelay use that, or are there other timers that are better (maybe
without the ACPI dependency)?

Regards -- Andy

> -----Original Message-----
> From: Pavel Machek [mailto:[email protected]]
> Sent: Sunday, March 25, 2001 4:07 PM
> To: Alan Cox
> Cc: [email protected]; [email protected];
> [email protected]
> Subject: Re: Incorrect mdelay() results on Power Managed Machines x86
>
>
> Hi!
>
> > > On the ThinkPad 600E (at least), we get a Power Status
> Change APM event.
> >
> > Any reason we couldn't recalibrate the bogomips on a power
> status change,
> > at least for laptops we know appear to need it (I can make
> the DMI code look
> > for matches there..)
>
> Notice that this is not 100% solution. APM is async, and you
> might already
> did few wrong delays by the time apm event is delivered to you.
>
> Also notice that at least my toshiba goes low speed (150MHz) on
> *) batteries going low
> *) overheat
>
> It goes back to 300MHz at ac power. Another crazy thing: it
> goes down to
> 35MHz on extreme overheat -- that's factor of 10 change.
> --
> Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
> details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.
>
> -
> To unsubscribe from this list: send the line "unsubscribe
> linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>

2001-03-29 04:10:15

by Alan

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

> I know on ACPI systems you are guaranteed a PM timer running at ~3.57 Mhz.
> Could udelay use that, or are there other timers that are better (maybe
> without the ACPI dependency)?

We could use that if ACPI was present. It might be worth exploring. Is this
PM timer well defined for accesses ?

2001-03-29 18:33:24

by Woller, Thomas

[permalink] [raw]
Subject: RE: Incorrect mdelay() results on Power Managed Machines x86

i talked with Keith Frechette at IBM, he is in charge of Linux for IBM. he
indicated that they are working issues with INTEL speedstep and Linux for
their newer laptops, albeit not at a swift pace. he will probably contact
the linux community at some point to help solve issues with SpeedStep, but
he affirms that INTEL treats this information as proprietary, so not sure
how much work can be done for linux. he also indicated that some of the
older IBM models did some non-standard manipulation with the CPU speed at
runtime, e.g. what I am seeing with mdelay failing if booting on a 600X on
battery power. most likely, no event notification would be available for
any of these CPU speed manipulations.
I am going to send some info on the issue to Keith, and he is going to
forward to the technical IBM folks somewhere at IBM, but any solution would
most likely be specific to IBM for the cs46xx audio driver.
It does sound like the PM timer is the best idea so far.
Tom
[email protected]

> -----Original Message-----
> From: Alan Cox [SMTP:[email protected]]
> Sent: Wednesday, March 28, 2001 10:11 PM
> To: [email protected]
> Cc: [email protected]; [email protected]; [email protected];
> [email protected]; [email protected]
> Subject: Re: Incorrect mdelay() results on Power Managed Machines x86
>
> > I know on ACPI systems you are guaranteed a PM timer running at ~3.57
> Mhz.
> > Could udelay use that, or are there other timers that are better (maybe
> > without the ACPI dependency)?
>
> We could use that if ACPI was present. It might be worth exploring. Is
> this
> PM timer well defined for accesses ?

2001-03-30 17:19:19

by Andrew Grover

[permalink] [raw]
Subject: RE: Incorrect mdelay() results on Power Managed Machines x86

I'm not sure what you mean by well-defined. Do you mean, does it have a
fixed address? No, it is relocatable. The ACPI driver can find it because
the base address is specified in the ACPI tables. After the ACPI driver is
loaded the driver could export a pmtimer read function. This is great except
that anything before ACPI load would be out of luck.

After reading a chipset datasheet (in this case for the ICH-2M) both the
8254 timers and the PM timer are driven off a 14.31818 MHz clock input - the
PM timer is that divided by 4 and the 8254 is that divided by 12.

Is there any way we could use the 8254 timer for a reliable udelay? Not as
accurate, but no ACPI dependency.

Regards -- Andy

> From: Alan Cox [mailto:[email protected]]
> > I know on ACPI systems you are guaranteed a PM timer
> running at ~3.57 Mhz.
> > Could udelay use that, or are there other timers that are
> better (maybe
> > without the ACPI dependency)?
>
> We could use that if ACPI was present. It might be worth
> exploring. Is this
> PM timer well defined for accesses ?

2001-03-28 20:57:35

by Pavel Machek

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

Hi!

> > On the ThinkPad 600E (at least), we get a Power Status Change APM event.
>
> Any reason we couldn't recalibrate the bogomips on a power status change,
> at least for laptops we know appear to need it (I can make the DMI code look
> for matches there..)

Notice that this is not 100% solution. APM is async, and you might already
did few wrong delays by the time apm event is delivered to you.

Also notice that at least my toshiba goes low speed (150MHz) on
*) batteries going low
*) overheat

It goes back to 300MHz at ac power. Another crazy thing: it goes down to
35MHz on extreme overheat -- that's factor of 10 change.
--
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.

2001-03-28 20:57:04

by Pavel Machek

[permalink] [raw]
Subject: Re: Incorrect mdelay() results on Power Managed Machines x86

Hi!

> > During resume the IBM thinkpad with the cs46xx driver needs
> > to delay 700
> > milleseconds, so if the machine is booted up on battery power, then to
> > ensure that the delay is long enough, then a value of 3000
> > milleseconds is
> > must be programmed into the driver (3 seconds!). all the
> > mdelay and udelay
> > wait times are incorrect by the same factor, resulting in some serious
> > problems when attempting to wait specific delay times in
> > other parts of the
> > driver.
>
> Well yes this is a problem, but only when starting out with a low effective
> CPU freq and going high - the reverse is usually OK because longer than
> anticipated waits are OK.
>
> However, you can alleviate this problem by not using udelay (or mdelay) but
> using a kernel timer. I would think you should be doing this anyway (700ms
> is a LONG TIME) but this should also work regardless of effective CPU freq.

Going from 59usec to 19usec is probably as fatal as going from 10sec to 3sec.

> A grep of the kernel source shows cs46xx isn't even doing the biggest
> mdelay. I can understand the use of spinning on a calibrated loop for less
> than a clock tick, but I gotta think there are better ways for longer
> periods.
>
> I wonder if there is a way to modify mdelay to use a kernel timer if
> interval > 10msec? I am not familiar with this section of the kernel, but I
> do know that Microsoft's similar function KeStallExecutionProcessor is not
> recommended for more than 50 *micro*seconds.

You can't use kernel timer from within interrupts.

--
Philips Velo 1: 1"x4"x8", 300gram, 60, 12MB, 40bogomips, linux, mutt,
details at http://atrey.karlin.mff.cuni.cz/~pavel/velo/index.html.