Simple userspace interface for PCI drivers
Subsystems (2)
RFC 1/1 Simple userspace interface for PCI drivers
A while ago, Thomas and I were sitting in the back of a conference presentation where the presenter was trying to describe what they did in order to add the ability to write a userspace PCI driver. As was usual in a presentation like this, the presenter totaly ignored the real-world needs for such a framework, and only got it up and working on a single type of embedded system. But the charts and graphs were quite pretty :)
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
Thomas mentioned that he had code to do all of this working in some customer sites already and that he would get it to me.
Fast forward to OLS of this year, and I bugged Thomas to send me the code. He did, and then I sat on it for a while longer...
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines. So it is possible to use this interface to successfully build your own laser wielding robot, all from userspace, allowing you to keep your special-secret-how-to-control-the-laser algorithm closed source if you so desire.
In looking at the proposed kevent interface, I think a few things in this proposed interface can be dropped in favor of using kevents instead, but I haven't looked at the latest version of that code to make sure of this.
And the name is a bit ackward, anyone have a better suggestion?
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
Comments?
thanks,
greg k-h
------------------------
From: Thomas Gleixner <[email protected]>
To: Greg KH <[email protected]>
Subject: IIO subsystem
From: Thomas Gleixner <[email protected]>
This allows userspace PCI drivers to be written in a sane manner.
From: Thomas Gleixner <[email protected]>
--- Documentation/DocBook/kernel-api.tmpl | 5 drivers/Kconfig | 2 drivers/Makefile | 1 drivers/iio/Kconfig | 11 drivers/iio/Makefile | 4 drivers/iio/iio_base.c | 438 ++++++++++++++++++++++++++++++++++ drivers/iio/iio_dev.c | 366 ++++++++++++++++++++++++++++ drivers/iio/iio_dummy.c | 269 ++++++++++++++++++++ include/linux/iio.h | 108 ++++++++ kernel/signal.c | 4 10 files changed, 1208 insertions(+)
Documentation/DocBook/kernel-api.tmpl +5 -0
@@ -430,6 +430,11 @@ X!Edrivers/pnp/system.c !Edrivers/pnp/manager.c !Edrivers/pnp/support.c </sect1> + <sect1><title>Industrial IO device driver</title> +!Edrivers/iio/iio_base.c +!Edrivers/iio/iio_dev.c +!Iinclude/linux/iio.h + </sect1> </chapter> <chapter id="blkdev">
drivers/Kconfig +2 -0
@@ -74,4 +74,6 @@ source "drivers/rtc/Kconfig" source "drivers/dma/Kconfig" +source "drivers/iio/Kconfig" + endmenu
drivers/Makefile +1 -0
@@ -36,6 +36,7 @@ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_IEEE1394) += ieee1394/ +obj-$(CONFIG_IIO) += iio/ obj-y += cdrom/ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_SPI) += spi/
drivers/iio/Kconfig new file +11 -0
@@ -0,0 +1,11 @@ +menu "Industrial IO" +config IIO + tristate "Industrial IO" + help + base driver for industrial IO + +config IIO_DUMMY + tristate "Industrial IO dummy driver" + help + example/dummy driver for industrial IO +endmenu
drivers/iio/Makefile new file +4 -0
@@ -0,0 +1,4 @@ +obj-$(CONFIG_IIO) += iio.o +obj-$(CONFIG_IIO_DUMMY) += iio_dummy.o + +iio-objs := iio_base.o iio_dev.o
drivers/iio/iio_base.c new file +438 -0
438 lines not on this page · raw message
drivers/iio/iio_dev.c new file +366 -0
366 lines not on this page · raw message
drivers/iio/iio_dummy.c new file +269 -0
269 lines not on this page · raw message
include/linux/iio.h new file +108 -0
108 lines not on this page · raw message
kernel/signal.c +4 -0
@@ -1296,6 +1296,7 @@ struct sigqueue *sigqueue_alloc(void) q->flags |=SIGQUEUE_PREALLOC ;return (q); } +EXPORT_SYMBOL_GPL (sigqueue_alloc);void sigqueue_free (struct sigqueue *q) {
@@ -1317,6 +1318,7 @@ void sigqueue_free(struct sigqueue *q) q->flags &= ~SIGQUEUE_PREALLOC ;__sigqueue_free (q); } +EXPORT_SYMBOL_GPL (sigqueue_free);int send_sigqueue (int sig,struct sigqueue *q,struct task_struct *p) {
@@ -1367,6 +1369,7 @@ out_err:return ret; } +EXPORT_SYMBOL_GPL (send_sigqueue);int send_group_sigqueue (int sig,struct sigqueue *q,struct task_struct *p)
@@ -1412,6 +1415,7 @@ out:read_unlock (&tasklist_lock);return ret; } +EXPORT_SYMBOL_GPL (send_group_sigqueue);/* * Wake up any threads in the parent blocked in wait* syscalls.
Quoted 8 lines · Greg KH
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines. So it is possible to use this interface to successfully build your own laser wielding robot, all from userspace, allowing you to keep your special-secret-how-to-control-the-laser algorithm closed source if you so desire.
Quoted 4 lines
In looking at the proposed kevent interface, I think a few things in this proposed interface can be dropped in favor of using kevents instead, but I haven't looked at the latest version of that code to make sure of this.
Yeah, that makes sense.
Quoted 5 lines
And the name is a bit ackward, anyone have a better suggestion?
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
Yup. I pinged the customer again to get the "non-secret" :) parts published.
tglx
Quoted 7 lines · Greg KH
A while ago, Thomas and I were sitting in the back of a conference presentation where the presenter was trying to describe what they did in order to add the ability to write a userspace PCI driver. As was usual in a presentation like this, the presenter totaly ignored the real-world needs for such a framework, and only got it up and working on a single type of embedded system. But the charts and graphs were quite pretty :)
Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
What about portable access to the PCI DMA API from userspace? I didn't think we had a way to handle DMA buffer management entirely from userspace. Looking at this code, it seems focused on one particular problem space of industrial control. If the goal is to allow most PCI drivers to be implemented in user space then I think it makes further sense to not limit the subsystem to PCI but any device (like things that are implemented as platform devices in kernel space).
Quoted 14 lines
Thomas mentioned that he had code to do all of this working in some customer sites already and that he would get it to me.
Fast forward to OLS of this year, and I bugged Thomas to send me the code. He did, and then I sat on it for a while longer...
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines. So it is possible to use this interface to successfully build your own laser wielding robot, all from userspace, allowing you to keep your special-secret-how-to-control-the-laser algorithm closed source if you so desire.
Quoted 6 lines
In looking at the proposed kevent interface, I think a few things in this proposed interface can be dropped in favor of using kevents instead, but I haven't looked at the latest version of that code to make sure of this.
And the name is a bit ackward, anyone have a better suggestion?
Well, if it's focused on industrial controls like it appears from the code here then the name is fine. If it's a starting point to become someting more generic then User Space Driver (USD) subsystem might be nice.
A more generic system would go a long way to get rid of the dubious secret-sauce binary kernel modules that are popular in embedded linux projects.
Quoted 3 lines
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
That would be nice to see. I can't see how devices and drivers are registered from user space with what's here. I see iio_register_device() exported but no clue how userspace tells the kernel to claim a device or register an iio driver.
-Matt
Quoted 8 lines · Matt Porter
Quoted 6 lines · Greg KH
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
Quoted 7 lines
What about portable access to the PCI DMA API from userspace? I didn't think we had a way to handle DMA buffer management entirely from userspace. Looking at this code, it seems focused on one particular problem space of industrial control. If the goal is to allow most PCI drivers to be implemented in user space then I think it makes further sense to not limit the subsystem to PCI but any device (like things that are implemented as platform devices in kernel space).
The code was written to have a unified kernel / userspace interface for a range of industrial I/O hardware - hence the name.
There is no real limitation for that type of devices and it is not restricted to PCI in any way. We had no need for DMA in the first place, but this should be an orthogonal extension.
Quoted 6 lines
Quoted 1 line
And the name is a bit ackward, anyone have a better suggestion?
Well, if it's focused on industrial controls like it appears from the code here then the name is fine. If it's a starting point to become someting more generic then User Space Driver (USD) subsystem might be nice.
Yup.
Quoted 4 lines
A more generic system would go a long way to get rid of the dubious secret-sauce binary kernel modules that are popular in embedded linux projects.
Quoted 8 lines
Quoted 3 lines
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
That would be nice to see. I can't see how devices and drivers are registered from user space with what's here. I see
iio_register_device()exported but no clue how userspace tells the kernel to claim a device or register an iio driver.
You still need a stub driver in the kernel. See below. The userspace side is just opening the device which is created by udev and uses the sysfs provided information to mmap the device space and to register notifications, which might be replaced by kevent.
The example below is a driver for a SERCOS chip, which is a motion control bus master. All we have in kernel is the register / unregister function and the primary interrupt acknowledge of the chip, which allows us to have this interrupt shared with other interrupt sources.
/**
* $Date: 2006-08-24 15:00:46 +0200 (Do, 24 Aug 2006) $
* $Author: baueh $
* $Rev: 370 $
*
* Sercos kernel stub driver
*
* Copyright (C) 2006 Berger Lahr GmbH
* Author: Thomas Bauer <[email protected]> *
* This code is GPL V2.
*/
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/iio.h>
#include <linux/delay.h>
#include "berger.h"
static struct pci_device_id sercos_table[] __devinitdata = {
{ MY_VENDOR_ID, MY_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0, }
};MODULE_DEVICE_TABLE(pci, sercos_table);
/*
* Use the generic file operations
*/
static struct file_operations generic_fops = {
.open = iio_open,
.release = iio_release,
.read = iio_read,
.write = iio_write,
.llseek = iio_lseek,
.mmap = iio_mmap,
};
/*
* The chip specific portion of the interrupt handler. The framework code
* takes care of userspace notification when we return IRQ_HANDLED */
static irqreturn_t sercos_handler (int irq, void *dev_id, struct pt_regs *reg)
{
struct iio_device *idev = (struct iio_device *) dev_id;
/* Check, if this interrupt is originated from the SERCOS chip */
if (!(*((u16 *)(idev->virtaddr + SERCOS_INTERRUPT_STATUS)) & SERCOS_INTERRUPT_MASK))
return IRQ_NONE;
/* Acknowledge the chip interrupts */
*((u16 *)(idev->virtaddr + SERCOS_INTERRUPT_ACK1_OFFSET)) = SERCOS_INTERRUPT_ACK1;
*((u16 *)(idev->virtaddr + SERCOS_INTERRUPT_ACK2_OFFSET)) = SERCOS_INTERRUPT_ACK2;
return IRQ_HANDLED;
}static struct iio_device sercos_idev = {
.name = "SERCON816",
.version = "0x0010",
.fops = &generic_fops,
.handler = sercos_handler,
};static struct sercos_idevs
{
int sercos;
} sercos_idevs;static int sercos_register (struct pci_dev *pdev, const struct pci_device_id *ent)
{
if (pci_enable_device(pdev) != 0) {
printk(KERN_ERR "sercos: Cannot enable PCI device\n");
return -ENODEV;
}
/* FIXME: Read this from PCI ! */
sercos_idev.size = SERCOS_SIZE;
sercos_idev.virtaddr = ioremap(pci_resource_start (pdev, 0), sercos_idev.size);
sercos_idev.physaddr = pci_resource_start(pdev, 0);
sercos_idev.irq = SERCOS_IRQ;
sercos_idevs.sercos = iio_register_device(&pdev->dev, &sercos_idev);
printk(KERN_INFO "SERCOS = %d\n",sercos_idevs.sercos);
printk(KERN_INFO "SERCOS registered at Phys. address 0x%lx \n", sercos_idev.physaddr);
printk(KERN_INFO "SERCOS registered at Virt. address 0x%x \n", (unsigned int) sercos_idev.virtaddr);
printk(KERN_INFO "SERCOS SIZE 0x%lx \n", sercos_idev.size);
pdev->dev.driver_data = &sercos_idevs;
return 0;
}static void __devexit sercos_unregister (struct pci_dev *pdev)
{
if (sercos_idevs.sercos)
iio_unregister_device(sercos_idevs.sercos);
release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
}static struct pci_driver sercos_driver = {
.name = "sercos",
.id_table = sercos_table,
.probe = sercos_register,
.remove = __devexit_p(sercos_unregister),
};static int __init sercos_init (void)
{
return pci_register_driver (&sercos_driver);
}static void __exit sercos_exit (void)
{
pci_unregister_driver (&sercos_driver);
}module_init(sercos_init);module_exit(sercos_exit);
MODULE_LICENSE("GPL");MODULE_AUTHOR("BergerLahr");MODULE_DESCRIPTION("sercos driver");
/*
* Userspace portion of the SERCOS driver - simplified *
* iionum - the iio device number to access:
* /dev/iioX
* /dev/iioX_event
* /sys/class/iio/iioX
*/
int sercos_driver(int iionum)
{
int fd;
char fnam[64];
size_t maplen;
uint16_t *sercos;
sprintf(fnam, "/dev/iio%d", iionum);
fd = open(fnam, O_RDWR);
if (fd < 0)
return -EIO;
/* Get map length from /sys/class/iioX/size */
if (iiolib_getmaplen(iionum, &maplen)) {
close(fd);
return -ENODEV;
}
/* Map the chip space */
sercos = mmap(NULL, maplen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (sercos == MAP_FAILED) {
close(fd);
return -ENODEV;
}
close(fd);
/* Initialize the chip */
sercos_init_chip(sercos);
/*
* Open the event channel. We are the only user, but this could also
* be done by requesting notification by a signal.
*/
sprintf(fnam, "/dev/iio%d_event", iionum);
fd = open(fnam, O_RDONLY);
if (fd < 0) {
sercos_reset_chip(sercos);
munmap(sercos, maplen);
return -EIO;
}
/* interrupt event loop */
while (!stop_sercos) {
char c;
/* Block on the interrupt event */
read(fd, &c, 1);
sercos_handle_interrupt(sercos);
}
sercos_reset_chip(sercos);
munmap(sercos, maplen);
return 0;
}Quoted 8 lines · Matt Porter
Quoted 7 lines · Greg KH
A while ago, Thomas and I were sitting in the back of a conference presentation where the presenter was trying to describe what they did in order to add the ability to write a userspace PCI driver. As was usual in a presentation like this, the presenter totaly ignored the real-world needs for such a framework, and only got it up and working on a single type of embedded system. But the charts and graphs were quite pretty :)
Quoted 8 lines
Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
What about portable access to the PCI DMA API from userspace?
It currently does not provide this, but if you know how your card works, I'm pretty sure you can get this working without such an interface.
If you wish to add this functionality, to make it easier, that would be great.
Quoted 21 lines
Quoted 14 lines
Thomas mentioned that he had code to do all of this working in some customer sites already and that he would get it to me.
Fast forward to OLS of this year, and I bugged Thomas to send me the code. He did, and then I sat on it for a while longer...
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines. So it is possible to use this interface to successfully build your own laser wielding robot, all from userspace, allowing you to keep your special-secret-how-to-control-the-laser algorithm closed source if you so desire.
Quoted 6 lines
In looking at the proposed kevent interface, I think a few things in this proposed interface can be dropped in favor of using kevents instead, but I haven't looked at the latest version of that code to make sure of this.
And the name is a bit ackward, anyone have a better suggestion?
Quoted 8 lines
Well, if it's focused on industrial controls like it appears from the code here then the name is fine. If it's a starting point to become someting more generic then User Space Driver (USD) subsystem might be nice.
A more generic system would go a long way to get rid of the dubious secret-sauce binary kernel modules that are popular in embedded linux projects.
It's not focused on industrial controls at all, that just happens to be the name of it right now, as that is why it was written. It is much more generic than that.
"USD" is a bit too close to "USB" for a name. Any other ideas?
Quoted 8 lines
Quoted 3 lines
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
That would be nice to see. I can't see how devices and drivers are registered from user space with what's here. I see
iio_register_device()exported but no clue how userspace tells the kernel to claim a device or register an iio driver.
His posted example should show you how this all works together.
thanks,
greg k-h
Quoted 4 lines · Matt Porter
Quoted 2 lines · Greg KH
Quoted 1 line
A while ago, Thomas and I were sitting in the back of a conference
.
.
.
Quoted 3 lines
more generic than that.
"USD" is a bit too close to "USB" for a name. Any other ideas?
what about U_IO ;-)
Quoted 16 lines
Quoted 9 lines
Quoted 4 lines
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
That would be nice to see. I can't see how devices and drivers are registered from user space with what's here. I see
iio_register_device()exported but no clue how userspace tells the kernel to claim a device or register an iio driver.His posted example should show you how this all works together.
thanks,
greg k-h
Quoted 11 lines · Greg KH
Quoted 5 lines · Matt Porter
Well, if it's focused on industrial controls like it appears from the code here then the name is fine. If it's a starting point to become someting more generic then User Space Driver (USD) subsystem might be nice.
It's not focused on industrial controls at all, that just happens to be the name of it right now, as that is why it was written. It is much more generic than that.
"USD" is a bit too close to "USB" for a name. Any other ideas?
DFU - Drivers for Userspace
DFU - Driver from Userspace
DFUF - Drivers for Userspace Framework
DIFUS - Drive It From Userspace :-)
FUD - Framework (for) Userspace Drivers ;-)
GUDI - Generic Userspace Driver Interface
UDF - Userspace Driver Framework :-)
UDI - Userspace Driver Interface :-)
UUDI - Unified Userspace Driver Interface
UFD - Userspace Framework (for) Drivers
...
Bis denn
Signature · 4 lines
Real Programmers consider "what you see is what you get" to be just as bad a concept in Text Editors as it is in women. No, the Real Programmer wants a "you asked for it, you got it" text editor -- complicated, cryptic, powerful, unforgiving, dangerous.
Quoted 24 lines · Matthias Schniedermeyer
Quoted 11 lines · Greg KH
Quoted 5 lines · Matt Porter
Well, if it's focused on industrial controls like it appears from the code here then the name is fine. If it's a starting point to become someting more generic then User Space Driver (USD) subsystem might be nice.
It's not focused on industrial controls at all, that just happens to be the name of it right now, as that is why it was written. It is much more generic than that.
"USD" is a bit too close to "USB" for a name. Any other ideas?
DFU - Drivers for Userspace
DFU - Driver from Userspace
DFUF - Drivers for Userspace Framework DIFUS - Drive It From Userspace :-) FUD - Framework (for) Userspace Drivers ;-) GUDI - Generic Userspace Driver Interface UDF - Userspace Driver Framework :-) UDI - Userspace Driver Interface :-) UUDI - Unified Userspace Driver Interface UFD - Userspace Framework (for) Drivers
Quoted 2 lines
Bis denn
Something to consider if/when you expose PCI to user-space is that protection on ix86 extends to PAGE_SIZE pages. This means that when you ioremap() some PCI addresses to user-space, user-mode code can write (or read) well beyond the few bytes that you may think that you have mapped! When you make a driver in the kernel, your code can check to see if the read or write is going to be out-of-bounds. When you mmap() something to user-space, its the user-space code that needs to protect hardware and/or the kernel. This is not good.
Let's say that I mapped() 512 bytes to access my controller. If I have a another controller, perhaps one for my SCSI disk, that's within that allocated page, I can easily "deprogram" the controller and fail the system, file-system, or both.
User mode drivers are NOT good. For them to work, too much stuff needs to be exposed. Then there is the problem of interrupts. You are not going to be able to make an interrupt 'thunker' like you could in the old DOS days. The kernel isn't going to call user-mode code because nobody is going to provide such a potentially destructive interface. If you think you can handle hardware interrupt requests with the poll() interface, you are going to be in a world of hurt for throughput.
Cheers,
Dick Johnson
Penguin : Linux version 2.6.16.24 on an i686 machine (5592.62 BogoMips). New book: http://www.AbominableFirebug.com/
_
****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.
Thank you.
Quoted 8 lines · linux-os (Dick Johnson)
User mode drivers are NOT good. For them to work, too much stuff needs to be exposed. Then there is the problem of interrupts. You are not going to be able to make an interrupt 'thunker' like you could in the old DOS days. The kernel isn't going to call user-mode code because nobody is going to provide such a potentially destructive interface. If you think you can handle hardware interrupt requests with the
poll()interface, you are going to be in a world of hurt for throughput.
If you feel this way, then don't use them on your system, for your hardware.
Quoted 18 lines · Greg KH
Quoted 16 lines · Matt Porter
Quoted 14 lines · Greg KH
A while ago, Thomas and I were sitting in the back of a conference presentation where the presenter was trying to describe what they did in order to add the ability to write a userspace PCI driver. As was usual in a presentation like this, the presenter totaly ignored the real-world needs for such a framework, and only got it up and working on a single type of embedded system. But the charts and graphs were quite pretty :)
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
Quoted 9 lines
Quoted 2 lines
What about portable access to the PCI DMA API from userspace?
It currently does not provide this, but if you know how your card works, I'm pretty sure you can get this working without such an interface.
If you wish to add this functionality, to make it easier, that would be great.
I might be nice to have something like a copy-block where the application writes/reads data, while the device does DMA only from/to there. We would need an easy way to mmap some anonymous DMA-ready memory in user-space, and something to give the corresponding DMA addresses to the application.
Additionally, the current code might not be flexible enough regarding acknowledging of interrupts. It might be good to use the bit that PCI 2.2 defines in the config space to mask/unmask interrupt in a generic way. Something like : when an interrupt comes, the driver mask the interrupts using this bit, and then passes the event to user-space. The user-space interrupt handler acknowledges the interrupt with the device specific code, and then unmask with the PCI 2.2 bit.
Brice
Quoted 5 lines · Brice Goglin
I might be nice to have something like a copy-block where the application writes/reads data, while the device does DMA only from/to there. We would need an easy way to mmap some anonymous DMA-ready memory in user-space, and something to give the corresponding DMA addresses to the application.
Sure, send a patch :)
Quoted 7 lines
Additionally, the current code might not be flexible enough regarding acknowledging of interrupts. It might be good to use the bit that PCI 2.2 defines in the config space to mask/unmask interrupt in a generic way. Something like : when an interrupt comes, the driver mask the interrupts using this bit, and then passes the event to user-space. The user-space interrupt handler acknowledges the interrupt with the device specific code, and then unmask with the PCI 2.2 bit.
You can do that today with this code. Remember, you have to have a tiny kernelspace portion of your driver to handle the interrupt. You can do whatever you want in that interrupt handler.
thanks,
greg k-h
Quoted 9 lines · Greg KH
Quoted 8 lines
Additionally, the current code might not be flexible enough regarding acknowledging of interrupts. It might be good to use the bit that PCI 2.2 defines in the config space to mask/unmask interrupt in a generic way. Something like : when an interrupt comes, the driver mask the interrupts using this bit, and then passes the event to user-space. The user-space interrupt handler acknowledges the interrupt with the device specific code, and then unmask with the PCI 2.2 bit.
Quoted 4 lines
You can do that today with this code. Remember, you have to have a tiny kernelspace portion of your driver to handle the interrupt. You can do whatever you want in that interrupt handler.
The whole point of masking interrupt with this config-space bit is that we might not need any tiny kernelspace portion for our driver anymore. It won't work for devices that are not PCI 2.2 compliant. But, it might be good for the ones that are?
Brice
Quoted 15 lines · Brice Goglin
Quoted 9 lines · Greg KH
Quoted 8 lines
Additionally, the current code might not be flexible enough regarding acknowledging of interrupts. It might be good to use the bit that PCI 2.2 defines in the config space to mask/unmask interrupt in a generic way. Something like : when an interrupt comes, the driver mask the interrupts using this bit, and then passes the event to user-space. The user-space interrupt handler acknowledges the interrupt with the device specific code, and then unmask with the PCI 2.2 bit.
Quoted 4 lines
You can do that today with this code. Remember, you have to have a tiny kernelspace portion of your driver to handle the interrupt. You can do whatever you want in that interrupt handler.
Quoted 4 lines
The whole point of masking interrupt with this config-space bit is that we might not need any tiny kernelspace portion for our driver anymore. It won't work for devices that are not PCI 2.2 compliant. But, it might be good for the ones that are?
I don't really know. I think 2.2 PCI devices might still be a bit rare, but do not know for sure.
thanks,
greg k-h
Quoted 2 lines · Matt Porter
What about portable access to the PCI DMA API from userspace?
We'll definitely need this for X11 anyways. Currently it is not possible to run the standard X server with a IOMMU that isolates the graphics card because it has no way to get at the GPU MMIO registers then.
My long-term plan was to integrate it in /sys/bus/pci mmaps (together with PAT etc.). When you mmap it there the kernel allocates a DMA mapping and then frees it on unmap.
Then it should hopefully just work.
-Andi
Quoted 4 lines · Andi Kleen
Quoted 2 lines · Matt Porter
What about portable access to the PCI DMA API from userspace?
Quoted 8 lines
We'll definitely need this for X11 anyways. Currently it is not possible to run the standard X server with a IOMMU that isolates the graphics card because it has no way to get at the GPU MMIO registers then.
My long-term plan was to integrate it in
/sys/bus/pcimmaps (together with PAT etc.). When you mmap it there the kernel allocates a DMA mapping and then frees it on unmap.
That sounds very reasonable, looking forward to it.
thanks,
greg k-h
Quoted 7 lines · Greg KH
A while ago, Thomas and I were sitting in the back of a conference presentation where the presenter was trying to describe what they did in order to add the ability to write a userspace PCI driver. As was usual in a presentation like this, the presenter totaly ignored the real-world needs for such a framework, and only got it up and working on a single type of embedded system. But the charts and graphs were quite pretty :)
Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
A while back, while we (myself and Andrew De Quincey) were struggling with new DVB frontend devices that needed math operations to be performed in the frontends themselves for frequency tracking / locking etc, we found that eventually userspace was a much better place to have such code, rather than being in kernel.
After quite some thoughts we found it would be much better to have them implemented in userspace. We did finally draw up to some conclusions, eventually.
We came up with some code eventually, but time was limited on our hands that we went into discussion of the newer delivery systems that came along, so development was a bit halted in that aspect.
http://www.thadathil.net/dvb/msg_transfer_interface
http://thadathil.net:8000/cgi-bin/hgwebdir.cgi/v4l-dvb-user
http://thadathil.net:8000/cgi-bin/hgwebdir.cgi/libdvbapi
Quoted 20 lines
Thomas mentioned that he had code to do all of this working in some customer sites already and that he would get it to me.
Fast forward to OLS of this year, and I bugged Thomas to send me the code. He did, and then I sat on it for a while longer...
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines. So it is possible to use this interface to successfully build your own laser wielding robot, all from userspace, allowing you to keep your special-secret-how-to-control-the-laser algorithm closed source if you so desire.
In looking at the proposed kevent interface, I think a few things in this proposed interface can be dropped in favor of using kevents instead, but I haven't looked at the latest version of that code to make sure of this.
Quoted 7 lines
And the name is a bit ackward, anyone have a better suggestion?
Thomas has also promised to come up with some userspace code that uses this interface to show how to use it, but seems to have forgotten. Consider this a reminder :)
Comments?
Being a bit excited and it is really interesting to have such a proposal, it would simplify the matters that held us up even more, probably. The name sounds fine though. All i was wondering whether there would be any high latencies for the same using in such a context. But since the transfers would occur in any way, even with a kernel mode driver, i think it should be pretty much fine.
Manu
Quoted 7 lines · Manu Abraham
Being a bit excited and it is really interesting to have such a proposal, it would simplify the matters that held us up even more, probably. The name sounds fine though. All i was wondering whether there would be any high latencies for the same using in such a context. But since the transfers would occur in any way, even with a kernel mode driver, i think it should be pretty much fine.
As mentioned, this framework is being used in industrial settings right now, where latencies are a huge issue. It works just fine, so I do not think there are any problems in this area.
thanks,
greg k-h
Quoted 11 lines · Greg KH
Quoted 6 lines · Manu Abraham
Being a bit excited and it is really interesting to have such a proposal, it would simplify the matters that held us up even more, probably. The name sounds fine though. All i was wondering whether there would be any high latencies for the same using in such a context. But since the transfers would occur in any way, even with a kernel mode driver, i think it should be pretty much fine.
As mentioned, this framework is being used in industrial settings right now, where latencies are a huge issue. It works just fine, so I do not think there are any problems in this area.
Cool.
Is there some way we can avoid the poll ? It would be a real gain indeed, if a POLL can be avoided.
Regards,
Manu
Quoted 9 lines · Manu Abraham
Quoted 8 lines · Greg KH
Quoted 6 lines · Manu Abraham
Being a bit excited and it is really interesting to have such a proposal, it would simplify the matters that held us up even more, probably. The name sounds fine though. All i was wondering whether there would be any high latencies for the same using in such a context. But since the transfers would occur in any way, even with a kernel mode driver, i think it should be pretty much fine.
Quoted 8 lines
Quoted 3 lines
As mentioned, this framework is being used in industrial settings right now, where latencies are a huge issue. It works just fine, so I do not think there are any problems in this area.
Cool.
Is there some way we can avoid the poll ? It would be a real gain indeed, if a POLL can be avoided.
Use the signal that will be sent to your userspace program when an interrupt happens.
If you can handle the small latency that causes it should be fine, but if you can't, then you should be using poll :)
It all depends on the hardware you are using, your processor, and what your tolerances are on your interrupt handling latency.
thanks,
greg k-h
Quoted 12 lines · Greg KH
Quoted 11 lines · Manu Abraham
Quoted 10 lines · Greg KH
Quoted 6 lines · Manu Abraham
Being a bit excited and it is really interesting to have such a proposal, it would simplify the matters that held us up even more, probably. The name sounds fine though. All i was wondering whether there would be any high latencies for the same using in such a context. But since the transfers would occur in any way, even with a kernel mode driver, i think it should be pretty much fine.
As mentioned, this framework is being used in industrial settings right now, where latencies are a huge issue. It works just fine, so I do not think there are any problems in this area.
Quoted 8 lines
Quoted 4 lines
Cool.
Is there some way we can avoid the poll ? It would be a real gain indeed, if a POLL can be avoided.
Use the signal that will be sent to your userspace program when an interrupt happens.
Ok, that said, If we had RT signalling, that would have been a quantum leap.
Quoted 3 lines
If you can handle the small latency that causes it should be fine, but if you can't, then you should be using poll :)
hmm.. having a choice does always hurt your brain. ;-)
Quoted 2 lines
It all depends on the hardware you are using, your processor, and what your tolerances are on your interrupt handling latency.
Usually in the typical application we have (where latency is an issue), most probably many of the people have a saturated PCI bus. In most cases, the IPTV guys have such a scenario. Say > 6 or 7 DVB adapters and the latency goes very high. What i have seen is that when the bus gets saturated, the CPU usage shoots of rather abnormally. When the latency goes higher, the resultant stream is useless and packets needs to be dropped, eventually that results in Transport Stream discontinuities.
Currently we already have a latency issue, based on the loud cries from some people.
Thanks,
Manu
Quoted 4 lines · Manu Abraham
Usually in the typical application we have (where latency is an issue), most probably many of the people have a saturated PCI bus. In most cases, the IPTV guys have such a scenario. Say > 6 or 7 DVB adapters and the latency goes very high.
Sure, when you are pushing your hardware to the maximum, you should expect issues like this. I agree we should do as best as we can for things like this, but when you over-subscribe your PCI bus by doing something like this, I really recommend just buying some hardware that will work better for you (separate PCI busses, etc. The hardware is out there to do this properly.)
Quoted 2 lines
What i have seen is that when the bus gets saturated, the CPU usage shoots of rather abnormally.
As is to be expected.
Quoted 3 lines
When the latency goes higher, the resultant stream is useless and packets needs to be dropped, eventually that results in Transport Stream discontinuities.
Sure, that's understandable.
Quoted 2 lines
Currently we already have a latency issue, based on the loud cries from some people.
Trying to do things the hardware is not ment to do, should not result in cries from users :)
thanks,
greg k-h
Quoted 20 lines · On Tue, 29 Aug 2006 23:23:38 -0700 Greg KH <[email protected]> wrote:
drivers/iio/iio_dummy.c new file +20
-0+static ssize_t store_sig_pid (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ + iio_dummy_signal.pid =simple_strtol (buf,NULL ,10 ); +if (iio_dummy_signal.pid ==0 ) { +if (iio_dummy_signal.it_process) { +put_task_struct (iio_dummy_signal.it_process); + iio_dummy_signal.it_process =NULL ; + } + + iio_dummy_signal.pid =0 ; +return count; + } + +if (iio_dummy_signal.pid ==1 ) + goto out; + + iio_dummy_signal.it_process =find_task_by_pid (iio_dummy_signal.pid); +if (iio_dummy_signal.it_process) { +get_task_struct (iio_dummy_signal.it_process);
drivers/iio/iio_dummy.c line 118
Quoted 10 lines
drivers/iio/iio_dummy.c new file +10
-0+ iio_dummy_signal.it_sigev_notify =SIGEV_SIGNAL ; + iio_dummy_signal.it_sigev_signo =SIGALRM ; + iio_dummy_signal.it_sigev_value.sival_int =0 ; + +return count; + } +out: + iio_dummy_signal.pid =0 ; +return -EINVAL ; +}
This is racy: find_task_by_pid() needs tasklist_lock or rcu_read_lock().
It doesn't work as a module due to missing __put_task_struct.
It is also rather nasty. Why go shoving some random pid into a sysfs file, then hang onto a ref on a task_struct for some process which exitted last week? It would be cleaner and more idiomatic to require that the controlling process hold an fd open against the instance so that resources can be managed correctly. Maybe use SIGIO too, so the driver doesn't need to know about pids and task_structs and things. Which all maps better onto ioctls than sysfs (ties self to stake)
<looks>
iio_dev.c seems to already be doing this. Why does iio_dummy.c exist?
Quoted 47 lines · Andrew Morton
Quoted 20 lines · On Tue, 29 Aug 2006 23:23:38 -0700 Greg KH <[email protected]> wrote:
drivers/iio/iio_dummy.c new file +20
-0+static ssize_t store_sig_pid (struct device *dev,struct device_attribute *attr, +const char *buf,size_t count) +{ + iio_dummy_signal.pid =simple_strtol (buf,NULL ,10 ); +if (iio_dummy_signal.pid ==0 ) { +if (iio_dummy_signal.it_process) { +put_task_struct (iio_dummy_signal.it_process); + iio_dummy_signal.it_process =NULL ; + } + + iio_dummy_signal.pid =0 ; +return count; + } + +if (iio_dummy_signal.pid ==1 ) + goto out; + + iio_dummy_signal.it_process =find_task_by_pid (iio_dummy_signal.pid); +if (iio_dummy_signal.it_process) { +get_task_struct (iio_dummy_signal.it_process);drivers/iio/iio_dummy.c line 118
Quoted 10 lines
drivers/iio/iio_dummy.c new file +10
-0+ iio_dummy_signal.it_sigev_notify =SIGEV_SIGNAL ; + iio_dummy_signal.it_sigev_signo =SIGALRM ; + iio_dummy_signal.it_sigev_value.sival_int =0 ; + +return count; + } +out: + iio_dummy_signal.pid =0 ; +return -EINVAL ; +}This is racy:
find_task_by_pid()needstasklist_lockorrcu_read_lock().It doesn't work as a module due to missing
__put_task_struct.It is also rather nasty. Why go shoving some random pid into a sysfs file, then hang onto a ref on a
task_structfor some process which exitted last week? It would be cleaner and more idiomatic to require that the controlling process hold an fd open against the instance so that resources can be managed correctly. Maybe use SIGIO too, so the driver doesn't need to know about pids andtask_structsand things. Which all maps better onto ioctls than sysfs (ties self to stake)
Quoted 3 lines
<looks>
iio_dev.cseems to already be doing this. Why doesiio_dummy.cexist?
Uurg. That's an old dummy/test driver which never got updated.
tglx
Hi Greg,
On Wed, 2006-08-30 at 08:23, Greg KH wrote:
[...]
Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
[...]
Quoted 1 line
So, here's the code.
I know I look like I'm trolling here, but as this is the perfect stable-binary-driver-ABI some people have been looking for, it would be wise to make it taint the kernel with its own flag.
Xav
Quoted 10 lines · Xavier Bestel
Hi Greg,
On Wed, 2006-08-30 at 08:23, Greg KH wrote:
[...]Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
Quoted 6 lines
[...]
Quoted 1 line
So, here's the code.
I know I look like I'm trolling here, but as this is the perfect stable-binary-driver-ABI some people have been looking for, it would be wise to make it taint the kernel with its own flag.
Why? There's no technical or legal requirement for userspace drivers to be GPLed.
Lee
Quoted 2 lines · Lee Revell
Why? There's no technical or legal requirement for userspace drivers to be GPLed.
I could see a benefit to tainting the kernel once userspace starts poking at the hardware directly. That way at least we'd know that a crash might be due to userspace doing bad things.
For instance, consider the case where userspace misprograms a DMA engine, which starts overwriting random kernel memory.
Chris
Quoted 11 lines · Chris Friesen
Quoted 2 lines · Lee Revell
Why? There's no technical or legal requirement for userspace drivers to be GPLed.
I could see a benefit to tainting the kernel once userspace starts poking at the hardware directly. That way at least we'd know that a crash might be due to userspace doing bad things.
For instance, consider the case where userspace misprograms a DMA engine, which starts overwriting random kernel memory.
Then you get to keep the two pieces that the kernel just broke into.
We can't "taint" anything here. Userspace is doing these kinds of things already today. You can mmap a PCI device and plug away at all sorts of fun things with it right now. You can to /dev/mem fun tricks, and all sorts of other 'evil' things.
And us kernel developers don't really care.
What this framework does, is give users who already do this kind of userspace driver thing today, a sane interface in which to do it. One that is simple and fast, and makes sense, unlike almost every other proposal like this that I have seen in the past.
We are trying to help people out here. Pushing drivers to userspace is a good thing from a kernel's perspective, if they work well for the driver in question. USB has been doing this for years quite well. This just allows the PCI interrupt to be sanely handled so PCI and other types of devices like it, can also work in a well defined way.
If a author of a driver doesn't want to put it in the kernel for whatever reason, that's fine, do it in userspace. Not all types of drivers make sense in the kernel as they don't need any of the things kernelspace is good for (speed, caching, common userspace interfaces, etc.)
So there is nothing to worry about here, except for more Linux based, laser welding robots taking over your neighborhood manufacturing plant.
And to answer the question that everyones been asking me in private, no, I have no idea if nVidia or ATI can use this interface to move their kerneldrivers out into userspace. I've never seen that code and do not know what their requirements are, nor do I care. Go ask them, they know this kind of thing, I sure don't. And if they can move them there, bully for them.
I don't know why people have this morbid fascination with these two, monstrously horrible closed source drivers. There are way more much more insidious and common closed source Linux kernel modules out there right now that everyone in the press seems to be ignoring. Those are the ones that I worry about...
And those are the ones that this interface might just help out with, and if that happens, it is a very good thing for Linux overall.
thanks,
greg k-h
Quoted 12 lines · Lee Revell
Quoted 11 lines · Xavier Bestel
Hi Greg,
On Wed, 2006-08-30 at 08:23, Greg KH wrote:
[...]Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
[...]
Quoted 8 lines
Quoted 5 lines
Quoted 1 line
So, here's the code.
I know I look like I'm trolling here, but as this is the perfect stable-binary-driver-ABI some people have been looking for, it would be wise to make it taint the kernel with its own flag.
Why? There's no technical or legal requirement for userspace drivers to be GPLed.
Precisely. How do you know the bugreport you received isn't caused by some weird binary userspace driver hosing the PCI bus ?
Xav
Quoted 2 lines · Xavier Bestel
Precisely. How do you know the bugreport you received isn't caused by some weird binary userspace driver hosing the PCI bus ?
Can't X, or any application that access hardware directly by mmaping /dev/mem, do this now?
Lee
Quoted 6 lines · Lee Revell
Quoted 2 lines · Xavier Bestel
Precisely. How do you know the bugreport you received isn't caused by some weird binary userspace driver hosing the PCI bus ?
Can't X, or any application that access hardware directly by mmaping
/dev/mem, do this now?
Yes they can, but X's behavior is pretty well known by now :) and it's open source.
Xav
Quoted 10 lines · Xavier Bestel
Quoted 5 lines · Lee Revell
Quoted 2 lines · Xavier Bestel
Precisely. How do you know the bugreport you received isn't caused by some weird binary userspace driver hosing the PCI bus ?
Can't X, or any application that access hardware directly by mmaping
/dev/mem, do this now?Yes they can, but X's behavior is pretty well known by now :) and it's open source.
what about binary drivers in kernel like nVidia or ATI ?
Well above all, user-space drivers can be of help in a lot of other ways. An example is rapid prototyping. Some times it makes sense as well to do in user-space, where you can really control things. Drivers using math is an example
Manu
Quoted 19 lines · Xavier Bestel
Le jeudi 31 ao?t 2006 ? 16:39 -0400, Lee Revell a ?crit :
Quoted 18 lines · Xavier Bestel
Quoted 16 lines
Hi Greg,
On Wed, 2006-08-30 at 08:23, Greg KH wrote:
[...]Quoted 6 lines
Thomas and I lamented that we were getting tired of seeing stuff like this, and it was about time that we added the proper code to the kernel to provide everything that would be needed in order to write PCI drivers in userspace in a sane manner. Really all that is needed is a way to handle the interrupt, everything else can already be done in userspace (look at X for an example of this...)
[...]
Quoted 1 line
So, here's the code.
I know I look like I'm trolling here, but as this is the perfect stable-binary-driver-ABI some people have been looking for, it would be wise to make it taint the kernel with its own flag.
Quoted 5 lines
Quoted 2 lines
Why? There's no technical or legal requirement for userspace drivers to be GPLed.
Precisely. How do you know the bugreport you received isn't caused by some weird binary userspace driver hosing the PCI bus ?
You don't know that today. Nothing new here. So no, adding a taint flag would achieve nothing. Unless you want to do that today for all the ways a userspace program can directly access a PCI device today?
greg k-h
Hi!
Quoted 1 line
And the name is a bit ackward, anyone have a better suggestion?
drivers/uio (for userspace io driver)?
And yes, I think this one _should_ taint the kernel. When userspace starts playing with interrupts, chances of kernel crash are high.
Does it work properly with pci shared interrupts?
Signature · 4 lines
Thanks for all the (sleeping) penguins. -- VGER BF report: H 0.000174266
Quoted 5 lines · Pavel Machek
Hi!
Quoted 1 line
And the name is a bit ackward, anyone have a better suggestion?
drivers/uio(for userspace io driver)?
not too bad.
Quoted 2 lines
And yes, I think this one _should_ taint the kernel. When userspace starts playing with interrupts, chances of kernel crash are high.
Userspace does not play with interrupts directly. You still have a small stub driver, which does the primary interrupt handling, else you would have a hard time to deal with shared irqs.
Quoted 1 line
Does it work properly with pci shared interrupts?
See the SERCOS example I posted.
tglx
Signature · 1 line
VGER BF report: U 0.500128
Quoted 5 lines · Greg KH
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines.
At present it is named uio in -mm. But that seems to conflict with a few cases (uio.h + Solaris).
How about:
Universal User IO => uuio
A quick google did not turn up anything conflicting.
[Lost the mail thread about naming so replying to this old mail instead].
Sam
Quoted 7 lines · Sam Ravnborg
Quoted 5 lines · Greg KH
So, here's the code. I think it does a bit too much all at once, but it is an example of how this can be done. This is working today in some industrial environments, successfully handling hardware controls of very large and scary machines.
Quoted 7 lines
At present it is named uio in -mm. But that seems to conflict with a few cases (
uio.h+ Solaris).How about:
Universal User IO => uuioA quick google did not turn up anything conflicting.
Ah, I like that better. I had made the header file be called uio_driver.h to get around the namespace issue, but uuio sounds nice.
thanks,
greg k-h