linux-rt-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* uio drivers with IRQF_NO_THREAD on preempt-rt kernel
@ 2018-05-08 15:59 Matthias Fuchs
  2018-05-09 17:56 ` Julia Cartwright
  0 siblings, 1 reply; 6+ messages in thread
From: Matthias Fuchs @ 2018-05-08 15:59 UTC (permalink / raw)
  To: linux-rt-users

Hi folks,

I am running stable kernel v4.4.110 with preempt-rt patch rt125 on a AM335x non-SMP system.
There is one thread with hard realtime requirements running on this system. This thread is scheduled
by a hardware interrupt (either AM335x PRUSS or external FPGA).

Latencies from interrupt into process are as expected. Interrupt thread prio has been
bumped to 90. But I want/need even shorter latencies.

So I tried to use IRQF_NO_THREAD in my uio driver to get rid of the scheduling detour through over the interrupt thread. The interrupt handling should be quiet fast - most handling is done in userspace.

Here comes the problem. The uio framework uses wake_up_interruptible() in the isr which does
not work from hard interrupt handlers. I tried to modify uio.c to use wake_up_process() with a limitation
to support a single process having opened the device.

This works fine in most cases :-( Userspace uses select() on the device with timeouts. Sometimes my process is woken
by interrupt event and sometimes by timeout - fine. But it looks like I am missing some interrupts.
I expect some issue with uio poll/waitqueue handling. 

Any idea how to fix this? It would be fine to stay with poll in the uio drivers. I already thought about a special hrtimer handling in my situation. But I hope about something more pretty.

BTW, latencies are shorter with this approach!

Matthias


diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bcc1fc0..7eb8257 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -394,8 +394,12 @@ void uio_event_notify(struct uio_info *info)
 	struct uio_device *idev = info->uio_dev;
 
 	atomic_inc(&idev->event);
-	wake_up_interruptible(&idev->wait);
-	kill_fasync(&idev->async_queue, SIGIO, POLL_IN);
+	if (idev->rt_consumer) {
+		wake_up_process(idev->rt_consumer);
+	} else {
+		wake_up_interruptible(&idev->wait);
+		kill_fasync(&idev->async_queue, SIGIO, POLL_IN);
+	}
 }
 EXPORT_SYMBOL_GPL(uio_event_notify);
 
@@ -439,6 +443,17 @@ static int uio_open(struct inode *inode, struct file *filep)
 		goto out;
 	}
 
+	if (idev->rt_consumer) {
+		ret = -EBUSY;
+		goto err_alloc_listener;
+	}
+
+#ifdef CONFIG_PREEMPT_RT_FULL
+	if (idev->info->irq_flags & IRQF_NO_THREAD) {
+	  idev->rt_consumer = current;
+	}
+#endif
+
 	listener = kmalloc(sizeof(*listener), GFP_KERNEL);
 	if (!listener) {
 		ret = -ENOMEM;
@@ -480,6 +495,7 @@ static int uio_release(struct inode *inode, struct file *filep)
 	struct uio_listener *listener = filep->private_data;
 	struct uio_device *idev = listener->dev;
 
+	idev->rt_consumer = NULL;
 	if (idev->info->release)
 		ret = idev->info->release(idev->info, inode);
 
diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h
index 32c0e83..cf314da 100644
--- a/include/linux/uio_driver.h
+++ b/include/linux/uio_driver.h
@@ -73,6 +73,7 @@ struct uio_device {
         struct uio_info         *info;
         struct kobject          *map_dir;
         struct kobject          *portio_dir;
+        struct task_struct      *rt_consumer;
 };
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-05-30 17:53 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-08 15:59 uio drivers with IRQF_NO_THREAD on preempt-rt kernel Matthias Fuchs
2018-05-09 17:56 ` Julia Cartwright
2018-05-15 14:02   ` Sebastian Andrzej Siewior
2018-05-28 20:26     ` Matthias Fuchs
2018-05-29 16:51       ` Sebastian Andrzej Siewior
2018-05-30 17:50         ` Matthias Fuchs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).