From 7a21a3cc0be92e70474cc2ab06cb074f6a7c3f09 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 12 Jan 2011 17:00:49 -0800 Subject: pps: trivial fixes Here are some very trivial fixes combined: - add macro definitions to protect header file from including several times - remove declaration for an unexistent array - fix typos Signed-off-by: Alexander Gordeev Acked-by: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pps_kernel.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'include/linux/pps_kernel.h') diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h index e0a193f830ef..23f63c3263bb 100644 --- a/include/linux/pps_kernel.h +++ b/include/linux/pps_kernel.h @@ -18,6 +18,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifndef LINUX_PPS_KERNEL_H +#define LINUX_PPS_KERNEL_H + #include #include @@ -71,7 +74,6 @@ struct pps_device { extern spinlock_t pps_idr_lock; extern struct idr pps_idr; -extern struct timespec pps_irq_ts[]; extern struct device_attribute pps_attrs[]; @@ -87,3 +89,5 @@ extern void pps_unregister_source(int source); extern int pps_register_cdev(struct pps_device *pps); extern void pps_unregister_cdev(struct pps_device *pps); extern void pps_event(int source, struct pps_ktime *ts, int event, void *data); + +#endif /* LINUX_PPS_KERNEL_H */ -- cgit v1.2.3 From 3003d55b59aa98aeaff2773df69732b27c0cbf6a Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 12 Jan 2011 17:00:50 -0800 Subject: pps: fix race in PPS_FETCH handler There was a race in PPS_FETCH ioctl handler when several processes want to obtain PPS data simultaneously using sleeping PPS_FETCH. They all sleep most of the time in the system call. With the old approach when the first process waiting on the pps queue is waken up it makes new system call right away and zeroes pps->go. So other processes continue to sleep. This is a clear race condition because of the global 'go' variable. With the new approach pps->last_ev holds some value increasing at each PPS event. PPS_FETCH ioctl handler saves current value to the local variable at the very beginning so it can safely check that there is a new event by just comparing both variables. Signed-off-by: Alexander Gordeev Acked-by: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pps_kernel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux/pps_kernel.h') diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h index 23f63c3263bb..65194fe498bb 100644 --- a/include/linux/pps_kernel.h +++ b/include/linux/pps_kernel.h @@ -55,7 +55,7 @@ struct pps_device { struct pps_ktime clear_tu; int current_mode; /* PPS mode at event time */ - int go; /* PPS event is arrived? */ + unsigned int last_ev; /* last PPS event id */ wait_queue_head_t queue; /* PPS event queue */ unsigned int id; /* PPS source unique ID */ -- cgit v1.2.3 From 6f4229b51106cbc859e9d8209b22c8a2ec749e64 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 12 Jan 2011 17:00:50 -0800 Subject: pps: unify timestamp gathering Add a helper function to gather timestamps. This way clients don't have to duplicate it. Signed-off-by: Alexander Gordeev Acked-by: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pps_kernel.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'include/linux/pps_kernel.h') diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h index 65194fe498bb..32aa6763ca1b 100644 --- a/include/linux/pps_kernel.h +++ b/include/linux/pps_kernel.h @@ -43,6 +43,10 @@ struct pps_source_info { struct device *dev; }; +struct pps_event_time { + struct timespec ts_real; +}; + /* The main struct */ struct pps_device { struct pps_source_info info; /* PSS source info */ @@ -88,6 +92,20 @@ extern int pps_register_source(struct pps_source_info *info, extern void pps_unregister_source(int source); extern int pps_register_cdev(struct pps_device *pps); extern void pps_unregister_cdev(struct pps_device *pps); -extern void pps_event(int source, struct pps_ktime *ts, int event, void *data); +extern void pps_event(int source, struct pps_event_time *ts, int event, + void *data); + +static inline void timespec_to_pps_ktime(struct pps_ktime *kt, + struct timespec ts) +{ + kt->sec = ts.tv_sec; + kt->nsec = ts.tv_nsec; +} + +static inline void pps_get_ts(struct pps_event_time *ts) +{ + getnstimeofday(&ts->ts_real); +} #endif /* LINUX_PPS_KERNEL_H */ + -- cgit v1.2.3 From 5e196d34a776420278e4117b4742cd9d3f2350ed Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 12 Jan 2011 17:00:51 -0800 Subject: pps: access pps device by direct pointer Using device index as a pointer needs some unnecessary work to be done every time the pointer is needed (in irq handler for example). Using a direct pointer is much more easy (and safe as well). Signed-off-by: Alexander Gordeev Acked-by: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pps_kernel.h | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) (limited to 'include/linux/pps_kernel.h') diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h index 32aa6763ca1b..1aedf50088cf 100644 --- a/include/linux/pps_kernel.h +++ b/include/linux/pps_kernel.h @@ -31,13 +31,16 @@ * Global defines */ +struct pps_device; + /* The specific PPS source info */ struct pps_source_info { char name[PPS_MAX_NAME_LEN]; /* simbolic name */ char path[PPS_MAX_NAME_LEN]; /* path of connected device */ int mode; /* PPS's allowed mode */ - void (*echo)(int source, int event, void *data); /* PPS echo function */ + void (*echo)(struct pps_device *pps, + int event, void *data); /* PPS echo function */ struct module *owner; struct device *dev; @@ -65,35 +68,27 @@ struct pps_device { unsigned int id; /* PPS source unique ID */ struct cdev cdev; struct device *dev; - int devno; struct fasync_struct *async_queue; /* fasync method */ spinlock_t lock; - - atomic_t usage; /* usage count */ }; /* * Global variables */ -extern spinlock_t pps_idr_lock; -extern struct idr pps_idr; - extern struct device_attribute pps_attrs[]; /* * Exported functions */ -struct pps_device *pps_get_source(int source); -extern void pps_put_source(struct pps_device *pps); -extern int pps_register_source(struct pps_source_info *info, - int default_params); -extern void pps_unregister_source(int source); +extern struct pps_device *pps_register_source( + struct pps_source_info *info, int default_params); +extern void pps_unregister_source(struct pps_device *pps); extern int pps_register_cdev(struct pps_device *pps); extern void pps_unregister_cdev(struct pps_device *pps); -extern void pps_event(int source, struct pps_event_time *ts, int event, - void *data); +extern void pps_event(struct pps_device *pps, + struct pps_event_time *ts, int event, void *data); static inline void timespec_to_pps_ktime(struct pps_ktime *kt, struct timespec ts) -- cgit v1.2.3 From e2c18e49a0d4f822ffc29fb4958943beb1ff08b7 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 12 Jan 2011 17:00:57 -0800 Subject: pps: capture MONOTONIC_RAW timestamps as well MONOTONIC_RAW clock timestamps are ideally suited for frequency calculation and also fit well into the original NTP hardpps design. Now phase and frequency can be adjusted separately: the former based on REALTIME clock and the latter based on MONOTONIC_RAW clock. A new function getnstime_raw_and_real is added to timekeeping subsystem to capture both timestamps at the same time and atomically. Signed-off-by: Alexander Gordeev Acked-by: John Stultz Cc: Rodolfo Giometti Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/pps_kernel.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'include/linux/pps_kernel.h') diff --git a/include/linux/pps_kernel.h b/include/linux/pps_kernel.h index 1aedf50088cf..94048547f29a 100644 --- a/include/linux/pps_kernel.h +++ b/include/linux/pps_kernel.h @@ -47,6 +47,9 @@ struct pps_source_info { }; struct pps_event_time { +#ifdef CONFIG_NTP_PPS + struct timespec ts_raw; +#endif /* CONFIG_NTP_PPS */ struct timespec ts_real; }; @@ -97,10 +100,21 @@ static inline void timespec_to_pps_ktime(struct pps_ktime *kt, kt->nsec = ts.tv_nsec; } +#ifdef CONFIG_NTP_PPS + +static inline void pps_get_ts(struct pps_event_time *ts) +{ + getnstime_raw_and_real(&ts->ts_raw, &ts->ts_real); +} + +#else /* CONFIG_NTP_PPS */ + static inline void pps_get_ts(struct pps_event_time *ts) { getnstimeofday(&ts->ts_real); } +#endif /* CONFIG_NTP_PPS */ + #endif /* LINUX_PPS_KERNEL_H */ -- cgit v1.2.3