void pps_event(int source, struct pps_ktime *ts, int event, void *data) { struct pps_device *pps; unsigned long flags; if ((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0) { printk(KERN_ERR "pps: unknown event (%x) for source %d\n", event, source); return; } pps = pps_get_source(source); if (!pps) return; pr_debug("PPS event on source %d at %llu.%06u\n", pps->id, (unsigned long long) ts->sec, ts->nsec); spin_lock_irqsave(&pps->lock, flags); /* Must call the echo function? */ if ((pps->params.mode & (PPS_ECHOASSERT | PPS_ECHOCLEAR))) pps->info.echo(source, event, data); /* Check the event */ pps->current_mode = pps->params.mode; if (event & PPS_CAPTUREASSERT) { /* We have to add an offset? */ if (pps->params.mode & PPS_OFFSETASSERT) pps_add_offset(ts, &pps->params.assert_off_tu); /* Save the time stamp */ pps->assert_tu = *ts; pps->assert_sequence++; pr_debug("capture assert seq #%u for source %d\n", pps->assert_sequence, source); } if (event & PPS_CAPTURECLEAR) { /* We have to add an offset? */ if (pps->params.mode & PPS_OFFSETCLEAR) pps_add_offset(ts, &pps->params.clear_off_tu); /* Save the time stamp */ pps->clear_tu = *ts; pps->clear_sequence++; pr_debug("capture clear seq #%u for source %d\n", pps->clear_sequence, source); } pps->go = ~0; wake_up_interruptible(&pps->queue); kill_fasync(&pps->async_queue, SIGIO, POLL_IN); spin_unlock_irqrestore(&pps->lock, flags); /* Now we can release the PPS source for (possible) deregistration */ pps_put_source(pps); }
static int pps_cdev_release(struct inode *inode, struct file *file) { struct pps_device *pps = file->private_data; /* Free the PPS source and wake up (possible) deregistration */ pps_put_source(pps); return 0; }
void pps_unregister_source(int source) { struct pps_device *pps; spin_lock_irq(&pps_idr_lock); pps = idr_find(&pps_idr, source); if (!pps) { BUG(); spin_unlock_irq(&pps_idr_lock); return; } spin_unlock_irq(&pps_idr_lock); pps_unregister_cdev(pps); pps_put_source(pps); }