linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RE: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
@ 2003-08-29 16:12 Pallipadi, Venkatesh
  2003-08-30  4:59 ` David Mosberger-Tang
  0 siblings, 1 reply; 15+ messages in thread
From: Pallipadi, Venkatesh @ 2003-08-29 16:12 UTC (permalink / raw)
  To: David Mosberger-Tang; +Cc: linux-kernel



The part of the patch that does the HPET initialization for timer
interrupt, and general HPET registers read/write/programming can be
common across architectures.
However, different archs diverge, when it comes to gettimeofday-timer
implementation (tsc, pit, itc, hpet, ) and we may still have to keep
that part architecture specific. 

Thanks,
Venkatesh

> -----Original Message-----
> From: David Mosberger-Tang [mailto:David.Mosberger@acm.org] 
> Sent: Thursday, August 28, 2003 8:41 PM
> To: Pallipadi, Venkatesh
> Cc: linux-kernel@vger.kernel.org
> Subject: Re: [PATCHSET][2.6-test4][0/6]Support for HPET based 
> timer - Take 2
> 
> 
> >>>>> On Fri, 29 Aug 2003 01:50:09 +0200, "Pallipadi, 
> Venkatesh" <venkatesh.pallipadi@intel.com> said:
> 
>   Venkatesh> Resending the patch. A major change from previous version
>   Venkatesh> is elimination of fixmap for HPET. Based on Andrew
>   Venkatesh> Morton's suggestion, we have a new hook in init/main.c
>   Venkatesh> for late_time_init(), at which time we can use ioremap,
>   Venkatesh> in place of fixmap.  Impact on other archs:
>   Venkatesh> Calibrate_delay() (and hence loops_per_jiffy calculation)
>   Venkatesh> has moved down in main.c, from after time_init() to after
>   Venkatesh> kmem_cache_init().
> 
>   Venkatesh> All comments/feedbacks welcome.
> 
> How much is really architecture-specific?  HPET isn't x86-only so
> sooner or later, we'll have to move it out of arch/i386 anyhow.
> 
> 	--david
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-29 16:12 [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2 Pallipadi, Venkatesh
@ 2003-08-30  4:59 ` David Mosberger-Tang
  0 siblings, 0 replies; 15+ messages in thread
From: David Mosberger-Tang @ 2003-08-30  4:59 UTC (permalink / raw)
  To: Pallipadi, Venkatesh; +Cc: David Mosberger-Tang, linux-kernel

>>>>> On Fri, 29 Aug 2003 09:12:52 -0700, "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> said:

  Venkatesh> The part of the patch that does the HPET initialization
  Venkatesh> for timer interrupt, and general HPET registers
  Venkatesh> read/write/programming can be common across
  Venkatesh> architectures.  However, different archs diverge, when it
  Venkatesh> comes to gettimeofday-timer implementation (tsc, pit,
  Venkatesh> itc, hpet, ) and we may still have to keep that part
  Venkatesh> architecture specific.

Is the time_interpolator interface provided by timex.h sufficient for
HPET timer-interrupt needs?  I think It ought to be.  If so, perhaps
all that's missing is that x86 needs to be switched over to that
interface?

	--david

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-09-06 19:04 Pallipadi, Venkatesh
@ 2003-09-07 17:57 ` George Anzinger
  0 siblings, 0 replies; 15+ messages in thread
From: George Anzinger @ 2003-09-07 17:57 UTC (permalink / raw)
  To: Pallipadi, Venkatesh; +Cc: Andrew Morton, torvalds, linux-kernel, Nakajima, Jun

Pallipadi, Venkatesh wrote:
> 
> 
>>-----Original Message-----
>>From: George Anzinger [mailto:george@mvista.com]
>>
>>Pallipadi, Venkatesh wrote:
>>
>>>
>>>>-----Original Message-----
>>>>From: Andrew Morton [mailto:akpm@osdl.org] 
>>>>
>>>>We seem to keep on proliferating home-grown x86 64-bit math 
>>
>>functions.
>>
>>>>Do you really need these?  Is it possible to use do_div() and 
>>>>the C 64x64
>>>>`*' operator instead?
>>>>
>>>
>>>
>>>
>>>We can change these handcoded 64 bit divs to do_div, with just an
>>>additional data copy 
>>
>>We already have this in .../include/asm-i386/div64.h.  Check usage in 
>>.../posix-timers.c to cover archs that have not yet included it in 
>>there div64.h.
>>
> 
> 
> 
> Yes. We can surely use div_long_long_rem from div64 in place of defining 
> this again. This kind of code is already there in the existing ia32 timer
> code too. I will try and come up with a cleanup patch to replace all 
> these individual asm div statements.
> 
> 
> 
>>>(as do_div changes dividend in place). But, changing mul 
>>
>>into 64x64 '*'
>>
>>>may be tricky. 
>>>Gcc seem to generate a combination of mul, 2imul and add, 
>>
>>where as we
>>
>>>are happy with 
>>>using only one mull here.
>>
>>You just need to do the right casting.  It should like 
>>u64=u32*(u64)u32  as in .../kernel/posix-timers.c.  This 
>>could also be 
>>signed with the same results.  If you really need to do a u64*u32, it 
>>will do that as well but takes two mpys.  In this case you will need 
>>to do it unsigned to eliminate the third mpy.
> 
> 
> 
> Interesting. Is this casting to generate proper mul instruction
> some sort of C standard or is it a gcc feature. I just want to
> make sure doing this way won't break on some other compiler 
> (or on some other version of gcc itself).

I don't really know, but I suspect it is a gcc thing.  Some how the 
standards folks got in and messed up the original idea of keeping the 
language close to the machine when they said that the data type in to 
and out of a C operator should be the same, thus not allowing the true 
mpy result to find expression in the language.  The same thing applies 
to the "/" and "%" operators, which to my knowledge, require either 
really messy macros/c code or asm to allow the machine u64/u32 to work.
> 
> 
> Thanks,
> -Venkatesh
> 
> 

-- 
George Anzinger   george@mvista.com
High-res-timers:  http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml


