Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next
Backmerge to catch up with 4.3. slightly more involved conflict in the irq code, but nothing beyond adjacent changes. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
This commit is contained in:
@@ -15,7 +15,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
|
||||
80211.xml debugobjects.xml sh.xml regulator.xml \
|
||||
alsa-driver-api.xml writing-an-alsa-driver.xml \
|
||||
tracepoint.xml drm.xml media_api.xml w1.xml \
|
||||
writing_musb_glue_layer.xml crypto-API.xml
|
||||
writing_musb_glue_layer.xml crypto-API.xml iio.xml
|
||||
|
||||
include Documentation/DocBook/media/Makefile
|
||||
|
||||
@@ -56,16 +56,19 @@ htmldocs: $(HTML)
|
||||
|
||||
MAN := $(patsubst %.xml, %.9, $(BOOKS))
|
||||
mandocs: $(MAN)
|
||||
find $(obj)/man -name '*.9' | xargs gzip -f
|
||||
find $(obj)/man -name '*.9' | xargs gzip -nf
|
||||
|
||||
installmandocs: mandocs
|
||||
mkdir -p /usr/local/man/man9/
|
||||
install $(obj)/man/*.9.gz /usr/local/man/man9/
|
||||
find $(obj)/man -name '*.9.gz' -printf '%h %f\n' | \
|
||||
sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \
|
||||
xargs install -m 644 -t /usr/local/man/man9/
|
||||
|
||||
###
|
||||
#External programs used
|
||||
KERNELDOC = $(srctree)/scripts/kernel-doc
|
||||
DOCPROC = $(objtree)/scripts/docproc
|
||||
KERNELDOCXMLREF = $(srctree)/scripts/kernel-doc-xml-ref
|
||||
KERNELDOC = $(srctree)/scripts/kernel-doc
|
||||
DOCPROC = $(objtree)/scripts/docproc
|
||||
|
||||
XMLTOFLAGS = -m $(srctree)/$(src)/stylesheet.xsl
|
||||
XMLTOFLAGS += --skip-validation
|
||||
@@ -89,7 +92,7 @@ define rule_docproc
|
||||
) > $(dir $@).$(notdir $@).cmd
|
||||
endef
|
||||
|
||||
%.xml: %.tmpl $(KERNELDOC) $(DOCPROC) FORCE
|
||||
%.xml: %.tmpl $(KERNELDOC) $(DOCPROC) $(KERNELDOCXMLREF) FORCE
|
||||
$(call if_changed_rule,docproc)
|
||||
|
||||
# Tell kbuild to always build the programs
|
||||
@@ -140,7 +143,20 @@ quiet_cmd_db2html = HTML $@
|
||||
echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/index.html"> \
|
||||
$(patsubst %.html,%,$(notdir $@))</a><p>' > $@
|
||||
|
||||
%.html: %.xml
|
||||
###
|
||||
# Rules to create an aux XML and .db, and use them to re-process the DocBook XML
|
||||
# to fill internal hyperlinks
|
||||
gen_aux_xml = :
|
||||
quiet_gen_aux_xml = echo ' XMLREF $@'
|
||||
silent_gen_aux_xml = :
|
||||
%.aux.xml: %.xml
|
||||
@$($(quiet)gen_aux_xml)
|
||||
@rm -rf $@
|
||||
@(cat $< | egrep "^<refentry id" | egrep -o "\".*\"" | cut -f 2 -d \" > $<.db)
|
||||
@$(KERNELDOCXMLREF) -db $<.db $< > $@
|
||||
.PRECIOUS: %.aux.xml
|
||||
|
||||
%.html: %.aux.xml
|
||||
@(which xmlto > /dev/null 2>&1) || \
|
||||
(echo "*** You need to install xmlto ***"; \
|
||||
exit 1)
|
||||
@@ -150,12 +166,12 @@ quiet_cmd_db2html = HTML $@
|
||||
cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
|
||||
|
||||
quiet_cmd_db2man = MAN $@
|
||||
cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man $< ; fi
|
||||
cmd_db2man = if grep -q refentry $<; then xmlto man $(XMLTOFLAGS) -o $(obj)/man/$(*F) $< ; fi
|
||||
%.9 : %.xml
|
||||
@(which xmlto > /dev/null 2>&1) || \
|
||||
(echo "*** You need to install xmlto ***"; \
|
||||
exit 1)
|
||||
$(Q)mkdir -p $(obj)/man
|
||||
$(Q)mkdir -p $(obj)/man/$(*F)
|
||||
$(call cmd,db2man)
|
||||
@touch $@
|
||||
|
||||
@@ -209,15 +225,18 @@ dochelp:
|
||||
###
|
||||
# Temporary files left by various tools
|
||||
clean-files := $(DOCBOOKS) \
|
||||
$(patsubst %.xml, %.dvi, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.aux, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.tex, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.log, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.out, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.ps, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.html, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.dvi, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.aux, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.tex, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.log, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.out, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.ps, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.html, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.aux.xml, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.xml.db, $(DOCBOOKS)) \
|
||||
$(patsubst %.xml, %.xml, $(DOCBOOKS)) \
|
||||
$(index)
|
||||
|
||||
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
|
||||
|
@@ -108,7 +108,7 @@
|
||||
<sect1><title>ASoC Core API</title>
|
||||
!Iinclude/sound/soc.h
|
||||
!Esound/soc/soc-core.c
|
||||
!Esound/soc/soc-cache.c
|
||||
<!-- !Esound/soc/soc-cache.c no docbook comments here -->
|
||||
!Esound/soc/soc-devres.c
|
||||
!Esound/soc/soc-io.c
|
||||
!Esound/soc/soc-pcm.c
|
||||
|
@@ -585,7 +585,7 @@ kernel crypto API | IPSEC Layer
|
||||
+-----------+ |
|
||||
| | (1)
|
||||
| aead | <----------------------------------- esp_output
|
||||
| (seqniv) | ---+
|
||||
| (seqiv) | ---+
|
||||
+-----------+ |
|
||||
| (2)
|
||||
+-----------+ |
|
||||
@@ -1101,7 +1101,7 @@ kernel crypto API | Caller
|
||||
</para>
|
||||
|
||||
<para>
|
||||
[1] http://www.chronox.de/libkcapi.html
|
||||
[1] <ulink url="http://www.chronox.de/libkcapi.html">http://www.chronox.de/libkcapi.html</ulink>
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
@@ -1661,7 +1661,7 @@ read(opfd, out, outlen);
|
||||
</para>
|
||||
|
||||
<para>
|
||||
[1] http://www.chronox.de/libkcapi.html
|
||||
[1] <ulink url="http://www.chronox.de/libkcapi.html">http://www.chronox.de/libkcapi.html</ulink>
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
@@ -1687,7 +1687,7 @@ read(opfd, out, outlen);
|
||||
!Pinclude/linux/crypto.h Block Cipher Algorithm Definitions
|
||||
!Finclude/linux/crypto.h crypto_alg
|
||||
!Finclude/linux/crypto.h ablkcipher_alg
|
||||
!Finclude/linux/crypto.h aead_alg
|
||||
!Finclude/crypto/aead.h aead_alg
|
||||
!Finclude/linux/crypto.h blkcipher_alg
|
||||
!Finclude/linux/crypto.h cipher_alg
|
||||
!Finclude/crypto/rng.h rng_alg
|
||||
|
@@ -66,6 +66,7 @@
|
||||
!Ekernel/time/hrtimer.c
|
||||
</sect1>
|
||||
<sect1><title>Workqueues and Kevents</title>
|
||||
!Iinclude/linux/workqueue.h
|
||||
!Ekernel/workqueue.c
|
||||
</sect1>
|
||||
<sect1><title>Internal Functions</title>
|
||||
@@ -216,6 +217,40 @@ X!Isound/sound_firmware.c
|
||||
-->
|
||||
</chapter>
|
||||
|
||||
<chapter id="mediadev">
|
||||
<title>Media Devices</title>
|
||||
|
||||
<sect1><title>Video2Linux devices</title>
|
||||
!Iinclude/media/v4l2-async.h
|
||||
!Iinclude/media/v4l2-ctrls.h
|
||||
!Iinclude/media/v4l2-dv-timings.h
|
||||
!Iinclude/media/v4l2-event.h
|
||||
!Iinclude/media/v4l2-flash-led-class.h
|
||||
!Iinclude/media/v4l2-mediabus.h
|
||||
!Iinclude/media/v4l2-mem2mem.h
|
||||
!Iinclude/media/v4l2-of.h
|
||||
!Iinclude/media/v4l2-subdev.h
|
||||
!Iinclude/media/videobuf2-core.h
|
||||
!Iinclude/media/videobuf2-memops.h
|
||||
</sect1>
|
||||
<sect1><title>Digital TV (DVB) devices</title>
|
||||
!Idrivers/media/dvb-core/dvb_ca_en50221.h
|
||||
!Idrivers/media/dvb-core/dvb_frontend.h
|
||||
!Idrivers/media/dvb-core/dvb_math.h
|
||||
!Idrivers/media/dvb-core/dvb_ringbuffer.h
|
||||
!Idrivers/media/dvb-core/dvbdev.h
|
||||
</sect1>
|
||||
<sect1><title>Remote Controller devices</title>
|
||||
!Iinclude/media/rc-core.h
|
||||
</sect1>
|
||||
<sect1><title>Media Controller devices</title>
|
||||
!Iinclude/media/media-device.h
|
||||
!Iinclude/media/media-devnode.h
|
||||
!Iinclude/media/media-entity.h
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="uart16x50">
|
||||
<title>16x50 UART Driver</title>
|
||||
!Edrivers/tty/serial/serial_core.c
|
||||
@@ -455,4 +490,31 @@ X!Ilib/fonts/fonts.c
|
||||
!Edrivers/hsi/hsi.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="pwm">
|
||||
<title>Pulse-Width Modulation (PWM)</title>
|
||||
<para>
|
||||
Pulse-width modulation is a modulation technique primarily used to
|
||||
control power supplied to electrical devices.
|
||||
</para>
|
||||
<para>
|
||||
The PWM framework provides an abstraction for providers and consumers
|
||||
of PWM signals. A controller that provides one or more PWM signals is
|
||||
registered as <structname>struct pwm_chip</structname>. Providers are
|
||||
expected to embed this structure in a driver-specific structure. This
|
||||
structure contains fields that describe a particular chip.
|
||||
</para>
|
||||
<para>
|
||||
A chip exposes one or more PWM signal sources, each of which exposed
|
||||
as a <structname>struct pwm_device</structname>. Operations can be
|
||||
performed on PWM devices to control the period, duty cycle, polarity
|
||||
and active state of the signal.
|
||||
</para>
|
||||
<para>
|
||||
Note that PWM devices are exclusive resources: they can always only be
|
||||
used by one consumer at a time.
|
||||
</para>
|
||||
!Iinclude/linux/pwm.h
|
||||
!Edrivers/pwm/core.c
|
||||
</chapter>
|
||||
|
||||
</book>
|
||||
|
@@ -3646,7 +3646,7 @@ void (*postclose) (struct drm_device *, struct drm_file *);</synopsis>
|
||||
plane properties to default value, so that a subsequent open of the
|
||||
device will not inherit state from the previous user. It can also be
|
||||
used to execute delayed power switching state changes, e.g. in
|
||||
conjunction with the vga-switcheroo infrastructure. Beyond that KMS
|
||||
conjunction with the vga_switcheroo infrastructure. Beyond that KMS
|
||||
drivers should not do any further cleanup. Only legacy UMS drivers might
|
||||
need to clean up device state so that the vga console or an independent
|
||||
fbdev driver could take over.
|
||||
|
@@ -146,36 +146,30 @@
|
||||
The journalling layer is easy to use. You need to
|
||||
first of all create a journal_t data structure. There are
|
||||
two calls to do this dependent on how you decide to allocate the physical
|
||||
media on which the journal resides. The journal_init_inode() call
|
||||
is for journals stored in filesystem inodes, or the journal_init_dev()
|
||||
call can be use for journal stored on a raw device (in a continuous range
|
||||
media on which the journal resides. The jbd2_journal_init_inode() call
|
||||
is for journals stored in filesystem inodes, or the jbd2_journal_init_dev()
|
||||
call can be used for journal stored on a raw device (in a continuous range
|
||||
of blocks). A journal_t is a typedef for a struct pointer, so when
|
||||
you are finally finished make sure you call journal_destroy() on it
|
||||
you are finally finished make sure you call jbd2_journal_destroy() on it
|
||||
to free up any used kernel memory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you have got your journal_t object you need to 'mount' or load the journal
|
||||
file, unless of course you haven't initialised it yet - in which case you
|
||||
need to call journal_create().
|
||||
file. The journalling layer expects the space for the journal was already
|
||||
allocated and initialized properly by the userspace tools. When loading the
|
||||
journal you must call jbd2_journal_load() to process journal contents. If the
|
||||
client file system detects the journal contents does not need to be processed
|
||||
(or even need not have valid contents), it may call jbd2_journal_wipe() to
|
||||
clear the journal contents before calling jbd2_journal_load().
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Most of the time however your journal file will already have been created, but
|
||||
before you load it you must call journal_wipe() to empty the journal file.
|
||||
Hang on, you say , what if the filesystem wasn't cleanly umount()'d . Well, it is the
|
||||
job of the client file system to detect this and skip the call to journal_wipe().
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In either case the next call should be to journal_load() which prepares the
|
||||
journal file for use. Note that journal_wipe(..,0) calls journal_skip_recovery()
|
||||
for you if it detects any outstanding transactions in the journal and similarly
|
||||
journal_load() will call journal_recover() if necessary.
|
||||
I would advise reading fs/ext3/super.c for examples on this stage.
|
||||
[RGG: Why is the journal_wipe() call necessary - doesn't this needlessly
|
||||
complicate the API. Or isn't a good idea for the journal layer to hide
|
||||
dirty mounts from the client fs]
|
||||
Note that jbd2_journal_wipe(..,0) calls jbd2_journal_skip_recovery() for you if
|
||||
it detects any outstanding transactions in the journal and similarly
|
||||
jbd2_journal_load() will call jbd2_journal_recover() if necessary. I would
|
||||
advise reading ext4_load_journal() in fs/ext4/super.c for examples on this
|
||||
stage.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -189,41 +183,41 @@ You still need to actually journal your filesystem changes, this
|
||||
is done by wrapping them into transactions. Additionally you
|
||||
also need to wrap the modification of each of the buffers
|
||||
with calls to the journal layer, so it knows what the modifications
|
||||
you are actually making are. To do this use journal_start() which
|
||||
you are actually making are. To do this use jbd2_journal_start() which
|
||||
returns a transaction handle.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
journal_start()
|
||||
and its counterpart journal_stop(), which indicates the end of a transaction
|
||||
are nestable calls, so you can reenter a transaction if necessary,
|
||||
but remember you must call journal_stop() the same number of times as
|
||||
journal_start() before the transaction is completed (or more accurately
|
||||
leaves the update phase). Ext3/VFS makes use of this feature to simplify
|
||||
quota support.
|
||||
jbd2_journal_start()
|
||||
and its counterpart jbd2_journal_stop(), which indicates the end of a
|
||||
transaction are nestable calls, so you can reenter a transaction if necessary,
|
||||
but remember you must call jbd2_journal_stop() the same number of times as
|
||||
jbd2_journal_start() before the transaction is completed (or more accurately
|
||||
leaves the update phase). Ext4/VFS makes use of this feature to simplify
|
||||
handling of inode dirtying, quota support, etc.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Inside each transaction you need to wrap the modifications to the
|
||||
individual buffers (blocks). Before you start to modify a buffer you
|
||||
need to call journal_get_{create,write,undo}_access() as appropriate,
|
||||
need to call jbd2_journal_get_{create,write,undo}_access() as appropriate,
|
||||
this allows the journalling layer to copy the unmodified data if it
|
||||
needs to. After all the buffer may be part of a previously uncommitted
|
||||
transaction.
|
||||
At this point you are at last ready to modify a buffer, and once
|
||||
you are have done so you need to call journal_dirty_{meta,}data().
|
||||
you are have done so you need to call jbd2_journal_dirty_{meta,}data().
|
||||
Or if you've asked for access to a buffer you now know is now longer
|
||||
required to be pushed back on the device you can call journal_forget()
|
||||
required to be pushed back on the device you can call jbd2_journal_forget()
|
||||
in much the same way as you might have used bforget() in the past.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A journal_flush() may be called at any time to commit and checkpoint
|
||||
A jbd2_journal_flush() may be called at any time to commit and checkpoint
|
||||
all your transactions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Then at umount time , in your put_super() you can then call journal_destroy()
|
||||
Then at umount time , in your put_super() you can then call jbd2_journal_destroy()
|
||||
to clean up your in-core journal object.
|
||||
</para>
|
||||
|
||||
@@ -231,82 +225,74 @@ to clean up your in-core journal object.
|
||||
Unfortunately there a couple of ways the journal layer can cause a deadlock.
|
||||
The first thing to note is that each task can only have
|
||||
a single outstanding transaction at any one time, remember nothing
|
||||
commits until the outermost journal_stop(). This means
|
||||
commits until the outermost jbd2_journal_stop(). This means
|
||||
you must complete the transaction at the end of each file/inode/address
|
||||
etc. operation you perform, so that the journalling system isn't re-entered
|
||||
on another journal. Since transactions can't be nested/batched
|
||||
across differing journals, and another filesystem other than
|
||||
yours (say ext3) may be modified in a later syscall.
|
||||
yours (say ext4) may be modified in a later syscall.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The second case to bear in mind is that journal_start() can
|
||||
The second case to bear in mind is that jbd2_journal_start() can
|
||||
block if there isn't enough space in the journal for your transaction
|
||||
(based on the passed nblocks param) - when it blocks it merely(!) needs to
|
||||
wait for transactions to complete and be committed from other tasks,
|
||||
so essentially we are waiting for journal_stop(). So to avoid
|
||||
deadlocks you must treat journal_start/stop() as if they
|
||||
so essentially we are waiting for jbd2_journal_stop(). So to avoid
|
||||
deadlocks you must treat jbd2_journal_start/stop() as if they
|
||||
were semaphores and include them in your semaphore ordering rules to prevent
|
||||
deadlocks. Note that journal_extend() has similar blocking behaviour to
|
||||
journal_start() so you can deadlock here just as easily as on journal_start().
|
||||
deadlocks. Note that jbd2_journal_extend() has similar blocking behaviour to
|
||||
jbd2_journal_start() so you can deadlock here just as easily as on
|
||||
jbd2_journal_start().
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Try to reserve the right number of blocks the first time. ;-). This will
|
||||
be the maximum number of blocks you are going to touch in this transaction.
|
||||
I advise having a look at at least ext3_jbd.h to see the basis on which
|
||||
ext3 uses to make these decisions.
|
||||
I advise having a look at at least ext4_jbd.h to see the basis on which
|
||||
ext4 uses to make these decisions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Another wriggle to watch out for is your on-disk block allocation strategy.
|
||||
why? Because, if you undo a delete, you need to ensure you haven't reused any
|
||||
of the freed blocks in a later transaction. One simple way of doing this
|
||||
is make sure any blocks you allocate only have checkpointed transactions
|
||||
listed against them. Ext3 does this in ext3_test_allocatable().
|
||||
Why? Because, if you do a delete, you need to ensure you haven't reused any
|
||||
of the freed blocks until the transaction freeing these blocks commits. If you
|
||||
reused these blocks and crash happens, there is no way to restore the contents
|
||||
of the reallocated blocks at the end of the last fully committed transaction.
|
||||
|
||||
One simple way of doing this is to mark blocks as free in internal in-memory
|
||||
block allocation structures only after the transaction freeing them commits.
|
||||
Ext4 uses journal commit callback for this purpose.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Lock is also providing through journal_{un,}lock_updates(),
|
||||
ext3 uses this when it wants a window with a clean and stable fs for a moment.
|
||||
eg.
|
||||
With journal commit callbacks you can ask the journalling layer to call a
|
||||
callback function when the transaction is finally committed to disk, so that
|
||||
you can do some of your own management. You ask the journalling layer for
|
||||
calling the callback by simply setting journal->j_commit_callback function
|
||||
pointer and that function is called after each transaction commit. You can also
|
||||
use transaction->t_private_list for attaching entries to a transaction that
|
||||
need processing when the transaction commits.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
JBD2 also provides a way to block all transaction updates via
|
||||
jbd2_journal_{un,}lock_updates(). Ext4 uses this when it wants a window with a
|
||||
clean and stable fs for a moment. E.g.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
|
||||
journal_lock_updates() //stop new stuff happening..
|
||||
journal_flush() // checkpoint everything.
|
||||
jbd2_journal_lock_updates() //stop new stuff happening..
|
||||
jbd2_journal_flush() // checkpoint everything.
|
||||
..do stuff on stable fs
|
||||
journal_unlock_updates() // carry on with filesystem use.
|
||||
jbd2_journal_unlock_updates() // carry on with filesystem use.
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
The opportunities for abuse and DOS attacks with this should be obvious,
|
||||
if you allow unprivileged userspace to trigger codepaths containing these
|
||||
calls.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A new feature of jbd since 2.5.25 is commit callbacks with the new
|
||||
journal_callback_set() function you can now ask the journalling layer
|
||||
to call you back when the transaction is finally committed to disk, so that
|
||||
you can do some of your own management. The key to this is the journal_callback
|
||||
struct, this maintains the internal callback information but you can
|
||||
extend it like this:-
|
||||
</para>
|
||||
<programlisting>
|
||||
struct myfs_callback_s {
|
||||
//Data structure element required by jbd..
|
||||
struct journal_callback for_jbd;
|
||||
// Stuff for myfs allocated together.
|
||||
myfs_inode* i_commited;
|
||||
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
<para>
|
||||
this would be useful if you needed to know when data was committed to a
|
||||
particular inode.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
@@ -319,36 +305,6 @@ being each mount, each modification (transaction) and each changed buffer
|
||||
to tell the journalling layer about them.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is a some pseudo code to give you an idea of how it works, as
|
||||
an example.
|
||||
</para>
|
||||
|
||||
<programlisting>
|
||||
journal_t* my_jnrl = journal_create();
|
||||
journal_init_{dev,inode}(jnrl,...)
|
||||
if (clean) journal_wipe();
|
||||
journal_load();
|
||||
|
||||
foreach(transaction) { /*transactions must be
|
||||
completed before
|
||||
a syscall returns to
|
||||
userspace*/
|
||||
|
||||
handle_t * xct=journal_start(my_jnrl);
|
||||
foreach(bh) {
|
||||
journal_get_{create,write,undo}_access(xact,bh);
|
||||
if ( myfs_modify(bh) ) { /* returns true
|
||||
if makes changes */
|
||||
journal_dirty_{meta,}data(xact,bh);
|
||||
} else {
|
||||
journal_forget(bh);
|
||||
}
|
||||
}
|
||||
journal_stop(xct);
|
||||
}
|
||||
journal_destroy(my_jrnl);
|
||||
</programlisting>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
@@ -357,13 +313,13 @@ an example.
|
||||
<title>Data Types</title>
|
||||
<para>
|
||||
The journalling layer uses typedefs to 'hide' the concrete definitions
|
||||
of the structures used. As a client of the JBD layer you can
|
||||
of the structures used. As a client of the JBD2 layer you can
|
||||
just rely on the using the pointer as a magic cookie of some sort.
|
||||
|
||||
Obviously the hiding is not enforced as this is 'C'.
|
||||
</para>
|
||||
<sect2 id="structures"><title>Structures</title>
|
||||
!Iinclude/linux/jbd.h
|
||||
!Iinclude/linux/jbd2.h
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
@@ -375,11 +331,11 @@ an example.
|
||||
manage transactions
|
||||
</para>
|
||||
<sect2 id="journal_level"><title>Journal Level</title>
|
||||
!Efs/jbd/journal.c
|
||||
!Ifs/jbd/recovery.c
|
||||
!Efs/jbd2/journal.c
|
||||
!Ifs/jbd2/recovery.c
|
||||
</sect2>
|
||||
<sect2 id="transaction_level"><title>Transasction Level</title>
|
||||
!Efs/jbd/transaction.c
|
||||
!Efs/jbd2/transaction.c
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1 id="see_also">
|
||||
|
697
Documentation/DocBook/iio.tmpl
Normal file
697
Documentation/DocBook/iio.tmpl
Normal file
@@ -0,0 +1,697 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
|
||||
|
||||
<book id="iioid">
|
||||
<bookinfo>
|
||||
<title>Industrial I/O driver developer's guide </title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Daniel</firstname>
|
||||
<surname>Baluta</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>daniel.baluta@intel.com</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2015</year>
|
||||
<holder>Intel Corporation</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
This documentation is free software; you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public
|
||||
License version 2.
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="intro">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
The main purpose of the Industrial I/O subsystem (IIO) is to provide
|
||||
support for devices that in some sense perform either analog-to-digital
|
||||
conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
|
||||
is to fill the gap between the somewhat similar hwmon and input
|
||||
subsystems.
|
||||
Hwmon is directed at low sample rate sensors used to monitor and
|
||||
control the system itself, like fan speed control or temperature
|
||||
measurement. Input is, as its name suggests, focused on human interaction
|
||||
input devices (keyboard, mouse, touchscreen). In some cases there is
|
||||
considerable overlap between these and IIO.
|
||||
</para>
|
||||
<para>
|
||||
Devices that fall into this category include:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
analog to digital converters (ADCs)
|
||||
</listitem>
|
||||
<listitem>
|
||||
accelerometers
|
||||
</listitem>
|
||||
<listitem>
|
||||
capacitance to digital converters (CDCs)
|
||||
</listitem>
|
||||
<listitem>
|
||||
digital to analog converters (DACs)
|
||||
</listitem>
|
||||
<listitem>
|
||||
gyroscopes
|
||||
</listitem>
|
||||
<listitem>
|
||||
inertial measurement units (IMUs)
|
||||
</listitem>
|
||||
<listitem>
|
||||
color and light sensors
|
||||
</listitem>
|
||||
<listitem>
|
||||
magnetometers
|
||||
</listitem>
|
||||
<listitem>
|
||||
pressure sensors
|
||||
</listitem>
|
||||
<listitem>
|
||||
proximity sensors
|
||||
</listitem>
|
||||
<listitem>
|
||||
temperature sensors
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
Usually these sensors are connected via SPI or I2C. A common use case of the
|
||||
sensors devices is to have combined functionality (e.g. light plus proximity
|
||||
sensor).
|
||||
</para>
|
||||
</chapter>
|
||||
<chapter id='iiosubsys'>
|
||||
<title>Industrial I/O core</title>
|
||||
<para>
|
||||
The Industrial I/O core offers:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
a unified framework for writing drivers for many different types of
|
||||
embedded sensors.
|
||||
</listitem>
|
||||
<listitem>
|
||||
a standard interface to user space applications manipulating sensors.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
The implementation can be found under <filename>
|
||||
drivers/iio/industrialio-*</filename>
|
||||
</para>
|
||||
<sect1 id="iiodevice">
|
||||
<title> Industrial I/O devices </title>
|
||||
|
||||
!Finclude/linux/iio/iio.h iio_dev
|
||||
!Fdrivers/iio/industrialio-core.c iio_device_alloc
|
||||
!Fdrivers/iio/industrialio-core.c iio_device_free
|
||||
!Fdrivers/iio/industrialio-core.c iio_device_register
|
||||
!Fdrivers/iio/industrialio-core.c iio_device_unregister
|
||||
|
||||
<para>
|
||||
An IIO device usually corresponds to a single hardware sensor and it
|
||||
provides all the information needed by a driver handling a device.
|
||||
Let's first have a look at the functionality embedded in an IIO
|
||||
device then we will show how a device driver makes use of an IIO
|
||||
device.
|
||||
</para>
|
||||
<para>
|
||||
There are two ways for a user space application to interact
|
||||
with an IIO driver.
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/iio:deviceX/</filename>, this
|
||||
represents a hardware sensor and groups together the data
|
||||
channels of the same chip.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>/dev/iio:deviceX</filename>, character device node
|
||||
interface used for buffered data transfer and for events information
|
||||
retrieval.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
A typical IIO driver will register itself as an I2C or SPI driver and will
|
||||
create two routines, <function> probe </function> and <function> remove
|
||||
</function>. At <function>probe</function>:
|
||||
<itemizedlist>
|
||||
<listitem>call <function>iio_device_alloc</function>, which allocates memory
|
||||
for an IIO device.
|
||||
</listitem>
|
||||
<listitem> initialize IIO device fields with driver specific information
|
||||
(e.g. device name, device channels).
|
||||
</listitem>
|
||||
<listitem>call <function> iio_device_register</function>, this registers the
|
||||
device with the IIO core. After this call the device is ready to accept
|
||||
requests from user space applications.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
At <function>remove</function>, we free the resources allocated in
|
||||
<function>probe</function> in reverse order:
|
||||
<itemizedlist>
|
||||
<listitem><function>iio_device_unregister</function>, unregister the device
|
||||
from the IIO core.
|
||||
</listitem>
|
||||
<listitem><function>iio_device_free</function>, free the memory allocated
|
||||
for the IIO device.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<sect2 id="iioattr"> <title> IIO device sysfs interface </title>
|
||||
<para>
|
||||
Attributes are sysfs files used to expose chip info and also allowing
|
||||
applications to set various configuration parameters. For device
|
||||
with index X, attributes can be found under
|
||||
<filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
|
||||
Common attributes are:
|
||||
<itemizedlist>
|
||||
<listitem><filename>name</filename>, description of the physical
|
||||
chip.
|
||||
</listitem>
|
||||
<listitem><filename>dev</filename>, shows the major:minor pair
|
||||
associated with <filename>/dev/iio:deviceX</filename> node.
|
||||
</listitem>
|
||||
<listitem><filename>sampling_frequency_available</filename>,
|
||||
available discrete set of sampling frequency values for
|
||||
device.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
Available standard attributes for IIO devices are described in the
|
||||
<filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
|
||||
in the Linux kernel sources.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="iiochannel"> <title> IIO device channels </title>
|
||||
!Finclude/linux/iio/iio.h iio_chan_spec structure.
|
||||
<para>
|
||||
An IIO device channel is a representation of a data channel. An
|
||||
IIO device can have one or multiple channels. For example:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
a thermometer sensor has one channel representing the
|
||||
temperature measurement.
|
||||
</listitem>
|
||||
<listitem>
|
||||
a light sensor with two channels indicating the measurements in
|
||||
the visible and infrared spectrum.
|
||||
</listitem>
|
||||
<listitem>
|
||||
an accelerometer can have up to 3 channels representing
|
||||
acceleration on X, Y and Z axes.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
An IIO channel is described by the <type> struct iio_chan_spec
|
||||
</type>. A thermometer driver for the temperature sensor in the
|
||||
example above would have to describe its channel as follows:
|
||||
<programlisting>
|
||||
static const struct iio_chan_spec temp_channel[] = {
|
||||
{
|
||||
.type = IIO_TEMP,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
|
||||
},
|
||||
};
|
||||
|
||||
</programlisting>
|
||||
Channel sysfs attributes exposed to userspace are specified in
|
||||
the form of <emphasis>bitmasks</emphasis>. Depending on their
|
||||
shared info, attributes can be set in one of the following masks:
|
||||
<itemizedlist>
|
||||
<listitem><emphasis>info_mask_separate</emphasis>, attributes will
|
||||
be specific to this channel</listitem>
|
||||
<listitem><emphasis>info_mask_shared_by_type</emphasis>,
|
||||
attributes are shared by all channels of the same type</listitem>
|
||||
<listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
|
||||
are shared by all channels of the same direction </listitem>
|
||||
<listitem><emphasis>info_mask_shared_by_all</emphasis>,
|
||||
attributes are shared by all channels</listitem>
|
||||
</itemizedlist>
|
||||
When there are multiple data channels per channel type we have two
|
||||
ways to distinguish between them:
|
||||
<itemizedlist>
|
||||
<listitem> set <emphasis> .modified</emphasis> field of <type>
|
||||
iio_chan_spec</type> to 1. Modifiers are specified using
|
||||
<emphasis>.channel2</emphasis> field of the same
|
||||
<type>iio_chan_spec</type> structure and are used to indicate a
|
||||
physically unique characteristic of the channel such as its direction
|
||||
or spectral response. For example, a light sensor can have two channels,
|
||||
one for infrared light and one for both infrared and visible light.
|
||||
</listitem>
|
||||
<listitem> set <emphasis>.indexed </emphasis> field of
|
||||
<type>iio_chan_spec</type> to 1. In this case the channel is
|
||||
simply another instance with an index specified by the
|
||||
<emphasis>.channel</emphasis> field.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
Here is how we can make use of the channel's modifiers:
|
||||
<programlisting>
|
||||
static const struct iio_chan_spec light_channels[] = {
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.modified = 1,
|
||||
.channel2 = IIO_MOD_LIGHT_IR,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
},
|
||||
{
|
||||
.type = IIO_INTENSITY,
|
||||
.modified = 1,
|
||||
.channel2 = IIO_MOD_LIGHT_BOTH,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
.info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
},
|
||||
{
|
||||
.type = IIO_LIGHT,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
|
||||
.info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
|
||||
},
|
||||
|
||||
}
|
||||
</programlisting>
|
||||
This channel's definition will generate two separate sysfs files
|
||||
for raw data retrieval:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
one file for processed data:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
|
||||
</filename>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
and one shared sysfs file for sampling frequency:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/iio:deviceX/sampling_frequency.
|
||||
</filename>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Here is how we can make use of the channel's indexing:
|
||||
<programlisting>
|
||||
static const struct iio_chan_spec light_channels[] = {
|
||||
{
|
||||
.type = IIO_VOLTAGE,
|
||||
.indexed = 1,
|
||||
.channel = 0,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
},
|
||||
{
|
||||
.type = IIO_VOLTAGE,
|
||||
.indexed = 1,
|
||||
.channel = 1,
|
||||
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
|
||||
},
|
||||
}
|
||||
</programlisting>
|
||||
This will generate two separate attributes files for raw data
|
||||
retrieval:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
|
||||
representing voltage measurement for channel 0.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
|
||||
representing voltage measurement for channel 1.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
|
||||
!Finclude/linux/iio/buffer.h iio_buffer
|
||||
!Edrivers/iio/industrialio-buffer.c
|
||||
|
||||
<para>
|
||||
The Industrial I/O core offers a way for continuous data capture
|
||||
based on a trigger source. Multiple data channels can be read at once
|
||||
from <filename>/dev/iio:deviceX</filename> character device node,
|
||||
thus reducing the CPU load.
|
||||
</para>
|
||||
|
||||
<sect2 id="iiobuffersysfs">
|
||||
<title>IIO buffer sysfs interface </title>
|
||||
<para>
|
||||
An IIO buffer has an associated attributes directory under <filename>
|
||||
/sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
|
||||
attributes:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<emphasis>length</emphasis>, the total number of data samples
|
||||
(capacity) that can be stored by the buffer.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis>enable</emphasis>, activate buffer capture.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
|
||||
<para>The meta information associated with a channel reading
|
||||
placed in a buffer is called a <emphasis> scan element </emphasis>.
|
||||
The important bits configuring scan elements are exposed to
|
||||
userspace applications via the <filename>
|
||||
/sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
|
||||
file contains attributes of the following form:
|
||||
<itemizedlist>
|
||||
<listitem><emphasis>enable</emphasis>, used for enabling a channel.
|
||||
If and only if its attribute is non zero, then a triggered capture
|
||||
will contain data samples for this channel.
|
||||
</listitem>
|
||||
<listitem><emphasis>type</emphasis>, description of the scan element
|
||||
data storage within the buffer and hence the form in which it is
|
||||
read from user space. Format is <emphasis>
|
||||
[be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
|
||||
<itemizedlist>
|
||||
<listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis>, specifies
|
||||
big or little endian.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis>s </emphasis>or <emphasis>u</emphasis>, specifies if
|
||||
signed (2's complement) or unsigned.
|
||||
</listitem>
|
||||
<listitem><emphasis>bits</emphasis>, is the number of valid data
|
||||
bits.
|
||||
</listitem>
|
||||
<listitem><emphasis>storagebits</emphasis>, is the number of bits
|
||||
(after padding) that it occupies in the buffer.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis>shift</emphasis>, if specified, is the shift that needs
|
||||
to be applied prior to masking out unused bits.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis>repeat</emphasis>, specifies the number of bits/storagebits
|
||||
repetitions. When the repeat element is 0 or 1, then the repeat
|
||||
value is omitted.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
For example, a driver for a 3-axis accelerometer with 12 bit
|
||||
resolution where data is stored in two 8-bits registers as
|
||||
follows:
|
||||
<programlisting>
|
||||
7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|
||||
7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+
|
||||
|D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
|
||||
+---+---+---+---+---+---+---+---+
|
||||
</programlisting>
|
||||
|
||||
will have the following scan element type for each axis:
|
||||
<programlisting>
|
||||
$ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
|
||||
le:s12/16>>4
|
||||
</programlisting>
|
||||
A user space application will interpret data samples read from the
|
||||
buffer as two byte little endian signed data, that needs a 4 bits
|
||||
right shift before masking out the 12 valid bits of data.
|
||||
</para>
|
||||
<para>
|
||||
For implementing buffer support a driver should initialize the following
|
||||
fields in <type>iio_chan_spec</type> definition:
|
||||
<programlisting>
|
||||
struct iio_chan_spec {
|
||||
/* other members */
|
||||
int scan_index
|
||||
struct {
|
||||
char sign;
|
||||
u8 realbits;
|
||||
u8 storagebits;
|
||||
u8 shift;
|
||||
u8 repeat;
|
||||
enum iio_endian endianness;
|
||||
} scan_type;
|
||||
};
|
||||
</programlisting>
|
||||
The driver implementing the accelerometer described above will
|
||||
have the following channel definition:
|
||||
<programlisting>
|
||||
struct struct iio_chan_spec accel_channels[] = {
|
||||
{
|
||||
.type = IIO_ACCEL,
|
||||
.modified = 1,
|
||||
.channel2 = IIO_MOD_X,
|
||||
/* other stuff here */
|
||||
.scan_index = 0,
|
||||
.scan_type = {
|
||||
.sign = 's',
|
||||
.realbits = 12,
|
||||
.storgebits = 16,
|
||||
.shift = 4,
|
||||
.endianness = IIO_LE,
|
||||
},
|
||||
}
|
||||
/* similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1)
|
||||
* and Z (with channel2 = IIO_MOD_Z, scan_index = 2) axis
|
||||
*/
|
||||
}
|
||||
</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Here <emphasis> scan_index </emphasis> defines the order in which
|
||||
the enabled channels are placed inside the buffer. Channels with a lower
|
||||
scan_index will be placed before channels with a higher index. Each
|
||||
channel needs to have a unique scan_index.
|
||||
</para>
|
||||
<para>
|
||||
Setting scan_index to -1 can be used to indicate that the specific
|
||||
channel does not support buffered capture. In this case no entries will
|
||||
be created for the channel in the scan_elements directory.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="iiotrigger"> <title> Industrial I/O triggers </title>
|
||||
!Finclude/linux/iio/trigger.h iio_trigger
|
||||
!Edrivers/iio/industrialio-trigger.c
|
||||
<para>
|
||||
In many situations it is useful for a driver to be able to
|
||||
capture data based on some external event (trigger) as opposed
|
||||
to periodically polling for data. An IIO trigger can be provided
|
||||
by a device driver that also has an IIO device based on hardware
|
||||
generated events (e.g. data ready or threshold exceeded) or
|
||||
provided by a separate driver from an independent interrupt
|
||||
source (e.g. GPIO line connected to some external system, timer
|
||||
interrupt or user space writing a specific file in sysfs). A
|
||||
trigger may initiate data capture for a number of sensors and
|
||||
also it may be completely unrelated to the sensor itself.
|
||||
</para>
|
||||
|
||||
<sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
|
||||
There are two locations in sysfs related to triggers:
|
||||
<itemizedlist>
|
||||
<listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
|
||||
this file is created once an IIO trigger is registered with
|
||||
the IIO core and corresponds to trigger with index Y. Because
|
||||
triggers can be very different depending on type there are few
|
||||
standard attributes that we can describe here:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<emphasis>name</emphasis>, trigger name that can be later
|
||||
used for association with a device.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<emphasis>sampling_frequency</emphasis>, some timer based
|
||||
triggers use this attribute to specify the frequency for
|
||||
trigger calls.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
|
||||
directory is created once the device supports a triggered
|
||||
buffer. We can associate a trigger with our device by writing
|
||||
the trigger's name in the <filename>current_trigger</filename> file.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
|
||||
|
||||
<para>
|
||||
Let's see a simple example of how to setup a trigger to be used
|
||||
by a driver.
|
||||
|
||||
<programlisting>
|
||||
struct iio_trigger_ops trigger_ops = {
|
||||
.set_trigger_state = sample_trigger_state,
|
||||
.validate_device = sample_validate_device,
|
||||
}
|
||||
|
||||
struct iio_trigger *trig;
|
||||
|
||||
/* first, allocate memory for our trigger */
|
||||
trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
|
||||
|
||||
/* setup trigger operations field */
|
||||
trig->ops = &trigger_ops;
|
||||
|
||||
/* now register the trigger with the IIO core */
|
||||
iio_trigger_register(trig);
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
|
||||
!Finclude/linux/iio/trigger.h iio_trigger_ops
|
||||
<para>
|
||||
Notice that a trigger has a set of operations attached:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<function>set_trigger_state</function>, switch the trigger on/off
|
||||
on demand.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<function>validate_device</function>, function to validate the
|
||||
device when the current trigger gets changed.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1 id="iiotriggered_buffer">
|
||||
<title> Industrial I/O triggered buffers </title>
|
||||
<para>
|
||||
Now that we know what buffers and triggers are let's see how they
|
||||
work together.
|
||||
</para>
|
||||
<sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
|
||||
!Edrivers/iio/industrialio-triggered-buffer.c
|
||||
!Finclude/linux/iio/iio.h iio_buffer_setup_ops
|
||||
|
||||
|
||||
<para>
|
||||
A typical triggered buffer setup looks like this:
|
||||
<programlisting>
|
||||
const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
|
||||
.preenable = sensor_buffer_preenable,
|
||||
.postenable = sensor_buffer_postenable,
|
||||
.postdisable = sensor_buffer_postdisable,
|
||||
.predisable = sensor_buffer_predisable,
|
||||
};
|
||||
|
||||
irqreturn_t sensor_iio_pollfunc(int irq, void *p)
|
||||
{
|
||||
pf->timestamp = iio_get_time_ns();
|
||||
return IRQ_WAKE_THREAD;
|
||||
}
|
||||
|
||||
irqreturn_t sensor_trigger_handler(int irq, void *p)
|
||||
{
|
||||
u16 buf[8];
|
||||
int i = 0;
|
||||
|
||||
/* read data for each active channel */
|
||||
for_each_set_bit(bit, active_scan_mask, masklength)
|
||||
buf[i++] = sensor_get_data(bit)
|
||||
|
||||
iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp);
|
||||
|
||||
iio_trigger_notify_done(trigger);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* setup triggered buffer, usually in probe function */
|
||||
iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
|
||||
sensor_trigger_handler,
|
||||
sensor_buffer_setup_ops);
|
||||
</programlisting>
|
||||
</para>
|
||||
The important things to notice here are:
|
||||
<itemizedlist>
|
||||
<listitem><function> iio_buffer_setup_ops</function>, the buffer setup
|
||||
functions to be called at predefined points in the buffer configuration
|
||||
sequence (e.g. before enable, after disable). If not specified, the
|
||||
IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
|
||||
</listitem>
|
||||
<listitem><function>sensor_iio_pollfunc</function>, the function that
|
||||
will be used as top half of poll function. It should do as little
|
||||
processing as possible, because it runs in interrupt context. The most
|
||||
common operation is recording of the current timestamp and for this reason
|
||||
one can use the IIO core defined <function>iio_pollfunc_store_time
|
||||
</function> function.
|
||||
</listitem>
|
||||
<listitem><function>sensor_trigger_handler</function>, the function that
|
||||
will be used as bottom half of the poll function. This runs in the
|
||||
context of a kernel thread and all the processing takes place here.
|
||||
It usually reads data from the device and stores it in the internal
|
||||
buffer together with the timestamp recorded in the top half.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
||||
<chapter id='iioresources'>
|
||||
<title> Resources </title>
|
||||
IIO core may change during time so the best documentation to read is the
|
||||
source code. There are several locations where you should look:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<filename>drivers/iio/</filename>, contains the IIO core plus
|
||||
and directories for each sensor type (e.g. accel, magnetometer,
|
||||
etc.)
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>include/linux/iio/</filename>, contains the header
|
||||
files, nice to read for the internal kernel interfaces.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>include/uapi/linux/iio/</filename>, contains files to be
|
||||
used by user space applications.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>tools/iio/</filename>, contains tools for rapidly
|
||||
testing buffers, events and device creation.
|
||||
</listitem>
|
||||
<listitem>
|
||||
<filename>drivers/staging/iio/</filename>, contains code for some
|
||||
drivers or experimental features that are not yet mature enough
|
||||
to be moved out.
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Besides the code, there are some good online documentation sources:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
|
||||
list </ulink>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
|
||||
Analog Device IIO wiki page </ulink>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
|
||||
Using the Linux IIO framework for SDR, Lars-Peter Clausen's
|
||||
presentation at FOSDEM </ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</chapter>
|
||||
</book>
|
||||
|
||||
<!--
|
||||
vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
|
||||
-->
|
@@ -199,7 +199,8 @@ DVB_DOCUMENTED = \
|
||||
#
|
||||
|
||||
install_media_images = \
|
||||
$(Q)-cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/*.svg $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api
|
||||
$(Q)-mkdir $(MEDIA_OBJ_DIR)/media_api; \
|
||||
cp $(OBJIMGFILES) $(MEDIA_SRC_DIR)/*.svg $(MEDIA_SRC_DIR)/v4l/*.svg $(MEDIA_OBJ_DIR)/media_api
|
||||
|
||||
$(MEDIA_OBJ_DIR)/%: $(MEDIA_SRC_DIR)/%.b64
|
||||
$(Q)base64 -d $< >$@
|
||||
|
@@ -163,9 +163,8 @@ are called:</para>
|
||||
<para>where N enumerates the DVB PCI cards in a system starting
|
||||
from 0, and M enumerates the devices of each type within each
|
||||
adapter, starting from 0, too. We will omit the “
|
||||
<constant>/dev/dvb/adapterN/</constant>” in the further dicussion
|
||||
of these devices. The naming scheme for the devices is the same wheter
|
||||
devfs is used or not.</para>
|
||||
<constant>/dev/dvb/adapterN/</constant>” in the further discussion
|
||||
of these devices.</para>
|
||||
|
||||
<para>More details about the data structures and function calls of all
|
||||
the devices are described in the following chapters.</para>
|
||||
|
@@ -3414,7 +3414,7 @@ giving priority to the center of the metered area.</entry>
|
||||
<row>
|
||||
<entry><constant>V4L2_EXPOSURE_METERING_MATRIX</constant> </entry>
|
||||
<entry>A multi-zone metering. The light intensity is measured
|
||||
in several points of the frame and the the results are combined. The
|
||||
in several points of the frame and the results are combined. The
|
||||
algorithm of the zones selection and their significance in calculating the
|
||||
final value is device dependent.</entry>
|
||||
</row>
|
||||
|
@@ -102,7 +102,7 @@
|
||||
</row>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>media_version</structfield></entry>
|
||||
<entry><structfield>driver_version</structfield></entry>
|
||||
<entry>Media device driver version, formatted with the
|
||||
<constant>KERNEL_VERSION()</constant> macro. Together with the
|
||||
<structfield>driver</structfield> field this identifies a particular
|
||||
|
@@ -62,28 +62,28 @@ buffer as a DMABUF file at any time after buffers have been allocated with the
|
||||
&VIDIOC-REQBUFS; ioctl.</para>
|
||||
|
||||
<para> To export a buffer, applications fill &v4l2-exportbuffer;. The
|
||||
<structfield> type </structfield> field is set to the same buffer type as was
|
||||
previously used with &v4l2-requestbuffers;<structfield> type </structfield>.
|
||||
Applications must also set the <structfield> index </structfield> field. Valid
|
||||
<structfield>type</structfield> field is set to the same buffer type as was
|
||||
previously used with &v4l2-requestbuffers; <structfield>type</structfield>.
|
||||
Applications must also set the <structfield>index</structfield> field. Valid
|
||||
index numbers range from zero to the number of buffers allocated with
|
||||
&VIDIOC-REQBUFS; (&v4l2-requestbuffers;<structfield> count </structfield>)
|
||||
minus one. For the multi-planar API, applications set the <structfield> plane
|
||||
</structfield> field to the index of the plane to be exported. Valid planes
|
||||
&VIDIOC-REQBUFS; (&v4l2-requestbuffers; <structfield>count</structfield>)
|
||||
minus one. For the multi-planar API, applications set the <structfield>plane</structfield>
|
||||
field to the index of the plane to be exported. Valid planes
|
||||
range from zero to the maximal number of valid planes for the currently active
|
||||
format. For the single-planar API, applications must set <structfield> plane
|
||||
</structfield> to zero. Additional flags may be posted in the <structfield>
|
||||
flags </structfield> field. Refer to a manual for open() for details.
|
||||
format. For the single-planar API, applications must set <structfield>plane</structfield>
|
||||
to zero. Additional flags may be posted in the <structfield>flags</structfield>
|
||||
field. Refer to a manual for open() for details.
|
||||
Currently only O_CLOEXEC, O_RDONLY, O_WRONLY, and O_RDWR are supported. All
|
||||
other fields must be set to zero.
|
||||
In the case of multi-planar API, every plane is exported separately using
|
||||
multiple <constant> VIDIOC_EXPBUF </constant> calls. </para>
|
||||
multiple <constant>VIDIOC_EXPBUF</constant> calls.</para>
|
||||
|
||||
<para> After calling <constant>VIDIOC_EXPBUF</constant> the <structfield> fd
|
||||
</structfield> field will be set by a driver. This is a DMABUF file
|
||||
<para>After calling <constant>VIDIOC_EXPBUF</constant> the <structfield>fd</structfield>
|
||||
field will be set by a driver. This is a DMABUF file
|
||||
descriptor. The application may pass it to other DMABUF-aware devices. Refer to
|
||||
<link linkend="dmabuf">DMABUF importing</link> for details about importing
|
||||
DMABUF files into V4L2 nodes. It is recommended to close a DMABUF file when it
|
||||
is no longer used to allow the associated memory to be reclaimed. </para>
|
||||
is no longer used to allow the associated memory to be reclaimed.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@@ -170,9 +170,9 @@ multi-planar API. Otherwise this value must be set to zero. </entry>
|
||||
<row>
|
||||
<entry>__u32</entry>
|
||||
<entry><structfield>flags</structfield></entry>
|
||||
<entry>Flags for the newly created file, currently only <constant>
|
||||
O_CLOEXEC </constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY
|
||||
</constant>, and <constant>O_RDWR</constant> are supported, refer to the manual
|
||||
<entry>Flags for the newly created file, currently only
|
||||
<constant>O_CLOEXEC</constant>, <constant>O_RDONLY</constant>, <constant>O_WRONLY</constant>,
|
||||
and <constant>O_RDWR</constant> are supported, refer to the manual
|
||||
of open() for more details.</entry>
|
||||
</row>
|
||||
<row>
|
||||
@@ -200,9 +200,9 @@ set the array to zero.</entry>
|
||||
<term><errorcode>EINVAL</errorcode></term>
|
||||
<listitem>
|
||||
<para>A queue is not in MMAP mode or DMABUF exporting is not
|
||||
supported or <structfield> flags </structfield> or <structfield> type
|
||||
</structfield> or <structfield> index </structfield> or <structfield> plane
|
||||
</structfield> fields are invalid.</para>
|
||||
supported or <structfield>flags</structfield> or <structfield>type</structfield>
|
||||
or <structfield>index</structfield> or <structfield>plane</structfield> fields
|
||||
are invalid.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
@@ -267,7 +267,7 @@ is intended for still imaging applications. The idea is to get the
|
||||
best possible image quality that the hardware can deliver. It is not
|
||||
defined how the driver writer may achieve that; it will depend on the
|
||||
hardware and the ingenuity of the driver writer. High quality mode is
|
||||
a different mode from the the regular motion video capture modes. In
|
||||
a different mode from the regular motion video capture modes. In
|
||||
high quality mode:<itemizedlist>
|
||||
<listitem>
|
||||
<para>The driver may be able to capture higher
|
||||
|
@@ -616,7 +616,7 @@ pointer to memory containing the payload of the control.</entry>
|
||||
<entry><constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant></entry>
|
||||
<entry>0x0200</entry>
|
||||
<entry>The value provided to the control will be propagated to the driver
|
||||
even if remains constant. This is required when the control represents an action
|
||||
even if it remains constant. This is required when the control represents an action
|
||||
on the hardware. For example: clearing an error flag or triggering the flash. All the
|
||||
controls of the type <constant>V4L2_CTRL_TYPE_BUTTON</constant> have this flag set.</entry>
|
||||
</row>
|
||||
|
@@ -5,6 +5,7 @@
|
||||
<param name="funcsynopsis.tabular.threshold">80</param>
|
||||
<param name="callout.graphics">0</param>
|
||||
<!-- <param name="paper.type">A4</param> -->
|
||||
<param name="generate.consistent.ids">1</param>
|
||||
<param name="generate.section.toc.level">2</param>
|
||||
<param name="use.id.as.filename">1</param>
|
||||
</stylesheet>
|
||||
|
Reference in New Issue
Block a user