linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Alexander Gordeev <lasaine@lvk.cs.msu.su>
To: john stultz <johnstul@us.ibm.com>
Cc: linux-kernel@vger.kernel.org, linuxpps@ml.enneenne.com,
	"Nikita V. Youshchenko" <yoush@cs.msu.su>,
	stas@lvk.cs.msu.su, Rodolfo Giometti <giometti@enneenne.com>,
	Rodolfo Giometti <giometti@linux.it>,
	Andrew Morton <akpm@linux-foundation.org>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>, Ingo Molnar <mingo@elte.hu>,
	Thomas Gleixner <tglx@linutronix.de>,
	Rik van Riel <riel@redhat.com>
Subject: Re: [PATCH 1/5] ntp: add hardpps implementation
Date: Thu, 4 Feb 2010 02:51:53 +0300	[thread overview]
Message-ID: <20100204025153.52fe962a@lvk.cs.msu.su> (raw)
In-Reply-To: <1265234930.3255.54.camel@work-vm>

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

Thanks for the review!

В Wed, 03 Feb 2010 14:08:50 -0800
john stultz <johnstul@us.ibm.com> пишет:

> On Wed, 2010-02-03 at 23:56 +0300, Alexander Gordeev wrote:
> > This commit adds hardpps() implementation based upon the original
> > one from the NTPv4 reference kernel code. However, it is highly
> > optimized towards very fast syncronization and maximum stickness to
> > PPS signal. The typical error is less then a microsecond.
> > To make it sync faster I had to throw away exponential phase filter
> > so that the full phase offset is corrected immediately. Then I also
> > had to throw away median phase filter because it gives a bigger
> > error itself if used without exponential filter.
> > Maybe we will find an appropriate filtering scheme in the future but
> > it's not necessary if the signal quality is ok.
> > 
> > Signed-off-by: Alexander Gordeev <lasaine@lvk.cs.msu.su>
> 
> Very cool! Bunch of style comments below.
> 
> One other thing: From the comments in the code, it looks like this may
> have come straight from the reference implementation. You might want
> to provide some extra documentation or comment providing proper
> credit, and clarifying that the code is in fact GPLv2 compatible. 
> 
> Also please review Section 12 of Documentation/SubmittingPatches 

Indeed, this code is a direct descendant of the reference
implementation. However it is mostly rewritten because the original
code was too hard to read. But I thought it is not an issue because the
whole ntp.c seems to have a lot of code from it... Well, I'm not quite
good in license compatibility. :)

Here is the copyright notice from the original code for reference:
/***********************************************************************
 *                                                                     *
 * Copyright (c) David L. Mills 1993-2001                              *
 *                                                                     *
 * Permission to use, copy, modify, and distribute this software and   *
 * its documentation for any purpose and without fee is hereby         *
 * granted, provided that the above copyright notice appears in all    *
 * copies and that both the copyright notice and this permission       *
 * notice appear in supporting documentation, and that the name        *
 * University of Delaware not be used in advertising or publicity      *
 * pertaining to distribution of the software without specific,        *
 * written prior permission. The University of Delaware makes no       *
 * representations about the suitability this software for any         *
 * purpose. It is provided "as is" without express or implied          *
 * warranty.                                                           *
 *                                                                     *
 **********************************************************************/

Maybe adding a comment like the one above second_overflow() is enough?


> [snip]
> > +long pps_tf[3];			/* phase median filter */
> > +s64 pps_freq;			/* scaled frequency offset
> > (ns/s) */ +s64 pps_fcount;			/* frequency
> > accumulator */ +long pps_jitter;		/* nominal jitter
> > (ns) */ +long pps_stabil;		/* nominal stability
> > (scaled ns/s) */ +int pps_valid;			/* signal
> > watchdog counter */ +int pps_shift;			/*
> > nominal interval duration (s) (shift) */ +int
> > pps_shiftmax;		/* max interval duration (s) (shift)
> > */ +int pps_intcnt;			/* interval counter */ +
> > +/*
> > + * PPS signal quality monitors
> > + */
> > +long pps_calcnt;		/* calibration intervals */
> > +long pps_jitcnt;		/* jitter limit exceeded */
> > +long pps_stbcnt;		/* stability limit exceeded */
> > +long pps_errcnt;		/* calibration errors */
> > +
> 
> Shouldn't all of the above values be made static?

