Commit c1aac62f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'docs-4.11' of git://git.lwn.net/linux

Pull documentation updates from Jonathan Corbet:
 "A slightly quieter cycle for documentation this time around.

  Three more DocBook template files have been converted to RST; only 21
  to go. There are various build improvements and the usual array of
  documentation improvements and fixes"

* tag 'docs-4.11' of git://git.lwn.net/linux: (44 commits)
  docs / driver-api: Fix structure references in device_link.rst
  PM / docs: Fix structure references in device.rst
  Add a target to check broken external links in the Documentation
  Documentation: Fix linux-api list typo
  Documentation: DocBook/Makefile comment typo
  Improve sparse documentation
  Documentation: make Makefile.sphinx no-ops quieter
  Documentation: DMA-ISA-LPC.txt
  Documentation: input: fix path to input code definitions
  docs: Remove the copyright year from conf.py
  docs: Fix a warning in the Korean HOWTO.rst translation
  PM / sleep / docs: Convert PM notifiers document to reST
  PM / core / docs: Convert sleep states API document to reST
  PM / core: Update kerneldoc comments in pm.h
  doc-rst: Fix recursive make invocation from macros
  doc-rst: Delete output of failed dot-SVG conversion
  doc-rst: Break shell command sequences on failure
  Documentation/sphinx: make targets independent of Sphinx work for HAVE_SPHINX=0
  doc-rst: fixed cleandoc target when used with O=dir
  Documentation/sphinx: prevent generation of .pyc files in the source tree
  ...
