From patchwork Tue Jun 15 16:09:46 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Cochran X-Patchwork-Id: 55751 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 7C02510155A for ; Wed, 16 Jun 2010 02:09:01 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754725Ab0FOQI4 (ORCPT ); Tue, 15 Jun 2010 12:08:56 -0400 Received: from mail-fx0-f46.google.com ([209.85.161.46]:43726 "EHLO mail-fx0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754656Ab0FOQIz (ORCPT ); Tue, 15 Jun 2010 12:08:55 -0400 Received: by mail-fx0-f46.google.com with SMTP id 10so266600fxm.19 for ; Tue, 15 Jun 2010 09:08:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:references:mime-version:content-type:content-disposition :in-reply-to:user-agent; bh=im6VGz342FZZ6jPfxToREK3SPMK4XBlYaMav6bdLHWM=; b=EJQitdIoPo2tUR/AM+gdy4Td4mbmw+ghezbF5l0GWLY0TrylSH6vISIUXP+w5U5fh6 9yPU+3wp6mwH0LS42eH7FQE4I49QO/cSOGwKnO+oWiSSX/YM5iz+78bnNGX4Vpmv/gNU AhJwmEWVtiChjfq+VeIq0xu4+yHVxYhv1s7z0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=ilWGmdj9FEB+wA+ruZV9/4+Wqphr/0l1rtmogb5NGWmOEqPBytDOWetmRVZk7LlR2D wWTEQHkJzdeeKPRgGlRNP8bsQOFCKHShpuqb50AF50K9W2/Hr5Qwos4Di5prJPdksY95 c6X/iaqxcBHFLVj4hJ76ZasQWoGMteh2CARxA= Received: by 10.223.21.22 with SMTP id h22mr7470825fab.106.1276618134995; Tue, 15 Jun 2010 09:08:54 -0700 (PDT) Received: from riccoc20.at.omicron.at (vs162244.vserver.de [62.75.162.244]) by mx.google.com with ESMTPS id k5sm10091356faa.46.2010.06.15.09.08.53 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 15 Jun 2010 09:08:54 -0700 (PDT) Date: Tue, 15 Jun 2010 18:09:46 +0200 From: Richard Cochran To: netdev@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, devicetree-discuss@lists.ozlabs.org, Krzysztof Halasa , linux-arm-kernel@lists.infradead.org Subject: [PATCH 09/12] ptp: Added a clock that uses the Linux system time. Message-ID: <2a9d504ab573d8b83137bd16a318940aaac15d7f.1276615626.git.richard.cochran@omicron.at> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-06-14) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This PTP clock simply uses the NTP time adjustment system calls. The driver can be used in systems that lack a special hardware PTP clock. Signed-off-by: Richard Cochran --- drivers/ptp/Kconfig | 12 ++++ drivers/ptp/Makefile | 1 + drivers/ptp/ptp_linux.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++ kernel/time/ntp.c | 2 + 4 files changed, 151 insertions(+), 0 deletions(-) create mode 100644 drivers/ptp/ptp_linux.c diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index c80a25b..9390d44 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -23,4 +23,16 @@ config PTP_1588_CLOCK To compile this driver as a module, choose M here: the module will be called ptp_clock. +config PTP_1588_CLOCK_LINUX + tristate "Linux system timer as PTP clock" + depends on PTP_1588_CLOCK + help + This driver adds support for using the standard Linux time + source as a PTP clock. This clock is only useful if your PTP + programs are using software time stamps for the PTP Ethernet + packets. + + To compile this driver as a module, choose M here: the module + will be called ptp_linux. + endmenu diff --git a/drivers/ptp/Makefile b/drivers/ptp/Makefile index b86695c..1651d52 100644 --- a/drivers/ptp/Makefile +++ b/drivers/ptp/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_PTP_1588_CLOCK) += ptp_clock.o +obj-$(CONFIG_PTP_1588_CLOCK_LINUX) += ptp_linux.o diff --git a/drivers/ptp/ptp_linux.c b/drivers/ptp/ptp_linux.c new file mode 100644 index 0000000..f93ae0c --- /dev/null +++ b/drivers/ptp/ptp_linux.c @@ -0,0 +1,136 @@ +/* + * PTP 1588 clock using the Linux system clock + * + * Copyright (C) 2010 OMICRON electronics GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct ptp_clock *linux_clock; + +DEFINE_SPINLOCK(adjtime_lock); + +static int ptp_linux_adjfreq(void *priv, s32 delta) +{ + struct timex txc; + s64 tmp = delta; + int err; + txc.freq = div_s64(tmp<<16, 1000); + txc.modes = ADJ_FREQUENCY; + err = do_adjtimex(&txc); + return err < 0 ? err : 0; +} + +static int ptp_linux_adjtime(void *priv, struct timespec *ts) +{ + s64 delta; + ktime_t now; + struct timespec t2; + unsigned long flags; + int err; + + delta = 1000000000LL * ts->tv_sec + ts->tv_nsec; + + spin_lock_irqsave(&adjtime_lock, flags); + + now = ktime_get_real(); + + now = delta < 0 ? ktime_sub_ns(now, -delta) : ktime_add_ns(now, delta); + + t2 = ktime_to_timespec(now); + + err = do_settimeofday(&t2); + + spin_unlock_irqrestore(&adjtime_lock, flags); + + return err; +} + +static int ptp_linux_gettime(void *priv, struct timespec *ts) +{ + getnstimeofday(ts); + return 0; +} + +static int ptp_linux_settime(void *priv, struct timespec *ts) +{ + return do_settimeofday(ts); +} + +static int ptp_linux_gettimer(void *priv, int index, struct itimerspec *ts) +{ + /* We do not offer any ancillary features at all. */ + return -EOPNOTSUPP; +} + +static int ptp_linux_settimer(void *p, int i, int abs, struct itimerspec *ts) +{ + /* We do not offer any ancillary features at all. */ + return -EOPNOTSUPP; +} + +static int ptp_linux_enable(void *priv, struct ptp_clock_request *rq, int on) +{ + /* We do not offer any ancillary features at all. */ + return -EOPNOTSUPP; +} + +static struct ptp_clock_info ptp_linux_caps = { + .owner = THIS_MODULE, + .name = "Linux timer", + .max_adj = 512000, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .pps = 0, + .priv = NULL, + .adjfreq = ptp_linux_adjfreq, + .adjtime = ptp_linux_adjtime, + .gettime = ptp_linux_gettime, + .settime = ptp_linux_settime, + .gettimer = ptp_linux_gettimer, + .settimer = ptp_linux_settimer, + .enable = ptp_linux_enable, +}; + +/* module operations */ + +static void __exit ptp_linux_exit(void) +{ + ptp_clock_unregister(linux_clock); +} + +static int __init ptp_linux_init(void) +{ + linux_clock = ptp_clock_register(&ptp_linux_caps); + + return IS_ERR(linux_clock) ? PTR_ERR(linux_clock) : 0; +} + +module_init(ptp_linux_init); +module_exit(ptp_linux_exit); + +MODULE_AUTHOR("Richard Cochran "); +MODULE_DESCRIPTION("PTP clock using the Linux system timer"); +MODULE_LICENSE("GPL"); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index c631168..eba3bcf 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * NTP timekeeping variables: @@ -535,6 +536,7 @@ int do_adjtimex(struct timex *txc) return result; } +EXPORT_SYMBOL(do_adjtimex); static int __init ntp_tick_adj_setup(char *str) {