^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
@ 2003-09-06 19:04 Pallipadi, Venkatesh
  2003-09-07 17:57 ` George Anzinger
  0 siblings, 1 reply; 15+ messages in thread
From: Pallipadi, Venkatesh @ 2003-09-06 19:04 UTC (permalink / raw)
  To: George Anzinger; +Cc: Andrew Morton, torvalds, linux-kernel, Nakajima, Jun




> -----Original Message-----
> From: George Anzinger [mailto:george@mvista.com]
> 
> Pallipadi, Venkatesh wrote:
> > 
> > 
> >>-----Original Message-----
> >>From: Andrew Morton [mailto:akpm@osdl.org] 
> >>
> >>We seem to keep on proliferating home-grown x86 64-bit math 
> functions.
> >>
> >>Do you really need these?  Is it possible to use do_div() and 
> >>the C 64x64
> >>`*' operator instead?
> >>
> > 
> > 
> > 
> > We can change these handcoded 64 bit divs to do_div, with just an
> > additional data copy 
> 
> We already have this in .../include/asm-i386/div64.h.  Check usage in 
> .../posix-timers.c to cover archs that have not yet included it in 
> there div64.h.
>


Yes. We can surely use div_long_long_rem from div64 in place of defining 
this again. This kind of code is already there in the existing ia32 timer
code too. I will try and come up with a cleanup patch to replace all 
these individual asm div statements.


> > (as do_div changes dividend in place). But, changing mul 
> into 64x64 '*'
> > may be tricky. 
> > Gcc seem to generate a combination of mul, 2imul and add, 
> where as we
> > are happy with 
> > using only one mull here.
> 
> You just need to do the right casting.  It should like 
> u64=u32*(u64)u32  as in .../kernel/posix-timers.c.  This 
> could also be 
> signed with the same results.  If you really need to do a u64*u32, it 
> will do that as well but takes two mpys.  In this case you will need 
> to do it unsigned to eliminate the third mpy.


Interesting. Is this casting to generate proper mul instruction
some sort of C standard or is it a gcc feature. I just want to
make sure doing this way won't break on some other compiler 
(or on some other version of gcc itself).


Thanks,
-Venkatesh

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-29 23:58 Pallipadi, Venkatesh
@ 2003-09-05 22:26 ` George Anzinger
  0 siblings, 0 replies; 15+ messages in thread
From: George Anzinger @ 2003-09-05 22:26 UTC (permalink / raw)
  To: Pallipadi, Venkatesh; +Cc: Andrew Morton, torvalds, linux-kernel, Nakajima, Jun

Pallipadi, Venkatesh wrote:
> 
> 
>>-----Original Message-----
>>From: Andrew Morton [mailto:akpm@osdl.org] 
>>
>>We seem to keep on proliferating home-grown x86 64-bit math functions.
>>
>>Do you really need these?  Is it possible to use do_div() and 
>>the C 64x64
>>`*' operator instead?
>>
> 
> 
> 
> We can change these handcoded 64 bit divs to do_div, with just an
> additional data copy 

We already have this in .../include/asm-i386/div64.h.  Check usage in 
.../posix-timers.c to cover archs that have not yet included it in 
there div64.h.

> (as do_div changes dividend in place). But, changing mul into 64x64 '*'
> may be tricky. 
> Gcc seem to generate a combination of mul, 2imul and add, where as we
> are happy with 
> using only one mull here.

You just need to do the right casting.  It should like 
u64=u32*(u64)u32  as in .../kernel/posix-timers.c.  This could also be 
signed with the same results.  If you really need to do a u64*u32, it 
will do that as well but takes two mpys.  In this case you will need 
to do it unsigned to eliminate the third mpy.
> 
> 

-- 
George Anzinger   george@mvista.com
High-res-timers:  http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-29 21:03   ` Erik Andersen
  2003-08-31 21:05     ` Linus Torvalds
@ 2003-09-05 22:19     ` George Anzinger
  1 sibling, 0 replies; 15+ messages in thread
From: George Anzinger @ 2003-09-05 22:19 UTC (permalink / raw)
  To: andersen
  Cc: Andrew Morton, Pallipadi, Venkatesh, torvalds, linux-kernel,
	jun.nakajima

Erik Andersen wrote:
> On Fri Aug 29, 2003 at 11:23:47AM -0700, Andrew Morton wrote:
> 
>>"Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> wrote:
>>
>>>Resending the patch.
>>
>>Thanks, I'll include these in the next -mm kernel.
>>
>>Reading the code, the only thing which leaps out is:
>>
>>+/* Use our own asm for 64 bit multiply/divide */
>>+#define ASM_MUL64_REG(eax_out,edx_out,reg_in,eax_in) 			\
>>+		__asm__ __volatile__("mull %2" 				\
>>+				:"=a" (eax_out), "=d" (edx_out) 	\
>>+				:"r" (reg_in), "0" (eax_in))

This can be done in standard C.  If you want an inline, how about 
(from .../kernel/posix-timers.c):

static inline u64  mpy_l_X_l_ll(unsigned long mpy1,unsigned long mpy2)
{
	return (u64)mpy1 * mpy2;
}


>>+
>>+#define ASM_DIV64_REG(eax_out,edx_out,reg_in,eax_in,edx_in) 		\
>>+		__asm__ __volatile__("divl %2" 				\
>>+				:"=a" (eax_out), "=d" (edx_out) 	\
>>+				:"r" (reg_in), "0" (eax_in), "1" (edx_in))

This appears to be the same as (from .../include/asm-i386/div64.h):

#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c)

extern inline long
div_ll_X_l_rem(long long divs, long div, long *rem)
{
	long dum2;
       __asm__("divl %2":"=a"(dum2), "=d"(*rem)
       :	"rm"(div), "A"(divs));

	return dum2;

}

-g

>>
>>We seem to keep on proliferating home-grown x86 64-bit math functions.
>>
>>Do you really need these?  Is it possible to use do_div() and the C 64x64
>>`*' operator instead?
> 
> 
> 
> The fundamental reason these are proliferating is that given
> some random bit of code such as:
> 
>     u64 foo=9, bar=3, baz;
>     baz = foo / bar;
>     baz = foo % bar;
> 
> gcc then generates code calling __udivdi3 and __umoddi3.  Since
> the kernel does not provide these, people keep reinventing them.
> Perhaps it is time to kill off do_div and all its little friends
> and simply copy __udivdi3 and __umoddi3 from libgcc.....
> 
>  -Erik
> 
> --
> Erik B. Andersen             http://codepoet-consulting.com/
> --This message was written using 73% post-consumer electrons--
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