parents fd7e9a88 bd856262
...@@ -42,7 +42,7 @@ requirements you pass the flag GFP_DMA to kmalloc. ...@@ -42,7 +42,7 @@ requirements you pass the flag GFP_DMA to kmalloc.
Unfortunately the memory available for ISA DMA is scarce so unless you Unfortunately the memory available for ISA DMA is scarce so unless you
allocate the memory during boot-up it's a good idea to also pass allocate the memory during boot-up it's a good idea to also pass
__GFP_REPEAT and __GFP_NOWARN to make the allocater try a bit harder. __GFP_REPEAT and __GFP_NOWARN to make the allocator try a bit harder.
(This scarcity also means that you should allocate the buffer as (This scarcity also means that you should allocate the buffer as
early as possible and not release it until the driver is unloaded.) early as possible and not release it until the driver is unloaded.)
......
...@@ -13,7 +13,7 @@ DOCBOOKS := z8530book.xml \ ...@@ -13,7 +13,7 @@ DOCBOOKS := z8530book.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml scsi.xml \ genericirq.xml s390-drivers.xml scsi.xml \
sh.xml regulator.xml w1.xml \ sh.xml regulator.xml w1.xml \
writing_musb_glue_layer.xml iio.xml writing_musb_glue_layer.xml
ifeq ($(DOCBOOKS),) ifeq ($(DOCBOOKS),)
...@@ -71,6 +71,7 @@ installmandocs: mandocs ...@@ -71,6 +71,7 @@ installmandocs: mandocs
# no-op for the DocBook toolchain # no-op for the DocBook toolchain
epubdocs: epubdocs:
latexdocs: latexdocs:
linkcheckdocs:
### ###
#External programs used #External programs used
...@@ -272,6 +273,6 @@ cleandocs: ...@@ -272,6 +273,6 @@ cleandocs:
$(Q)rm -rf $(call objectify, $(clean-dirs)) $(Q)rm -rf $(call objectify, $(clean-dirs))
# Declare the contents of the .PHONY variable as phony. We keep that # Declare the contents of the .PHONY variable as phony. We keep that
# information in a variable se we can use it in if_changed and friends. # information in a variable so we can use it in if_changed and friends.
.PHONY: $(PHONY) .PHONY: $(PHONY)
<?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="DoingIO">
<bookinfo>
<title>Bus-Independent Device Accesses</title>
<authorgroup>
<author>
<firstname>Matthew</firstname>
<surname>Wilcox</surname>
<affiliation>
<address>
<email>matthew@wil.cx</email>
</address>
</affiliation>
</author>
</authorgroup>
<authorgroup>
<author>
<firstname>Alan</firstname>
<surname>Cox</surname>
<affiliation>
<address>
<email>alan@lxorguk.ukuu.org.uk</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2001</year>
<holder>Matthew Wilcox</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 as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
Linux provides an API which abstracts performing IO across all busses
and devices, allowing device drivers to be written independently of
bus type.
</para>
</chapter>
<chapter id="bugs">
<title>Known Bugs And Assumptions</title>
<para>
None.
</para>
</chapter>
<chapter id="mmio">
<title>Memory Mapped IO</title>
<sect1 id="getting_access_to_the_device">
<title>Getting Access to the Device</title>
<para>
The most widely supported form of IO is memory mapped IO.
That is, a part of the CPU's address space is interpreted
not as accesses to memory, but as accesses to a device. Some
architectures define devices to be at a fixed address, but most
have some method of discovering devices. The PCI bus walk is a
good example of such a scheme. This document does not cover how
to receive such an address, but assumes you are starting with one.
Physical addresses are of type unsigned long.
</para>
<para>
This address should not be used directly. Instead, to get an
address suitable for passing to the accessor functions described
below, you should call <function>ioremap</function>.
An address suitable for accessing the device will be returned to you.
</para>
<para>
After you've finished using the device (say, in your module's
exit routine), call <function>iounmap</function> in order to return
the address space to the kernel. Most architectures allocate new
address space each time you call <function>ioremap</function>, and
they can run out unless you call <function>iounmap</function>.
</para>
</sect1>
<sect1 id="accessing_the_device">
<title>Accessing the device</title>
<para>
The part of the interface most used by drivers is reading and
writing memory-mapped registers on the device. Linux provides
interfaces to read and write 8-bit, 16-bit, 32-bit and 64-bit
quantities. Due to a historical accident, these are named byte,
word, long and quad accesses. Both read and write accesses are
supported; there is no prefetch support at this time.
</para>
<para>
The functions are named <function>readb</function>,
<function>readw</function>, <function>readl</function>,
<function>readq</function>, <function>readb_relaxed</function>,
<function>readw_relaxed</function>, <function>readl_relaxed</function>,
<function>readq_relaxed</function>, <function>writeb</function>,
<function>writew</function>, <function>writel</function> and
<function>writeq</function>.
</para>
<para>
Some devices (such as framebuffers) would like to use larger
transfers than 8 bytes at a time. For these devices, the
<function>memcpy_toio</function>, <function>memcpy_fromio</function>
and <function>memset_io</function> functions are provided.
Do not use memset or memcpy on IO addresses; they
are not guaranteed to copy data in order.
</para>
<para>
The read and write functions are defined to be ordered. That is the
compiler is not permitted to reorder the I/O sequence. When the
ordering can be compiler optimised, you can use <function>
__readb</function> and friends to indicate the relaxed ordering. Use
this with care.
</para>
<para>
While the basic functions are defined to be synchronous with respect
to each other and ordered with respect to each other the busses the
devices sit on may themselves have asynchronicity. In particular many
authors are burned by the fact that PCI bus writes are posted
asynchronously. A driver author must issue a read from the same
device to ensure that writes have occurred in the specific cases the
author cares. This kind of property cannot be hidden from driver
writers in the API. In some cases, the read used to flush the device
may be expected to fail (if the card is resetting, for example). In
that case, the read should be done from config space, which is
guaranteed to soft-fail if the card doesn't respond.
</para>
<para>
The following is an example of flushing a write to a device when
the driver would like to ensure the write's effects are visible prior
to continuing execution.
</para>
<programlisting>
static inline void
qla1280_disable_intrs(struct scsi_qla_host *ha)
{
struct device_reg *reg;
reg = ha->iobase;
/* disable risc and host interrupts */
WRT_REG_WORD(&amp;reg->ictrl, 0);
/*
* The following read will ensure that the above write
* has been received by the device before we return from this
* function.
*/
RD_REG_WORD(&amp;reg->ictrl);
ha->flags.ints_enabled = 0;
}
</programlisting>
<para>
In addition to write posting, on some large multiprocessing systems
(e.g. SGI Challenge, Origin and Altix machines) posted writes won't
be strongly ordered coming from different CPUs. Thus it's important
to properly protect parts of your driver that do memory-mapped writes
with locks and use the <function>mmiowb</function> to make sure they
arrive in the order intended. Issuing a regular <function>readX
</function> will also ensure write ordering, but should only be used
when the driver has to be sure that the write has actually arrived
at the device (not that it's simply ordered with respect to other
writes), since a full <function>readX</function> is a relatively
expensive operation.
</para>
<para>
Generally, one should use <function>mmiowb</function> prior to
releasing a spinlock that protects regions using <function>writeb
</function> or similar functions that aren't surrounded by <function>
readb</function> calls, which will ensure ordering and flushing. The
following pseudocode illustrates what might occur if write ordering
isn't guaranteed via <function>mmiowb</function> or one of the
<function>readX</function> functions.
</para>
<programlisting>
CPU A: spin_lock_irqsave(&amp;dev_lock, flags)
CPU A: ...
CPU A: writel(newval, ring_ptr);
CPU A: spin_unlock_irqrestore(&amp;dev_lock, flags)
...
CPU B: spin_lock_irqsave(&amp;dev_lock, flags)
CPU B: writel(newval2, ring_ptr);
CPU B: ...
CPU B: spin_unlock_irqrestore(&amp;dev_lock, flags)
</programlisting>
<para>
In the case above, newval2 could be written to ring_ptr before
newval. Fixing it is easy though:
</para>
<programlisting>
CPU A: spin_lock_irqsave(&amp;dev_lock, flags)
CPU A: ...
CPU A: writel(newval, ring_ptr);
CPU A: mmiowb(); /* ensure no other writes beat us to the device */
CPU A: spin_unlock_irqrestore(&amp;dev_lock, flags)
...
CPU B: spin_lock_irqsave(&amp;dev_lock, flags)
CPU B: writel(newval2, ring_ptr);
CPU B: ...
CPU B: mmiowb();
CPU B: spin_unlock_irqrestore(&amp;dev_lock, flags)
</programlisting>
<para>
See tg3.c for a real world example of how to use <function>mmiowb
</function>
</para>
<para>
PCI ordering rules also guarantee that PIO read responses arrive
after any outstanding DMA writes from that bus, since for some devices
the result of a <function>readb</function> call may signal to the
driver that a DMA transaction is complete. In many cases, however,
the driver may want to indicate that the next
<function>readb</function> call has no relation to any previous DMA
writes performed by the device. The driver can use
<function>readb_relaxed</function> for these cases, although only
some platforms will honor the relaxed semantics. Using the relaxed
read functions will provide significant performance benefits on
platforms that support it. The qla2xxx driver provides examples
of how to use <function>readX_relaxed</function>. In many cases,
a majority of the driver's <function>readX</function> calls can
safely be converted to <function>readX_relaxed</function> calls, since
only a few will indicate or depend on DMA completion.
</para>
</sect1>
</chapter>
<chapter id="port_space_accesses">
<title>Port Space Accesses</title>
<sect1 id="port_space_explained">
<title>Port Space Explained</title>
<para>
Another form of IO commonly supported is Port Space. This is a
range of addresses separate to the normal memory address space.
Access to these addresses is generally not as fast as accesses
to the memory mapped addresses, and it also has a potentially
smaller address space.
</para>
<para>
Unlike memory mapped IO, no preparation is required
to access port space.
</para>
</sect1>
<sect1 id="accessing_port_space">
<title>Accessing Port Space</title>
<para>
Accesses to this space are provided through a set of functions
which allow 8-bit, 16-bit and 32-bit accesses; also
known as byte, word and long. These functions are
<function>inb</function>, <function>inw</function>,
<function>inl</function>, <function>outb</function>,
<function>outw</function> and <function>outl</function>.
</para>
<para>
Some variants are provided for these functions. Some devices
require that accesses to their ports are slowed down. This
functionality is provided by appending a <function>_p</function>
to the end of the function. There are also equivalents to memcpy.
The <function>ins</function> and <function>outs</function>
functions copy bytes, words or longs to the given port.
</para>
</sect1>
</chapter>
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Iarch/x86/include/asm/io.h
!Elib/pci_iomap.c
</chapter>
</book>
<?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,
.storagebits = 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 = &amp;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/buffer/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((struct indio_dev *)p);
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
-->
<?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="regulator-api">
<bookinfo>
<title>Voltage and current regulator API</title>
<authorgroup>
<author>
<firstname>Liam</firstname>
<surname>Girdwood</surname>
<affiliation>
<address>
<email>lrg@slimlogic.co.uk</email>
</address>
</affiliation>
</author>
<author>
<firstname>Mark</firstname>
<surname>Brown</surname>
<affiliation>
<orgname>Wolfson Microelectronics</orgname>
<address>
<email>broonie@opensource.wolfsonmicro.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2007-2008</year>
<holder>Wolfson Microelectronics</holder>
</copyright>
<copyright>
<year>2008</year>
<holder>Liam Girdwood</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 as published by the Free Software Foundation.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
This framework is designed to provide a standard kernel
interface to control voltage and current regulators.
</para>
<para>
The intention is to allow systems to dynamically control
regulator power output in order to save power and prolong
battery life. This applies to both voltage regulators (where
voltage output is controllable) and current sinks (where current
limit is controllable).
</para>
<para>
Note that additional (and currently more complete) documentation
is available in the Linux kernel source under
<filename>Documentation/power/regulator</filename>.
</para>
<sect1 id="glossary">
<title>Glossary</title>
<para>
The regulator API uses a number of terms which may not be
familiar:
</para>
<glossary>
<glossentry>
<glossterm>Regulator</glossterm>
<glossdef>
<para>
Electronic device that supplies power to other devices. Most
regulators can enable and disable their output and some can also
control their output voltage or current.
</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>Consumer</glossterm>
<glossdef>
<para>
Electronic device which consumes power provided by a regulator.
These may either be static, requiring only a fixed supply, or
dynamic, requiring active management of the regulator at
runtime.
</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>Power Domain</glossterm>
<glossdef>
<para>
The electronic circuit supplied by a given regulator, including
the regulator and all consumer devices. The configuration of
the regulator is shared between all the components in the
circuit.
</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>Power Management Integrated Circuit</glossterm>
<acronym>PMIC</acronym>
<glossdef>
<para>
An IC which contains numerous regulators and often also other
subsystems. In an embedded system the primary PMIC is often
equivalent to a combination of the PSU and southbridge in a
desktop system.
</para>
</glossdef>
</glossentry>
</glossary>
</sect1>
</chapter>
<chapter id="consumer">
<title>Consumer driver interface</title>
<para>
This offers a similar API to the kernel clock framework.
Consumer drivers use <link
linkend='API-regulator-get'>get</link> and <link
linkend='API-regulator-put'>put</link> operations to acquire and
release regulators. Functions are
provided to <link linkend='API-regulator-enable'>enable</link>
and <link linkend='API-regulator-disable'>disable</link> the
regulator and to get and set the runtime parameters of the
regulator.
</para>
<para>
When requesting regulators consumers use symbolic names for their
supplies, such as "Vcc", which are mapped into actual regulator
devices by the machine interface.
</para>
<para>
A stub version of this API is provided when the regulator
framework is not in use in order to minimise the need to use
ifdefs.
</para>
<sect1 id="consumer-enable">
<title>Enabling and disabling</title>
<para>
The regulator API provides reference counted enabling and
disabling of regulators. Consumer devices use the <function><link
linkend='API-regulator-enable'>regulator_enable</link></function>
and <function><link
linkend='API-regulator-disable'>regulator_disable</link>
</function> functions to enable and disable regulators. Calls
to the two functions must be balanced.
</para>
<para>
Note that since multiple consumers may be using a regulator and
machine constraints may not allow the regulator to be disabled
there is no guarantee that calling
<function>regulator_disable</function> will actually cause the
supply provided by the regulator to be disabled. Consumer
drivers should assume that the regulator may be enabled at all
times.
</para>
</sect1>
<sect1 id="consumer-config">
<title>Configuration</title>
<para>
Some consumer devices may need to be able to dynamically
configure their supplies. For example, MMC drivers may need to
select the correct operating voltage for their cards. This may
be done while the regulator is enabled or disabled.
</para>
<para>
The <function><link
linkend='API-regulator-set-voltage'>regulator_set_voltage</link>
</function> and <function><link
linkend='API-regulator-set-current-limit'
>regulator_set_current_limit</link>
</function> functions provide the primary interface for this.
Both take ranges of voltages and currents, supporting drivers
that do not require a specific value (eg, CPU frequency scaling
normally permits the CPU to use a wider range of supply
voltages at lower frequencies but does not require that the
supply voltage be lowered). Where an exact value is required
both minimum and maximum values should be identical.
</para>
</sect1>
<sect1 id="consumer-callback">
<title>Callbacks</title>
<para>
Callbacks may also be <link
linkend='API-regulator-register-notifier'>registered</link>
for events such as regulation failures.
</para>
</sect1>
</chapter>
<chapter id="driver">
<title>Regulator driver interface</title>
<para>
Drivers for regulator chips <link
linkend='API-regulator-register'>register</link> the regulators
with the regulator core, providing operations structures to the
core. A <link
linkend='API-regulator-notifier-call-chain'>notifier</link> interface
allows error conditions to be reported to the core.
</para>
<para>
Registration should be triggered by explicit setup done by the
platform, supplying a <link
linkend='API-struct-regulator-init-data'>struct
regulator_init_data</link> for the regulator containing
<link linkend='machine-constraint'>constraint</link> and
<link linkend='machine-supply'>supply</link> information.
</para>
</chapter>
<chapter id="machine">
<title>Machine interface</title>
<para>
This interface provides a way to define how regulators are
connected to consumers on a given system and what the valid
operating parameters are for the system.
</para>
<sect1 id="machine-supply">
<title>Supplies</title>
<para>
Regulator supplies are specified using <link
linkend='API-struct-regulator-consumer-supply'>struct
regulator_consumer_supply</link>. This is done at
<link linkend='driver'>driver registration
time</link> as part of the machine constraints.
</para>
</sect1>
<sect1 id="machine-constraint">
<title>Constraints</title>
<para>
As well as defining the connections the machine interface
also provides constraints defining the operations that
clients are allowed to perform and the parameters that may be
set. This is required since generally regulator devices will
offer more flexibility than it is safe to use on a given
system, for example supporting higher supply voltages than the
consumers are rated for.
</para>
<para>
This is done at <link linkend='driver'>driver
registration time</link> by providing a <link
linkend='API-struct-regulation-constraints'>struct
regulation_constraints</link>.
</para>
<para>
The constraints may also specify an initial configuration for the
regulator in the constraints, which is particularly useful for
use with static consumers.
</para>
</sect1>
</chapter>
<chapter id="api">
<title>API reference</title>
<para>
Due to limitations of the kernel documentation framework and the
existing layout of the source code the entire regulator API is
documented here.
</para>
!Iinclude/linux/regulator/consumer.h
!Iinclude/linux/regulator/machine.h
!Iinclude/linux/regulator/driver.h
!Edrivers/regulator/core.c
</chapter>
</book>
...@@ -43,7 +43,7 @@ ALLSPHINXOPTS = $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ...@@ -43,7 +43,7 @@ ALLSPHINXOPTS = $(KERNELDOC_CONF) $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# commands; the 'cmd' from scripts/Kbuild.include is not *loopable* # commands; the 'cmd' from scripts/Kbuild.include is not *loopable*
loop_cmd = $(echo-cmd) $(cmd_$(1)) loop_cmd = $(echo-cmd) $(cmd_$(1)) || exit;
# $2 sphinx builder e.g. "html" # $2 sphinx builder e.g. "html"
# $3 name of the build subfolder / e.g. "media", used as: # $3 name of the build subfolder / e.g. "media", used as:
...@@ -54,7 +54,8 @@ loop_cmd = $(echo-cmd) $(cmd_$(1)) ...@@ -54,7 +54,8 @@ loop_cmd = $(echo-cmd) $(cmd_$(1))
# e.g. "media" for the linux-tv book-set at ./Documentation/media # e.g. "media" for the linux-tv book-set at ./Documentation/media
quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4) quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2;\ cmd_sphinx = $(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media $2 && \
PYTHONDONTWRITEBYTECODE=1 \
BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \ BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \
$(SPHINXBUILD) \ $(SPHINXBUILD) \
-b $2 \ -b $2 \
...@@ -63,13 +64,16 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4) ...@@ -63,13 +64,16 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
-D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \ -D version=$(KERNELVERSION) -D release=$(KERNELRELEASE) \
$(ALLSPHINXOPTS) \ $(ALLSPHINXOPTS) \
$(abspath $(srctree)/$(src)/$5) \ $(abspath $(srctree)/$(src)/$5) \
$(abspath $(BUILDDIR)/$3/$4); $(abspath $(BUILDDIR)/$3/$4)
htmldocs: htmldocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var))) @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
linkcheckdocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
latexdocs: latexdocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var))) @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,latex,$(var),latex,$(var)))
ifeq ($(HAVE_PDFLATEX),0) ifeq ($(HAVE_PDFLATEX),0)
...@@ -80,27 +84,34 @@ pdfdocs: ...@@ -80,27 +84,34 @@ pdfdocs:
else # HAVE_PDFLATEX else # HAVE_PDFLATEX
pdfdocs: latexdocs pdfdocs: latexdocs
$(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex;) $(foreach var,$(SPHINXDIRS), $(MAKE) PDFLATEX=$(PDFLATEX) LATEXOPTS="$(LATEXOPTS)" -C $(BUILDDIR)/$(var)/latex || exit;)
endif # HAVE_PDFLATEX endif # HAVE_PDFLATEX
epubdocs: epubdocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var))) @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,epub,$(var),epub,$(var)))
xmldocs: xmldocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var))) @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,xml,$(var),xml,$(var)))
endif # HAVE_SPHINX
# The following targets are independent of HAVE_SPHINX, and the rules should
# work or silently pass without Sphinx.
# no-ops for the Sphinx toolchain # no-ops for the Sphinx toolchain
sgmldocs: sgmldocs:
@:
psdocs: psdocs:
@:
mandocs: mandocs:
@:
installmandocs: installmandocs:
@:
cleandocs: cleandocs:
$(Q)rm -rf $(BUILDDIR) $(Q)rm -rf $(BUILDDIR)
$(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) -C Documentation/media clean $(Q)$(MAKE) BUILDDIR=$(abspath $(BUILDDIR)) $(build)=Documentation/media clean
endif # HAVE_SPHINX
dochelp: dochelp:
@echo ' Linux kernel internal documentation in different formats (Sphinx):' @echo ' Linux kernel internal documentation in different formats (Sphinx):'
...@@ -109,6 +120,7 @@ dochelp: ...@@ -109,6 +120,7 @@ dochelp:
@echo ' pdfdocs - PDF' @echo ' pdfdocs - PDF'
@echo ' epubdocs - EPUB' @echo ' epubdocs - EPUB'
@echo ' xmldocs - XML' @echo ' xmldocs - XML'
@echo ' linkcheckdocs - check for broken external links (will connect to external hosts)'
@echo ' cleandocs - clean all generated files' @echo ' cleandocs - clean all generated files'
@echo @echo
@echo ' make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2' @echo ' make SPHINXDIRS="s1 s2" [target] Generate only docs of folder s1, s2'
......
...@@ -17,7 +17,7 @@ What is Linux? ...@@ -17,7 +17,7 @@ What is Linux?
loading, shared copy-on-write executables, proper memory management, loading, shared copy-on-write executables, proper memory management,
and multistack networking including IPv4 and IPv6. and multistack networking including IPv4 and IPv6.
It is distributed under the GNU General Public License - see the It is distributed under the GNU General Public License v2 - see the
accompanying COPYING file for more details. accompanying COPYING file for more details.
On what hardware does it run? On what hardware does it run?
...@@ -236,7 +236,7 @@ Configuring the kernel ...@@ -236,7 +236,7 @@ Configuring the kernel
- Having unnecessary drivers will make the kernel bigger, and can - Having unnecessary drivers will make the kernel bigger, and can
under some circumstances lead to problems: probing for a under some circumstances lead to problems: probing for a
nonexistent controller card may confuse your other controllers nonexistent controller card may confuse your other controllers.
- A kernel with math-emulation compiled in will still use the - A kernel with math-emulation compiled in will still use the
coprocessor if one is present: the math emulation will just coprocessor if one is present: the math emulation will just
......
...@@ -93,9 +93,9 @@ Command Language Reference ...@@ -93,9 +93,9 @@ Command Language Reference
At the lexical level, a command comprises a sequence of words separated At the lexical level, a command comprises a sequence of words separated
by spaces or tabs. So these are all equivalent:: by spaces or tabs. So these are all equivalent::
nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' > nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control <debugfs>/dynamic_debug/control
nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' > nullarbor:~ # echo -n ' file svcsock.c line 1603 +p ' >
<debugfs>/dynamic_debug/control <debugfs>/dynamic_debug/control
nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' >
<debugfs>/dynamic_debug/control <debugfs>/dynamic_debug/control
......
...@@ -90,7 +90,7 @@ and thus removes any access restriction implied by it. ...@@ -90,7 +90,7 @@ and thus removes any access restriction implied by it.
4. IOC_PR_PREEMPT 4. IOC_PR_PREEMPT
This ioctl command releases the existing reservation referred to by This ioctl command releases the existing reservation referred to by
old_key and replaces it with a a new reservation of type for the old_key and replaces it with a new reservation of type for the
reservation key new_key. reservation key new_key.
......
...@@ -615,7 +615,7 @@ to allocate a page of memory for that task. ...@@ -615,7 +615,7 @@ to allocate a page of memory for that task.
If a cpuset has its 'cpuset.cpus' modified, then each task in that cpuset If a cpuset has its 'cpuset.cpus' modified, then each task in that cpuset
will have its allowed CPU placement changed immediately. Similarly, will have its allowed CPU placement changed immediately. Similarly,
if a task's pid is written to another cpusets 'cpuset.tasks' file, then its if a task's pid is written to another cpuset's 'tasks' file, then its
allowed CPU placement is changed immediately. If such a task had been allowed CPU placement is changed immediately. If such a task had been
bound to some subset of its cpuset using the sched_setaffinity() call, bound to some subset of its cpuset using the sched_setaffinity() call,
the task will be allowed to run on any CPU allowed in its new cpuset, the task will be allowed to run on any CPU allowed in its new cpuset,
......
...@@ -58,7 +58,7 @@ master_doc = 'index' ...@@ -58,7 +58,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = 'The Linux Kernel' project = 'The Linux Kernel'
copyright = '2016, The kernel development community' copyright = 'The kernel development community'
author = 'The kernel development community' author = 'The kernel development community'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
......
=========================
CPU hotplug in the Kernel
=========================
:Date: December, 2016
:Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>,
Rusty Russell <rusty@rustcorp.com.au>,
Srivatsa Vaddagiri <vatsa@in.ibm.com>,
Ashok Raj <ashok.raj@intel.com>,
Joel Schopp <jschopp@austin.ibm.com>
Introduction
============
Modern advances in system architectures have introduced advanced error
reporting and correction capabilities in processors. There are couple OEMS that
support NUMA hardware which are hot pluggable as well, where physical node
insertion and removal require support for CPU hotplug.
Such advances require CPUs available to a kernel to be removed either for
provisioning reasons, or for RAS purposes to keep an offending CPU off
system execution path. Hence the need for CPU hotplug support in the
Linux kernel.
A more novel use of CPU-hotplug support is its use today in suspend resume
support for SMP. Dual-core and HT support makes even a laptop run SMP kernels
which didn't support these methods.
Command Line Switches
=====================
``maxcpus=n``
Restrict boot time CPUs to *n*. Say if you have fourV CPUs, using
``maxcpus=2`` will only boot two. You can choose to bring the
other CPUs later online.
``nr_cpus=n``
Restrict the total amount CPUs the kernel will support. If the number
supplied here is lower than the number of physically available CPUs than
those CPUs can not be brought online later.
``additional_cpus=n``
Use this to limit hotpluggable CPUs. This option sets
``cpu_possible_mask = cpu_present_mask + additional_cpus``
This option is limited to the IA64 architecture.
``possible_cpus=n``
This option sets ``possible_cpus`` bits in ``cpu_possible_mask``.
This option is limited to the X86 and S390 architecture.
``cede_offline={"off","on"}``
Use this option to disable/enable putting offlined processors to an extended
``H_CEDE`` state on supported pseries platforms. If nothing is specified,
``cede_offline`` is set to "on".
This option is limited to the PowerPC architecture.
``cpu0_hotplug``
Allow to shutdown CPU0.
This option is limited to the X86 architecture.
CPU maps
========
``cpu_possible_mask``
Bitmap of possible CPUs that can ever be available in the
system. This is used to allocate some boot time memory for per_cpu variables
that aren't designed to grow/shrink as CPUs are made available or removed.
Once set during boot time discovery phase, the map is static, i.e no bits
are added or removed anytime. Trimming it accurately for your system needs
upfront can save some boot time memory.
``cpu_online_mask``
Bitmap of all CPUs currently online. Its set in ``__cpu_up()``
after a CPU is available for kernel scheduling and ready to receive
interrupts from devices. Its cleared when a CPU is brought down using
``__cpu_disable()``, before which all OS services including interrupts are
migrated to another target CPU.
``cpu_present_mask``
Bitmap of CPUs currently present in the system. Not all
of them may be online. When physical hotplug is processed by the relevant
subsystem (e.g ACPI) can change and new bit either be added or removed
from the map depending on the event is hot-add/hot-remove. There are currently
no locking rules as of now. Typical usage is to init topology during boot,
at which time hotplug is disabled.
You really don't need to manipulate any of the system CPU maps. They should
be read-only for most use. When setting up per-cpu resources almost always use
``cpu_possible_mask`` or ``for_each_possible_cpu()`` to iterate. To macro
``for_each_cpu()`` can be used to iterate over a custom CPU mask.
Never use anything other than ``cpumask_t`` to represent bitmap of CPUs.
Using CPU hotplug
=================
The kernel option *CONFIG_HOTPLUG_CPU* needs to be enabled. It is currently
available on multiple architectures including ARM, MIPS, PowerPC and X86. The
configuration is done via the sysfs interface: ::
$ ls -lh /sys/devices/system/cpu
total 0
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu0
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu1
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu2
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu3
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu4
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu5
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu6
drwxr-xr-x 9 root root 0 Dec 21 16:33 cpu7
drwxr-xr-x 2 root root 0 Dec 21 16:33 hotplug
-r--r--r-- 1 root root 4.0K Dec 21 16:33 offline
-r--r--r-- 1 root root 4.0K Dec 21 16:33 online
-r--r--r-- 1 root root 4.0K Dec 21 16:33 possible
-r--r--r-- 1 root root 4.0K Dec 21 16:33 present
The files *offline*, *online*, *possible*, *present* represent the CPU masks.
Each CPU folder contains an *online* file which controls the logical on (1) and
off (0) state. To logically shutdown CPU4: ::
$ echo 0 > /sys/devices/system/cpu/cpu4/online
smpboot: CPU 4 is now offline
Once the CPU is shutdown, it will be removed from */proc/interrupts*,
*/proc/cpuinfo* and should also not be shown visible by the *top* command. To
bring CPU4 back online: ::
$ echo 1 > /sys/devices/system/cpu/cpu4/online
smpboot: Booting Node 0 Processor 4 APIC 0x1
The CPU is usable again. This should work on all CPUs. CPU0 is often special
and excluded from CPU hotplug. On X86 the kernel option
*CONFIG_BOOTPARAM_HOTPLUG_CPU0* has to be enabled in order to be able to
shutdown CPU0. Alternatively the kernel command option *cpu0_hotplug* can be
used. Some known dependencies of CPU0:
* Resume from hibernate/suspend. Hibernate/suspend will fail if CPU0 is offline.
* PIC interrupts. CPU0 can't be removed if a PIC interrupt is detected.
Please let Fenghua Yu <fenghua.yu@intel.com> know if you find any dependencies
on CPU0.
The CPU hotplug coordination
============================
The offline case
----------------
Once a CPU has been logically shutdown the teardown callbacks of registered
hotplug states will be invoked, starting with ``CPUHP_ONLINE`` and terminating
at state ``CPUHP_OFFLINE``. This includes:
* If tasks are frozen due to a suspend operation then *cpuhp_tasks_frozen*
will be set to true.
* All processes are migrated away from this outgoing CPU to new CPUs.
The new CPU is chosen from each process' current cpuset, which may be
a subset of all online CPUs.
* All interrupts targeted to this CPU are migrated to a new CPU
* timers are also migrated to a new CPU
* Once all services are migrated, kernel calls an arch specific routine
``__cpu_disable()`` to perform arch specific cleanup.
Using the hotplug API
---------------------
It is possible to receive notifications once a CPU is offline or onlined. This
might be important to certain drivers which need to perform some kind of setup
or clean up functions based on the number of available CPUs: ::
#include <linux/cpuhotplug.h>
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "X/Y:online",
Y_online, Y_prepare_down);
*X* is the subsystem and *Y* the particular driver. The *Y_online* callback
will be invoked during registration on all online CPUs. If an error
occurs during the online callback the *Y_prepare_down* callback will be
invoked on all CPUs on which the online callback was previously invoked.
After registration completed, the *Y_online* callback will be invoked
once a CPU is brought online and *Y_prepare_down* will be invoked when a
CPU is shutdown. All resources which were previously allocated in
*Y_online* should be released in *Y_prepare_down*.
The return value *ret* is negative if an error occurred during the
registration process. Otherwise a positive value is returned which
contains the allocated hotplug for dynamically allocated states
(*CPUHP_AP_ONLINE_DYN*). It will return zero for predefined states.
The callback can be remove by invoking ``cpuhp_remove_state()``. In case of a
dynamically allocated state (*CPUHP_AP_ONLINE_DYN*) use the returned state.
During the removal of a hotplug state the teardown callback will be invoked.
Multiple instances
~~~~~~~~~~~~~~~~~~
If a driver has multiple instances and each instance needs to perform the
callback independently then it is likely that a ''multi-state'' should be used.
First a multi-state state needs to be registered: ::
ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "X/Y:online,
Y_online, Y_prepare_down);
Y_hp_online = ret;
The ``cpuhp_setup_state_multi()`` behaves similar to ``cpuhp_setup_state()``
except it prepares the callbacks for a multi state and does not invoke
the callbacks. This is a one time setup.
Once a new instance is allocated, you need to register this new instance: ::
ret = cpuhp_state_add_instance(Y_hp_online, &d->node);
This function will add this instance to your previously allocated
*Y_hp_online* state and invoke the previously registered callback
(*Y_online*) on all online CPUs. The *node* element is a ``struct
hlist_node`` member of your per-instance data structure.
On removal of the instance: ::
cpuhp_state_remove_instance(Y_hp_online, &d->node)
should be invoked which will invoke the teardown callback on all online
CPUs.
Manual setup
~~~~~~~~~~~~
Usually it is handy to invoke setup and teardown callbacks on registration or
removal of a state because usually the operation needs to performed once a CPU
goes online (offline) and during initial setup (shutdown) of the driver. However
each registration and removal function is also available with a ``_nocalls``
suffix which does not invoke the provided callbacks if the invocation of the
callbacks is not desired. During the manual setup (or teardown) the functions
``get_online_cpus()`` and ``put_online_cpus()`` should be used to inhibit CPU
hotplug operations.
The ordering of the events
--------------------------
The hotplug states are defined in ``include/linux/cpuhotplug.h``:
* The states *CPUHP_OFFLINE* … *CPUHP_AP_OFFLINE* are invoked before the
CPU is up.
* The states *CPUHP_AP_OFFLINE* … *CPUHP_AP_ONLINE* are invoked
just the after the CPU has been brought up. The interrupts are off and
the scheduler is not yet active on this CPU. Starting with *CPUHP_AP_OFFLINE*
the callbacks are invoked on the target CPU.
* The states between *CPUHP_AP_ONLINE_DYN* and *CPUHP_AP_ONLINE_DYN_END* are
reserved for the dynamic allocation.
* The states are invoked in the reverse order on CPU shutdown starting with
*CPUHP_ONLINE* and stopping at *CPUHP_OFFLINE*. Here the callbacks are
invoked on the CPU that will be shutdown until *CPUHP_AP_OFFLINE*.
A dynamically allocated state via *CPUHP_AP_ONLINE_DYN* is often enough.
However if an earlier invocation during the bring up or shutdown is required
then an explicit state should be acquired. An explicit state might also be
required if the hotplug event requires specific ordering in respect to
another hotplug event.
Testing of hotplug states
=========================
One way to verify whether a custom state is working as expected or not is to
shutdown a CPU and then put it online again. It is also possible to put the CPU
to certain state (for instance *CPUHP_AP_ONLINE*) and then go back to
*CPUHP_ONLINE*. This would simulate an error one state after *CPUHP_AP_ONLINE*
which would lead to rollback to the online state.
All registered states are enumerated in ``/sys/devices/system/cpu/hotplug/states``: ::
$ tail /sys/devices/system/cpu/hotplug/states
138: mm/vmscan:online
139: mm/vmstat:online
140: lib/percpu_cnt:online
141: acpi/cpu-drv:online
142: base/cacheinfo:online
143: virtio/net:online
144: x86/mce:online
145: printk:online
168: sched:active
169: online
To rollback CPU4 to ``lib/percpu_cnt:online`` and back online just issue: ::
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
$ echo 140 > /sys/devices/system/cpu/cpu4/hotplug/target
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
140
It is important to note that the teardown callbac of state 140 have been
invoked. And now get back online: ::
$ echo 169 > /sys/devices/system/cpu/cpu4/hotplug/target
$ cat /sys/devices/system/cpu/cpu4/hotplug/state
169
With trace events enabled, the individual steps are visible, too: ::
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
bash-394 [001] 22.976: cpuhp_enter: cpu: 0004 target: 140 step: 169 (cpuhp_kick_ap_work)
cpuhp/4-31 [004] 22.977: cpuhp_enter: cpu: 0004 target: 140 step: 168 (sched_cpu_deactivate)
cpuhp/4-31 [004] 22.990: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0
cpuhp/4-31 [004] 22.991: cpuhp_enter: cpu: 0004 target: 140 step: 144 (mce_cpu_pre_down)
cpuhp/4-31 [004] 22.992: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0
cpuhp/4-31 [004] 22.993: cpuhp_multi_enter: cpu: 0004 target: 140 step: 143 (virtnet_cpu_down_prep)
cpuhp/4-31 [004] 22.994: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0
cpuhp/4-31 [004] 22.995: cpuhp_enter: cpu: 0004 target: 140 step: 142 (cacheinfo_cpu_pre_down)
cpuhp/4-31 [004] 22.996: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0
bash-394 [001] 22.997: cpuhp_exit: cpu: 0004 state: 140 step: 169 ret: 0
bash-394 [005] 95.540: cpuhp_enter: cpu: 0004 target: 169 step: 140 (cpuhp_kick_ap_work)
cpuhp/4-31 [004] 95.541: cpuhp_enter: cpu: 0004 target: 169 step: 141 (acpi_soft_cpu_online)
cpuhp/4-31 [004] 95.542: cpuhp_exit: cpu: 0004 state: 141 step: 141 ret: 0
cpuhp/4-31 [004] 95.543: cpuhp_enter: cpu: 0004 target: 169 step: 142 (cacheinfo_cpu_online)
cpuhp/4-31 [004] 95.544: cpuhp_exit: cpu: 0004 state: 142 step: 142 ret: 0
cpuhp/4-31 [004] 95.545: cpuhp_multi_enter: cpu: 0004 target: 169 step: 143 (virtnet_cpu_online)
cpuhp/4-31 [004] 95.546: cpuhp_exit: cpu: 0004 state: 143 step: 143 ret: 0
cpuhp/4-31 [004] 95.547: cpuhp_enter: cpu: 0004 target: 169 step: 144 (mce_cpu_online)
cpuhp/4-31 [004] 95.548: cpuhp_exit: cpu: 0004 state: 144 step: 144 ret: 0
cpuhp/4-31 [004] 95.549: cpuhp_enter: cpu: 0004 target: 169 step: 145 (console_cpu_notify)
cpuhp/4-31 [004] 95.550: cpuhp_exit: cpu: 0004 state: 145 step: 145 ret: 0
cpuhp/4-31 [004] 95.551: cpuhp_enter: cpu: 0004 target: 169 step: 168 (sched_cpu_activate)
cpuhp/4-31 [004] 95.552: cpuhp_exit: cpu: 0004 state: 168 step: 168 ret: 0
bash-394 [005] 95.553: cpuhp_exit: cpu: 0004 state: 169 step: 140 ret: 0
As it an be seen, CPU4 went down until timestamp 22.996 and then back up until
95.552. All invoked callbacks including their return codes are visible in the
trace.
Architecture's requirements
===========================
The following functions and configurations are required:
``CONFIG_HOTPLUG_CPU``
This entry needs to be enabled in Kconfig
``__cpu_up()``
Arch interface to bring up a CPU
``__cpu_disable()``
Arch interface to shutdown a CPU, no more interrupts can be handled by the
kernel after the routine returns. This includes the shutdown of the timer.
``__cpu_die()``
This actually supposed to ensure death of the CPU. Actually look at some
example code in other arch that implement CPU hotplug. The processor is taken
down from the ``idle()`` loop for that specific architecture. ``__cpu_die()``
typically waits for some per_cpu state to be set, to ensure the processor dead
routine is called to be sure positively.
User Space Notification
=======================
After CPU successfully onlined or offline udev events are sent. A udev rule like: ::
SUBSYSTEM=="cpu", DRIVERS=="processor", DEVPATH=="/devices/system/cpu/*", RUN+="the_hotplug_receiver.sh"
will receive all events. A script like: ::
#!/bin/sh
if [ "${ACTION}" = "offline" ]
then
echo "CPU ${DEVPATH##*/} offline"
elif [ "${ACTION}" = "online" ]
then
echo "CPU ${DEVPATH##*/} online"
fi
can process the event further.
Kernel Inline Documentations Reference
======================================
.. kernel-doc:: include/linux/cpuhotplug.h
...@@ -13,6 +13,7 @@ Core utilities ...@@ -13,6 +13,7 @@ Core utilities
assoc_array assoc_array
atomic_ops atomic_ops
cpu_hotplug
local_ops local_ops
workqueue workqueue
......
...@@ -82,7 +82,9 @@ UltraSPARC-III ...@@ -82,7 +82,9 @@ UltraSPARC-III
------- -------
Several "PowerBook" and "iBook2" notebooks are supported. Several "PowerBook" and "iBook2" notebooks are supported.
The following POWER processors are supported in powernv mode:
POWER8
POWER9
1.5 SuperH 1.5 SuperH
---------- ----------
......
CPU hotplug Support in Linux(tm) Kernel
Maintainers:
CPU Hotplug Core:
Rusty Russell <rusty@rustcorp.com.au>
Srivatsa Vaddagiri <vatsa@in.ibm.com>
i386:
Zwane Mwaikambo <zwanem@gmail.com>
ppc64:
Nathan Lynch <nathanl@austin.ibm.com>
Joel Schopp <jschopp@austin.ibm.com>
ia64/x86_64:
Ashok Raj <ashok.raj@intel.com>
s390:
Heiko Carstens <heiko.carstens@de.ibm.com>
Authors: Ashok Raj <ashok.raj@intel.com>
Lots of feedback: Nathan Lynch <nathanl@austin.ibm.com>,
Joel Schopp <jschopp@austin.ibm.com>
Introduction
Modern advances in system architectures have introduced advanced error
reporting and correction capabilities in processors. CPU architectures permit
partitioning support, where compute resources of a single CPU could be made
available to virtual machine environments. There are couple OEMS that
support NUMA hardware which are hot pluggable as well, where physical
node insertion and removal require support for CPU hotplug.
Such advances require CPUs available to a kernel to be removed either for
provisioning reasons, or for RAS purposes to keep an offending CPU off
system execution path. Hence the need for CPU hotplug support in the
Linux kernel.
A more novel use of CPU-hotplug support is its use today in suspend
resume support for SMP. Dual-core and HT support makes even
a laptop run SMP kernels which didn't support these methods. SMP support
for suspend/resume is a work in progress.
General Stuff about CPU Hotplug
--------------------------------
Command Line Switches
---------------------
maxcpus=n Restrict boot time cpus to n. Say if you have 4 cpus, using
maxcpus=2 will only boot 2. You can choose to bring the
other cpus later online, read FAQ's for more info.
additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets
cpu_possible_mask = cpu_present_mask + additional_cpus
cede_offline={"off","on"} Use this option to disable/enable putting offlined
processors to an extended H_CEDE state on
supported pseries platforms.
If nothing is specified,
cede_offline is set to "on".
(*) Option valid only for following architectures
- ia64
ia64 uses the number of disabled local apics in ACPI tables MADT to
determine the number of potentially hot-pluggable cpus. The implementation
should only rely on this to count the # of cpus, but *MUST* not rely
on the apicid values in those tables for disabled apics. In the event
BIOS doesn't mark such hot-pluggable cpus as disabled entries, one could
use this parameter "additional_cpus=x" to represent those cpus in the
cpu_possible_mask.
possible_cpus=n [s390,x86_64] use this to set hotpluggable cpus.
This option sets possible_cpus bits in
cpu_possible_mask. Thus keeping the numbers of bits set
constant even if the machine gets rebooted.
CPU maps and such
-----------------
[More on cpumaps and primitive to manipulate, please check
include/linux/cpumask.h that has more descriptive text.]
cpu_possible_mask: Bitmap of possible CPUs that can ever be available in the
system. This is used to allocate some boot time memory for per_cpu variables
that aren't designed to grow/shrink as CPUs are made available or removed.
Once set during boot time discovery phase, the map is static, i.e no bits
are added or removed anytime. Trimming it accurately for your system needs
upfront can save some boot time memory. See below for how we use heuristics
in x86_64 case to keep this under check.
cpu_online_mask: Bitmap of all CPUs currently online. It's set in __cpu_up()
after a CPU is available for kernel scheduling and ready to receive
interrupts from devices. It's cleared when a CPU is brought down using
__cpu_disable(), before which all OS services including interrupts are
migrated to another target CPU.
cpu_present_mask: Bitmap of CPUs currently present in the system. Not all
of them may be online. When physical hotplug is processed by the relevant
subsystem (e.g ACPI) can change and new bit either be added or removed
from the map depending on the event is hot-add/hot-remove. There are currently
no locking rules as of now. Typical usage is to init topology during boot,
at which time hotplug is disabled.
You really dont need to manipulate any of the system cpu maps. They should
be read-only for most use. When setting up per-cpu resources almost always use
cpu_possible_mask/for_each_possible_cpu() to iterate.
Never use anything other than cpumask_t to represent bitmap of CPUs.
#include <linux/cpumask.h>
for_each_possible_cpu - Iterate over cpu_possible_mask
for_each_online_cpu - Iterate over cpu_online_mask
for_each_present_cpu - Iterate over cpu_present_mask
for_each_cpu(x,mask) - Iterate over some random collection of cpu mask.
#include <linux/cpu.h>
get_online_cpus() and put_online_cpus():
The above calls are used to inhibit cpu hotplug operations. While the
cpu_hotplug.refcount is non zero, the cpu_online_mask will not change.
If you merely need to avoid cpus going away, you could also use
preempt_disable() and preempt_enable() for those sections.
Just remember the critical section cannot call any
function that can sleep or schedule this process away. The preempt_disable()
will work as long as stop_machine_run() is used to take a cpu down.
CPU Hotplug - Frequently Asked Questions.
Q: How to enable my kernel to support CPU hotplug?
A: When doing make defconfig, Enable CPU hotplug support
"Processor type and Features" -> Support for Hotpluggable CPUs
Make sure that you have CONFIG_SMP turned on as well.
You would need to enable CONFIG_HOTPLUG_CPU for SMP suspend/resume support
as well.
Q: What architectures support CPU hotplug?
A: As of 2.6.14, the following architectures support CPU hotplug.
i386 (Intel), ppc, ppc64, parisc, s390, ia64 and x86_64
Q: How to test if hotplug is supported on the newly built kernel?
A: You should now notice an entry in sysfs.
Check if sysfs is mounted, using the "mount" command. You should notice
an entry as shown below in the output.
....
none on /sys type sysfs (rw)
....
If this is not mounted, do the following.
#mkdir /sys
#mount -t sysfs sys /sys
Now you should see entries for all present cpu, the following is an example
in a 8-way system.
#pwd
#/sys/devices/system/cpu
#ls -l
total 0
drwxr-xr-x 10 root root 0 Sep 19 07:44 .
drwxr-xr-x 13 root root 0 Sep 19 07:45 ..
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu0
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu1
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu2
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu3
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu4
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu5
drwxr-xr-x 3 root root 0 Sep 19 07:44 cpu6
drwxr-xr-x 3 root root 0 Sep 19 07:48 cpu7
Under each directory you would find an "online" file which is the control
file to logically online/offline a processor.
Q: Does hot-add/hot-remove refer to physical add/remove of cpus?
A: The usage of hot-add/remove may not be very consistently used in the code.
CONFIG_HOTPLUG_CPU enables logical online/offline capability in the kernel.
To support physical addition/removal, one would need some BIOS hooks and
the platform should have something like an attention button in PCI hotplug.
CONFIG_ACPI_HOTPLUG_CPU enables ACPI support for physical add/remove of CPUs.
Q: How do I logically offline a CPU?
A: Do the following.
#echo 0 > /sys/devices/system/cpu/cpuX/online
Once the logical offline is successful, check
#cat /proc/interrupts
You should now not see the CPU that you removed. Also online file will report
the state as 0 when a CPU is offline and 1 when it's online.
#To display the current cpu state.
#cat /sys/devices/system/cpu/cpuX/online
Q: Why can't I remove CPU0 on some systems?
A: Some architectures may have some special dependency on a certain CPU.
For e.g in IA64 platforms we have ability to send platform interrupts to the
OS. a.k.a Corrected Platform Error Interrupts (CPEI). In current ACPI
specifications, we didn't have a way to change the target CPU. Hence if the
current ACPI version doesn't support such re-direction, we disable that CPU
by making it not-removable.
In such cases you will also notice that the online file is missing under cpu0.
Q: Is CPU0 removable on X86?
A: Yes. If kernel is compiled with CONFIG_BOOTPARAM_HOTPLUG_CPU0=y, CPU0 is
removable by default. Otherwise, CPU0 is also removable by kernel option
cpu0_hotplug.
But some features depend on CPU0. Two known dependencies are:
1. Resume from hibernate/suspend depends on CPU0. Hibernate/suspend will fail if
CPU0 is offline and you need to online CPU0 before hibernate/suspend can
continue.
2. PIC interrupts also depend on CPU0. CPU0 can't be removed if a PIC interrupt
is detected.
It's said poweroff/reboot may depend on CPU0 on some machines although I haven't
seen any poweroff/reboot failure so far after CPU0 is offline on a few tested
machines.
Please let me know if you know or see any other dependencies of CPU0.
If the dependencies are under your control, you can turn on CPU0 hotplug feature
either by CONFIG_BOOTPARAM_HOTPLUG_CPU0 or by kernel parameter cpu0_hotplug.
--Fenghua Yu <fenghua.yu@intel.com>
Q: How do I find out if a particular CPU is not removable?
A: Depending on the implementation, some architectures may show this by the
absence of the "online" file. This is done if it can be determined ahead of
time that this CPU cannot be removed.
In some situations, this can be a run time check, i.e if you try to remove the
last CPU, this will not be permitted. You can find such failures by
investigating the return value of the "echo" command.
Q: What happens when a CPU is being logically offlined?
A: The following happen, listed in no particular order :-)
- A notification is sent to in-kernel registered modules by sending an event
CPU_DOWN_PREPARE or CPU_DOWN_PREPARE_FROZEN, depending on whether or not the
CPU is being offlined while tasks are frozen due to a suspend operation in
progress
- All processes are migrated away from this outgoing CPU to new CPUs.
The new CPU is chosen from each process' current cpuset, which may be
a subset of all online CPUs.
- All interrupts targeted to this CPU are migrated to a new CPU
- timers/bottom half/task lets are also migrated to a new CPU
- Once all services are migrated, kernel calls an arch specific routine
__cpu_disable() to perform arch specific cleanup.
- Once this is successful, an event for successful cleanup is sent by an event
CPU_DEAD (or CPU_DEAD_FROZEN if tasks are frozen due to a suspend while the
CPU is being offlined).
"It is expected that each service cleans up when the CPU_DOWN_PREPARE
notifier is called, when CPU_DEAD is called it's expected there is nothing
running on behalf of this CPU that was offlined"
Q: If I have some kernel code that needs to be aware of CPU arrival and
departure, how to i arrange for proper notification?
A: This is what you would need in your kernel code to receive notifications.
#include <linux/cpu.h>
static int foobar_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
foobar_online_action(cpu);
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
foobar_dead_action(cpu);
break;
}
return NOTIFY_OK;
}
static struct notifier_block foobar_cpu_notifier =
{
.notifier_call = foobar_cpu_callback,
};
You need to call register_cpu_notifier() from your init function.
Init functions could be of two types:
1. early init (init function called when only the boot processor is online).
2. late init (init function called _after_ all the CPUs are online).
For the first case, you should add the following to your init function
register_cpu_notifier(&foobar_cpu_notifier);
For the second case, you should add the following to your init function
register_hotcpu_notifier(&foobar_cpu_notifier);
You can fail PREPARE notifiers if something doesn't work to prepare resources.
This will stop the activity and send a following CANCELED event back.
CPU_DEAD should not be failed, its just a goodness indication, but bad
things will happen if a notifier in path sent a BAD notify code.
Q: I don't see my action being called for all CPUs already up and running?
A: Yes, CPU notifiers are called only when new CPUs are on-lined or offlined.
If you need to perform some action for each CPU already in the system, then
do this:
for_each_online_cpu(i) {
foobar_cpu_callback(&foobar_cpu_notifier, CPU_UP_PREPARE, i);
foobar_cpu_callback(&foobar_cpu_notifier, CPU_ONLINE, i);
}
However, if you want to register a hotplug callback, as well as perform
some initialization for CPUs that are already online, then do this:
Version 1: (Correct)
---------
cpu_notifier_register_begin();
for_each_online_cpu(i) {
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_UP_PREPARE, i);
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_ONLINE, i);
}
/* Note the use of the double underscored version of the API */
__register_cpu_notifier(&foobar_cpu_notifier);
cpu_notifier_register_done();
Note that the following code is *NOT* the right way to achieve this,
because it is prone to an ABBA deadlock between the cpu_add_remove_lock
and the cpu_hotplug.lock.
Version 2: (Wrong!)
---------
get_online_cpus();
for_each_online_cpu(i) {
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_UP_PREPARE, i);
foobar_cpu_callback(&foobar_cpu_notifier,
CPU_ONLINE, i);
}
register_cpu_notifier(&foobar_cpu_notifier);
put_online_cpus();
So always use the first version shown above when you want to register
callbacks as well as initialize the already online CPUs.
Q: If I would like to develop CPU hotplug support for a new architecture,
what do I need at a minimum?
A: The following are what is required for CPU hotplug infrastructure to work
correctly.
- Make sure you have an entry in Kconfig to enable CONFIG_HOTPLUG_CPU
- __cpu_up() - Arch interface to bring up a CPU
- __cpu_disable() - Arch interface to shutdown a CPU, no more interrupts
can be handled by the kernel after the routine
returns. Including local APIC timers etc are
shutdown.
- __cpu_die() - This actually supposed to ensure death of the CPU.
Actually look at some example code in other arch
that implement CPU hotplug. The processor is taken
down from the idle() loop for that specific
architecture. __cpu_die() typically waits for some
per_cpu state to be set, to ensure the processor
dead routine is called to be sure positively.
Q: I need to ensure that a particular CPU is not removed when there is some
work specific to this CPU in progress.
A: There are two ways. If your code can be run in interrupt context, use
smp_call_function_single(), otherwise use work_on_cpu(). Note that
work_on_cpu() is slow, and can fail due to out of memory:
int my_func_on_cpu(int cpu)
{
int err;
get_online_cpus();
if (!cpu_online(cpu))
err = -EINVAL;
else
#if NEEDS_BLOCKING
err = work_on_cpu(cpu, __my_func_on_cpu, NULL);
#else
smp_call_function_single(cpu, __my_func_on_cpu, &err,
true);
#endif
put_online_cpus();
return err;
}
Q: How do we determine how many CPUs are available for hotplug.
A: There is no clear spec defined way from ACPI that can give us that
information today. Based on some input from Natalie of Unisys,
that the ACPI MADT (Multiple APIC Description Tables) marks those possible
CPUs in a system with disabled status.
Andi implemented some simple heuristics that count the number of disabled
CPUs in MADT as hotpluggable CPUS. In the case there are no disabled CPUS
we assume 1/2 the number of CPUs currently present can be hotplugged.
Caveat: ACPI MADT can only provide 256 entries in systems with only ACPI 2.0c
or earlier ACPI version supported, because the apicid field in MADT is only
8 bits. From ACPI 3.0, this limitation was removed since the apicid field
was extended to 32 bits with x2APIC introduced.
User Space Notification
Hotplug support for devices is common in Linux today. Its being used today to
support automatic configuration of network, usb and pci devices. A hotplug
event can be used to invoke an agent script to perform the configuration task.
You can add /etc/hotplug/cpu.agent to handle hotplug notification user space
scripts.
#!/bin/bash
# $Id: cpu.agent
# Kernel hotplug params include:
#ACTION=%s [online or offline]
#DEVPATH=%s
#
cd /etc/hotplug
. ./hotplug.functions
case $ACTION in
online)
echo `date` ":cpu.agent" add cpu >> /tmp/hotplug.txt
;;
offline)
echo `date` ":cpu.agent" remove cpu >>/tmp/hotplug.txt
;;
*)
debug_mesg CPU $ACTION event not supported
exit 1
;;
esac
...@@ -103,3 +103,9 @@ have already built it. ...@@ -103,3 +103,9 @@ have already built it.
The optional make variable CF can be used to pass arguments to sparse. The The optional make variable CF can be used to pass arguments to sparse. The
build system passes -Wbitwise to sparse automatically. build system passes -Wbitwise to sparse automatically.
Checking RCU annotations
~~~~~~~~~~~~~~~~~~~~~~~~
RCU annotations are not checked by default. To enable RCU annotation
checks, include -DCONFIG_SPARSE_RCU_POINTER in your CF flags.
...@@ -116,9 +116,11 @@ crc32table.h* ...@@ -116,9 +116,11 @@ crc32table.h*
cscope.* cscope.*
defkeymap.c defkeymap.c
devlist.h* devlist.h*
devicetable-offsets.h
dnotify_test dnotify_test
docproc docproc
dslm dslm
dtc
elf2ecoff elf2ecoff
elfconfig.h* elfconfig.h*
evergreen_reg_safe.h evergreen_reg_safe.h
...@@ -153,8 +155,8 @@ keywords.c ...@@ -153,8 +155,8 @@ keywords.c
ksym.c* ksym.c*
ksym.h* ksym.h*
kxgettext kxgettext
lex.c *lex.c
lex.*.c *lex.*.c
linux linux
logo_*.c logo_*.c
logo_*_clut224.c logo_*_clut224.c
...@@ -215,6 +217,7 @@ series ...@@ -215,6 +217,7 @@ series
setup setup
setup.bin setup.bin
setup.elf setup.elf
sortextable
sImage sImage
sm_tbl* sm_tbl*
split-include split-include
......
.. Copyright 2001 Matthew Wilcox
..
.. This documentation is free software; you can redistribute
.. it and/or modify it under the terms of the GNU General Public
.. License as published by the Free Software Foundation; either
.. version 2 of the License, or (at your option) any later
.. version.
===============================
Bus-Independent Device Accesses
===============================
:Author: Matthew Wilcox
:Author: Alan Cox
Introduction
============
Linux provides an API which abstracts performing IO across all busses
and devices, allowing device drivers to be written independently of bus
type.
Memory Mapped IO
================
Getting Access to the Device
----------------------------
The most widely supported form of IO is memory mapped IO. That is, a
part of the CPU's address space is interpreted not as accesses to
memory, but as accesses to a device. Some architectures define devices
to be at a fixed address, but most have some method of discovering
devices. The PCI bus walk is a good example of such a scheme. This
document does not cover how to receive such an address, but assumes you
are starting with one. Physical addresses are of type unsigned long.
This address should not be used directly. Instead, to get an address
suitable for passing to the accessor functions described below, you
should call :c:func:`ioremap()`. An address suitable for accessing
the device will be returned to you.
After you've finished using the device (say, in your module's exit
routine), call :c:func:`iounmap()` in order to return the address
space to the kernel. Most architectures allocate new address space each
time you call :c:func:`ioremap()`, and they can run out unless you
call :c:func:`iounmap()`.
Accessing the device
--------------------
The part of the interface most used by drivers is reading and writing
memory-mapped registers on the device. Linux provides interfaces to read
and write 8-bit, 16-bit, 32-bit and 64-bit quantities. Due to a
historical accident, these are named byte, word, long and quad accesses.
Both read and write accesses are supported; there is no prefetch support
at this time.
The functions are named readb(), readw(), readl(), readq(),
readb_relaxed(), readw_relaxed(), readl_relaxed(), readq_relaxed(),
writeb(), writew(), writel() and writeq().
Some devices (such as framebuffers) would like to use larger transfers than
8 bytes at a time. For these devices, the :c:func:`memcpy_toio()`,
:c:func:`memcpy_fromio()` and :c:func:`memset_io()` functions are
provided. Do not use memset or memcpy on IO addresses; they are not
guaranteed to copy data in order.
The read and write functions are defined to be ordered. That is the
compiler is not permitted to reorder the I/O sequence. When the ordering
can be compiler optimised, you can use __readb() and friends to
indicate the relaxed ordering. Use this with care.
While the basic functions are defined to be synchronous with respect to
each other and ordered with respect to each other the busses the devices
sit on may themselves have asynchronicity. In particular many authors
are burned by the fact that PCI bus writes are posted asynchronously. A
driver author must issue a read from the same device to ensure that
writes have occurred in the specific cases the author cares. This kind
of property cannot be hidden from driver writers in the API. In some
cases, the read used to flush the device may be expected to fail (if the
card is resetting, for example). In that case, the read should be done
from config space, which is guaranteed to soft-fail if the card doesn't
respond.
The following is an example of flushing a write to a device when the
driver would like to ensure the write's effects are visible prior to
continuing execution::
static inline void
qla1280_disable_intrs(struct scsi_qla_host *ha)
{
struct device_reg *reg;
reg = ha->iobase;
/* disable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, 0);
/*
* The following read will ensure that the above write
* has been received by the device before we return from this
* function.
*/
RD_REG_WORD(&reg->ictrl);
ha->flags.ints_enabled = 0;
}
In addition to write posting, on some large multiprocessing systems
(e.g. SGI Challenge, Origin and Altix machines) posted writes won't be
strongly ordered coming from different CPUs. Thus it's important to
properly protect parts of your driver that do memory-mapped writes with
locks and use the :c:func:`mmiowb()` to make sure they arrive in the
order intended. Issuing a regular readX() will also ensure write ordering,
but should only be used when the
driver has to be sure that the write has actually arrived at the device
(not that it's simply ordered with respect to other writes), since a
full readX() is a relatively expensive operation.
Generally, one should use :c:func:`mmiowb()` prior to releasing a spinlock
that protects regions using :c:func:`writeb()` or similar functions that
aren't surrounded by readb() calls, which will ensure ordering
and flushing. The following pseudocode illustrates what might occur if
write ordering isn't guaranteed via :c:func:`mmiowb()` or one of the
readX() functions::
CPU A: spin_lock_irqsave(&dev_lock, flags)
CPU A: ...
CPU A: writel(newval, ring_ptr);
CPU A: spin_unlock_irqrestore(&dev_lock, flags)
...
CPU B: spin_lock_irqsave(&dev_lock, flags)
CPU B: writel(newval2, ring_ptr);
CPU B: ...
CPU B: spin_unlock_irqrestore(&dev_lock, flags)
In the case above, newval2 could be written to ring_ptr before newval.
Fixing it is easy though::
CPU A: spin_lock_irqsave(&dev_lock, flags)
CPU A: ...
CPU A: writel(newval, ring_ptr);
CPU A: mmiowb(); /* ensure no other writes beat us to the device */
CPU A: spin_unlock_irqrestore(&dev_lock, flags)
...
CPU B: spin_lock_irqsave(&dev_lock, flags)
CPU B: writel(newval2, ring_ptr);
CPU B: ...
CPU B: mmiowb();
CPU B: spin_unlock_irqrestore(&dev_lock, flags)
See tg3.c for a real world example of how to use :c:func:`mmiowb()`
PCI ordering rules also guarantee that PIO read responses arrive after any
outstanding DMA writes from that bus, since for some devices the result of
a readb() call may signal to the driver that a DMA transaction is
complete. In many cases, however, the driver may want to indicate that the
next readb() call has no relation to any previous DMA writes
performed by the device. The driver can use readb_relaxed() for
these cases, although only some platforms will honor the relaxed
semantics. Using the relaxed read functions will provide significant
performance benefits on platforms that support it. The qla2xxx driver
provides examples of how to use readX_relaxed(). In many cases, a majority
of the driver's readX() calls can safely be converted to readX_relaxed()
calls, since only a few will indicate or depend on DMA completion.
Port Space Accesses
===================
Port Space Explained
--------------------
Another form of IO commonly supported is Port Space. This is a range of
addresses separate to the normal memory address space. Access to these
addresses is generally not as fast as accesses to the memory mapped
addresses, and it also has a potentially smaller address space.
Unlike memory mapped IO, no preparation is required to access port
space.
Accessing Port Space
--------------------
Accesses to this space are provided through a set of functions which
allow 8-bit, 16-bit and 32-bit accesses; also known as byte, word and
long. These functions are :c:func:`inb()`, :c:func:`inw()`,
:c:func:`inl()`, :c:func:`outb()`, :c:func:`outw()` and
:c:func:`outl()`.
Some variants are provided for these functions. Some devices require
that accesses to their ports are slowed down. This functionality is
provided by appending a ``_p`` to the end of the function.
There are also equivalents to memcpy. The :c:func:`ins()` and
:c:func:`outs()` functions copy bytes, words or longs to the given
port.
Public Functions Provided
=========================
.. kernel-doc:: arch/x86/include/asm/io.h
:internal:
.. kernel-doc:: lib/pci_iomap.c
:export:
.. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
.. |struct generic_pm_domain| replace:: :c:type:`struct generic_pm_domain <generic_pm_domain>`
============ ============
Device links Device links
============ ============
...@@ -120,12 +123,11 @@ Examples ...@@ -120,12 +123,11 @@ Examples
is the same as if the MMU was the parent of the master device. is the same as if the MMU was the parent of the master device.
The fact that both devices share the same power domain would normally The fact that both devices share the same power domain would normally
suggest usage of a :c:type:`struct dev_pm_domain` or :c:type:`struct suggest usage of a |struct dev_pm_domain| or |struct generic_pm_domain|,
generic_pm_domain`, however these are not independent devices that however these are not independent devices that happen to share a power
happen to share a power switch, but rather the MMU device serves the switch, but rather the MMU device serves the busmaster device and is
busmaster device and is useless without it. A device link creates a useless without it. A device link creates a synthetic hierarchical
synthetic hierarchical relationship between the devices and is thus relationship between the devices and is thus more apt.
more apt.
* A Thunderbolt host controller comprises a number of PCIe hotplug ports * A Thunderbolt host controller comprises a number of PCIe hotplug ports
and an NHI device to manage the PCIe switch. On resume from system sleep, and an NHI device to manage the PCIe switch. On resume from system sleep,
...@@ -157,7 +159,7 @@ Examples ...@@ -157,7 +159,7 @@ Examples
Alternatives Alternatives
============ ============
* A :c:type:`struct dev_pm_domain` can be used to override the bus, * A |struct dev_pm_domain| can be used to override the bus,
class or device type callbacks. It is intended for devices sharing class or device type callbacks. It is intended for devices sharing
a single on/off switch, however it does not guarantee a specific a single on/off switch, however it does not guarantee a specific
suspend/resume ordering, this needs to be implemented separately. suspend/resume ordering, this needs to be implemented separately.
...@@ -166,7 +168,7 @@ Alternatives ...@@ -166,7 +168,7 @@ Alternatives
suspended. Furthermore it cannot be used to enforce a specific shutdown suspended. Furthermore it cannot be used to enforce a specific shutdown
ordering or a driver presence dependency. ordering or a driver presence dependency.
* A :c:type:`struct generic_pm_domain` is a lot more heavyweight than a * A |struct generic_pm_domain| is a lot more heavyweight than a
device link and does not allow for shutdown ordering or driver presence device link and does not allow for shutdown ordering or driver presence
dependencies. It also cannot be used on ACPI systems. dependencies. It also cannot be used on ACPI systems.
......
=======
Buffers
=======
* struct :c:type:`iio_buffer` — general buffer structure
* :c:func:`iio_validate_scan_mask_onehot` — Validates that exactly one channel
is selected
* :c:func:`iio_buffer_get` — Grab a reference to the buffer
* :c:func:`iio_buffer_put` — Release the reference to the buffer
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
:file:`/dev/iio:device{X}` character device node, thus reducing the CPU load.
IIO buffer sysfs interface
==========================
An IIO buffer has an associated attributes directory under
:file:`/sys/bus/iio/iio:device{X}/buffer/*`. Here are some of the existing
attributes:
* :file:`length`, the total number of data samples (capacity) that can be
stored by the buffer.
* :file:`enable`, activate buffer capture.
IIO buffer setup
================
The meta information associated with a channel reading placed in a buffer is
called a scan element . The important bits configuring scan elements are
exposed to userspace applications via the
:file:`/sys/bus/iio/iio:device{X}/scan_elements/*` directory. This file contains
attributes of the following form:
* :file:`enable`, 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.
* :file:`type`, description of the scan element data storage within the buffer
and hence the form in which it is read from user space.
Format is [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] .
* *be* or *le*, specifies big or little endian.
* *s* or *u*, specifies if signed (2's complement) or unsigned.
* *bits*, is the number of valid data bits.
* *storagebits*, is the number of bits (after padding) that it occupies in the
buffer.
* *shift*, if specified, is the shift that needs to be applied prior to
masking out unused bits.
* *repeat*, specifies the number of bits/storagebits repetitions. When the
repeat element is 0 or 1, then the repeat value is omitted.
For example, a driver for a 3-axis accelerometer with 12 bit resolution where
data is stored in two 8-bits registers as follows::
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)
+---+---+---+---+---+---+---+---+
will have the following scan element type for each axis::
$ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
le:s12/16>>4
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.
For implementing buffer support a driver should initialize the following
fields in iio_chan_spec definition::
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;
};
The driver implementing the accelerometer described above will have the
following channel definition::
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,
.storagebits = 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
*/
}
Here **scan_index** 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**.
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.
More details
============
.. kernel-doc:: include/linux/iio/buffer.h
.. kernel-doc:: drivers/iio/industrialio-buffer.c
:export:
=============
Core elements
=============
The Industrial I/O core offers a unified framework for writing drivers for
many different types of embedded sensors. a standard interface to user space
applications manipulating sensors. The implementation can be found under
:file:`drivers/iio/industrialio-*`
Industrial I/O Devices
----------------------
* struct :c:type:`iio_dev` - industrial I/O device
* :c:func:`iio_device_alloc()` - alocate an :c:type:`iio_dev` from a driver
* :c:func:`iio_device_free()` - free an :c:type:`iio_dev` from a driver
* :c:func:`iio_device_register()` - register a device with the IIO subsystem
* :c:func:`iio_device_unregister()` - unregister a device from the IIO
subsystem
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.
There are two ways for a user space application to interact with an IIO driver.
1. :file:`/sys/bus/iio/iio:device{X}/`, this represents a hardware sensor
and groups together the data channels of the same chip.
2. :file:`/dev/iio:device{X}`, character device node interface used for
buffered data transfer and for events information retrieval.
A typical IIO driver will register itself as an :doc:`I2C <../i2c>` or
:doc:`SPI <../spi>` driver and will create two routines, probe and remove.
At probe:
1. Call :c:func:`iio_device_alloc()`, which allocates memory for an IIO device.
2. Initialize IIO device fields with driver specific information (e.g.
device name, device channels).
3. Call :c:func:`iio_device_register()`, this registers the device with the
IIO core. After this call the device is ready to accept requests from user
space applications.
At remove, we free the resources allocated in probe in reverse order:
1. :c:func:`iio_device_unregister()`, unregister the device from the IIO core.
2. :c:func:`iio_device_free()`, free the memory allocated for the IIO device.
IIO device sysfs interface
==========================
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 /sys/bus/iio/iio:deviceX/ directory.
Common attributes are:
* :file:`name`, description of the physical chip.
* :file:`dev`, shows the major:minor pair associated with
:file:`/dev/iio:deviceX` node.
* :file:`sampling_frequency_available`, available discrete set of sampling
frequency values for device.
* Available standard attributes for IIO devices are described in the
:file:`Documentation/ABI/testing/sysfs-bus-iio` file in the Linux kernel
sources.
IIO device channels
===================
struct :c:type:`iio_chan_spec` - specification of a single channel
An IIO device channel is a representation of a data channel. An IIO device can
have one or multiple channels. For example:
* a thermometer sensor has one channel representing the temperature measurement.
* a light sensor with two channels indicating the measurements in the visible
and infrared spectrum.
* an accelerometer can have up to 3 channels representing acceleration on X, Y
and Z axes.
An IIO channel is described by the struct :c:type:`iio_chan_spec`.
A thermometer driver for the temperature sensor in the example above would
have to describe its channel as follows::
static const struct iio_chan_spec temp_channel[] = {
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
},
};
Channel sysfs attributes exposed to userspace are specified in the form of
bitmasks. Depending on their shared info, attributes can be set in one of the
following masks:
* **info_mask_separate**, attributes will be specific to
this channel
* **info_mask_shared_by_type**, attributes are shared by all channels of the
same type
* **info_mask_shared_by_dir**, attributes are shared by all channels of the same
direction
* **info_mask_shared_by_all**, attributes are shared by all channels
When there are multiple data channels per channel type we have two ways to
distinguish between them:
* set **.modified** field of :c:type:`iio_chan_spec` to 1. Modifiers are
specified using **.channel2** field of the same :c:type:`iio_chan_spec`
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.
* set **.indexed** field of :c:type:`iio_chan_spec` to 1. In this case the
channel is simply another instance with an index specified by the **.channel**
field.
Here is how we can make use of the channel's modifiers::
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),
},
}
This channel's definition will generate two separate sysfs files for raw data
retrieval:
* :file:`/sys/bus/iio/iio:device{X}/in_intensity_ir_raw`
* :file:`/sys/bus/iio/iio:device{X}/in_intensity_both_raw`
one file for processed data:
* :file:`/sys/bus/iio/iio:device{X}/in_illuminance_input`
and one shared sysfs file for sampling frequency:
* :file:`/sys/bus/iio/iio:device{X}/sampling_frequency`.
Here is how we can make use of the channel's indexing::
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),
},
}
This will generate two separate attributes files for raw data retrieval:
* :file:`/sys/bus/iio/devices/iio:device{X}/in_voltage0_raw`, representing
voltage measurement for channel 0.
* :file:`/sys/bus/iio/devices/iio:device{X}/in_voltage1_raw`, representing
voltage measurement for channel 1.
More details
============
.. kernel-doc:: include/linux/iio/iio.h
.. kernel-doc:: drivers/iio/industrialio-core.c
:export:
.. include:: <isonum.txt>
Industrial I/O
==============
**Copyright** |copy| 2015 Intel Corporation
Contents:
.. toctree::
:maxdepth: 2
intro
core
buffers
triggers
triggered-buffers
.. include:: <isonum.txt>
============
Introduction
============
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
:doc:`input <../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. :doc:`Input <../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.
Devices that fall into this category include:
* analog to digital converters (ADCs)
* accelerometers
* capacitance to digital converters (CDCs)
* digital to analog converters (DACs)
* gyroscopes
* inertial measurement units (IMUs)
* color and light sensors
* magnetometers
* pressure sensors
* proximity sensors
* temperature sensors
Usually these sensors are connected via :doc:`SPI <../spi>` or
:doc:`I2C <../i2c>`. A common use case of the sensors devices is to have
combined functionality (e.g. light plus proximity sensor).
=================
Triggered Buffers
=================
Now that we know what buffers and triggers are let's see how they work together.
IIO triggered buffer setup
==========================
* :c:func:`iio_triggered_buffer_setup` — Setup triggered buffer and pollfunc
* :c:func:`iio_triggered_buffer_cleanup` — Free resources allocated by
:c:func:`iio_triggered_buffer_setup`
* struct :c:type:`iio_buffer_setup_ops` — buffer setup related callbacks
A typical triggered buffer setup looks like this::
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((struct indio_dev *)p);
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);
The important things to notice here are:
* :c:type:`iio_buffer_setup_ops`, 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
iio_triggered_buffer_setup_ops.
* **sensor_iio_pollfunc**, 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
:c:func:`iio_pollfunc_store_time` function.
* **sensor_trigger_handler**, 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.
More details
============
.. kernel-doc:: drivers/iio/buffer/industrialio-triggered-buffer.c
========
Triggers
========
* struct :c:type:`iio_trigger` — industrial I/O trigger device
* :c:func:`devm_iio_trigger_alloc` — Resource-managed iio_trigger_alloc
* :c:func:`devm_iio_trigger_free` — Resource-managed iio_trigger_free
* :c:func:`devm_iio_trigger_register` — Resource-managed iio_trigger_register
* :c:func:`devm_iio_trigger_unregister` — Resource-managed
iio_trigger_unregister
* :c:func:`iio_trigger_validate_own_device` — Check if a trigger and IIO
device belong to the same device
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.
IIO trigger sysfs interface
===========================
There are two locations in sysfs related to triggers:
* :file:`/sys/bus/iio/devices/trigger{Y}/*`, 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:
* :file:`name`, trigger name that can be later used for association with a
device.
* :file:`sampling_frequency`, some timer based triggers use this attribute to
specify the frequency for trigger calls.
* :file:`/sys/bus/iio/devices/iio:device{X}/trigger/*`, 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
:file:`current_trigger` file.
IIO trigger setup
=================
Let's see a simple example of how to setup a trigger to be used by a driver::
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);
IIO trigger ops
===============
* struct :c:type:`iio_trigger_ops` — operations structure for an iio_trigger.
Notice that a trigger has a set of operations attached:
* :file:`set_trigger_state`, switch the trigger on/off on demand.
* :file:`validate_device`, function to validate the device when the current
trigger gets changed.
More details
============
.. kernel-doc:: include/linux/iio/trigger.h
.. kernel-doc:: drivers/iio/industrialio-trigger.c
:export:
...@@ -16,11 +16,15 @@ available subsections can be seen below. ...@@ -16,11 +16,15 @@ available subsections can be seen below.
basics basics
infrastructure infrastructure
pm/index
device-io
dma-buf dma-buf
device_link device_link
message-based message-based
sound sound
frame-buffer frame-buffer
regulator
iio/index
input input
usb usb
spi spi
......
# -*- coding: utf-8; mode: python -*-
project = "Device Power Management"
tags.add("subproject")
latex_documents = [
('index', 'pm.tex', project,
'The kernel development community', 'manual'),
]
Device Power Management .. |struct dev_pm_ops| replace:: :c:type:`struct dev_pm_ops <dev_pm_ops>`
.. |struct dev_pm_domain| replace:: :c:type:`struct dev_pm_domain <dev_pm_domain>`
.. |struct bus_type| replace:: :c:type:`struct bus_type <bus_type>`
.. |struct device_type| replace:: :c:type:`struct device_type <device_type>`
.. |struct class| replace:: :c:type:`struct class <class>`
.. |struct wakeup_source| replace:: :c:type:`struct wakeup_source <wakeup_source>`
.. |struct device| replace:: :c:type:`struct device <device>`
Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. ==============================
Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu> Device Power Management Basics
Copyright (c) 2014 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com> ==============================
::
Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu>
Copyright (c) 2016 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Most of the code in Linux is device drivers, so most of the Linux power Most of the code in Linux is device drivers, so most of the Linux power
management (PM) code is also driver-specific. Most drivers will do very management (PM) code is also driver-specific. Most drivers will do very
...@@ -18,10 +29,12 @@ background for the domain-specific work you'd do with any specific driver. ...@@ -18,10 +29,12 @@ background for the domain-specific work you'd do with any specific driver.
Two Models for Device Power Management Two Models for Device Power Management
====================================== ======================================
Drivers will use one or both of these models to put devices into low-power Drivers will use one or both of these models to put devices into low-power
states: states:
System Sleep model: System Sleep model:
Drivers can enter low-power states as part of entering system-wide Drivers can enter low-power states as part of entering system-wide
low-power states like "suspend" (also known as "suspend-to-RAM"), or low-power states like "suspend" (also known as "suspend-to-RAM"), or
(mostly for systems with disks) "hibernation" (also known as (mostly for systems with disks) "hibernation" (also known as
...@@ -34,12 +47,13 @@ states: ...@@ -34,12 +47,13 @@ states:
Some drivers can manage hardware wakeup events, which make the system Some drivers can manage hardware wakeup events, which make the system
leave the low-power state. This feature may be enabled or disabled leave the low-power state. This feature may be enabled or disabled
using the relevant /sys/devices/.../power/wakeup file (for Ethernet using the relevant :file:`/sys/devices/.../power/wakeup` file (for
drivers the ioctl interface used by ethtool may also be used for this Ethernet drivers the ioctl interface used by ethtool may also be used
purpose); enabling it may cost some power usage, but let the whole for this purpose); enabling it may cost some power usage, but let the
system enter low-power states more often. whole system enter low-power states more often.
Runtime Power Management model: Runtime Power Management model:
Devices may also be put into low-power states while the system is Devices may also be put into low-power states while the system is
running, independently of other power management activity in principle. running, independently of other power management activity in principle.
However, devices are not generally independent of each other (for However, devices are not generally independent of each other (for
...@@ -73,9 +87,9 @@ Examples of hardware wakeup events include an alarm from a real time clock, ...@@ -73,9 +87,9 @@ Examples of hardware wakeup events include an alarm from a real time clock,
network wake-on-LAN packets, keyboard or mouse activity, and media insertion network wake-on-LAN packets, keyboard or mouse activity, and media insertion
or removal (for PCMCIA, MMC/SD, USB, and so on). or removal (for PCMCIA, MMC/SD, USB, and so on).
Interfaces for Entering System Sleep States Interfaces for Entering System Sleep States
=========================================== ===========================================
There are programming interfaces provided for subsystems (bus type, device type, There are programming interfaces provided for subsystems (bus type, device type,
device class) and device drivers to allow them to participate in the power device class) and device drivers to allow them to participate in the power
management of devices they are concerned with. These interfaces cover both management of devices they are concerned with. These interfaces cover both
...@@ -84,58 +98,34 @@ system sleep and runtime power management. ...@@ -84,58 +98,34 @@ system sleep and runtime power management.
Device Power Management Operations Device Power Management Operations
---------------------------------- ----------------------------------
Device power management operations, at the subsystem level as well as at the Device power management operations, at the subsystem level as well as at the
device driver level, are implemented by defining and populating objects of type device driver level, are implemented by defining and populating objects of type
struct dev_pm_ops: |struct dev_pm_ops| defined in :file:`include/linux/pm.h`. The roles of the
methods included in it will be explained in what follows. For now, it should be
struct dev_pm_ops { sufficient to remember that the last three methods are specific to runtime power
int (*prepare)(struct device *dev); management while the remaining ones are used during system-wide power
void (*complete)(struct device *dev); transitions.
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
};
This structure is defined in include/linux/pm.h and the methods included in it
are also described in that file. Their roles will be explained in what follows.
For now, it should be sufficient to remember that the last three methods are
specific to runtime power management while the remaining ones are used during
system-wide power transitions.
There also is a deprecated "old" or "legacy" interface for power management There also is a deprecated "old" or "legacy" interface for power management
operations available at least for some subsystems. This approach does not use operations available at least for some subsystems. This approach does not use
struct dev_pm_ops objects and it is suitable only for implementing system sleep |struct dev_pm_ops| objects and it is suitable only for implementing system
power management methods. Therefore it is not described in this document, so sleep power management methods in a limited way. Therefore it is not described
please refer directly to the source code for more information about it. in this document, so please refer directly to the source code for more
information about it.
Subsystem-Level Methods Subsystem-Level Methods
----------------------- -----------------------
The core methods to suspend and resume devices reside in struct dev_pm_ops
pointed to by the ops member of struct dev_pm_domain, or by the pm member of The core methods to suspend and resume devices reside in
struct bus_type, struct device_type and struct class. They are mostly of |struct dev_pm_ops| pointed to by the :c:member:`ops` member of
interest to the people writing infrastructure for platforms and buses, like PCI |struct dev_pm_domain|, or by the :c:member:`pm` member of |struct bus_type|,
or USB, or device type and device class drivers. They also are relevant to the |struct device_type| and |struct class|. They are mostly of interest to the
writers of device drivers whose subsystems (PM domains, device types, device people writing infrastructure for platforms and buses, like PCI or USB, or
classes and bus types) don't provide all power management methods. device type and device class drivers. They also are relevant to the writers of
device drivers whose subsystems (PM domains, device types, device classes and
bus types) don't provide all power management methods.
Bus drivers implement these methods as appropriate for the hardware and the Bus drivers implement these methods as appropriate for the hardware and the
drivers using it; PCI works differently from USB, and so on. Not many people drivers using it; PCI works differently from USB, and so on. Not many people
...@@ -147,49 +137,51 @@ they are called in phases for every device, respecting the parent-child ...@@ -147,49 +137,51 @@ they are called in phases for every device, respecting the parent-child
sequencing in the driver model tree. sequencing in the driver model tree.
/sys/devices/.../power/wakeup files :file:`/sys/devices/.../power/wakeup` files
----------------------------------- -------------------------------------------
All device objects in the driver model contain fields that control the handling All device objects in the driver model contain fields that control the handling
of system wakeup events (hardware signals that can force the system out of a of system wakeup events (hardware signals that can force the system out of a
sleep state). These fields are initialized by bus or device driver code using sleep state). These fields are initialized by bus or device driver code using
device_set_wakeup_capable() and device_set_wakeup_enable(), defined in :c:func:`device_set_wakeup_capable()` and :c:func:`device_set_wakeup_enable()`,
include/linux/pm_wakeup.h. defined in :file:`include/linux/pm_wakeup.h`.
The "power.can_wakeup" flag just records whether the device (and its driver) can The :c:member:`power.can_wakeup` flag just records whether the device (and its
physically support wakeup events. The device_set_wakeup_capable() routine driver) can physically support wakeup events. The
affects this flag. The "power.wakeup" field is a pointer to an object of type :c:func:`device_set_wakeup_capable()` routine affects this flag. The
struct wakeup_source used for controlling whether or not the device should use :c:member:`power.wakeup` field is a pointer to an object of type
|struct wakeup_source| used for controlling whether or not the device should use
its system wakeup mechanism and for notifying the PM core of system wakeup its system wakeup mechanism and for notifying the PM core of system wakeup
events signaled by the device. This object is only present for wakeup-capable events signaled by the device. This object is only present for wakeup-capable
devices (i.e. devices whose "can_wakeup" flags are set) and is created (or devices (i.e. devices whose :c:member:`can_wakeup` flags are set) and is created
removed) by device_set_wakeup_capable(). (or removed) by :c:func:`device_set_wakeup_capable()`.
Whether or not a device is capable of issuing wakeup events is a hardware Whether or not a device is capable of issuing wakeup events is a hardware
matter, and the kernel is responsible for keeping track of it. By contrast, matter, and the kernel is responsible for keeping track of it. By contrast,
whether or not a wakeup-capable device should issue wakeup events is a policy whether or not a wakeup-capable device should issue wakeup events is a policy
decision, and it is managed by user space through a sysfs attribute: the decision, and it is managed by user space through a sysfs attribute: the
"power/wakeup" file. User space can write the strings "enabled" or "disabled" :file:`power/wakeup` file. User space can write the "enabled" or "disabled"
to it to indicate whether or not, respectively, the device is supposed to signal strings to it to indicate whether or not, respectively, the device is supposed
system wakeup. This file is only present if the "power.wakeup" object exists to signal system wakeup. This file is only present if the
for the given device and is created (or removed) along with that object, by :c:member:`power.wakeup` object exists for the given device and is created (or
device_set_wakeup_capable(). Reads from the file will return the corresponding removed) along with that object, by :c:func:`device_set_wakeup_capable()`.
string. Reads from the file will return the corresponding string.
The "power/wakeup" file is supposed to contain the "disabled" string initially The initial value in the :file:`power/wakeup` file is "disabled" for the
for the majority of devices; the major exceptions are power buttons, keyboards, majority of devices; the major exceptions are power buttons, keyboards, and
and Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with ethtool.
ethtool. It should also default to "enabled" for devices that don't generate It should also default to "enabled" for devices that don't generate wakeup
wakeup requests on their own but merely forward wakeup requests from one bus to requests on their own but merely forward wakeup requests from one bus to another
another (like PCI Express ports). (like PCI Express ports).
The device_may_wakeup() routine returns true only if the "power.wakeup" object The :c:func:`device_may_wakeup()` routine returns true only if the
exists and the corresponding "power/wakeup" file contains the string "enabled". :c:member:`power.wakeup` object exists and the corresponding :file:`power/wakeup`
This information is used by subsystems, like the PCI bus type code, to see file contains the "enabled" string. This information is used by subsystems,
whether or not to enable the devices' wakeup mechanisms. If device wakeup like the PCI bus type code, to see whether or not to enable the devices' wakeup
mechanisms are enabled or disabled directly by drivers, they also should use mechanisms. If device wakeup mechanisms are enabled or disabled directly by
device_may_wakeup() to decide what to do during a system sleep transition. drivers, they also should use :c:func:`device_may_wakeup()` to decide what to do
Device drivers, however, are not supposed to call device_set_wakeup_enable() during a system sleep transition. Device drivers, however, are not expected to
directly in any case. call :c:func:`device_set_wakeup_enable()` directly in any case.
It ought to be noted that system wakeup is conceptually different from "remote It ought to be noted that system wakeup is conceptually different from "remote
wakeup" used by runtime power management, although it may be supported by the wakeup" used by runtime power management, although it may be supported by the
...@@ -201,32 +193,38 @@ some systems it is impossible to trigger them from system sleep states. In any ...@@ -201,32 +193,38 @@ some systems it is impossible to trigger them from system sleep states. In any
case, remote wakeup should always be enabled for runtime power management for case, remote wakeup should always be enabled for runtime power management for
all devices and drivers that support it. all devices and drivers that support it.
/sys/devices/.../power/control files
------------------------------------ :file:`/sys/devices/.../power/control` files
--------------------------------------------
Each device in the driver model has a flag to control whether it is subject to Each device in the driver model has a flag to control whether it is subject to
runtime power management. This flag, called runtime_auto, is initialized by the runtime power management. This flag, :c:member:`runtime_auto`, is initialized
bus type (or generally subsystem) code using pm_runtime_allow() or by the bus type (or generally subsystem) code using :c:func:`pm_runtime_allow()`
pm_runtime_forbid(); the default is to allow runtime power management. or :c:func:`pm_runtime_forbid()`; the default is to allow runtime power
management.
The setting can be adjusted by user space by writing either "on" or "auto" to The setting can be adjusted by user space by writing either "on" or "auto" to
the device's power/control sysfs file. Writing "auto" calls pm_runtime_allow(), the device's :file:`power/control` sysfs file. Writing "auto" calls
setting the flag and allowing the device to be runtime power-managed by its :c:func:`pm_runtime_allow()`, setting the flag and allowing the device to be
driver. Writing "on" calls pm_runtime_forbid(), clearing the flag, returning runtime power-managed by its driver. Writing "on" calls
the device to full power if it was in a low-power state, and preventing the :c:func:`pm_runtime_forbid()`, clearing the flag, returning the device to full
power if it was in a low-power state, and preventing the
device from being runtime power-managed. User space can check the current value device from being runtime power-managed. User space can check the current value
of the runtime_auto flag by reading the file. of the :c:member:`runtime_auto` flag by reading that file.
The device's runtime_auto flag has no effect on the handling of system-wide The device's :c:member:`runtime_auto` flag has no effect on the handling of
power transitions. In particular, the device can (and in the majority of cases system-wide power transitions. In particular, the device can (and in the
should and will) be put into a low-power state during a system-wide transition majority of cases should and will) be put into a low-power state during a
to a sleep state even though its runtime_auto flag is clear. system-wide transition to a sleep state even though its :c:member:`runtime_auto`
flag is clear.
For more information about the runtime power management framework, refer to For more information about the runtime power management framework, refer to
Documentation/power/runtime_pm.txt. :file:`Documentation/power/runtime_pm.txt`.
Calling Drivers to Enter and Leave System Sleep States Calling Drivers to Enter and Leave System Sleep States
====================================================== ======================================================
When the system goes into a sleep state, each device's driver is asked to When the system goes into a sleep state, each device's driver is asked to
suspend the device by putting it into a state compatible with the target suspend the device by putting it into a state compatible with the target
system state. That's usually some version of "off", but the details are system state. That's usually some version of "off", but the details are
...@@ -248,17 +246,18 @@ events. ...@@ -248,17 +246,18 @@ events.
Call Sequence Guarantees Call Sequence Guarantees
------------------------ ------------------------
To ensure that bridges and similar links needing to talk to a device are To ensure that bridges and similar links needing to talk to a device are
available when the device is suspended or resumed, the device tree is available when the device is suspended or resumed, the device hierarchy is
walked in a bottom-up order to suspend devices. A top-down order is walked in a bottom-up order to suspend devices. A top-down order is
used to resume those devices. used to resume those devices.
The ordering of the device tree is defined by the order in which devices The ordering of the device hierarchy is defined by the order in which devices
get registered: a child can never be registered, probed or resumed before get registered: a child can never be registered, probed or resumed before
its parent; and can't be removed or suspended after that parent. its parent; and can't be removed or suspended after that parent.
The policy is that the device tree should match hardware bus topology. The policy is that the device hierarchy should match hardware bus topology.
(Or at least the control bus, for devices which use multiple busses.) [Or at least the control bus, for devices which use multiple busses.]
In particular, this means that a device registration may fail if the parent of In particular, this means that a device registration may fail if the parent of
the device is suspending (i.e. has been chosen by the PM core as the next the device is suspending (i.e. has been chosen by the PM core as the next
device to suspend) or has already suspended, as well as after all of the other device to suspend) or has already suspended, as well as after all of the other
...@@ -268,61 +267,65 @@ situations. ...@@ -268,61 +267,65 @@ situations.
System Power Management Phases System Power Management Phases
------------------------------ ------------------------------
Suspending or resuming the system is done in several phases. Different phases Suspending or resuming the system is done in several phases. Different phases
are used for freeze, standby, and memory sleep states ("suspend-to-RAM") and the are used for suspend-to-idle, shallow (standby), and deep ("suspend-to-RAM")
hibernation state ("suspend-to-disk"). Each phase involves executing callbacks sleep states and the hibernation state ("suspend-to-disk"). Each phase involves
for every device before the next phase begins. Not all busses or classes executing callbacks for every device before the next phase begins. Not all
support all these callbacks and not all drivers use all the callbacks. The buses or classes support all these callbacks and not all drivers use all the
various phases always run after tasks have been frozen and before they are callbacks. The various phases always run after tasks have been frozen and
unfrozen. Furthermore, the *_noirq phases run at a time when IRQ handlers have before they are unfrozen. Furthermore, the ``*_noirq phases`` run at a time
been disabled (except for those marked with the IRQF_NO_SUSPEND flag). when IRQ handlers have been disabled (except for those marked with the
IRQF_NO_SUSPEND flag).
All phases use PM domain, bus, type, class or driver callbacks (that is, methods All phases use PM domain, bus, type, class or driver callbacks (that is, methods
defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, dev->class->pm or defined in ``dev->pm_domain->ops``, ``dev->bus->pm``, ``dev->type->pm``,
dev->driver->pm). These callbacks are regarded by the PM core as mutually ``dev->class->pm`` or ``dev->driver->pm``). These callbacks are regarded by the
exclusive. Moreover, PM domain callbacks always take precedence over all of the PM core as mutually exclusive. Moreover, PM domain callbacks always take
other callbacks and, for example, type callbacks take precedence over bus, class precedence over all of the other callbacks and, for example, type callbacks take
and driver callbacks. To be precise, the following rules are used to determine precedence over bus, class and driver callbacks. To be precise, the following
which callback to execute in the given phase: rules are used to determine which callback to execute in the given phase:
1. If dev->pm_domain is present, the PM core will choose the callback 1. If ``dev->pm_domain`` is present, the PM core will choose the callback
included in dev->pm_domain->ops for execution provided by ``dev->pm_domain->ops`` for execution.
2. Otherwise, if both dev->type and dev->type->pm are present, the callback 2. Otherwise, if both ``dev->type`` and ``dev->type->pm`` are present, the
included in dev->type->pm will be chosen for execution. callback provided by ``dev->type->pm`` will be chosen for execution.
3. Otherwise, if both dev->class and dev->class->pm are present, the 3. Otherwise, if both ``dev->class`` and ``dev->class->pm`` are present,
callback included in dev->class->pm will be chosen for execution. the callback provided by ``dev->class->pm`` will be chosen for
execution.
4. Otherwise, if both dev->bus and dev->bus->pm are present, the callback 4. Otherwise, if both ``dev->bus`` and ``dev->bus->pm`` are present, the
included in dev->bus->pm will be chosen for execution. callback provided by ``dev->bus->pm`` will be chosen for execution.
This allows PM domains and device types to override callbacks provided by bus This allows PM domains and device types to override callbacks provided by bus
types or device classes if necessary. types or device classes if necessary.
The PM domain, type, class and bus callbacks may in turn invoke device- or The PM domain, type, class and bus callbacks may in turn invoke device- or
driver-specific methods stored in dev->driver->pm, but they don't have to do driver-specific methods stored in ``dev->driver->pm``, but they don't have to do
that. that.
If the subsystem callback chosen for execution is not present, the PM core will If the subsystem callback chosen for execution is not present, the PM core will
execute the corresponding method from dev->driver->pm instead if there is one. execute the corresponding method from the ``dev->driver->pm`` set instead if
there is one.
Entering System Suspend Entering System Suspend
----------------------- -----------------------
When the system goes into the freeze, standby or memory sleep state,
the phases are:
prepare, suspend, suspend_late, suspend_noirq. When the system goes into the freeze, standby or memory sleep state,
the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
1. The prepare phase is meant to prevent races by preventing new devices 1. The ``prepare`` phase is meant to prevent races by preventing new
from being registered; the PM core would never know that all the devices from being registered; the PM core would never know that all the
children of a device had been suspended if new children could be children of a device had been suspended if new children could be
registered at will. (By contrast, devices may be unregistered at any registered at will. [By contrast, from the PM core's perspective,
time.) Unlike the other suspend-related phases, during the prepare devices may be unregistered at any time.] Unlike the other
phase the device tree is traversed top-down. suspend-related phases, during the ``prepare`` phase the device
hierarchy is traversed top-down.
After the prepare callback method returns, no new children may be After the ``->prepare`` callback method returns, no new children may be
registered below the device. The method may also prepare the device or registered below the device. The method may also prepare the device or
driver in some way for the upcoming system power transition, but it driver in some way for the upcoming system power transition, but it
should not put the device into a low-power state. should not put the device into a low-power state.
...@@ -334,35 +337,35 @@ the phases are: ...@@ -334,35 +337,35 @@ the phases are:
runtime suspend. Namely, if the prepare callback returns a positive runtime suspend. Namely, if the prepare callback returns a positive
number and that happens for all of the descendants of the device too, number and that happens for all of the descendants of the device too,
and all of them (including the device itself) are runtime-suspended, the and all of them (including the device itself) are runtime-suspended, the
PM core will skip the suspend, suspend_late and suspend_noirq suspend PM core will skip the ``suspend``, ``suspend_late`` and
phases as well as the resume_noirq, resume_early and resume phases of ``suspend_noirq`` phases as well as all of the corresponding phases of
the following system resume for all of these devices. In that case, the subsequent device resume for all of these devices. In that case,
the complete callback will be called directly after the prepare callback the ``->complete`` callback will be invoked directly after the
and is entirely responsible for bringing the device back to the ``->prepare`` callback and is entirely responsible for putting the
functional state as appropriate. device into a consistent state as appropriate.
Note that this direct-complete procedure applies even if the device is Note that this direct-complete procedure applies even if the device is
disabled for runtime PM; only the runtime-PM status matters. It follows disabled for runtime PM; only the runtime-PM status matters. It follows
that if a device has system-sleep callbacks but does not support runtime that if a device has system-sleep callbacks but does not support runtime
PM, then its prepare callback must never return a positive value. This PM, then its prepare callback must never return a positive value. This
is because all devices are initially set to runtime-suspended with is because all such devices are initially set to runtime-suspended with
runtime PM disabled. runtime PM disabled.
2. The suspend methods should quiesce the device to stop it from performing 2. The ``->suspend`` methods should quiesce the device to stop it from
I/O. They also may save the device registers and put it into the performing I/O. They also may save the device registers and put it into
appropriate low-power state, depending on the bus type the device is on, the appropriate low-power state, depending on the bus type the device is
and they may enable wakeup events. on, and they may enable wakeup events.
3 For a number of devices it is convenient to split suspend into the 3. For a number of devices it is convenient to split suspend into the
"quiesce device" and "save device state" phases, in which cases "quiesce device" and "save device state" phases, in which cases
suspend_late is meant to do the latter. It is always executed after ``suspend_late`` is meant to do the latter. It is always executed after
runtime power management has been disabled for all devices. runtime power management has been disabled for the device in question.
4. The suspend_noirq phase occurs after IRQ handlers have been disabled, 4. The ``suspend_noirq`` phase occurs after IRQ handlers have been disabled,
which means that the driver's interrupt handler will not be called while which means that the driver's interrupt handler will not be called while
the callback method is running. The methods should save the values of the callback method is running. The ``->suspend_noirq`` methods should
the device's registers that weren't saved previously and finally put the save the values of the device's registers that weren't saved previously
device into the appropriate low-power state. and finally put the device into the appropriate low-power state.
The majority of subsystems and device drivers need not implement this The majority of subsystems and device drivers need not implement this
callback. However, bus types allowing devices to share interrupt callback. However, bus types allowing devices to share interrupt
...@@ -375,65 +378,69 @@ At the end of these phases, drivers should have stopped all I/O transactions ...@@ -375,65 +378,69 @@ At the end of these phases, drivers should have stopped all I/O transactions
(DMA, IRQs), saved enough state that they can re-initialize or restore previous (DMA, IRQs), saved enough state that they can re-initialize or restore previous
state (as needed by the hardware), and placed the device into a low-power state. state (as needed by the hardware), and placed the device into a low-power state.
On many platforms they will gate off one or more clock sources; sometimes they On many platforms they will gate off one or more clock sources; sometimes they
will also switch off power supplies or reduce voltages. (Drivers supporting will also switch off power supplies or reduce voltages. [Drivers supporting
runtime PM may already have performed some or all of these steps.) runtime PM may already have performed some or all of these steps.]
If device_may_wakeup(dev) returns true, the device should be prepared for If :c:func:`device_may_wakeup(dev)` returns ``true``, the device should be
generating hardware wakeup signals to trigger a system wakeup event when the prepared for generating hardware wakeup signals to trigger a system wakeup event
system is in the sleep state. For example, enable_irq_wake() might identify when the system is in the sleep state. For example, :c:func:`enable_irq_wake()`
GPIO signals hooked up to a switch or other external hardware, and might identify GPIO signals hooked up to a switch or other external hardware,
pci_enable_wake() does something similar for the PCI PME signal. and :c:func:`pci_enable_wake()` does something similar for the PCI PME signal.
If any of these callbacks returns an error, the system won't enter the desired If any of these callbacks returns an error, the system won't enter the desired
low-power state. Instead the PM core will unwind its actions by resuming all low-power state. Instead, the PM core will unwind its actions by resuming all
the devices that were suspended. the devices that were suspended.
Leaving System Suspend Leaving System Suspend
---------------------- ----------------------
When resuming from freeze, standby or memory sleep, the phases are:
resume_noirq, resume_early, resume, complete. When resuming from freeze, standby or memory sleep, the phases are:
``resume_noirq``, ``resume_early``, ``resume``, ``complete``.
1. The resume_noirq callback methods should perform any actions needed
before the driver's interrupt handlers are invoked. This generally 1. The ``->resume_noirq`` callback methods should perform any actions
means undoing the actions of the suspend_noirq phase. If the bus type needed before the driver's interrupt handlers are invoked. This
permits devices to share interrupt vectors, like PCI, the method should generally means undoing the actions of the ``suspend_noirq`` phase. If
bring the device and its driver into a state in which the driver can the bus type permits devices to share interrupt vectors, like PCI, the
recognize if the device is the source of incoming interrupts, if any, method should bring the device and its driver into a state in which the
and handle them correctly. driver can recognize if the device is the source of incoming interrupts,
if any, and handle them correctly.
For example, the PCI bus type's ->pm.resume_noirq() puts the device into
the full-power state (D0 in the PCI terminology) and restores the For example, the PCI bus type's ``->pm.resume_noirq()`` puts the device
into the full-power state (D0 in the PCI terminology) and restores the
standard configuration registers of the device. Then it calls the standard configuration registers of the device. Then it calls the
device driver's ->pm.resume_noirq() method to perform device-specific device driver's ``->pm.resume_noirq()`` method to perform device-specific
actions. actions.
2. The resume_early methods should prepare devices for the execution of 2. The ``->resume_early`` methods should prepare devices for the execution
the resume methods. This generally involves undoing the actions of the of the resume methods. This generally involves undoing the actions of
preceding suspend_late phase. the preceding ``suspend_late`` phase.
3 The resume methods should bring the device back to its operating 3. The ``->resume`` methods should bring the device back to its operating
state, so that it can perform normal I/O. This generally involves state, so that it can perform normal I/O. This generally involves
undoing the actions of the suspend phase. undoing the actions of the ``suspend`` phase.
4. The complete phase should undo the actions of the prepare phase. Note, 4. The ``complete`` phase should undo the actions of the ``prepare`` phase.
however, that new children may be registered below the device as soon as For this reason, unlike the other resume-related phases, during the
the resume callbacks occur; it's not necessary to wait until the ``complete`` phase the device hierarchy is traversed bottom-up.
complete phase.
Note, however, that new children may be registered below the device as
Moreover, if the preceding prepare callback returned a positive number, soon as the ``->resume`` callbacks occur; it's not necessary to wait
the device may have been left in runtime suspend throughout the whole until the ``complete`` phase with that.
system suspend and resume (the suspend, suspend_late, suspend_noirq
phases of system suspend and the resume_noirq, resume_early, resume Moreover, if the preceding ``->prepare`` callback returned a positive
phases of system resume may have been skipped for it). In that case, number, the device may have been left in runtime suspend throughout the
the complete callback is entirely responsible for bringing the device whole system suspend and resume (the ``suspend``, ``suspend_late``,
back to the functional state after system suspend if necessary. [For ``suspend_noirq`` phases of system suspend and the ``resume_noirq``,
example, it may need to queue up a runtime resume request for the device ``resume_early``, ``resume`` phases of system resume may have been
for this purpose.] To check if that is the case, the complete callback skipped for it). In that case, the ``->complete`` callback is entirely
can consult the device's power.direct_complete flag. Namely, if that responsible for putting the device into a consistent state after system
flag is set when the complete callback is being run, it has been called suspend if necessary. [For example, it may need to queue up a runtime
directly after the preceding prepare and special action may be required resume request for the device for this purpose.] To check if that is
the case, the ``->complete`` callback can consult the device's
``power.direct_complete`` flag. Namely, if that flag is set when the
``->complete`` callback is being run, it has been called directly after
the preceding ``->prepare`` and special actions may be required
to make the device work correctly afterward. to make the device work correctly afterward.
At the end of these phases, drivers should be as functional as they were before At the end of these phases, drivers should be as functional as they were before
...@@ -446,12 +453,14 @@ the end of resume might not be the one which preceded suspension. ...@@ -446,12 +453,14 @@ the end of resume might not be the one which preceded suspension.
That means availability of certain clocks or power supplies changed, That means availability of certain clocks or power supplies changed,
which could easily affect how a driver works. which could easily affect how a driver works.
Drivers need to be able to handle hardware which has been reset since the Drivers need to be able to handle hardware which has been reset since all of the
suspend methods were called, for example by complete reinitialization. suspend methods were called, for example by complete reinitialization.
This may be the hardest part, and the one most protected by NDA'd documents This may be the hardest part, and the one most protected by NDA'd documents
and chip errata. It's simplest if the hardware state hasn't changed since and chip errata. It's simplest if the hardware state hasn't changed since
the suspend was carried out, but that can't be guaranteed (in fact, it usually the suspend was carried out, but that can only be guaranteed if the target
is not the case). system sleep entered was suspend-to-idle. For the other system sleep states
that may not be the case (and usually isn't for ACPI-defined system sleep
states, like S3).
Drivers must also be prepared to notice that the device has been removed Drivers must also be prepared to notice that the device has been removed
while the system was powered down, whenever that's physically possible. while the system was powered down, whenever that's physically possible.
...@@ -467,197 +476,174 @@ the system log. ...@@ -467,197 +476,174 @@ the system log.
Entering Hibernation Entering Hibernation
-------------------- --------------------
Hibernating the system is more complicated than putting it into the other
sleep states, because it involves creating and saving a system image.
Therefore there are more phases for hibernation, with a different set of
callbacks. These phases always run after tasks have been frozen and memory has
been freed.
The general procedure for hibernation is to quiesce all devices (freeze), create Hibernating the system is more complicated than putting it into sleep states,
an image of the system memory while everything is stable, reactivate all because it involves creating and saving a system image. Therefore there are
devices (thaw), write the image to permanent storage, and finally shut down the more phases for hibernation, with a different set of callbacks. These phases
system (poweroff). The phases used to accomplish this are: always run after tasks have been frozen and enough memory has been freed.
prepare, freeze, freeze_late, freeze_noirq, thaw_noirq, thaw_early, The general procedure for hibernation is to quiesce all devices ("freeze"),
thaw, complete, prepare, poweroff, poweroff_late, poweroff_noirq create an image of the system memory while everything is stable, reactivate all
devices ("thaw"), write the image to permanent storage, and finally shut down
the system ("power off"). The phases used to accomplish this are: ``prepare``,
``freeze``, ``freeze_late``, ``freeze_noirq``, ``thaw_noirq``, ``thaw_early``,
``thaw``, ``complete``, ``prepare``, ``poweroff``, ``poweroff_late``,
``poweroff_noirq``.
1. The prepare phase is discussed in the "Entering System Suspend" section 1. The ``prepare`` phase is discussed in the "Entering System Suspend"
above. section above.
2. The freeze methods should quiesce the device so that it doesn't generate 2. The ``->freeze`` methods should quiesce the device so that it doesn't
IRQs or DMA, and they may need to save the values of device registers. generate IRQs or DMA, and they may need to save the values of device
However the device does not have to be put in a low-power state, and to registers. However the device does not have to be put in a low-power
save time it's best not to do so. Also, the device should not be state, and to save time it's best not to do so. Also, the device should
prepared to generate wakeup events. not be prepared to generate wakeup events.
3. The freeze_late phase is analogous to the suspend_late phase described 3. The ``freeze_late`` phase is analogous to the ``suspend_late`` phase
above, except that the device should not be put in a low-power state and described earlier, except that the device should not be put into a
should not be allowed to generate wakeup events by it. low-power state and should not be allowed to generate wakeup events.
4. The freeze_noirq phase is analogous to the suspend_noirq phase discussed 4. The ``freeze_noirq`` phase is analogous to the ``suspend_noirq`` phase
above, except again that the device should not be put in a low-power discussed earlier, except again that the device should not be put into
state and should not be allowed to generate wakeup events. a low-power state and should not be allowed to generate wakeup events.
At this point the system image is created. All devices should be inactive and At this point the system image is created. All devices should be inactive and
the contents of memory should remain undisturbed while this happens, so that the the contents of memory should remain undisturbed while this happens, so that the
image forms an atomic snapshot of the system state. image forms an atomic snapshot of the system state.
5. The thaw_noirq phase is analogous to the resume_noirq phase discussed 5. The ``thaw_noirq`` phase is analogous to the ``resume_noirq`` phase
above. The main difference is that its methods can assume the device is discussed earlier. The main difference is that its methods can assume
in the same state as at the end of the freeze_noirq phase. the device is in the same state as at the end of the ``freeze_noirq``
phase.
6. The thaw_early phase is analogous to the resume_early phase described 6. The ``thaw_early`` phase is analogous to the ``resume_early`` phase
above. Its methods should undo the actions of the preceding described above. Its methods should undo the actions of the preceding
freeze_late, if necessary. ``freeze_late``, if necessary.
7. The thaw phase is analogous to the resume phase discussed above. Its 7. The ``thaw`` phase is analogous to the ``resume`` phase discussed
methods should bring the device back to an operating state, so that it earlier. Its methods should bring the device back to an operating
can be used for saving the image if necessary. state, so that it can be used for saving the image if necessary.
8. The complete phase is discussed in the "Leaving System Suspend" section 8. The ``complete`` phase is discussed in the "Leaving System Suspend"
above. section above.
At this point the system image is saved, and the devices then need to be At this point the system image is saved, and the devices then need to be
prepared for the upcoming system shutdown. This is much like suspending them prepared for the upcoming system shutdown. This is much like suspending them
before putting the system into the freeze, standby or memory sleep state, before putting the system into the suspend-to-idle, shallow or deep sleep state,
and the phases are similar. and the phases are similar.
9. The prepare phase is discussed above. 9. The ``prepare`` phase is discussed above.
10. The poweroff phase is analogous to the suspend phase. 10. The ``poweroff`` phase is analogous to the ``suspend`` phase.
11. The poweroff_late phase is analogous to the suspend_late phase. 11. The ``poweroff_late`` phase is analogous to the ``suspend_late`` phase.
12. The poweroff_noirq phase is analogous to the suspend_noirq phase. 12. The ``poweroff_noirq`` phase is analogous to the ``suspend_noirq`` phase.
The poweroff, poweroff_late and poweroff_noirq callbacks should do essentially The ``->poweroff``, ``->poweroff_late`` and ``->poweroff_noirq`` callbacks
the same things as the suspend, suspend_late and suspend_noirq callbacks, should do essentially the same things as the ``->suspend``, ``->suspend_late``
respectively. The only notable difference is that they need not store the and ``->suspend_noirq`` callbacks, respectively. The only notable difference is
device register values, because the registers should already have been stored that they need not store the device register values, because the registers
during the freeze, freeze_late or freeze_noirq phases. should already have been stored during the ``freeze``, ``freeze_late`` or
``freeze_noirq`` phases.
Leaving Hibernation Leaving Hibernation
------------------- -------------------
Resuming from hibernation is, again, more complicated than resuming from a sleep Resuming from hibernation is, again, more complicated than resuming from a sleep
state in which the contents of main memory are preserved, because it requires state in which the contents of main memory are preserved, because it requires
a system image to be loaded into memory and the pre-hibernation memory contents a system image to be loaded into memory and the pre-hibernation memory contents
to be restored before control can be passed back to the image kernel. to be restored before control can be passed back to the image kernel.
Although in principle, the image might be loaded into memory and the Although in principle the image might be loaded into memory and the
pre-hibernation memory contents restored by the boot loader, in practice this pre-hibernation memory contents restored by the boot loader, in practice this
can't be done because boot loaders aren't smart enough and there is no can't be done because boot loaders aren't smart enough and there is no
established protocol for passing the necessary information. So instead, the established protocol for passing the necessary information. So instead, the
boot loader loads a fresh instance of the kernel, called the boot kernel, into boot loader loads a fresh instance of the kernel, called "the restore kernel",
memory and passes control to it in the usual way. Then the boot kernel reads into memory and passes control to it in the usual way. Then the restore kernel
the system image, restores the pre-hibernation memory contents, and passes reads the system image, restores the pre-hibernation memory contents, and passes
control to the image kernel. Thus two different kernels are involved in control to the image kernel. Thus two different kernel instances are involved
resuming from hibernation. In fact, the boot kernel may be completely different in resuming from hibernation. In fact, the restore kernel may be completely
from the image kernel: a different configuration and even a different version. different from the image kernel: a different configuration and even a different
This has important consequences for device drivers and their subsystems. version. This has important consequences for device drivers and their
subsystems.
To be able to load the system image into memory, the boot kernel needs to
To be able to load the system image into memory, the restore kernel needs to
include at least a subset of device drivers allowing it to access the storage include at least a subset of device drivers allowing it to access the storage
medium containing the image, although it doesn't need to include all of the medium containing the image, although it doesn't need to include all of the
drivers present in the image kernel. After the image has been loaded, the drivers present in the image kernel. After the image has been loaded, the
devices managed by the boot kernel need to be prepared for passing control back devices managed by the boot kernel need to be prepared for passing control back
to the image kernel. This is very similar to the initial steps involved in to the image kernel. This is very similar to the initial steps involved in
creating a system image, and it is accomplished in the same way, using prepare, creating a system image, and it is accomplished in the same way, using
freeze, and freeze_noirq phases. However the devices affected by these phases ``prepare``, ``freeze``, and ``freeze_noirq`` phases. However, the devices
are only those having drivers in the boot kernel; other devices will still be in affected by these phases are only those having drivers in the restore kernel;
whatever state the boot loader left them. other devices will still be in whatever state the boot loader left them.
Should the restoration of the pre-hibernation memory contents fail, the boot Should the restoration of the pre-hibernation memory contents fail, the restore
kernel would go through the "thawing" procedure described above, using the kernel would go through the "thawing" procedure described above, using the
thaw_noirq, thaw, and complete phases, and then continue running normally. This ``thaw_noirq``, ``thaw_early``, ``thaw``, and ``complete`` phases, and then
happens only rarely. Most often the pre-hibernation memory contents are continue running normally. This happens only rarely. Most often the
restored successfully and control is passed to the image kernel, which then pre-hibernation memory contents are restored successfully and control is passed
becomes responsible for bringing the system back to the working state. to the image kernel, which then becomes responsible for bringing the system back
to the working state.
To achieve this, the image kernel must restore the devices' pre-hibernation To achieve this, the image kernel must restore the devices' pre-hibernation
functionality. The operation is much like waking up from the memory sleep functionality. The operation is much like waking up from a sleep state (with
state, although it involves different phases: the memory contents preserved), although it involves different phases:
``restore_noirq``, ``restore_early``, ``restore``, ``complete``.
restore_noirq, restore_early, restore, complete 1. The ``restore_noirq`` phase is analogous to the ``resume_noirq`` phase.
1. The restore_noirq phase is analogous to the resume_noirq phase. 2. The ``restore_early`` phase is analogous to the ``resume_early`` phase.
2. The restore_early phase is analogous to the resume_early phase. 3. The ``restore`` phase is analogous to the ``resume`` phase.
3. The restore phase is analogous to the resume phase. 4. The ``complete`` phase is discussed above.
4. The complete phase is discussed above. The main difference from ``resume[_early|_noirq]`` is that
``restore[_early|_noirq]`` must assume the device has been accessed and
reconfigured by the boot loader or the restore kernel. Consequently, the state
of the device may be different from the state remembered from the ``freeze``,
``freeze_late`` and ``freeze_noirq`` phases. The device may even need to be
reset and completely re-initialized. In many cases this difference doesn't
matter, so the ``->resume[_early|_noirq]`` and ``->restore[_early|_norq]``
method pointers can be set to the same routines. Nevertheless, different
callback pointers are used in case there is a situation where it actually does
matter.
The main difference from resume[_early|_noirq] is that restore[_early|_noirq]
must assume the device has been accessed and reconfigured by the boot loader or
the boot kernel. Consequently the state of the device may be different from the
state remembered from the freeze, freeze_late and freeze_noirq phases. The
device may even need to be reset and completely re-initialized. In many cases
this difference doesn't matter, so the resume[_early|_noirq] and
restore[_early|_norq] method pointers can be set to the same routines.
Nevertheless, different callback pointers are used in case there is a situation
where it actually does matter.
Power Management Notifiers
==========================
Device Power Management Domains There are some operations that cannot be carried out by the power management
------------------------------- callbacks discussed above, because the callbacks occur too late or too early.
Sometimes devices share reference clocks or other power resources. In those To handle these cases, subsystems and device drivers may register power
cases it generally is not possible to put devices into low-power states management notifiers that are called before tasks are frozen and after they have
individually. Instead, a set of devices sharing a power resource can be put been thawed. Generally speaking, the PM notifiers are suitable for performing
into a low-power state together at the same time by turning off the shared actions that either require user space to be available, or at least won't
power resource. Of course, they also need to be put into the full-power state interfere with user space.
together, by turning the shared power resource on. A set of devices with this
property is often referred to as a power domain. A power domain may also be
nested inside another power domain. The nested domain is referred to as the
sub-domain of the parent domain.
Support for power domains is provided through the pm_domain field of struct For details refer to :doc:`notifiers`.
device. This field is a pointer to an object of type struct dev_pm_domain,
defined in include/linux/pm.h, providing a set of power management callbacks
analogous to the subsystem-level and device driver callbacks that are executed
for the given device during all power transitions, instead of the respective
subsystem-level callbacks. Specifically, if a device's pm_domain pointer is
not NULL, the ->suspend() callback from the object pointed to by it will be
executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and
analogously for all of the remaining callbacks. In other words, power
management domain callbacks, if defined for the given device, always take
precedence over the callbacks provided by the device's subsystem (e.g. bus
type).
The support for device power management domains is only relevant to platforms
needing to use the same device driver power management callbacks in many
different power domain configurations and wanting to avoid incorporating the
support for power domains into subsystem-level callbacks, for example by
modifying the platform bus type. Other platforms need not implement it or take
it into account in any way.
Devices may be defined as IRQ-safe which indicates to the PM core that their Device Low-Power (suspend) States
runtime PM callbacks may be invoked with disabled interrupts (see =================================
Documentation/power/runtime_pm.txt for more information). If an IRQ-safe
device belongs to a PM domain, the runtime PM of the domain will be
disallowed, unless the domain itself is defined as IRQ-safe. However, it
makes sense to define a PM domain as IRQ-safe only if all the devices in it
are IRQ-safe. Moreover, if an IRQ-safe domain has a parent domain, the runtime
PM of the parent is only allowed if the parent itself is IRQ-safe too with the
additional restriction that all child domains of an IRQ-safe parent must also
be IRQ-safe.
Device Low Power (suspend) States
---------------------------------
Device low-power states aren't standard. One device might only handle Device low-power states aren't standard. One device might only handle
"on" and "off", while another might support a dozen different versions of "on" and "off", while another might support a dozen different versions of
"on" (how many engines are active?), plus a state that gets back to "on" "on" (how many engines are active?), plus a state that gets back to "on"
faster than from a full "off". faster than from a full "off".
Some busses define rules about what different suspend states mean. PCI Some buses define rules about what different suspend states mean. PCI
gives one example: after the suspend sequence completes, a non-legacy gives one example: after the suspend sequence completes, a non-legacy
PCI device may not perform DMA or issue IRQs, and any wakeup events it PCI device may not perform DMA or issue IRQs, and any wakeup events it
issues would be issued through the PME# bus signal. Plus, there are issues would be issued through the PME# bus signal. Plus, there are
several PCI-standard device states, some of which are optional. several PCI-standard device states, some of which are optional.
In contrast, integrated system-on-chip processors often use IRQs as the In contrast, integrated system-on-chip processors often use IRQs as the
wakeup event sources (so drivers would call enable_irq_wake) and might wakeup event sources (so drivers would call :c:func:`enable_irq_wake`) and
be able to treat DMA completion as a wakeup event (sometimes DMA can stay might be able to treat DMA completion as a wakeup event (sometimes DMA can stay
active too, it'd only be the CPU and some peripherals that sleep). active too, it'd only be the CPU and some peripherals that sleep).
Some details here may be platform-specific. Systems may have devices that Some details here may be platform-specific. Systems may have devices that
...@@ -674,21 +660,54 @@ ways; the aforementioned LCD might be active in one product's "standby", ...@@ -674,21 +660,54 @@ ways; the aforementioned LCD might be active in one product's "standby",
but a different product using the same SOC might work differently. but a different product using the same SOC might work differently.
Power Management Notifiers Device Power Management Domains
-------------------------- ===============================
There are some operations that cannot be carried out by the power management
callbacks discussed above, because the callbacks occur too late or too early.
To handle these cases, subsystems and device drivers may register power
management notifiers that are called before tasks are frozen and after they have
been thawed. Generally speaking, the PM notifiers are suitable for performing
actions that either require user space to be available, or at least won't
interfere with user space.
For details refer to Documentation/power/notifiers.txt. Sometimes devices share reference clocks or other power resources. In those
cases it generally is not possible to put devices into low-power states
individually. Instead, a set of devices sharing a power resource can be put
into a low-power state together at the same time by turning off the shared
power resource. Of course, they also need to be put into the full-power state
together, by turning the shared power resource on. A set of devices with this
property is often referred to as a power domain. A power domain may also be
nested inside another power domain. The nested domain is referred to as the
sub-domain of the parent domain.
Support for power domains is provided through the :c:member:`pm_domain` field of
|struct device|. This field is a pointer to an object of type
|struct dev_pm_domain|, defined in :file:`include/linux/pm.h``, providing a set
of power management callbacks analogous to the subsystem-level and device driver
callbacks that are executed for the given device during all power transitions,
instead of the respective subsystem-level callbacks. Specifically, if a
device's :c:member:`pm_domain` pointer is not NULL, the ``->suspend()`` callback
from the object pointed to by it will be executed instead of its subsystem's
(e.g. bus type's) ``->suspend()`` callback and analogously for all of the
remaining callbacks. In other words, power management domain callbacks, if
defined for the given device, always take precedence over the callbacks provided
by the device's subsystem (e.g. bus type).
The support for device power management domains is only relevant to platforms
needing to use the same device driver power management callbacks in many
different power domain configurations and wanting to avoid incorporating the
support for power domains into subsystem-level callbacks, for example by
modifying the platform bus type. Other platforms need not implement it or take
it into account in any way.
Devices may be defined as IRQ-safe which indicates to the PM core that their
runtime PM callbacks may be invoked with disabled interrupts (see
:file:`Documentation/power/runtime_pm.txt` for more information). If an
IRQ-safe device belongs to a PM domain, the runtime PM of the domain will be
disallowed, unless the domain itself is defined as IRQ-safe. However, it
makes sense to define a PM domain as IRQ-safe only if all the devices in it
are IRQ-safe. Moreover, if an IRQ-safe domain has a parent domain, the runtime
PM of the parent is only allowed if the parent itself is IRQ-safe too with the
additional restriction that all child domains of an IRQ-safe parent must also
be IRQ-safe.
Runtime Power Management Runtime Power Management
======================== ========================
Many devices are able to dynamically power down while the system is still Many devices are able to dynamically power down while the system is still
running. This feature is useful for devices that are not being used, and running. This feature is useful for devices that are not being used, and
can offer significant power savings on a running system. These devices can offer significant power savings on a running system. These devices
...@@ -711,6 +730,7 @@ disabled. This all depends on the hardware and the design of the subsystem and ...@@ -711,6 +730,7 @@ disabled. This all depends on the hardware and the design of the subsystem and
device driver in question. device driver in question.
During system-wide resume from a sleep state it's easiest to put devices into During system-wide resume from a sleep state it's easiest to put devices into
the full-power state, as explained in Documentation/power/runtime_pm.txt. Refer the full-power state, as explained in :file:`Documentation/power/runtime_pm.txt`.
to that document for more information regarding this particular issue as well as Refer to that document for more information regarding this particular issue as
for information on the device runtime power management framework in general. well as for information on the device runtime power management framework in
general.
=======================
Device Power Management
=======================
.. toctree::
devices
notifiers
types
.. only:: subproject and html
Indices
=======
* :ref:`genindex`
=============================
Suspend/Hibernation Notifiers
=============================
::
Copyright (c) 2016 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
There are some operations that subsystems or drivers may want to carry out
before hibernation/suspend or after restore/resume, but they require the system
to be fully functional, so the drivers' and subsystems' ``->suspend()`` and
``->resume()`` or even ``->prepare()`` and ``->complete()`` callbacks are not
suitable for this purpose.
For example, device drivers may want to upload firmware to their devices after
resume/restore, but they cannot do it by calling :c:func:`request_firmware()`
from their ``->resume()`` or ``->complete()`` callback routines (user land
processes are frozen at these points). The solution may be to load the firmware
into memory before processes are frozen and upload it from there in the
``->resume()`` routine. A suspend/hibernation notifier may be used for that.
Subsystems or drivers having such needs can register suspend notifiers that
will be called upon the following events by the PM core:
``PM_HIBERNATION_PREPARE``
The system is going to hibernate, tasks will be frozen immediately. This
is different from ``PM_SUSPEND_PREPARE`` below, because in this case
additional work is done between the notifiers and the invocation of PM
callbacks for the "freeze" transition.
``PM_POST_HIBERNATION``
The system memory state has been restored from a hibernation image or an
error occurred during hibernation. Device restore callbacks have been
executed and tasks have been thawed.
``PM_RESTORE_PREPARE``
The system is going to restore a hibernation image. If all goes well,
the restored image kernel will issue a ``PM_POST_HIBERNATION``
notification.
``PM_POST_RESTORE``
An error occurred during restore from hibernation. Device restore
callbacks have been executed and tasks have been thawed.
``PM_SUSPEND_PREPARE``
The system is preparing for suspend.
``PM_POST_SUSPEND``
The system has just resumed or an error occurred during suspend. Device
resume callbacks have been executed and tasks have been thawed.
It is generally assumed that whatever the notifiers do for
``PM_HIBERNATION_PREPARE``, should be undone for ``PM_POST_HIBERNATION``.
Analogously, operations carried out for ``PM_SUSPEND_PREPARE`` should be
reversed for ``PM_POST_SUSPEND``.
Moreover, if one of the notifiers fails for the ``PM_HIBERNATION_PREPARE`` or
``PM_SUSPEND_PREPARE`` event, the notifiers that have already succeeded for that
event will be called for ``PM_POST_HIBERNATION`` or ``PM_POST_SUSPEND``,
respectively.
The hibernation and suspend notifiers are called with :c:data:`pm_mutex` held.
They are defined in the usual way, but their last argument is meaningless (it is
always NULL).
To register and/or unregister a suspend notifier use
:c:func:`register_pm_notifier()` and :c:func:`unregister_pm_notifier()`,
respectively (both defined in :file:`include/linux/suspend.h`). If you don't
need to unregister the notifier, you can also use the :c:func:`pm_notifier()`
macro defined in :file:`include/linux/suspend.h`.
==================================
Device Power Management Data Types
==================================
.. kernel-doc:: include/linux/pm.h
.. Copyright 2007-2008 Wolfson Microelectronics
.. This documentation is free software; you can redistribute
.. it and/or modify it under the terms of the GNU General Public
.. License version 2 as published by the Free Software Foundation.
=================================
Voltage and current regulator API
=================================
:Author: Liam Girdwood
:Author: Mark Brown
Introduction
============
This framework is designed to provide a standard kernel interface to
control voltage and current regulators.
The intention is to allow systems to dynamically control regulator power
output in order to save power and prolong battery life. This applies to
both voltage regulators (where voltage output is controllable) and
current sinks (where current limit is controllable).
Note that additional (and currently more complete) documentation is
available in the Linux kernel source under
``Documentation/power/regulator``.
Glossary
--------
The regulator API uses a number of terms which may not be familiar:
Regulator
Electronic device that supplies power to other devices. Most regulators
can enable and disable their output and some can also control their
output voltage or current.
Consumer
Electronic device which consumes power provided by a regulator. These
may either be static, requiring only a fixed supply, or dynamic,
requiring active management of the regulator at runtime.
Power Domain
The electronic circuit supplied by a given regulator, including the
regulator and all consumer devices. The configuration of the regulator
is shared between all the components in the circuit.
Power Management Integrated Circuit (PMIC)
An IC which contains numerous regulators and often also other
subsystems. In an embedded system the primary PMIC is often equivalent
to a combination of the PSU and southbridge in a desktop system.
Consumer driver interface
=========================
This offers a similar API to the kernel clock framework. Consumer
drivers use `get <#API-regulator-get>`__ and
`put <#API-regulator-put>`__ operations to acquire and release
regulators. Functions are provided to `enable <#API-regulator-enable>`__
and `disable <#API-regulator-disable>`__ the regulator and to get and
set the runtime parameters of the regulator.
When requesting regulators consumers use symbolic names for their
supplies, such as "Vcc", which are mapped into actual regulator devices
by the machine interface.
A stub version of this API is provided when the regulator framework is
not in use in order to minimise the need to use ifdefs.
Enabling and disabling
----------------------
The regulator API provides reference counted enabling and disabling of
regulators. Consumer devices use the :c:func:`regulator_enable()` and
:c:func:`regulator_disable()` functions to enable and disable
regulators. Calls to the two functions must be balanced.
Note that since multiple consumers may be using a regulator and machine
constraints may not allow the regulator to be disabled there is no
guarantee that calling :c:func:`regulator_disable()` will actually
cause the supply provided by the regulator to be disabled. Consumer
drivers should assume that the regulator may be enabled at all times.
Configuration
-------------
Some consumer devices may need to be able to dynamically configure their
supplies. For example, MMC drivers may need to select the correct
operating voltage for their cards. This may be done while the regulator
is enabled or disabled.
The :c:func:`regulator_set_voltage()` and
:c:func:`regulator_set_current_limit()` functions provide the primary
interface for this. Both take ranges of voltages and currents, supporting
drivers that do not require a specific value (eg, CPU frequency scaling
normally permits the CPU to use a wider range of supply voltages at lower
frequencies but does not require that the supply voltage be lowered). Where
an exact value is required both minimum and maximum values should be
identical.
Callbacks
---------
Callbacks may also be registered for events such as regulation failures.
Regulator driver interface
==========================
Drivers for regulator chips register the regulators with the regulator
core, providing operations structures to the core. A notifier interface
allows error conditions to be reported to the core.
Registration should be triggered by explicit setup done by the platform,
supplying a struct :c:type:`regulator_init_data` for the regulator
containing constraint and supply information.
Machine interface
=================
This interface provides a way to define how regulators are connected to
consumers on a given system and what the valid operating parameters are
for the system.
Supplies
--------
Regulator supplies are specified using struct
:c:type:`regulator_consumer_supply`. This is done at driver registration
time as part of the machine constraints.
Constraints
-----------
As well as defining the connections the machine interface also provides
constraints defining the operations that clients are allowed to perform
and the parameters that may be set. This is required since generally
regulator devices will offer more flexibility than it is safe to use on
a given system, for example supporting higher supply voltages than the
consumers are rated for.
This is done at driver registration time` by providing a
struct :c:type:`regulation_constraints`.
The constraints may also specify an initial configuration for the
regulator in the constraints, which is particularly useful for use with
static consumers.
API reference
=============
Due to limitations of the kernel documentation framework and the
existing layout of the source code the entire regulator API is
documented here.
.. kernel-doc:: include/linux/regulator/consumer.h
:internal:
.. kernel-doc:: include/linux/regulator/machine.h
:internal:
.. kernel-doc:: include/linux/regulator/driver.h
:internal:
.. kernel-doc:: drivers/regulator/core.c
:export:
...@@ -117,10 +117,10 @@ support, which is achieved via the R0 and R1 config register bits, where: ...@@ -117,10 +117,10 @@ support, which is achieved via the R0 and R1 config register bits, where:
R0..R1 R0..R1
------ ------
0 0 => 9 bits, 0.5 degrees Celcius 0 0 => 9 bits, 0.5 degrees Celsius
1 0 => 10 bits, 0.25 degrees Celcius 1 0 => 10 bits, 0.25 degrees Celsius
0 1 => 11 bits, 0.125 degrees Celcius 0 1 => 11 bits, 0.125 degrees Celsius
1 1 => 12 bits, 0.0625 degrees Celcius 1 1 => 12 bits, 0.0625 degrees Celsius
Note: Note:
At initial device power-on, the default resolution is set to 12-bits. At initial device power-on, the default resolution is set to 12-bits.
......
...@@ -47,7 +47,7 @@ These books get into the details of how specific kernel subsystems work ...@@ -47,7 +47,7 @@ These books get into the details of how specific kernel subsystems work
from the point of view of a kernel developer. Much of the information here from the point of view of a kernel developer. Much of the information here
is taken directly from the kernel source, with supplemental material added is taken directly from the kernel source, with supplemental material added
as needed (or at least as we managed to add it — probably *not* all that is as needed (or at least as we managed to add it — probably *not* all that is
needed). needed).
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
...@@ -68,6 +68,14 @@ Korean translations ...@@ -68,6 +68,14 @@ Korean translations
translations/ko_KR/index translations/ko_KR/index
Chinese translations
--------------------
.. toctree::
:maxdepth: 1
translations/zh_CN/index
Indices and tables Indices and tables
================== ==================
......
...@@ -279,10 +279,10 @@ struct input_event { ...@@ -279,10 +279,10 @@ struct input_event {
'time' is the timestamp, it returns the time at which the event happened. 'time' is the timestamp, it returns the time at which the event happened.
Type is for example EV_REL for relative moment, EV_KEY for a keypress or Type is for example EV_REL for relative moment, EV_KEY for a keypress or
release. More types are defined in include/linux/input.h. release. More types are defined in include/uapi/linux/input-event-codes.h.
'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete 'code' is event code, for example REL_X or KEY_BACKSPACE, again a complete
list is in include/linux/input.h. list is in include/uapi/linux/input-event-codes.h.
'value' is the value the event carries. Either a relative change for 'value' is the value the event carries. Either a relative change for
EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for EV_REL, absolute new value for EV_ABS (joysticks ...), or 0 for EV_KEY for
......
...@@ -24,7 +24,7 @@ Prerequisites ...@@ -24,7 +24,7 @@ Prerequisites
------------- -------------
First the prerequisites. Without these you have already failed, because you First the prerequisites. Without these you have already failed, because you
will need to add a a 32-bit compat layer: will need to add a 32-bit compat layer:
* Only use fixed sized integers. To avoid conflicts with typedefs in userspace * Only use fixed sized integers. To avoid conflicts with typedefs in userspace
the kernel has special types like __u32, __s64. Use them. the kernel has special types like __u32, __s64. Use them.
......
...@@ -358,7 +358,7 @@ The current Livepatch implementation has several limitations: ...@@ -358,7 +358,7 @@ The current Livepatch implementation has several limitations:
Each function has to handle TOC and save LR before it could call Each function has to handle TOC and save LR before it could call
the ftrace handler. This operation has to be reverted on return. the ftrace handler. This operation has to be reverted on return.
Fortunately, the generic ftrace code has the same problem and all Fortunately, the generic ftrace code has the same problem and all
this is is handled on the ftrace level. this is handled on the ftrace level.
+ Kretprobes using the ftrace framework conflict with the patched + Kretprobes using the ftrace framework conflict with the patched
......
...@@ -36,7 +36,7 @@ quiet_cmd_genpdf = GENPDF $2 ...@@ -36,7 +36,7 @@ quiet_cmd_genpdf = GENPDF $2
cmd_genpdf = convert $2 $3 cmd_genpdf = convert $2 $3
quiet_cmd_gendot = DOT $2 quiet_cmd_gendot = DOT $2
cmd_gendot = dot -Tsvg $2 > $3 cmd_gendot = dot -Tsvg $2 > $3 || { rm -f $3; exit 1; }
%.pdf: %.svg %.pdf: %.svg
@$(call cmd,genpdf,$<,$@) @$(call cmd,genpdf,$<,$@)
...@@ -103,6 +103,7 @@ html: all ...@@ -103,6 +103,7 @@ html: all
epub: all epub: all
xml: all xml: all
latex: $(IMGPDF) all latex: $(IMGPDF) all
linkcheck:
clean: clean:
-rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null -rm -f $(DOTTGT) $(IMGTGT) ${TARGETS} 2>/dev/null
......
...@@ -272,7 +272,7 @@ on the socket thus waking up the application thread. When the application ...@@ -272,7 +272,7 @@ on the socket thus waking up the application thread. When the application
sees the error (which may just be a disconnect) it should unattach the sees the error (which may just be a disconnect) it should unattach the
socket from KCM and then close it. It is assumed that once an error is socket from KCM and then close it. It is assumed that once an error is
posted on the TCP socket the data stream is unrecoverable (i.e. an error posted on the TCP socket the data stream is unrecoverable (i.e. an error
may have occurred in in the middle of receiving a messssge). may have occurred in the middle of receiving a messssge).
TCP connection monitoring TCP connection monitoring
------------------------- -------------------------
......
...@@ -14,8 +14,6 @@ freezing-of-tasks.txt ...@@ -14,8 +14,6 @@ freezing-of-tasks.txt
- How processes and controlled during suspend - How processes and controlled during suspend
interface.txt interface.txt
- Power management user interface in /sys/power - Power management user interface in /sys/power
notifiers.txt
- Registering suspend notifiers in device drivers
opp.txt opp.txt
- Operating Performance Point library - Operating Performance Point library
pci.txt pci.txt
......
...@@ -197,7 +197,8 @@ tasks, since it generally exists anyway. ...@@ -197,7 +197,8 @@ tasks, since it generally exists anyway.
A driver must have all firmwares it may need in RAM before suspend() is called. A driver must have all firmwares it may need in RAM before suspend() is called.
If keeping them is not practical, for example due to their size, they must be If keeping them is not practical, for example due to their size, they must be
requested early enough using the suspend notifier API described in notifiers.txt. requested early enough using the suspend notifier API described in
Documentation/driver-api/pm/notifiers.rst.
VI. Are there any precautions to be taken to prevent freezing failures? VI. Are there any precautions to be taken to prevent freezing failures?
......
Suspend notifiers
(C) 2007-2011 Rafael J. Wysocki <rjw@sisk.pl>, GPL
There are some operations that subsystems or drivers may want to carry out
before hibernation/suspend or after restore/resume, but they require the system
to be fully functional, so the drivers' and subsystems' .suspend() and .resume()
or even .prepare() and .complete() callbacks are not suitable for this purpose.
For example, device drivers may want to upload firmware to their devices after
resume/restore, but they cannot do it by calling request_firmware() from their
.resume() or .complete() routines (user land processes are frozen at these
points). The solution may be to load the firmware into memory before processes
are frozen and upload it from there in the .resume() routine.
A suspend/hibernation notifier may be used for this purpose.
The subsystems or drivers having such needs can register suspend notifiers that
will be called upon the following events by the PM core:
PM_HIBERNATION_PREPARE The system is going to hibernate, tasks will be frozen
immediately. This is different from PM_SUSPEND_PREPARE
below because here we do additional work between notifiers
and drivers freezing.
PM_POST_HIBERNATION The system memory state has been restored from a
hibernation image or an error occurred during
hibernation. Device drivers' restore callbacks have
been executed and tasks have been thawed.
PM_RESTORE_PREPARE The system is going to restore a hibernation image.
If all goes well, the restored kernel will issue a
PM_POST_HIBERNATION notification.
PM_POST_RESTORE An error occurred during restore from hibernation.
Device drivers' restore callbacks have been executed
and tasks have been thawed.
PM_SUSPEND_PREPARE The system is preparing for suspend.
PM_POST_SUSPEND The system has just resumed or an error occurred during
suspend. Device drivers' resume callbacks have been
executed and tasks have been thawed.
It is generally assumed that whatever the notifiers do for
PM_HIBERNATION_PREPARE, should be undone for PM_POST_HIBERNATION. Analogously,
operations performed for PM_SUSPEND_PREPARE should be reversed for
PM_POST_SUSPEND. Additionally, all of the notifiers are called for
PM_POST_HIBERNATION if one of them fails for PM_HIBERNATION_PREPARE, and
all of the notifiers are called for PM_POST_SUSPEND if one of them fails for
PM_SUSPEND_PREPARE.
The hibernation and suspend notifiers are called with pm_mutex held. They are
defined in the usual way, but their last argument is meaningless (it is always
NULL). To register and/or unregister a suspend notifier use the functions
register_pm_notifier() and unregister_pm_notifier(), respectively, defined in
include/linux/suspend.h . If you don't need to unregister the notifier, you can
also use the pm_notifier() macro defined in include/linux/suspend.h .
...@@ -713,7 +713,7 @@ In addition to that the prepare() callback may carry out some operations ...@@ -713,7 +713,7 @@ In addition to that the prepare() callback may carry out some operations
preparing the device to be suspended, although it should not allocate memory preparing the device to be suspended, although it should not allocate memory
(if additional memory is required to suspend the device, it has to be (if additional memory is required to suspend the device, it has to be
preallocated earlier, for example in a suspend/hibernate notifier as described preallocated earlier, for example in a suspend/hibernate notifier as described
in Documentation/power/notifiers.txt). in Documentation/driver-api/pm/notifiers.rst).
3.1.2. suspend() 3.1.2. suspend()
......
...@@ -63,7 +63,7 @@ for instance) is a PPS source too, and if not they should provide the ...@@ -63,7 +63,7 @@ for instance) is a PPS source too, and if not they should provide the
possibility to open another device as PPS source. possibility to open another device as PPS source.
In LinuxPPS the PPS sources are simply char devices usually mapped In LinuxPPS the PPS sources are simply char devices usually mapped
into files /dev/pps0, /dev/pps1, etc.. into files /dev/pps0, /dev/pps1, etc.
PPS with USB to serial devices PPS with USB to serial devices
...@@ -71,9 +71,12 @@ PPS with USB to serial devices ...@@ -71,9 +71,12 @@ PPS with USB to serial devices
It is possible to grab the PPS from an USB to serial device. However, It is possible to grab the PPS from an USB to serial device. However,
you should take into account the latencies and jitter introduced by you should take into account the latencies and jitter introduced by
the USB stack. Users has reported clock instability around +-1ms when the USB stack. Users have reported clock instability around +-1ms when
synchronized with PPS through USB. This isn't suited for time server synchronized with PPS through USB. With USB 2.0, jitter may decrease
synchronization. down to the order of 125 microseconds.
This may be suitable for time server synchronization with NTP because
of its undersampling and algorithms.
If your device doesn't report PPS, you can check that the feature is If your device doesn't report PPS, you can check that the feature is
supported by its driver. Most of the time, you only need to add a call supported by its driver. Most of the time, you only need to add a call
...@@ -166,7 +169,8 @@ Testing the PPS support ...@@ -166,7 +169,8 @@ Testing the PPS support
In order to test the PPS support even without specific hardware you can use In order to test the PPS support even without specific hardware you can use
the ktimer driver (see the client subsection in the PPS configuration menu) the ktimer driver (see the client subsection in the PPS configuration menu)
and the userland tools provided in the Documentation/pps/ directory. and the userland tools available in your distribution's pps-tools package,
http://linuxpps.org , or https://github.com/ago/pps-tools .
Once you have enabled the compilation of ktimer just modprobe it (if Once you have enabled the compilation of ktimer just modprobe it (if
not statically compiled): not statically compiled):
...@@ -183,8 +187,8 @@ and the run ppstest as follow: ...@@ -183,8 +187,8 @@ and the run ppstest as follow:
source 0 - assert 1186592700.388931295, sequence: 365 - clear 0.000000000, sequence: 0 source 0 - assert 1186592700.388931295, sequence: 365 - clear 0.000000000, sequence: 0
source 0 - assert 1186592701.389032765, sequence: 366 - clear 0.000000000, sequence: 0 source 0 - assert 1186592701.389032765, sequence: 366 - clear 0.000000000, sequence: 0
Please, note that to compile userland programs you need the file timepps.h Please, note that to compile userland programs you need the file timepps.h .
(see Documentation/pps/). This is available in the pps-tools repository mentioned above.
Generators Generators
......
...@@ -42,7 +42,7 @@ thresholds can be configured thanks to the following HWMON attributes: ...@@ -42,7 +42,7 @@ thresholds can be configured thanks to the following HWMON attributes:
* Critical: temp1_crit and temp1_crit_hyst; * Critical: temp1_crit and temp1_crit_hyst;
* Shutdown: temp1_emergency and temp1_emergency_hyst. * Shutdown: temp1_emergency and temp1_emergency_hyst.
NOTE: Remember that the values are stored as milli degrees Celcius. Don't forget NOTE: Remember that the values are stored as milli degrees Celsius. Don't forget
to multiply! to multiply!
Fan management Fan management
......
...@@ -111,7 +111,7 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを ...@@ -111,7 +111,7 @@ Linux カーネルソースツリーは幅広い範囲のドキュメントを
カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの カーネルの変更が、カーネルがユーザ空間に公開しているインターフェイスの
変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報 変更を引き起こす場合、その変更を説明するマニュアルページのパッチや情報
をマニュアルページのメンテナ mtk.manpages@gmail.com に送り、CC を をマニュアルページのメンテナ mtk.manpages@gmail.com に送り、CC を
linux-api@ver.kernel.org に送ることを勧めます。 linux-api@vger.kernel.org に送ることを勧めます。
以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で 以下はカーネルソースツリーに含まれている読んでおくべきファイルの一覧で
す- す-
......
...@@ -289,8 +289,8 @@ pub/linux/kernel/v4.x/ 디렉토리에서 참조될 수 있다.개발 프로세 ...@@ -289,8 +289,8 @@ pub/linux/kernel/v4.x/ 디렉토리에서 참조될 수 있다.개발 프로세
Andrew Morton의 글이 있다. Andrew Morton의 글이 있다.
*"커널이 언제 배포될지는 아무도 모른다. 왜냐하면 배포는 알려진 *"커널이 언제 배포될지는 아무도 모른다. 왜냐하면 배포는 알려진
버그의 상황에 따라 배포되는 것이지 미리정해 놓은 시간에 따라 버그의 상황에 따라 배포되는 것이지 미리정해 놓은 시간에 따라
배포되는 것은 아니기 때문이다."* 배포되는 것은 아니기 때문이다."*
4.x.y - 안정 커널 트리 4.x.y - 안정 커널 트리
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
......
...@@ -6,51 +6,61 @@ Chinese maintainer for help. Contact the Chinese maintainer, if this ...@@ -6,51 +6,61 @@ Chinese maintainer for help. Contact the Chinese maintainer, if this
translation is outdated or there is problem with translation. translation is outdated or there is problem with translation.
Chinese maintainer: Zhang Le <r0bertz@gentoo.org> Chinese maintainer: Zhang Le <r0bertz@gentoo.org>
--------------------------------------------------------------------- ---------------------------------------------------------------------
Documentation/process/coding-style.rst的中文翻译
Documentation/process/coding-style.rst 的中文翻译
如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可
以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。 如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,
也可以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版
中文版维护者: 张乐 Zhang Le <r0bertz@gentoo.org> 维护者::
中文版翻译者: 张乐 Zhang Le <r0bertz@gentoo.org>
中文版校译者: 王聪 Wang Cong <xiyou.wangcong@gmail.com> 中文版维护者: 张乐 Zhang Le <r0bertz@gentoo.org>
wheelz <kernel.zeng@gmail.com> 中文版翻译者: 张乐 Zhang Le <r0bertz@gentoo.org>
管旭东 Xudong Guan <xudong.guan@gmail.com> 中文版校译者: 王聪 Wang Cong <xiyou.wangcong@gmail.com>
Li Zefan <lizf@cn.fujitsu.com> wheelz <kernel.zeng@gmail.com>
Wang Chen <wangchen@cn.fujitsu.com> 管旭东 Xudong Guan <xudong.guan@gmail.com>
Li Zefan <lizf@cn.fujitsu.com>
Wang Chen <wangchen@cn.fujitsu.com>
以下为正文 以下为正文
--------------------------------------------------------------------- ---------------------------------------------------------------------
Linux内核代码风格 Linux 内核代码风格
=========================
这是一个简短的文档,描述了 linux 内核的首选代码风格。代码风格是因人而异的,而且我 这是一个简短的文档,描述了 linux 内核的首选代码风格。代码风格是因人而异的,
不愿意把自己的观点强加给任何人,但这就像我去做任何事情都必须遵循的原则那样,我也 而且我不愿意把自己的观点强加给任何人,但这就像我去做任何事情都必须遵循的原则
希望在绝大多数事上保持这种的态度。请(在写代码时)至少考虑一下这里的代码风格。 那样,我也希望在绝大多数事上保持这种的态度。请 (在写代码时) 至少考虑一下这里
的代码风格。
首先,我建议你打印一份 GNU 代码规范,然后不要读。烧了它,这是一个具有重大象征性意义 首先,我建议你打印一份 GNU 代码规范,然后不要读。烧了它,这是一个具有重大象征
的动作。 性意义的动作。
不管怎样,现在我们开始: 不管怎样,现在我们开始:
第一章:缩进 1) 缩进
--------------
制表符是 8 个字符,所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4 (甚至
2!) 字符深,这几乎相当于尝试将圆周率的值定义为 3。
制表符是 8 个字符,所以缩进也是 8 个字符。有些异端运动试图将缩进变为 4(甚至 2!) 理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的
个字符深,这几乎相当于尝试将圆周率的值定义为 3 屏幕连续看了 20 小时之后,你将会发现大一点的缩进会使你更容易分辨缩进
理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕 现在,有些人会抱怨 8 个字符的缩进会使代码向右边移动的太远,在 80 个字符的终端
连续看了 20 小时之后,你将会发现大一点的缩进会使你更容易分辨缩进。 屏幕上就很难读这样的代码。这个问题的答案是,如果你需要 3 级以上的缩进,不管用
何种方式你的代码已经有问题了,应该修正你的程序。
现在,有些人会抱怨 8 个字符的缩进会使代码向右边移动的太远,在 80 个字符的终端屏幕上 简而言之,8 个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太
就很难读这样的代码。这个问题的答案是,如果你需要 3 级以上的缩进,不管用何种方式你 深的时候可以给你警告。留心这个警告。
的代码已经有问题了,应该修正你的程序。
简而言之,8 个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太深的 在 switch 语句中消除多级缩进的首选的方式是让 ``switch`` 和从属于它的 ``case``
时候可以给你警告。留心这个警告。 标签对齐于同一列,而不要 ``两次缩进`` ``case`` 标签。比如:
在 switch 语句中消除多级缩进的首选的方式是让 “switch” 和从属于它的 “case” 标签 .. code-block:: c
对齐于同一列,而不要 “两次缩进” “case” 标签。比如:
switch (suffix) { switch (suffix) {
case 'G': case 'G':
...@@ -71,39 +81,49 @@ Documentation/process/coding-style.rst的中文翻译 ...@@ -71,39 +81,49 @@ Documentation/process/coding-style.rst的中文翻译
不要把多个语句放在一行里,除非你有什么东西要隐藏: 不要把多个语句放在一行里,除非你有什么东西要隐藏:
.. code-block:: c
if (condition) do_this; if (condition) do_this;
do_something_everytime; do_something_everytime;
也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读的表 也不要在一行里放多个赋值语句。内核代码风格超级简单。就是避免可能导致别人误读
达式。 的表达式。
除了注释、文档和 Kconfig 之外,不要使用空格来缩进,前面的例子是例外,是有意为之。 除了注释、文档和 Kconfig 之外,不要使用空格来缩进,前面的例子是例外,是有意为
之。
选用一个好的编辑器,不要在行尾留空格。 选用一个好的编辑器,不要在行尾留空格。
第二章:把长的行和字符串打散 2) 把长的行和字符串打散
------------------------------
代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。 代码风格的意义就在于使用平常使用的工具来维持代码的可读性和可维护性。
每一行的长度的限制是 80 列,我们强烈建议您遵守这个惯例。 每一行的长度的限制是 80 列,我们强烈建议您遵守这个惯例。
长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性,并且不会隐藏 长于 80 列的语句要打散成有意义的片段。除非超过 80 列能显著增加可读性,并且不
信息。子片段要明显短于母片段,并明显靠右。这同样适用于有着很长参数列表的函数头。 会隐藏信息。子片段要明显短于母片段,并明显靠右。这同样适用于有着很长参数列表
然而,绝对不要打散对用户可见的字符串,例如 printk 信息,因为这将导致无法 grep 这些 的函数头。然而,绝对不要打散对用户可见的字符串,例如 printk 信息,因为这样就
信息。 很难对它们 grep。
第三章:大括号和空格的放置 3) 大括号和空格的放置
------------------------------
C语言风格中另外一个常见问题是大括号的放置。和缩进大小不同,选择或弃用某种放置策 C 语言风格中另外一个常见问题是大括号的放置。和缩进大小不同,选择或弃用某种放
略并没有多少技术上的原因,不过首选的方式,就像 Kernighan 和 Ritchie 展示给我们的, 置策略并没有多少技术上的原因,不过首选的方式,就像 Kernighan 和 Ritchie 展示
是把起始大括号放在行尾,而把结束大括号放在行首,所以: 给我们的,是把起始大括号放在行尾,而把结束大括号放在行首,所以:
.. code-block:: c
if (x is true) { if (x is true) {
we do y we do y
} }
这适用于所有的非函数语句块(if、switch、for、while、do)。比如: 这适用于所有的非函数语句块 (if, switch, for, while, do)。比如:
.. code-block:: c
switch (action) { switch (action) {
case KOBJ_ADD: case KOBJ_ADD:
...@@ -118,17 +138,21 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小 ...@@ -118,17 +138,21 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小
不过,有一个例外,那就是函数:函数的起始大括号放置于下一行的开头,所以: 不过,有一个例外,那就是函数:函数的起始大括号放置于下一行的开头,所以:
.. code-block:: c
int function(int x) int function(int x)
{ {
body of function body of function
} }
全世界的异端可能会抱怨这个不一致性是……呃……不一致的,不过所有思维健全的人都知道 全世界的异端可能会抱怨这个不一致性是... 呃... 不一致的,不过所有思维健全的人
(a) K&R 是 _正确的_,并且 (b) K&R 是正确的。此外,不管怎样函数都是特殊的(C 都知道 (a) K&R 是 **正确的** 并且 (b) K&R 是正确的。此外,不管怎样函数都是特
函数是不能嵌套的)。 殊的 (C 函数是不能嵌套的)。
注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是 do 语
句中的 "while" 或者 if 语句中的 "else",像这样:
注意结束大括号独自占据一行,除非它后面跟着同一个语句的剩余部分,也就是 do 语句中的 .. code-block:: c
“while” 或者 if 语句中的 “else”,像这样:
do { do {
body of do-loop body of do-loop
...@@ -136,6 +160,8 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小 ...@@ -136,6 +160,8 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小
.. code-block:: c
if (x == y) { if (x == y) {
.. ..
} else if (x > y) { } else if (x > y) {
...@@ -146,17 +172,21 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小 ...@@ -146,17 +172,21 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小
理由:K&R。 理由:K&R。
也请注意这种大括号的放置方式也能使空(或者差不多空的)行的数量最小化,同时不失可 也请注意这种大括号的放置方式也能使空 (或者差不多空的) 行的数量最小化,同时不
读性。因此,由于你的屏幕上的新行是不可再生资源(想想 25 行的终端屏幕),你将会有更 失可读性。因此,由于你的屏幕上的新行是不可再生资源 (想想 25 行的终端屏幕),你
多的空行来放置注释。 将会有更多的空行来放置注释。
当只有一个单独的语句的时候,不用加不必要的大括号。 当只有一个单独的语句的时候,不用加不必要的大括号。
.. code-block:: c
if (condition) if (condition)
action(); action();
.. code-block:: c
if (condition) if (condition)
do_this(); do_this();
else else
...@@ -164,6 +194,8 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小 ...@@ -164,6 +194,8 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小
这并不适用于只有一个条件分支是单语句的情况;这时所有分支都要使用大括号: 这并不适用于只有一个条件分支是单语句的情况;这时所有分支都要使用大括号:
.. code-block:: c
if (condition) { if (condition) {
do_this(); do_this();
do_that(); do_that();
...@@ -171,88 +203,103 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小 ...@@ -171,88 +203,103 @@ C语言风格中另外一个常见问题是大括号的放置。和缩进大小
otherwise(); otherwise();
} }
3.1:空格 3.1) 空格
********************
Linux 内核的空格使用方式(主要)取决于它是用于函数还是关键字。(大多数)关键字后 Linux 内核的空格使用方式 (主要) 取决于它是用于函数还是关键字。(大多数) 关键字
要加一个空格。值得注意的例外是 sizeof、typeof、alignof 和 __attribute__,这些 后要加一个空格。值得注意的例外是 sizeof, typeof, alignof 和 __attribute__,这
关键字某些程度上看起来更像函数(它们在 Linux 里也常常伴随小括号而使用,尽管在 C 里 些关键字某些程度上看起来更像函数 (它们在 Linux 里也常常伴随小括号而使用,尽管
这样的小括号不是必需的,就像 “struct fileinfo info” 声明过后的 “sizeof info”)。 在 C 里这样的小括号不是必需的,就像 ``struct fileinfo info;`` 声明过后的
``sizeof info``)。
所以在这些关键字之后放一个空格 所以在这些关键字之后放一个空格::
if, switch, case, for, do, while if, switch, case, for, do, while
但是不要在 sizeof、typeof、alignof 或者 __attribute__ 这些关键字之后放空格。例如, 但是不要在 sizeof, typeof, alignof 或者 __attribute__ 这些关键字之后放空格。
例如,
.. code-block:: c
s = sizeof(struct file); s = sizeof(struct file);
不要在小括号里的表达式两侧加空格。这是一个反例: 不要在小括号里的表达式两侧加空格。这是一个 **反例** :
.. code-block:: c
s = sizeof( struct file ); s = sizeof( struct file );
当声明指针类型或者返回指针类型的函数时,“*” 的首选使用方式是使之靠近变量名或者函 当声明指针类型或者返回指针类型的函数时, ``*`` 的首选使用方式是使之靠近变量名
数名,而不是靠近类型名。例子: 或者函数名,而不是靠近类型名。例子:
.. code-block:: c
char *linux_banner; char *linux_banner;
unsigned long long memparse(char *ptr, char **retptr); unsigned long long memparse(char *ptr, char **retptr);
char *match_strdup(substring_t *s); char *match_strdup(substring_t *s);
在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符 在大多数二元和三元操作符两侧使用一个空格,例如下面所有这些操作符::
= + - < > * / % | & ^ <= >= == != ? : = + - < > * / % | & ^ <= >= == != ? :
但是一元操作符后不要加空格 但是一元操作符后不要加空格::
& * + - ~ ! sizeof typeof alignof __attribute__ defined & * + - ~ ! sizeof typeof alignof __attribute__ defined
后缀自加和自减一元操作符前不加空格 后缀自加和自减一元操作符前不加空格::
++ -- ++ --
前缀自加和自减一元操作符后不加空格 前缀自加和自减一元操作符后不加空格::
++ -- ++ --
‘.’ 和 “->” 结构体成员操作符前后不加空格。 ``.`` 和 ``->`` 结构体成员操作符前后不加空格。
不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后 不要在行尾留空白。有些可以自动缩进的编辑器会在新行的行首加入适量的空白,然后
就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码,有些编辑器就不 你就可以直接在那一行输入代码。不过假如你最后没有在那一行输入代码,有些编辑器
会移除已经加入的空白,就像你故意留下一个只有空白的行。包含行尾空白的行就这样产 就不会移除已经加入的空白,就像你故意留下一个只有空白的行。包含行尾空白的行就
生了。 这样产生了。
当git发现补丁包含了行尾空白的时候会警告你,并且可以应你的要求去掉行尾空白;不过 当 git 发现补丁包含了行尾空白的时候会警告你,并且可以应你的要求去掉行尾空白;
如果你是正在打一系列补丁,这样做会导致后面的补丁失败,因为你改变了补丁的上下文。 不过如果你是正在打一系列补丁,这样做会导致后面的补丁失败,因为你改变了补丁的
上下文。
第四章:命名 4) 命名
------------------------------
C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同,C 程序员 C 是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pascal 程序员不同,
不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会称那个变量 C 程序员不使用类似 ThisVariableIsATemporaryCounter 这样华丽的名字。C 程序员会
为 “tmp”,这样写起来会更容易,而且至少不会令其难于理解。 称那个变量为 ``tmp`` ,这样写起来会更容易,而且至少不会令其难于理解。
不过,虽然混用大小写的名字是不提倡使用的,但是全局变量还是需要一个具描述性的名字 不过,虽然混用大小写的名字是不提倡使用的,但是全局变量还是需要一个具描述性的
。称一个全局函数为 “foo” 是一个难以饶恕的错误。 名字。称一个全局函数为 ``foo`` 是一个难以饶恕的错误。
全局变量(只有当你真正需要它们的时候再用它)需要有一个具描述性的名字,就像全局函 全局变量 (只有当你 **真正** 需要它们的时候再用它) 需要有一个具描述性的名字,就
数。如果你有一个可以计算活动用户数量的函数,你应该叫它 “count_active_users()” 像全局函数。如果你有一个可以计算活动用户数量的函数,你应该叫它
或者类似的名字,你不应该叫它 “cntuser()” ``count_active_users()`` 或者类似的名字,你不应该叫它 ``cntuser()``
在函数名中包含函数类型(所谓的匈牙利命名法)是脑子出了问题——编译器知道那些类型而 在函数名中包含函数类型 (所谓的匈牙利命名法) 是脑子出了问题——编译器知道那些类
且能够检查那些类型,这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题的程序。 型而且能够检查那些类型,这样做只能把程序员弄糊涂了。难怪微软总是制造出有问题
的程序。
本地变量名应该简短,而且能够表达相关的含义。如果你有一些随机的整数型的循环计数器 本地变量名应该简短,而且能够表达相关的含义。如果你有一些随机的整数型的循环计
,它应该被称为 “i”。叫它 “loop_counter” 并无益处,如果它没有被误解的可能的话。 数器,它应该被称为 ``i`` 。叫它 ``loop_counter`` 并无益处,如果它没有被误解的
类似的,“tmp” 可以用来称呼任意类型的临时变量。 可能的话。类似的, ``tmp`` 可以用来称呼任意类型的临时变量。
如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综合症 如果你怕混淆了你的本地变量名,你就遇到另一个问题了,叫做函数增长荷尔蒙失衡综
。请看第六章(函数) 合症。请看第六章 (函数)
第五章:Typedef 5) Typedef
-----------
不要使用类似 “vps_t” 之类的东西。 不要使用类似 ``vps_t`` 之类的东西。
对结构体和指针使用 typedef 是一个错误。当你在代码里看到: 对结构体和指针使用 typedef 是一个 **错误** 。当你在代码里看到:
.. code-block:: c
vps_t a; vps_t a;
...@@ -260,75 +307,89 @@ C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pasca ...@@ -260,75 +307,89 @@ C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pasca
相反,如果是这样 相反,如果是这样
.. code-block:: c
struct virtual_container *a; struct virtual_container *a;
你就知道 “a” 是什么了。 你就知道 ``a`` 是什么了。
很多人认为 typedef “能提高可读性”。实际不是这样的。它们只在下列情况下有用: 很多人认为 typedef ``能提高可读性`` 。实际不是这样的。它们只在下列情况下有用:
(a) 完全不透明的对象(这种情况下要主动使用 typedef 来隐藏这个对象实际上是什么)。 (a) 完全不透明的对象 (这种情况下要主动使用 typedef 来 **隐藏** 这个对象实际上
是什么)。
例如:“pte_t” 等不透明对象,你只能用合适的访问函数来访问它们。 例如: ``pte_t`` 等不透明对象,你只能用合适的访问函数来访问它们。
注意!不透明性和“访问函数”本身是不好的。我们使用 pte_t 等类型的原因在于真的是 .. note::
完全没有任何共用的可访问信息。
(b) 清楚的整数类型,如此,这层抽象就可以帮助消除到底是 “int” 还是 “long” 的混淆。 不透明性和 "访问函数" 本身是不好的。我们使用 pte_t 等类型的原因在于真
的是完全没有任何共用的可访问信息。
(b) 清楚的整数类型,如此,这层抽象就可以 **帮助** 消除到底是 ``int`` 还是
``long`` 的混淆。
u8/u16/u32 是完全没有问题的 typedef,不过它们更符合类别 (d) 而不是这里。 u8/u16/u32 是完全没有问题的 typedef,不过它们更符合类别 (d) 而不是这里。
再次注意!要这样做,必须事出有因。如果某个变量是 “unsigned long“,那么没有必要 .. note::
要这样做,必须事出有因。如果某个变量是 ``unsigned long`` ,那么没有必要
typedef unsigned long myflags_t; typedef unsigned long myflags_t;
不过如果有一个明确的原因,比如它在某种情况下可能会是一个 “unsigned int” 而在 不过如果有一个明确的原因,比如它在某种情况下可能会是一个 ``unsigned int``
其他情况下可能为 “unsigned long”,那么就不要犹豫,请务必使用 typedef。 而在其他情况下可能为 ``unsigned long`` ,那么就不要犹豫,请务必使用
typedef。
(c) 当你使用sparse按字面的创建一个新类型来做类型检查的时候。 (c) 当你使用 sparse 按字面的创建一个 **新** 类型来做类型检查的时候。
(d) 和标准C99类型相同的类型,在某些例外的情况下。 (d) 和标准 C99 类型相同的类型,在某些例外的情况下。
虽然让眼睛和脑筋来适应新的标准类型比如 “uint32_t” 不需要花很多时间,可是有些 虽然让眼睛和脑筋来适应新的标准类型比如 ``uint32_t`` 不需要花很多时间,可
人仍然拒绝使用它们。 是有些人仍然拒绝使用它们。
因此,Linux 特有的等同于标准类型的 “u8/u16/u32/u64” 类型和它们的有符号类型是被 因此,Linux 特有的等同于标准类型的 ``u8/u16/u32/u64`` 类型和它们的有符号
允许的——尽管在你自己的新代码中,它们不是强制要求要使用的。 类型是被允许的——尽管在你自己的新代码中,它们不是强制要求要使用的。
当编辑已经使用了某个类型集的已有代码时,你应该遵循那些代码中已经做出的选择。 当编辑已经使用了某个类型集的已有代码时,你应该遵循那些代码中已经做出的选
择。
(e) 可以在用户空间安全使用的类型。 (e) 可以在用户空间安全使用的类型。
在某些用户空间可见的结构体里,我们不能要求C99类型而且不能用上面提到的 “u32” 在某些用户空间可见的结构体里,我们不能要求 C99 类型而且不能用上面提到的
类型。因此,我们在与用户空间共享的所有结构体中使用 __u32 和类似的类型。 ``u32`` 类型。因此,我们在与用户空间共享的所有结构体中使用 __u32 和类似
的类型。
可能还有其他的情况,不过基本的规则是永远不要使用 typedef,除非你可以明确的应用上 可能还有其他的情况,不过基本的规则是 **永远不要** 使用 typedef,除非你可以明
述某个规则中的一个。 确的应用上述某个规则中的一个。
总的来说,如果一个指针或者一个结构体里的元素可以合理的被直接访问到,那么它们就不 总的来说,如果一个指针或者一个结构体里的元素可以合理的被直接访问到,那么它们
应该是一个 typedef。 就不应该是一个 typedef。
第六章:函数 6) 函数
------------------------------
函数应该简短而漂亮,并且只完成一件事情。函数应该可以一屏或者两屏显示完(我们都知 函数应该简短而漂亮,并且只完成一件事情。函数应该可以一屏或者两屏显示完 (我们
道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。 都知道 ISO/ANSI 屏幕大小是 80x24),只做一件事情,而且把它做好。
一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以,如果你有一个理论上 一个函数的最大长度是和该函数的复杂度和缩进级数成反比的。所以,如果你有一个理
很简单的只有一个很长(但是简单)的 case 语句的函数,而且你需要在每个 case 里做 论上很简单的只有一个很长 (但是简单) 的 case 语句的函数,而且你需要在每个 case
很多很小的事情,这样的函数尽管很长,但也是可以的。 里做很多很小的事情,这样的函数尽管很长,但也是可以的。
不过,如果你有一个复杂的函数,而且你怀疑一个天分不是很高的高中一年级学生可能甚至 不过,如果你有一个复杂的函数,而且你怀疑一个天分不是很高的高中一年级学生可能
搞不清楚这个函数的目的,你应该严格的遵守前面提到的长度限制。使用辅助函数,并为之 甚至搞不清楚这个函数的目的,你应该严格遵守前面提到的长度限制。使用辅助函数,
取个具描述性的名字(如果你觉得它们的性能很重要的话,可以让编译器内联它们,这样的 并为之取个具描述性的名字 (如果你觉得它们的性能很重要的话,可以让编译器内联它
效果往往会比你写一个复杂函数的效果要好。) 们,这样的效果往往会比你写一个复杂函数的效果要好。)
函数的另外一个衡量标准是本地变量的数量。此数量不应超过 5-10 个,否则你的函数就有 函数的另外一个衡量标准是本地变量的数量。此数量不应超过 5-10 个,否则你的函数
问题了。重新考虑一下你的函数,把它分拆成更小的函数。人的大脑一般可以轻松的同时跟 就有问题了。重新考虑一下你的函数,把它分拆成更小的函数。人的大脑一般可以轻松
踪 7 个不同的事物,如果再增多的话,就会糊涂了。即便你聪颖过人,你也可能会记不清你 的同时跟踪 7 个不同的事物,如果再增多的话,就会糊涂了。即便你聪颖过人,你也可
2 个星期前做过的事情。 能会记不清你 2 个星期前做过的事情。
在源文件里,使用空行隔开不同的函数。如果该函数需要被导出,它的 EXPORT* 宏应该紧贴 在源文件里,使用空行隔开不同的函数。如果该函数需要被导出,它的 **EXPORT** 宏
在它的结束大括号之下。比如: 应该紧贴在它的结束大括号之下。比如:
.. code-block:: c
int system_is_up(void) int system_is_up(void)
{ {
...@@ -336,24 +397,32 @@ C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pasca ...@@ -336,24 +397,32 @@ C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pasca
} }
EXPORT_SYMBOL(system_is_up); EXPORT_SYMBOL(system_is_up);
在函数原型中,包含函数名和它们的数据类型。虽然C语言里没有这样的要求,在 Linux 里这 在函数原型中,包含函数名和它们的数据类型。虽然 C 语言里没有这样的要求,在
是提倡的做法,因为这样可以很简单的给读者提供更多的有价值的信息。 Linux 里这是提倡的做法,因为这样可以很简单的给读者提供更多的有价值的信息。
7) 集中的函数退出途径
------------------------------
第七章:集中的函数退出途径 虽然被某些人声称已经过时,但是 goto 语句的等价物还是经常被编译器所使用,具体
形式是无条件跳转指令。
虽然被某些人声称已经过时,但是 goto 语句的等价物还是经常被编译器所使用,具体形式是 当一个函数从多个位置退出,并且需要做一些类似清理的常见操作时,goto 语句就很方
无条件跳转指令 便了。如果并不需要清理操作,那么直接 return 即可
当一个函数从多个位置退出,并且需要做一些类似清理的常见操作时,goto 语句就很方便了。 选择一个能够说明 goto 行为或它为何存在的标签名。如果 goto 要释放 ``buffer``,
如果并不需要清理操作,那么直接 return 即可。 一个不错的名字可以是 ``out_free_buffer:`` 。别去使用像 ``err1:`` 和 ``err2:``
这样的GW_BASIC 名称,因为一旦你添加或删除了 (函数的) 退出路径,你就必须对它们
重新编号,这样会难以去检验正确性。
理由是: 使用 goto 的理由是:
- 无条件语句容易理解和跟踪 - 无条件语句容易理解和跟踪
- 嵌套程度减小 - 嵌套程度减小
- 可以避免由于修改时忘记更新某个单独的退出点而导致的错误 - 可以避免由于修改时忘记更新个别的退出点而导致错误
- 减轻了编译器的工作,无需删除冗余代码;) - 让编译器省去删除冗余代码的工作 ;)
.. code-block:: c
int fun(int a) int fun(int a)
{ {
...@@ -369,41 +438,55 @@ C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pasca ...@@ -369,41 +438,55 @@ C是一个简朴的语言,你的命名也应该这样。和 Modula-2 和 Pasca
... ...
} }
result = 1; result = 1;
goto out_buffer; goto out_free_buffer;
} }
... ...
out_buffer: out_free_buffer:
kfree(buffer); kfree(buffer);
return result; return result;
} }
一个需要注意的常见错误是“一个 err 错误”,就像这样: 一个需要注意的常见错误是 ``一个 err 错误`` ,就像这样:
.. code-block:: c
err: err:
kfree(foo->bar); kfree(foo->bar);
kfree(foo); kfree(foo);
return ret; return ret;
这段代码的错误是,在某些退出路径上 “foo” 是 NULL。通常情况下,通过把它分离成两个 这段代码的错误是,在某些退出路径上 ``foo`` 是 NULL。通常情况下,通过把它分离
错误标签 “err_bar:” 和 “err_foo:” 来修复这个错误。 成两个错误标签 ``err_free_bar:`` 和 ``err_free_foo:`` 来修复这个错误:
.. code-block:: c
err_free_bar:
kfree(foo->bar);
err_free_foo:
kfree(foo);
return ret;
理想情况下,你应该模拟错误来测试所有退出路径。
第八章:注释
注释是好的,不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的:更好 8) 注释
的做法是让别人一看你的代码就可以明白,解释写的很差的代码是浪费时间。 ------------------------------
一般的,你想要你的注释告诉别人你的代码做了什么,而不是怎么做的。也请你不要把注释 注释是好的,不过有过度注释的危险。永远不要在注释里解释你的代码是如何运作的:
放在一个函数体内部:如果函数复杂到你需要独立的注释其中的一部分,你很可能需要回到 更好的做法是让别人一看你的代码就可以明白,解释写的很差的代码是浪费时间。
第六章看一看。你可以做一些小注释来注明或警告某些很聪明(或者槽糕)的做法,但不要
加太多。你应该做的,是把注释放在函数的头部,告诉人们它做了什么,也可以加上它做这
些事情的原因。
当注释内核API函数时,请使用 kernel-doc 格式。请看 一般的,你想要你的注释告诉别人你的代码做了什么,而不是怎么做的。也请你不要把
Documentation/doc-guide/和scripts/kernel-doc 以获得详细信息。 注释放在一个函数体内部:如果函数复杂到你需要独立的注释其中的一部分,你很可能
需要回到第六章看一看。你可以做一些小注释来注明或警告某些很聪明 (或者槽糕) 的
做法,但不要加太多。你应该做的,是把注释放在函数的头部,告诉人们它做了什么,
也可以加上它做这些事情的原因。
Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “// ...” 注释。 当注释内核 API 函数时,请使用 kernel-doc 格式。请看
Documentation/doc-guide/ 和 scripts/kernel-doc 以获得详细信息。
长(多行)的首选注释风格是: 长 (多行) 注释的首选风格是:
.. code-block:: c
/* /*
* This is the preferred style for multi-line * This is the preferred style for multi-line
...@@ -414,7 +497,9 @@ Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “ ...@@ -414,7 +497,9 @@ Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “
* with beginning and ending almost-blank lines. * with beginning and ending almost-blank lines.
*/ */
对于在 net/ 和 drivers/net/ 的文件,首选的长(多行)注释风格有些不同。 对于在 net/ 和 drivers/net/ 的文件,首选的长 (多行) 注释风格有些不同。
.. code-block:: c
/* The preferred comment style for files in net/ and drivers/net /* The preferred comment style for files in net/ and drivers/net
* looks like this. * looks like this.
...@@ -423,72 +508,77 @@ Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “ ...@@ -423,72 +508,77 @@ Linux的注释风格是 C89 “/* ... */” 风格。不要使用 C99 风格 “
* but there is no initial almost-blank line. * but there is no initial almost-blank line.
*/ */
注释数据也是很重要的,不管是基本类型还是衍生类型。为了方便实现这一点,每一行应只 注释数据也是很重要的,不管是基本类型还是衍生类型。为了方便实现这一点,每一行
声明一个数据(不要使用逗号来一次声明多个数据)。这样你就有空间来为每个数据写一段 应只声明一个数据 (不要使用逗号来一次声明多个数据)。这样你就有空间来为每个数据
小注释来解释它们的用途了。 写一段小注释来解释它们的用途了。
第九章:你已经把事情弄糟了 9) 你已经把事情弄糟了
------------------------------
这没什么,我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你 “GNU emacs” 能
自动帮你格式化 C 源代码,而且你也注意到了,确实是这样,不过它所使用的默认值和我们 这没什么,我们都是这样。可能你的使用了很长时间 Unix 的朋友已经告诉你
想要的相去甚远(实际上,甚至比随机打的还要差——无数个猴子在 GNU emacs 里打字永远不 ``GNU emacs`` 能自动帮你格式化 C 源代码,而且你也注意到了,确实是这样,不过它
会创造出一个好程序)(译注:请参考 Infinite Monkey Theorem) 所使用的默认值和我们想要的相去甚远 (实际上,甚至比随机打的还要差——无数个猴子
在 GNU emacs 里打字永远不会创造出一个好程序) (译注:Infinite Monkey Theorem)
所以你要么放弃 GNU emacs,要么改变它让它使用更合理的设定。要采用后一个方案,你可
以把下面这段粘贴到你的 .emacs 文件里。 所以你要么放弃 GNU emacs,要么改变它让它使用更合理的设定。要采用后一个方案,
你可以把下面这段粘贴到你的 .emacs 文件里。
(defun c-lineup-arglist-tabs-only (ignored)
"Line up argument lists by tabs, not spaces" .. code-block:: none
(let* ((anchor (c-langelem-pos c-syntactic-element))
(column (c-langelem-2nd-pos c-syntactic-element)) (defun c-lineup-arglist-tabs-only (ignored)
(offset (- (1+ column) anchor)) "Line up argument lists by tabs, not spaces"
(steps (floor offset c-basic-offset))) (let* ((anchor (c-langelem-pos c-syntactic-element))
(* (max steps 1) (column (c-langelem-2nd-pos c-syntactic-element))
c-basic-offset))) (offset (- (1+ column) anchor))
(steps (floor offset c-basic-offset)))
(add-hook 'c-mode-common-hook (* (max steps 1)
(lambda () c-basic-offset)))
;; Add kernel style
(c-add-style (add-hook 'c-mode-common-hook
"linux-tabs-only" (lambda ()
'("linux" (c-offsets-alist ;; Add kernel style
(arglist-cont-nonempty (c-add-style
c-lineup-gcc-asm-reg "linux-tabs-only"
c-lineup-arglist-tabs-only)))))) '("linux" (c-offsets-alist
(arglist-cont-nonempty
(add-hook 'c-mode-hook c-lineup-gcc-asm-reg
(lambda () c-lineup-arglist-tabs-only))))))
(let ((filename (buffer-file-name)))
;; Enable kernel mode for the appropriate files (add-hook 'c-mode-hook
(when (and filename (lambda ()
(string-match (expand-file-name "~/src/linux-trees") (let ((filename (buffer-file-name)))
filename)) ;; Enable kernel mode for the appropriate files
(setq indent-tabs-mode t) (when (and filename
(setq show-trailing-whitespace t) (string-match (expand-file-name "~/src/linux-trees")
(c-set-style "linux-tabs-only"))))) filename))
(setq indent-tabs-mode t)
这会让 emacs 在 ~/src/linux-trees 目录下的 C 源文件获得更好的内核代码风格。 (setq show-trailing-whitespace t)
(c-set-style "linux-tabs-only")))))
不过就算你尝试让 emacs 正确的格式化代码失败了,也并不意味着你失去了一切:还可以用
“indent”。 这会让 emacs 在 ``~/src/linux-trees`` 下的 C 源文件获得更好的内核代码风格。
不过,GNU indent 也有和 GNU emacs 一样有问题的设定,所以你需要给它一些命令选项。不 不过就算你尝试让 emacs 正确的格式化代码失败了,也并不意味着你失去了一切:还可
过,这还不算太糟糕,因为就算是 GNU indent 的作者也认同 K&R 的权威性(GNU 的人并不是 以用 ``indent`` 。
坏人,他们只是在这个问题上被严重的误导了),所以你只要给 indent 指定选项 “-kr -i8”
(代表 “K&R,8 个字符缩进”),或者使用 “scripts/Lindent”,这样就可以以最时髦的方式 不过,GNU indent 也有和 GNU emacs 一样有问题的设定,所以你需要给它一些命令选
缩进源代码。 项。不过,这还不算太糟糕,因为就算是 GNU indent 的作者也认同 K&R 的权威性
(GNU 的人并不是坏人,他们只是在这个问题上被严重的误导了),所以你只要给 indent
“indent” 有很多选项,特别是重新格式化注释的时候,你可能需要看一下它的手册页。不过 指定选项 ``-kr -i8`` (代表 ``K&R,8 字符缩进``),或使用 ``scripts/Lindent``
记住:“indent” 不能修正坏的编程习惯。 这样就可以以最时髦的方式缩进源代码。
``indent`` 有很多选项,特别是重新格式化注释的时候,你可能需要看一下它的手册。
第十章:Kconfig 配置文件 不过记住: ``indent`` 不能修正坏的编程习惯。
对于遍布源码树的所有 Kconfig* 配置文件来说,它们缩进方式与 C 代码相比有所不同。紧挨
在 “config” 定义下面的行缩进一个制表符,帮助信息则再多缩进 2 个空格。比如: 10) Kconfig 配置文件
------------------------------
config AUDIT
对于遍布源码树的所有 Kconfig* 配置文件来说,它们缩进方式有所不同。紧挨着
``config`` 定义的行,用一个制表符缩进,然而 help 信息的缩进则额外增加 2 个空
格。举个例子::
config AUDIT
bool "Auditing support" bool "Auditing support"
depends on NET depends on NET
help help
...@@ -497,10 +587,10 @@ config AUDIT ...@@ -497,10 +587,10 @@ config AUDIT
logging of avc messages output). Does not do system-call logging of avc messages output). Does not do system-call
auditing without CONFIG_AUDITSYSCALL. auditing without CONFIG_AUDITSYSCALL.
而那些危险的功能(比如某些文件系统的写支持)应该在它们的提示字符串里显著的声明这 而那些危险的功能 (比如某些文件系统的写支持) 应该在它们的提示字符串里显著的声
一点: 明这一点::
config ADFS_FS_RW config ADFS_FS_RW
bool "ADFS write support (DANGEROUS)" bool "ADFS write support (DANGEROUS)"
depends on ADFS_FS depends on ADFS_FS
... ...
...@@ -508,34 +598,38 @@ config ADFS_FS_RW ...@@ -508,34 +598,38 @@ config ADFS_FS_RW
要查看配置文件的完整文档,请看 Documentation/kbuild/kconfig-language.txt。 要查看配置文件的完整文档,请看 Documentation/kbuild/kconfig-language.txt。
第十一章:数据结构 11) 数据结构
------------------------------
如果一个数据结构,在创建和销毁它的单线执行环境之外可见,那么它必须要有一个引用计 如果一个数据结构,在创建和销毁它的单线执行环境之外可见,那么它必须要有一个引
数器。内核里没有垃圾收集(并且内核之外的垃圾收集慢且效率低下),这意味着你绝对需 用计数器。内核里没有垃圾收集 (并且内核之外的垃圾收集慢且效率低下),这意味着你
要记录你对这种数据结构的使用情况。 绝对需要记录你对这种数据结构的使用情况。
引用计数意味着你能够避免上锁,并且允许多个用户并行访问这个数据结构——而不需要担心 引用计数意味着你能够避免上锁,并且允许多个用户并行访问这个数据结构——而不需要
这个数据结构仅仅因为暂时不被使用就消失了,那些用户可能不过是沉睡了一阵或者做了一 担心这个数据结构仅仅因为暂时不被使用就消失了,那些用户可能不过是沉睡了一阵或
些其他事情而已。 者做了一些其他事情而已。
注意上锁不能取代引用计数。上锁是为了保持数据结构的一致性,而引用计数是一个内存管 注意上锁 **不能** 取代引用计数。上锁是为了保持数据结构的一致性,而引用计数是一
理技巧。通常二者都需要,不要把两个搞混了。 个内存管理技巧。通常二者都需要,不要把两个搞混了。
很多数据结构实际上有2级引用计数,它们通常有不同“类”的用户。子类计数器统计子类用 很多数据结构实际上有 2 级引用计数,它们通常有不同 ``类`` 的用户。子类计数器统
户的数量,每当子类计数器减至零时,全局计数器减一。 计子类用户的数量,每当子类计数器减至零时,全局计数器减一。
这种“多级引用计数”的例子可以在内存管理(“struct mm_struct”:mm_users 和 mm_count) 这种 ``多级引用计数`` 的例子可以在内存管理 (``struct mm_struct``: mm_users 和
和文件系统(“struct super_block”:s_count和s_active)中找到。 mm_count),和文件系统 (``struct super_block``: s_count 和 s_active) 中找到。
记住:如果另一个执行线索可以找到你的数据结构,但是这个数据结构没有引用计数器,这 记住:如果另一个执行线索可以找到你的数据结构,但这个数据结构没有引用计数器,
里几乎肯定是一个 bug。 里几乎肯定是一个 bug。
第十二章:宏,枚举和RTL 12) 宏,枚举和RTL
------------------------------
用于定义常量的宏的名字及枚举里的标签需要大写。 用于定义常量的宏的名字及枚举里的标签需要大写。
#define CONSTANT 0x12345 .. code-block:: c
#define CONSTANT 0x12345
在定义几个相关的常量时,最好用枚举。 在定义几个相关的常量时,最好用枚举。
...@@ -545,6 +639,8 @@ config ADFS_FS_RW ...@@ -545,6 +639,8 @@ config ADFS_FS_RW
含有多个语句的宏应该被包含在一个 do-while 代码块里: 含有多个语句的宏应该被包含在一个 do-while 代码块里:
.. code-block:: c
#define macrofun(a, b, c) \ #define macrofun(a, b, c) \
do { \ do { \
if (a == 5) \ if (a == 5) \
...@@ -555,33 +651,41 @@ config ADFS_FS_RW ...@@ -555,33 +651,41 @@ config ADFS_FS_RW
1) 影响控制流程的宏: 1) 影响控制流程的宏:
.. code-block:: c
#define FOO(x) \ #define FOO(x) \
do { \ do { \
if (blah(x) < 0) \ if (blah(x) < 0) \
return -EBUGGERED; \ return -EBUGGERED; \
} while (0) } while (0)
非常不好。它看起来像一个函数,不过却能导致“调用”它的函数退出;不要打乱读者大脑里 **非常** 不好。它看起来像一个函数,不过却能导致 ``调用`` 它的函数退出;不要打
的语法分析器。 乱读者大脑里的语法分析器。
2) 依赖于一个固定名字的本地变量的宏: 2) 依赖于一个固定名字的本地变量的宏:
.. code-block:: c
#define FOO(val) bar(index, val) #define FOO(val) bar(index, val)
可能看起来像是个不错的东西,不过它非常容易把读代码的人搞糊涂,而且容易导致看起来 可能看起来像是个不错的东西,不过它非常容易把读代码的人搞糊涂,而且容易导致看起
不相关的改动带来错误。 来不相关的改动带来错误。
3) 作为左值的带参数的宏: FOO(x) = y;如果有人把 FOO 变成一个内联函数的话,这
种用法就会出错了。
3) 作为左值的带参数的宏: FOO(x) = y;如果有人把 FOO 变成一个内联函数的话,这种用 4) 忘记了优先级:使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数
法就会出错了 的宏也要注意此类问题
4) 忘记了优先级:使用表达式定义常量的宏必须将表达式置于一对小括号之内。带参数的 .. code-block:: c
宏也要注意此类问题。
#define CONSTANT 0x4000 #define CONSTANT 0x4000
#define CONSTEXP (CONSTANT | 3) #define CONSTEXP (CONSTANT | 3)
5) 在宏里定义类似函数的本地变量时命名冲突: 5) 在宏里定义类似函数的本地变量时命名冲突:
.. code-block:: c
#define FOO(x) \ #define FOO(x) \
({ \ ({ \
typeof(x) ret; \ typeof(x) ret; \
...@@ -591,133 +695,154 @@ config ADFS_FS_RW ...@@ -591,133 +695,154 @@ config ADFS_FS_RW
ret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。 ret 是本地变量的通用名字 - __foo_ret 更不容易与一个已存在的变量冲突。
cpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL(译注:register cpp 手册对宏的讲解很详细。gcc internals 手册也详细讲解了 RTL,内核里的汇编语
transfer language),内核里的汇编语言经常用到它。 言经常用到它。
第十三章:打印内核消息 13) 打印内核消息
------------------------------
内核开发者应该是受过良好教育的。请一定注意内核信息的拼写,以给人以好的印象。不要 内核开发者应该是受过良好教育的。请一定注意内核信息的拼写,以给人以好的印象。
用不规范的单词比如 “dont”,而要用 “do not”或者 “don't”。保证这些信息简单、明了、 不要用不规范的单词比如 ``dont``,而要用 ``do not`` 或者 ``don't`` 。保证这些信
无歧义。 息简单明了,无歧义。
内核信息不必以句号(译注:英文句号,即点)结束。 内核信息不必以英文句号结束。
在小括号里打印数字 (%d) 没有任何价值,应该避免这样做。 在小括号里打印数字 (%d) 没有任何价值,应该避免这样做。
<linux/device.h> 里有一些驱动模型诊断宏,你应该使用它们,以确保信息对应于正确 <linux/device.h> 里有一些驱动模型诊断宏,你应该使用它们,以确保信息对应于正确
设备和驱动,并且被标记了正确的消息级别。这些宏有:dev_err(),dev_warn(), 的设备和驱动,并且被标记了正确的消息级别。这些宏有:dev_err(), dev_warn(),
dev_info() 等等。对于那些不和某个特定设备相关连的信息,<linux/printk.h> 定义 dev_info() 等等。对于那些不和某个特定设备相关连的信息,<linux/printk.h> 定义
pr_notice(),pr_info(),pr_warn(),pr_err() 和其他。 了 pr_notice(), pr_info(), pr_warn(), pr_err() 和其他。
写出好的调试信息可以是一个很大的挑战;一旦你写出后,这些信息在远程除错时能提供极大 写出好的调试信息可以是一个很大的挑战;一旦你写出后,这些信息在远程除错时能提
的帮助。然而打印调试信息的处理方式同打印非调试信息不同。其他 pr_XXX() 函数能无条件地 供极大的帮助。然而打印调试信息的处理方式同打印非调试信息不同。其他 pr_XXX()
打印,pr_debug() 却不;默认情况下它不会被编译,除非定义了 DEBUG 或设定了 函数能无条件地打印,pr_debug() 却不;默认情况下它不会被编译,除非定义了 DEBUG
CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg(),一个相关约定是在一个已经开启了 或设定了 CONFIG_DYNAMIC_DEBUG。实际这同样是为了 dev_dbg(),一个相关约定是在一
DEBUG 时,使用 VERBOSE_DEBUG 来添加 dev_vdbg()。 个已经开启了 DEBUG 时,使用 VERBOSE_DEBUG 来添加 dev_vdbg()。
许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面;在其他 许多子系统拥有 Kconfig 调试选项来开启 -DDEBUG 在对应的 Makefile 里面;在其他
情况下,特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时,例如,如果 情况下,特殊文件使用 #define DEBUG。当一条调试信息需要被无条件打印时,例如,
已经包含一个调试相关的 #ifdef 条件,printk(KERN_DEBUG ...) 就可被使用。 如果已经包含一个调试相关的 #ifdef 条件,printk(KERN_DEBUG ...) 就可被使用。
第十四章:分配内存 14) 分配内存
------------------------------
内核提供了下面的一般用途的内存分配函数: 内核提供了下面的一般用途的内存分配函数:
kmalloc(),kzalloc(),kmalloc_array(),kcalloc(),vmalloc() 和 vzalloc()。 kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() 和 vzalloc()。
请参考 API 文档以获取有关它们的详细信息。 请参考 API 文档以获取有关它们的详细信息。
传递结构体大小的首选形式是这样的: 传递结构体大小的首选形式是这样的:
.. code-block:: c
p = kmalloc(sizeof(*p), ...); p = kmalloc(sizeof(*p), ...);
另外一种传递方式中,sizeof 的操作数是结构体的名字,这样会降低可读性,并且可能会引 另外一种传递方式中,sizeof 的操作数是结构体的名字,这样会降低可读性,并且可能
入 bug。有可能指针变量类型被改变时,而对应的传递给内存分配函数的 sizeof 的结果不变。 会引入 bug。有可能指针变量类型被改变时,而对应的传递给内存分配函数的 sizeof
的结果不变。
强制转换一个 void 指针返回值是多余的。C 语言本身保证了从 void 指针到其他任何指针类型 强制转换一个 void 指针返回值是多余的。C 语言本身保证了从 void 指针到其他任何
的转换是没有问题的。 指针类型的转换是没有问题的。
分配一个数组的首选形式是这样的: 分配一个数组的首选形式是这样的:
.. code-block:: c
p = kmalloc_array(n, sizeof(...), ...); p = kmalloc_array(n, sizeof(...), ...);
分配一个零长数组的首选形式是这样的: 分配一个零长数组的首选形式是这样的:
.. code-block:: c
p = kcalloc(n, sizeof(...), ...); p = kcalloc(n, sizeof(...), ...);
两种形式检查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。 两种形式检查分配大小 n * sizeof(...) 的溢出,如果溢出返回 NULL。
第十五章:内联弊病 15) 内联弊病
------------------------------
有一个常见的误解是内联函数是 gcc 提供的可以让代码运行更快的一个选项。虽然使用内联 有一个常见的误解是 ``内联`` 是 gcc 提供的可以让代码运行更快的一个选项。虽然使
函数有时候是恰当的(比如作为一种替代宏的方式,请看第十二章),不过很多情况下不是 用内联函数有时候是恰当的 (比如作为一种替代宏的方式,请看第十二章),不过很多情
这样。inline 关键字的过度使用会使内核变大,从而使整个系统运行速度变慢。因为大内核 况下不是这样。inline 的过度使用会使内核变大,从而使整个系统运行速度变慢。
会占用更多的指令高速缓存(译注:一级缓存通常是指令缓存和数据缓存分开的)而且会导 因为体积大内核会占用更多的指令高速缓存,而且会导致 pagecache 的可用内存减少。
致 pagecache 的可用内存减少。想象一下,一次pagecache未命中就会导致一次磁盘寻址, 想象一下,一次 pagecache 未命中就会导致一次磁盘寻址,将耗时 5 毫秒。5 毫秒的
将耗时 5 毫秒。5 毫秒的时间内 CPU 能执行很多很多指令。 时间内 CPU 能执行很多很多指令。
一个基本的原则是如果一个函数有 3 行以上,就不要把它变成内联函数。这个原则的一个例 一个基本的原则是如果一个函数有 3 行以上,就不要把它变成内联函数。这个原则的一
外是,如果你知道某个参数是一个编译时常量,而且因为这个常量你确定编译器在编译时能 个例外是,如果你知道某个参数是一个编译时常量,而且因为这个常量你确定编译器在
优化掉你的函数的大部分代码,那仍然可以给它加上 inline 关键字。kmalloc() 内联函数就 编译时能优化掉你的函数的大部分代码,那仍然可以给它加上 inline 关键字。
是一个很好的例子。 kmalloc() 内联函数就是一个很好的例子。
人们经常主张给 static 的而且只用了一次的函数加上 inline,如此不会有任何损失,因为没 人们经常主张给 static 的而且只用了一次的函数加上 inline,如此不会有任何损失,
有什么好权衡的。虽然从技术上说这是正确的,但是实际上这种情况下即使不加 inline gcc 因为没有什么好权衡的。虽然从技术上说这是正确的,但是实际上这种情况下即使不加
也可以自动使其内联。而且其他用户可能会要求移除 inline,由此而来的争论会抵消 inline inline gcc 也可以自动使其内联。而且其他用户可能会要求移除 inline,由此而来的
自身的潜在价值,得不偿失。 争论会抵消 inline 自身的潜在价值,得不偿失。
第十六章:函数返回值及命名 16) 函数返回值及命名
------------------------------
函数可以返回多种不同类型的值,最常见的一种是表明函数执行成功或者失败的值。这样 函数可以返回多种不同类型的值,最常见的一种是表明函数执行成功或者失败的值。这样
的一个值可以表示为一个错误代码整数(-Exxx=失败,0=成功)或者一个“成功”布尔值( 的一个值可以表示为一个错误代码整数 (-Exxx=失败,0=成功) 或者一个 ``成功``
0=失败,非0=成功) 布尔值 (0=失败,非0=成功)
混合使用这两种表达方式是难于发现的 bug 的来源。如果 C 语言本身严格区分整形和布尔型变 混合使用这两种表达方式是难于发现的 bug 的来源。如果 C 语言本身严格区分整形和
量,那么编译器就能够帮我们发现这些错误……不过 C 语言不区分。为了避免产生这种 bug,请 布尔型变量,那么编译器就能够帮我们发现这些错误... 不过 C 语言不区分。为了避免
遵循下面的惯例: 产生这种 bug,请遵循下面的惯例::
如果函数的名字是一个动作或者强制性的命令,那么这个函数应该返回错误代码整 如果函数的名字是一个动作或者强制性的命令,那么这个函数应该返回错误代
数。如果是一个判断,那么函数应该返回一个“成功”布尔值。 码整数。如果是一个判断,那么函数应该返回一个 "成功" 布尔值。
比如,“add work” 是一个命令,所以 add_work() 函数在成功时返回 0,在失败时返回 -EBUSY。 比如, ``add work`` 是一个命令,所以 add_work() 在成功时返回 0,在失败时返回
类似的,因为 “PCI device present” 是一个判断,所以 pci_dev_present() 函数在成功找到 -EBUSY。类似的,因为 ``PCI device present`` 是一个判断,所以 pci_dev_present()
一个匹配的设备时应该返回 1,如果找不到时应该返回 0。 在成功找到一个匹配的设备时应该返回 1,如果找不到时应该返回 0。
所有导出(译注:EXPORT)的函数都必须遵守这个惯例,所有的公共函数也都应该如此。私 所有 EXPORTed 函数都必须遵守这个惯例,所有的公共函数也都应该如此。私有
有(static)函数不需要如此,但是我们也推荐这样做。 (static) 函数不需要如此,但是我们也推荐这样做。
返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的,他们 返回值是实际计算结果而不是计算是否成功的标志的函数不受此惯例的限制。一般的,
通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数,他们使用 他们通过返回一些正常值范围之外的结果来表示出错。典型的例子是返回指针的函数,
NULL 或者 ERR_PTR 机制来报告错误。 他们使用 NULL 或者 ERR_PTR 机制来报告错误。
第十七章:不要重新发明内核宏 17) 不要重新发明内核宏
------------------------------
头文件 include/linux/kernel.h 包含了一些宏,你应该使用它们,而不要自己写一些它们的 头文件 include/linux/kernel.h 包含了一些宏,你应该使用它们,而不要自己写一些
变种。比如,如果你需要计算一个数组的长度,使用这个宏 它们的变种。比如,如果你需要计算一个数组的长度,使用这个宏
.. code-block:: c
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
类似的,如果你要计算某结构体成员的大小,使用 类似的,如果你要计算某结构体成员的大小,使用
.. code-block:: c
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以自己看看 还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以
那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应在你的代码里 自己看看那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应
自己重新定义。 在你的代码里自己重新定义。
第十八章:编辑器模式行和其他需要罗嗦的事情 18) 编辑器模式行和其他需要罗嗦的事情
--------------------------------------------------
有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如,emacs 有一些编辑器可以解释嵌入在源文件里的由一些特殊标记标明的配置信息。比如,emacs
能够解释被标记成这样的行: 能够解释被标记成这样的行:
.. code-block:: c
-*- mode: c -*- -*- mode: c -*-
或者这样的: 或者这样的:
.. code-block:: c
/* /*
Local Variables: Local Variables:
compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c" compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
...@@ -726,73 +851,85 @@ NULL 或者 ERR_PTR 机制来报告错误。 ...@@ -726,73 +851,85 @@ NULL 或者 ERR_PTR 机制来报告错误。
Vim 能够解释这样的标记: Vim 能够解释这样的标记:
.. code-block:: c
/* vim:set sw=8 noet */ /* vim:set sw=8 noet */
不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置,你的源文件不应 不要在源代码中包含任何这样的内容。每个人都有他自己的编辑器配置,你的源文件不
该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制的模 应该覆盖别人的配置。这包括有关缩进和模式配置的标记。人们可以使用他们自己定制
式,或者使用其他可以产生正确的缩进的巧妙方法。 的模式,或者使用其他可以产生正确的缩进的巧妙方法。
19) 内联汇编
------------------------------
第十九章:内联汇编 在特定架构的代码中,你可能需要内联汇编与 CPU 和平台相关功能连接。需要这么做时
就不要犹豫。然而,当 C 可以完成工作时,不要平白无故地使用内联汇编。在可能的情
况下,你可以并且应该用 C 和硬件沟通。
在特定架构的代码中,你也许需要内联汇编来使用 CPU 接口和平台相关功能。在需要 请考虑去写捆绑通用位元 (wrap common bits) 的内联汇编的简单辅助函数,别去重复
这么做时,不要犹豫。然而,当 C 可以完成工作时,不要无端地使用内联汇编。如果 地写下只有细微差异内联汇编。记住内联汇编可以使用 C 参数。
可能,你可以并且应该用 C 和硬件交互。
考虑去写通用一点的内联汇编作为简明的辅助函数,而不是重复写下它们的细节。记住 大型,有一定复杂度的汇编函数应该放在 .S 文件内,用相应的 C 原型定义在 C 头文
内联汇编可以使用 C 参数 件中。汇编函数的 C 原型应该使用 ``asmlinkage``
大而特殊的汇编函数应该放在 .S 文件中,对应 C 的原型定义在 C 头文件中。汇编 你可能需要把汇编语句标记为 volatile,用来阻止 GCC 在没发现任何副作用后就把它
函数的 C 原型应该使用 “asmlinkage” 移除了。你不必总是这样做,尽管,这不必要的举动会限制优化
你可能需要将你的汇编语句标记为 volatile,来阻止 GCC 在没发现任何副作用后就 在写一个包含多条指令的单个内联汇编语句时,把每条指令用引号分割而且各占一行,
移除了它。你不必总是这样做,虽然,这样可以限制不必要的优化。 除了最后一条指令外,在每个指令结尾加上 \n\t,让汇编输出时可以正确地缩进下一条
指令:
在写一个包含多条指令的单个内联汇编语句时,把每条指令用引号字符串分离,并写在 .. code-block:: c
单独一行,在每个字符串结尾,除了 \n\t 结尾之外,在汇编输出中适当地缩进下
一条指令:
asm ("magic %reg1, #42\n\t" asm ("magic %reg1, #42\n\t"
"more_magic %reg2, %reg3" "more_magic %reg2, %reg3"
: /* outputs */ : /* inputs */ : /* clobbers */); : /* outputs */ : /* inputs */ : /* clobbers */);
第二十章:条件编译 20) 条件编译
------------------------------
只要可能,就不要在 .c 文件里面使用预处理条件;这样做让代码更难阅读并且逻辑难以 只要可能,就不要在 .c 文件里面使用预处理条件 (#if, #ifdef);这样做让代码更难
跟踪。替代方案是,在头文件定义函数在这些 .c 文件中使用这类的条件表达式,提供空 阅读并且更难去跟踪逻辑。替代方案是,在头文件中用预处理条件提供给那些 .c 文件
操作的桩版本(译注:桩程序,是指用来替换一部分功能的程序段)在 #else 情况下, 使用,再给 #else 提供一个空桩 (no-op stub) 版本,然后在 .c 文件内无条件地调用
再从 .c 文件中无条件地调用这些函数。编译器会避免生成任何桩调用的代码,产生一致 那些 (定义在头文件内的) 函数。这样做,编译器会避免为桩函数 (stub) 的调用生成
的结果,但逻辑将更加清晰。 任何代码,产生的结果是相同的,但逻辑将更加清晰。
宁可编译整个函数,而不是部分函数或部分表达式。而不是在一个表达式添加 ifdef, 最好倾向于编译整个函数,而不是函数的一部分或表达式的一部分。与其放一个 ifdef
解析部分或全部表达式到一个单独的辅助函数,并应用条件到该函数内。 在表达式内,不如分解出部分或全部表达式,放进一个单独的辅助函数,并应用预处理
条件到这个辅助函数内。
如果你有一个在特定配置中可能是未使用的函数或变量,编译器将警告它定义了但未使用, 如果你有一个在特定配置中,可能变成未使用的函数或变量,编译器会警告它定义了但
标记这个定义为 __maybe_unused 而不是将它包含在一个预处理条件中。(然而,如果 未使用,把它标记为 __maybe_unused 而不是将它包含在一个预处理条件中。(然而,如
一个函数或变量总是未使用的,就直接删除它。) 果一个函数或变量总是未使用,就直接删除它。)
在代码中,可能的情况下,使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔 在代码中,尽可能地使用 IS_ENABLED 宏来转化某个 Kconfig 标记为 C 的布尔
表达式,并在正常的 C 条件中使用它: 表达式,并在一般的 C 条件中使用它:
.. code-block:: c
if (IS_ENABLED(CONFIG_SOMETHING)) { if (IS_ENABLED(CONFIG_SOMETHING)) {
... ...
} }
编译器会无条件地做常数合并,就像使用 #ifdef 那样,包含或排除代码块,所以这不会 编译器会做常量折叠,然后就像使用 #ifdef 那样去包含或排除代码块,所以这不会带
带来任何运行时开销。然而,这种方法依旧允许 C 编译器查看块内的代码,并检查它的正确 来任何运行时开销。然而,这种方法依旧允许 C 编译器查看块内的代码,并检查它的正
性(语法,类型,符号引用,等等)。因此,如果条件不满足,代码块内的引用符号将不存在, 确性 (语法,类型,符号引用,等等)。因此,如果条件不满足,代码块内的引用符号就
你必须继续使用 #ifdef。 不存在时,你还是必须去用 #ifdef。
在任何有意义的 #if 或 #ifdef 块的末尾 (超过几行的),在 #endif 同一行的后面写下
注解,注释这个条件表达式。例如:
在任何有意义的 #if 或 #ifdef 块的末尾(超过几行),在 #endif 同一行的后面写下 .. code-block:: c
注释,指出该条件表达式被使用。例如:
#ifdef CONFIG_SOMETHING #ifdef CONFIG_SOMETHING
... ...
#endif /* CONFIG_SOMETHING */ #endif /* CONFIG_SOMETHING */
附录 I:参考 附录 I) 参考
-------------------
The C Programming Language, 第二版 The C Programming Language, 第二版
作者:Brian W. Kernighan 和 Denni M. Ritchie. 作者:Brian W. Kernighan 和 Denni M. Ritchie.
...@@ -807,7 +944,7 @@ ISBN 0-201-61586-X. ...@@ -807,7 +944,7 @@ ISBN 0-201-61586-X.
GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent, GNU 手册 - 遵循 K&R 标准和此文本 - cpp, gcc, gcc internals and indent,
都可以从 http://www.gnu.org/manual/ 找到 都可以从 http://www.gnu.org/manual/ 找到
WG14是C语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/ WG14 是 C 语言的国际标准化工作组,URL: http://www.open-std.org/JTC1/SC22/WG14/
Kernel process/coding-style.rst,作者 greg@kroah.com 发表于OLS 2002: Kernel process/coding-style.rst,作者 greg@kroah.com 发表于 OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
.. raw:: latex
\renewcommand\thesection*
\renewcommand\thesubsection*
Chinese translations
====================
.. toctree::
:maxdepth: 1
coding-style
...@@ -543,7 +543,7 @@ relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm. ...@@ -543,7 +543,7 @@ relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
When a USB 3.0 lpm-capable device is plugged in to a When a USB 3.0 lpm-capable device is plugged in to a
xHCI host which supports link PM, it will check if U1 xHCI host which supports link PM, it will check if U1
and U2 exit latencies have been set in the BOS and U2 exit latencies have been set in the BOS
descriptor; if the check is is passed and the host descriptor; if the check is passed and the host
supports USB3 hardware LPM, USB3 hardware LPM will be supports USB3 hardware LPM, USB3 hardware LPM will be
enabled for the device and these files will be created. enabled for the device and these files will be created.
The files hold a string value (enable or disable) The files hold a string value (enable or disable)
......
...@@ -296,7 +296,7 @@ thp_split_page is incremented every time a huge page is split into base ...@@ -296,7 +296,7 @@ thp_split_page is incremented every time a huge page is split into base
reason is that a huge page is old and is being reclaimed. reason is that a huge page is old and is being reclaimed.
This action implies splitting all PMD the page mapped with. This action implies splitting all PMD the page mapped with.
thp_split_page_failed is is incremented if kernel fails to split huge thp_split_page_failed is incremented if kernel fails to split huge
page. This can happen if the page was pinned by somebody. page. This can happen if the page was pinned by somebody.
thp_deferred_split_page is incremented when a huge page is put onto split thp_deferred_split_page is incremented when a huge page is put onto split
......
...@@ -1446,7 +1446,7 @@ $(help-board-dirs): help-%: ...@@ -1446,7 +1446,7 @@ $(help-board-dirs): help-%:
# Documentation targets # Documentation targets
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
DOC_TARGETS := xmldocs sgmldocs psdocs latexdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs DOC_TARGETS := xmldocs sgmldocs psdocs latexdocs pdfdocs htmldocs mandocs installmandocs epubdocs cleandocs linkcheckdocs
PHONY += $(DOC_TARGETS) PHONY += $(DOC_TARGETS)
$(DOC_TARGETS): scripts_basic FORCE $(DOC_TARGETS): scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype $(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype
......
...@@ -64,24 +64,7 @@ typedef struct pm_message { ...@@ -64,24 +64,7 @@ typedef struct pm_message {
} pm_message_t; } pm_message_t;
/** /**
* struct dev_pm_ops - device PM callbacks * struct dev_pm_ops - device PM callbacks.
*
* Several device power state transitions are externally visible, affecting
* the state of pending I/O queues and (for drivers that touch hardware)
* interrupts, wakeups, DMA, and other hardware state. There may also be
* internal transitions to various low-power modes which are transparent
* to the rest of the driver stack (such as a driver that's ON gating off
* clocks which are not in active use).
*
* The externally visible transitions are handled with the help of callbacks
* included in this structure in such a way that two levels of callbacks are
* involved. First, the PM core executes callbacks provided by PM domains,
* device types, classes and bus types. They are the subsystem-level callbacks
* supposed to execute callbacks provided by device drivers, although they may
* choose not to do that. If the driver callbacks are executed, they have to
* collaborate with the subsystem-level callbacks to achieve the goals
* appropriate for the given system transition, given transition phase and the
* subsystem the device belongs to.
* *
* @prepare: The principal role of this callback is to prevent new children of * @prepare: The principal role of this callback is to prevent new children of
* the device from being registered after it has returned (the driver's * the device from being registered after it has returned (the driver's
...@@ -240,34 +223,6 @@ typedef struct pm_message { ...@@ -240,34 +223,6 @@ typedef struct pm_message {
* driver's interrupt handler, which is guaranteed not to run while * driver's interrupt handler, which is guaranteed not to run while
* @restore_noirq() is being executed. Analogous to @resume_noirq(). * @restore_noirq() is being executed. Analogous to @resume_noirq().
* *
* All of the above callbacks, except for @complete(), return error codes.
* However, the error codes returned by the resume operations, @resume(),
* @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq(), do
* not cause the PM core to abort the resume transition during which they are
* returned. The error codes returned in those cases are only printed by the PM
* core to the system logs for debugging purposes. Still, it is recommended
* that drivers only return error codes from their resume methods in case of an
* unrecoverable failure (i.e. when the device being handled refuses to resume
* and becomes unusable) to allow us to modify the PM core in the future, so
* that it can avoid attempting to handle devices that failed to resume and
* their children.
*
* It is allowed to unregister devices while the above callbacks are being
* executed. However, a callback routine must NOT try to unregister the device
* it was called for, although it may unregister children of that device (for
* example, if it detects that a child was unplugged while the system was
* asleep).
*
* Refer to Documentation/power/admin-guide/devices.rst for more information about the role
* of the above callbacks in the system suspend process.
*
* There also are callbacks related to runtime power management of devices.
* Again, these callbacks are executed by the PM core only for subsystems
* (PM domains, device types, classes and bus types) and the subsystem-level
* callbacks are supposed to invoke the driver callbacks. Moreover, the exact
* actions to be performed by a device driver's callbacks generally depend on
* the platform and subsystem the device belongs to.
*
* @runtime_suspend: Prepare the device for a condition in which it won't be * @runtime_suspend: Prepare the device for a condition in which it won't be
* able to communicate with the CPU(s) and RAM due to power management. * able to communicate with the CPU(s) and RAM due to power management.
* This need not mean that the device should be put into a low-power state. * This need not mean that the device should be put into a low-power state.
...@@ -287,11 +242,51 @@ typedef struct pm_message { ...@@ -287,11 +242,51 @@ typedef struct pm_message {
* Check these conditions, and return 0 if it's appropriate to let the PM * Check these conditions, and return 0 if it's appropriate to let the PM
* core queue a suspend request for the device. * core queue a suspend request for the device.
* *
* Refer to Documentation/power/runtime_pm.txt for more information about the * Several device power state transitions are externally visible, affecting
* role of the above callbacks in device runtime power management. * the state of pending I/O queues and (for drivers that touch hardware)
* interrupts, wakeups, DMA, and other hardware state. There may also be
* internal transitions to various low-power modes which are transparent
* to the rest of the driver stack (such as a driver that's ON gating off
* clocks which are not in active use).
* *
* The externally visible transitions are handled with the help of callbacks
* included in this structure in such a way that, typically, two levels of
* callbacks are involved. First, the PM core executes callbacks provided by PM
* domains, device types, classes and bus types. They are the subsystem-level
* callbacks expected to execute callbacks provided by device drivers, although
* they may choose not to do that. If the driver callbacks are executed, they
* have to collaborate with the subsystem-level callbacks to achieve the goals
* appropriate for the given system transition, given transition phase and the
* subsystem the device belongs to.
*
* All of the above callbacks, except for @complete(), return error codes.
* However, the error codes returned by @resume(), @thaw(), @restore(),
* @resume_noirq(), @thaw_noirq(), and @restore_noirq(), do not cause the PM
* core to abort the resume transition during which they are returned. The
* error codes returned in those cases are only printed to the system logs for
* debugging purposes. Still, it is recommended that drivers only return error
* codes from their resume methods in case of an unrecoverable failure (i.e.
* when the device being handled refuses to resume and becomes unusable) to
* allow the PM core to be modified in the future, so that it can avoid
* attempting to handle devices that failed to resume and their children.
*
* It is allowed to unregister devices while the above callbacks are being
* executed. However, a callback routine MUST NOT try to unregister the device
* it was called for, although it may unregister children of that device (for
* example, if it detects that a child was unplugged while the system was
* asleep).
*
* There also are callbacks related to runtime power management of devices.
* Again, as a rule these callbacks are executed by the PM core for subsystems
* (PM domains, device types, classes and bus types) and the subsystem-level
* callbacks are expected to invoke the driver callbacks. Moreover, the exact
* actions to be performed by a device driver's callbacks generally depend on
* the platform and subsystem the device belongs to.
*
* Refer to Documentation/power/runtime_pm.txt for more information about the
* role of the @runtime_suspend(), @runtime_resume() and @runtime_idle()
* callbacks in device runtime power management.
*/ */
struct dev_pm_ops { struct dev_pm_ops {
int (*prepare)(struct device *dev); int (*prepare)(struct device *dev);
void (*complete)(struct device *dev); void (*complete)(struct device *dev);
...@@ -391,7 +386,7 @@ const struct dev_pm_ops name = { \ ...@@ -391,7 +386,7 @@ const struct dev_pm_ops name = { \
SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
} }
/** /*
* PM_EVENT_ messages * PM_EVENT_ messages
* *
* The following PM_EVENT_ messages are defined for the internal use of the PM * The following PM_EVENT_ messages are defined for the internal use of the PM
...@@ -487,7 +482,7 @@ const struct dev_pm_ops name = { \ ...@@ -487,7 +482,7 @@ const struct dev_pm_ops name = { \
#define PMSG_IS_AUTO(msg) (((msg).event & PM_EVENT_AUTO) != 0) #define PMSG_IS_AUTO(msg) (((msg).event & PM_EVENT_AUTO) != 0)
/** /*
* Device run-time power management status. * Device run-time power management status.
* *
* These status labels are used internally by the PM core to indicate the * These status labels are used internally by the PM core to indicate the
...@@ -517,7 +512,7 @@ enum rpm_status { ...@@ -517,7 +512,7 @@ enum rpm_status {
RPM_SUSPENDING, RPM_SUSPENDING,
}; };
/** /*
* Device run-time power management request types. * Device run-time power management request types.
* *
* RPM_REQ_NONE Do nothing. * RPM_REQ_NONE Do nothing.
...@@ -616,15 +611,18 @@ extern void update_pm_runtime_accounting(struct device *dev); ...@@ -616,15 +611,18 @@ extern void update_pm_runtime_accounting(struct device *dev);
extern int dev_pm_get_subsys_data(struct device *dev); extern int dev_pm_get_subsys_data(struct device *dev);
extern void dev_pm_put_subsys_data(struct device *dev); extern void dev_pm_put_subsys_data(struct device *dev);
/* /**
* Power domains provide callbacks that are executed during system suspend, * struct dev_pm_domain - power management domain representation.
* hibernation, system resume and during runtime PM transitions along with
* subsystem-level and driver-level callbacks.
* *
* @ops: Power management operations associated with this domain.
* @detach: Called when removing a device from the domain. * @detach: Called when removing a device from the domain.
* @activate: Called before executing probe routines for bus types and drivers. * @activate: Called before executing probe routines for bus types and drivers.
* @sync: Called after successful driver probe. * @sync: Called after successful driver probe.
* @dismiss: Called after unsuccessful driver probe and after driver removal. * @dismiss: Called after unsuccessful driver probe and after driver removal.
*
* Power domains provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions instead of
* subsystem-level and driver-level callbacks.
*/ */
struct dev_pm_domain { struct dev_pm_domain {
struct dev_pm_ops ops; struct dev_pm_ops ops;
......
...@@ -199,12 +199,12 @@ EOF ...@@ -199,12 +199,12 @@ EOF
# 'funcname()' - function # 'funcname()' - function
# '$ENVVAR' - environmental variable # '$ENVVAR' - environmental variable
# '&struct_name' - name of a structure (up to two words including 'struct') # '&struct_name' - name of a structure (up to two words including 'struct')
# '&struct_name.member' - name of a structure member
# '@parameter' - name of a parameter # '@parameter' - name of a parameter
# '%CONST' - name of a constant. # '%CONST' - name of a constant.
## init lots of data ## init lots of data
my $errors = 0; my $errors = 0;
my $warnings = 0; my $warnings = 0;
my $anon_struct_union = 0; my $anon_struct_union = 0;
...@@ -214,14 +214,19 @@ my $type_constant = '\%([-_\w]+)'; ...@@ -214,14 +214,19 @@ my $type_constant = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)'; my $type_func = '(\w+)\(\)';
my $type_param = '\@(\w+(\.\.\.)?)'; my $type_param = '\@(\w+(\.\.\.)?)';
my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
my $type_struct = '\&((struct\s*)*[_\w]+)';
my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
my $type_env = '(\$\w+)'; my $type_env = '(\$\w+)';
my $type_enum_full = '\&(enum)\s*([_\w]+)'; my $type_enum = '\&(enum\s*([_\w]+))';
my $type_struct_full = '\&(struct)\s*([_\w]+)'; my $type_struct = '\&(struct\s*([_\w]+))';
my $type_typedef_full = '\&(typedef)\s*([_\w]+)'; my $type_typedef = '\&(typedef\s*([_\w]+))';
my $type_union_full = '\&(union)\s*([_\w]+)'; my $type_union = '\&(union\s*([_\w]+))';
my $type_member = '\&([_\w]+)((\.|->)[_\w]+)'; my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
my $type_fallback = '\&([_\w]+)';
my $type_enum_xml = '\&amp;(enum\s*([_\w]+))';
my $type_struct_xml = '\&amp;(struct\s*([_\w]+))';
my $type_typedef_xml = '\&amp;(typedef\s*([_\w]+))';
my $type_union_xml = '\&amp;(union\s*([_\w]+))';
my $type_member_xml = '\&amp;([_\w]+)(\.|-\&gt;)([_\w]+)';
my $type_fallback_xml = '\&amp([_\w]+)';
my $type_member_func = $type_member . '\(\)'; my $type_member_func = $type_member . '\(\)';
# Output conversion substitutions. # Output conversion substitutions.
...@@ -231,9 +236,14 @@ my $type_member_func = $type_member . '\(\)'; ...@@ -231,9 +236,14 @@ my $type_member_func = $type_member . '\(\)';
my @highlights_html = ( my @highlights_html = (
[$type_constant, "<i>\$1</i>"], [$type_constant, "<i>\$1</i>"],
[$type_func, "<b>\$1</b>"], [$type_func, "<b>\$1</b>"],
[$type_enum_xml, "<i>\$1</i>"],
[$type_struct_xml, "<i>\$1</i>"], [$type_struct_xml, "<i>\$1</i>"],
[$type_typedef_xml, "<i>\$1</i>"],
[$type_union_xml, "<i>\$1</i>"],
[$type_env, "<b><i>\$1</i></b>"], [$type_env, "<b><i>\$1</i></b>"],
[$type_param, "<tt><b>\$1</b></tt>"] [$type_param, "<tt><b>\$1</b></tt>"],
[$type_member_xml, "<tt><i>\$1</i>\$2\$3</tt>"],
[$type_fallback_xml, "<i>\$1</i>"]
); );
my $local_lt = "\\\\\\\\lt:"; my $local_lt = "\\\\\\\\lt:";
my $local_gt = "\\\\\\\\gt:"; my $local_gt = "\\\\\\\\gt:";
...@@ -243,9 +253,14 @@ my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" ...@@ -243,9 +253,14 @@ my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
my @highlights_html5 = ( my @highlights_html5 = (
[$type_constant, "<span class=\"const\">\$1</span>"], [$type_constant, "<span class=\"const\">\$1</span>"],
[$type_func, "<span class=\"func\">\$1</span>"], [$type_func, "<span class=\"func\">\$1</span>"],
[$type_enum_xml, "<span class=\"enum\">\$1</span>"],
[$type_struct_xml, "<span class=\"struct\">\$1</span>"], [$type_struct_xml, "<span class=\"struct\">\$1</span>"],
[$type_typedef_xml, "<span class=\"typedef\">\$1</span>"],
[$type_union_xml, "<span class=\"union\">\$1</span>"],
[$type_env, "<span class=\"env\">\$1</span>"], [$type_env, "<span class=\"env\">\$1</span>"],
[$type_param, "<span class=\"param\">\$1</span>]"] [$type_param, "<span class=\"param\">\$1</span>]"],
[$type_member_xml, "<span class=\"literal\"><span class=\"struct\">\$1</span>\$2<span class=\"member\">\$3</span></span>"],
[$type_fallback_xml, "<span class=\"struct\">\$1</span>"]
); );
my $blankline_html5 = $local_lt . "br /" . $local_gt; my $blankline_html5 = $local_lt . "br /" . $local_gt;
...@@ -253,10 +268,15 @@ my $blankline_html5 = $local_lt . "br /" . $local_gt; ...@@ -253,10 +268,15 @@ my $blankline_html5 = $local_lt . "br /" . $local_gt;
my @highlights_xml = ( my @highlights_xml = (
["([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>"], ["([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>"],
[$type_constant, "<constant>\$1</constant>"], [$type_constant, "<constant>\$1</constant>"],
[$type_enum_xml, "<type>\$1</type>"],
[$type_struct_xml, "<structname>\$1</structname>"], [$type_struct_xml, "<structname>\$1</structname>"],
[$type_typedef_xml, "<type>\$1</type>"],
[$type_union_xml, "<structname>\$1</structname>"],
[$type_param, "<parameter>\$1</parameter>"], [$type_param, "<parameter>\$1</parameter>"],
[$type_func, "<function>\$1</function>"], [$type_func, "<function>\$1</function>"],
[$type_env, "<envar>\$1</envar>"] [$type_env, "<envar>\$1</envar>"],
[$type_member_xml, "<literal><structname>\$1</structname>\$2<structfield>\$3</structfield></literal>"],
[$type_fallback_xml, "<structname>\$1</structname>"]
); );
my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n"; my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
...@@ -264,9 +284,14 @@ my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $loca ...@@ -264,9 +284,14 @@ my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $loca
my @highlights_gnome = ( my @highlights_gnome = (
[$type_constant, "<replaceable class=\"option\">\$1</replaceable>"], [$type_constant, "<replaceable class=\"option\">\$1</replaceable>"],
[$type_func, "<function>\$1</function>"], [$type_func, "<function>\$1</function>"],
[$type_enum, "<type>\$1</type>"],
[$type_struct, "<structname>\$1</structname>"], [$type_struct, "<structname>\$1</structname>"],
[$type_typedef, "<type>\$1</type>"],
[$type_union, "<structname>\$1</structname>"],
[$type_env, "<envar>\$1</envar>"], [$type_env, "<envar>\$1</envar>"],
[$type_param, "<parameter>\$1</parameter>" ] [$type_param, "<parameter>\$1</parameter>" ],
[$type_member, "<literal><structname>\$1</structname>\$2<structfield>\$3</structfield></literal>"],
[$type_fallback, "<structname>\$1</structname>"]
); );
my $blankline_gnome = "</para><para>\n"; my $blankline_gnome = "</para><para>\n";
...@@ -274,8 +299,13 @@ my $blankline_gnome = "</para><para>\n"; ...@@ -274,8 +299,13 @@ my $blankline_gnome = "</para><para>\n";
my @highlights_man = ( my @highlights_man = (
[$type_constant, "\$1"], [$type_constant, "\$1"],
[$type_func, "\\\\fB\$1\\\\fP"], [$type_func, "\\\\fB\$1\\\\fP"],
[$type_enum, "\\\\fI\$1\\\\fP"],
[$type_struct, "\\\\fI\$1\\\\fP"], [$type_struct, "\\\\fI\$1\\\\fP"],
[$type_param, "\\\\fI\$1\\\\fP"] [$type_typedef, "\\\\fI\$1\\\\fP"],
[$type_union, "\\\\fI\$1\\\\fP"],
[$type_param, "\\\\fI\$1\\\\fP"],
[$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
[$type_fallback, "\\\\fI\$1\\\\fP"]
); );
my $blankline_man = ""; my $blankline_man = "";
...@@ -283,8 +313,13 @@ my $blankline_man = ""; ...@@ -283,8 +313,13 @@ my $blankline_man = "";
my @highlights_text = ( my @highlights_text = (
[$type_constant, "\$1"], [$type_constant, "\$1"],
[$type_func, "\$1"], [$type_func, "\$1"],
[$type_enum, "\$1"],
[$type_struct, "\$1"], [$type_struct, "\$1"],
[$type_param, "\$1"] [$type_typedef, "\$1"],
[$type_union, "\$1"],
[$type_param, "\$1"],
[$type_member, "\$1\$2\$3"],
[$type_fallback, "\$1"]
); );
my $blankline_text = ""; my $blankline_text = "";
...@@ -292,16 +327,16 @@ my $blankline_text = ""; ...@@ -292,16 +327,16 @@ my $blankline_text = "";
my @highlights_rst = ( my @highlights_rst = (
[$type_constant, "``\$1``"], [$type_constant, "``\$1``"],
# Note: need to escape () to avoid func matching later # Note: need to escape () to avoid func matching later
[$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"], [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
[$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"], [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
[$type_fp_param, "**\$1\\\\(\\\\)**"], [$type_fp_param, "**\$1\\\\(\\\\)**"],
[$type_func, "\\:c\\:func\\:`\$1()`"], [$type_func, "\\:c\\:func\\:`\$1()`"],
[$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
[$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
[$type_typedef_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
[$type_union_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
# in rst this can refer to any type # in rst this can refer to any type
[$type_struct, "\\:c\\:type\\:`\$1`"], [$type_fallback, "\\:c\\:type\\:`\$1`"],
[$type_param, "**\$1**"] [$type_param, "**\$1**"]
); );
my $blankline_rst = "\n"; my $blankline_rst = "\n";
...@@ -310,8 +345,13 @@ my $blankline_rst = "\n"; ...@@ -310,8 +345,13 @@ my $blankline_rst = "\n";
my @highlights_list = ( my @highlights_list = (
[$type_constant, "\$1"], [$type_constant, "\$1"],
[$type_func, "\$1"], [$type_func, "\$1"],
[$type_enum, "\$1"],
[$type_struct, "\$1"], [$type_struct, "\$1"],
[$type_param, "\$1"] [$type_typedef, "\$1"],
[$type_union, "\$1"],
[$type_param, "\$1"],
[$type_member, "\$1"],
[$type_fallback, "\$1"]
); );
my $blankline_list = ""; my $blankline_list = "";
...@@ -1131,8 +1171,9 @@ sub output_function_xml(%) { ...@@ -1131,8 +1171,9 @@ sub output_function_xml(%) {
foreach $parameter (@{$args{'parameterlist'}}) { foreach $parameter (@{$args{'parameterlist'}}) {
my $parameter_name = $parameter; my $parameter_name = $parameter;
$parameter_name =~ s/\[.*//; $parameter_name =~ s/\[.*//;
$type = $args{'parametertypes'}{$parameter};
print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n"; print " <varlistentry>\n <term><parameter>$type $parameter</parameter></term>\n";
print " <listitem>\n <para>\n"; print " <listitem>\n <para>\n";
$lineprefix=" "; $lineprefix=" ";
output_highlight($args{'parameterdescs'}{$parameter_name}); output_highlight($args{'parameterdescs'}{$parameter_name});
...@@ -1223,8 +1264,9 @@ sub output_struct_xml(%) { ...@@ -1223,8 +1264,9 @@ sub output_struct_xml(%) {
defined($args{'parameterdescs'}{$parameter_name}) || next; defined($args{'parameterdescs'}{$parameter_name}) || next;
($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
$type = $args{'parametertypes'}{$parameter};
print " <varlistentry>"; print " <varlistentry>";
print " <term>$parameter</term>\n"; print " <term><literal>$type $parameter</literal></term>\n";
print " <listitem><para>\n"; print " <listitem><para>\n";
output_highlight($args{'parameterdescs'}{$parameter_name}); output_highlight($args{'parameterdescs'}{$parameter_name});
print " </para></listitem>\n"; print " </para></listitem>\n";
...@@ -1883,7 +1925,7 @@ sub output_function_rst(%) { ...@@ -1883,7 +1925,7 @@ sub output_function_rst(%) {
$lineprefix = " "; $lineprefix = " ";
foreach $parameter (@{$args{'parameterlist'}}) { foreach $parameter (@{$args{'parameterlist'}}) {
my $parameter_name = $parameter; my $parameter_name = $parameter;
#$parameter_name =~ s/\[.*//; $parameter_name =~ s/\[.*//;
$type = $args{'parametertypes'}{$parameter}; $type = $args{'parametertypes'}{$parameter};
if ($type ne "") { if ($type ne "") {
...@@ -2409,6 +2451,7 @@ sub push_parameter($$$) { ...@@ -2409,6 +2451,7 @@ sub push_parameter($$$) {
# "[blah" in a parameter string; # "[blah" in a parameter string;
###$param =~ s/\s*//g; ###$param =~ s/\s*//g;
push @parameterlist, $param; push @parameterlist, $param;
$type =~ s/\s\s+/ /g;
$parametertypes{$param} = $type; $parametertypes{$param} = $type;
} }
...@@ -2505,7 +2548,13 @@ sub dump_function($$) { ...@@ -2505,7 +2548,13 @@ sub dump_function($$) {
$prototype =~ s/__must_check +//; $prototype =~ s/__must_check +//;
$prototype =~ s/__weak +//; $prototype =~ s/__weak +//;
my $define = $prototype =~ s/^#\s*define\s+//; #ak added my $define = $prototype =~ s/^#\s*define\s+//; #ak added
$prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//; $prototype =~ s/__attribute__\s*\(\(
(?:
[\w\s]++ # attribute name
(?:\([^)]*+\))? # attribute arguments
\s*+,? # optional comma at the end
)+
\)\)\s+//x;
# Yes, this truly is vile. We are looking for: # Yes, this truly is vile. We are looking for:
# 1. Return type (may be nothing if we're looking at a macro) # 1. Return type (may be nothing if we're looking at a macro)
...@@ -2533,21 +2582,21 @@ sub dump_function($$) { ...@@ -2533,21 +2582,21 @@ sub dump_function($$) {
$noret = 1; $noret = 1;
} elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
$prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
$prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { $prototype =~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) {
$return_type = $1; $return_type = $1;
$declaration_name = $2; $declaration_name = $2;
my $args = $3; my $args = $3;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment