diff options
author | Rodolfo Giometti <giometti@linux.it> | 2009-11-11 17:26:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-11-12 10:26:01 -0500 |
commit | 276b282e904f690dc930f9bc946110651f297669 (patch) | |
tree | 7e50db4cee555f6044bd389452269d3c0fe45ed6 /drivers | |
parent | cbf83cc5a29dba480cf1ba1c5e3417a0d4a31410 (diff) |
pps: events reporting fix up
PPS events must be recorded according to PPS's mode settings.
If a process asks for (i.e.) capture-assert events only, when the PPS
client calls the pps_event() function to save the current PPS event, we
should verify the event type and then discard unwanted ones.
Also, without this patch userland processes waiting for a specific PPS
event (assert or clear but not both) may be awakened at wrong time.
Signed-off-by: Rodolfo Giometti <giometti@linux.it>
Tested-by: William S. Brasher <billb958@door.net>
Tested-by: Reg Clemens <clemens@dwf.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pps/kapi.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c index 35a0b192d768..2d414e23d390 100644 --- a/drivers/pps/kapi.c +++ b/drivers/pps/kapi.c | |||
@@ -271,6 +271,7 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data) | |||
271 | { | 271 | { |
272 | struct pps_device *pps; | 272 | struct pps_device *pps; |
273 | unsigned long flags; | 273 | unsigned long flags; |
274 | int captured = 0; | ||
274 | 275 | ||
275 | if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { | 276 | if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { |
276 | printk(KERN_ERR "pps: unknown event (%x) for source %d\n", | 277 | printk(KERN_ERR "pps: unknown event (%x) for source %d\n", |
@@ -293,7 +294,8 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data) | |||
293 | 294 | ||
294 | /* Check the event */ | 295 | /* Check the event */ |
295 | pps->current_mode = pps->params.mode; | 296 | pps->current_mode = pps->params.mode; |
296 | if (event & PPS_CAPTUREASSERT) { | 297 | if ((event & PPS_CAPTUREASSERT) & |
298 | (pps->params.mode & PPS_CAPTUREASSERT)) { | ||
297 | /* We have to add an offset? */ | 299 | /* We have to add an offset? */ |
298 | if (pps->params.mode & PPS_OFFSETASSERT) | 300 | if (pps->params.mode & PPS_OFFSETASSERT) |
299 | pps_add_offset(ts, &pps->params.assert_off_tu); | 301 | pps_add_offset(ts, &pps->params.assert_off_tu); |
@@ -303,8 +305,11 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data) | |||
303 | pps->assert_sequence++; | 305 | pps->assert_sequence++; |
304 | pr_debug("capture assert seq #%u for source %d\n", | 306 | pr_debug("capture assert seq #%u for source %d\n", |
305 | pps->assert_sequence, source); | 307 | pps->assert_sequence, source); |
308 | |||
309 | captured = ~0; | ||
306 | } | 310 | } |
307 | if (event & PPS_CAPTURECLEAR) { | 311 | if ((event & PPS_CAPTURECLEAR) & |
312 | (pps->params.mode & PPS_CAPTURECLEAR)) { | ||
308 | /* We have to add an offset? */ | 313 | /* We have to add an offset? */ |
309 | if (pps->params.mode & PPS_OFFSETCLEAR) | 314 | if (pps->params.mode & PPS_OFFSETCLEAR) |
310 | pps_add_offset(ts, &pps->params.clear_off_tu); | 315 | pps_add_offset(ts, &pps->params.clear_off_tu); |
@@ -314,12 +319,17 @@ void pps_event(int source, struct pps_ktime *ts, int event, void *data) | |||
314 | pps->clear_sequence++; | 319 | pps->clear_sequence++; |
315 | pr_debug("capture clear seq #%u for source %d\n", | 320 | pr_debug("capture clear seq #%u for source %d\n", |
316 | pps->clear_sequence, source); | 321 | pps->clear_sequence, source); |
322 | |||
323 | captured = ~0; | ||
317 | } | 324 | } |
318 | 325 | ||
319 | pps->go = ~0; | 326 | /* Wake up iif captured somthing */ |
320 | wake_up_interruptible(&pps->queue); | 327 | if (captured) { |
328 | pps->go = ~0; | ||
329 | wake_up_interruptible(&pps->queue); | ||
321 | 330 | ||
322 | kill_fasync(&pps->async_queue, SIGIO, POLL_IN); | 331 | kill_fasync(&pps->async_queue, SIGIO, POLL_IN); |
332 | } | ||
323 | 333 | ||
324 | spin_unlock_irqrestore(&pps->lock, flags); | 334 | spin_unlock_irqrestore(&pps->lock, flags); |
325 | 335 | ||