-- 
George Anzinger   george@mvista.com
High-res-timers:  http://sourceforge.net/projects/high-res-timers/
Preemption patch: http://www.kernel.org/pub/linux/kernel/people/rml


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-31 22:24       ` Erik Andersen
@ 2003-08-31 22:48         ` Linus Torvalds
  0 siblings, 0 replies; 15+ messages in thread
From: Linus Torvalds @ 2003-08-31 22:48 UTC (permalink / raw)
  To: Erik Andersen
  Cc: Andrew Morton, Pallipadi, Venkatesh, linux-kernel, jun.nakajima


On Sun, 31 Aug 2003, Erik Andersen wrote:
>
> Been there done that, got the scars to prove it.  do_div() is a
> macro that acts sortof like the ISO C99 lldiv(3) function.

No.

You missed a very important part of do_div() - it has _totally_ different 
numerical range than a regular /, % or lldiv() call.

All of /, % and lldiv() work on 64-bit numbers. do_div() DOES NOT!

do_div() very much is all about:

	***   32-bit divisor  ***

which also implies that the remainder is 32-bit.

And the fact is, such a division is a lot faster than a full 64-bit 
division. On a _lot_ of architectures, but notably so on x86.

It is _not_ a 64-bit divide, and that's not only important, it's the 
whole _reason_d'etre_ for the whole function. See?

So by continually confusing it with a 64-bit divide (either by confusing 
it with lldiv() or those horrible gcc internal __{div|mod}di3u things), 
you miss the whole point of the function.

		Linus
 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-31 21:05     ` Linus Torvalds
@ 2003-08-31 22:24       ` Erik Andersen
  2003-08-31 22:48         ` Linus Torvalds
  0 siblings, 1 reply; 15+ messages in thread
From: Erik Andersen @ 2003-08-31 22:24 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Andrew Morton, Pallipadi, Venkatesh, linux-kernel, jun.nakajima

On Sun Aug 31, 2003 at 02:05:25PM -0700, Linus Torvalds wrote:
> 
> On Fri, 29 Aug 2003, Erik Andersen wrote:
> > 
> > gcc then generates code calling __udivdi3 and __umoddi3.  Since
> > the kernel does not provide these, people keep reinventing them.
> > Perhaps it is time to kill off do_div and all its little friends
> > and simply copy __udivdi3 and __umoddi3 from libgcc.....
> 
> No. do_div() does _nothing_ like __udivdi3/__umoddi3.
> 
> Read the documentation.

Been there done that, got the scars to prove it.  do_div() is a
macro that acts sortof like the ISO C99 lldiv(3) function.
Except it does unexpected things like modify its arguments... 

Most places in the kernel using do_div() not because it is the
right thing to do, but because they tried to do something
seemingly simple such as:

    u64 foo, bar, baz;
    ...
    baz = foo / bar;

and then got an error that __udivdi3 was undefined.  So the
authors then go hunting for a way to do a 64 bit division and
find do_div()...

See mm/vmscan.c, mm/shmem.c, fs/proc/proc_misc.c,
drivers/ide/ide-disk.c, etc, etc, etc, for plenty of examples of
_exactly_ this sort of thing.  Every one of them is using
do_div() to perform 64 bit division.  Not becase that is the
right thing to do, but because __udivdi3 is missing.

 -Erik

--
Erik B. Andersen             http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-29 21:03   ` Erik Andersen
@ 2003-08-31 21:05     ` Linus Torvalds
  2003-08-31 22:24       ` Erik Andersen
  2003-09-05 22:19     ` George Anzinger
  1 sibling, 1 reply; 15+ messages in thread
From: Linus Torvalds @ 2003-08-31 21:05 UTC (permalink / raw)
  To: Erik Andersen
  Cc: Andrew Morton, Pallipadi, Venkatesh, linux-kernel, jun.nakajima


On Fri, 29 Aug 2003, Erik Andersen wrote:
> 
> gcc then generates code calling __udivdi3 and __umoddi3.  Since
> the kernel does not provide these, people keep reinventing them.
> Perhaps it is time to kill off do_div and all its little friends
> and simply copy __udivdi3 and __umoddi3 from libgcc.....

No. do_div() does _nothing_ like __udivdi3/__umoddi3.

Read the documentation.


		Linus


^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
@ 2003-08-30 16:26 Pallipadi, Venkatesh
  0 siblings, 0 replies; 15+ messages in thread
From: Pallipadi, Venkatesh @ 2003-08-30 16:26 UTC (permalink / raw)
  To: David.Mosberger; +Cc: linux-kernel


> -----Original Message-----
> From: David Mosberger-Tang [mailto:davidm@mostang.com]
> >>>>> On Fri, 29 Aug 2003 09:12:52 -0700, "Pallipadi, 
> Venkatesh" <venkatesh.pallipadi@intel.com> said:
> 
>   Venkatesh> The part of the patch that does the HPET initialization
>   Venkatesh> for timer interrupt, and general HPET registers
>   Venkatesh> read/write/programming can be common across
>   Venkatesh> architectures.  However, different archs diverge, when it
>   Venkatesh> comes to gettimeofday-timer implementation (tsc, pit,
>   Venkatesh> itc, hpet, ) and we may still have to keep that part
>   Venkatesh> architecture specific.
> 
> Is the time_interpolator interface provided by timex.h sufficient for
> HPET timer-interrupt needs?  I think It ought to be.  If so, perhaps
> all that's missing is that x86 needs to be switched over to that
> interface?
> 

timer_interpolator kind of interface helps for one part of HPET changes.
That is using HPET during gettimeofday(). Unfortunately, i386 has its
own timer infrastructure (which is quite similar to timer_interpolator),
which is already being used by variety of timers that exist (cyclone_timer,
tsc, pit - code under arch/i386/kernel/timers). i386 timers seems to be 
the superset of timer_interpolator.
struct timer_opts{
        int (*init)(char *override);
        void (*mark_offset)(void);
        unsigned long (*get_offset)(void);
        unsigned long long (*monotonic_clock)(void);
        void (*delay)(unsigned long);
};
I agree, in future, it is best to integrate these timers in an 
architecture independent way. 

The other part of HPET change is, change in kernel base timer. In i386, 
along with local APIC timer interrupts, we also have a IRQ0 timer interrupt.
This is where kernel time-keeping happens (similar to TIME_KEEPER_ID in IPF).
This will also used for process times in UP case, when there is no LAPIC.
As of now this interrupt comes from PIT/8254. HPET will replace this too, 
and can be programmed to generate periodic interrupts at a particular rate.
This part may be specific to i386.


Thanks,
-Venkatesh


^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
@ 2003-08-29 23:58 Pallipadi, Venkatesh
  2003-09-05 22:26 ` George Anzinger
  0 siblings, 1 reply; 15+ messages in thread
