diff options
author | James Morris <jmorris@namei.org> | 2009-02-06 01:01:45 +0100 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-02-06 01:01:45 +0100 |
commit | cb5629b10d64a8006622ce3a52bc887d91057d69 (patch) | |
tree | 7c06d8f30783115e3384721046258ce615b129c5 /Documentation/DocBook/uio-howto.tmpl | |
parent | TPM: integrity fix (diff) | |
parent | seq_file: fix big-enough lseek() + read() (diff) | |
download | linux-cb5629b10d64a8006622ce3a52bc887d91057d69.tar.xz linux-cb5629b10d64a8006622ce3a52bc887d91057d69.zip |
Merge branch 'master' into next
Conflicts:
fs/namei.c
Manually merged per:
diff --cc fs/namei.c
index 734f2b5,bbc15c2..0000000
--- a/fs/namei.c
+++ b/fs/namei.c
@@@ -860,9 -848,8 +849,10 @@@ static int __link_path_walk(const char
nd->flags |= LOOKUP_CONTINUE;
err = exec_permission_lite(inode);
if (err == -EAGAIN)
- err = vfs_permission(nd, MAY_EXEC);
+ err = inode_permission(nd->path.dentry->d_inode,
+ MAY_EXEC);
+ if (!err)
+ err = ima_path_check(&nd->path, MAY_EXEC);
if (err)
break;
@@@ -1525,14 -1506,9 +1509,14 @@@ int may_open(struct path *path, int acc
flag &= ~O_TRUNC;
}
- error = vfs_permission(nd, acc_mode);
+ error = inode_permission(inode, acc_mode);
if (error)
return error;
+
- error = ima_path_check(&nd->path,
++ error = ima_path_check(path,
+ acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC));
+ if (error)
+ return error;
/*
* An append-only file must be opened in append mode for writing.
*/
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'Documentation/DocBook/uio-howto.tmpl')
-rw-r--r-- | Documentation/DocBook/uio-howto.tmpl | 189 |
1 files changed, 187 insertions, 2 deletions
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index df87d1b93605..52e1b79ce0e6 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -42,6 +42,18 @@ GPL version 2. <revhistory> <revision> + <revnumber>0.7</revnumber> + <date>2008-12-23</date> + <authorinitials>hjk</authorinitials> + <revremark>Added generic platform drivers and offset attribute.</revremark> + </revision> + <revision> + <revnumber>0.6</revnumber> + <date>2008-12-05</date> + <authorinitials>hjk</authorinitials> + <revremark>Added description of portio sysfs attributes.</revremark> + </revision> + <revision> <revnumber>0.5</revnumber> <date>2008-05-22</date> <authorinitials>hjk</authorinitials> @@ -306,6 +318,16 @@ interested in translating it, please email me pointed to by addr. </para> </listitem> +<listitem> + <para> + <filename>offset</filename>: The offset, in bytes, that has to be + added to the pointer returned by <function>mmap()</function> to get + to the actual device memory. This is important if the device's memory + is not page aligned. Remember that pointers returned by + <function>mmap()</function> are always page aligned, so it is good + style to always add this offset. + </para> +</listitem> </itemizedlist> <para> @@ -318,6 +340,54 @@ interested in translating it, please email me offset = N * getpagesize(); </programlisting> +<para> + Sometimes there is hardware with memory-like regions that can not be + mapped with the technique described here, but there are still ways to + access them from userspace. The most common example are x86 ioports. + On x86 systems, userspace can access these ioports using + <function>ioperm()</function>, <function>iopl()</function>, + <function>inb()</function>, <function>outb()</function>, and similar + functions. +</para> +<para> + Since these ioport regions can not be mapped, they will not appear under + <filename>/sys/class/uio/uioX/maps/</filename> like the normal memory + described above. Without information about the port regions a hardware + has to offer, it becomes difficult for the userspace part of the + driver to find out which ports belong to which UIO device. +</para> +<para> + To address this situation, the new directory + <filename>/sys/class/uio/uioX/portio/</filename> was added. It only + exists if the driver wants to pass information about one or more port + regions to userspace. If that is the case, subdirectories named + <filename>port0</filename>, <filename>port1</filename>, and so on, + will appear underneath + <filename>/sys/class/uio/uioX/portio/</filename>. +</para> +<para> + Each <filename>portX/</filename> directory contains three read-only + files that show start, size, and type of the port region: +</para> +<itemizedlist> +<listitem> + <para> + <filename>start</filename>: The first port of this region. + </para> +</listitem> +<listitem> + <para> + <filename>size</filename>: The number of ports in this region. + </para> +</listitem> +<listitem> + <para> + <filename>porttype</filename>: A string describing the type of port. + </para> +</listitem> +</itemizedlist> + + </sect1> </chapter> @@ -339,12 +409,12 @@ offset = N * getpagesize(); <itemizedlist> <listitem><para> -<varname>char *name</varname>: Required. The name of your driver as +<varname>const char *name</varname>: Required. The name of your driver as it will appear in sysfs. I recommend using the name of your module for this. </para></listitem> <listitem><para> -<varname>char *version</varname>: Required. This string appears in +<varname>const char *version</varname>: Required. This string appears in <filename>/sys/class/uio/uioX/version</filename>. </para></listitem> @@ -356,6 +426,13 @@ See the description below for details. </para></listitem> <listitem><para> +<varname>struct uio_port port[ MAX_UIO_PORTS_REGIONS ]</varname>: Required +if you want to pass information about ioports to userspace. For each port +region you need to fill one of the <varname>uio_port</varname> structures. +See the description below for details. +</para></listitem> + +<listitem><para> <varname>long irq</varname>: Required. If your hardware generates an interrupt, it's your modules task to determine the irq number during initialization. If you don't have a hardware generated interrupt but @@ -448,6 +525,42 @@ Please do not touch the <varname>kobj</varname> element of <varname>struct uio_mem</varname>! It is used by the UIO framework to set up sysfs files for this mapping. Simply leave it alone. </para> + +<para> +Sometimes, your device can have one or more port regions which can not be +mapped to userspace. But if there are other possibilities for userspace to +access these ports, it makes sense to make information about the ports +available in sysfs. For each region, you have to set up a +<varname>struct uio_port</varname> in the <varname>port[]</varname> array. +Here's a description of the fields of <varname>struct uio_port</varname>: +</para> + +<itemizedlist> +<listitem><para> +<varname>char *porttype</varname>: Required. Set this to one of the predefined +constants. Use <varname>UIO_PORT_X86</varname> for the ioports found in x86 +architectures. +</para></listitem> + +<listitem><para> +<varname>unsigned long start</varname>: Required if the port region is used. +Fill in the number of the first port of this region. +</para></listitem> + +<listitem><para> +<varname>unsigned long size</varname>: Fill in the number of ports in this +region. If <varname>size</varname> is zero, the region is considered unused. +Note that you <emphasis>must</emphasis> initialize <varname>size</varname> +with zero for all unused regions. +</para></listitem> +</itemizedlist> + +<para> +Please do not touch the <varname>portio</varname> element of +<varname>struct uio_port</varname>! It is used internally by the UIO +framework to set up sysfs files for this region. Simply leave it alone. +</para> + </sect1> <sect1 id="adding_irq_handler"> @@ -497,6 +610,78 @@ to set up sysfs files for this mapping. Simply leave it alone. </para> </sect1> +<sect1 id="using_uio_pdrv"> +<title>Using uio_pdrv for platform devices</title> + <para> + In many cases, UIO drivers for platform devices can be handled in a + generic way. In the same place where you define your + <varname>struct platform_device</varname>, you simply also implement + your interrupt handler and fill your + <varname>struct uio_info</varname>. A pointer to this + <varname>struct uio_info</varname> is then used as + <varname>platform_data</varname> for your platform device. + </para> + <para> + You also need to set up an array of <varname>struct resource</varname> + containing addresses and sizes of your memory mappings. This + information is passed to the driver using the + <varname>.resource</varname> and <varname>.num_resources</varname> + elements of <varname>struct platform_device</varname>. + </para> + <para> + You now have to set the <varname>.name</varname> element of + <varname>struct platform_device</varname> to + <varname>"uio_pdrv"</varname> to use the generic UIO platform device + driver. This driver will fill the <varname>mem[]</varname> array + according to the resources given, and register the device. + </para> + <para> + The advantage of this approach is that you only have to edit a file + you need to edit anyway. You do not have to create an extra driver. + </para> +</sect1> + +<sect1 id="using_uio_pdrv_genirq"> +<title>Using uio_pdrv_genirq for platform devices</title> + <para> + Especially in embedded devices, you frequently find chips where the + irq pin is tied to its own dedicated interrupt line. In such cases, + where you can be really sure the interrupt is not shared, we can take + the concept of <varname>uio_pdrv</varname> one step further and use a + generic interrupt handler. That's what + <varname>uio_pdrv_genirq</varname> does. + </para> + <para> + The setup for this driver is the same as described above for + <varname>uio_pdrv</varname>, except that you do not implement an + interrupt handler. The <varname>.handler</varname> element of + <varname>struct uio_info</varname> must remain + <varname>NULL</varname>. The <varname>.irq_flags</varname> element + must not contain <varname>IRQF_SHARED</varname>. + </para> + <para> + You will set the <varname>.name</varname> element of + <varname>struct platform_device</varname> to + <varname>"uio_pdrv_genirq"</varname> to use this driver. + </para> + <para> + The generic interrupt handler of <varname>uio_pdrv_genirq</varname> + will simply disable the interrupt line using + <function>disable_irq_nosync()</function>. After doing its work, + userspace can reenable the interrupt by writing 0x00000001 to the UIO + device file. The driver already implements an + <function>irq_control()</function> to make this possible, you must not + implement your own. + </para> + <para> + Using <varname>uio_pdrv_genirq</varname> not only saves a few lines of + interrupt handler code. You also do not need to know anything about + the chip's internal registers to create the kernel part of the driver. + All you need to know is the irq number of the pin the chip is + connected to. + </para> +</sect1> + </chapter> <chapter id="userspace_driver" xreflabel="Writing a driver in user space"> |