mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-18 22:14:16 +00:00
pps: fix poll support
Because pps_cdev_poll() returns unconditionally EPOLLIN,
a user space program that calls select/poll get always an immediate data
ready-to-read response. As a result the intended use to wait until next
data becomes ready does not work.
User space snippet:
struct pollfd pollfd = {
.fd = open("/dev/pps0", O_RDONLY),
.events = POLLIN|POLLERR,
.revents = 0 };
while(1) {
poll(&pollfd, 1, 2000/*ms*/); // returns immediate, but should wait
if(revents & EPOLLIN) { // always true
struct pps_fdata fdata;
memset(&fdata, 0, sizeof(memdata));
ioctl(PPS_FETCH, &fdata); // currently fetches data at max speed
}
}
Lets remember the last fetch event counter and compare this value
in pps_cdev_poll() with most recent event counter
and return 0 if they are equal.
Signed-off-by: Denis OSTERLAND-HEIM <denis.osterland@diehl.com>
Co-developed-by: Rodolfo Giometti <giometti@enneenne.com>
Signed-off-by: Rodolfo Giometti <giometti@enneenne.com>
Fixes: eae9d2ba0c
("LinuxPPS: core support")
Link: https://lore.kernel.org/all/f6bed779-6d59-4f0f-8a59-b6312bd83b4e@enneenne.com/
Acked-by: Rodolfo Giometti <giometti@enneenne.com>
Link: https://lore.kernel.org/r/c3c50ad1eb19ef553eca8a57c17f4c006413ab70.camel@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
6bca1e9558
commit
12c409aa1e
2 changed files with 10 additions and 2 deletions
|
@ -41,6 +41,9 @@ static __poll_t pps_cdev_poll(struct file *file, poll_table *wait)
|
|||
|
||||
poll_wait(file, &pps->queue, wait);
|
||||
|
||||
if (pps->last_fetched_ev == pps->last_ev)
|
||||
return 0;
|
||||
|
||||
return EPOLLIN | EPOLLRDNORM;
|
||||
}
|
||||
|
||||
|
@ -186,9 +189,11 @@ static long pps_cdev_ioctl(struct file *file,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* Return the fetched timestamp */
|
||||
/* Return the fetched timestamp and save last fetched event */
|
||||
spin_lock_irq(&pps->lock);
|
||||
|
||||
pps->last_fetched_ev = pps->last_ev;
|
||||
|
||||
fdata.info.assert_sequence = pps->assert_sequence;
|
||||
fdata.info.clear_sequence = pps->clear_sequence;
|
||||
fdata.info.assert_tu = pps->assert_tu;
|
||||
|
@ -272,9 +277,11 @@ static long pps_cdev_compat_ioctl(struct file *file,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
/* Return the fetched timestamp */
|
||||
/* Return the fetched timestamp and save last fetched event */
|
||||
spin_lock_irq(&pps->lock);
|
||||
|
||||
pps->last_fetched_ev = pps->last_ev;
|
||||
|
||||
compat.info.assert_sequence = pps->assert_sequence;
|
||||
compat.info.clear_sequence = pps->clear_sequence;
|
||||
compat.info.current_mode = pps->current_mode;
|
||||
|
|
|
@ -52,6 +52,7 @@ struct pps_device {
|
|||
int current_mode; /* PPS mode at event time */
|
||||
|
||||
unsigned int last_ev; /* last PPS event id */
|
||||
unsigned int last_fetched_ev; /* last fetched PPS event id */
|
||||
wait_queue_head_t queue; /* PPS event queue */
|
||||
|
||||
unsigned int id; /* PPS source unique ID */
|
||||
|
|
Loading…
Add table
Reference in a new issue