From: Pallipadi, Venkatesh @ 2003-08-29 23:58 UTC (permalink / raw)
  To: Andrew Morton; +Cc: torvalds, linux-kernel, Nakajima, Jun

[-- Attachment #1: Type: text/plain, Size: 1256 bytes --]




> -----Original Message-----
> From: Andrew Morton [mailto:akpm@osdl.org] 
> 
> We seem to keep on proliferating home-grown x86 64-bit math functions.
> 
> Do you really need these?  Is it possible to use do_div() and 
> the C 64x64
> `*' operator instead?
> 


We can change these handcoded 64 bit divs to do_div, with just an
additional data copy 
(as do_div changes dividend in place). But, changing mul into 64x64 '*'
may be tricky. 
Gcc seem to generate a combination of mul, 2imul and add, where as we
are happy with 
using only one mull here.

> 
> I'd like the rtc emulation patch to be redone to remove the 
> ifdefs please,
> they're a real eyesore.
> 
> At the top of rtc.c, do something like this:
> 
> #ifndef CONFIG_HPET_EMULATE_RTC
> #define is_hpet_enabled() 0
> #define hpet_set_alarm_time(hrs, min, sec) 0
> #define hpet_set_periodic_freq(arg) 0
> static inline int hpet_mask_rtc_irq_bit(int arg) { return 0; }
> #define hpet_rtc_timer_init() do { } while (0)
> #define hpet_rtc_dropped_irq() 0
> #endif
> 
> And then all those eleven ifdefs can be removed from rtc.c.


Yes. That surely makes the patch lot more cleaner. Attached is the
updated rtc 
emulation patch.

Thanks,
-Venkatesh

[-- Attachment #2: hpet06_new.patch --]
[-- Type: application/octet-stream, Size: 14753 bytes --]

diff -purN linux-2.6.0-test4-hpetnortc/arch/i386/kernel/time_hpet.c linux-2.6.0-test4-hpet/arch/i386/kernel/time_hpet.c
--- linux-2.6.0-test4-hpetnortc/arch/i386/kernel/time_hpet.c	2003-08-29 17:56:48.000000000 -0700
+++ linux-2.6.0-test4-hpet/arch/i386/kernel/time_hpet.c	2003-08-28 16:20:50.000000000 -0700
@@ -168,4 +168,225 @@ static int __init hpet_setup(char* str)
 
 __setup("hpet=", hpet_setup);
 
+#ifdef CONFIG_HPET_EMULATE_RTC
+/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET 
+ * is enabled, we support RTC interrupt functionality in software. 
+ * RTC has 3 kinds of interrupts:
+ * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
+ *    is updated
+ * 2) Alarm Interrupt - generate an interrupt at a specific time of day
+ * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
+ *    2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
+ * (1) and (2) above are implemented using polling at a frequency of 
+ * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
+ * overhead. (DEFAULT_RTC_INT_FREQ)
+ * For (3), we use interrupts at 64Hz or user specified periodic 
+ * frequency, whichever is higher.
+ */
+#include <linux/mc146818rtc.h>
+#include <linux/rtc.h>
+
+extern irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+extern void get_rtc_time(struct rtc_time *rtc_tm);
+
+#define DEFAULT_RTC_INT_FREQ 	64
+#define RTC_NUM_INTS 		1
+
+static unsigned long UIE_on;
+static unsigned long prev_update_sec;
+
+static unsigned long AIE_on;
+static struct rtc_time alarm_time;
+
+static unsigned long PIE_on;
+static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
+static unsigned long PIE_count;
+
+static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
+
+/*
+ * Timer 1 for RTC, we do not use periodic interrupt feature, 
+ * even if HPET supports periodic interrupts on Timer 1.
+ * The reason being, to set up a periodic interrupt in HPET, we need to 
+ * stop the main counter. And if we do that everytime someone diables/enables
+ * RTC, we will have adverse effect on main kernel timer running on Timer 0.
+ * So, for the time being, simulate the periodic interrupt in software.
+ * 
+ * hpet_rtc_timer_init() is called for the first time and during subsequent 
+ * interuppts reinit happens through hpet_rtc_timer_reinit().
+ */
+int hpet_rtc_timer_init(void)
+{
+	unsigned int cfg, cnt;
+	unsigned long flags;
+
+	if (!is_hpet_enabled())
+		return 0;
+	/*
+	 * Set the counter 1 and enable the interrupts.
+	 */
+	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
+		hpet_rtc_int_freq = PIE_freq;
+	else
+		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
+
+	local_irq_save(flags);
+	cnt = hpet_readl(HPET_COUNTER);
+	cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
+	hpet_writel(cnt, HPET_T1_CMP);
+	local_irq_restore(flags);
+
+	cfg = hpet_readl(HPET_T1_CFG);
+	cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT;
+	hpet_writel(cfg, HPET_T1_CFG);
+
+	return 1;
+}
+
+static void hpet_rtc_timer_reinit(void)
+{
+	unsigned int cfg, cnt;
+
+	if (!(PIE_on | AIE_on | UIE_on))
+		return;
+
+	if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
+		hpet_rtc_int_freq = PIE_freq;
+	else
+		hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
+
+	/* It is more accurate to use the comparator value than current count.*/
+	cnt = hpet_readl(HPET_T1_CMP);
+	cnt += hpet_tick*HZ/hpet_rtc_int_freq;
+	hpet_writel(cnt, HPET_T1_CMP);
+
+	cfg = hpet_readl(HPET_T1_CFG);
+	cfg |= HPET_TN_ENABLE | HPET_TN_SETVAL | HPET_TN_32BIT;
+	hpet_writel(cfg, HPET_T1_CFG);
+
+	return;
+}
+
+/* 
+ * The functions below are called from rtc driver. 
+ * Return 0 if HPET is not being used.
+ * Otherwise do the necessary changes and return 1.
+ */
+int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	if (bit_mask & RTC_UIE)
+		UIE_on = 0;
+	if (bit_mask & RTC_PIE)
+		PIE_on = 0;
+	if (bit_mask & RTC_AIE)
+		AIE_on = 0;
+
+	return 1;
+}
+
+int hpet_set_rtc_irq_bit(unsigned long bit_mask)
+{
+	int timer_init_reqd = 0;
+
+	if (!is_hpet_enabled())
+		return 0;
+
+	if (!(PIE_on | AIE_on | UIE_on))
+		timer_init_reqd = 1;
+
+	if (bit_mask & RTC_UIE) {
+		UIE_on = 1;
+	}
+	if (bit_mask & RTC_PIE) {
+		PIE_on = 1;
+		PIE_count = 0;
+	}
+	if (bit_mask & RTC_AIE) {
+		AIE_on = 1;
+	}
+
+	if (timer_init_reqd)
+		hpet_rtc_timer_init();
+
+	return 1;
+}
+
+int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	alarm_time.tm_hour = hrs;
+	alarm_time.tm_min = min;
+	alarm_time.tm_sec = sec;
+
+	return 1;
+}
+
+int hpet_set_periodic_freq(unsigned long freq)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	PIE_freq = freq;
+	PIE_count = 0;
+
+	return 1;
+}
+
+int hpet_rtc_dropped_irq(void)
+{
+	if (!is_hpet_enabled())
+		return 0;
+
+	return 1;
+}
+
+irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct rtc_time curr_time;
+	unsigned long rtc_int_flag = 0;
+	int call_rtc_interrupt = 0;
+
+	hpet_rtc_timer_reinit();
+
+	if (UIE_on | AIE_on) {
+		get_rtc_time(&curr_time);
+	}
+	if (UIE_on) {
+		if (curr_time.tm_sec != prev_update_sec) {
+			/* Set update int info, call real rtc int routine */
+			call_rtc_interrupt = 1;
+			rtc_int_flag = RTC_UF;
+			prev_update_sec = curr_time.tm_sec;
+		}
+	}
+	if (PIE_on) {
+		PIE_count++;
+		if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
+			/* Set periodic int info, call real rtc int routine */
+			call_rtc_interrupt = 1;
+			rtc_int_flag |= RTC_PF;
+			PIE_count = 0;
+		}
+	}
+	if (AIE_on) {
+		if ((curr_time.tm_sec == alarm_time.tm_sec) &&
+		    (curr_time.tm_min == alarm_time.tm_min) &&
+		    (curr_time.tm_hour == alarm_time.tm_hour)) {
+			/* Set alarm int info, call real rtc int routine */
+			call_rtc_interrupt = 1;
+			rtc_int_flag |= RTC_AF;
+		}
+	}
+	if (call_rtc_interrupt) {
+		rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
+		rtc_interrupt(rtc_int_flag, dev_id, regs);
+	}
+	return IRQ_HANDLED;
+}
+#endif
 
diff -purN linux-2.6.0-test4-hpetnortc/drivers/char/rtc.c linux-2.6.0-test4-hpet/drivers/char/rtc.c
--- linux-2.6.0-test4-hpetnortc/drivers/char/rtc.c	2003-08-29 17:56:48.000000000 -0700
+++ linux-2.6.0-test4-hpet/drivers/char/rtc.c	2003-08-29 17:06:24.000000000 -0700
@@ -44,10 +44,12 @@
  *      1.11    Takashi Iwai: Kernel access functions
  *			      rtc_register/rtc_unregister/rtc_control
  *      1.11a   Daniele Bellucci: Audit create_proc_read_entry in rtc_init
+ *	1.12	Venkatesh Pallipadi: Hooks for emulating rtc on HPET base-timer
+ *		CONFIG_HPET_EMULATE_RTC
  *
  */
 
-#define RTC_VERSION		"1.11a"
+#define RTC_VERSION		"1.12"
 
 #define RTC_IO_EXTENT	0x8
 
@@ -80,6 +82,10 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#if defined(__i386__)
+#include <asm/hpet.h>
+#endif
+
 #ifdef __sparc__
 #include <linux/pci.h>
 #include <asm/ebus.h>
@@ -95,6 +101,17 @@ static int rtc_irq = PCI_IRQ_NONE;
 static int rtc_has_irq = 1;
 #endif
 
+#ifndef CONFIG_HPET_EMULATE_RTC
+#define is_hpet_enabled()			0
+#define hpet_set_alarm_time(hrs, min, sec) 	0
+#define hpet_set_periodic_freq(arg) 		0
+#define hpet_mask_rtc_irq_bit(arg) 		0
+#define hpet_set_rtc_irq_bit(arg) 		0
+#define hpet_rtc_timer_init() 			do { } while (0)
+#define hpet_rtc_dropped_irq() 			0
+static inline irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) {return 0;}
+#endif
+
 /*
  *	We sponge a minor off of the misc major. No need slurping
  *	up another valuable major dev number for this. If you add
@@ -120,7 +137,7 @@ static int rtc_ioctl(struct inode *inode
 static unsigned int rtc_poll(struct file *file, poll_table *wait);
 #endif
 
-static void get_rtc_time (struct rtc_time *rtc_tm);
+void get_rtc_time (struct rtc_time *rtc_tm);
 static void get_rtc_alm_time (struct rtc_time *alm_tm);
 #if RTC_IRQ
 static void rtc_dropped_irq(unsigned long data);
@@ -182,7 +199,7 @@ static const unsigned char days_in_mo[] 
  *	(See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
  */
 
-static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/*
 	 *	Can be an alarm interrupt, update complete interrupt,
@@ -194,7 +211,16 @@ static irqreturn_t rtc_interrupt(int irq
 	spin_lock (&rtc_lock);
 	rtc_irq_data += 0x100;
 	rtc_irq_data &= ~0xff;
-	rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
+	if (is_hpet_enabled()) {
+		/*
+		 * In this case it is HPET RTC interrupt handler
+		 * calling us, with the interrupt information
+		 * passed as arg1, instead of irq.
+		 */
+		rtc_irq_data |= (unsigned long)irq & 0xF0;
+	} else {
+		rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
+	}
 
 	if (rtc_status & RTC_TIMER_ON)
 		mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
@@ -429,6 +455,12 @@ static int rtc_do_ioctl(unsigned int cmd
 		sec = alm_tm.tm_sec;
 
 		spin_lock_irq(&rtc_lock);
+		if (hpet_set_alarm_time(hrs, min, sec)) {
+			/*
+			 * Fallthru and set alarm time in CMOS too, 
+			 * so that we will get proper value in RTC_ALM_READ
+			 */
+		}
 		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
 		    RTC_ALWAYS_BCD)
 		{
@@ -582,6 +614,10 @@ static int rtc_do_ioctl(unsigned int cmd
 			return -EINVAL;
 
 		spin_lock_irq(&rtc_lock);
+		if (hpet_set_periodic_freq(arg)) {
+			spin_unlock_irq(&rtc_lock);
+			return 0;
+		}
 		rtc_freq = arg;
 
 		val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
@@ -667,13 +703,14 @@ static int rtc_release(struct inode *ino
 	 */
 
 	spin_lock_irq(&rtc_lock);
-	tmp = CMOS_READ(RTC_CONTROL);
-	tmp &=  ~RTC_PIE;
-	tmp &=  ~RTC_AIE;
-	tmp &=  ~RTC_UIE;
-	CMOS_WRITE(tmp, RTC_CONTROL);
-	CMOS_READ(RTC_INTR_FLAGS);
-
+	if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) {
+		tmp = CMOS_READ(RTC_CONTROL);
+		tmp &=  ~RTC_PIE;
+		tmp &=  ~RTC_AIE;
+		tmp &=  ~RTC_UIE;
+		CMOS_WRITE(tmp, RTC_CONTROL);
+		CMOS_READ(RTC_INTR_FLAGS);
+	}
 	if (rtc_status & RTC_TIMER_ON) {
 		rtc_status &= ~RTC_TIMER_ON;
 		del_timer(&rtc_irq_timer);
@@ -765,12 +802,14 @@ int rtc_unregister(rtc_task_t *task)
 	rtc_callback = NULL;
 	
 	/* disable controls */
-	tmp = CMOS_READ(RTC_CONTROL);
-	tmp &= ~RTC_PIE;
-	tmp &= ~RTC_AIE;
-	tmp &= ~RTC_UIE;
-	CMOS_WRITE(tmp, RTC_CONTROL);
-	CMOS_READ(RTC_INTR_FLAGS);
+	if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) {
+		tmp = CMOS_READ(RTC_CONTROL);
+		tmp &= ~RTC_PIE;
+		tmp &= ~RTC_AIE;
+		tmp &= ~RTC_UIE;
+		CMOS_WRITE(tmp, RTC_CONTROL);
+		CMOS_READ(RTC_INTR_FLAGS);
+	}
 	if (rtc_status & RTC_TIMER_ON) {
 		rtc_status &= ~RTC_TIMER_ON;
 		del_timer(&rtc_irq_timer);
@@ -822,6 +861,10 @@ static struct miscdevice rtc_dev=
 	&rtc_fops
 };
 
+#if RTC_IRQ
+static irqreturn_t (*rtc_int_handler_ptr)(int irq, void *dev_id, struct pt_regs *regs);
+#endif
+
 static int __init rtc_init(void)
 {
 #if defined(__alpha__) || defined(__mips__)
@@ -889,12 +932,20 @@ no_irq:
 	}
 
 #if RTC_IRQ
-	if (request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL)) {
+	if (is_hpet_enabled()) {
+		rtc_int_handler_ptr = hpet_rtc_interrupt;
+	} else {
+		rtc_int_handler_ptr = rtc_interrupt;
+	}
+
+	if(request_irq(RTC_IRQ, rtc_int_handler_ptr, SA_INTERRUPT, "rtc", NULL)) {
 		/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
 		printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
 		release_region(RTC_PORT(0), RTC_IO_EXTENT);
 		return -EIO;
 	}
+	hpet_rtc_timer_init();
+
 #endif
 
 #endif /* __sparc__ vs. others */
@@ -965,10 +1016,12 @@ no_irq:
 	init_timer(&rtc_irq_timer);
 	rtc_irq_timer.function = rtc_dropped_irq;
 	spin_lock_irq(&rtc_lock);
-	/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
-	CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
-	spin_unlock_irq(&rtc_lock);
 	rtc_freq = 1024;
+	if (!hpet_set_periodic_freq(rtc_freq)) {
+		/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
+		CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
+	}
+	spin_unlock_irq(&rtc_lock);
 no_irq2:
 #endif
 
@@ -1019,6 +1072,11 @@ static void rtc_dropped_irq(unsigned lon
 
 	spin_lock_irq (&rtc_lock);
 
+	if (hpet_rtc_dropped_irq()) {
+		spin_unlock_irq(&rtc_lock);
+		return;
+	}
+
 	/* Just in case someone disabled the timer from behind our back... */
 	if (rtc_status & RTC_TIMER_ON)
 		mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
@@ -1148,7 +1206,7 @@ static inline unsigned char rtc_is_updat
 	return uip;
 }
 
-static void get_rtc_time(struct rtc_time *rtc_tm)
+void get_rtc_time(struct rtc_time *rtc_tm)
 {
 	unsigned long uip_watchdog = jiffies;
 	unsigned char ctrl;
@@ -1254,6 +1312,10 @@ static void mask_rtc_irq_bit(unsigned ch
 	unsigned char val;
 
 	spin_lock_irq(&rtc_lock);
+	if (hpet_mask_rtc_irq_bit(bit)) {
+		spin_unlock_irq(&rtc_lock);
+		return;
+	}
 	val = CMOS_READ(RTC_CONTROL);
 	val &=  ~bit;
 	CMOS_WRITE(val, RTC_CONTROL);
@@ -1268,6 +1330,10 @@ static void set_rtc_irq_bit(unsigned cha
 	unsigned char val;
 
 	spin_lock_irq(&rtc_lock);
+	if (hpet_set_rtc_irq_bit(bit)) {
+		spin_unlock_irq(&rtc_lock);
+		return;
+	}
 	val = CMOS_READ(RTC_CONTROL);
 	val |= bit;
 	CMOS_WRITE(val, RTC_CONTROL);
diff -purN linux-2.6.0-test4-hpetnortc/include/asm-i386/hpet.h linux-2.6.0-test4-hpet/include/asm-i386/hpet.h
--- linux-2.6.0-test4-hpetnortc/include/asm-i386/hpet.h	2003-08-29 17:56:48.000000000 -0700
+++ linux-2.6.0-test4-hpet/include/asm-i386/hpet.h	2003-08-28 16:20:50.000000000 -0700
@@ -102,5 +102,15 @@ extern int is_hpet_capable(void);
 extern int hpet_readl(unsigned long a);
 extern void hpet_writel(unsigned long d, unsigned long a);
 
+#ifdef CONFIG_RTC
+#define CONFIG_HPET_EMULATE_RTC 	1
+extern int hpet_mask_rtc_irq_bit(unsigned long bit_mask);
+extern int hpet_set_rtc_irq_bit(unsigned long bit_mask);
+extern int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec);
+extern int hpet_set_periodic_freq(unsigned long freq);
+extern int hpet_rtc_dropped_irq(void);
+extern int hpet_rtc_timer_init(void);
+extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+#endif /* CONFIG_RTC */
 #endif /* CONFIG_HPET_TIMER */
 #endif /* _I386_HPET_H */
diff -purN linux-2.6.0-test4-hpetnortc/include/asm-i386/mc146818rtc.h linux-2.6.0-test4-hpet/include/asm-i386/mc146818rtc.h
--- linux-2.6.0-test4-hpetnortc/include/asm-i386/mc146818rtc.h	2003-08-29 17:56:48.000000000 -0700
+++ linux-2.6.0-test4-hpet/include/asm-i386/mc146818rtc.h	2003-08-28 16:20:50.000000000 -0700
@@ -24,10 +24,6 @@ outb_p((addr),RTC_PORT(0)); \
 outb_p((val),RTC_PORT(1)); \
 })
 
-#ifdef CONFIG_HPET_TIMER
-#define RTC_IRQ 0
-#else
 #define RTC_IRQ 8
-#endif
 
 #endif /* _ASM_MC146818RTC_H */

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-29 18:23 ` Andrew Morton
@ 2003-08-29 21:03   ` Erik Andersen
  2003-08-31 21:05     ` Linus Torvalds
  2003-09-05 22:19     ` George Anzinger
  0 siblings, 2 replies; 15+ messages in thread
From: Erik Andersen @ 2003-08-29 21:03 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Pallipadi, Venkatesh, torvalds, linux-kernel, jun.nakajima

On Fri Aug 29, 2003 at 11:23:47AM -0700, Andrew Morton wrote:
> "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> wrote:
> >
> > Resending the patch.
> 
> Thanks, I'll include these in the next -mm kernel.
> 
> Reading the code, the only thing which leaps out is:
> 
> +/* Use our own asm for 64 bit multiply/divide */
> +#define ASM_MUL64_REG(eax_out,edx_out,reg_in,eax_in) 			\
> +		__asm__ __volatile__("mull %2" 				\
> +				:"=a" (eax_out), "=d" (edx_out) 	\
> +				:"r" (reg_in), "0" (eax_in))
> +
> +#define ASM_DIV64_REG(eax_out,edx_out,reg_in,eax_in,edx_in) 		\
> +		__asm__ __volatile__("divl %2" 				\
> +				:"=a" (eax_out), "=d" (edx_out) 	\
> +				:"r" (reg_in), "0" (eax_in), "1" (edx_in))
> 
> We seem to keep on proliferating home-grown x86 64-bit math functions.
> 
> Do you really need these?  Is it possible to use do_div() and the C 64x64
> `*' operator instead?


The fundamental reason these are proliferating is that given
some random bit of code such as:

    u64 foo=9, bar=3, baz;
    baz = foo / bar;
    baz = foo % bar;

gcc then generates code calling __udivdi3 and __umoddi3.  Since
the kernel does not provide these, people keep reinventing them.
Perhaps it is time to kill off do_div and all its little friends
and simply copy __udivdi3 and __umoddi3 from libgcc.....

 -Erik

--
Erik B. Andersen             http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
  2003-08-28 23:41 Pallipadi, Venkatesh
@ 2003-08-29 18:23 ` Andrew Morton
  2003-08-29 21:03   ` Erik Andersen
  0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2003-08-29 18:23 UTC (permalink / raw)
  To: Pallipadi, Venkatesh; +Cc: torvalds, linux-kernel, jun.nakajima

"Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> wrote:
>
> Resending the patch.

Thanks, I'll include these in the next -mm kernel.

Reading the code, the only thing which leaps out is:

+/* Use our own asm for 64 bit multiply/divide */
+#define ASM_MUL64_REG(eax_out,edx_out,reg_in,eax_in) 			\
+		__asm__ __volatile__("mull %2" 				\
+				:"=a" (eax_out), "=d" (edx_out) 	\
+				:"r" (reg_in), "0" (eax_in))
+
+#define ASM_DIV64_REG(eax_out,edx_out,reg_in,eax_in,edx_in) 		\
+		__asm__ __volatile__("divl %2" 				\
+				:"=a" (eax_out), "=d" (edx_out) 	\
+				:"r" (reg_in), "0" (eax_in), "1" (edx_in))

We seem to keep on proliferating home-grown x86 64-bit math functions.

Do you really need these?  Is it possible to use do_div() and the C 64x64
`*' operator instead?


I'd like the rtc emulation patch to be redone to remove the ifdefs please,
they're a real eyesore.

At the top of rtc.c, do something like this:

#ifndef CONFIG_HPET_EMULATE_RTC
#define is_hpet_enabled() 0
#define hpet_set_alarm_time(hrs, min, sec) 0
#define hpet_set_periodic_freq(arg) 0
static inline int hpet_mask_rtc_irq_bit(int arg) { return 0; }
#define hpet_rtc_timer_init() do { } while (0)
#define hpet_rtc_dropped_irq() 0
#endif

And then all those eleven ifdefs can be removed from rtc.c.

Thanks.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
       [not found] <pEGJ.73p.5@gated-at.bofh.it>
@ 2003-08-29  3:40 ` David Mosberger-Tang
  0 siblings, 0 replies; 15+ messages in thread
From: David Mosberger-Tang @ 2003-08-29  3:40 UTC (permalink / raw)
  To: Pallipadi, Venkatesh; +Cc: linux-kernel

>>>>> On Fri, 29 Aug 2003 01:50:09 +0200, "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com> said:

  Venkatesh> Resending the patch. A major change from previous version
  Venkatesh> is elimination of fixmap for HPET. Based on Andrew
  Venkatesh> Morton's suggestion, we have a new hook in init/main.c
  Venkatesh> for late_time_init(), at which time we can use ioremap,
  Venkatesh> in place of fixmap.  Impact on other archs:
  Venkatesh> Calibrate_delay() (and hence loops_per_jiffy calculation)
  Venkatesh> has moved down in main.c, from after time_init() to after
  Venkatesh> kmem_cache_init().

  Venkatesh> All comments/feedbacks welcome.

How much is really architecture-specific?  HPET isn't x86-only so
sooner or later, we'll have to move it out of arch/i386 anyhow.

	--david

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2
@ 2003-08-28 23:41 Pallipadi, Venkatesh
  2003-08-29 18:23 ` Andrew Morton
  0 siblings, 1 reply; 15+ messages in thread
From: Pallipadi, Venkatesh @ 2003-08-28 23:41 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, Nakajima, Jun



Resending the patch. A major change from previous version is
elimination of fixmap for HPET. Based on Andrew Morton's suggestion, 
we have a new hook in init/main.c for late_time_init(), at which 
time we can use ioremap, in place of fixmap.
Impact on other archs: Calibrate_delay() (and hence loops_per_jiffy
calculation) has moved down in main.c, from after time_init() 
to after kmem_cache_init().


Patchset description:
1/6 - hpet1.patch - main.c change to introduce late_time_init()
2/6 - hpet2.patch - acpi boot time parsing changes to look for HPET
3/6 - hpet3.patch - Miscallaneous makefile and config changes
4/6 - hpet4.patch - All the changes required to use HPET in place
                    of PIT as the kernel base-timer at IRQ 0.
5/6 - hpet5.patch - All changes required to support timer services
                    (gettimeofday) with HPET. There are two options:
                    - Use HPET for gettimeofday.
                    - Use rdtsc for gettimeofday.
                    rdtsc is still faster then HPET reads, but HPET
                    has advantage that its rate remain same,
                    irrespective of CPU frequency. Also, HPET is
                    more scalable than TSC in case of multi-node
                    systems. So, our timer priority is
                    platform_specific_timer(if any), timer_hpet
                    and timer_tsc in that order.
6/6 - hpet6.patch - This can be a standalone patch. Without this
                    patch we loose interrupt generation capability
                    of RTC (/dev/rtc), due to HPET. With this patch
                    we basically try to emulate RTC interrupt
                    functions in software using HPET counter 1.
                    This is only required to provide compatibility
                    to the applications that depend on rtc driver's
                    interrupt generation capability.
                    This emulation will not be as accurate as RTC
                    interrupt, as HPET is not tied to RTC hardware
                    and does not know anything about RTC time.
                    But should enough for compatibility purposes.

All comments/feedbacks welcome.

Thanks,
-Venkatesh


HPET Description
High Precision Event Timer (HPET) is next generation timer
hardware and has various advantages over legacy 8254
(PIT) timer, like:
- Associated registers are mapped to memory space. So, we no
  longer require in and out on legacy ioports
- Memory map address is reported by ACPI (and are not
  hard-coded)
- Each timer can be configured to generate separate interrupts,
  even sharing lines with PCI devices
- HPET has a minimum period of 100 nanosecs and is not fixed.
  Giving a flexibility of increasing the resolution in future.
- Most current implementations has 3 counters, but in future,
  we can have as many as 32 timers per block, and 8
  HPET timer blocks (total 256 timers)
- Can support 32bit and 64bit counting

(Refer to http://www.intel.com/labs/platcomp/hpet/hpetspec.htm
 for complete specs)

The patchset that follow adds support for High Precision Event
Timer (HPET) based timer in kernel. This uses the HPET in
LegacyReplacement mode (so that counter 0 will be tied to IRQ0,
and counter 1 will be tied to IRQ 8). In this mode, HPET overrides
PIT and RTC interrupt lines. The patch will enable HPET by default,
on systems where ACPI tables reports this feature. The patch will
have no impact on systems that do not support this feature.



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2003-09-07 17:57 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-08-29 16:12 [PATCHSET][2.6-test4][0/6]Support for HPET based timer - Take 2 Pallipadi, Venkatesh
2003-08-30  4:59 ` David Mosberger-Tang
  -- strict thread matches above, loose matches on Subject: below --
2003-09-06 19:04 Pallipadi, Venkatesh
2003-09-07 17:57 ` George Anzinger
2003-08-30 16:26 Pallipadi, Venkatesh
2003-08-29 23:58 Pallipadi, Venkatesh
2003-09-05 22:26 ` George Anzinger
     [not found] <pEGJ.73p.5@gated-at.bofh.it>
2003-08-29  3:40 ` David Mosberger-Tang
2003-08-28 23:41 Pallipadi, Venkatesh
2003-08-29 18:23 ` Andrew Morton
2003-08-29 21:03   ` Erik Andersen
2003-08-31 21:05     ` Linus Torvalds
2003-08-31 22:24       ` Erik Andersen
2003-08-31 22:48         ` Linus Torvalds
2003-09-05 22:19     ` George Anzinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).