Commit 12c409aa authored by Denis OSTERLAND-HEIM's avatar Denis OSTERLAND-HEIM Committed by Greg Kroah-Hartman
Browse files

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: default avatarDenis OSTERLAND-HEIM <denis.osterland@diehl.com>
Co-developed-by: default avatarRodolfo Giometti <giometti@enneenne.com>
Signed-off-by: default avatarRodolfo Giometti <giometti@enneenne.com>
Fixes: eae9d2ba ("LinuxPPS: core support")
Link: https://lore.kernel.org/all/f6bed779-6d59-4f0f-8a59-b6312bd83b4e@enneenne.com/


Acked-by: default avatarRodolfo Giometti <giometti@enneenne.com>
Link: https://lore.kernel.org/r/c3c50ad1eb19ef553eca8a57c17f4c006413ab70.camel@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6bca1e95
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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 */