Sure, thanks.

> [snip]
> 
> >  /*
> > @@ -233,8 +277,6 @@ static enum hrtimer_restart
> > ntp_leap_second(struct hrtimer *timer) */
> >  void second_overflow(void)
> >  {
> > -	s64 delta;
> > -
> >  	/* Bump the maxerror field */
> >  	time_maxerror += MAXFREQ / NSEC_PER_USEC;
> >  	if (time_maxerror > NTP_PHASE_LIMIT) {
> > @@ -248,9 +290,27 @@ void second_overflow(void)
> >  	 */
> >  	tick_length	 = tick_length_base;
> > 
> > -	delta		 = shift_right(time_offset, SHIFT_PLL
> > + time_constant);
> > -	time_offset	-= delta;
> > -	tick_length	+= delta;
> > +#ifdef CONFIG_NTP_PPS
> > +	if (time_status & STA_PPSTIME && time_status &
> > STA_PPSSIGNAL) {
> > +		tick_length	+= time_offset;
> > +		time_offset	 = 0;
> > +	} else
> > +#endif /* CONFIG_NTP_PPS */
> > +	{
> > +		s64 delta;
> > +		delta		 =
> > +			shift_right(time_offset, SHIFT_PLL +
> > time_constant);
> > +		time_offset	-= delta;
> > +		tick_length	+= delta;
> > +	}
> 
> 
> Ugh. Surely there's a better way to do this then using the ifdefs in
> code? 
> 
> Maybe something like:
> 
> #ifdef CONFIG_NTP_PPS
> /* Comment about how pps consumes the whole offset */
> static inline s64 ntp_offset_chunk(s64 offset)
> {
> 	if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL)
> 		return offset
> 	else
> 		return shift_right(offset, SHIFT_PLL + time_constant);
> }
> #else
> static inline s64 ntp_offset_chunk(s64 offset)
> {
> 	return shift_right(offset, SHIFT_PLL + time_constant);
> }
> #endif
> 
> Then in second_overflow():
> 
> delta		 = ntp_offset_chunk(time_offset);
> time_offset	-= delta;
> tick_length	+= delta;
> 
> Feel free to use a better name then ntp_offset_chunk(), but this keeps
> the logic from being obfuscated by all the #ifdefs
>
> > +#ifdef	CONFIG_NTP_PPS
> > +	if (pps_valid > 0)
> > +		pps_valid--;
> > +	else
> > +		time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
> > +				 STA_PPSWANDER | STA_PPSERROR);
> > +#endif /* CONFIG_NTP_PPS */
> 
> Similarly, can some sort of pps_dec_valid() inline function be used
> here?

Ok, it is better indeed.

> [snip]
> 
> > +#ifdef	CONFIG_NTP_PPS
> > +
> > +/* normalize the timestamp so that nsec is in the
> > +   ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval */
> > +static inline struct timespec pps_normalize_ts(struct timespec ts)
> > +{
> > +	if (ts.tv_nsec > (NSEC_PER_SEC >> 1)) {
> > +		ts.tv_nsec -= NSEC_PER_SEC;
> > +		ts.tv_sec++;
> > +	}
> > +
> > +	return ts;
> > +}
> 
> Hrmm.. So by converting a timespec into a second + [-NSEC_PER_SEC/2,
> NSEC_PER_SEC/2] value, you aren't really using a timespec anymore,
> right? I mean, the timepsec_valid() would fail in many cases, for
> instance.
> 
> I realize its pretty close, and you *can* use a timespec this way, but
> to me it seems reasonable to introduce a new structure (pps_normtime?)
> so that its clear you shouldn't exchange timespec values and
> pps_normtime values directly?
> 
> This is sort of a nit, and maybe others disagree, so not the most
> critical issue. But it seems like you're abusing the structure a bit.

