aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pps/kapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pps/kapi.c')
-rw-r--r--drivers/pps/kapi.c210
1 files changed, 50 insertions, 160 deletions
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index 1aa02db3ff4..cba1b43f751 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -19,24 +19,20 @@
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */ 20 */
21 21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22 23
23#include <linux/kernel.h> 24#include <linux/kernel.h>
24#include <linux/module.h> 25#include <linux/module.h>
25#include <linux/init.h> 26#include <linux/init.h>
26#include <linux/sched.h> 27#include <linux/sched.h>
27#include <linux/time.h> 28#include <linux/time.h>
29#include <linux/timex.h>
28#include <linux/spinlock.h> 30#include <linux/spinlock.h>
29#include <linux/idr.h>
30#include <linux/fs.h> 31#include <linux/fs.h>
31#include <linux/pps_kernel.h> 32#include <linux/pps_kernel.h>
32#include <linux/slab.h> 33#include <linux/slab.h>
33 34
34/* 35#include "kc.h"
35 * Global variables
36 */
37
38DEFINE_SPINLOCK(pps_idr_lock);
39DEFINE_IDR(pps_idr);
40 36
41/* 37/*
42 * Local functions 38 * Local functions
@@ -60,60 +56,6 @@ static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
60 * Exported functions 56 * Exported functions
61 */ 57 */
62 58
63/* pps_get_source - find a PPS source
64 * @source: the PPS source ID.
65 *
66 * This function is used to find an already registered PPS source into the
67 * system.
68 *
69 * The function returns NULL if found nothing, otherwise it returns a pointer
70 * to the PPS source data struct (the refcounter is incremented by 1).
71 */
72
73struct pps_device *pps_get_source(int source)
74{
75 struct pps_device *pps;
76 unsigned long flags;
77
78 spin_lock_irqsave(&pps_idr_lock, flags);
79
80 pps = idr_find(&pps_idr, source);
81 if (pps != NULL)
82 atomic_inc(&pps->usage);
83
84 spin_unlock_irqrestore(&pps_idr_lock, flags);
85
86 return pps;
87}
88
89/* pps_put_source - free the PPS source data
90 * @pps: a pointer to the PPS source.
91 *
92 * This function is used to free a PPS data struct if its refcount is 0.
93 */
94
95void pps_put_source(struct pps_device *pps)
96{
97 unsigned long flags;
98
99 spin_lock_irqsave(&pps_idr_lock, flags);
100 BUG_ON(atomic_read(&pps->usage) == 0);
101
102 if (!atomic_dec_and_test(&pps->usage)) {
103 pps = NULL;
104 goto exit;
105 }
106
107 /* No more reference to the PPS source. We can safely remove the
108 * PPS data struct.
109 */
110 idr_remove(&pps_idr, pps->id);
111
112exit:
113 spin_unlock_irqrestore(&pps_idr_lock, flags);
114 kfree(pps);
115}
116
117/* pps_register_source - add a PPS source in the system 59/* pps_register_source - add a PPS source in the system
118 * @info: the PPS info struct 60 * @info: the PPS info struct
119 * @default_params: the default PPS parameters of the new source 61 * @default_params: the default PPS parameters of the new source
@@ -122,31 +64,31 @@ exit:
122 * source is described by info's fields and it will have, as default PPS 64 * source is described by info's fields and it will have, as default PPS
123 * parameters, the ones specified into default_params. 65 * parameters, the ones specified into default_params.
124 * 66 *
125 * The function returns, in case of success, the PPS source ID. 67 * The function returns, in case of success, the PPS device. Otherwise NULL.
126 */ 68 */
127 69
128int pps_register_source(struct pps_source_info *info, int default_params) 70struct pps_device *pps_register_source(struct pps_source_info *info,
71 int default_params)
129{ 72{
130 struct pps_device *pps; 73 struct pps_device *pps;
131 int id;
132 int err; 74 int err;
133 75
134 /* Sanity checks */ 76 /* Sanity checks */
135 if ((info->mode & default_params) != default_params) { 77 if ((info->mode & default_params) != default_params) {
136 printk(KERN_ERR "pps: %s: unsupported default parameters\n", 78 pr_err("%s: unsupported default parameters\n",
137 info->name); 79 info->name);
138 err = -EINVAL; 80 err = -EINVAL;
139 goto pps_register_source_exit; 81 goto pps_register_source_exit;
140 } 82 }
141 if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 && 83 if ((info->mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)) != 0 &&
142 info->echo == NULL) { 84 info->echo == NULL) {
143 printk(KERN_ERR "pps: %s: echo function is not defined\n", 85 pr_err("%s: echo function is not defined\n",
144 info->name); 86 info->name);
145 err = -EINVAL; 87 err = -EINVAL;
146 goto pps_register_source_exit; 88 goto pps_register_source_exit;
147 } 89 }
148 if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) { 90 if ((info->mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
149 printk(KERN_ERR "pps: %s: unspecified time format\n", 91 pr_err("%s: unspecified time format\n",
150 info->name); 92 info->name);
151 err = -EINVAL; 93 err = -EINVAL;
152 goto pps_register_source_exit; 94 goto pps_register_source_exit;
@@ -168,94 +110,48 @@ int pps_register_source(struct pps_source_info *info, int default_params)
168 110
169 init_waitqueue_head(&pps->queue); 111 init_waitqueue_head(&pps->queue);
170 spin_lock_init(&pps->lock); 112 spin_lock_init(&pps->lock);
171 atomic_set(&pps->usage, 1);
172
173 /* Get new ID for the new PPS source */
174 if (idr_pre_get(&pps_idr, GFP_KERNEL) == 0) {
175 err = -ENOMEM;
176 goto kfree_pps;
177 }
178
179 spin_lock_irq(&pps_idr_lock);
180
181 /* Now really allocate the PPS source.
182 * After idr_get_new() calling the new source will be freely available
183 * into the kernel.
184 */
185 err = idr_get_new(&pps_idr, pps, &id);
186 if (err < 0) {
187 spin_unlock_irq(&pps_idr_lock);
188 goto kfree_pps;
189 }
190
191 id = id & MAX_ID_MASK;
192 if (id >= PPS_MAX_SOURCES) {
193 spin_unlock_irq(&pps_idr_lock);
194
195 printk(KERN_ERR "pps: %s: too many PPS sources in the system\n",
196 info->name);
197 err = -EBUSY;
198 goto free_idr;
199 }
200 pps->id = id;
201
202 spin_unlock_irq(&pps_idr_lock);
203 113
204 /* Create the char device */ 114 /* Create the char device */
205 err = pps_register_cdev(pps); 115 err = pps_register_cdev(pps);
206 if (err < 0) { 116 if (err < 0) {
207 printk(KERN_ERR "pps: %s: unable to create char device\n", 117 pr_err("%s: unable to create char device\n",
208 info->name); 118 info->name);
209 goto free_idr; 119 goto kfree_pps;
210 } 120 }
211 121
212 pr_info("new PPS source %s at ID %d\n", info->name, id); 122 dev_info(pps->dev, "new PPS source %s\n", info->name);
213 123
214 return id; 124 return pps;
215
216free_idr:
217 spin_lock_irq(&pps_idr_lock);
218 idr_remove(&pps_idr, id);
219 spin_unlock_irq(&pps_idr_lock);
220 125
221kfree_pps: 126kfree_pps:
222 kfree(pps); 127 kfree(pps);
223 128
224pps_register_source_exit: 129pps_register_source_exit:
225 printk(KERN_ERR "pps: %s: unable to register source\n", info->name); 130 pr_err("%s: unable to register source\n", info->name);
226 131
227 return err; 132 return NULL;
228} 133}
229EXPORT_SYMBOL(pps_register_source); 134EXPORT_SYMBOL(pps_register_source);
230 135
231/* pps_unregister_source - remove a PPS source from the system 136/* pps_unregister_source - remove a PPS source from the system
232 * @source: the PPS source ID 137 * @pps: the PPS source
233 * 138 *
234 * This function is used to remove a previously registered PPS source from 139 * This function is used to remove a previously registered PPS source from
235 * the system. 140 * the system.
236 */ 141 */
237 142
238void pps_unregister_source(int source) 143void pps_unregister_source(struct pps_device *pps)
239{ 144{
240 struct pps_device *pps; 145 pps_kc_remove(pps);
241
242 spin_lock_irq(&pps_idr_lock);
243 pps = idr_find(&pps_idr, source);
244
245 if (!pps) {
246 BUG();
247 spin_unlock_irq(&pps_idr_lock);
248 return;
249 }
250 spin_unlock_irq(&pps_idr_lock);
251
252 pps_unregister_cdev(pps); 146 pps_unregister_cdev(pps);
253 pps_put_source(pps); 147
148 /* don't have to kfree(pps) here because it will be done on
149 * device destruction */
254} 150}
255EXPORT_SYMBOL(pps_unregister_source); 151EXPORT_SYMBOL(pps_unregister_source);
256 152
257/* pps_event - register a PPS event into the system 153/* pps_event - register a PPS event into the system
258 * @source: the PPS source ID 154 * @pps: the PPS device
259 * @ts: the event timestamp 155 * @ts: the event timestamp
260 * @event: the event type 156 * @event: the event type
261 * @data: userdef pointer 157 * @data: userdef pointer
@@ -263,78 +159,72 @@ EXPORT_SYMBOL(pps_unregister_source);
263 * This function is used by each PPS client in order to register a new 159 * This function is used by each PPS client in order to register a new
264 * PPS event into the system (it's usually called inside an IRQ handler). 160 * PPS event into the system (it's usually called inside an IRQ handler).
265 * 161 *
266 * If an echo function is associated with the PPS source it will be called 162 * If an echo function is associated with the PPS device it will be called
267 * as: 163 * as:
268 * pps->info.echo(source, event, data); 164 * pps->info.echo(pps, event, data);
269 */ 165 */
270 166void pps_event(struct pps_device *pps, struct pps_event_time *ts, int event,
271void pps_event(int source, struct pps_ktime *ts, int event, void *data) 167 void *data)
272{ 168{
273 struct pps_device *pps;
274 unsigned long flags; 169 unsigned long flags;
275 int captured = 0; 170 int captured = 0;
171 struct pps_ktime ts_real;
276 172
277 if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { 173 /* check event type */
278 printk(KERN_ERR "pps: unknown event (%x) for source %d\n", 174 BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
279 event, source);
280 return;
281 }
282 175
283 pps = pps_get_source(source); 176 dev_dbg(pps->dev, "PPS event at %ld.%09ld\n",
284 if (!pps) 177 ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
285 return;
286 178
287 pr_debug("PPS event on source %d at %llu.%06u\n", 179 timespec_to_pps_ktime(&ts_real, ts->ts_real);
288 pps->id, (unsigned long long) ts->sec, ts->nsec);
289 180
290 spin_lock_irqsave(&pps->lock, flags); 181 spin_lock_irqsave(&pps->lock, flags);
291 182
292 /* Must call the echo function? */ 183 /* Must call the echo function? */
293 if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) 184 if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR)))
294 pps->info.echo(source, event, data); 185 pps->info.echo(pps, event, data);
295 186
296 /* Check the event */ 187 /* Check the event */
297 pps->current_mode = pps->params.mode; 188 pps->current_mode = pps->params.mode;
298 if ((event & PPS_CAPTUREASSERT) & 189 if (event & pps->params.mode & PPS_CAPTUREASSERT) {
299 (pps->params.mode & PPS_CAPTUREASSERT)) {
300 /* We have to add an offset? */ 190 /* We have to add an offset? */
301 if (pps->params.mode & PPS_OFFSETASSERT) 191 if (pps->params.mode & PPS_OFFSETASSERT)
302 pps_add_offset(ts, &pps->params.assert_off_tu); 192 pps_add_offset(&ts_real,
193 &pps->params.assert_off_tu);
303 194
304 /* Save the time stamp */ 195 /* Save the time stamp */
305 pps->assert_tu = *ts; 196 pps->assert_tu = ts_real;
306 pps->assert_sequence++; 197 pps->assert_sequence++;
307 pr_debug("capture assert seq #%u for source %d\n", 198 dev_dbg(pps->dev, "capture assert seq #%u\n",
308 pps->assert_sequence, source); 199 pps->assert_sequence);
309 200
310 captured = ~0; 201 captured = ~0;
311 } 202 }
312 if ((event & PPS_CAPTURECLEAR) & 203 if (event & pps->params.mode & PPS_CAPTURECLEAR) {
313 (pps->params.mode & PPS_CAPTURECLEAR)) {
314 /* We have to add an offset? */ 204 /* We have to add an offset? */
315 if (pps->params.mode & PPS_OFFSETCLEAR) 205 if (pps->params.mode & PPS_OFFSETCLEAR)
316 pps_add_offset(ts, &pps->params.clear_off_tu); 206 pps_add_offset(&ts_real,
207 &pps->params.clear_off_tu);
317 208
318 /* Save the time stamp */ 209 /* Save the time stamp */
319 pps->clear_tu = *ts; 210 pps->clear_tu = ts_real;
320 pps->clear_sequence++; 211 pps->clear_sequence++;
321 pr_debug("capture clear seq #%u for source %d\n", 212 dev_dbg(pps->dev, "capture clear seq #%u\n",
322 pps->clear_sequence, source); 213 pps->clear_sequence);
323 214
324 captured = ~0; 215 captured = ~0;
325 } 216 }
326 217
327 /* Wake up iif captured somthing */ 218 pps_kc_event(pps, ts, event);
219
220 /* Wake up if captured something */
328 if (captured) { 221 if (captured) {
329 pps->go = ~0; 222 pps->last_ev++;
330 wake_up_interruptible(&pps->queue); 223 wake_up_interruptible_all(&pps->queue);
331 224
332 kill_fasync(&pps->async_queue, SIGIO, POLL_IN); 225 kill_fasync(&pps->async_queue, SIGIO, POLL_IN);
333 } 226 }
334 227
335 spin_unlock_irqrestore(&pps->lock, flags); 228 spin_unlock_irqrestore(&pps->lock, flags);
336
337 /* Now we can release the PPS source for (possible) deregistration */
338 pps_put_source(pps);
339} 229}
340EXPORT_SYMBOL(pps_event); 230EXPORT_SYMBOL(pps_event);