Well, I don't mind adding a structure for this. Seems like timespec
is not expected to be used this way.

> [snip]
> > +/* decrease frequency calibration interval length */
> > +static inline void pps_dec_freq_interval(void)
> > +{
> > +	if (--pps_intcnt <= -4) {
> > +		pps_intcnt = -4;
> 
> Is -4 a magic value?
> 
> [snip]
> > +	} else {	/* good sample */
> > +		if (++pps_intcnt >= 4) {
> > +			pps_intcnt = 4;
> 
> Again, the magic 4?

Yep :)
The values are from the reference implementation. Frequency calculation
is mostly the same as in the original code because it works good.
I'll add a define for these values.

> [snip]
> > +	pps_stabil += (div_s64(((s64)delta_mod) <<
> > +				(NTP_SCALE_SHIFT - SHIFT_USEC),
> > +				NSEC_PER_USEC) - pps_stabil) >>
> > PPS_FAVG;
> 
> Hmm. Two 64bit divides in this path? This code would run each second,
> right? It would probably be good to see if this could be optimized a
> little bit more, but I guess its similar to ntp_update_frequency()
> which is called on adjtimex() calls (every 16 seconds at most with
> networked ntp).

Well, this is not quite right. The interval is at least 4 seconds (1
<< PPS_FAVG) and increases if the signal is good. Maximum interval
length is 256 seconds (1 << PPS_FAVGDEF).
I don't see how it can be optimized right now.

> > +void hardpps(const struct timespec *p_ts, s64 nsec)
> > +{
> > +	struct timespec ts_norm, freq_norm;
> > +
> > +	ts_norm = pps_normalize_ts(*p_ts);
> > +	freq_norm = pps_normalize_ts(ns_to_timespec(nsec));
> > +
> [snip]
> > +
> > +	write_seqlock_irq(&xtime_lock);
> 
> This is called possibly in irq context, right? So you probably want to
> use write_seqlock_irqsave(), no?

Right, thanks, it's bug. However, I think of moving it to a worqueue.

-- 
  Alexander

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

  reply	other threads:[~2010-02-03 23:52 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-03 20:56 [PATCH 0/5] pps: time synchronization over LPT Alexander Gordeev
2010-02-03 20:56 ` [PATCH 1/5] ntp: add hardpps implementation Alexander Gordeev
2010-02-03 22:08   ` john stultz
2010-02-03 23:51     ` Alexander Gordeev [this message]
2010-02-03 20:56 ` [PATCH 2/5] pps: capture MONOTONIC_RAW timestamps as well Alexander Gordeev
2010-02-03 22:26   ` john stultz
2010-02-04 11:05     ` Alexander Gordeev
2010-02-03 20:56 ` [PATCH 3/5] pps: add kernel consumer support Alexander Gordeev
2010-02-03 20:56 ` [PATCH 4/5] pps: add parallel port PPS signal generator Alexander Gordeev
2010-02-05 10:39   ` Rodolfo Giometti
2010-02-06  8:57     ` [LinuxPPS] " Alexander Gordeev
2010-02-03 20:56 ` [PATCH 5/5] pps: add parallel port PPS client Alexander Gordeev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100204025153.52fe962a@lvk.cs.msu.su \
    --to=lasaine@lvk.cs.msu.su \
    --cc=akpm@linux-foundation.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=giometti@enneenne.com \
    --cc=giometti@linux.it \
    --cc=johnstul@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxpps@ml.enneenne.com \
    --cc=mingo@elte.hu \
    --cc=riel@redhat.com \
    --cc=stas@lvk.cs.msu.su \
    --cc=tglx@linutronix.de \
    --cc=yoush@cs.msu.su \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).