A reasonably busy cycle for documentation this time around. There is a new
guide for user-space API documents, rather sparsely populated at the moment, but it's a start. Markus improved the infrastructure for converting diagrams. Mauro has converted much of the USB documentation over to RST. Plus the usual set of fixes, improvements, and tweaks. There's a bit more than the usual amount of reaching out of Documentation/ to fix comments elsewhere in the tree; I have acks for those where I could get them. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZB1elAAoJEI3ONVYwIuV6wUIQAJSM/4rNdj6z+GXeWhRfbsOo vqqVYluvXQIJaaqdsy9dgcfThhOXWYsPyVF6Xd+bDJpwF3BMZYbX1CI1Mo3kRD+7 9+Pf68cYSHRoU3l/sFI8q0zfKbHtmFteIvnRQoFtRaExqgTR8glUfxNDyN9XuNAZ 3naS4qMZivM4gjMcSpIB/wFOQpV+6qVIs6VTFLdCC8wodT3W/Wmb+bqrCVJ0twbB t8jJeYHt2wsiTdqrKU+VilAUAZ1Lby+DNfeWrO18rC1ohktPyUzOGg8JmTKUBpVO qj1OJwD6abuaNh/J9bXsh8u0OrVrBKWjVrhq9IFYDlm92fu3Bgr6YeoaVPEpcklt jdlgZnWs9/oXa6d32aMc9F7mP9a0Q1qikFTYINhaHQZCb4VDRuQ9hCSuqWm5jlVy lmVAoxLa0zSdOoXaYuO3HC99ku1cIn814CXMDz/IwKXkqUCV+zl+H3AGkvxGyQ5M eblw2TnQnc6e1LRcxt5bgpFR1JYMbCJhu0U5XrNFueQV8ReB15dvL7h4y21dWJKF 2Sr83rwfG1rpZQiSqCjOXxIzuXbEGH3+a+zCDV5IHhQRt/VNDOt2hgmcyucSSJ5h 5GRFYgTlGvoT/6LdIT39QooHB+4tSDRtEQ6lh0q2ZtVV2rfG/I6/PR5sUbWM65SN vAfctRm2afHLhdonSX5O =41m+ -----END PGP SIGNATURE----- Merge tag 'docs-4.12' of git://git.lwn.net/linux Pull documentation update from Jonathan Corbet: "A reasonably busy cycle for documentation this time around. There is a new guide for user-space API documents, rather sparsely populated at the moment, but it's a start. Markus improved the infrastructure for converting diagrams. Mauro has converted much of the USB documentation over to RST. Plus the usual set of fixes, improvements, and tweaks. There's a bit more than the usual amount of reaching out of Documentation/ to fix comments elsewhere in the tree; I have acks for those where I could get them" * tag 'docs-4.12' of git://git.lwn.net/linux: (74 commits) docs: Fix a couple typos docs: Fix a spelling error in vfio-mediated-device.txt docs: Fix a spelling error in ioctl-number.txt MAINTAINERS: update file entry for HSI subsystem Documentation: allow installing man pages to a user defined directory Doc/PM: Sync with intel_powerclamp code behavior zr364xx.rst: usb/devices is now at /sys/kernel/debug/ usb.rst: move documentation from proc_usb_info.txt to USB ReST book convert philips.txt to ReST and add to media docs docs-rst: usb: update old usbfs-related documentation arm: Documentation: update a path name docs: process/4.Coding.rst: Fix a couple of document refs docs-rst: fix usb cross-references usb: gadget.h: be consistent at kernel doc macros usb: composite.h: fix two warnings when building docs usb: get rid of some ReST doc build errors usb.rst: get rid of some Sphinx errors usb/URB.txt: convert to ReST and update it usb/persist.txt: convert to ReST and add to driver-api book usb/hotplug.txt: convert to ReST and add to driver-api book ...
This commit is contained in:
commit
c58d4055c0
132 changed files with 6094 additions and 5400 deletions
|
@ -9,7 +9,7 @@ Description:
|
|||
hubs this facility is always enabled and their device
|
||||
directories will not contain this file.
|
||||
|
||||
For more information, see Documentation/usb/persist.txt.
|
||||
For more information, see Documentation/driver-api/usb/persist.rst.
|
||||
|
||||
What: /sys/bus/usb/devices/.../power/autosuspend
|
||||
Date: March 2007
|
||||
|
|
|
@ -16,7 +16,8 @@ The vDSO uses symbol versioning; whenever you request a symbol from the
|
|||
vDSO, specify the version you are expecting.
|
||||
|
||||
Programs that dynamically link to glibc will use the vDSO automatically.
|
||||
Otherwise, you can use the reference parser in Documentation/vDSO/parse_vdso.c.
|
||||
Otherwise, you can use the reference parser in
|
||||
tools/testing/selftests/vDSO/parse_vdso.c.
|
||||
|
||||
Unless otherwise noted, the set of symbols with any given version and the
|
||||
ABI of those symbols is considered stable. It may vary across architectures,
|
||||
|
|
|
@ -299,5 +299,5 @@ What: /sys/bus/pci/devices/.../revision
|
|||
Date: November 2016
|
||||
Contact: Emil Velikov <emil.l.velikov@gmail.com>
|
||||
Description:
|
||||
This file contains the revision field of the the PCI device.
|
||||
This file contains the revision field of the PCI device.
|
||||
The value comes from device config space. The file is read only.
|
||||
|
|
|
@ -8,12 +8,11 @@
|
|||
|
||||
DOCBOOKS := z8530book.xml \
|
||||
kernel-hacking.xml kernel-locking.xml \
|
||||
writing_usb_driver.xml networking.xml \
|
||||
kernel-api.xml filesystems.xml lsm.xml kgdb.xml \
|
||||
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
||||
genericirq.xml s390-drivers.xml scsi.xml \
|
||||
sh.xml w1.xml \
|
||||
writing_musb_glue_layer.xml
|
||||
networking.xml \
|
||||
filesystems.xml lsm.xml kgdb.xml \
|
||||
libata.xml mtdnand.xml librs.xml rapidio.xml \
|
||||
s390-drivers.xml scsi.xml \
|
||||
sh.xml w1.xml
|
||||
|
||||
ifeq ($(DOCBOOKS),)
|
||||
|
||||
|
@ -62,11 +61,14 @@ MAN := $(patsubst %.xml, %.9, $(BOOKS))
|
|||
mandocs: $(MAN)
|
||||
find $(obj)/man -name '*.9' | xargs gzip -nf
|
||||
|
||||
# Default location for installed man pages
|
||||
export INSTALL_MAN_PATH = $(objtree)/usr
|
||||
|
||||
installmandocs: mandocs
|
||||
mkdir -p /usr/local/man/man9/
|
||||
mkdir -p $(INSTALL_MAN_PATH)/man/man9/
|
||||
find $(obj)/man -name '*.9.gz' -printf '%h %f\n' | \
|
||||
sort -k 2 -k 1 | uniq -f 1 | sed -e 's: :/:' | \
|
||||
xargs install -m 644 -t /usr/local/man/man9/
|
||||
xargs install -m 644 -t $(INSTALL_MAN_PATH)/man/man9/
|
||||
|
||||
# no-op for the DocBook toolchain
|
||||
epubdocs:
|
||||
|
@ -238,7 +240,9 @@ dochelp:
|
|||
@echo ' psdocs - Postscript'
|
||||
@echo ' xmldocs - XML DocBook'
|
||||
@echo ' mandocs - man pages'
|
||||
@echo ' installmandocs - install man pages generated by mandocs'
|
||||
@echo ' installmandocs - install man pages generated by mandocs to INSTALL_MAN_PATH'; \
|
||||
echo ' (default: $(INSTALL_MAN_PATH))'; \
|
||||
echo ''
|
||||
@echo ' cleandocs - clean all generated DocBook files'
|
||||
@echo
|
||||
@echo ' make DOCBOOKS="s1.xml s2.xml" [target] Generate only docs s1.xml s2.xml'
|
||||
|
|
|
@ -1,793 +0,0 @@
|
|||
<?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="USB-Gadget-API">
|
||||
<bookinfo>
|
||||
<title>USB Gadget API for Linux</title>
|
||||
<date>20 August 2004</date>
|
||||
<edition>20 August 2004</edition>
|
||||
|
||||
<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>
|
||||
<copyright>
|
||||
<year>2003-2004</year>
|
||||
<holder>David Brownell</holder>
|
||||
</copyright>
|
||||
|
||||
<author>
|
||||
<firstname>David</firstname>
|
||||
<surname>Brownell</surname>
|
||||
<affiliation>
|
||||
<address><email>dbrownell@users.sourceforge.net</email></address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="intro"><title>Introduction</title>
|
||||
|
||||
<para>This document presents a Linux-USB "Gadget"
|
||||
kernel mode
|
||||
API, for use within peripherals and other USB devices
|
||||
that embed Linux.
|
||||
It provides an overview of the API structure,
|
||||
and shows how that fits into a system development project.
|
||||
This is the first such API released on Linux to address
|
||||
a number of important problems, including: </para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>Supports USB 2.0, for high speed devices which
|
||||
can stream data at several dozen megabytes per second.
|
||||
</para></listitem>
|
||||
<listitem><para>Handles devices with dozens of endpoints just as
|
||||
well as ones with just two fixed-function ones. Gadget drivers
|
||||
can be written so they're easy to port to new hardware.
|
||||
</para></listitem>
|
||||
<listitem><para>Flexible enough to expose more complex USB device
|
||||
capabilities such as multiple configurations, multiple interfaces,
|
||||
composite devices,
|
||||
and alternate interface settings.
|
||||
</para></listitem>
|
||||
<listitem><para>USB "On-The-Go" (OTG) support, in conjunction
|
||||
with updates to the Linux-USB host side.
|
||||
</para></listitem>
|
||||
<listitem><para>Sharing data structures and API models with the
|
||||
Linux-USB host side API. This helps the OTG support, and
|
||||
looks forward to more-symmetric frameworks (where the same
|
||||
I/O model is used by both host and device side drivers).
|
||||
</para></listitem>
|
||||
<listitem><para>Minimalist, so it's easier to support new device
|
||||
controller hardware. I/O processing doesn't imply large
|
||||
demands for memory or CPU resources.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
|
||||
<para>Most Linux developers will not be able to use this API, since they
|
||||
have USB "host" hardware in a PC, workstation, or server.
|
||||
Linux users with embedded systems are more likely to
|
||||
have USB peripheral hardware.
|
||||
To distinguish drivers running inside such hardware from the
|
||||
more familiar Linux "USB device drivers",
|
||||
which are host side proxies for the real USB devices,
|
||||
a different term is used:
|
||||
the drivers inside the peripherals are "USB gadget drivers".
|
||||
In USB protocol interactions, the device driver is the master
|
||||
(or "client driver")
|
||||
and the gadget driver is the slave (or "function driver").
|
||||
</para>
|
||||
|
||||
<para>The gadget API resembles the host side Linux-USB API in that both
|
||||
use queues of request objects to package I/O buffers, and those requests
|
||||
may be submitted or canceled.
|
||||
They share common definitions for the standard USB
|
||||
<emphasis>Chapter 9</emphasis> messages, structures, and constants.
|
||||
Also, both APIs bind and unbind drivers to devices.
|
||||
The APIs differ in detail, since the host side's current
|
||||
URB framework exposes a number of implementation details
|
||||
and assumptions that are inappropriate for a gadget API.
|
||||
While the model for control transfers and configuration
|
||||
management is necessarily different (one side is a hardware-neutral master,
|
||||
the other is a hardware-aware slave), the endpoint I/0 API used here
|
||||
should also be usable for an overhead-reduced host side API.
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="structure"><title>Structure of Gadget Drivers</title>
|
||||
|
||||
<para>A system running inside a USB peripheral
|
||||
normally has at least three layers inside the kernel to handle
|
||||
USB protocol processing, and may have additional layers in
|
||||
user space code.
|
||||
The "gadget" API is used by the middle layer to interact
|
||||
with the lowest level (which directly handles hardware).
|
||||
</para>
|
||||
|
||||
<para>In Linux, from the bottom up, these layers are:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><emphasis>USB Controller Driver</emphasis></term>
|
||||
|
||||
<listitem>
|
||||
<para>This is the lowest software level.
|
||||
It is the only layer that talks to hardware,
|
||||
through registers, fifos, dma, irqs, and the like.
|
||||
The <filename><linux/usb/gadget.h></filename> API abstracts
|
||||
the peripheral controller endpoint hardware.
|
||||
That hardware is exposed through endpoint objects, which accept
|
||||
streams of IN/OUT buffers, and through callbacks that interact
|
||||
with gadget drivers.
|
||||
Since normal USB devices only have one upstream
|
||||
port, they only have one of these drivers.
|
||||
The controller driver can support any number of different
|
||||
gadget drivers, but only one of them can be used at a time.
|
||||
</para>
|
||||
|
||||
<para>Examples of such controller hardware include
|
||||
the PCI-based NetChip 2280 USB 2.0 high speed controller,
|
||||
the SA-11x0 or PXA-25x UDC (found within many PDAs),
|
||||
and a variety of other products.
|
||||
</para>
|
||||
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><emphasis>Gadget Driver</emphasis></term>
|
||||
|
||||
<listitem>
|
||||
<para>The lower boundary of this driver implements hardware-neutral
|
||||
USB functions, using calls to the controller driver.
|
||||
Because such hardware varies widely in capabilities and restrictions,
|
||||
and is used in embedded environments where space is at a premium,
|
||||
the gadget driver is often configured at compile time
|
||||
to work with endpoints supported by one particular controller.
|
||||
Gadget drivers may be portable to several different controllers,
|
||||
using conditional compilation.
|
||||
(Recent kernels substantially simplify the work involved in
|
||||
supporting new hardware, by <emphasis>autoconfiguring</emphasis>
|
||||
endpoints automatically for many bulk-oriented drivers.)
|
||||
Gadget driver responsibilities include:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>handling setup requests (ep0 protocol responses)
|
||||
possibly including class-specific functionality
|
||||
</para></listitem>
|
||||
<listitem><para>returning configuration and string descriptors
|
||||
</para></listitem>
|
||||
<listitem><para>(re)setting configurations and interface
|
||||
altsettings, including enabling and configuring endpoints
|
||||
</para></listitem>
|
||||
<listitem><para>handling life cycle events, such as managing
|
||||
bindings to hardware,
|
||||
USB suspend/resume, remote wakeup,
|
||||
and disconnection from the USB host.
|
||||
</para></listitem>
|
||||
<listitem><para>managing IN and OUT transfers on all currently
|
||||
enabled endpoints
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Such drivers may be modules of proprietary code, although
|
||||
that approach is discouraged in the Linux community.
|
||||
</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><emphasis>Upper Level</emphasis></term>
|
||||
|
||||
<listitem>
|
||||
<para>Most gadget drivers have an upper boundary that connects
|
||||
to some Linux driver or framework in Linux.
|
||||
Through that boundary flows the data which the gadget driver
|
||||
produces and/or consumes through protocol transfers over USB.
|
||||
Examples include:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem><para>user mode code, using generic (gadgetfs)
|
||||
or application specific files in
|
||||
<filename>/dev</filename>
|
||||
</para></listitem>
|
||||
<listitem><para>networking subsystem (for network gadgets,
|
||||
like the CDC Ethernet Model gadget driver)
|
||||
</para></listitem>
|
||||
<listitem><para>data capture drivers, perhaps video4Linux or
|
||||
a scanner driver; or test and measurement hardware.
|
||||
</para></listitem>
|
||||
<listitem><para>input subsystem (for HID gadgets)
|
||||
</para></listitem>
|
||||
<listitem><para>sound subsystem (for audio gadgets)
|
||||
</para></listitem>
|
||||
<listitem><para>file system (for PTP gadgets)
|
||||
</para></listitem>
|
||||
<listitem><para>block i/o subsystem (for usb-storage gadgets)
|
||||
</para></listitem>
|
||||
<listitem><para>... and more </para></listitem>
|
||||
</itemizedlist>
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><emphasis>Additional Layers</emphasis></term>
|
||||
|
||||
<listitem>
|
||||
<para>Other layers may exist.
|
||||
These could include kernel layers, such as network protocol stacks,
|
||||
as well as user mode applications building on standard POSIX
|
||||
system call APIs such as
|
||||
<emphasis>open()</emphasis>, <emphasis>close()</emphasis>,
|
||||
<emphasis>read()</emphasis> and <emphasis>write()</emphasis>.
|
||||
On newer systems, POSIX Async I/O calls may be an option.
|
||||
Such user mode code will not necessarily be subject to
|
||||
the GNU General Public License (GPL).
|
||||
</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>OTG-capable systems will also need to include a standard Linux-USB
|
||||
host side stack,
|
||||
with <emphasis>usbcore</emphasis>,
|
||||
one or more <emphasis>Host Controller Drivers</emphasis> (HCDs),
|
||||
<emphasis>USB Device Drivers</emphasis> to support
|
||||
the OTG "Targeted Peripheral List",
|
||||
and so forth.
|
||||
There will also be an <emphasis>OTG Controller Driver</emphasis>,
|
||||
which is visible to gadget and device driver developers only indirectly.
|
||||
That helps the host and device side USB controllers implement the
|
||||
two new OTG protocols (HNP and SRP).
|
||||
Roles switch (host to peripheral, or vice versa) using HNP
|
||||
during USB suspend processing, and SRP can be viewed as a
|
||||
more battery-friendly kind of device wakeup protocol.
|
||||
</para>
|
||||
|
||||
<para>Over time, reusable utilities are evolving to help make some
|
||||
gadget driver tasks simpler.
|
||||
For example, building configuration descriptors from vectors of
|
||||
descriptors for the configurations interfaces and endpoints is
|
||||
now automated, and many drivers now use autoconfiguration to
|
||||
choose hardware endpoints and initialize their descriptors.
|
||||
|
||||
A potential example of particular interest
|
||||
is code implementing standard USB-IF protocols for
|
||||
HID, networking, storage, or audio classes.
|
||||
Some developers are interested in KDB or KGDB hooks, to let
|
||||
target hardware be remotely debugged.
|
||||
Most such USB protocol code doesn't need to be hardware-specific,
|
||||
any more than network protocols like X11, HTTP, or NFS are.
|
||||
Such gadget-side interface drivers should eventually be combined,
|
||||
to implement composite devices.
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
|
||||
<chapter id="api"><title>Kernel Mode Gadget API</title>
|
||||
|
||||
<para>Gadget drivers declare themselves through a
|
||||
<emphasis>struct usb_gadget_driver</emphasis>, which is responsible for
|
||||
most parts of enumeration for a <emphasis>struct usb_gadget</emphasis>.
|
||||
The response to a set_configuration usually involves
|
||||
enabling one or more of the <emphasis>struct usb_ep</emphasis> objects
|
||||
exposed by the gadget, and submitting one or more
|
||||
<emphasis>struct usb_request</emphasis> buffers to transfer data.
|
||||
Understand those four data types, and their operations, and
|
||||
you will understand how this API works.
|
||||
</para>
|
||||
|
||||
<note><title>Incomplete Data Type Descriptions</title>
|
||||
|
||||
<para>This documentation was prepared using the standard Linux
|
||||
kernel <filename>docproc</filename> tool, which turns text
|
||||
and in-code comments into SGML DocBook and then into usable
|
||||
formats such as HTML or PDF.
|
||||
Other than the "Chapter 9" data types, most of the significant
|
||||
data types and functions are described here.
|
||||
</para>
|
||||
|
||||
<para>However, docproc does not understand all the C constructs
|
||||
that are used, so some relevant information is likely omitted from
|
||||
what you are reading.
|
||||
One example of such information is endpoint autoconfiguration.
|
||||
You'll have to read the header file, and use example source
|
||||
code (such as that for "Gadget Zero"), to fully understand the API.
|
||||
</para>
|
||||
|
||||
<para>The part of the API implementing some basic
|
||||
driver capabilities is specific to the version of the
|
||||
Linux kernel that's in use.
|
||||
The 2.6 kernel includes a <emphasis>driver model</emphasis>
|
||||
framework that has no analogue on earlier kernels;
|
||||
so those parts of the gadget API are not fully portable.
|
||||
(They are implemented on 2.4 kernels, but in a different way.)
|
||||
The driver model state is another part of this API that is
|
||||
ignored by the kerneldoc tools.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>The core API does not expose
|
||||
every possible hardware feature, only the most widely available ones.
|
||||
There are significant hardware features, such as device-to-device DMA
|
||||
(without temporary storage in a memory buffer)
|
||||
that would be added using hardware-specific APIs.
|
||||
</para>
|
||||
|
||||
<para>This API allows drivers to use conditional compilation to handle
|
||||
endpoint capabilities of different hardware, but doesn't require that.
|
||||
Hardware tends to have arbitrary restrictions, relating to
|
||||
transfer types, addressing, packet sizes, buffering, and availability.
|
||||
As a rule, such differences only matter for "endpoint zero" logic
|
||||
that handles device configuration and management.
|
||||
The API supports limited run-time
|
||||
detection of capabilities, through naming conventions for endpoints.
|
||||
Many drivers will be able to at least partially autoconfigure
|
||||
themselves.
|
||||
In particular, driver init sections will often have endpoint
|
||||
autoconfiguration logic that scans the hardware's list of endpoints
|
||||
to find ones matching the driver requirements
|
||||
(relying on those conventions), to eliminate some of the most
|
||||
common reasons for conditional compilation.
|
||||
</para>
|
||||
|
||||
<para>Like the Linux-USB host side API, this API exposes
|
||||
the "chunky" nature of USB messages: I/O requests are in terms
|
||||
of one or more "packets", and packet boundaries are visible to drivers.
|
||||
Compared to RS-232 serial protocols, USB resembles
|
||||
synchronous protocols like HDLC
|
||||
(N bytes per frame, multipoint addressing, host as the primary
|
||||
station and devices as secondary stations)
|
||||
more than asynchronous ones
|
||||
(tty style: 8 data bits per frame, no parity, one stop bit).
|
||||
So for example the controller drivers won't buffer
|
||||
two single byte writes into a single two-byte USB IN packet,
|
||||
although gadget drivers may do so when they implement
|
||||
protocols where packet boundaries (and "short packets")
|
||||
are not significant.
|
||||
</para>
|
||||
|
||||
<sect1 id="lifecycle"><title>Driver Life Cycle</title>
|
||||
|
||||
<para>Gadget drivers make endpoint I/O requests to hardware without
|
||||
needing to know many details of the hardware, but driver
|
||||
setup/configuration code needs to handle some differences.
|
||||
Use the API like this:
|
||||
</para>
|
||||
|
||||
<orderedlist numeration='arabic'>
|
||||
|
||||
<listitem><para>Register a driver for the particular device side
|
||||
usb controller hardware,
|
||||
such as the net2280 on PCI (USB 2.0),
|
||||
sa11x0 or pxa25x as found in Linux PDAs,
|
||||
and so on.
|
||||
At this point the device is logically in the USB ch9 initial state
|
||||
("attached"), drawing no power and not usable
|
||||
(since it does not yet support enumeration).
|
||||
Any host should not see the device, since it's not
|
||||
activated the data line pullup used by the host to
|
||||
detect a device, even if VBUS power is available.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Register a gadget driver that implements some higher level
|
||||
device function. That will then bind() to a usb_gadget, which
|
||||
activates the data line pullup sometime after detecting VBUS.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>The hardware driver can now start enumerating.
|
||||
The steps it handles are to accept USB power and set_address requests.
|
||||
Other steps are handled by the gadget driver.
|
||||
If the gadget driver module is unloaded before the host starts to
|
||||
enumerate, steps before step 7 are skipped.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>The gadget driver's setup() call returns usb descriptors,
|
||||
based both on what the bus interface hardware provides and on the
|
||||
functionality being implemented.
|
||||
That can involve alternate settings or configurations,
|
||||
unless the hardware prevents such operation.
|
||||
For OTG devices, each configuration descriptor includes
|
||||
an OTG descriptor.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>The gadget driver handles the last step of enumeration,
|
||||
when the USB host issues a set_configuration call.
|
||||
It enables all endpoints used in that configuration,
|
||||
with all interfaces in their default settings.
|
||||
That involves using a list of the hardware's endpoints, enabling each
|
||||
endpoint according to its descriptor.
|
||||
It may also involve using <function>usb_gadget_vbus_draw</function>
|
||||
to let more power be drawn from VBUS, as allowed by that configuration.
|
||||
For OTG devices, setting a configuration may also involve reporting
|
||||
HNP capabilities through a user interface.
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>Do real work and perform data transfers, possibly involving
|
||||
changes to interface settings or switching to new configurations, until the
|
||||
device is disconnect()ed from the host.
|
||||
Queue any number of transfer requests to each endpoint.
|
||||
It may be suspended and resumed several times before being disconnected.
|
||||
On disconnect, the drivers go back to step 3 (above).
|
||||
</para></listitem>
|
||||
|
||||
<listitem><para>When the gadget driver module is being unloaded,
|
||||
the driver unbind() callback is issued. That lets the controller
|
||||
driver be unloaded.
|
||||
</para></listitem>
|
||||
|
||||
</orderedlist>
|
||||
|
||||
<para>Drivers will normally be arranged so that just loading the
|
||||
gadget driver module (or statically linking it into a Linux kernel)
|
||||
allows the peripheral device to be enumerated, but some drivers
|
||||
will defer enumeration until some higher level component (like
|
||||
a user mode daemon) enables it.
|
||||
Note that at this lowest level there are no policies about how
|
||||
ep0 configuration logic is implemented,
|
||||
except that it should obey USB specifications.
|
||||
Such issues are in the domain of gadget drivers,
|
||||
including knowing about implementation constraints
|
||||
imposed by some USB controllers
|
||||
or understanding that composite devices might happen to
|
||||
be built by integrating reusable components.
|
||||
</para>
|
||||
|
||||
<para>Note that the lifecycle above can be slightly different
|
||||
for OTG devices.
|
||||
Other than providing an additional OTG descriptor in each
|
||||
configuration, only the HNP-related differences are particularly
|
||||
visible to driver code.
|
||||
They involve reporting requirements during the SET_CONFIGURATION
|
||||
request, and the option to invoke HNP during some suspend callbacks.
|
||||
Also, SRP changes the semantics of
|
||||
<function>usb_gadget_wakeup</function>
|
||||
slightly.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="ch9"><title>USB 2.0 Chapter 9 Types and Constants</title>
|
||||
|
||||
<para>Gadget drivers
|
||||
rely on common USB structures and constants
|
||||
defined in the
|
||||
<filename><linux/usb/ch9.h></filename>
|
||||
header file, which is standard in Linux 2.6 kernels.
|
||||
These are the same types and constants used by host
|
||||
side drivers (and usbcore).
|
||||
</para>
|
||||
|
||||
!Iinclude/linux/usb/ch9.h
|
||||
</sect1>
|
||||
|
||||
<sect1 id="core"><title>Core Objects and Methods</title>
|
||||
|
||||
<para>These are declared in
|
||||
<filename><linux/usb/gadget.h></filename>,
|
||||
and are used by gadget drivers to interact with
|
||||
USB peripheral controller drivers.
|
||||
</para>
|
||||
|
||||
<!-- yeech, this is ugly in nsgmls PDF output.
|
||||
|
||||
the PDF bookmark and refentry output nesting is wrong,
|
||||
and the member/argument documentation indents ugly.
|
||||
|
||||
plus something (docproc?) adds whitespace before the
|
||||
descriptive paragraph text, so it can't line up right
|
||||
unless the explanations are trivial.
|
||||
-->
|
||||
|
||||
!Iinclude/linux/usb/gadget.h
|
||||
</sect1>
|
||||
|
||||
<sect1 id="utils"><title>Optional Utilities</title>
|
||||
|
||||
<para>The core API is sufficient for writing a USB Gadget Driver,
|
||||
but some optional utilities are provided to simplify common tasks.
|
||||
These utilities include endpoint autoconfiguration.
|
||||
</para>
|
||||
|
||||
!Edrivers/usb/gadget/usbstring.c
|
||||
!Edrivers/usb/gadget/config.c
|
||||
<!-- !Edrivers/usb/gadget/epautoconf.c -->
|
||||
</sect1>
|
||||
|
||||
<sect1 id="composite"><title>Composite Device Framework</title>
|
||||
|
||||
<para>The core API is sufficient for writing drivers for composite
|
||||
USB devices (with more than one function in a given configuration),
|
||||
and also multi-configuration devices (also more than one function,
|
||||
but not necessarily sharing a given configuration).
|
||||
There is however an optional framework which makes it easier to
|
||||
reuse and combine functions.
|
||||
</para>
|
||||
|
||||
<para>Devices using this framework provide a <emphasis>struct
|
||||
usb_composite_driver</emphasis>, which in turn provides one or
|
||||
more <emphasis>struct usb_configuration</emphasis> instances.
|
||||
Each such configuration includes at least one
|
||||
<emphasis>struct usb_function</emphasis>, which packages a user
|
||||
visible role such as "network link" or "mass storage device".
|
||||
Management functions may also exist, such as "Device Firmware
|
||||
Upgrade".
|
||||
</para>
|
||||
|
||||
!Iinclude/linux/usb/composite.h
|
||||
!Edrivers/usb/gadget/composite.c
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="functions"><title>Composite Device Functions</title>
|
||||
|
||||
<para>At this writing, a few of the current gadget drivers have
|
||||
been converted to this framework.
|
||||
Near-term plans include converting all of them, except for "gadgetfs".
|
||||
</para>
|
||||
|
||||
!Edrivers/usb/gadget/function/f_acm.c
|
||||
!Edrivers/usb/gadget/function/f_ecm.c
|
||||
!Edrivers/usb/gadget/function/f_subset.c
|
||||
!Edrivers/usb/gadget/function/f_obex.c
|
||||
!Edrivers/usb/gadget/function/f_serial.c
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="controllers"><title>Peripheral Controller Drivers</title>
|
||||
|
||||
<para>The first hardware supporting this API was the NetChip 2280
|
||||
controller, which supports USB 2.0 high speed and is based on PCI.
|
||||
This is the <filename>net2280</filename> driver module.
|
||||
The driver supports Linux kernel versions 2.4 and 2.6;
|
||||
contact NetChip Technologies for development boards and product
|
||||
information.
|
||||
</para>
|
||||
|
||||
<para>Other hardware working in the "gadget" framework includes:
|
||||
Intel's PXA 25x and IXP42x series processors
|
||||
(<filename>pxa2xx_udc</filename>),
|
||||
Toshiba TC86c001 "Goku-S" (<filename>goku_udc</filename>),
|
||||
Renesas SH7705/7727 (<filename>sh_udc</filename>),
|
||||
MediaQ 11xx (<filename>mq11xx_udc</filename>),
|
||||
Hynix HMS30C7202 (<filename>h7202_udc</filename>),
|
||||
National 9303/4 (<filename>n9604_udc</filename>),
|
||||
Texas Instruments OMAP (<filename>omap_udc</filename>),
|
||||
Sharp LH7A40x (<filename>lh7a40x_udc</filename>),
|
||||
and more.
|
||||
Most of those are full speed controllers.
|
||||
</para>
|
||||
|
||||
<para>At this writing, there are people at work on drivers in
|
||||
this framework for several other USB device controllers,
|
||||
with plans to make many of them be widely available.
|
||||
</para>
|
||||
|
||||
<!-- !Edrivers/usb/gadget/net2280.c -->
|
||||
|
||||
<para>A partial USB simulator,
|
||||
the <filename>dummy_hcd</filename> driver, is available.
|
||||
It can act like a net2280, a pxa25x, or an sa11x0 in terms
|
||||
of available endpoints and device speeds; and it simulates
|
||||
control, bulk, and to some extent interrupt transfers.
|
||||
That lets you develop some parts of a gadget driver on a normal PC,
|
||||
without any special hardware, and perhaps with the assistance
|
||||
of tools such as GDB running with User Mode Linux.
|
||||
At least one person has expressed interest in adapting that
|
||||
approach, hooking it up to a simulator for a microcontroller.
|
||||
Such simulators can help debug subsystems where the runtime hardware
|
||||
is unfriendly to software development, or is not yet available.
|
||||
</para>
|
||||
|
||||
<para>Support for other controllers is expected to be developed
|
||||
and contributed
|
||||
over time, as this driver framework evolves.
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="gadget"><title>Gadget Drivers</title>
|
||||
|
||||
<para>In addition to <emphasis>Gadget Zero</emphasis>
|
||||
(used primarily for testing and development with drivers
|
||||
for usb controller hardware), other gadget drivers exist.
|
||||
</para>
|
||||
|
||||
<para>There's an <emphasis>ethernet</emphasis> gadget
|
||||
driver, which implements one of the most useful
|
||||
<emphasis>Communications Device Class</emphasis> (CDC) models.
|
||||
One of the standards for cable modem interoperability even
|
||||
specifies the use of this ethernet model as one of two
|
||||
mandatory options.
|
||||
Gadgets using this code look to a USB host as if they're
|
||||
an Ethernet adapter.
|
||||
It provides access to a network where the gadget's CPU is one host,
|
||||
which could easily be bridging, routing, or firewalling
|
||||
access to other networks.
|
||||
Since some hardware can't fully implement the CDC Ethernet
|
||||
requirements, this driver also implements a "good parts only"
|
||||
subset of CDC Ethernet.
|
||||
(That subset doesn't advertise itself as CDC Ethernet,
|
||||
to avoid creating problems.)
|
||||
</para>
|
||||
|
||||
<para>Support for Microsoft's <emphasis>RNDIS</emphasis>
|
||||
protocol has been contributed by Pengutronix and Auerswald GmbH.
|
||||
This is like CDC Ethernet, but it runs on more slightly USB hardware
|
||||
(but less than the CDC subset).
|
||||
However, its main claim to fame is being able to connect directly to
|
||||
recent versions of Windows, using drivers that Microsoft bundles
|
||||
and supports, making it much simpler to network with Windows.
|
||||
</para>
|
||||
|
||||
<para>There is also support for user mode gadget drivers,
|
||||
using <emphasis>gadgetfs</emphasis>.
|
||||
This provides a <emphasis>User Mode API</emphasis> that presents
|
||||
each endpoint as a single file descriptor. I/O is done using
|
||||
normal <emphasis>read()</emphasis> and <emphasis>read()</emphasis> calls.
|
||||
Familiar tools like GDB and pthreads can be used to
|
||||
develop and debug user mode drivers, so that once a robust
|
||||
controller driver is available many applications for it
|
||||
won't require new kernel mode software.
|
||||
Linux 2.6 <emphasis>Async I/O (AIO)</emphasis>
|
||||
support is available, so that user mode software
|
||||
can stream data with only slightly more overhead
|
||||
than a kernel driver.
|
||||
</para>
|
||||
|
||||
<para>There's a USB Mass Storage class driver, which provides
|
||||
a different solution for interoperability with systems such
|
||||
as MS-Windows and MacOS.
|
||||
That <emphasis>Mass Storage</emphasis> driver uses a
|
||||
file or block device as backing store for a drive,
|
||||
like the <filename>loop</filename> driver.
|
||||
The USB host uses the BBB, CB, or CBI versions of the mass
|
||||
storage class specification, using transparent SCSI commands
|
||||
to access the data from the backing store.
|
||||
</para>
|
||||
|
||||
<para>There's a "serial line" driver, useful for TTY style
|
||||
operation over USB.
|
||||
The latest version of that driver supports CDC ACM style
|
||||
operation, like a USB modem, and so on most hardware it can
|
||||
interoperate easily with MS-Windows.
|
||||
One interesting use of that driver is in boot firmware (like a BIOS),
|
||||
which can sometimes use that model with very small systems without
|
||||
real serial lines.
|
||||
</para>
|
||||
|
||||
<para>Support for other kinds of gadget is expected to
|
||||
be developed and contributed
|
||||
over time, as this driver framework evolves.
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="otg"><title>USB On-The-GO (OTG)</title>
|
||||
|
||||
<para>USB OTG support on Linux 2.6 was initially developed
|
||||
by Texas Instruments for
|
||||
<ulink url="http://www.omap.com">OMAP</ulink> 16xx and 17xx
|
||||
series processors.
|
||||
Other OTG systems should work in similar ways, but the
|
||||
hardware level details could be very different.
|
||||
</para>
|
||||
|
||||
<para>Systems need specialized hardware support to implement OTG,
|
||||
notably including a special <emphasis>Mini-AB</emphasis> jack
|
||||
and associated transceiver to support <emphasis>Dual-Role</emphasis>
|
||||
operation:
|
||||
they can act either as a host, using the standard
|
||||
Linux-USB host side driver stack,
|
||||
or as a peripheral, using this "gadget" framework.
|
||||
To do that, the system software relies on small additions
|
||||
to those programming interfaces,
|
||||
and on a new internal component (here called an "OTG Controller")
|
||||
affecting which driver stack connects to the OTG port.
|
||||
In each role, the system can re-use the existing pool of
|
||||
hardware-neutral drivers, layered on top of the controller
|
||||
driver interfaces (<emphasis>usb_bus</emphasis> or
|
||||
<emphasis>usb_gadget</emphasis>).
|
||||
Such drivers need at most minor changes, and most of the calls
|
||||
added to support OTG can also benefit non-OTG products.
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>Gadget drivers test the <emphasis>is_otg</emphasis>
|
||||
flag, and use it to determine whether or not to include
|
||||
an OTG descriptor in each of their configurations.
|
||||
</para></listitem>
|
||||
<listitem><para>Gadget drivers may need changes to support the
|
||||
two new OTG protocols, exposed in new gadget attributes
|
||||
such as <emphasis>b_hnp_enable</emphasis> flag.
|
||||
HNP support should be reported through a user interface
|
||||
(two LEDs could suffice), and is triggered in some cases
|
||||
when the host suspends the peripheral.
|
||||
SRP support can be user-initiated just like remote wakeup,
|
||||
probably by pressing the same button.
|
||||
</para></listitem>
|
||||
<listitem><para>On the host side, USB device drivers need
|
||||
to be taught to trigger HNP at appropriate moments, using
|
||||
<function>usb_suspend_device()</function>.
|
||||
That also conserves battery power, which is useful even
|
||||
for non-OTG configurations.
|
||||
</para></listitem>
|
||||
<listitem><para>Also on the host side, a driver must support the
|
||||
OTG "Targeted Peripheral List". That's just a whitelist,
|
||||
used to reject peripherals not supported with a given
|
||||
Linux OTG host.
|
||||
<emphasis>This whitelist is product-specific;
|
||||
each product must modify <filename>otg_whitelist.h</filename>
|
||||
to match its interoperability specification.
|
||||
</emphasis>
|
||||
</para>
|
||||
<para>Non-OTG Linux hosts, like PCs and workstations,
|
||||
normally have some solution for adding drivers, so that
|
||||
peripherals that aren't recognized can eventually be supported.
|
||||
That approach is unreasonable for consumer products that may
|
||||
never have their firmware upgraded, and where it's usually
|
||||
unrealistic to expect traditional PC/workstation/server kinds
|
||||
of support model to work.
|
||||
For example, it's often impractical to change device firmware
|
||||
once the product has been distributed, so driver bugs can't
|
||||
normally be fixed if they're found after shipment.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Additional changes are needed below those hardware-neutral
|
||||
<emphasis>usb_bus</emphasis> and <emphasis>usb_gadget</emphasis>
|
||||
driver interfaces; those aren't discussed here in any detail.
|
||||
Those affect the hardware-specific code for each USB Host or Peripheral
|
||||
controller, and how the HCD initializes (since OTG can be active only
|
||||
on a single port).
|
||||
They also involve what may be called an <emphasis>OTG Controller
|
||||
Driver</emphasis>, managing the OTG transceiver and the OTG state
|
||||
machine logic as well as much of the root hub behavior for the
|
||||
OTG port.
|
||||
The OTG controller driver needs to activate and deactivate USB
|
||||
controllers depending on the relevant device role.
|
||||
Some related changes were needed inside usbcore, so that it
|
||||
can identify OTG-capable devices and respond appropriately
|
||||
to HNP or SRP protocols.
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim:syntax=sgml:sw=4
|
||||
-->
|
|
@ -1,520 +0,0 @@
|
|||
<?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="Generic-IRQ-Guide">
|
||||
<bookinfo>
|
||||
<title>Linux generic IRQ handling</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Thomas</firstname>
|
||||
<surname>Gleixner</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>tglx@linutronix.de</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Ingo</firstname>
|
||||
<surname>Molnar</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>mingo@elte.hu</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2005-2010</year>
|
||||
<holder>Thomas Gleixner</holder>
|
||||
</copyright>
|
||||
<copyright>
|
||||
<year>2005-2006</year>
|
||||
<holder>Ingo Molnar</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>
|
||||
The generic interrupt handling layer is designed to provide a
|
||||
complete abstraction of interrupt handling for device drivers.
|
||||
It is able to handle all the different types of interrupt controller
|
||||
hardware. Device drivers use generic API functions to request, enable,
|
||||
disable and free interrupts. The drivers do not have to know anything
|
||||
about interrupt hardware details, so they can be used on different
|
||||
platforms without code changes.
|
||||
</para>
|
||||
<para>
|
||||
This documentation is provided to developers who want to implement
|
||||
an interrupt subsystem based for their architecture, with the help
|
||||
of the generic IRQ handling layer.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="rationale">
|
||||
<title>Rationale</title>
|
||||
<para>
|
||||
The original implementation of interrupt handling in Linux uses
|
||||
the __do_IRQ() super-handler, which is able to deal with every
|
||||
type of interrupt logic.
|
||||
</para>
|
||||
<para>
|
||||
Originally, Russell King identified different types of handlers to
|
||||
build a quite universal set for the ARM interrupt handler
|
||||
implementation in Linux 2.5/2.6. He distinguished between:
|
||||
<itemizedlist>
|
||||
<listitem><para>Level type</para></listitem>
|
||||
<listitem><para>Edge type</para></listitem>
|
||||
<listitem><para>Simple type</para></listitem>
|
||||
</itemizedlist>
|
||||
During the implementation we identified another type:
|
||||
<itemizedlist>
|
||||
<listitem><para>Fast EOI type</para></listitem>
|
||||
</itemizedlist>
|
||||
In the SMP world of the __do_IRQ() super-handler another type
|
||||
was identified:
|
||||
<itemizedlist>
|
||||
<listitem><para>Per CPU type</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
This split implementation of high-level IRQ handlers allows us to
|
||||
optimize the flow of the interrupt handling for each specific
|
||||
interrupt type. This reduces complexity in that particular code path
|
||||
and allows the optimized handling of a given type.
|
||||
</para>
|
||||
<para>
|
||||
The original general IRQ implementation used hw_interrupt_type
|
||||
structures and their ->ack(), ->end() [etc.] callbacks to
|
||||
differentiate the flow control in the super-handler. This leads to
|
||||
a mix of flow logic and low-level hardware logic, and it also leads
|
||||
to unnecessary code duplication: for example in i386, there is an
|
||||
ioapic_level_irq and an ioapic_edge_irq IRQ-type which share many
|
||||
of the low-level details but have different flow handling.
|
||||
</para>
|
||||
<para>
|
||||
A more natural abstraction is the clean separation of the
|
||||
'irq flow' and the 'chip details'.
|
||||
</para>
|
||||
<para>
|
||||
Analysing a couple of architecture's IRQ subsystem implementations
|
||||
reveals that most of them can use a generic set of 'irq flow'
|
||||
methods and only need to add the chip-level specific code.
|
||||
The separation is also valuable for (sub)architectures
|
||||
which need specific quirks in the IRQ flow itself but not in the
|
||||
chip details - and thus provides a more transparent IRQ subsystem
|
||||
design.
|
||||
</para>
|
||||
<para>
|
||||
Each interrupt descriptor is assigned its own high-level flow
|
||||
handler, which is normally one of the generic
|
||||
implementations. (This high-level flow handler implementation also
|
||||
makes it simple to provide demultiplexing handlers which can be
|
||||
found in embedded platforms on various architectures.)
|
||||
</para>
|
||||
<para>
|
||||
The separation makes the generic interrupt handling layer more
|
||||
flexible and extensible. For example, an (sub)architecture can
|
||||
use a generic IRQ-flow implementation for 'level type' interrupts
|
||||
and add a (sub)architecture specific 'edge type' implementation.
|
||||
</para>
|
||||
<para>
|
||||
To make the transition to the new model easier and prevent the
|
||||
breakage of existing implementations, the __do_IRQ() super-handler
|
||||
is still available. This leads to a kind of duality for the time
|
||||
being. Over time the new model should be used in more and more
|
||||
architectures, as it enables smaller and cleaner IRQ subsystems.
|
||||
It's deprecated for three years now and about to be removed.
|
||||
</para>
|
||||
</chapter>
|
||||
<chapter id="bugs">
|
||||
<title>Known Bugs And Assumptions</title>
|
||||
<para>
|
||||
None (knock on wood).
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="Abstraction">
|
||||
<title>Abstraction layers</title>
|
||||
<para>
|
||||
There are three main levels of abstraction in the interrupt code:
|
||||
<orderedlist>
|
||||
<listitem><para>High-level driver API</para></listitem>
|
||||
<listitem><para>High-level IRQ flow handlers</para></listitem>
|
||||
<listitem><para>Chip-level hardware encapsulation</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
<sect1 id="Interrupt_control_flow">
|
||||
<title>Interrupt control flow</title>
|
||||
<para>
|
||||
Each interrupt is described by an interrupt descriptor structure
|
||||
irq_desc. The interrupt is referenced by an 'unsigned int' numeric
|
||||
value which selects the corresponding interrupt description structure
|
||||
in the descriptor structures array.
|
||||
The descriptor structure contains status information and pointers
|
||||
to the interrupt flow method and the interrupt chip structure
|
||||
which are assigned to this interrupt.
|
||||
</para>
|
||||
<para>
|
||||
Whenever an interrupt triggers, the low-level architecture code calls
|
||||
into the generic interrupt code by calling desc->handle_irq().
|
||||
This high-level IRQ handling function only uses desc->irq_data.chip
|
||||
primitives referenced by the assigned chip descriptor structure.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="Highlevel_Driver_API">
|
||||
<title>High-level Driver API</title>
|
||||
<para>
|
||||
The high-level Driver API consists of following functions:
|
||||
<itemizedlist>
|
||||
<listitem><para>request_irq()</para></listitem>
|
||||
<listitem><para>free_irq()</para></listitem>
|
||||
<listitem><para>disable_irq()</para></listitem>
|
||||
<listitem><para>enable_irq()</para></listitem>
|
||||
<listitem><para>disable_irq_nosync() (SMP only)</para></listitem>
|
||||
<listitem><para>synchronize_irq() (SMP only)</para></listitem>
|
||||
<listitem><para>irq_set_irq_type()</para></listitem>
|
||||
<listitem><para>irq_set_irq_wake()</para></listitem>
|
||||
<listitem><para>irq_set_handler_data()</para></listitem>
|
||||
<listitem><para>irq_set_chip()</para></listitem>
|
||||
<listitem><para>irq_set_chip_data()</para></listitem>
|
||||
</itemizedlist>
|
||||
See the autogenerated function documentation for details.
|
||||
</para>
|
||||
</sect1>
|
||||
<sect1 id="Highlevel_IRQ_flow_handlers">
|
||||
<title>High-level IRQ flow handlers</title>
|
||||
<para>
|
||||
The generic layer provides a set of pre-defined irq-flow methods:
|
||||
<itemizedlist>
|
||||
<listitem><para>handle_level_irq</para></listitem>
|
||||
<listitem><para>handle_edge_irq</para></listitem>
|
||||
<listitem><para>handle_fasteoi_irq</para></listitem>
|
||||
<listitem><para>handle_simple_irq</para></listitem>
|
||||
<listitem><para>handle_percpu_irq</para></listitem>
|
||||
<listitem><para>handle_edge_eoi_irq</para></listitem>
|
||||
<listitem><para>handle_bad_irq</para></listitem>
|
||||
</itemizedlist>
|
||||
The interrupt flow handlers (either pre-defined or architecture
|
||||
specific) are assigned to specific interrupts by the architecture
|
||||
either during bootup or during device initialization.
|
||||
</para>
|
||||
<sect2 id="Default_flow_implementations">
|
||||
<title>Default flow implementations</title>
|
||||
<sect3 id="Helper_functions">
|
||||
<title>Helper functions</title>
|
||||
<para>
|
||||
The helper functions call the chip primitives and
|
||||
are used by the default flow implementations.
|
||||
The following helper functions are implemented (simplified excerpt):
|
||||
<programlisting>
|
||||
default_enable(struct irq_data *data)
|
||||
{
|
||||
desc->irq_data.chip->irq_unmask(data);
|
||||
}
|
||||
|
||||
default_disable(struct irq_data *data)
|
||||
{
|
||||
if (!delay_disable(data))
|
||||
desc->irq_data.chip->irq_mask(data);
|
||||
}
|
||||
|
||||
default_ack(struct irq_data *data)
|
||||
{
|
||||
chip->irq_ack(data);
|
||||
}
|
||||
|
||||
default_mask_ack(struct irq_data *data)
|
||||
{
|
||||
if (chip->irq_mask_ack) {
|
||||
chip->irq_mask_ack(data);
|
||||
} else {
|
||||
chip->irq_mask(data);
|
||||
chip->irq_ack(data);
|
||||
}
|
||||
}
|
||||
|
||||
noop(struct irq_data *data))
|
||||
{
|
||||
}
|
||||
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
<sect2 id="Default_flow_handler_implementations">
|
||||
<title>Default flow handler implementations</title>
|
||||
<sect3 id="Default_Level_IRQ_flow_handler">
|
||||
<title>Default Level IRQ flow handler</title>
|
||||
<para>
|
||||
handle_level_irq provides a generic implementation
|
||||
for level-triggered interrupts.
|
||||
</para>
|
||||
<para>
|
||||
The following control flow is implemented (simplified excerpt):
|
||||
<programlisting>
|
||||
desc->irq_data.chip->irq_mask_ack();
|
||||
handle_irq_event(desc->action);
|
||||
desc->irq_data.chip->irq_unmask();
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3 id="Default_FASTEOI_IRQ_flow_handler">
|
||||
<title>Default Fast EOI IRQ flow handler</title>
|
||||
<para>
|
||||
handle_fasteoi_irq provides a generic implementation
|
||||
for interrupts, which only need an EOI at the end of
|
||||
the handler.
|
||||
</para>
|
||||
<para>
|
||||
The following control flow is implemented (simplified excerpt):
|
||||
<programlisting>
|
||||
handle_irq_event(desc->action);
|
||||
desc->irq_data.chip->irq_eoi();
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3 id="Default_Edge_IRQ_flow_handler">
|
||||
<title>Default Edge IRQ flow handler</title>
|
||||
<para>
|
||||
handle_edge_irq provides a generic implementation
|
||||
for edge-triggered interrupts.
|
||||
</para>
|
||||
<para>
|
||||
The following control flow is implemented (simplified excerpt):
|
||||
<programlisting>
|
||||
if (desc->status & running) {
|
||||
desc->irq_data.chip->irq_mask_ack();
|
||||
desc->status |= pending | masked;
|
||||
return;
|
||||
}
|
||||
desc->irq_data.chip->irq_ack();
|
||||
desc->status |= running;
|
||||
do {
|
||||
if (desc->status & masked)
|
||||
desc->irq_data.chip->irq_unmask();
|
||||
desc->status &= ~pending;
|
||||
handle_irq_event(desc->action);
|
||||
} while (status & pending);
|
||||
desc->status &= ~running;
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3 id="Default_simple_IRQ_flow_handler">
|
||||
<title>Default simple IRQ flow handler</title>
|
||||
<para>
|
||||
handle_simple_irq provides a generic implementation
|
||||
for simple interrupts.
|
||||
</para>
|
||||
<para>
|
||||
Note: The simple flow handler does not call any
|
||||
handler/chip primitives.
|
||||
</para>
|
||||
<para>
|
||||
The following control flow is implemented (simplified excerpt):
|
||||
<programlisting>
|
||||
handle_irq_event(desc->action);
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3 id="Default_per_CPU_flow_handler">
|
||||
<title>Default per CPU flow handler</title>
|
||||
<para>
|
||||
handle_percpu_irq provides a generic implementation
|
||||
for per CPU interrupts.
|
||||
</para>
|
||||
<para>
|
||||
Per CPU interrupts are only available on SMP and
|
||||
the handler provides a simplified version without
|
||||
locking.
|
||||
</para>
|
||||
<para>
|
||||
The following control flow is implemented (simplified excerpt):
|
||||
<programlisting>
|
||||
if (desc->irq_data.chip->irq_ack)
|
||||
desc->irq_data.chip->irq_ack();
|
||||
handle_irq_event(desc->action);
|
||||
if (desc->irq_data.chip->irq_eoi)
|
||||
desc->irq_data.chip->irq_eoi();
|
||||
</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3 id="EOI_Edge_IRQ_flow_handler">
|
||||
<title>EOI Edge IRQ flow handler</title>
|
||||
<para>
|
||||
handle_edge_eoi_irq provides an abnomination of the edge
|
||||
handler which is solely used to tame a badly wreckaged
|
||||
irq controller on powerpc/cell.
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3 id="BAD_IRQ_flow_handler">
|
||||
<title>Bad IRQ flow handler</title>
|
||||
<para>
|
||||
handle_bad_irq is used for spurious interrupts which
|
||||
have no real handler assigned..
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
<sect2 id="Quirks_and_optimizations">
|
||||
<title>Quirks and optimizations</title>
|
||||
<para>
|
||||
The generic functions are intended for 'clean' architectures and chips,
|
||||
which have no platform-specific IRQ handling quirks. If an architecture
|
||||
needs to implement quirks on the 'flow' level then it can do so by
|
||||
overriding the high-level irq-flow handler.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="Delayed_interrupt_disable">
|
||||
<title>Delayed interrupt disable</title>
|
||||
<para>
|
||||
This per interrupt selectable feature, which was introduced by Russell
|
||||
King in the ARM interrupt implementation, does not mask an interrupt
|
||||
at the hardware level when disable_irq() is called. The interrupt is
|
||||
kept enabled and is masked in the flow handler when an interrupt event
|
||||
happens. This prevents losing edge interrupts on hardware which does
|
||||
not store an edge interrupt event while the interrupt is disabled at
|
||||
the hardware level. When an interrupt arrives while the IRQ_DISABLED
|
||||
flag is set, then the interrupt is masked at the hardware level and
|
||||
the IRQ_PENDING bit is set. When the interrupt is re-enabled by
|
||||
enable_irq() the pending bit is checked and if it is set, the
|
||||
interrupt is resent either via hardware or by a software resend
|
||||
mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when
|
||||
you want to use the delayed interrupt disable feature and your
|
||||
hardware is not capable of retriggering an interrupt.)
|
||||
The delayed interrupt disable is not configurable.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1 id="Chiplevel_hardware_encapsulation">
|
||||
<title>Chip-level hardware encapsulation</title>
|
||||
<para>
|
||||
The chip-level hardware descriptor structure irq_chip
|
||||
contains all the direct chip relevant functions, which
|
||||
can be utilized by the irq flow implementations.
|
||||
<itemizedlist>
|
||||
<listitem><para>irq_ack()</para></listitem>
|
||||
<listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
|
||||
<listitem><para>irq_mask()</para></listitem>
|
||||
<listitem><para>irq_unmask()</para></listitem>
|
||||
<listitem><para>irq_eoi() - Optional, required for EOI flow handlers</para></listitem>
|
||||
<listitem><para>irq_retrigger() - Optional</para></listitem>
|
||||
<listitem><para>irq_set_type() - Optional</para></listitem>
|
||||
<listitem><para>irq_set_wake() - Optional</para></listitem>
|
||||
</itemizedlist>
|
||||
These primitives are strictly intended to mean what they say: ack means
|
||||
ACK, masking means masking of an IRQ line, etc. It is up to the flow
|
||||
handler(s) to use these basic units of low-level functionality.
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="doirq">
|
||||
<title>__do_IRQ entry point</title>
|
||||
<para>
|
||||
The original implementation __do_IRQ() was an alternative entry
|
||||
point for all types of interrupts. It no longer exists.
|
||||
</para>
|
||||
<para>
|
||||
This handler turned out to be not suitable for all
|
||||
interrupt hardware and was therefore reimplemented with split
|
||||
functionality for edge/level/simple/percpu interrupts. This is not
|
||||
only a functional optimization. It also shortens code paths for
|
||||
interrupts.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="locking">
|
||||
<title>Locking on SMP</title>
|
||||
<para>
|
||||
The locking of chip registers is up to the architecture that
|
||||
defines the chip primitives. The per-irq structure is
|
||||
protected via desc->lock, by the generic layer.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="genericchip">
|
||||
<title>Generic interrupt chip</title>
|
||||
<para>
|
||||
To avoid copies of identical implementations of IRQ chips the
|
||||
core provides a configurable generic interrupt chip
|
||||
implementation. Developers should check carefully whether the
|
||||
generic chip fits their needs before implementing the same
|
||||
functionality slightly differently themselves.
|
||||
</para>
|
||||
!Ekernel/irq/generic-chip.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="structs">
|
||||
<title>Structures</title>
|
||||
<para>
|
||||
This chapter contains the autogenerated documentation of the structures which are
|
||||
used in the generic IRQ layer.
|
||||
</para>
|
||||
!Iinclude/linux/irq.h
|
||||
!Iinclude/linux/interrupt.h
|
||||
</chapter>
|
||||
|
||||
<chapter id="pubfunctions">
|
||||
<title>Public Functions Provided</title>
|
||||
<para>
|
||||
This chapter contains the autogenerated documentation of the kernel API functions
|
||||
which are exported.
|
||||
</para>
|
||||
!Ekernel/irq/manage.c
|
||||
!Ekernel/irq/chip.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="intfunctions">
|
||||
<title>Internal Functions Provided</title>
|
||||
<para>
|
||||
This chapter contains the autogenerated documentation of the internal functions.
|
||||
</para>
|
||||
!Ikernel/irq/irqdesc.c
|
||||
!Ikernel/irq/handle.c
|
||||
!Ikernel/irq/chip.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="credits">
|
||||
<title>Credits</title>
|
||||
<para>
|
||||
The following people have contributed to this document:
|
||||
<orderedlist>
|
||||
<listitem><para>Thomas Gleixner<email>tglx@linutronix.de</email></para></listitem>
|
||||
<listitem><para>Ingo Molnar<email>mingo@elte.hu</email></para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</chapter>
|
||||
</book>
|
|
@ -1,331 +0,0 @@
|
|||
<?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="LinuxKernelAPI">
|
||||
<bookinfo>
|
||||
<title>The Linux Kernel API</title>
|
||||
|
||||
<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="adt">
|
||||
<title>Data Types</title>
|
||||
<sect1><title>Doubly Linked Lists</title>
|
||||
!Iinclude/linux/list.h
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="libc">
|
||||
<title>Basic C Library Functions</title>
|
||||
|
||||
<para>
|
||||
When writing drivers, you cannot in general use routines which are
|
||||
from the C Library. Some of the functions have been found generally
|
||||
useful and they are listed below. The behaviour of these functions
|
||||
may vary slightly from those defined by ANSI, and these deviations
|
||||
are noted in the text.
|
||||
</para>
|
||||
|
||||
<sect1><title>String Conversions</title>
|
||||
!Elib/vsprintf.c
|
||||
!Finclude/linux/kernel.h kstrtol
|
||||
!Finclude/linux/kernel.h kstrtoul
|
||||
!Elib/kstrtox.c
|
||||
</sect1>
|
||||
<sect1><title>String Manipulation</title>
|
||||
<!-- All functions are exported at now
|
||||
X!Ilib/string.c
|
||||
-->
|
||||
!Elib/string.c
|
||||
</sect1>
|
||||
<sect1><title>Bit Operations</title>
|
||||
!Iarch/x86/include/asm/bitops.h
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="kernel-lib">
|
||||
<title>Basic Kernel Library Functions</title>
|
||||
|
||||
<para>
|
||||
The Linux kernel provides more basic utility functions.
|
||||
</para>
|
||||
|
||||
<sect1><title>Bitmap Operations</title>
|
||||
!Elib/bitmap.c
|
||||
!Ilib/bitmap.c
|
||||
</sect1>
|
||||
|
||||
<sect1><title>Command-line Parsing</title>
|
||||
!Elib/cmdline.c
|
||||
</sect1>
|
||||
|
||||
<sect1 id="crc"><title>CRC Functions</title>
|
||||
!Elib/crc7.c
|
||||
!Elib/crc16.c
|
||||
!Elib/crc-itu-t.c
|
||||
!Elib/crc32.c
|
||||
!Elib/crc-ccitt.c
|
||||
</sect1>
|
||||
|
||||
<sect1 id="idr"><title>idr/ida Functions</title>
|
||||
!Pinclude/linux/idr.h idr sync
|
||||
!Plib/idr.c IDA description
|
||||
!Elib/idr.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="mm">
|
||||
<title>Memory Management in Linux</title>
|
||||
<sect1><title>The Slab Cache</title>
|
||||
!Iinclude/linux/slab.h
|
||||
!Emm/slab.c
|
||||
!Emm/util.c
|
||||
</sect1>
|
||||
<sect1><title>User Space Memory Access</title>
|
||||
!Iarch/x86/include/asm/uaccess_32.h
|
||||
!Earch/x86/lib/usercopy_32.c
|
||||
</sect1>
|
||||
<sect1><title>More Memory Management Functions</title>
|
||||
!Emm/readahead.c
|
||||
!Emm/filemap.c
|
||||
!Emm/memory.c
|
||||
!Emm/vmalloc.c
|
||||
!Imm/page_alloc.c
|
||||
!Emm/mempool.c
|
||||
!Emm/dmapool.c
|
||||
!Emm/page-writeback.c
|
||||
!Emm/truncate.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
|
||||
<chapter id="ipc">
|
||||
<title>Kernel IPC facilities</title>
|
||||
|
||||
<sect1><title>IPC utilities</title>
|
||||
!Iipc/util.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="kfifo">
|
||||
<title>FIFO Buffer</title>
|
||||
<sect1><title>kfifo interface</title>
|
||||
!Iinclude/linux/kfifo.h
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="relayfs">
|
||||
<title>relay interface support</title>
|
||||
|
||||
<para>
|
||||
Relay interface support
|
||||
is designed to provide an efficient mechanism for tools and
|
||||
facilities to relay large amounts of data from kernel space to
|
||||
user space.
|
||||
</para>
|
||||
|
||||
<sect1><title>relay interface</title>
|
||||
!Ekernel/relay.c
|
||||
!Ikernel/relay.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="modload">
|
||||
<title>Module Support</title>
|
||||
<sect1><title>Module Loading</title>
|
||||
!Ekernel/kmod.c
|
||||
</sect1>
|
||||
<sect1><title>Inter Module support</title>
|
||||
<para>
|
||||
Refer to the file kernel/module.c for more information.
|
||||
</para>
|
||||
<!-- FIXME: Removed for now since no structured comments in source
|
||||
X!Ekernel/module.c
|
||||
-->
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="hardware">
|
||||
<title>Hardware Interfaces</title>
|
||||
<sect1><title>Interrupt Handling</title>
|
||||
!Ekernel/irq/manage.c
|
||||
</sect1>
|
||||
|
||||
<sect1><title>DMA Channels</title>
|
||||
!Ekernel/dma.c
|
||||
</sect1>
|
||||
|
||||
<sect1><title>Resources Management</title>
|
||||
!Ikernel/resource.c
|
||||
!Ekernel/resource.c
|
||||
</sect1>
|
||||
|
||||
<sect1><title>MTRR Handling</title>
|
||||
!Earch/x86/kernel/cpu/mtrr/main.c
|
||||
</sect1>
|
||||
|
||||
<sect1><title>PCI Support Library</title>
|
||||
!Edrivers/pci/pci.c
|
||||
!Edrivers/pci/pci-driver.c
|
||||
!Edrivers/pci/remove.c
|
||||
!Edrivers/pci/search.c
|
||||
!Edrivers/pci/msi.c
|
||||
!Edrivers/pci/bus.c
|
||||
!Edrivers/pci/access.c
|
||||
!Edrivers/pci/irq.c
|
||||
!Edrivers/pci/htirq.c
|
||||
<!-- FIXME: Removed for now since no structured comments in source
|
||||
X!Edrivers/pci/hotplug.c
|
||||
-->
|
||||
!Edrivers/pci/probe.c
|
||||
!Edrivers/pci/slot.c
|
||||
!Edrivers/pci/rom.c
|
||||
!Edrivers/pci/iov.c
|
||||
!Idrivers/pci/pci-sysfs.c
|
||||
</sect1>
|
||||
<sect1><title>PCI Hotplug Support Library</title>
|
||||
!Edrivers/pci/hotplug/pci_hotplug_core.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="firmware">
|
||||
<title>Firmware Interfaces</title>
|
||||
<sect1><title>DMI Interfaces</title>
|
||||
!Edrivers/firmware/dmi_scan.c
|
||||
</sect1>
|
||||
<sect1><title>EDD Interfaces</title>
|
||||
!Idrivers/firmware/edd.c
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
<chapter id="security">
|
||||
<title>Security Framework</title>
|
||||
!Isecurity/security.c
|
||||
!Esecurity/inode.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="audit">
|
||||
<title>Audit Interfaces</title>
|
||||
!Ekernel/audit.c
|
||||
!Ikernel/auditsc.c
|
||||
!Ikernel/auditfilter.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="accounting">
|
||||
<title>Accounting Framework</title>
|
||||
!Ikernel/acct.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="blkdev">
|
||||
<title>Block Devices</title>
|
||||
!Eblock/blk-core.c
|
||||
!Iblock/blk-core.c
|
||||
!Eblock/blk-map.c
|
||||
!Iblock/blk-sysfs.c
|
||||
!Eblock/blk-settings.c
|
||||
!Eblock/blk-exec.c
|
||||
!Eblock/blk-flush.c
|
||||
!Eblock/blk-lib.c
|
||||
!Eblock/blk-tag.c
|
||||
!Iblock/blk-tag.c
|
||||
!Eblock/blk-integrity.c
|
||||
!Ikernel/trace/blktrace.c
|
||||
!Iblock/genhd.c
|
||||
!Eblock/genhd.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="chrdev">
|
||||
<title>Char devices</title>
|
||||
!Efs/char_dev.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="miscdev">
|
||||
<title>Miscellaneous Devices</title>
|
||||
!Edrivers/char/misc.c
|
||||
</chapter>
|
||||
|
||||
<chapter id="clk">
|
||||
<title>Clock Framework</title>
|
||||
|
||||
<para>
|
||||
The clock framework defines programming interfaces to support
|
||||
software management of the system clock tree.
|
||||
This framework is widely used with System-On-Chip (SOC) platforms
|
||||
to support power management and various devices which may need
|
||||
custom clock rates.
|
||||
Note that these "clocks" don't relate to timekeeping or real
|
||||
time clocks (RTCs), each of which have separate frameworks.
|
||||
These <structname>struct clk</structname> instances may be used
|
||||
to manage for example a 96 MHz signal that is used to shift bits
|
||||
into and out of peripherals or busses, or otherwise trigger
|
||||
synchronous state machine transitions in system hardware.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Power management is supported by explicit software clock gating:
|
||||
unused clocks are disabled, so the system doesn't waste power
|
||||
changing the state of transistors that aren't in active use.
|
||||
On some systems this may be backed by hardware clock gating,
|
||||
where clocks are gated without being disabled in software.
|
||||
Sections of chips that are powered but not clocked may be able
|
||||
to retain their last state.
|
||||
This low power state is often called a <emphasis>retention
|
||||
mode</emphasis>.
|
||||
This mode still incurs leakage currents, especially with finer
|
||||
circuit geometries, but for CMOS circuits power is mostly used
|
||||
by clocked state changes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Power-aware drivers only enable their clocks when the device
|
||||
they manage is in active use. Also, system sleep states often
|
||||
differ according to which clock domains are active: while a
|
||||
"standby" state may allow wakeup from several active domains, a
|
||||
"mem" (suspend-to-RAM) state may require a more wholesale shutdown
|
||||
of clocks derived from higher speed PLLs and oscillators, limiting
|
||||
the number of possible wakeup event sources. A driver's suspend
|
||||
method may need to be aware of system-specific clock constraints
|
||||
on the target sleep state.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Some platforms support programmable clock generators. These
|
||||
can be used by external chips of various kinds, such as other
|
||||
CPUs, multimedia codecs, and devices with strict requirements
|
||||
for interface clocking.
|
||||
</para>
|
||||
|
||||
!Iinclude/linux/clk.h
|
||||
</chapter>
|
||||
|
||||
</book>
|
|
@ -1,873 +0,0 @@
|
|||
<?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="Writing-MUSB-Glue-Layer">
|
||||
<bookinfo>
|
||||
<title>Writing an MUSB Glue Layer</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Apelete</firstname>
|
||||
<surname>Seketeli</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>apelete at seketeli.net</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2014</year>
|
||||
<holder>Apelete Seketeli</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 documentation 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 documentation; 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 Linux kernel source
|
||||
tree.
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="introduction">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
The Linux MUSB subsystem is part of the larger Linux USB
|
||||
subsystem. It provides support for embedded USB Device Controllers
|
||||
(UDC) that do not use Universal Host Controller Interface (UHCI)
|
||||
or Open Host Controller Interface (OHCI).
|
||||
</para>
|
||||
<para>
|
||||
Instead, these embedded UDC rely on the USB On-the-Go (OTG)
|
||||
specification which they implement at least partially. The silicon
|
||||
reference design used in most cases is the Multipoint USB
|
||||
Highspeed Dual-Role Controller (MUSB HDRC) found in the Mentor
|
||||
Graphics Inventra™ design.
|
||||
</para>
|
||||
<para>
|
||||
As a self-taught exercise I have written an MUSB glue layer for
|
||||
the Ingenic JZ4740 SoC, modelled after the many MUSB glue layers
|
||||
in the kernel source tree. This layer can be found at
|
||||
drivers/usb/musb/jz4740.c. In this documentation I will walk
|
||||
through the basics of the jz4740.c glue layer, explaining the
|
||||
different pieces and what needs to be done in order to write your
|
||||
own device glue layer.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="linux-musb-basics">
|
||||
<title>Linux MUSB Basics</title>
|
||||
<para>
|
||||
To get started on the topic, please read USB On-the-Go Basics (see
|
||||
Resources) which provides an introduction of USB OTG operation at
|
||||
the hardware level. A couple of wiki pages by Texas Instruments
|
||||
and Analog Devices also provide an overview of the Linux kernel
|
||||
MUSB configuration, albeit focused on some specific devices
|
||||
provided by these companies. Finally, getting acquainted with the
|
||||
USB specification at USB home page may come in handy, with
|
||||
practical instance provided through the Writing USB Device Drivers
|
||||
documentation (again, see Resources).
|
||||
</para>
|
||||
<para>
|
||||
Linux USB stack is a layered architecture in which the MUSB
|
||||
controller hardware sits at the lowest. The MUSB controller driver
|
||||
abstract the MUSB controller hardware to the Linux USB stack.
|
||||
</para>
|
||||
<programlisting>
|
||||
------------------------
|
||||
| | <------- drivers/usb/gadget
|
||||
| Linux USB Core Stack | <------- drivers/usb/host
|
||||
| | <------- drivers/usb/core
|
||||
------------------------
|
||||
⬍
|
||||
--------------------------
|
||||
| | <------ drivers/usb/musb/musb_gadget.c
|
||||
| MUSB Controller driver | <------ drivers/usb/musb/musb_host.c
|
||||
| | <------ drivers/usb/musb/musb_core.c
|
||||
--------------------------
|
||||
⬍
|
||||
---------------------------------
|
||||
| MUSB Platform Specific Driver |
|
||||
| | <-- drivers/usb/musb/jz4740.c
|
||||
| aka "Glue Layer" |
|
||||
---------------------------------
|
||||
⬍
|
||||
---------------------------------
|
||||
| MUSB Controller Hardware |
|
||||
---------------------------------
|
||||
</programlisting>
|
||||
<para>
|
||||
As outlined above, the glue layer is actually the platform
|
||||
specific code sitting in between the controller driver and the
|
||||
controller hardware.
|
||||
</para>
|
||||
<para>
|
||||
Just like a Linux USB driver needs to register itself with the
|
||||
Linux USB subsystem, the MUSB glue layer needs first to register
|
||||
itself with the MUSB controller driver. This will allow the
|
||||
controller driver to know about which device the glue layer
|
||||
supports and which functions to call when a supported device is
|
||||
detected or released; remember we are talking about an embedded
|
||||
controller chip here, so no insertion or removal at run-time.
|
||||
</para>
|
||||
<para>
|
||||
All of this information is passed to the MUSB controller driver
|
||||
through a platform_driver structure defined in the glue layer as:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static struct platform_driver jz4740_driver = {
|
||||
.probe = jz4740_probe,
|
||||
.remove = jz4740_remove,
|
||||
.driver = {
|
||||
.name = "musb-jz4740",
|
||||
},
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
The probe and remove function pointers are called when a matching
|
||||
device is detected and, respectively, released. The name string
|
||||
describes the device supported by this glue layer. In the current
|
||||
case it matches a platform_device structure declared in
|
||||
arch/mips/jz4740/platform.c. Note that we are not using device
|
||||
tree bindings here.
|
||||
</para>
|
||||
<para>
|
||||
In order to register itself to the controller driver, the glue
|
||||
layer goes through a few steps, basically allocating the
|
||||
controller hardware resources and initialising a couple of
|
||||
circuits. To do so, it needs to keep track of the information used
|
||||
throughout these steps. This is done by defining a private
|
||||
jz4740_glue structure:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
struct jz4740_glue {
|
||||
struct device *dev;
|
||||
struct platform_device *musb;
|
||||
struct clk *clk;
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
The dev and musb members are both device structure variables. The
|
||||
first one holds generic information about the device, since it's
|
||||
the basic device structure, and the latter holds information more
|
||||
closely related to the subsystem the device is registered to. The
|
||||
clk variable keeps information related to the device clock
|
||||
operation.
|
||||
</para>
|
||||
<para>
|
||||
Let's go through the steps of the probe function that leads the
|
||||
glue layer to register itself to the controller driver.
|
||||
</para>
|
||||
<para>
|
||||
N.B.: For the sake of readability each function will be split in
|
||||
logical parts, each part being shown as if it was independent from
|
||||
the others.
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_device *musb;
|
||||
struct jz4740_glue *glue;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
|
||||
if (!glue)
|
||||
return -ENOMEM;
|
||||
|
||||
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
|
||||
if (!musb) {
|
||||
dev_err(&pdev->dev, "failed to allocate musb device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk = devm_clk_get(&pdev->dev, "udc");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
ret = PTR_ERR(clk);
|
||||
goto err_platform_device_put;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock\n");
|
||||
goto err_platform_device_put;
|
||||
}
|
||||
|
||||
musb->dev.parent = &pdev->dev;
|
||||
|
||||
glue->dev = &pdev->dev;
|
||||
glue->musb = musb;
|
||||
glue->clk = clk;
|
||||
|
||||
return 0;
|
||||
|
||||
err_platform_device_put:
|
||||
platform_device_put(musb);
|
||||
return ret;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
The first few lines of the probe function allocate and assign the
|
||||
glue, musb and clk variables. The GFP_KERNEL flag (line 8) allows
|
||||
the allocation process to sleep and wait for memory, thus being
|
||||
usable in a blocking situation. The PLATFORM_DEVID_AUTO flag (line
|
||||
12) allows automatic allocation and management of device IDs in
|
||||
order to avoid device namespace collisions with explicit IDs. With
|
||||
devm_clk_get() (line 18) the glue layer allocates the clock -- the
|
||||
<literal>devm_</literal> prefix indicates that clk_get() is
|
||||
managed: it automatically frees the allocated clock resource data
|
||||
when the device is released -- and enable it.
|
||||
</para>
|
||||
<para>
|
||||
Then comes the registration steps:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data;
|
||||
|
||||
pdata->platform_ops = &jz4740_musb_ops;
|
||||
|
||||
platform_set_drvdata(pdev, glue);
|
||||
|
||||
ret = platform_device_add_resources(musb, pdev->resource,
|
||||
pdev->num_resources);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add resources\n");
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add platform_data\n");
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
err_platform_device_put:
|
||||
platform_device_put(musb);
|
||||
return ret;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
The first step is to pass the device data privately held by the
|
||||
glue layer on to the controller driver through
|
||||
platform_set_drvdata() (line 7). Next is passing on the device
|
||||
resources information, also privately held at that point, through
|
||||
platform_device_add_resources() (line 9).
|
||||
</para>
|
||||
<para>
|
||||
Finally comes passing on the platform specific data to the
|
||||
controller driver (line 16). Platform data will be discussed in
|
||||
<link linkend="device-platform-data">Chapter 4</link>, but here
|
||||
we are looking at the platform_ops function pointer (line 5) in
|
||||
musb_hdrc_platform_data structure (line 3). This function
|
||||
pointer allows the MUSB controller driver to know which function
|
||||
to call for device operation:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static const struct musb_platform_ops jz4740_musb_ops = {
|
||||
.init = jz4740_musb_init,
|
||||
.exit = jz4740_musb_exit,
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
Here we have the minimal case where only init and exit functions
|
||||
are called by the controller driver when needed. Fact is the
|
||||
JZ4740 MUSB controller is a basic controller, lacking some
|
||||
features found in other controllers, otherwise we may also have
|
||||
pointers to a few other functions like a power management function
|
||||
or a function to switch between OTG and non-OTG modes, for
|
||||
instance.
|
||||
</para>
|
||||
<para>
|
||||
At that point of the registration process, the controller driver
|
||||
actually calls the init function:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_musb_init(struct musb *musb)
|
||||
{
|
||||
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||
if (!musb->xceiv) {
|
||||
pr_err("HS UDC: no transceiver configured\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Silicon does not implement ConfigData register.
|
||||
* Set dyn_fifo to avoid reading EP config from hardware.
|
||||
*/
|
||||
musb->dyn_fifo = true;
|
||||
|
||||
musb->isr = jz4740_musb_interrupt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
The goal of jz4740_musb_init() is to get hold of the transceiver
|
||||
driver data of the MUSB controller hardware and pass it on to the
|
||||
MUSB controller driver, as usual. The transceiver is the circuitry
|
||||
inside the controller hardware responsible for sending/receiving
|
||||
the USB data. Since it is an implementation of the physical layer
|
||||
of the OSI model, the transceiver is also referred to as PHY.
|
||||
</para>
|
||||
<para>
|
||||
Getting hold of the MUSB PHY driver data is done with
|
||||
usb_get_phy() which returns a pointer to the structure
|
||||
containing the driver instance data. The next couple of
|
||||
instructions (line 12 and 14) are used as a quirk and to setup
|
||||
IRQ handling respectively. Quirks and IRQ handling will be
|
||||
discussed later in <link linkend="device-quirks">Chapter
|
||||
5</link> and <link linkend="handling-irqs">Chapter 3</link>.
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_musb_exit(struct musb *musb)
|
||||
{
|
||||
usb_put_phy(musb->xceiv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Acting as the counterpart of init, the exit function releases the
|
||||
MUSB PHY driver when the controller hardware itself is about to be
|
||||
released.
|
||||
</para>
|
||||
<para>
|
||||
Again, note that init and exit are fairly simple in this case due
|
||||
to the basic set of features of the JZ4740 controller hardware.
|
||||
When writing an musb glue layer for a more complex controller
|
||||
hardware, you might need to take care of more processing in those
|
||||
two functions.
|
||||
</para>
|
||||
<para>
|
||||
Returning from the init function, the MUSB controller driver jumps
|
||||
back into the probe function:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_probe(struct platform_device *pdev)
|
||||
{
|
||||
ret = platform_device_add(musb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register musb device\n");
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
err_platform_device_put:
|
||||
platform_device_put(musb);
|
||||
return ret;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
This is the last part of the device registration process where the
|
||||
glue layer adds the controller hardware device to Linux kernel
|
||||
device hierarchy: at this stage, all known information about the
|
||||
device is passed on to the Linux USB core stack.
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct jz4740_glue *glue = platform_get_drvdata(pdev);
|
||||
|
||||
platform_device_unregister(glue->musb);
|
||||
clk_disable_unprepare(glue->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Acting as the counterpart of probe, the remove function unregister
|
||||
the MUSB controller hardware (line 5) and disable the clock (line
|
||||
6), allowing it to be gated.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="handling-irqs">
|
||||
<title>Handling IRQs</title>
|
||||
<para>
|
||||
Additionally to the MUSB controller hardware basic setup and
|
||||
registration, the glue layer is also responsible for handling the
|
||||
IRQs:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
|
||||
{
|
||||
unsigned long flags;
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
struct musb *musb = __hci;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
|
||||
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
|
||||
musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
|
||||
|
||||
/*
|
||||
* The controller is gadget only, the state of the host mode IRQ bits is
|
||||
* undefined. Mask them to make sure that the musb driver core will
|
||||
* never see them set
|
||||
*/
|
||||
musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
|
||||
MUSB_INTR_RESET | MUSB_INTR_SOF;
|
||||
|
||||
if (musb->int_usb || musb->int_tx || musb->int_rx)
|
||||
retval = musb_interrupt(musb);
|
||||
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Here the glue layer mostly has to read the relevant hardware
|
||||
registers and pass their values on to the controller driver which
|
||||
will handle the actual event that triggered the IRQ.
|
||||
</para>
|
||||
<para>
|
||||
The interrupt handler critical section is protected by the
|
||||
spin_lock_irqsave() and counterpart spin_unlock_irqrestore()
|
||||
functions (line 7 and 24 respectively), which prevent the
|
||||
interrupt handler code to be run by two different threads at the
|
||||
same time.
|
||||
</para>
|
||||
<para>
|
||||
Then the relevant interrupt registers are read (line 9 to 11):
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
MUSB_INTRUSB: indicates which USB interrupts are currently
|
||||
active,
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
MUSB_INTRTX: indicates which of the interrupts for TX
|
||||
endpoints are currently active,
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
MUSB_INTRRX: indicates which of the interrupts for TX
|
||||
endpoints are currently active.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Note that musb_readb() is used to read 8-bit registers at most,
|
||||
while musb_readw() allows us to read at most 16-bit registers.
|
||||
There are other functions that can be used depending on the size
|
||||
of your device registers. See musb_io.h for more information.
|
||||
</para>
|
||||
<para>
|
||||
Instruction on line 18 is another quirk specific to the JZ4740
|
||||
USB device controller, which will be discussed later in <link
|
||||
linkend="device-quirks">Chapter 5</link>.
|
||||
</para>
|
||||
<para>
|
||||
The glue layer still needs to register the IRQ handler though.
|
||||
Remember the instruction on line 14 of the init function:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_musb_init(struct musb *musb)
|
||||
{
|
||||
musb->isr = jz4740_musb_interrupt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
This instruction sets a pointer to the glue layer IRQ handler
|
||||
function, in order for the controller hardware to call the handler
|
||||
back when an IRQ comes from the controller hardware. The interrupt
|
||||
handler is now implemented and registered.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="device-platform-data">
|
||||
<title>Device Platform Data</title>
|
||||
<para>
|
||||
In order to write an MUSB glue layer, you need to have some data
|
||||
describing the hardware capabilities of your controller hardware,
|
||||
which is called the platform data.
|
||||
</para>
|
||||
<para>
|
||||
Platform data is specific to your hardware, though it may cover a
|
||||
broad range of devices, and is generally found somewhere in the
|
||||
arch/ directory, depending on your device architecture.
|
||||
</para>
|
||||
<para>
|
||||
For instance, platform data for the JZ4740 SoC is found in
|
||||
arch/mips/jz4740/platform.c. In the platform.c file each device of
|
||||
the JZ4740 SoC is described through a set of structures.
|
||||
</para>
|
||||
<para>
|
||||
Here is the part of arch/mips/jz4740/platform.c that covers the
|
||||
USB Device Controller (UDC):
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
/* USB Device Controller */
|
||||
struct platform_device jz4740_udc_xceiv_device = {
|
||||
.name = "usb_phy_gen_xceiv",
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
static struct resource jz4740_udc_resources[] = {
|
||||
[0] = {
|
||||
.start = JZ4740_UDC_BASE_ADDR,
|
||||
.end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = JZ4740_IRQ_UDC,
|
||||
.end = JZ4740_IRQ_UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
.name = "mc",
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device jz4740_udc_device = {
|
||||
.name = "musb-jz4740",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &jz4740_udc_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz4740_udc_resources),
|
||||
.resource = jz4740_udc_resources,
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
The jz4740_udc_xceiv_device platform device structure (line 2)
|
||||
describes the UDC transceiver with a name and id number.
|
||||
</para>
|
||||
<para>
|
||||
At the time of this writing, note that
|
||||
"usb_phy_gen_xceiv" is the specific name to be used for
|
||||
all transceivers that are either built-in with reference USB IP or
|
||||
autonomous and doesn't require any PHY programming. You will need
|
||||
to set CONFIG_NOP_USB_XCEIV=y in the kernel configuration to make
|
||||
use of the corresponding transceiver driver. The id field could be
|
||||
set to -1 (equivalent to PLATFORM_DEVID_NONE), -2 (equivalent to
|
||||
PLATFORM_DEVID_AUTO) or start with 0 for the first device of this
|
||||
kind if we want a specific id number.
|
||||
</para>
|
||||
<para>
|
||||
The jz4740_udc_resources resource structure (line 7) defines the
|
||||
UDC registers base addresses.
|
||||
</para>
|
||||
<para>
|
||||
The first array (line 9 to 11) defines the UDC registers base
|
||||
memory addresses: start points to the first register memory
|
||||
address, end points to the last register memory address and the
|
||||
flags member defines the type of resource we are dealing with. So
|
||||
IORESOURCE_MEM is used to define the registers memory addresses.
|
||||
The second array (line 14 to 17) defines the UDC IRQ registers
|
||||
addresses. Since there is only one IRQ register available for the
|
||||
JZ4740 UDC, start and end point at the same address. The
|
||||
IORESOURCE_IRQ flag tells that we are dealing with IRQ resources,
|
||||
and the name "mc" is in fact hard-coded in the MUSB core
|
||||
in order for the controller driver to retrieve this IRQ resource
|
||||
by querying it by its name.
|
||||
</para>
|
||||
<para>
|
||||
Finally, the jz4740_udc_device platform device structure (line 21)
|
||||
describes the UDC itself.
|
||||
</para>
|
||||
<para>
|
||||
The "musb-jz4740" name (line 22) defines the MUSB
|
||||
driver that is used for this device; remember this is in fact
|
||||
the name that we used in the jz4740_driver platform driver
|
||||
structure in <link linkend="linux-musb-basics">Chapter
|
||||
2</link>. The id field (line 23) is set to -1 (equivalent to
|
||||
PLATFORM_DEVID_NONE) since we do not need an id for the device:
|
||||
the MUSB controller driver was already set to allocate an
|
||||
automatic id in <link linkend="linux-musb-basics">Chapter
|
||||
2</link>. In the dev field we care for DMA related information
|
||||
here. The dma_mask field (line 25) defines the width of the DMA
|
||||
mask that is going to be used, and coherent_dma_mask (line 26)
|
||||
has the same purpose but for the alloc_coherent DMA mappings: in
|
||||
both cases we are using a 32 bits mask. Then the resource field
|
||||
(line 29) is simply a pointer to the resource structure defined
|
||||
before, while the num_resources field (line 28) keeps track of
|
||||
the number of arrays defined in the resource structure (in this
|
||||
case there were two resource arrays defined before).
|
||||
</para>
|
||||
<para>
|
||||
With this quick overview of the UDC platform data at the arch/
|
||||
level now done, let's get back to the MUSB glue layer specific
|
||||
platform data in drivers/usb/musb/jz4740.c:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static struct musb_hdrc_config jz4740_musb_config = {
|
||||
/* Silicon does not implement USB OTG. */
|
||||
.multipoint = 0,
|
||||
/* Max EPs scanned, driver will decide which EP can be used. */
|
||||
.num_eps = 4,
|
||||
/* RAMbits needed to configure EPs from table */
|
||||
.ram_bits = 9,
|
||||
.fifo_cfg = jz4740_musb_fifo_cfg,
|
||||
.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
|
||||
};
|
||||
|
||||
static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
|
||||
.mode = MUSB_PERIPHERAL,
|
||||
.config = &jz4740_musb_config,
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
First the glue layer configures some aspects of the controller
|
||||
driver operation related to the controller hardware specifics.
|
||||
This is done through the jz4740_musb_config musb_hdrc_config
|
||||
structure.
|
||||
</para>
|
||||
<para>
|
||||
Defining the OTG capability of the controller hardware, the
|
||||
multipoint member (line 3) is set to 0 (equivalent to false)
|
||||
since the JZ4740 UDC is not OTG compatible. Then num_eps (line
|
||||
5) defines the number of USB endpoints of the controller
|
||||
hardware, including endpoint 0: here we have 3 endpoints +
|
||||
endpoint 0. Next is ram_bits (line 7) which is the width of the
|
||||
RAM address bus for the MUSB controller hardware. This
|
||||
information is needed when the controller driver cannot
|
||||
automatically configure endpoints by reading the relevant
|
||||
controller hardware registers. This issue will be discussed when
|
||||
we get to device quirks in <link linkend="device-quirks">Chapter
|
||||
5</link>. Last two fields (line 8 and 9) are also about device
|
||||
quirks: fifo_cfg points to the USB endpoints configuration table
|
||||
and fifo_cfg_size keeps track of the size of the number of
|
||||
entries in that configuration table. More on that later in <link
|
||||
linkend="device-quirks">Chapter 5</link>.
|
||||
</para>
|
||||
<para>
|
||||
Then this configuration is embedded inside
|
||||
jz4740_musb_platform_data musb_hdrc_platform_data structure (line
|
||||
11): config is a pointer to the configuration structure itself,
|
||||
and mode tells the controller driver if the controller hardware
|
||||
may be used as MUSB_HOST only, MUSB_PERIPHERAL only or MUSB_OTG
|
||||
which is a dual mode.
|
||||
</para>
|
||||
<para>
|
||||
Remember that jz4740_musb_platform_data is then used to convey
|
||||
platform data information as we have seen in the probe function
|
||||
in <link linkend="linux-musb-basics">Chapter 2</link>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="device-quirks">
|
||||
<title>Device Quirks</title>
|
||||
<para>
|
||||
Completing the platform data specific to your device, you may also
|
||||
need to write some code in the glue layer to work around some
|
||||
device specific limitations. These quirks may be due to some
|
||||
hardware bugs, or simply be the result of an incomplete
|
||||
implementation of the USB On-the-Go specification.
|
||||
</para>
|
||||
<para>
|
||||
The JZ4740 UDC exhibits such quirks, some of which we will discuss
|
||||
here for the sake of insight even though these might not be found
|
||||
in the controller hardware you are working on.
|
||||
</para>
|
||||
<para>
|
||||
Let's get back to the init function first:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static int jz4740_musb_init(struct musb *musb)
|
||||
{
|
||||
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||
if (!musb->xceiv) {
|
||||
pr_err("HS UDC: no transceiver configured\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Silicon does not implement ConfigData register.
|
||||
* Set dyn_fifo to avoid reading EP config from hardware.
|
||||
*/
|
||||
musb->dyn_fifo = true;
|
||||
|
||||
musb->isr = jz4740_musb_interrupt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Instruction on line 12 helps the MUSB controller driver to work
|
||||
around the fact that the controller hardware is missing registers
|
||||
that are used for USB endpoints configuration.
|
||||
</para>
|
||||
<para>
|
||||
Without these registers, the controller driver is unable to read
|
||||
the endpoints configuration from the hardware, so we use line 12
|
||||
instruction to bypass reading the configuration from silicon, and
|
||||
rely on a hard-coded table that describes the endpoints
|
||||
configuration instead:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
|
||||
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
Looking at the configuration table above, we see that each
|
||||
endpoints is described by three fields: hw_ep_num is the endpoint
|
||||
number, style is its direction (either FIFO_TX for the controller
|
||||
driver to send packets in the controller hardware, or FIFO_RX to
|
||||
receive packets from hardware), and maxpacket defines the maximum
|
||||
size of each data packet that can be transmitted over that
|
||||
endpoint. Reading from the table, the controller driver knows that
|
||||
endpoint 1 can be used to send and receive USB data packets of 512
|
||||
bytes at once (this is in fact a bulk in/out endpoint), and
|
||||
endpoint 2 can be used to send data packets of 64 bytes at once
|
||||
(this is in fact an interrupt endpoint).
|
||||
</para>
|
||||
<para>
|
||||
Note that there is no information about endpoint 0 here: that one
|
||||
is implemented by default in every silicon design, with a
|
||||
predefined configuration according to the USB specification. For
|
||||
more examples of endpoint configuration tables, see musb_core.c.
|
||||
</para>
|
||||
<para>
|
||||
Let's now get back to the interrupt handler function:
|
||||
</para>
|
||||
<programlisting linenumbering="numbered">
|
||||
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
|
||||
{
|
||||
unsigned long flags;
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
struct musb *musb = __hci;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
|
||||
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
|
||||
musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
|
||||
|
||||
/*
|
||||
* The controller is gadget only, the state of the host mode IRQ bits is
|
||||
* undefined. Mask them to make sure that the musb driver core will
|
||||
* never see them set
|
||||
*/
|
||||
musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
|
||||
MUSB_INTR_RESET | MUSB_INTR_SOF;
|
||||
|
||||
if (musb->int_usb || musb->int_tx || musb->int_rx)
|
||||
retval = musb_interrupt(musb);
|
||||
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
Instruction on line 18 above is a way for the controller driver to
|
||||
work around the fact that some interrupt bits used for USB host
|
||||
mode operation are missing in the MUSB_INTRUSB register, thus left
|
||||
in an undefined hardware state, since this MUSB controller
|
||||
hardware is used in peripheral mode only. As a consequence, the
|
||||
glue layer masks these missing bits out to avoid parasite
|
||||
interrupts by doing a logical AND operation between the value read
|
||||
from MUSB_INTRUSB and the bits that are actually implemented in
|
||||
the register.
|
||||
</para>
|
||||
<para>
|
||||
These are only a couple of the quirks found in the JZ4740 USB
|
||||
device controller. Some others were directly addressed in the MUSB
|
||||
core since the fixes were generic enough to provide a better
|
||||
handling of the issues for others controller hardware eventually.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="conclusion">
|
||||
<title>Conclusion</title>
|
||||
<para>
|
||||
Writing a Linux MUSB glue layer should be a more accessible task,
|
||||
as this documentation tries to show the ins and outs of this
|
||||
exercise.
|
||||
</para>
|
||||
<para>
|
||||
The JZ4740 USB device controller being fairly simple, I hope its
|
||||
glue layer serves as a good example for the curious mind. Used
|
||||
with the current MUSB glue layers, this documentation should
|
||||
provide enough guidance to get started; should anything gets out
|
||||
of hand, the linux-usb mailing list archive is another helpful
|
||||
resource to browse through.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="acknowledgements">
|
||||
<title>Acknowledgements</title>
|
||||
<para>
|
||||
Many thanks to Lars-Peter Clausen and Maarten ter Huurne for
|
||||
answering my questions while I was writing the JZ4740 glue layer
|
||||
and for helping me out getting the code in good shape.
|
||||
</para>
|
||||
<para>
|
||||
I would also like to thank the Qi-Hardware community at large for
|
||||
its cheerful guidance and support.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="resources">
|
||||
<title>Resources</title>
|
||||
<para>
|
||||
USB Home Page:
|
||||
<ulink url="http://www.usb.org">http://www.usb.org</ulink>
|
||||
</para>
|
||||
<para>
|
||||
linux-usb Mailing List Archives:
|
||||
<ulink url="http://marc.info/?l=linux-usb">http://marc.info/?l=linux-usb</ulink>
|
||||
</para>
|
||||
<para>
|
||||
USB On-the-Go Basics:
|
||||
<ulink url="http://www.maximintegrated.com/app-notes/index.mvp/id/1822">http://www.maximintegrated.com/app-notes/index.mvp/id/1822</ulink>
|
||||
</para>
|
||||
<para>
|
||||
Writing USB Device Drivers:
|
||||
<ulink url="https://www.kernel.org/doc/htmldocs/writing_usb_driver/index.html">https://www.kernel.org/doc/htmldocs/writing_usb_driver/index.html</ulink>
|
||||
</para>
|
||||
<para>
|
||||
Texas Instruments USB Configuration Wiki Page:
|
||||
<ulink url="http://processors.wiki.ti.com/index.php/Usbgeneralpage">http://processors.wiki.ti.com/index.php/Usbgeneralpage</ulink>
|
||||
</para>
|
||||
<para>
|
||||
Analog Devices Blackfin MUSB Configuration:
|
||||
<ulink url="http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb">http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb</ulink>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
</book>
|
|
@ -1,412 +0,0 @@
|
|||
<?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="USBDeviceDriver">
|
||||
<bookinfo>
|
||||
<title>Writing USB Device Drivers</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Greg</firstname>
|
||||
<surname>Kroah-Hartman</surname>
|
||||
<affiliation>
|
||||
<address>
|
||||
<email>greg@kroah.com</email>
|
||||
</address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2001-2002</year>
|
||||
<holder>Greg Kroah-Hartman</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>
|
||||
|
||||
<para>
|
||||
This documentation is based on an article published in
|
||||
Linux Journal Magazine, October 2001, Issue 90.
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="intro">
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
The Linux USB subsystem has grown from supporting only two different
|
||||
types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
|
||||
different types of devices in the 2.4 kernel. Linux currently supports
|
||||
almost all USB class devices (standard types of devices like keyboards,
|
||||
mice, modems, printers and speakers) and an ever-growing number of
|
||||
vendor-specific devices (such as USB to serial converters, digital
|
||||
cameras, Ethernet devices and MP3 players). For a full list of the
|
||||
different USB devices currently supported, see Resources.
|
||||
</para>
|
||||
<para>
|
||||
The remaining kinds of USB devices that do not have support on Linux are
|
||||
almost all vendor-specific devices. Each vendor decides to implement a
|
||||
custom protocol to talk to their device, so a custom driver usually needs
|
||||
to be created. Some vendors are open with their USB protocols and help
|
||||
with the creation of Linux drivers, while others do not publish them, and
|
||||
developers are forced to reverse-engineer. See Resources for some links
|
||||
to handy reverse-engineering tools.
|
||||
</para>
|
||||
<para>
|
||||
Because each different protocol causes a new driver to be created, I have
|
||||
written a generic USB driver skeleton, modelled after the pci-skeleton.c
|
||||
file in the kernel source tree upon which many PCI network drivers have
|
||||
been based. This USB skeleton can be found at drivers/usb/usb-skeleton.c
|
||||
in the kernel source tree. In this article I will walk through the basics
|
||||
of the skeleton driver, explaining the different pieces and what needs to
|
||||
be done to customize it to your specific device.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="basics">
|
||||
<title>Linux USB Basics</title>
|
||||
<para>
|
||||
If you are going to write a Linux USB driver, please become familiar with
|
||||
the USB protocol specification. It can be found, along with many other
|
||||
useful documents, at the USB home page (see Resources). An excellent
|
||||
introduction to the Linux USB subsystem can be found at the USB Working
|
||||
Devices List (see Resources). It explains how the Linux USB subsystem is
|
||||
structured and introduces the reader to the concept of USB urbs
|
||||
(USB Request Blocks), which are essential to USB drivers.
|
||||
</para>
|
||||
<para>
|
||||
The first thing a Linux USB driver needs to do is register itself with
|
||||
the Linux USB subsystem, giving it some information about which devices
|
||||
the driver supports and which functions to call when a device supported
|
||||
by the driver is inserted or removed from the system. All of this
|
||||
information is passed to the USB subsystem in the usb_driver structure.
|
||||
The skeleton driver declares a usb_driver as:
|
||||
</para>
|
||||
<programlisting>
|
||||
static struct usb_driver skel_driver = {
|
||||
.name = "skeleton",
|
||||
.probe = skel_probe,
|
||||
.disconnect = skel_disconnect,
|
||||
.fops = &skel_fops,
|
||||
.minor = USB_SKEL_MINOR_BASE,
|
||||
.id_table = skel_table,
|
||||
};
|
||||
</programlisting>
|
||||
<para>
|
||||
The variable name is a string that describes the driver. It is used in
|
||||
informational messages printed to the system log. The probe and
|
||||
disconnect function pointers are called when a device that matches the
|
||||
information provided in the id_table variable is either seen or removed.
|
||||
</para>
|
||||
<para>
|
||||
The fops and minor variables are optional. Most USB drivers hook into
|
||||
another kernel subsystem, such as the SCSI, network or TTY subsystem.
|
||||
These types of drivers register themselves with the other kernel
|
||||
subsystem, and any user-space interactions are provided through that
|
||||
interface. But for drivers that do not have a matching kernel subsystem,
|
||||
such as MP3 players or scanners, a method of interacting with user space
|
||||
is needed. The USB subsystem provides a way to register a minor device
|
||||
number and a set of file_operations function pointers that enable this
|
||||
user-space interaction. The skeleton driver needs this kind of interface,
|
||||
so it provides a minor starting number and a pointer to its
|
||||
file_operations functions.
|
||||
</para>
|
||||
<para>
|
||||
The USB driver is then registered with a call to usb_register, usually in
|
||||
the driver's init function, as shown here:
|
||||
</para>
|
||||
<programlisting>
|
||||
static int __init usb_skel_init(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
result = usb_register(&skel_driver);
|
||||
if (result < 0) {
|
||||
err("usb_register failed for the "__FILE__ "driver."
|
||||
"Error number %d", result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(usb_skel_init);
|
||||
</programlisting>
|
||||
<para>
|
||||
When the driver is unloaded from the system, it needs to deregister
|
||||
itself with the USB subsystem. This is done with the usb_deregister
|
||||
function:
|
||||
</para>
|
||||
<programlisting>
|
||||
static void __exit usb_skel_exit(void)
|
||||
{
|
||||
/* deregister this driver with the USB subsystem */
|
||||
usb_deregister(&skel_driver);
|
||||
}
|
||||
module_exit(usb_skel_exit);
|
||||
</programlisting>
|
||||
<para>
|
||||
To enable the linux-hotplug system to load the driver automatically when
|
||||
the device is plugged in, you need to create a MODULE_DEVICE_TABLE. The
|
||||
following code tells the hotplug scripts that this module supports a
|
||||
single device with a specific vendor and product ID:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id skel_table [] = {
|
||||
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, skel_table);
|
||||
</programlisting>
|
||||
<para>
|
||||
There are other macros that can be used in describing a usb_device_id for
|
||||
drivers that support a whole class of USB drivers. See usb.h for more
|
||||
information on this.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="device">
|
||||
<title>Device operation</title>
|
||||
<para>
|
||||
When a device is plugged into the USB bus that matches the device ID
|
||||
pattern that your driver registered with the USB core, the probe function
|
||||
is called. The usb_device structure, interface number and the interface ID
|
||||
are passed to the function:
|
||||
</para>
|
||||
<programlisting>
|
||||
static int skel_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id)
|
||||
</programlisting>
|
||||
<para>
|
||||
The driver now needs to verify that this device is actually one that it
|
||||
can accept. If so, it returns 0.
|
||||
If not, or if any error occurs during initialization, an errorcode
|
||||
(such as <literal>-ENOMEM</literal> or <literal>-ENODEV</literal>)
|
||||
is returned from the probe function.
|
||||
</para>
|
||||
<para>
|
||||
In the skeleton driver, we determine what end points are marked as bulk-in
|
||||
and bulk-out. We create buffers to hold the data that will be sent and
|
||||
received from the device, and a USB urb to write data to the device is
|
||||
initialized.
|
||||
</para>
|
||||
<para>
|
||||
Conversely, when the device is removed from the USB bus, the disconnect
|
||||
function is called with the device pointer. The driver needs to clean any
|
||||
private data that has been allocated at this time and to shut down any
|
||||
pending urbs that are in the USB system.
|
||||
</para>
|
||||
<para>
|
||||
Now that the device is plugged into the system and the driver is bound to
|
||||
the device, any of the functions in the file_operations structure that
|
||||
were passed to the USB subsystem will be called from a user program trying
|
||||
to talk to the device. The first function called will be open, as the
|
||||
program tries to open the device for I/O. We increment our private usage
|
||||
count and save a pointer to our internal structure in the file
|
||||
structure. This is done so that future calls to file operations will
|
||||
enable the driver to determine which device the user is addressing. All
|
||||
of this is done with the following code:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* increment our usage count for the module */
|
||||
++skel->open_count;
|
||||
|
||||
/* save our object in the file's private structure */
|
||||
file->private_data = dev;
|
||||
</programlisting>
|
||||
<para>
|
||||
After the open function is called, the read and write functions are called
|
||||
to receive and send data to the device. In the skel_write function, we
|
||||
receive a pointer to some data that the user wants to send to the device
|
||||
and the size of the data. The function determines how much data it can
|
||||
send to the device based on the size of the write urb it has created (this
|
||||
size depends on the size of the bulk out end point that the device has).
|
||||
Then it copies the data from user space to kernel space, points the urb to
|
||||
the data and submits the urb to the USB subsystem. This can be seen in
|
||||
the following code:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* we can only write as much as 1 urb will hold */
|
||||
bytes_written = (count > skel->bulk_out_size) ? skel->bulk_out_size : count;
|
||||
|
||||
/* copy the data from user space into our urb */
|
||||
copy_from_user(skel->write_urb->transfer_buffer, buffer, bytes_written);
|
||||
|
||||
/* set up our urb */
|
||||
usb_fill_bulk_urb(skel->write_urb,
|
||||
skel->dev,
|
||||
usb_sndbulkpipe(skel->dev, skel->bulk_out_endpointAddr),
|
||||
skel->write_urb->transfer_buffer,
|
||||
bytes_written,
|
||||
skel_write_bulk_callback,
|
||||
skel);
|
||||
|
||||
/* send the data out the bulk port */
|
||||
result = usb_submit_urb(skel->write_urb);
|
||||
if (result) {
|
||||
err("Failed submitting write urb, error %d", result);
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
When the write urb is filled up with the proper information using the
|
||||
usb_fill_bulk_urb function, we point the urb's completion callback to call our
|
||||
own skel_write_bulk_callback function. This function is called when the
|
||||
urb is finished by the USB subsystem. The callback function is called in
|
||||
interrupt context, so caution must be taken not to do very much processing
|
||||
at that time. Our implementation of skel_write_bulk_callback merely
|
||||
reports if the urb was completed successfully or not and then returns.
|
||||
</para>
|
||||
<para>
|
||||
The read function works a bit differently from the write function in that
|
||||
we do not use an urb to transfer data from the device to the driver.
|
||||
Instead we call the usb_bulk_msg function, which can be used to send or
|
||||
receive data from a device without having to create urbs and handle
|
||||
urb completion callback functions. We call the usb_bulk_msg function,
|
||||
giving it a buffer into which to place any data received from the device
|
||||
and a timeout value. If the timeout period expires without receiving any
|
||||
data from the device, the function will fail and return an error message.
|
||||
This can be shown with the following code:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* do an immediate bulk read to get data from the device */
|
||||
retval = usb_bulk_msg (skel->dev,
|
||||
usb_rcvbulkpipe (skel->dev,
|
||||
skel->bulk_in_endpointAddr),
|
||||
skel->bulk_in_buffer,
|
||||
skel->bulk_in_size,
|
||||
&count, HZ*10);
|
||||
/* if the read was successful, copy the data to user space */
|
||||
if (!retval) {
|
||||
if (copy_to_user (buffer, skel->bulk_in_buffer, count))
|
||||
retval = -EFAULT;
|
||||
else
|
||||
retval = count;
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
The usb_bulk_msg function can be very useful for doing single reads or
|
||||
writes to a device; however, if you need to read or write constantly to a
|
||||
device, it is recommended to set up your own urbs and submit them to the
|
||||
USB subsystem.
|
||||
</para>
|
||||
<para>
|
||||
When the user program releases the file handle that it has been using to
|
||||
talk to the device, the release function in the driver is called. In this
|
||||
function we decrement our private usage count and wait for possible
|
||||
pending writes:
|
||||
</para>
|
||||
<programlisting>
|
||||
/* decrement our usage count for the device */
|
||||
--skel->open_count;
|
||||
</programlisting>
|
||||
<para>
|
||||
One of the more difficult problems that USB drivers must be able to handle
|
||||
smoothly is the fact that the USB device may be removed from the system at
|
||||
any point in time, even if a program is currently talking to it. It needs
|
||||
to be able to shut down any current reads and writes and notify the
|
||||
user-space programs that the device is no longer there. The following
|
||||
code (function <function>skel_delete</function>)
|
||||
is an example of how to do this: </para>
|
||||
<programlisting>
|
||||
static inline void skel_delete (struct usb_skel *dev)
|
||||
{
|
||||
kfree (dev->bulk_in_buffer);
|
||||
if (dev->bulk_out_buffer != NULL)
|
||||
usb_free_coherent (dev->udev, dev->bulk_out_size,
|
||||
dev->bulk_out_buffer,
|
||||
dev->write_urb->transfer_dma);
|
||||
usb_free_urb (dev->write_urb);
|
||||
kfree (dev);
|
||||
}
|
||||
</programlisting>
|
||||
<para>
|
||||
If a program currently has an open handle to the device, we reset the flag
|
||||
<literal>device_present</literal>. For
|
||||
every read, write, release and other functions that expect a device to be
|
||||
present, the driver first checks this flag to see if the device is
|
||||
still present. If not, it releases that the device has disappeared, and a
|
||||
-ENODEV error is returned to the user-space program. When the release
|
||||
function is eventually called, it determines if there is no device
|
||||
and if not, it does the cleanup that the skel_disconnect
|
||||
function normally does if there are no open files on the device (see
|
||||
Listing 5).
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="iso">
|
||||
<title>Isochronous Data</title>
|
||||
<para>
|
||||
This usb-skeleton driver does not have any examples of interrupt or
|
||||
isochronous data being sent to or from the device. Interrupt data is sent
|
||||
almost exactly as bulk data is, with a few minor exceptions. Isochronous
|
||||
data works differently with continuous streams of data being sent to or
|
||||
from the device. The audio and video camera drivers are very good examples
|
||||
of drivers that handle isochronous data and will be useful if you also
|
||||
need to do this.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="Conclusion">
|
||||
<title>Conclusion</title>
|
||||
<para>
|
||||
Writing Linux USB device drivers is not a difficult task as the
|
||||
usb-skeleton driver shows. This driver, combined with the other current
|
||||
USB drivers, should provide enough examples to help a beginning author
|
||||
create a working driver in a minimal amount of time. The linux-usb-devel
|
||||
mailing list archives also contain a lot of helpful information.
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
<chapter id="resources">
|
||||
<title>Resources</title>
|
||||
<para>
|
||||
The Linux USB Project: <ulink url="http://www.linux-usb.org">http://www.linux-usb.org/</ulink>
|
||||
</para>
|
||||
<para>
|
||||
Linux Hotplug Project: <ulink url="http://linux-hotplug.sourceforge.net">http://linux-hotplug.sourceforge.net/</ulink>
|
||||
</para>
|
||||
<para>
|
||||
Linux USB Working Devices List: <ulink url="http://www.qbik.ch/usb/devices">http://www.qbik.ch/usb/devices/</ulink>
|
||||
</para>
|
||||
<para>
|
||||
linux-usb-devel Mailing List Archives: <ulink url="http://marc.theaimsgroup.com/?l=linux-usb-devel">http://marc.theaimsgroup.com/?l=linux-usb-devel</ulink>
|
||||
</para>
|
||||
<para>
|
||||
Programming Guide for Linux USB Device Drivers: <ulink url="http://usb.cs.tum.edu/usbdoc">http://usb.cs.tum.edu/usbdoc</ulink>
|
||||
</para>
|
||||
<para>
|
||||
USB Home Page: <ulink url="http://www.usb.org">http://www.usb.org</ulink>
|
||||
</para>
|
||||
</chapter>
|
||||
|
||||
</book>
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
Many PCI bus controllers are able to detect a variety of hardware
|
||||
PCI errors on the bus, such as parity errors on the data and address
|
||||
busses, as well as SERR and PERR errors. Some of the more advanced
|
||||
buses, as well as SERR and PERR errors. Some of the more advanced
|
||||
chipsets are able to deal with these errors; these include PCI-E chipsets,
|
||||
and the PCI-host bridges found on IBM Power4, Power5 and Power6-based
|
||||
pSeries boxes. A typical action taken is to disconnect the affected device,
|
||||
|
@ -173,7 +173,7 @@ is STEP 6 (Permanent Failure).
|
|||
>>> a value of 0xff on read, and writes will be dropped. If more than
|
||||
>>> EEH_MAX_FAILS I/O's are attempted to a frozen adapter, EEH
|
||||
>>> assumes that the device driver has gone into an infinite loop
|
||||
>>> and prints an error to syslog. A reboot is then required to
|
||||
>>> and prints an error to syslog. A reboot is then required to
|
||||
>>> get the device working again.
|
||||
|
||||
STEP 2: MMIO Enabled
|
||||
|
@ -231,14 +231,14 @@ proceeds to STEP 4 (Slot Reset)
|
|||
STEP 3: Link Reset
|
||||
------------------
|
||||
The platform resets the link. This is a PCI-Express specific step
|
||||
and is done whenever a non-fatal error has been detected that can be
|
||||
and is done whenever a fatal error has been detected that can be
|
||||
"solved" by resetting the link.
|
||||
|
||||
STEP 4: Slot Reset
|
||||
------------------
|
||||
|
||||
In response to a return value of PCI_ERS_RESULT_NEED_RESET, the
|
||||
the platform will perform a slot reset on the requesting PCI device(s).
|
||||
the platform will perform a slot reset on the requesting PCI device(s).
|
||||
The actual steps taken by a platform to perform a slot reset
|
||||
will be platform-dependent. Upon completion of slot reset, the
|
||||
platform will call the device slot_reset() callback.
|
||||
|
@ -258,7 +258,7 @@ configuration registers to initialize to their default conditions.
|
|||
|
||||
For most PCI devices, a soft reset will be sufficient for recovery.
|
||||
Optional fundamental reset is provided to support a limited number
|
||||
of PCI Express PCI devices for which a soft reset is not sufficient
|
||||
of PCI Express devices for which a soft reset is not sufficient
|
||||
for recovery.
|
||||
|
||||
If the platform supports PCI hotplug, then the reset might be
|
||||
|
@ -303,7 +303,7 @@ driver performs device init only from PCI function 0:
|
|||
Same as above.
|
||||
|
||||
Drivers for PCI Express cards that require a fundamental reset must
|
||||
set the needs_freset bit in the pci_dev structure in their probe function.
|
||||
set the needs_freset bit in the pci_dev structure in their probe function.
|
||||
For example, the QLogic qla2xxx driver sets the needs_freset bit for certain
|
||||
PCI card types:
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ kernel.
|
|||
CONFIG_ACPI_DEBUGGER=y
|
||||
CONFIG_ACPI_DEBUGGER_USER=m
|
||||
|
||||
The userspace utlities can be built from the kernel source tree using
|
||||
The userspace utilities can be built from the kernel source tree using
|
||||
the following commands:
|
||||
|
||||
$ cd tools
|
||||
|
|
|
@ -367,10 +367,10 @@ resulting child platform device.
|
|||
|
||||
Device Tree namespace link device ID
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The Device Tree protocol uses device indentification based on the "compatible"
|
||||
The Device Tree protocol uses device identification based on the "compatible"
|
||||
property whose value is a string or an array of strings recognized as device
|
||||
identifiers by drivers and the driver core. The set of all those strings may be
|
||||
regarded as a device indentification namespace analogous to the ACPI/PNP device
|
||||
regarded as a device identification namespace analogous to the ACPI/PNP device
|
||||
ID namespace. Consequently, in principle it should not be necessary to allocate
|
||||
a new (and arguably redundant) ACPI/PNP device ID for a devices with an existing
|
||||
identification string in the Device Tree (DT) namespace, especially if that ID
|
||||
|
@ -381,7 +381,7 @@ In ACPI, the device identification object called _CID (Compatible ID) is used to
|
|||
list the IDs of devices the given one is compatible with, but those IDs must
|
||||
belong to one of the namespaces prescribed by the ACPI specification (see
|
||||
Section 6.1.2 of ACPI 6.0 for details) and the DT namespace is not one of them.
|
||||
Moreover, the specification mandates that either a _HID or an _ADR identificaion
|
||||
Moreover, the specification mandates that either a _HID or an _ADR identification
|
||||
object be present for all ACPI objects representing devices (Section 6.1 of ACPI
|
||||
6.0). For non-enumerable bus types that object must be _HID and its value must
|
||||
be a device ID from one of the namespaces prescribed by the specification too.
|
||||
|
|
|
@ -60,6 +60,7 @@ configure specific aspects of kernel behavior to your liking.
|
|||
mono
|
||||
java
|
||||
ras
|
||||
pm/index
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. _kernelparameters:
|
||||
|
||||
The kernel's command-line parameters
|
||||
====================================
|
||||
|
||||
|
@ -196,7 +198,7 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
|
||||
Finally, the [KMG] suffix is commonly described after a number of kernel
|
||||
parameter values. These 'K', 'M', and 'G' letters represent the _binary_
|
||||
multipliers 'Kilo', 'Mega', and 'Giga', equalling 2^10, 2^20, and 2^30
|
||||
multipliers 'Kilo', 'Mega', and 'Giga', equaling 2^10, 2^20, and 2^30
|
||||
bytes respectively. Such letter suffixes can also be entirely omitted:
|
||||
|
||||
.. include:: kernel-parameters.txt
|
||||
|
|
700
Documentation/admin-guide/pm/cpufreq.rst
Normal file
700
Documentation/admin-guide/pm/cpufreq.rst
Normal file
|
@ -0,0 +1,700 @@
|
|||
.. |struct cpufreq_policy| replace:: :c:type:`struct cpufreq_policy <cpufreq_policy>`
|
||||
|
||||
=======================
|
||||
CPU Performance Scaling
|
||||
=======================
|
||||
|
||||
::
|
||||
|
||||
Copyright (c) 2017 Intel Corp., Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
|
||||
The Concept of CPU Performance Scaling
|
||||
======================================
|
||||
|
||||
The majority of modern processors are capable of operating in a number of
|
||||
different clock frequency and voltage configurations, often referred to as
|
||||
Operating Performance Points or P-states (in ACPI terminology). As a rule,
|
||||
the higher the clock frequency and the higher the voltage, the more instructions
|
||||
can be retired by the CPU over a unit of time, but also the higher the clock
|
||||
frequency and the higher the voltage, the more energy is consumed over a unit of
|
||||
time (or the more power is drawn) by the CPU in the given P-state. Therefore
|
||||
there is a natural tradeoff between the CPU capacity (the number of instructions
|
||||
that can be executed over a unit of time) and the power drawn by the CPU.
|
||||
|
||||
In some situations it is desirable or even necessary to run the program as fast
|
||||
as possible and then there is no reason to use any P-states different from the
|
||||
highest one (i.e. the highest-performance frequency/voltage configuration
|
||||
available). In some other cases, however, it may not be necessary to execute
|
||||
instructions so quickly and maintaining the highest available CPU capacity for a
|
||||
relatively long time without utilizing it entirely may be regarded as wasteful.
|
||||
It also may not be physically possible to maintain maximum CPU capacity for too
|
||||
long for thermal or power supply capacity reasons or similar. To cover those
|
||||
cases, there are hardware interfaces allowing CPUs to be switched between
|
||||
different frequency/voltage configurations or (in the ACPI terminology) to be
|
||||
put into different P-states.
|
||||
|
||||
Typically, they are used along with algorithms to estimate the required CPU
|
||||
capacity, so as to decide which P-states to put the CPUs into. Of course, since
|
||||
the utilization of the system generally changes over time, that has to be done
|
||||
repeatedly on a regular basis. The activity by which this happens is referred
|
||||
to as CPU performance scaling or CPU frequency scaling (because it involves
|
||||
adjusting the CPU clock frequency).
|
||||
|
||||
|
||||
CPU Performance Scaling in Linux
|
||||
================================
|
||||
|
||||
The Linux kernel supports CPU performance scaling by means of the ``CPUFreq``
|
||||
(CPU Frequency scaling) subsystem that consists of three layers of code: the
|
||||
core, scaling governors and scaling drivers.
|
||||
|
||||
The ``CPUFreq`` core provides the common code infrastructure and user space
|
||||
interfaces for all platforms that support CPU performance scaling. It defines
|
||||
the basic framework in which the other components operate.
|
||||
|
||||
Scaling governors implement algorithms to estimate the required CPU capacity.
|
||||
As a rule, each governor implements one, possibly parametrized, scaling
|
||||
algorithm.
|
||||
|
||||
Scaling drivers talk to the hardware. They provide scaling governors with
|
||||
information on the available P-states (or P-state ranges in some cases) and
|
||||
access platform-specific hardware interfaces to change CPU P-states as requested
|
||||
by scaling governors.
|
||||
|
||||
In principle, all available scaling governors can be used with every scaling
|
||||
driver. That design is based on the observation that the information used by
|
||||
performance scaling algorithms for P-state selection can be represented in a
|
||||
platform-independent form in the majority of cases, so it should be possible
|
||||
to use the same performance scaling algorithm implemented in exactly the same
|
||||
way regardless of which scaling driver is used. Consequently, the same set of
|
||||
scaling governors should be suitable for every supported platform.
|
||||
|
||||
However, that observation may not hold for performance scaling algorithms
|
||||
based on information provided by the hardware itself, for example through
|
||||
feedback registers, as that information is typically specific to the hardware
|
||||
interface it comes from and may not be easily represented in an abstract,
|
||||
platform-independent way. For this reason, ``CPUFreq`` allows scaling drivers
|
||||
to bypass the governor layer and implement their own performance scaling
|
||||
algorithms. That is done by the ``intel_pstate`` scaling driver.
|
||||
|
||||
|
||||
``CPUFreq`` Policy Objects
|
||||
==========================
|
||||
|
||||
In some cases the hardware interface for P-state control is shared by multiple
|
||||
CPUs. That is, for example, the same register (or set of registers) is used to
|
||||
control the P-state of multiple CPUs at the same time and writing to it affects
|
||||
all of those CPUs simultaneously.
|
||||
|
||||
Sets of CPUs sharing hardware P-state control interfaces are represented by
|
||||
``CPUFreq`` as |struct cpufreq_policy| objects. For consistency,
|
||||
|struct cpufreq_policy| is also used when there is only one CPU in the given
|
||||
set.
|
||||
|
||||
The ``CPUFreq`` core maintains a pointer to a |struct cpufreq_policy| object for
|
||||
every CPU in the system, including CPUs that are currently offline. If multiple
|
||||
CPUs share the same hardware P-state control interface, all of the pointers
|
||||
corresponding to them point to the same |struct cpufreq_policy| object.
|
||||
|
||||
``CPUFreq`` uses |struct cpufreq_policy| as its basic data type and the design
|
||||
of its user space interface is based on the policy concept.
|
||||
|
||||
|
||||
CPU Initialization
|
||||
==================
|
||||
|
||||
First of all, a scaling driver has to be registered for ``CPUFreq`` to work.
|
||||
It is only possible to register one scaling driver at a time, so the scaling
|
||||
driver is expected to be able to handle all CPUs in the system.
|
||||
|
||||
The scaling driver may be registered before or after CPU registration. If
|
||||
CPUs are registered earlier, the driver core invokes the ``CPUFreq`` core to
|
||||
take a note of all of the already registered CPUs during the registration of the
|
||||
scaling driver. In turn, if any CPUs are registered after the registration of
|
||||
the scaling driver, the ``CPUFreq`` core will be invoked to take note of them
|
||||
at their registration time.
|
||||
|
||||
In any case, the ``CPUFreq`` core is invoked to take note of any logical CPU it
|
||||
has not seen so far as soon as it is ready to handle that CPU. [Note that the
|
||||
logical CPU may be a physical single-core processor, or a single core in a
|
||||
multicore processor, or a hardware thread in a physical processor or processor
|
||||
core. In what follows "CPU" always means "logical CPU" unless explicitly stated
|
||||
otherwise and the word "processor" is used to refer to the physical part
|
||||
possibly including multiple logical CPUs.]
|
||||
|
||||
Once invoked, the ``CPUFreq`` core checks if the policy pointer is already set
|
||||
for the given CPU and if so, it skips the policy object creation. Otherwise,
|
||||
a new policy object is created and initialized, which involves the creation of
|
||||
a new policy directory in ``sysfs``, and the policy pointer corresponding to
|
||||
the given CPU is set to the new policy object's address in memory.
|
||||
|
||||
Next, the scaling driver's ``->init()`` callback is invoked with the policy
|
||||
pointer of the new CPU passed to it as the argument. That callback is expected
|
||||
to initialize the performance scaling hardware interface for the given CPU (or,
|
||||
more precisely, for the set of CPUs sharing the hardware interface it belongs
|
||||
to, represented by its policy object) and, if the policy object it has been
|
||||
called for is new, to set parameters of the policy, like the minimum and maximum
|
||||
frequencies supported by the hardware, the table of available frequencies (if
|
||||
the set of supported P-states is not a continuous range), and the mask of CPUs
|
||||
that belong to the same policy (including both online and offline CPUs). That
|
||||
mask is then used by the core to populate the policy pointers for all of the
|
||||
CPUs in it.
|
||||
|
||||
The next major initialization step for a new policy object is to attach a
|
||||
scaling governor to it (to begin with, that is the default scaling governor
|
||||
determined by the kernel configuration, but it may be changed later
|
||||
via ``sysfs``). First, a pointer to the new policy object is passed to the
|
||||
governor's ``->init()`` callback which is expected to initialize all of the
|
||||
data structures necessary to handle the given policy and, possibly, to add
|
||||
a governor ``sysfs`` interface to it. Next, the governor is started by
|
||||
invoking its ``->start()`` callback.
|
||||
|
||||
That callback it expected to register per-CPU utilization update callbacks for
|
||||
all of the online CPUs belonging to the given policy with the CPU scheduler.
|
||||
The utilization update callbacks will be invoked by the CPU scheduler on
|
||||
important events, like task enqueue and dequeue, on every iteration of the
|
||||
scheduler tick or generally whenever the CPU utilization may change (from the
|
||||
scheduler's perspective). They are expected to carry out computations needed
|
||||
to determine the P-state to use for the given policy going forward and to
|
||||
invoke the scaling driver to make changes to the hardware in accordance with
|
||||
the P-state selection. The scaling driver may be invoked directly from
|
||||
scheduler context or asynchronously, via a kernel thread or workqueue, depending
|
||||
on the configuration and capabilities of the scaling driver and the governor.
|
||||
|
||||
Similar steps are taken for policy objects that are not new, but were "inactive"
|
||||
previously, meaning that all of the CPUs belonging to them were offline. The
|
||||
only practical difference in that case is that the ``CPUFreq`` core will attempt
|
||||
to use the scaling governor previously used with the policy that became
|
||||
"inactive" (and is re-initialized now) instead of the default governor.
|
||||
|
||||
In turn, if a previously offline CPU is being brought back online, but some
|
||||
other CPUs sharing the policy object with it are online already, there is no
|
||||
need to re-initialize the policy object at all. In that case, it only is
|
||||
necessary to restart the scaling governor so that it can take the new online CPU
|
||||
into account. That is achieved by invoking the governor's ``->stop`` and
|
||||
``->start()`` callbacks, in this order, for the entire policy.
|
||||
|
||||
As mentioned before, the ``intel_pstate`` scaling driver bypasses the scaling
|
||||
governor layer of ``CPUFreq`` and provides its own P-state selection algorithms.
|
||||
Consequently, if ``intel_pstate`` is used, scaling governors are not attached to
|
||||
new policy objects. Instead, the driver's ``->setpolicy()`` callback is invoked
|
||||
to register per-CPU utilization update callbacks for each policy. These
|
||||
callbacks are invoked by the CPU scheduler in the same way as for scaling
|
||||
governors, but in the ``intel_pstate`` case they both determine the P-state to
|
||||
use and change the hardware configuration accordingly in one go from scheduler
|
||||
context.
|
||||
|
||||
The policy objects created during CPU initialization and other data structures
|
||||
associated with them are torn down when the scaling driver is unregistered
|
||||
(which happens when the kernel module containing it is unloaded, for example) or
|
||||
when the last CPU belonging to the given policy in unregistered.
|
||||
|
||||
|
||||
Policy Interface in ``sysfs``
|
||||
=============================
|
||||
|
||||
During the initialization of the kernel, the ``CPUFreq`` core creates a
|
||||
``sysfs`` directory (kobject) called ``cpufreq`` under
|
||||
:file:`/sys/devices/system/cpu/`.
|
||||
|
||||
That directory contains a ``policyX`` subdirectory (where ``X`` represents an
|
||||
integer number) for every policy object maintained by the ``CPUFreq`` core.
|
||||
Each ``policyX`` directory is pointed to by ``cpufreq`` symbolic links
|
||||
under :file:`/sys/devices/system/cpu/cpuY/` (where ``Y`` represents an integer
|
||||
that may be different from the one represented by ``X``) for all of the CPUs
|
||||
associated with (or belonging to) the given policy. The ``policyX`` directories
|
||||
in :file:`/sys/devices/system/cpu/cpufreq` each contain policy-specific
|
||||
attributes (files) to control ``CPUFreq`` behavior for the corresponding policy
|
||||
objects (that is, for all of the CPUs associated with them).
|
||||
|
||||
Some of those attributes are generic. They are created by the ``CPUFreq`` core
|
||||
and their behavior generally does not depend on what scaling driver is in use
|
||||
and what scaling governor is attached to the given policy. Some scaling drivers
|
||||
also add driver-specific attributes to the policy directories in ``sysfs`` to
|
||||
control policy-specific aspects of driver behavior.
|
||||
|
||||
The generic attributes under :file:`/sys/devices/system/cpu/cpufreq/policyX/`
|
||||
are the following:
|
||||
|
||||
``affected_cpus``
|
||||
List of online CPUs belonging to this policy (i.e. sharing the hardware
|
||||
performance scaling interface represented by the ``policyX`` policy
|
||||
object).
|
||||
|
||||
``bios_limit``
|
||||
If the platform firmware (BIOS) tells the OS to apply an upper limit to
|
||||
CPU frequencies, that limit will be reported through this attribute (if
|
||||
present).
|
||||
|
||||
The existence of the limit may be a result of some (often unintentional)
|
||||
BIOS settings, restrictions coming from a service processor or another
|
||||
BIOS/HW-based mechanisms.
|
||||
|
||||
This does not cover ACPI thermal limitations which can be discovered
|
||||
through a generic thermal driver.
|
||||
|
||||
This attribute is not present if the scaling driver in use does not
|
||||
support it.
|
||||
|
||||
``cpuinfo_max_freq``
|
||||
Maximum possible operating frequency the CPUs belonging to this policy
|
||||
can run at (in kHz).
|
||||
|
||||
``cpuinfo_min_freq``
|
||||
Minimum possible operating frequency the CPUs belonging to this policy
|
||||
can run at (in kHz).
|
||||
|
||||
``cpuinfo_transition_latency``
|
||||
The time it takes to switch the CPUs belonging to this policy from one
|
||||
P-state to another, in nanoseconds.
|
||||
|
||||
If unknown or if known to be so high that the scaling driver does not
|
||||
work with the `ondemand`_ governor, -1 (:c:macro:`CPUFREQ_ETERNAL`)
|
||||
will be returned by reads from this attribute.
|
||||
|
||||
``related_cpus``
|
||||
List of all (online and offline) CPUs belonging to this policy.
|
||||
|
||||
``scaling_available_governors``
|
||||
List of ``CPUFreq`` scaling governors present in the kernel that can
|
||||
be attached to this policy or (if the ``intel_pstate`` scaling driver is
|
||||
in use) list of scaling algorithms provided by the driver that can be
|
||||
applied to this policy.
|
||||
|
||||
[Note that some governors are modular and it may be necessary to load a
|
||||
kernel module for the governor held by it to become available and be
|
||||
listed by this attribute.]
|
||||
|
||||
``scaling_cur_freq``
|
||||
Current frequency of all of the CPUs belonging to this policy (in kHz).
|
||||
|
||||
For the majority of scaling drivers, this is the frequency of the last
|
||||
P-state requested by the driver from the hardware using the scaling
|
||||
interface provided by it, which may or may not reflect the frequency
|
||||
the CPU is actually running at (due to hardware design and other
|
||||
limitations).
|
||||
|
||||
Some scaling drivers (e.g. ``intel_pstate``) attempt to provide
|
||||
information more precisely reflecting the current CPU frequency through
|
||||
this attribute, but that still may not be the exact current CPU
|
||||
frequency as seen by the hardware at the moment.
|
||||
|
||||
``scaling_driver``
|
||||
The scaling driver currently in use.
|
||||
|
||||
``scaling_governor``
|
||||
The scaling governor currently attached to this policy or (if the
|
||||
``intel_pstate`` scaling driver is in use) the scaling algorithm
|
||||
provided by the driver that is currently applied to this policy.
|
||||
|
||||
This attribute is read-write and writing to it will cause a new scaling
|
||||
governor to be attached to this policy or a new scaling algorithm
|
||||
provided by the scaling driver to be applied to it (in the
|
||||
``intel_pstate`` case), as indicated by the string written to this
|
||||
attribute (which must be one of the names listed by the
|
||||
``scaling_available_governors`` attribute described above).
|
||||
|
||||
``scaling_max_freq``
|
||||
Maximum frequency the CPUs belonging to this policy are allowed to be
|
||||
running at (in kHz).
|
||||
|
||||
This attribute is read-write and writing a string representing an
|
||||
integer to it will cause a new limit to be set (it must not be lower
|
||||
than the value of the ``scaling_min_freq`` attribute).
|
||||
|
||||
``scaling_min_freq``
|
||||
Minimum frequency the CPUs belonging to this policy are allowed to be
|
||||
running at (in kHz).
|
||||
|
||||
This attribute is read-write and writing a string representing a
|
||||
non-negative integer to it will cause a new limit to be set (it must not
|
||||
be higher than the value of the ``scaling_max_freq`` attribute).
|
||||
|
||||
``scaling_setspeed``
|
||||
This attribute is functional only if the `userspace`_ scaling governor
|
||||
is attached to the given policy.
|
||||
|
||||
It returns the last frequency requested by the governor (in kHz) or can
|
||||
be written to in order to set a new frequency for the policy.
|
||||
|
||||
|
||||
Generic Scaling Governors
|
||||
=========================
|
||||
|
||||
``CPUFreq`` provides generic scaling governors that can be used with all
|
||||
scaling drivers. As stated before, each of them implements a single, possibly
|
||||
parametrized, performance scaling algorithm.
|
||||
|
||||
Scaling governors are attached to policy objects and different policy objects
|
||||
can be handled by different scaling governors at the same time (although that
|
||||
may lead to suboptimal results in some cases).
|
||||
|
||||
The scaling governor for a given policy object can be changed at any time with
|
||||
the help of the ``scaling_governor`` policy attribute in ``sysfs``.
|
||||
|
||||
Some governors expose ``sysfs`` attributes to control or fine-tune the scaling
|
||||
algorithms implemented by them. Those attributes, referred to as governor
|
||||
tunables, can be either global (system-wide) or per-policy, depending on the
|
||||
scaling driver in use. If the driver requires governor tunables to be
|
||||
per-policy, they are located in a subdirectory of each policy directory.
|
||||
Otherwise, they are located in a subdirectory under
|
||||
:file:`/sys/devices/system/cpu/cpufreq/`. In either case the name of the
|
||||
subdirectory containing the governor tunables is the name of the governor
|
||||
providing them.
|
||||
|
||||
``performance``
|
||||
---------------
|
||||
|
||||
When attached to a policy object, this governor causes the highest frequency,
|
||||
within the ``scaling_max_freq`` policy limit, to be requested for that policy.
|
||||
|
||||
The request is made once at that time the governor for the policy is set to
|
||||
``performance`` and whenever the ``scaling_max_freq`` or ``scaling_min_freq``
|
||||
policy limits change after that.
|
||||
|
||||
``powersave``
|
||||
-------------
|
||||
|
||||
When attached to a policy object, this governor causes the lowest frequency,
|
||||
within the ``scaling_min_freq`` policy limit, to be requested for that policy.
|
||||
|
||||
The request is made once at that time the governor for the policy is set to
|
||||
``powersave`` and whenever the ``scaling_max_freq`` or ``scaling_min_freq``
|
||||
policy limits change after that.
|
||||
|
||||
``userspace``
|
||||
-------------
|
||||
|
||||
This governor does not do anything by itself. Instead, it allows user space
|
||||
to set the CPU frequency for the policy it is attached to by writing to the
|
||||
``scaling_setspeed`` attribute of that policy.
|
||||
|
||||
``schedutil``
|
||||
-------------
|
||||
|
||||
This governor uses CPU utilization data available from the CPU scheduler. It
|
||||
generally is regarded as a part of the CPU scheduler, so it can access the
|
||||
scheduler's internal data structures directly.
|
||||
|
||||
It runs entirely in scheduler context, although in some cases it may need to
|
||||
invoke the scaling driver asynchronously when it decides that the CPU frequency
|
||||
should be changed for a given policy (that depends on whether or not the driver
|
||||
is capable of changing the CPU frequency from scheduler context).
|
||||
|
||||
The actions of this governor for a particular CPU depend on the scheduling class
|
||||
invoking its utilization update callback for that CPU. If it is invoked by the
|
||||
RT or deadline scheduling classes, the governor will increase the frequency to
|
||||
the allowed maximum (that is, the ``scaling_max_freq`` policy limit). In turn,
|
||||
if it is invoked by the CFS scheduling class, the governor will use the
|
||||
Per-Entity Load Tracking (PELT) metric for the root control group of the
|
||||
given CPU as the CPU utilization estimate (see the `Per-entity load tracking`_
|
||||
LWN.net article for a description of the PELT mechanism). Then, the new
|
||||
CPU frequency to apply is computed in accordance with the formula
|
||||
|
||||
f = 1.25 * ``f_0`` * ``util`` / ``max``
|
||||
|
||||
where ``util`` is the PELT number, ``max`` is the theoretical maximum of
|
||||
``util``, and ``f_0`` is either the maximum possible CPU frequency for the given
|
||||
policy (if the PELT number is frequency-invariant), or the current CPU frequency
|
||||
(otherwise).
|
||||
|
||||
This governor also employs a mechanism allowing it to temporarily bump up the
|
||||
CPU frequency for tasks that have been waiting on I/O most recently, called
|
||||
"IO-wait boosting". That happens when the :c:macro:`SCHED_CPUFREQ_IOWAIT` flag
|
||||
is passed by the scheduler to the governor callback which causes the frequency
|
||||
to go up to the allowed maximum immediately and then draw back to the value
|
||||
returned by the above formula over time.
|
||||
|
||||
This governor exposes only one tunable:
|
||||
|
||||
``rate_limit_us``
|
||||
Minimum time (in microseconds) that has to pass between two consecutive
|
||||
runs of governor computations (default: 1000 times the scaling driver's
|
||||
transition latency).
|
||||
|
||||
The purpose of this tunable is to reduce the scheduler context overhead
|
||||
of the governor which might be excessive without it.
|
||||
|
||||
This governor generally is regarded as a replacement for the older `ondemand`_
|
||||
and `conservative`_ governors (described below), as it is simpler and more
|
||||
tightly integrated with the CPU scheduler, its overhead in terms of CPU context
|
||||
switches and similar is less significant, and it uses the scheduler's own CPU
|
||||
utilization metric, so in principle its decisions should not contradict the
|
||||
decisions made by the other parts of the scheduler.
|
||||
|
||||
``ondemand``
|
||||
------------
|
||||
|
||||
This governor uses CPU load as a CPU frequency selection metric.
|
||||
|
||||
In order to estimate the current CPU load, it measures the time elapsed between
|
||||
consecutive invocations of its worker routine and computes the fraction of that
|
||||
time in which the given CPU was not idle. The ratio of the non-idle (active)
|
||||
time to the total CPU time is taken as an estimate of the load.
|
||||
|
||||
If this governor is attached to a policy shared by multiple CPUs, the load is
|
||||
estimated for all of them and the greatest result is taken as the load estimate
|
||||
for the entire policy.
|
||||
|
||||
The worker routine of this governor has to run in process context, so it is
|
||||
invoked asynchronously (via a workqueue) and CPU P-states are updated from
|
||||
there if necessary. As a result, the scheduler context overhead from this
|
||||
governor is minimum, but it causes additional CPU context switches to happen
|
||||
relatively often and the CPU P-state updates triggered by it can be relatively
|
||||
irregular. Also, it affects its own CPU load metric by running code that
|
||||
reduces the CPU idle time (even though the CPU idle time is only reduced very
|
||||
slightly by it).
|
||||
|
||||
It generally selects CPU frequencies proportional to the estimated load, so that
|
||||
the value of the ``cpuinfo_max_freq`` policy attribute corresponds to the load of
|
||||
1 (or 100%), and the value of the ``cpuinfo_min_freq`` policy attribute
|
||||
corresponds to the load of 0, unless when the load exceeds a (configurable)
|
||||
speedup threshold, in which case it will go straight for the highest frequency
|
||||
it is allowed to use (the ``scaling_max_freq`` policy limit).
|
||||
|
||||
This governor exposes the following tunables:
|
||||
|
||||
``sampling_rate``
|
||||
This is how often the governor's worker routine should run, in
|
||||
microseconds.
|
||||
|
||||
Typically, it is set to values of the order of 10000 (10 ms). Its
|
||||
default value is equal to the value of ``cpuinfo_transition_latency``
|
||||
for each policy this governor is attached to (but since the unit here
|
||||
is greater by 1000, this means that the time represented by
|
||||
``sampling_rate`` is 1000 times greater than the transition latency by
|
||||
default).
|
||||
|
||||
If this tunable is per-policy, the following shell command sets the time
|
||||
represented by it to be 750 times as high as the transition latency::
|
||||
|
||||
# echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) > ondemand/sampling_rate
|
||||
|
||||
|
||||
``min_sampling_rate``
|
||||
The minimum value of ``sampling_rate``.
|
||||
|
||||
Equal to 10000 (10 ms) if :c:macro:`CONFIG_NO_HZ_COMMON` and
|
||||
:c:data:`tick_nohz_active` are both set or to 20 times the value of
|
||||
:c:data:`jiffies` in microseconds otherwise.
|
||||
|
||||
``up_threshold``
|
||||
If the estimated CPU load is above this value (in percent), the governor
|
||||
will set the frequency to the maximum value allowed for the policy.
|
||||
Otherwise, the selected frequency will be proportional to the estimated
|
||||
CPU load.
|
||||
|
||||
``ignore_nice_load``
|
||||
If set to 1 (default 0), it will cause the CPU load estimation code to
|
||||
treat the CPU time spent on executing tasks with "nice" levels greater
|
||||
than 0 as CPU idle time.
|
||||
|
||||
This may be useful if there are tasks in the system that should not be
|
||||
taken into account when deciding what frequency to run the CPUs at.
|
||||
Then, to make that happen it is sufficient to increase the "nice" level
|
||||
of those tasks above 0 and set this attribute to 1.
|
||||
|
||||
``sampling_down_factor``
|
||||
Temporary multiplier, between 1 (default) and 100 inclusive, to apply to
|
||||
the ``sampling_rate`` value if the CPU load goes above ``up_threshold``.
|
||||
|
||||
This causes the next execution of the governor's worker routine (after
|
||||
setting the frequency to the allowed maximum) to be delayed, so the
|
||||
frequency stays at the maximum level for a longer time.
|
||||
|
||||
Frequency fluctuations in some bursty workloads may be avoided this way
|
||||
at the cost of additional energy spent on maintaining the maximum CPU
|
||||
capacity.
|
||||
|
||||
``powersave_bias``
|
||||
Reduction factor to apply to the original frequency target of the
|
||||
governor (including the maximum value used when the ``up_threshold``
|
||||
value is exceeded by the estimated CPU load) or sensitivity threshold
|
||||
for the AMD frequency sensitivity powersave bias driver
|
||||
(:file:`drivers/cpufreq/amd_freq_sensitivity.c`), between 0 and 1000
|
||||
inclusive.
|
||||
|
||||
If the AMD frequency sensitivity powersave bias driver is not loaded,
|
||||
the effective frequency to apply is given by
|
||||
|
||||
f * (1 - ``powersave_bias`` / 1000)
|
||||
|
||||
where f is the governor's original frequency target. The default value
|
||||
of this attribute is 0 in that case.
|
||||
|
||||
If the AMD frequency sensitivity powersave bias driver is loaded, the
|
||||
value of this attribute is 400 by default and it is used in a different
|
||||
way.
|
||||
|
||||
On Family 16h (and later) AMD processors there is a mechanism to get a
|
||||
measured workload sensitivity, between 0 and 100% inclusive, from the
|
||||
hardware. That value can be used to estimate how the performance of the
|
||||
workload running on a CPU will change in response to frequency changes.
|
||||
|
||||
The performance of a workload with the sensitivity of 0 (memory-bound or
|
||||
IO-bound) is not expected to increase at all as a result of increasing
|
||||
the CPU frequency, whereas workloads with the sensitivity of 100%
|
||||
(CPU-bound) are expected to perform much better if the CPU frequency is
|
||||
increased.
|
||||
|
||||
If the workload sensitivity is less than the threshold represented by
|
||||
the ``powersave_bias`` value, the sensitivity powersave bias driver
|
||||
will cause the governor to select a frequency lower than its original
|
||||
target, so as to avoid over-provisioning workloads that will not benefit
|
||||
from running at higher CPU frequencies.
|
||||
|
||||
``conservative``
|
||||
----------------
|
||||
|
||||
This governor uses CPU load as a CPU frequency selection metric.
|
||||
|
||||
It estimates the CPU load in the same way as the `ondemand`_ governor described
|
||||
above, but the CPU frequency selection algorithm implemented by it is different.
|
||||
|
||||
Namely, it avoids changing the frequency significantly over short time intervals
|
||||
which may not be suitable for systems with limited power supply capacity (e.g.
|
||||
battery-powered). To achieve that, it changes the frequency in relatively
|
||||
small steps, one step at a time, up or down - depending on whether or not a
|
||||
(configurable) threshold has been exceeded by the estimated CPU load.
|
||||
|
||||
This governor exposes the following tunables:
|
||||
|
||||
``freq_step``
|
||||
Frequency step in percent of the maximum frequency the governor is
|
||||
allowed to set (the ``scaling_max_freq`` policy limit), between 0 and
|
||||
100 (5 by default).
|
||||
|
||||
This is how much the frequency is allowed to change in one go. Setting
|
||||
it to 0 will cause the default frequency step (5 percent) to be used
|
||||
and setting it to 100 effectively causes the governor to periodically
|
||||
switch the frequency between the ``scaling_min_freq`` and
|
||||
``scaling_max_freq`` policy limits.
|
||||
|
||||
``down_threshold``
|
||||
Threshold value (in percent, 20 by default) used to determine the
|
||||
frequency change direction.
|
||||
|
||||
If the estimated CPU load is greater than this value, the frequency will
|
||||
go up (by ``freq_step``). If the load is less than this value (and the
|
||||
``sampling_down_factor`` mechanism is not in effect), the frequency will
|
||||
go down. Otherwise, the frequency will not be changed.
|
||||
|
||||
``sampling_down_factor``
|
||||
Frequency decrease deferral factor, between 1 (default) and 10
|
||||
inclusive.
|
||||
|
||||
It effectively causes the frequency to go down ``sampling_down_factor``
|
||||
times slower than it ramps up.
|
||||
|
||||
|
||||
Frequency Boost Support
|
||||
=======================
|
||||
|
||||
Background
|
||||
----------
|
||||
|
||||
Some processors support a mechanism to raise the operating frequency of some
|
||||
cores in a multicore package temporarily (and above the sustainable frequency
|
||||
threshold for the whole package) under certain conditions, for example if the
|
||||
whole chip is not fully utilized and below its intended thermal or power budget.
|
||||
|
||||
Different names are used by different vendors to refer to this functionality.
|
||||
For Intel processors it is referred to as "Turbo Boost", AMD calls it
|
||||
"Turbo-Core" or (in technical documentation) "Core Performance Boost" and so on.
|
||||
As a rule, it also is implemented differently by different vendors. The simple
|
||||
term "frequency boost" is used here for brevity to refer to all of those
|
||||
implementations.
|
||||
|
||||
The frequency boost mechanism may be either hardware-based or software-based.
|
||||
If it is hardware-based (e.g. on x86), the decision to trigger the boosting is
|
||||
made by the hardware (although in general it requires the hardware to be put
|
||||
into a special state in which it can control the CPU frequency within certain
|
||||
limits). If it is software-based (e.g. on ARM), the scaling driver decides
|
||||
whether or not to trigger boosting and when to do that.
|
||||
|
||||
The ``boost`` File in ``sysfs``
|
||||
-------------------------------
|
||||
|
||||
This file is located under :file:`/sys/devices/system/cpu/cpufreq/` and controls
|
||||
the "boost" setting for the whole system. It is not present if the underlying
|
||||
scaling driver does not support the frequency boost mechanism (or supports it,
|
||||
but provides a driver-specific interface for controlling it, like
|
||||
``intel_pstate``).
|
||||
|
||||
If the value in this file is 1, the frequency boost mechanism is enabled. This
|
||||
means that either the hardware can be put into states in which it is able to
|
||||
trigger boosting (in the hardware-based case), or the software is allowed to
|
||||
trigger boosting (in the software-based case). It does not mean that boosting
|
||||
is actually in use at the moment on any CPUs in the system. It only means a
|
||||
permission to use the frequency boost mechanism (which still may never be used
|
||||
for other reasons).
|
||||
|
||||
If the value in this file is 0, the frequency boost mechanism is disabled and
|
||||
cannot be used at all.
|
||||
|
||||
The only values that can be written to this file are 0 and 1.
|
||||
|
||||
Rationale for Boost Control Knob
|
||||
--------------------------------
|
||||
|
||||
The frequency boost mechanism is generally intended to help to achieve optimum
|
||||
CPU performance on time scales below software resolution (e.g. below the
|
||||
scheduler tick interval) and it is demonstrably suitable for many workloads, but
|
||||
it may lead to problems in certain situations.
|
||||
|
||||
For this reason, many systems make it possible to disable the frequency boost
|
||||
mechanism in the platform firmware (BIOS) setup, but that requires the system to
|
||||
be restarted for the setting to be adjusted as desired, which may not be
|
||||
practical at least in some cases. For example:
|
||||
|
||||
1. Boosting means overclocking the processor, although under controlled
|
||||
conditions. Generally, the processor's energy consumption increases
|
||||
as a result of increasing its frequency and voltage, even temporarily.
|
||||
That may not be desirable on systems that switch to power sources of
|
||||
limited capacity, such as batteries, so the ability to disable the boost
|
||||
mechanism while the system is running may help there (but that depends on
|
||||
the workload too).
|
||||
|
||||
2. In some situations deterministic behavior is more important than
|
||||
performance or energy consumption (or both) and the ability to disable
|
||||
boosting while the system is running may be useful then.
|
||||
|
||||
3. To examine the impact of the frequency boost mechanism itself, it is useful
|
||||
to be able to run tests with and without boosting, preferably without
|
||||
restarting the system in the meantime.
|
||||
|
||||
4. Reproducible results are important when running benchmarks. Since
|
||||
the boosting functionality depends on the load of the whole package,
|
||||
single-thread performance may vary because of it which may lead to
|
||||
unreproducible results sometimes. That can be avoided by disabling the
|
||||
frequency boost mechanism before running benchmarks sensitive to that
|
||||
issue.
|
||||
|
||||
Legacy AMD ``cpb`` Knob
|
||||
-----------------------
|
||||
|
||||
The AMD powernow-k8 scaling driver supports a ``sysfs`` knob very similar to
|
||||
the global ``boost`` one. It is used for disabling/enabling the "Core
|
||||
Performance Boost" feature of some AMD processors.
|
||||
|
||||
If present, that knob is located in every ``CPUFreq`` policy directory in
|
||||
``sysfs`` (:file:`/sys/devices/system/cpu/cpufreq/policyX/`) and is called
|
||||
``cpb``, which indicates a more fine grained control interface. The actual
|
||||
implementation, however, works on the system-wide basis and setting that knob
|
||||
for one policy causes the same value of it to be set for all of the other
|
||||
policies at the same time.
|
||||
|
||||
That knob is still supported on AMD processors that support its underlying
|
||||
hardware feature, but it may be configured out of the kernel (via the
|
||||
:c:macro:`CONFIG_X86_ACPI_CPUFREQ_CPB` configuration option) and the global
|
||||
``boost`` knob is present regardless. Thus it is always possible use the
|
||||
``boost`` knob instead of the ``cpb`` one which is highly recommended, as that
|
||||
is more consistent with what all of the other systems do (and the ``cpb`` knob
|
||||
may not be supported any more in the future).
|
||||
|
||||
The ``cpb`` knob is never present for any processors without the underlying
|
||||
hardware feature (e.g. all Intel ones), even if the
|
||||
:c:macro:`CONFIG_X86_ACPI_CPUFREQ_CPB` configuration option is set.
|
||||
|
||||
|
||||
.. _Per-entity load tracking: https://lwn.net/Articles/531853/
|
15
Documentation/admin-guide/pm/index.rst
Normal file
15
Documentation/admin-guide/pm/index.rst
Normal file
|
@ -0,0 +1,15 @@
|
|||
================
|
||||
Power Management
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
cpufreq
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
|
@ -8,7 +8,7 @@ RAS concepts
|
|||
************
|
||||
|
||||
Reliability, Availability and Serviceability (RAS) is a concept used on
|
||||
servers meant to measure their robusteness.
|
||||
servers meant to measure their robustness.
|
||||
|
||||
Reliability
|
||||
is the probability that a system will produce correct outputs.
|
||||
|
@ -42,13 +42,13 @@ Among the monitoring measures, the most usual ones include:
|
|||
|
||||
* CPU – detect errors at instruction execution and at L1/L2/L3 caches;
|
||||
* Memory – add error correction logic (ECC) to detect and correct errors;
|
||||
* I/O – add CRC checksums for tranfered data;
|
||||
* I/O – add CRC checksums for transferred data;
|
||||
* Storage – RAID, journal file systems, checksums,
|
||||
Self-Monitoring, Analysis and Reporting Technology (SMART).
|
||||
|
||||
By monitoring the number of occurrences of error detections, it is possible
|
||||
to identify if the probability of hardware errors is increasing, and, on such
|
||||
case, do a preventive maintainance to replace a degrated component while
|
||||
case, do a preventive maintenance to replace a degraded component while
|
||||
those errors are correctable.
|
||||
|
||||
Types of errors
|
||||
|
@ -121,7 +121,7 @@ using the ``dmidecode`` tool. For example, on a desktop machine, it shows::
|
|||
On the above example, a DDR4 SO-DIMM memory module is located at the
|
||||
system's memory labeled as "BANK 0", as given by the *bank locator* field.
|
||||
Please notice that, on such system, the *total width* is equal to the
|
||||
*data witdh*. It means that such memory module doesn't have error
|
||||
*data width*. It means that such memory module doesn't have error
|
||||
detection/correction mechanisms.
|
||||
|
||||
Unfortunately, not all systems use the same field to specify the memory
|
||||
|
@ -145,7 +145,7 @@ bank. On this example, from an older server, ``dmidecode`` shows::
|
|||
|
||||
There, the DDR3 RDIMM memory module is located at the system's memory labeled
|
||||
as "DIMM_A1", as given by the *locator* field. Please notice that this
|
||||
memory module has 64 bits of *data witdh* and 72 bits of *total width*. So,
|
||||
memory module has 64 bits of *data width* and 72 bits of *total width*. So,
|
||||
it has 8 extra bits to be used by error detection and correction mechanisms.
|
||||
Such kind of memory is called Error-correcting code memory (ECC memory).
|
||||
|
||||
|
@ -186,7 +186,7 @@ Architecture (MCA)\ [#f3]_.
|
|||
.. [#f1] Please notice that several memory controllers allow operation on a
|
||||
mode called "Lock-Step", where it groups two memory modules together,
|
||||
doing 128-bit reads/writes. That gives 16 bits for error correction, with
|
||||
significatively improves the error correction mechanism, at the expense
|
||||
significantly improves the error correction mechanism, at the expense
|
||||
that, when an error happens, there's no way to know what memory module is
|
||||
to blame. So, it has to blame both memory modules.
|
||||
|
||||
|
|
|
@ -14,14 +14,17 @@ Contact
|
|||
The Linux kernel security team can be contacted by email at
|
||||
<security@kernel.org>. This is a private list of security officers
|
||||
who will help verify the bug report and develop and release a fix.
|
||||
It is possible that the security team will bring in extra help from
|
||||
area maintainers to understand and fix the security vulnerability.
|
||||
If you already have a fix, please include it with your report, as
|
||||
that can speed up the process considerably. It is possible that the
|
||||
security team will bring in extra help from area maintainers to
|
||||
understand and fix the security vulnerability.
|
||||
|
||||
As it is with any bug, the more information provided the easier it
|
||||
will be to diagnose and fix. Please review the procedure outlined in
|
||||
admin-guide/reporting-bugs.rst if you are unclear about what information is helpful.
|
||||
Any exploit code is very helpful and will not be released without
|
||||
consent from the reporter unless it has already been made public.
|
||||
admin-guide/reporting-bugs.rst if you are unclear about what
|
||||
information is helpful. Any exploit code is very helpful and will not
|
||||
be released without consent from the reporter unless it has already been
|
||||
made public.
|
||||
|
||||
Disclosure
|
||||
----------
|
||||
|
@ -39,6 +42,32 @@ disclosure is from immediate (esp. if it's already publicly known)
|
|||
to a few weeks. As a basic default policy, we expect report date to
|
||||
disclosure date to be on the order of 7 days.
|
||||
|
||||
Coordination
|
||||
------------
|
||||
|
||||
Fixes for sensitive bugs, such as those that might lead to privilege
|
||||
escalations, may need to be coordinated with the private
|
||||
<linux-distros@vs.openwall.org> mailing list so that distribution vendors
|
||||
are well prepared to issue a fixed kernel upon public disclosure of the
|
||||
upstream fix. Distros will need some time to test the proposed patch and
|
||||
will generally request at least a few days of embargo, and vendor update
|
||||
publication prefers to happen Tuesday through Thursday. When appropriate,
|
||||
the security team can assist with this coordination, or the reporter can
|
||||
include linux-distros from the start. In this case, remember to prefix
|
||||
the email Subject line with "[vs]" as described in the linux-distros wiki:
|
||||
<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>
|
||||
|
||||
CVE assignment
|
||||
--------------
|
||||
|
||||
The security team does not normally assign CVEs, nor do we require them
|
||||
for reports or fixes, as this can needlessly complicate the process and
|
||||
may delay the bug handling. If a reporter wishes to have a CVE identifier
|
||||
assigned ahead of public disclosure, they will need to contact the private
|
||||
linux-distros list, described above. When such a CVE identifier is known
|
||||
before a patch is provided, it is desirable to mention it in the commit
|
||||
message, though.
|
||||
|
||||
Non-disclosure agreements
|
||||
-------------------------
|
||||
|
||||
|
|
|
@ -212,7 +212,8 @@ I hit SysRq, but nothing seems to happen, what's wrong?
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are some keyboards that produce a different keycode for SysRq than the
|
||||
pre-defined value of 99 (see ``KEY_SYSRQ`` in ``include/linux/input.h``), or
|
||||
pre-defined value of 99
|
||||
(see ``KEY_SYSRQ`` in ``include/uapi/linux/input-event-codes.h``), or
|
||||
which don't have a SysRq key at all. In these cases, run ``showkey -s`` to find
|
||||
an appropriate scancode sequence, and use ``setkeycodes <sequence> 99`` to map
|
||||
this sequence to the usual SysRq code (e.g., ``setkeycodes e05b 99``). It's
|
||||
|
|
|
@ -48,7 +48,7 @@ Note that not all combinations are supported - only values 0 through 5.
|
|||
For example, the following will turn on the warnings, but without
|
||||
fixing up or sending SIGBUS signals:
|
||||
|
||||
echo 1 > /proc/sys/debug/alignment
|
||||
echo 1 > /proc/cpu/alignment
|
||||
|
||||
You can also read the content of the same file to get statistical
|
||||
information on unaligned access occurrences plus the current mode of
|
||||
|
|
|
@ -17,7 +17,7 @@ import os
|
|||
import sphinx
|
||||
|
||||
# Get Sphinx version
|
||||
major, minor, patch = map(int, sphinx.__version__.split("."))
|
||||
major, minor, patch = sphinx.version_info[:3]
|
||||
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
|
@ -29,12 +29,12 @@ from load_config import loadConfig
|
|||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
needs_sphinx = '1.2'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain']
|
||||
extensions = ['kerneldoc', 'rstFlatTable', 'kernel_include', 'cdomain', 'kfigure']
|
||||
|
||||
# The name of the math extension changed on Sphinx 1.4
|
||||
if major == 1 and minor > 3:
|
||||
|
|
130
Documentation/core-api/flexible-arrays.rst
Normal file
130
Documentation/core-api/flexible-arrays.rst
Normal file
|
@ -0,0 +1,130 @@
|
|||
|
||||
===================================
|
||||
Using flexible arrays in the kernel
|
||||
===================================
|
||||
|
||||
Large contiguous memory allocations can be unreliable in the Linux kernel.
|
||||
Kernel programmers will sometimes respond to this problem by allocating
|
||||
pages with :c:func:`vmalloc()`. This solution not ideal, though. On 32-bit
|
||||
systems, memory from vmalloc() must be mapped into a relatively small address
|
||||
space; it's easy to run out. On SMP systems, the page table changes required
|
||||
by vmalloc() allocations can require expensive cross-processor interrupts on
|
||||
all CPUs. And, on all systems, use of space in the vmalloc() range increases
|
||||
pressure on the translation lookaside buffer (TLB), reducing the performance
|
||||
of the system.
|
||||
|
||||
In many cases, the need for memory from vmalloc() can be eliminated by piecing
|
||||
together an array from smaller parts; the flexible array library exists to make
|
||||
this task easier.
|
||||
|
||||
A flexible array holds an arbitrary (within limits) number of fixed-sized
|
||||
objects, accessed via an integer index. Sparse arrays are handled
|
||||
reasonably well. Only single-page allocations are made, so memory
|
||||
allocation failures should be relatively rare. The down sides are that the
|
||||
arrays cannot be indexed directly, individual object size cannot exceed the
|
||||
system page size, and putting data into a flexible array requires a copy
|
||||
operation. It's also worth noting that flexible arrays do no internal
|
||||
locking at all; if concurrent access to an array is possible, then the
|
||||
caller must arrange for appropriate mutual exclusion.
|
||||
|
||||
The creation of a flexible array is done with :c:func:`flex_array_alloc()`::
|
||||
|
||||
#include <linux/flex_array.h>
|
||||
|
||||
struct flex_array *flex_array_alloc(int element_size,
|
||||
unsigned int total,
|
||||
gfp_t flags);
|
||||
|
||||
The individual object size is provided by ``element_size``, while total is the
|
||||
maximum number of objects which can be stored in the array. The flags
|
||||
argument is passed directly to the internal memory allocation calls. With
|
||||
the current code, using flags to ask for high memory is likely to lead to
|
||||
notably unpleasant side effects.
|
||||
|
||||
It is also possible to define flexible arrays at compile time with::
|
||||
|
||||
DEFINE_FLEX_ARRAY(name, element_size, total);
|
||||
|
||||
This macro will result in a definition of an array with the given name; the
|
||||
element size and total will be checked for validity at compile time.
|
||||
|
||||
Storing data into a flexible array is accomplished with a call to
|
||||
:c:func:`flex_array_put()`::
|
||||
|
||||
int flex_array_put(struct flex_array *array, unsigned int element_nr,
|
||||
void *src, gfp_t flags);
|
||||
|
||||
This call will copy the data from src into the array, in the position
|
||||
indicated by ``element_nr`` (which must be less than the maximum specified when
|
||||
the array was created). If any memory allocations must be performed, flags
|
||||
will be used. The return value is zero on success, a negative error code
|
||||
otherwise.
|
||||
|
||||
There might possibly be a need to store data into a flexible array while
|
||||
running in some sort of atomic context; in this situation, sleeping in the
|
||||
memory allocator would be a bad thing. That can be avoided by using
|
||||
``GFP_ATOMIC`` for the flags value, but, often, there is a better way. The
|
||||
trick is to ensure that any needed memory allocations are done before
|
||||
entering atomic context, using :c:func:`flex_array_prealloc()`::
|
||||
|
||||
int flex_array_prealloc(struct flex_array *array, unsigned int start,
|
||||
unsigned int nr_elements, gfp_t flags);
|
||||
|
||||
This function will ensure that memory for the elements indexed in the range
|
||||
defined by ``start`` and ``nr_elements`` has been allocated. Thereafter, a
|
||||
``flex_array_put()`` call on an element in that range is guaranteed not to
|
||||
block.
|
||||
|
||||
Getting data back out of the array is done with :c:func:`flex_array_get()`::
|
||||
|
||||
void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
|
||||
|
||||
The return value is a pointer to the data element, or NULL if that
|
||||
particular element has never been allocated.
|
||||
|
||||
Note that it is possible to get back a valid pointer for an element which
|
||||
has never been stored in the array. Memory for array elements is allocated
|
||||
one page at a time; a single allocation could provide memory for several
|
||||
adjacent elements. Flexible array elements are normally initialized to the
|
||||
value ``FLEX_ARRAY_FREE`` (defined as 0x6c in <linux/poison.h>), so errors
|
||||
involving that number probably result from use of unstored array entries.
|
||||
Note that, if array elements are allocated with ``__GFP_ZERO``, they will be
|
||||
initialized to zero and this poisoning will not happen.
|
||||
|
||||
Individual elements in the array can be cleared with
|
||||
:c:func:`flex_array_clear()`::
|
||||
|
||||
int flex_array_clear(struct flex_array *array, unsigned int element_nr);
|
||||
|
||||
This function will set the given element to ``FLEX_ARRAY_FREE`` and return
|
||||
zero. If storage for the indicated element is not allocated for the array,
|
||||
``flex_array_clear()`` will return ``-EINVAL`` instead. Note that clearing an
|
||||
element does not release the storage associated with it; to reduce the
|
||||
allocated size of an array, call :c:func:`flex_array_shrink()`::
|
||||
|
||||
int flex_array_shrink(struct flex_array *array);
|
||||
|
||||
The return value will be the number of pages of memory actually freed.
|
||||
This function works by scanning the array for pages containing nothing but
|
||||
``FLEX_ARRAY_FREE`` bytes, so (1) it can be expensive, and (2) it will not work
|
||||
if the array's pages are allocated with ``__GFP_ZERO``.
|
||||
|
||||
It is possible to remove all elements of an array with a call to
|
||||
:c:func:`flex_array_free_parts()`::
|
||||
|
||||
void flex_array_free_parts(struct flex_array *array);
|
||||
|
||||
This call frees all elements, but leaves the array itself in place.
|
||||
Freeing the entire array is done with :c:func:`flex_array_free()`::
|
||||
|
||||
void flex_array_free(struct flex_array *array);
|
||||
|
||||
As of this writing, there are no users of flexible arrays in the mainline
|
||||
kernel. The functions described here are also not exported to modules;
|
||||
that will probably be fixed when somebody comes up with a need for it.
|
||||
|
||||
|
||||
Flexible array functions
|
||||
------------------------
|
||||
|
||||
.. kernel-doc:: include/linux/flex_array.h
|
440
Documentation/core-api/genericirq.rst
Normal file
440
Documentation/core-api/genericirq.rst
Normal file
|
@ -0,0 +1,440 @@
|
|||
.. include:: <isonum.txt>
|
||||
|
||||
==========================
|
||||
Linux generic IRQ handling
|
||||
==========================
|
||||
|
||||
:Copyright: |copy| 2005-2010: Thomas Gleixner
|
||||
:Copyright: |copy| 2005-2006: Ingo Molnar
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The generic interrupt handling layer is designed to provide a complete
|
||||
abstraction of interrupt handling for device drivers. It is able to
|
||||
handle all the different types of interrupt controller hardware. Device
|
||||
drivers use generic API functions to request, enable, disable and free
|
||||
interrupts. The drivers do not have to know anything about interrupt
|
||||
hardware details, so they can be used on different platforms without
|
||||
code changes.
|
||||
|
||||
This documentation is provided to developers who want to implement an
|
||||
interrupt subsystem based for their architecture, with the help of the
|
||||
generic IRQ handling layer.
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
The original implementation of interrupt handling in Linux uses the
|
||||
:c:func:`__do_IRQ` super-handler, which is able to deal with every type of
|
||||
interrupt logic.
|
||||
|
||||
Originally, Russell King identified different types of handlers to build
|
||||
a quite universal set for the ARM interrupt handler implementation in
|
||||
Linux 2.5/2.6. He distinguished between:
|
||||
|
||||
- Level type
|
||||
|
||||
- Edge type
|
||||
|
||||
- Simple type
|
||||
|
||||
During the implementation we identified another type:
|
||||
|
||||
- Fast EOI type
|
||||
|
||||
In the SMP world of the :c:func:`__do_IRQ` super-handler another type was
|
||||
identified:
|
||||
|
||||
- Per CPU type
|
||||
|
||||
This split implementation of high-level IRQ handlers allows us to
|
||||
optimize the flow of the interrupt handling for each specific interrupt
|
||||
type. This reduces complexity in that particular code path and allows
|
||||
the optimized handling of a given type.
|
||||
|
||||
The original general IRQ implementation used hw_interrupt_type
|
||||
structures and their ``->ack``, ``->end`` [etc.] callbacks to differentiate
|
||||
the flow control in the super-handler. This leads to a mix of flow logic
|
||||
and low-level hardware logic, and it also leads to unnecessary code
|
||||
duplication: for example in i386, there is an ``ioapic_level_irq`` and an
|
||||
``ioapic_edge_irq`` IRQ-type which share many of the low-level details but
|
||||
have different flow handling.
|
||||
|
||||
A more natural abstraction is the clean separation of the 'irq flow' and
|
||||
the 'chip details'.
|
||||
|
||||
Analysing a couple of architecture's IRQ subsystem implementations
|
||||
reveals that most of them can use a generic set of 'irq flow' methods
|
||||
and only need to add the chip-level specific code. The separation is
|
||||
also valuable for (sub)architectures which need specific quirks in the
|
||||
IRQ flow itself but not in the chip details - and thus provides a more
|
||||
transparent IRQ subsystem design.
|
||||
|
||||
Each interrupt descriptor is assigned its own high-level flow handler,
|
||||
which is normally one of the generic implementations. (This high-level
|
||||
flow handler implementation also makes it simple to provide
|
||||
demultiplexing handlers which can be found in embedded platforms on
|
||||
various architectures.)
|
||||
|
||||
The separation makes the generic interrupt handling layer more flexible
|
||||
and extensible. For example, an (sub)architecture can use a generic
|
||||
IRQ-flow implementation for 'level type' interrupts and add a
|
||||
(sub)architecture specific 'edge type' implementation.
|
||||
|
||||
To make the transition to the new model easier and prevent the breakage
|
||||
of existing implementations, the :c:func:`__do_IRQ` super-handler is still
|
||||
available. This leads to a kind of duality for the time being. Over time
|
||||
the new model should be used in more and more architectures, as it
|
||||
enables smaller and cleaner IRQ subsystems. It's deprecated for three
|
||||
years now and about to be removed.
|
||||
|
||||
Known Bugs And Assumptions
|
||||
==========================
|
||||
|
||||
None (knock on wood).
|
||||
|
||||
Abstraction layers
|
||||
==================
|
||||
|
||||
There are three main levels of abstraction in the interrupt code:
|
||||
|
||||
1. High-level driver API
|
||||
|
||||
2. High-level IRQ flow handlers
|
||||
|
||||
3. Chip-level hardware encapsulation
|
||||
|
||||
Interrupt control flow
|
||||
----------------------
|
||||
|
||||
Each interrupt is described by an interrupt descriptor structure
|
||||
irq_desc. The interrupt is referenced by an 'unsigned int' numeric
|
||||
value which selects the corresponding interrupt description structure in
|
||||
the descriptor structures array. The descriptor structure contains
|
||||
status information and pointers to the interrupt flow method and the
|
||||
interrupt chip structure which are assigned to this interrupt.
|
||||
|
||||
Whenever an interrupt triggers, the low-level architecture code calls
|
||||
into the generic interrupt code by calling :c:func:`desc->handle_irq`. This
|
||||
high-level IRQ handling function only uses desc->irq_data.chip
|
||||
primitives referenced by the assigned chip descriptor structure.
|
||||
|
||||
High-level Driver API
|
||||
---------------------
|
||||
|
||||
The high-level Driver API consists of following functions:
|
||||
|
||||
- :c:func:`request_irq`
|
||||
|
||||
- :c:func:`free_irq`
|
||||
|
||||
- :c:func:`disable_irq`
|
||||
|
||||
- :c:func:`enable_irq`
|
||||
|
||||
- :c:func:`disable_irq_nosync` (SMP only)
|
||||
|
||||
- :c:func:`synchronize_irq` (SMP only)
|
||||
|
||||
- :c:func:`irq_set_irq_type`
|
||||
|
||||
- :c:func:`irq_set_irq_wake`
|
||||
|
||||
- :c:func:`irq_set_handler_data`
|
||||
|
||||
- :c:func:`irq_set_chip`
|
||||
|
||||
- :c:func:`irq_set_chip_data`
|
||||
|
||||
See the autogenerated function documentation for details.
|
||||
|
||||
High-level IRQ flow handlers
|
||||
----------------------------
|
||||
|
||||
The generic layer provides a set of pre-defined irq-flow methods:
|
||||
|
||||
- :c:func:`handle_level_irq`
|
||||
|
||||
- :c:func:`handle_edge_irq`
|
||||
|
||||
- :c:func:`handle_fasteoi_irq`
|
||||
|
||||
- :c:func:`handle_simple_irq`
|
||||
|
||||
- :c:func:`handle_percpu_irq`
|
||||
|
||||
- :c:func:`handle_edge_eoi_irq`
|
||||
|
||||
- :c:func:`handle_bad_irq`
|
||||
|
||||
The interrupt flow handlers (either pre-defined or architecture
|
||||
specific) are assigned to specific interrupts by the architecture either
|
||||
during bootup or during device initialization.
|
||||
|
||||
Default flow implementations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Helper functions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
The helper functions call the chip primitives and are used by the
|
||||
default flow implementations. The following helper functions are
|
||||
implemented (simplified excerpt)::
|
||||
|
||||
default_enable(struct irq_data *data)
|
||||
{
|
||||
desc->irq_data.chip->irq_unmask(data);
|
||||
}
|
||||
|
||||
default_disable(struct irq_data *data)
|
||||
{
|
||||
if (!delay_disable(data))
|
||||
desc->irq_data.chip->irq_mask(data);
|
||||
}
|
||||
|
||||
default_ack(struct irq_data *data)
|
||||
{
|
||||
chip->irq_ack(data);
|
||||
}
|
||||
|
||||
default_mask_ack(struct irq_data *data)
|
||||
{
|
||||
if (chip->irq_mask_ack) {
|
||||
chip->irq_mask_ack(data);
|
||||
} else {
|
||||
chip->irq_mask(data);
|
||||
chip->irq_ack(data);
|
||||
}
|
||||
}
|
||||
|
||||
noop(struct irq_data *data))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Default flow handler implementations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Default Level IRQ flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_level_irq provides a generic implementation for level-triggered
|
||||
interrupts.
|
||||
|
||||
The following control flow is implemented (simplified excerpt)::
|
||||
|
||||
:c:func:`desc->irq_data.chip->irq_mask_ack`;
|
||||
handle_irq_event(desc->action);
|
||||
:c:func:`desc->irq_data.chip->irq_unmask`;
|
||||
|
||||
|
||||
Default Fast EOI IRQ flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_fasteoi_irq provides a generic implementation for interrupts,
|
||||
which only need an EOI at the end of the handler.
|
||||
|
||||
The following control flow is implemented (simplified excerpt)::
|
||||
|
||||
handle_irq_event(desc->action);
|
||||
:c:func:`desc->irq_data.chip->irq_eoi`;
|
||||
|
||||
|
||||
Default Edge IRQ flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_edge_irq provides a generic implementation for edge-triggered
|
||||
interrupts.
|
||||
|
||||
The following control flow is implemented (simplified excerpt)::
|
||||
|
||||
if (desc->status & running) {
|
||||
:c:func:`desc->irq_data.chip->irq_mask_ack`;
|
||||
desc->status |= pending | masked;
|
||||
return;
|
||||
}
|
||||
:c:func:`desc->irq_data.chip->irq_ack`;
|
||||
desc->status |= running;
|
||||
do {
|
||||
if (desc->status & masked)
|
||||
:c:func:`desc->irq_data.chip->irq_unmask`;
|
||||
desc->status &= ~pending;
|
||||
handle_irq_event(desc->action);
|
||||
} while (status & pending);
|
||||
desc->status &= ~running;
|
||||
|
||||
|
||||
Default simple IRQ flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_simple_irq provides a generic implementation for simple
|
||||
interrupts.
|
||||
|
||||
.. note::
|
||||
|
||||
The simple flow handler does not call any handler/chip primitives.
|
||||
|
||||
The following control flow is implemented (simplified excerpt)::
|
||||
|
||||
handle_irq_event(desc->action);
|
||||
|
||||
|
||||
Default per CPU flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_percpu_irq provides a generic implementation for per CPU
|
||||
interrupts.
|
||||
|
||||
Per CPU interrupts are only available on SMP and the handler provides a
|
||||
simplified version without locking.
|
||||
|
||||
The following control flow is implemented (simplified excerpt)::
|
||||
|
||||
if (desc->irq_data.chip->irq_ack)
|
||||
:c:func:`desc->irq_data.chip->irq_ack`;
|
||||
handle_irq_event(desc->action);
|
||||
if (desc->irq_data.chip->irq_eoi)
|
||||
:c:func:`desc->irq_data.chip->irq_eoi`;
|
||||
|
||||
|
||||
EOI Edge IRQ flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_edge_eoi_irq provides an abnomination of the edge handler
|
||||
which is solely used to tame a badly wreckaged irq controller on
|
||||
powerpc/cell.
|
||||
|
||||
Bad IRQ flow handler
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
handle_bad_irq is used for spurious interrupts which have no real
|
||||
handler assigned..
|
||||
|
||||
Quirks and optimizations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The generic functions are intended for 'clean' architectures and chips,
|
||||
which have no platform-specific IRQ handling quirks. If an architecture
|
||||
needs to implement quirks on the 'flow' level then it can do so by
|
||||
overriding the high-level irq-flow handler.
|
||||
|
||||
Delayed interrupt disable
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This per interrupt selectable feature, which was introduced by Russell
|
||||
King in the ARM interrupt implementation, does not mask an interrupt at
|
||||
the hardware level when :c:func:`disable_irq` is called. The interrupt is kept
|
||||
enabled and is masked in the flow handler when an interrupt event
|
||||
happens. This prevents losing edge interrupts on hardware which does not
|
||||
store an edge interrupt event while the interrupt is disabled at the
|
||||
hardware level. When an interrupt arrives while the IRQ_DISABLED flag
|
||||
is set, then the interrupt is masked at the hardware level and the
|
||||
IRQ_PENDING bit is set. When the interrupt is re-enabled by
|
||||
:c:func:`enable_irq` the pending bit is checked and if it is set, the interrupt
|
||||
is resent either via hardware or by a software resend mechanism. (It's
|
||||
necessary to enable CONFIG_HARDIRQS_SW_RESEND when you want to use
|
||||
the delayed interrupt disable feature and your hardware is not capable
|
||||
of retriggering an interrupt.) The delayed interrupt disable is not
|
||||
configurable.
|
||||
|
||||
Chip-level hardware encapsulation
|
||||
---------------------------------
|
||||
|
||||
The chip-level hardware descriptor structure :c:type:`irq_chip` contains all
|
||||
the direct chip relevant functions, which can be utilized by the irq flow
|
||||
implementations.
|
||||
|
||||
- ``irq_ack``
|
||||
|
||||
- ``irq_mask_ack`` - Optional, recommended for performance
|
||||
|
||||
- ``irq_mask``
|
||||
|
||||
- ``irq_unmask``
|
||||
|
||||
- ``irq_eoi`` - Optional, required for EOI flow handlers
|
||||
|
||||
- ``irq_retrigger`` - Optional
|
||||
|
||||
- ``irq_set_type`` - Optional
|
||||
|
||||
- ``irq_set_wake`` - Optional
|
||||
|
||||
These primitives are strictly intended to mean what they say: ack means
|
||||
ACK, masking means masking of an IRQ line, etc. It is up to the flow
|
||||
handler(s) to use these basic units of low-level functionality.
|
||||
|
||||
__do_IRQ entry point
|
||||
====================
|
||||
|
||||
The original implementation :c:func:`__do_IRQ` was an alternative entry point
|
||||
for all types of interrupts. It no longer exists.
|
||||
|
||||
This handler turned out to be not suitable for all interrupt hardware
|
||||
and was therefore reimplemented with split functionality for
|
||||
edge/level/simple/percpu interrupts. This is not only a functional
|
||||
optimization. It also shortens code paths for interrupts.
|
||||
|
||||
Locking on SMP
|
||||
==============
|
||||
|
||||
The locking of chip registers is up to the architecture that defines the
|
||||
chip primitives. The per-irq structure is protected via desc->lock, by
|
||||
the generic layer.
|
||||
|
||||
Generic interrupt chip
|
||||
======================
|
||||
|
||||
To avoid copies of identical implementations of IRQ chips the core
|
||||
provides a configurable generic interrupt chip implementation.
|
||||
Developers should check carefully whether the generic chip fits their
|
||||
needs before implementing the same functionality slightly differently
|
||||
themselves.
|
||||
|
||||
.. kernel-doc:: kernel/irq/generic-chip.c
|
||||
:export:
|
||||
|
||||
Structures
|
||||
==========
|
||||
|
||||
This chapter contains the autogenerated documentation of the structures
|
||||
which are used in the generic IRQ layer.
|
||||
|
||||
.. kernel-doc:: include/linux/irq.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/linux/interrupt.h
|
||||
:internal:
|
||||
|
||||
Public Functions Provided
|
||||
=========================
|
||||
|
||||
This chapter contains the autogenerated documentation of the kernel API
|
||||
functions which are exported.
|
||||
|
||||
.. kernel-doc:: kernel/irq/manage.c
|
||||
|
||||
.. kernel-doc:: kernel/irq/chip.c
|
||||
|
||||
Internal Functions Provided
|
||||
===========================
|
||||
|
||||
This chapter contains the autogenerated documentation of the internal
|
||||
functions.
|
||||
|
||||
.. kernel-doc:: kernel/irq/irqdesc.c
|
||||
|
||||
.. kernel-doc:: kernel/irq/handle.c
|
||||
|
||||
.. kernel-doc:: kernel/irq/chip.c
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
The following people have contributed to this document:
|
||||
|
||||
1. Thomas Gleixner tglx@linutronix.de
|
||||
|
||||
2. Ingo Molnar mingo@elte.hu
|
|
@ -11,11 +11,14 @@ Core utilities
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
kernel-api
|
||||
assoc_array
|
||||
atomic_ops
|
||||
cpu_hotplug
|
||||
local_ops
|
||||
workqueue
|
||||
genericirq
|
||||
flexible-arrays
|
||||
|
||||
Interfaces for kernel debugging
|
||||
===============================
|
||||
|
|
346
Documentation/core-api/kernel-api.rst
Normal file
346
Documentation/core-api/kernel-api.rst
Normal file
|
@ -0,0 +1,346 @@
|
|||
====================
|
||||
The Linux Kernel API
|
||||
====================
|
||||
|
||||
Data Types
|
||||
==========
|
||||
|
||||
Doubly Linked Lists
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: include/linux/list.h
|
||||
:internal:
|
||||
|
||||
Basic C Library Functions
|
||||
=========================
|
||||
|
||||
When writing drivers, you cannot in general use routines which are from
|
||||
the C Library. Some of the functions have been found generally useful
|
||||
and they are listed below. The behaviour of these functions may vary
|
||||
slightly from those defined by ANSI, and these deviations are noted in
|
||||
the text.
|
||||
|
||||
String Conversions
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: lib/vsprintf.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: include/linux/kernel.h
|
||||
:functions: kstrtol
|
||||
|
||||
.. kernel-doc:: include/linux/kernel.h
|
||||
:functions: kstrtoul
|
||||
|
||||
.. kernel-doc:: lib/kstrtox.c
|
||||
:export:
|
||||
|
||||
String Manipulation
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: lib/string.c
|
||||
:export:
|
||||
|
||||
Bit Operations
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: arch/x86/include/asm/bitops.h
|
||||
:internal:
|
||||
|
||||
Basic Kernel Library Functions
|
||||
==============================
|
||||
|
||||
The Linux kernel provides more basic utility functions.
|
||||
|
||||
Bitmap Operations
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: lib/bitmap.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: lib/bitmap.c
|
||||
:internal:
|
||||
|
||||
Command-line Parsing
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: lib/cmdline.c
|
||||
:export:
|
||||
|
||||
CRC Functions
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: lib/crc7.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: lib/crc16.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: lib/crc-itu-t.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: lib/crc32.c
|
||||
|
||||
.. kernel-doc:: lib/crc-ccitt.c
|
||||
:export:
|
||||
|
||||
idr/ida Functions
|
||||
-----------------
|
||||
|
||||
.. kernel-doc:: include/linux/idr.h
|
||||
:doc: idr sync
|
||||
|
||||
.. kernel-doc:: lib/idr.c
|
||||
:doc: IDA description
|
||||
|
||||
.. kernel-doc:: lib/idr.c
|
||||
:export:
|
||||
|
||||
Memory Management in Linux
|
||||
==========================
|
||||
|
||||
The Slab Cache
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: include/linux/slab.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: mm/slab.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/util.c
|
||||
:export:
|
||||
|
||||
User Space Memory Access
|
||||
------------------------
|
||||
|
||||
.. kernel-doc:: arch/x86/include/asm/uaccess_32.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: arch/x86/lib/usercopy_32.c
|
||||
:export:
|
||||
|
||||
More Memory Management Functions
|
||||
--------------------------------
|
||||
|
||||
.. kernel-doc:: mm/readahead.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/filemap.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/memory.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/vmalloc.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/page_alloc.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: mm/mempool.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/dmapool.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/page-writeback.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: mm/truncate.c
|
||||
:export:
|
||||
|
||||
Kernel IPC facilities
|
||||
=====================
|
||||
|
||||
IPC utilities
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: ipc/util.c
|
||||
:internal:
|
||||
|
||||
FIFO Buffer
|
||||
===========
|
||||
|
||||
kfifo interface
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: include/linux/kfifo.h
|
||||
:internal:
|
||||
|
||||
relay interface support
|
||||
=======================
|
||||
|
||||
Relay interface support is designed to provide an efficient mechanism
|
||||
for tools and facilities to relay large amounts of data from kernel
|
||||
space to user space.
|
||||
|
||||
relay interface
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: kernel/relay.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: kernel/relay.c
|
||||
:internal:
|
||||
|
||||
Module Support
|
||||
==============
|
||||
|
||||
Module Loading
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: kernel/kmod.c
|
||||
:export:
|
||||
|
||||
Inter Module support
|
||||
--------------------
|
||||
|
||||
Refer to the file kernel/module.c for more information.
|
||||
|
||||
Hardware Interfaces
|
||||
===================
|
||||
|
||||
Interrupt Handling
|
||||
------------------
|
||||
|
||||
.. kernel-doc:: kernel/irq/manage.c
|
||||
:export:
|
||||
|
||||
DMA Channels
|
||||
------------
|
||||
|
||||
.. kernel-doc:: kernel/dma.c
|
||||
:export:
|
||||
|
||||
Resources Management
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: kernel/resource.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: kernel/resource.c
|
||||
:export:
|
||||
|
||||
MTRR Handling
|
||||
-------------
|
||||
|
||||
.. kernel-doc:: arch/x86/kernel/cpu/mtrr/main.c
|
||||
:export:
|
||||
|
||||
Security Framework
|
||||
==================
|
||||
|
||||
.. kernel-doc:: security/security.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: security/inode.c
|
||||
:export:
|
||||
|
||||
Audit Interfaces
|
||||
================
|
||||
|
||||
.. kernel-doc:: kernel/audit.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: kernel/auditsc.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: kernel/auditfilter.c
|
||||
:internal:
|
||||
|
||||
Accounting Framework
|
||||
====================
|
||||
|
||||
.. kernel-doc:: kernel/acct.c
|
||||
:internal:
|
||||
|
||||
Block Devices
|
||||
=============
|
||||
|
||||
.. kernel-doc:: block/blk-core.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-core.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: block/blk-map.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-sysfs.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: block/blk-settings.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-exec.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-flush.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-lib.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-tag.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: block/blk-tag.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: block/blk-integrity.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: kernel/trace/blktrace.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: block/genhd.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: block/genhd.c
|
||||
:export:
|
||||
|
||||
Char devices
|
||||
============
|
||||
|
||||
.. kernel-doc:: fs/char_dev.c
|
||||
:export:
|
||||
|
||||
Clock Framework
|
||||
===============
|
||||
|
||||
The clock framework defines programming interfaces to support software
|
||||
management of the system clock tree. This framework is widely used with
|
||||
System-On-Chip (SOC) platforms to support power management and various
|
||||
devices which may need custom clock rates. Note that these "clocks"
|
||||
don't relate to timekeeping or real time clocks (RTCs), each of which
|
||||
have separate frameworks. These :c:type:`struct clk <clk>`
|
||||
instances may be used to manage for example a 96 MHz signal that is used
|
||||
to shift bits into and out of peripherals or busses, or otherwise
|
||||
trigger synchronous state machine transitions in system hardware.
|
||||
|
||||
Power management is supported by explicit software clock gating: unused
|
||||
clocks are disabled, so the system doesn't waste power changing the
|
||||
state of transistors that aren't in active use. On some systems this may
|
||||
be backed by hardware clock gating, where clocks are gated without being
|
||||
disabled in software. Sections of chips that are powered but not clocked
|
||||
may be able to retain their last state. This low power state is often
|
||||
called a *retention mode*. This mode still incurs leakage currents,
|
||||
especially with finer circuit geometries, but for CMOS circuits power is
|
||||
mostly used by clocked state changes.
|
||||
|
||||
Power-aware drivers only enable their clocks when the device they manage
|
||||
is in active use. Also, system sleep states often differ according to
|
||||
which clock domains are active: while a "standby" state may allow wakeup
|
||||
from several active domains, a "mem" (suspend-to-RAM) state may require
|
||||
a more wholesale shutdown of clocks derived from higher speed PLLs and
|
||||
oscillators, limiting the number of possible wakeup event sources. A
|
||||
driver's suspend method may need to be aware of system-specific clock
|
||||
constraints on the target sleep state.
|
||||
|
||||
Some platforms support programmable clock generators. These can be used
|
||||
by external chips of various kinds, such as other CPUs, multimedia
|
||||
codecs, and devices with strict requirements for interface clocking.
|
||||
|
||||
.. kernel-doc:: include/linux/clk.h
|
||||
:internal:
|
|
@ -1,93 +0,0 @@
|
|||
Processor boosting control
|
||||
|
||||
- information for users -
|
||||
|
||||
Quick guide for the impatient:
|
||||
--------------------
|
||||
/sys/devices/system/cpu/cpufreq/boost
|
||||
controls the boost setting for the whole system. You can read and write
|
||||
that file with either "0" (boosting disabled) or "1" (boosting allowed).
|
||||
Reading or writing 1 does not mean that the system is boosting at this
|
||||
very moment, but only that the CPU _may_ raise the frequency at it's
|
||||
discretion.
|
||||
--------------------
|
||||
|
||||
Introduction
|
||||
-------------
|
||||
Some CPUs support a functionality to raise the operating frequency of
|
||||
some cores in a multi-core package if certain conditions apply, mostly
|
||||
if the whole chip is not fully utilized and below it's intended thermal
|
||||
budget. The decision about boost disable/enable is made either at hardware
|
||||
(e.g. x86) or software (e.g ARM).
|
||||
On Intel CPUs this is called "Turbo Boost", AMD calls it "Turbo-Core",
|
||||
in technical documentation "Core performance boost". In Linux we use
|
||||
the term "boost" for convenience.
|
||||
|
||||
Rationale for disable switch
|
||||
----------------------------
|
||||
|
||||
Though the idea is to just give better performance without any user
|
||||
intervention, sometimes the need arises to disable this functionality.
|
||||
Most systems offer a switch in the (BIOS) firmware to disable the
|
||||
functionality at all, but a more fine-grained and dynamic control would
|
||||
be desirable:
|
||||
1. While running benchmarks, reproducible results are important. Since
|
||||
the boosting functionality depends on the load of the whole package,
|
||||
single thread performance can vary. By explicitly disabling the boost
|
||||
functionality at least for the benchmark's run-time the system will run
|
||||
at a fixed frequency and results are reproducible again.
|
||||
2. To examine the impact of the boosting functionality it is helpful
|
||||
to do tests with and without boosting.
|
||||
3. Boosting means overclocking the processor, though under controlled
|
||||
conditions. By raising the frequency and the voltage the processor
|
||||
will consume more power than without the boosting, which may be
|
||||
undesirable for instance for mobile users. Disabling boosting may
|
||||
save power here, though this depends on the workload.
|
||||
|
||||
|
||||
User controlled switch
|
||||
----------------------
|
||||
|
||||
To allow the user to toggle the boosting functionality, the cpufreq core
|
||||
driver exports a sysfs knob to enable or disable it. There is a file:
|
||||
/sys/devices/system/cpu/cpufreq/boost
|
||||
which can either read "0" (boosting disabled) or "1" (boosting enabled).
|
||||
The file is exported only when cpufreq driver supports boosting.
|
||||
Explicitly changing the permissions and writing to that file anyway will
|
||||
return EINVAL.
|
||||
|
||||
On supported CPUs one can write either a "0" or a "1" into this file.
|
||||
This will either disable the boost functionality on all cores in the
|
||||
whole system (0) or will allow the software or hardware to boost at will
|
||||
(1).
|
||||
|
||||
Writing a "1" does not explicitly boost the system, but just allows the
|
||||
CPU to boost at their discretion. Some implementations take external
|
||||
factors like the chip's temperature into account, so boosting once does
|
||||
not necessarily mean that it will occur every time even using the exact
|
||||
same software setup.
|
||||
|
||||
|
||||
AMD legacy cpb switch
|
||||
---------------------
|
||||
The AMD powernow-k8 driver used to support a very similar switch to
|
||||
disable or enable the "Core Performance Boost" feature of some AMD CPUs.
|
||||
This switch was instantiated in each CPU's cpufreq directory
|
||||
(/sys/devices/system/cpu[0-9]*/cpufreq) and was called "cpb".
|
||||
Though the per CPU existence hints at a more fine grained control, the
|
||||
actual implementation only supported a system-global switch semantics,
|
||||
which was simply reflected into each CPU's file. Writing a 0 or 1 into it
|
||||
would pull the other CPUs to the same state.
|
||||
For compatibility reasons this file and its behavior is still supported
|
||||
on AMD CPUs, though it is now protected by a config switch
|
||||
(X86_ACPI_CPUFREQ_CPB). On Intel CPUs this file will never be created,
|
||||
even with the config option set.
|
||||
This functionality is considered legacy and will be removed in some future
|
||||
kernel version.
|
||||
|
||||
More fine grained boosting control
|
||||
----------------------------------
|
||||
|
||||
Technically it is possible to switch the boosting functionality at least
|
||||
on a per package basis, for some CPUs even per core. Currently the driver
|
||||
does not support it, but this may be implemented in the future.
|
|
@ -231,7 +231,7 @@ the reference implementation in drivers/cpufreq/longrun.c
|
|||
Only for drivers with target_index() and CPUFREQ_ASYNC_NOTIFICATION unset.
|
||||
|
||||
get_intermediate should return a stable intermediate frequency platform wants to
|
||||
switch to, and target_intermediate() should set CPU to to that frequency, before
|
||||
switch to, and target_intermediate() should set CPU to that frequency, before
|
||||
jumping to the frequency corresponding to 'index'. Core will take care of
|
||||
sending notifications and driver doesn't have to handle them in
|
||||
target_intermediate() or target_index().
|
||||
|
|
|
@ -1,301 +0,0 @@
|
|||
CPU frequency and voltage scaling code in the Linux(TM) kernel
|
||||
|
||||
|
||||
L i n u x C P U F r e q
|
||||
|
||||
C P U F r e q G o v e r n o r s
|
||||
|
||||
- information for users and developers -
|
||||
|
||||
|
||||
Dominik Brodowski <linux@brodo.de>
|
||||
some additions and corrections by Nico Golde <nico@ngolde.de>
|
||||
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
|
||||
Viresh Kumar <viresh.kumar@linaro.org>
|
||||
|
||||
|
||||
|
||||
Clock scaling allows you to change the clock speed of the CPUs on the
|
||||
fly. This is a nice method to save battery power, because the lower
|
||||
the clock speed, the less power the CPU consumes.
|
||||
|
||||
|
||||
Contents:
|
||||
---------
|
||||
1. What is a CPUFreq Governor?
|
||||
|
||||
2. Governors In the Linux Kernel
|
||||
2.1 Performance
|
||||
2.2 Powersave
|
||||
2.3 Userspace
|
||||
2.4 Ondemand
|
||||
2.5 Conservative
|
||||
2.6 Schedutil
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
|
||||
4. References
|
||||
|
||||
|
||||
1. What Is A CPUFreq Governor?
|
||||
==============================
|
||||
|
||||
Most cpufreq drivers (except the intel_pstate and longrun) or even most
|
||||
cpu frequency scaling algorithms only allow the CPU frequency to be set
|
||||
to predefined fixed values. In order to offer dynamic frequency
|
||||
scaling, the cpufreq core must be able to tell these drivers of a
|
||||
"target frequency". So these specific drivers will be transformed to
|
||||
offer a "->target/target_index/fast_switch()" call instead of the
|
||||
"->setpolicy()" call. For set_policy drivers, all stays the same,
|
||||
though.
|
||||
|
||||
How to decide what frequency within the CPUfreq policy should be used?
|
||||
That's done using "cpufreq governors".
|
||||
|
||||
Basically, it's the following flow graph:
|
||||
|
||||
CPU can be set to switch independently | CPU can only be set
|
||||
within specific "limits" | to specific frequencies
|
||||
|
||||
"CPUfreq policy"
|
||||
consists of frequency limits (policy->{min,max})
|
||||
and CPUfreq governor to be used
|
||||
/ \
|
||||
/ \
|
||||
/ the cpufreq governor decides
|
||||
/ (dynamically or statically)
|
||||
/ what target_freq to set within
|
||||
/ the limits of policy->{min,max}
|
||||
/ \
|
||||
/ \
|
||||
Using the ->setpolicy call, Using the ->target/target_index/fast_switch call,
|
||||
the limits and the the frequency closest
|
||||
"policy" is set. to target_freq is set.
|
||||
It is assured that it
|
||||
is within policy->{min,max}
|
||||
|
||||
|
||||
2. Governors In the Linux Kernel
|
||||
================================
|
||||
|
||||
2.1 Performance
|
||||
---------------
|
||||
|
||||
The CPUfreq governor "performance" sets the CPU statically to the
|
||||
highest frequency within the borders of scaling_min_freq and
|
||||
scaling_max_freq.
|
||||
|
||||
|
||||
2.2 Powersave
|
||||
-------------
|
||||
|
||||
The CPUfreq governor "powersave" sets the CPU statically to the
|
||||
lowest frequency within the borders of scaling_min_freq and
|
||||
scaling_max_freq.
|
||||
|
||||
|
||||
2.3 Userspace
|
||||
-------------
|
||||
|
||||
The CPUfreq governor "userspace" allows the user, or any userspace
|
||||
program running with UID "root", to set the CPU to a specific frequency
|
||||
by making a sysfs file "scaling_setspeed" available in the CPU-device
|
||||
directory.
|
||||
|
||||
|
||||
2.4 Ondemand
|
||||
------------
|
||||
|
||||
The CPUfreq governor "ondemand" sets the CPU frequency depending on the
|
||||
current system load. Load estimation is triggered by the scheduler
|
||||
through the update_util_data->func hook; when triggered, cpufreq checks
|
||||
the CPU-usage statistics over the last period and the governor sets the
|
||||
CPU accordingly. The CPU must have the capability to switch the
|
||||
frequency very quickly.
|
||||
|
||||
Sysfs files:
|
||||
|
||||
* sampling_rate:
|
||||
|
||||
Measured in uS (10^-6 seconds), this is how often you want the kernel
|
||||
to look at the CPU usage and to make decisions on what to do about the
|
||||
frequency. Typically this is set to values of around '10000' or more.
|
||||
It's default value is (cmp. with users-guide.txt): transition_latency
|
||||
* 1000. Be aware that transition latency is in ns and sampling_rate
|
||||
is in us, so you get the same sysfs value by default. Sampling rate
|
||||
should always get adjusted considering the transition latency to set
|
||||
the sampling rate 750 times as high as the transition latency in the
|
||||
bash (as said, 1000 is default), do:
|
||||
|
||||
$ echo `$(($(cat cpuinfo_transition_latency) * 750 / 1000)) > ondemand/sampling_rate
|
||||
|
||||
* sampling_rate_min:
|
||||
|
||||
The sampling rate is limited by the HW transition latency:
|
||||
transition_latency * 100
|
||||
|
||||
Or by kernel restrictions:
|
||||
- If CONFIG_NO_HZ_COMMON is set, the limit is 10ms fixed.
|
||||
- If CONFIG_NO_HZ_COMMON is not set or nohz=off boot parameter is
|
||||
used, the limits depend on the CONFIG_HZ option:
|
||||
HZ=1000: min=20000us (20ms)
|
||||
HZ=250: min=80000us (80ms)
|
||||
HZ=100: min=200000us (200ms)
|
||||
|
||||
The highest value of kernel and HW latency restrictions is shown and
|
||||
used as the minimum sampling rate.
|
||||
|
||||
* up_threshold:
|
||||
|
||||
This defines what the average CPU usage between the samplings of
|
||||
'sampling_rate' needs to be for the kernel to make a decision on
|
||||
whether it should increase the frequency. For example when it is set
|
||||
to its default value of '95' it means that between the checking
|
||||
intervals the CPU needs to be on average more than 95% in use to then
|
||||
decide that the CPU frequency needs to be increased.
|
||||
|
||||
* ignore_nice_load:
|
||||
|
||||
This parameter takes a value of '0' or '1'. When set to '0' (its
|
||||
default), all processes are counted towards the 'cpu utilisation'
|
||||
value. When set to '1', the processes that are run with a 'nice'
|
||||
value will not count (and thus be ignored) in the overall usage
|
||||
calculation. This is useful if you are running a CPU intensive
|
||||
calculation on your laptop that you do not care how long it takes to
|
||||
complete as you can 'nice' it and prevent it from taking part in the
|
||||
deciding process of whether to increase your CPU frequency.
|
||||
|
||||
* sampling_down_factor:
|
||||
|
||||
This parameter controls the rate at which the kernel makes a decision
|
||||
on when to decrease the frequency while running at top speed. When set
|
||||
to 1 (the default) decisions to reevaluate load are made at the same
|
||||
interval regardless of current clock speed. But when set to greater
|
||||
than 1 (e.g. 100) it acts as a multiplier for the scheduling interval
|
||||
for reevaluating load when the CPU is at its top speed due to high
|
||||
load. This improves performance by reducing the overhead of load
|
||||
evaluation and helping the CPU stay at its top speed when truly busy,
|
||||
rather than shifting back and forth in speed. This tunable has no
|
||||
effect on behavior at lower speeds/lower CPU loads.
|
||||
|
||||
* powersave_bias:
|
||||
|
||||
This parameter takes a value between 0 to 1000. It defines the
|
||||
percentage (times 10) value of the target frequency that will be
|
||||
shaved off of the target. For example, when set to 100 -- 10%, when
|
||||
ondemand governor would have targeted 1000 MHz, it will target
|
||||
1000 MHz - (10% of 1000 MHz) = 900 MHz instead. This is set to 0
|
||||
(disabled) by default.
|
||||
|
||||
When AMD frequency sensitivity powersave bias driver --
|
||||
drivers/cpufreq/amd_freq_sensitivity.c is loaded, this parameter
|
||||
defines the workload frequency sensitivity threshold in which a lower
|
||||
frequency is chosen instead of ondemand governor's original target.
|
||||
The frequency sensitivity is a hardware reported (on AMD Family 16h
|
||||
Processors and above) value between 0 to 100% that tells software how
|
||||
the performance of the workload running on a CPU will change when
|
||||
frequency changes. A workload with sensitivity of 0% (memory/IO-bound)
|
||||
will not perform any better on higher core frequency, whereas a
|
||||
workload with sensitivity of 100% (CPU-bound) will perform better
|
||||
higher the frequency. When the driver is loaded, this is set to 400 by
|
||||
default -- for CPUs running workloads with sensitivity value below
|
||||
40%, a lower frequency is chosen. Unloading the driver or writing 0
|
||||
will disable this feature.
|
||||
|
||||
|
||||
2.5 Conservative
|
||||
----------------
|
||||
|
||||
The CPUfreq governor "conservative", much like the "ondemand"
|
||||
governor, sets the CPU frequency depending on the current usage. It
|
||||
differs in behaviour in that it gracefully increases and decreases the
|
||||
CPU speed rather than jumping to max speed the moment there is any load
|
||||
on the CPU. This behaviour is more suitable in a battery powered
|
||||
environment. The governor is tweaked in the same manner as the
|
||||
"ondemand" governor through sysfs with the addition of:
|
||||
|
||||
* freq_step:
|
||||
|
||||
This describes what percentage steps the cpu freq should be increased
|
||||
and decreased smoothly by. By default the cpu frequency will increase
|
||||
in 5% chunks of your maximum cpu frequency. You can change this value
|
||||
to anywhere between 0 and 100 where '0' will effectively lock your CPU
|
||||
at a speed regardless of its load whilst '100' will, in theory, make
|
||||
it behave identically to the "ondemand" governor.
|
||||
|
||||
* down_threshold:
|
||||
|
||||
Same as the 'up_threshold' found for the "ondemand" governor but for
|
||||
the opposite direction. For example when set to its default value of
|
||||
'20' it means that if the CPU usage needs to be below 20% between
|
||||
samples to have the frequency decreased.
|
||||
|
||||
* sampling_down_factor:
|
||||
|
||||
Similar functionality as in "ondemand" governor. But in
|
||||
"conservative", it controls the rate at which the kernel makes a
|
||||
decision on when to decrease the frequency while running in any speed.
|
||||
Load for frequency increase is still evaluated every sampling rate.
|
||||
|
||||
|
||||
2.6 Schedutil
|
||||
-------------
|
||||
|
||||
The "schedutil" governor aims at better integration with the Linux
|
||||
kernel scheduler. Load estimation is achieved through the scheduler's
|
||||
Per-Entity Load Tracking (PELT) mechanism, which also provides
|
||||
information about the recent load [1]. This governor currently does
|
||||
load based DVFS only for tasks managed by CFS. RT and DL scheduler tasks
|
||||
are always run at the highest frequency. Unlike all the other
|
||||
governors, the code is located under the kernel/sched/ directory.
|
||||
|
||||
Sysfs files:
|
||||
|
||||
* rate_limit_us:
|
||||
|
||||
This contains a value in microseconds. The governor waits for
|
||||
rate_limit_us time before reevaluating the load again, after it has
|
||||
evaluated the load once.
|
||||
|
||||
For an in-depth comparison with the other governors refer to [2].
|
||||
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
=============================================
|
||||
|
||||
A new governor must register itself with the CPUfreq core using
|
||||
"cpufreq_register_governor". The struct cpufreq_governor, which has to
|
||||
be passed to that function, must contain the following values:
|
||||
|
||||
governor->name - A unique name for this governor.
|
||||
governor->owner - .THIS_MODULE for the governor module (if appropriate).
|
||||
|
||||
plus a set of hooks to the functions implementing the governor's logic.
|
||||
|
||||
The CPUfreq governor may call the CPU processor driver using one of
|
||||
these two functions:
|
||||
|
||||
int cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation);
|
||||
|
||||
int __cpufreq_driver_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation);
|
||||
|
||||
target_freq must be within policy->min and policy->max, of course.
|
||||
What's the difference between these two functions? When your governor is
|
||||
in a direct code path of a call to governor callbacks, like
|
||||
governor->start(), the policy->rwsem is still held in the cpufreq core,
|
||||
and there's no need to lock it again (in fact, this would cause a
|
||||
deadlock). So use __cpufreq_driver_target only in these cases. In all
|
||||
other cases (for example, when there's a "daemonized" function that
|
||||
wakes up every second), use cpufreq_driver_target to take policy->rwsem
|
||||
before the command is passed to the cpufreq driver.
|
||||
|
||||
4. References
|
||||
=============
|
||||
|
||||
[1] Per-entity load tracking: https://lwn.net/Articles/531853/
|
||||
[2] Improvements in CPU frequency management: https://lwn.net/Articles/682391/
|
||||
|
|
@ -21,8 +21,6 @@ Documents in this directory:
|
|||
|
||||
amd-powernow.txt - AMD powernow driver specific file.
|
||||
|
||||
boost.txt - Frequency boosting support.
|
||||
|
||||
core.txt - General description of the CPUFreq core and
|
||||
of CPUFreq notifiers.
|
||||
|
||||
|
@ -32,17 +30,12 @@ cpufreq-nforce2.txt - nVidia nForce2 platform specific file.
|
|||
|
||||
cpufreq-stats.txt - General description of sysfs cpufreq stats.
|
||||
|
||||
governors.txt - What are cpufreq governors and how to
|
||||
implement them?
|
||||
|
||||
index.txt - File index, Mailing list and Links (this document)
|
||||
|
||||
intel-pstate.txt - Intel pstate cpufreq driver specific file.
|
||||
|
||||
pcc-cpufreq.txt - PCC cpufreq driver specific file.
|
||||
|
||||
user-guide.txt - User Guide to CPUFreq
|
||||
|
||||
|
||||
Mailing List
|
||||
------------
|
||||
|
|
|
@ -1,228 +0,0 @@
|
|||
CPU frequency and voltage scaling code in the Linux(TM) kernel
|
||||
|
||||
|
||||
L i n u x C P U F r e q
|
||||
|
||||
U S E R G U I D E
|
||||
|
||||
|
||||
Dominik Brodowski <linux@brodo.de>
|
||||
|
||||
|
||||
|
||||
Clock scaling allows you to change the clock speed of the CPUs on the
|
||||
fly. This is a nice method to save battery power, because the lower
|
||||
the clock speed, the less power the CPU consumes.
|
||||
|
||||
|
||||
Contents:
|
||||
---------
|
||||
1. Supported Architectures and Processors
|
||||
1.1 ARM and ARM64
|
||||
1.2 x86
|
||||
1.3 sparc64
|
||||
1.4 ppc
|
||||
1.5 SuperH
|
||||
1.6 Blackfin
|
||||
|
||||
2. "Policy" / "Governor"?
|
||||
2.1 Policy
|
||||
2.2 Governor
|
||||
|
||||
3. How to change the CPU cpufreq policy and/or speed
|
||||
3.1 Preferred interface: sysfs
|
||||
|
||||
|
||||
|
||||
1. Supported Architectures and Processors
|
||||
=========================================
|
||||
|
||||
1.1 ARM and ARM64
|
||||
-----------------
|
||||
|
||||
Almost all ARM and ARM64 platforms support CPU frequency scaling.
|
||||
|
||||
1.2 x86
|
||||
-------
|
||||
|
||||
The following processors for the x86 architecture are supported by cpufreq:
|
||||
|
||||
AMD Elan - SC400, SC410
|
||||
AMD mobile K6-2+
|
||||
AMD mobile K6-3+
|
||||
AMD mobile Duron
|
||||
AMD mobile Athlon
|
||||
AMD Opteron
|
||||
AMD Athlon 64
|
||||
Cyrix Media GXm
|
||||
Intel mobile PIII and Intel mobile PIII-M on certain chipsets
|
||||
Intel Pentium 4, Intel Xeon
|
||||
Intel Pentium M (Centrino)
|
||||
National Semiconductors Geode GX
|
||||
Transmeta Crusoe
|
||||
Transmeta Efficeon
|
||||
VIA Cyrix 3 / C3
|
||||
various processors on some ACPI 2.0-compatible systems [*]
|
||||
And many more
|
||||
|
||||
[*] Only if "ACPI Processor Performance States" are available
|
||||
to the ACPI<->BIOS interface.
|
||||
|
||||
|
||||
1.3 sparc64
|
||||
-----------
|
||||
|
||||
The following processors for the sparc64 architecture are supported by
|
||||
cpufreq:
|
||||
|
||||
UltraSPARC-III
|
||||
|
||||
|
||||
1.4 ppc
|
||||
-------
|
||||
|
||||
Several "PowerBook" and "iBook2" notebooks are supported.
|
||||
The following POWER processors are supported in powernv mode:
|
||||
POWER8
|
||||
POWER9
|
||||
|
||||
1.5 SuperH
|
||||
----------
|
||||
|
||||
All SuperH processors supporting rate rounding through the clock
|
||||
framework are supported by cpufreq.
|
||||
|
||||
1.6 Blackfin
|
||||
------------
|
||||
|
||||
The following Blackfin processors are supported by cpufreq:
|
||||
|
||||
BF522, BF523, BF524, BF525, BF526, BF527, Rev 0.1 or higher
|
||||
BF531, BF532, BF533, Rev 0.3 or higher
|
||||
BF534, BF536, BF537, Rev 0.2 or higher
|
||||
BF561, Rev 0.3 or higher
|
||||
BF542, BF544, BF547, BF548, BF549, Rev 0.1 or higher
|
||||
|
||||
|
||||
2. "Policy" / "Governor" ?
|
||||
==========================
|
||||
|
||||
Some CPU frequency scaling-capable processor switch between various
|
||||
frequencies and operating voltages "on the fly" without any kernel or
|
||||
user involvement. This guarantees very fast switching to a frequency
|
||||
which is high enough to serve the user's needs, but low enough to save
|
||||
power.
|
||||
|
||||
|
||||
2.1 Policy
|
||||
----------
|
||||
|
||||
On these systems, all you can do is select the lower and upper
|
||||
frequency limit as well as whether you want more aggressive
|
||||
power-saving or more instantly available processing power.
|
||||
|
||||
|
||||
2.2 Governor
|
||||
------------
|
||||
|
||||
On all other cpufreq implementations, these boundaries still need to
|
||||
be set. Then, a "governor" must be selected. Such a "governor" decides
|
||||
what speed the processor shall run within the boundaries. One such
|
||||
"governor" is the "userspace" governor. This one allows the user - or
|
||||
a yet-to-implement userspace program - to decide what specific speed
|
||||
the processor shall run at.
|
||||
|
||||
|
||||
3. How to change the CPU cpufreq policy and/or speed
|
||||
====================================================
|
||||
|
||||
3.1 Preferred Interface: sysfs
|
||||
------------------------------
|
||||
|
||||
The preferred interface is located in the sysfs filesystem. If you
|
||||
mounted it at /sys, the cpufreq interface is located in a subdirectory
|
||||
"cpufreq" within the cpu-device directory
|
||||
(e.g. /sys/devices/system/cpu/cpu0/cpufreq/ for the first CPU).
|
||||
|
||||
affected_cpus : List of Online CPUs that require software
|
||||
coordination of frequency.
|
||||
|
||||
cpuinfo_cur_freq : Current frequency of the CPU as obtained from
|
||||
the hardware, in KHz. This is the frequency
|
||||
the CPU actually runs at.
|
||||
|
||||
cpuinfo_min_freq : this file shows the minimum operating
|
||||
frequency the processor can run at(in kHz)
|
||||
|
||||
cpuinfo_max_freq : this file shows the maximum operating
|
||||
frequency the processor can run at(in kHz)
|
||||
|
||||
cpuinfo_transition_latency The time it takes on this CPU to
|
||||
switch between two frequencies in nano
|
||||
seconds. If unknown or known to be
|
||||
that high that the driver does not
|
||||
work with the ondemand governor, -1
|
||||
(CPUFREQ_ETERNAL) will be returned.
|
||||
Using this information can be useful
|
||||
to choose an appropriate polling
|
||||
frequency for a kernel governor or
|
||||
userspace daemon. Make sure to not
|
||||
switch the frequency too often
|
||||
resulting in performance loss.
|
||||
|
||||
related_cpus : List of Online + Offline CPUs that need software
|
||||
coordination of frequency.
|
||||
|
||||
scaling_available_frequencies : List of available frequencies, in KHz.
|
||||
|
||||
scaling_available_governors : this file shows the CPUfreq governors
|
||||
available in this kernel. You can see the
|
||||
currently activated governor in
|
||||
|
||||
scaling_cur_freq : Current frequency of the CPU as determined by
|
||||
the governor and cpufreq core, in KHz. This is
|
||||
the frequency the kernel thinks the CPU runs
|
||||
at.
|
||||
|
||||
scaling_driver : this file shows what cpufreq driver is
|
||||
used to set the frequency on this CPU
|
||||
|
||||
scaling_governor, and by "echoing" the name of another
|
||||
governor you can change it. Please note
|
||||
that some governors won't load - they only
|
||||
work on some specific architectures or
|
||||
processors.
|
||||
|
||||
scaling_min_freq and
|
||||
scaling_max_freq show the current "policy limits" (in
|
||||
kHz). By echoing new values into these
|
||||
files, you can change these limits.
|
||||
NOTE: when setting a policy you need to
|
||||
first set scaling_max_freq, then
|
||||
scaling_min_freq.
|
||||
|
||||
scaling_setspeed This can be read to get the currently programmed
|
||||
value by the governor. This can be written to
|
||||
change the current frequency for a group of
|
||||
CPUs, represented by a policy. This is supported
|
||||
currently only by the userspace governor.
|
||||
|
||||
bios_limit : If the BIOS tells the OS to limit a CPU to
|
||||
lower frequencies, the user can read out the
|
||||
maximum available frequency from this file.
|
||||
This typically can happen through (often not
|
||||
intended) BIOS settings, restrictions
|
||||
triggered through a service processor or other
|
||||
BIOS/HW based implementations.
|
||||
This does not cover thermal ACPI limitations
|
||||
which can be detected through the generic
|
||||
thermal driver.
|
||||
|
||||
If you have selected the "userspace" governor which allows you to
|
||||
set the CPU operating frequency to a specific value, you can read out
|
||||
the current frequency in
|
||||
|
||||
scaling_setspeed. By "echoing" a new frequency into this
|
||||
you can change the speed of the CPU,
|
||||
but only within the limits of
|
||||
scaling_min_freq and scaling_max_freq.
|
|
@ -100,7 +100,7 @@ not defined by include/asm-XXX/topology.h:
|
|||
|
||||
For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
|
||||
default definitions for topology_book_id() and topology_book_cpumask().
|
||||
For architectures that don't support drawes (CONFIG_SCHED_DRAWER) there are
|
||||
For architectures that don't support drawers (CONFIG_SCHED_DRAWER) there are
|
||||
no default definitions for topology_drawer_id() and topology_drawer_cpumask().
|
||||
|
||||
Additionally, CPU topology information is provided under
|
||||
|
|
|
@ -100,8 +100,8 @@ Step-by-step instructions for using firescope with early OHCI initialization:
|
|||
CardBus and even some Express cards which are fully compliant to OHCI-1394
|
||||
specification are available. If it requires no driver for Windows operating
|
||||
systems, it most likely is. Only specialized shops have cards which are not
|
||||
compliant, they are based on TI PCILynx chips and require drivers for Win-
|
||||
dows operating systems.
|
||||
compliant, they are based on TI PCILynx chips and require drivers for Windows
|
||||
operating systems.
|
||||
|
||||
The mentioned kernel log message contains the string "physUB" if the
|
||||
controller implements a writable Physical Upper Bound register. This is
|
||||
|
|
|
@ -290,7 +290,7 @@ message, which takes an arbitrary number of cblock ranges. Each cblock
|
|||
range's end value is "one past the end", meaning 5-10 expresses a range
|
||||
of values from 5 to 9. Each cblock must be expressed as a decimal
|
||||
value, in the future a variant message that takes cblock ranges
|
||||
expressed in hexidecimal may be needed to better support efficient
|
||||
expressed in hexadecimal may be needed to better support efficient
|
||||
invalidation of larger caches. The cache must be in passthrough mode
|
||||
when invalidate_cblocks is used.
|
||||
|
||||
|
|
3
Documentation/doc-guide/hello.dot
Normal file
3
Documentation/doc-guide/hello.dot
Normal file
|
@ -0,0 +1,3 @@
|
|||
graph G {
|
||||
Hello -- World
|
||||
}
|
|
@ -34,8 +34,9 @@ format-specific subdirectories under ``Documentation/output``.
|
|||
|
||||
To generate documentation, Sphinx (``sphinx-build``) must obviously be
|
||||
installed. For prettier HTML output, the Read the Docs Sphinx theme
|
||||
(``sphinx_rtd_theme``) is used if available. For PDF output, ``rst2pdf`` is also
|
||||
needed. All of these are widely available and packaged in distributions.
|
||||
(``sphinx_rtd_theme``) is used if available. For PDF output you'll also need
|
||||
``XeLaTeX`` and ``convert(1)`` from ImageMagick (https://www.imagemagick.org).
|
||||
All of these are widely available and packaged in distributions.
|
||||
|
||||
To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
|
||||
variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
|
||||
|
@ -73,7 +74,16 @@ Specific guidelines for the kernel documentation
|
|||
|
||||
Here are some specific guidelines for the kernel documentation:
|
||||
|
||||
* Please don't go overboard with reStructuredText markup. Keep it simple.
|
||||
* Please don't go overboard with reStructuredText markup. Keep it
|
||||
simple. For the most part the documentation should be plain text with
|
||||
just enough consistency in formatting that it can be converted to
|
||||
other formats.
|
||||
|
||||
* Please keep the formatting changes minimal when converting existing
|
||||
documentation to reStructuredText.
|
||||
|
||||
* Also update the content, not just the formatting, when converting
|
||||
documentation.
|
||||
|
||||
* Please stick to this order of heading adornments:
|
||||
|
||||
|
@ -103,6 +113,12 @@ Here are some specific guidelines for the kernel documentation:
|
|||
the order as encountered."), having the higher levels the same overall makes
|
||||
it easier to follow the documents.
|
||||
|
||||
* For inserting fixed width text blocks (for code examples, use case
|
||||
examples, etc.), use ``::`` for anything that doesn't really benefit
|
||||
from syntax highlighting, especially short snippets. Use
|
||||
``.. code-block:: <language>`` for longer code blocks that benefit
|
||||
from highlighting.
|
||||
|
||||
|
||||
the C domain
|
||||
------------
|
||||
|
@ -217,3 +233,96 @@ Rendered as:
|
|||
* .. _`last row`:
|
||||
|
||||
- column 3
|
||||
|
||||
|
||||
Figures & Images
|
||||
================
|
||||
|
||||
If you want to add an image, you should use the ``kernel-figure`` and
|
||||
``kernel-image`` directives. E.g. to insert a figure with a scalable
|
||||
image format use SVG (:ref:`svg_image_example`)::
|
||||
|
||||
.. kernel-figure:: svg_image.svg
|
||||
:alt: simple SVG image
|
||||
|
||||
SVG image example
|
||||
|
||||
.. _svg_image_example:
|
||||
|
||||
.. kernel-figure:: svg_image.svg
|
||||
:alt: simple SVG image
|
||||
|
||||
SVG image example
|
||||
|
||||
The kernel figure (and image) directive support **DOT** formated files, see
|
||||
|
||||
* DOT: http://graphviz.org/pdf/dotguide.pdf
|
||||
* Graphviz: http://www.graphviz.org/content/dot-language
|
||||
|
||||
A simple example (:ref:`hello_dot_file`)::
|
||||
|
||||
.. kernel-figure:: hello.dot
|
||||
:alt: hello world
|
||||
|
||||
DOT's hello world example
|
||||
|
||||
.. _hello_dot_file:
|
||||
|
||||
.. kernel-figure:: hello.dot
|
||||
:alt: hello world
|
||||
|
||||
DOT's hello world example
|
||||
|
||||
Embed *render* markups (or languages) like Graphviz's **DOT** is provided by the
|
||||
``kernel-render`` directives.::
|
||||
|
||||
.. kernel-render:: DOT
|
||||
:alt: foobar digraph
|
||||
:caption: Embedded **DOT** (Graphviz) code
|
||||
|
||||
digraph foo {
|
||||
"bar" -> "baz";
|
||||
}
|
||||
|
||||
How this will be rendered depends on the installed tools. If Graphviz is
|
||||
installed, you will see an vector image. If not the raw markup is inserted as
|
||||
*literal-block* (:ref:`hello_dot_render`).
|
||||
|
||||
.. _hello_dot_render:
|
||||
|
||||
.. kernel-render:: DOT
|
||||
:alt: foobar digraph
|
||||
:caption: Embedded **DOT** (Graphviz) code
|
||||
|
||||
digraph foo {
|
||||
"bar" -> "baz";
|
||||
}
|
||||
|
||||
The *render* directive has all the options known from the *figure* directive,
|
||||
plus option ``caption``. If ``caption`` has a value, a *figure* node is
|
||||
inserted. If not, a *image* node is inserted. A ``caption`` is also needed, if
|
||||
you want to refer it (:ref:`hello_svg_render`).
|
||||
|
||||
Embedded **SVG**::
|
||||
|
||||
.. kernel-render:: SVG
|
||||
:caption: Embedded **SVG** markup
|
||||
:alt: so-nw-arrow
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" ...>
|
||||
...
|
||||
</svg>
|
||||
|
||||
.. _hello_svg_render:
|
||||
|
||||
.. kernel-render:: SVG
|
||||
:caption: Embedded **SVG** markup
|
||||
:alt: so-nw-arrow
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1" baseProfile="full" width="70px" height="40px" viewBox="0 0 700 400">
|
||||
<line x1="180" y1="370" x2="500" y2="50" stroke="black" stroke-width="15px"/>
|
||||
<polygon points="585 0 525 25 585 50" transform="rotate(135 525 25)"/>
|
||||
</svg>
|
||||
|
|
10
Documentation/doc-guide/svg_image.svg
Normal file
10
Documentation/doc-guide/svg_image.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- originate: https://commons.wikimedia.org/wiki/File:Variable_Resistor.svg -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1" baseProfile="full"
|
||||
width="70px" height="40px" viewBox="0 0 700 400">
|
||||
<line x1="0" y1="200" x2="700" y2="200" stroke="black" stroke-width="20px"/>
|
||||
<rect x="100" y="100" width="500" height="200" fill="white" stroke="black" stroke-width="20px"/>
|
||||
<line x1="180" y1="370" x2="500" y2="50" stroke="black" stroke-width="15px"/>
|
||||
<polygon points="585 0 525 25 585 50" transform="rotate(135 525 25)"/>
|
||||
</svg>
|
After Width: | Height: | Size: 580 B |
|
@ -7,6 +7,12 @@ Driver Entry and Exit points
|
|||
.. kernel-doc:: include/linux/init.h
|
||||
:internal:
|
||||
|
||||
Driver device table
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: include/linux/mod_devicetable.h
|
||||
:internal:
|
||||
|
||||
Atomic and pointer manipulation
|
||||
-------------------------------
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ Linux Firmware API
|
|||
introduction
|
||||
core
|
||||
request_firmware
|
||||
other_interfaces
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
|
15
Documentation/driver-api/firmware/other_interfaces.rst
Normal file
15
Documentation/driver-api/firmware/other_interfaces.rst
Normal file
|
@ -0,0 +1,15 @@
|
|||
Other Firmware Interfaces
|
||||
=========================
|
||||
|
||||
DMI Interfaces
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/firmware/dmi_scan.c
|
||||
:export:
|
||||
|
||||
EDD Interfaces
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/firmware/edd.c
|
||||
:internal:
|
||||
|
|
@ -26,7 +26,8 @@ available subsections can be seen below.
|
|||
regulator
|
||||
iio/index
|
||||
input
|
||||
usb
|
||||
usb/index
|
||||
pci
|
||||
spi
|
||||
i2c
|
||||
hsi
|
||||
|
@ -36,6 +37,7 @@ available subsections can be seen below.
|
|||
80211/index
|
||||
uio-howto
|
||||
firmware/index
|
||||
misc_devices
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
|
|
5
Documentation/driver-api/misc_devices.rst
Normal file
5
Documentation/driver-api/misc_devices.rst
Normal file
|
@ -0,0 +1,5 @@
|
|||
Miscellaneous Devices
|
||||
=====================
|
||||
|
||||
.. kernel-doc:: drivers/char/misc.c
|
||||
:export:
|
50
Documentation/driver-api/pci.rst
Normal file
50
Documentation/driver-api/pci.rst
Normal file
|
@ -0,0 +1,50 @@
|
|||
PCI Support Library
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: drivers/pci/pci.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/pci-driver.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/remove.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/search.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/msi.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/bus.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/access.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/irq.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/htirq.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/probe.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/slot.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/rom.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/iov.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/pci/pci-sysfs.c
|
||||
:internal:
|
||||
|
||||
PCI Hotplug Support Library
|
||||
---------------------------
|
||||
|
||||
.. kernel-doc:: drivers/pci/hotplug/pci_hotplug_core.c
|
||||
:export:
|
|
@ -1,28 +1,37 @@
|
|||
Revised: 2000-Dec-05.
|
||||
Again: 2002-Jul-06
|
||||
Again: 2005-Sep-19
|
||||
.. _usb-urb:
|
||||
|
||||
NOTE:
|
||||
USB Request Block (URB)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The USB subsystem now has a substantial section in "The Linux Kernel API"
|
||||
guide (in Documentation/DocBook), generated from the current source
|
||||
code. This particular documentation file isn't particularly current or
|
||||
complete; don't rely on it except for a quick overview.
|
||||
:Revised: 2000-Dec-05
|
||||
:Again: 2002-Jul-06
|
||||
:Again: 2005-Sep-19
|
||||
:Again: 2017-Mar-29
|
||||
|
||||
|
||||
1.1. Basic concept or 'What is an URB?'
|
||||
.. note::
|
||||
|
||||
The basic idea of the new driver is message passing, the message itself is
|
||||
called USB Request Block, or URB for short.
|
||||
The USB subsystem now has a substantial section at :ref:`usb-hostside-api`
|
||||
section, generated from the current source code.
|
||||
This particular documentation file isn't complete and may not be
|
||||
updated to the last version; don't rely on it except for a quick
|
||||
overview.
|
||||
|
||||
- An URB consists of all relevant information to execute any USB transaction
|
||||
and deliver the data and status back.
|
||||
Basic concept or 'What is an URB?'
|
||||
==================================
|
||||
|
||||
- Execution of an URB is inherently an asynchronous operation, i.e. the
|
||||
usb_submit_urb(urb) call returns immediately after it has successfully
|
||||
The basic idea of the new driver is message passing, the message itself is
|
||||
called USB Request Block, or URB for short.
|
||||
|
||||
- An URB consists of all relevant information to execute any USB transaction
|
||||
and deliver the data and status back.
|
||||
|
||||
- Execution of an URB is inherently an asynchronous operation, i.e. the
|
||||
:c:func:`usb_submit_urb` call returns immediately after it has successfully
|
||||
queued the requested action.
|
||||
|
||||
- Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time.
|
||||
- Transfers for one URB can be canceled with :c:func:`usb_unlink_urb`
|
||||
at any time.
|
||||
|
||||
- Each URB has a completion handler, which is called after the action
|
||||
has been successfully completed or canceled. The URB also contains a
|
||||
|
@ -35,53 +44,55 @@ called USB Request Block, or URB for short.
|
|||
of data to (or from) devices when using periodic transfer modes.
|
||||
|
||||
|
||||
1.2. The URB structure
|
||||
The URB structure
|
||||
=================
|
||||
|
||||
Some of the fields in an URB are:
|
||||
Some of the fields in struct :c:type:`urb` are::
|
||||
|
||||
struct urb
|
||||
{
|
||||
// (IN) device and pipe specify the endpoint queue
|
||||
struct urb
|
||||
{
|
||||
// (IN) device and pipe specify the endpoint queue
|
||||
struct usb_device *dev; // pointer to associated USB device
|
||||
unsigned int pipe; // endpoint information
|
||||
|
||||
unsigned int transfer_flags; // ISO_ASAP, SHORT_NOT_OK, etc.
|
||||
unsigned int transfer_flags; // URB_ISO_ASAP, URB_SHORT_NOT_OK, etc.
|
||||
|
||||
// (IN) all urbs need completion routines
|
||||
// (IN) all urbs need completion routines
|
||||
void *context; // context for completion routine
|
||||
void (*complete)(struct urb *); // pointer to completion routine
|
||||
usb_complete_t complete; // pointer to completion routine
|
||||
|
||||
// (OUT) status after each completion
|
||||
// (OUT) status after each completion
|
||||
int status; // returned status
|
||||
|
||||
// (IN) buffer used for data transfers
|
||||
// (IN) buffer used for data transfers
|
||||
void *transfer_buffer; // associated data buffer
|
||||
int transfer_buffer_length; // data buffer length
|
||||
u32 transfer_buffer_length; // data buffer length
|
||||
int number_of_packets; // size of iso_frame_desc
|
||||
|
||||
// (OUT) sometimes only part of CTRL/BULK/INTR transfer_buffer is used
|
||||
int actual_length; // actual data buffer length
|
||||
// (OUT) sometimes only part of CTRL/BULK/INTR transfer_buffer is used
|
||||
u32 actual_length; // actual data buffer length
|
||||
|
||||
// (IN) setup stage for CTRL (pass a struct usb_ctrlrequest)
|
||||
unsigned char* setup_packet; // setup packet (control only)
|
||||
// (IN) setup stage for CTRL (pass a struct usb_ctrlrequest)
|
||||
unsigned char *setup_packet; // setup packet (control only)
|
||||
|
||||
// Only for PERIODIC transfers (ISO, INTERRUPT)
|
||||
// (IN/OUT) start_frame is set unless ISO_ASAP isn't set
|
||||
// Only for PERIODIC transfers (ISO, INTERRUPT)
|
||||
// (IN/OUT) start_frame is set unless URB_ISO_ASAP isn't set
|
||||
int start_frame; // start frame
|
||||
int interval; // polling interval
|
||||
|
||||
// ISO only: packets are only "best effort"; each can have errors
|
||||
int error_count; // number of errors
|
||||
struct usb_iso_packet_descriptor iso_frame_desc[0];
|
||||
};
|
||||
};
|
||||
|
||||
Your driver must create the "pipe" value using values from the appropriate
|
||||
endpoint descriptor in an interface that it's claimed.
|
||||
|
||||
|
||||
1.3. How to get an URB?
|
||||
How to get an URB?
|
||||
==================
|
||||
|
||||
URBs are allocated with the following call
|
||||
URBs are allocated by calling :c:func:`usb_alloc_urb`::
|
||||
|
||||
struct urb *usb_alloc_urb(int isoframes, int mem_flags)
|
||||
|
||||
|
@ -91,7 +102,7 @@ you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags parameter
|
|||
holds standard memory allocation flags, letting you control (among other
|
||||
things) whether the underlying code may block or not.
|
||||
|
||||
To free an URB, use
|
||||
To free an URB, use :c:func:`usb_free_urb`::
|
||||
|
||||
void usb_free_urb(struct urb *urb)
|
||||
|
||||
|
@ -100,78 +111,84 @@ returned to you in a completion callback. It will automatically be
|
|||
deallocated when it is no longer in use.
|
||||
|
||||
|
||||
1.4. What has to be filled in?
|
||||
What has to be filled in?
|
||||
=========================
|
||||
|
||||
Depending on the type of transaction, there are some inline functions
|
||||
defined in <linux/usb.h> to simplify the initialization, such as
|
||||
fill_control_urb() and fill_bulk_urb(). In general, they need the usb
|
||||
device pointer, the pipe (usual format from usb.h), the transfer buffer,
|
||||
the desired transfer length, the completion handler, and its context.
|
||||
Take a look at the some existing drivers to see how they're used.
|
||||
Depending on the type of transaction, there are some inline functions
|
||||
defined in ``linux/usb.h`` to simplify the initialization, such as
|
||||
:c:func:`usb_fill_control_urb`, :c:func:`usb_fill_bulk_urb` and
|
||||
:c:func:`usb_fill_int_urb`. In general, they need the usb device pointer,
|
||||
the pipe (usual format from usb.h), the transfer buffer, the desired transfer
|
||||
length, the completion handler, and its context. Take a look at the some
|
||||
existing drivers to see how they're used.
|
||||
|
||||
Flags:
|
||||
For ISO there are two startup behaviors: Specified start_frame or ASAP.
|
||||
For ASAP set URB_ISO_ASAP in transfer_flags.
|
||||
|
||||
If short packets should NOT be tolerated, set URB_SHORT_NOT_OK in
|
||||
- For ISO there are two startup behaviors: Specified start_frame or ASAP.
|
||||
- For ASAP set ``URB_ISO_ASAP`` in transfer_flags.
|
||||
|
||||
If short packets should NOT be tolerated, set ``URB_SHORT_NOT_OK`` in
|
||||
transfer_flags.
|
||||
|
||||
|
||||
1.5. How to submit an URB?
|
||||
How to submit an URB?
|
||||
=====================
|
||||
|
||||
Just call
|
||||
Just call :c:func:`usb_submit_urb`::
|
||||
|
||||
int usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
|
||||
The mem_flags parameter, such as SLAB_ATOMIC, controls memory allocation,
|
||||
such as whether the lower levels may block when memory is tight.
|
||||
The ``mem_flags`` parameter, such as ``GFP_ATOMIC``, controls memory
|
||||
allocation, such as whether the lower levels may block when memory is tight.
|
||||
|
||||
It immediately returns, either with status 0 (request queued) or some
|
||||
error code, usually caused by the following:
|
||||
|
||||
- Out of memory (-ENOMEM)
|
||||
- Unplugged device (-ENODEV)
|
||||
- Stalled endpoint (-EPIPE)
|
||||
- Too many queued ISO transfers (-EAGAIN)
|
||||
- Too many requested ISO frames (-EFBIG)
|
||||
- Invalid INT interval (-EINVAL)
|
||||
- More than one packet for INT (-EINVAL)
|
||||
- Out of memory (``-ENOMEM``)
|
||||
- Unplugged device (``-ENODEV``)
|
||||
- Stalled endpoint (``-EPIPE``)
|
||||
- Too many queued ISO transfers (``-EAGAIN``)
|
||||
- Too many requested ISO frames (``-EFBIG``)
|
||||
- Invalid INT interval (``-EINVAL``)
|
||||
- More than one packet for INT (``-EINVAL``)
|
||||
|
||||
After submission, urb->status is -EINPROGRESS; however, you should never
|
||||
look at that value except in your completion callback.
|
||||
After submission, ``urb->status`` is ``-EINPROGRESS``; however, you should
|
||||
never look at that value except in your completion callback.
|
||||
|
||||
For isochronous endpoints, your completion handlers should (re)submit
|
||||
URBs to the same endpoint with the ISO_ASAP flag, using multi-buffering,
|
||||
to get seamless ISO streaming.
|
||||
URBs to the same endpoint with the ``URB_ISO_ASAP`` flag, using
|
||||
multi-buffering, to get seamless ISO streaming.
|
||||
|
||||
|
||||
1.6. How to cancel an already running URB?
|
||||
How to cancel an already running URB?
|
||||
=====================================
|
||||
|
||||
There are two ways to cancel an URB you've submitted but which hasn't
|
||||
been returned to your driver yet. For an asynchronous cancel, call
|
||||
:c:func:`usb_unlink_urb`::
|
||||
|
||||
int usb_unlink_urb(struct urb *urb)
|
||||
|
||||
It removes the urb from the internal list and frees all allocated
|
||||
HW descriptors. The status is changed to reflect unlinking. Note
|
||||
that the URB will not normally have finished when usb_unlink_urb()
|
||||
that the URB will not normally have finished when :c:func:`usb_unlink_urb`
|
||||
returns; you must still wait for the completion handler to be called.
|
||||
|
||||
To cancel an URB synchronously, call
|
||||
To cancel an URB synchronously, call :c:func:`usb_kill_urb`::
|
||||
|
||||
void usb_kill_urb(struct urb *urb)
|
||||
|
||||
It does everything usb_unlink_urb does, and in addition it waits
|
||||
It does everything :c:func:`usb_unlink_urb` does, and in addition it waits
|
||||
until after the URB has been returned and the completion handler
|
||||
has finished. It also marks the URB as temporarily unusable, so
|
||||
that if the completion handler or anyone else tries to resubmit it
|
||||
they will get a -EPERM error. Thus you can be sure that when
|
||||
usb_kill_urb() returns, the URB is totally idle.
|
||||
they will get a ``-EPERM`` error. Thus you can be sure that when
|
||||
:c:func:`usb_kill_urb` returns, the URB is totally idle.
|
||||
|
||||
There is a lifetime issue to consider. An URB may complete at any
|
||||
time, and the completion handler may free the URB. If this happens
|
||||
while usb_unlink_urb or usb_kill_urb is running, it will cause a
|
||||
memory-access violation. The driver is responsible for avoiding this,
|
||||
while :c:func:`usb_unlink_urb` or :c:func:`usb_kill_urb` is running, it will
|
||||
cause a memory-access violation. The driver is responsible for avoiding this,
|
||||
which often means some sort of lock will be needed to prevent the URB
|
||||
from being deallocated while it is still in use.
|
||||
|
||||
|
@ -181,24 +198,25 @@ when usb_unlink_urb is invoked. The general solution to this problem
|
|||
is to increment the URB's reference count while holding the lock, then
|
||||
drop the lock and call usb_unlink_urb or usb_kill_urb, and then
|
||||
decrement the URB's reference count. You increment the reference
|
||||
count by calling
|
||||
count by calling :c:func`usb_get_urb`::
|
||||
|
||||
struct urb *usb_get_urb(struct urb *urb)
|
||||
|
||||
(ignore the return value; it is the same as the argument) and
|
||||
decrement the reference count by calling usb_free_urb. Of course,
|
||||
decrement the reference count by calling :c:func:`usb_free_urb`. Of course,
|
||||
none of this is necessary if there's no danger of the URB being freed
|
||||
by the completion handler.
|
||||
|
||||
|
||||
1.7. What about the completion handler?
|
||||
What about the completion handler?
|
||||
==================================
|
||||
|
||||
The handler is of the following type:
|
||||
The handler is of the following type::
|
||||
|
||||
typedef void (*usb_complete_t)(struct urb *)
|
||||
|
||||
I.e., it gets the URB that caused the completion call. In the completion
|
||||
handler, you should have a look at urb->status to detect any USB errors.
|
||||
handler, you should have a look at ``urb->status`` to detect any USB errors.
|
||||
Since the context parameter is included in the URB, you can pass
|
||||
information to the completion handler.
|
||||
|
||||
|
@ -208,54 +226,65 @@ sixteen packets to transfer your 1KByte buffer, and ten of them might
|
|||
have transferred successfully before the completion was called.
|
||||
|
||||
|
||||
NOTE: ***** WARNING *****
|
||||
NEVER SLEEP IN A COMPLETION HANDLER. These are often called in atomic
|
||||
context.
|
||||
.. warning::
|
||||
|
||||
NEVER SLEEP IN A COMPLETION HANDLER.
|
||||
|
||||
These are often called in atomic context.
|
||||
|
||||
In the current kernel, completion handlers run with local interrupts
|
||||
disabled, but in the future this will be changed, so don't assume that
|
||||
local IRQs are always disabled inside completion handlers.
|
||||
|
||||
1.8. How to do isochronous (ISO) transfers?
|
||||
How to do isochronous (ISO) transfers?
|
||||
======================================
|
||||
|
||||
For ISO transfers you have to fill a usb_iso_packet_descriptor structure,
|
||||
allocated at the end of the URB by usb_alloc_urb(n,mem_flags), for each
|
||||
packet you want to schedule. You also have to set urb->interval to say
|
||||
how often to make transfers; it's often one per frame (which is once
|
||||
every microframe for highspeed devices). The actual interval used will
|
||||
be a power of two that's no bigger than what you specify.
|
||||
Besides the fields present on a bulk transfer, for ISO, you also
|
||||
also have to set ``urb->interval`` to say how often to make transfers; it's
|
||||
often one per frame (which is once every microframe for highspeed devices).
|
||||
The actual interval used will be a power of two that's no bigger than what
|
||||
you specify. You can use the :c:func:`usb_fill_int_urb` macro to fill
|
||||
most ISO transfer fields.
|
||||
|
||||
The usb_submit_urb() call modifies urb->interval to the implemented interval
|
||||
value that is less than or equal to the requested interval value. If
|
||||
ISO_ASAP scheduling is used, urb->start_frame is also updated.
|
||||
For ISO transfers you also have to fill a :c:type:`usb_iso_packet_descriptor`
|
||||
structure, allocated at the end of the URB by :c:func:`usb_alloc_urb`, for
|
||||
each packet you want to schedule.
|
||||
|
||||
The :c:func:`usb_submit_urb` call modifies ``urb->interval`` to the implemented
|
||||
interval value that is less than or equal to the requested interval value. If
|
||||
``URB_ISO_ASAP`` scheduling is used, ``urb->start_frame`` is also updated.
|
||||
|
||||
For each entry you have to specify the data offset for this frame (base is
|
||||
transfer_buffer), and the length you want to write/expect to read.
|
||||
After completion, actual_length contains the actual transferred length and
|
||||
After completion, actual_length contains the actual transferred length and
|
||||
status contains the resulting status for the ISO transfer for this frame.
|
||||
It is allowed to specify a varying length from frame to frame (e.g. for
|
||||
audio synchronisation/adaptive transfer rates). You can also use the length
|
||||
audio synchronisation/adaptive transfer rates). You can also use the length
|
||||
0 to omit one or more frames (striping).
|
||||
|
||||
For scheduling you can choose your own start frame or ISO_ASAP. As explained
|
||||
earlier, if you always keep at least one URB queued and your completion
|
||||
keeps (re)submitting a later URB, you'll get smooth ISO streaming (if usb
|
||||
bandwidth utilization allows).
|
||||
For scheduling you can choose your own start frame or ``URB_ISO_ASAP``. As
|
||||
explained earlier, if you always keep at least one URB queued and your
|
||||
completion keeps (re)submitting a later URB, you'll get smooth ISO streaming
|
||||
(if usb bandwidth utilization allows).
|
||||
|
||||
If you specify your own start frame, make sure it's several frames in advance
|
||||
of the current frame. You might want this model if you're synchronizing
|
||||
ISO data with some other event stream.
|
||||
|
||||
|
||||
1.9. How to start interrupt (INT) transfers?
|
||||
How to start interrupt (INT) transfers?
|
||||
=======================================
|
||||
|
||||
Interrupt transfers, like isochronous transfers, are periodic, and happen
|
||||
in intervals that are powers of two (1, 2, 4 etc) units. Units are frames
|
||||
for full and low speed devices, and microframes for high speed ones.
|
||||
The usb_submit_urb() call modifies urb->interval to the implemented interval
|
||||
value that is less than or equal to the requested interval value.
|
||||
You can use the :c:func:`usb_fill_int_urb` macro to fill INT transfer fields.
|
||||
|
||||
The :c:func:`usb_submit_urb` call modifies ``urb->interval`` to the implemented
|
||||
interval value that is less than or equal to the requested interval value.
|
||||
|
||||
In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically
|
||||
restarted when they complete. They end when the completion handler is
|
||||
called, just like other URBs. If you want an interrupt URB to be restarted,
|
||||
your completion handler must resubmit it.
|
||||
s
|
|
@ -1,3 +1,6 @@
|
|||
USB Anchors
|
||||
~~~~~~~~~~~
|
||||
|
||||
What is anchor?
|
||||
===============
|
||||
|
||||
|
@ -13,7 +16,7 @@ Allocation and Initialisation
|
|||
=============================
|
||||
|
||||
There's no API to allocate an anchor. It is simply declared
|
||||
as struct usb_anchor. init_usb_anchor() must be called to
|
||||
as struct usb_anchor. :c:func:`init_usb_anchor` must be called to
|
||||
initialise the data structure.
|
||||
|
||||
Deallocation
|
||||
|
@ -26,52 +29,53 @@ Association and disassociation of URBs with anchors
|
|||
===================================================
|
||||
|
||||
An association of URBs to an anchor is made by an explicit
|
||||
call to usb_anchor_urb(). The association is maintained until
|
||||
call to :c:func:`usb_anchor_urb`. The association is maintained until
|
||||
an URB is finished by (successful) completion. Thus disassociation
|
||||
is automatic. A function is provided to forcibly finish (kill)
|
||||
all URBs associated with an anchor.
|
||||
Furthermore, disassociation can be made with usb_unanchor_urb()
|
||||
Furthermore, disassociation can be made with :c:func:`usb_unanchor_urb`
|
||||
|
||||
Operations on multitudes of URBs
|
||||
================================
|
||||
|
||||
usb_kill_anchored_urbs()
|
||||
------------------------
|
||||
:c:func:`usb_kill_anchored_urbs`
|
||||
--------------------------------
|
||||
|
||||
This function kills all URBs associated with an anchor. The URBs
|
||||
are called in the reverse temporal order they were submitted.
|
||||
This way no data can be reordered.
|
||||
|
||||
usb_unlink_anchored_urbs()
|
||||
--------------------------
|
||||
:c:func:`usb_unlink_anchored_urbs`
|
||||
----------------------------------
|
||||
|
||||
|
||||
This function unlinks all URBs associated with an anchor. The URBs
|
||||
are processed in the reverse temporal order they were submitted.
|
||||
This is similar to usb_kill_anchored_urbs(), but it will not sleep.
|
||||
This is similar to :c:func:`usb_kill_anchored_urbs`, but it will not sleep.
|
||||
Therefore no guarantee is made that the URBs have been unlinked when
|
||||
the call returns. They may be unlinked later but will be unlinked in
|
||||
finite time.
|
||||
|
||||
usb_scuttle_anchored_urbs()
|
||||
---------------------------
|
||||
:c:func:`usb_scuttle_anchored_urbs`
|
||||
-----------------------------------
|
||||
|
||||
All URBs of an anchor are unanchored en masse.
|
||||
|
||||
usb_wait_anchor_empty_timeout()
|
||||
-------------------------------
|
||||
:c:func:`usb_wait_anchor_empty_timeout`
|
||||
---------------------------------------
|
||||
|
||||
This function waits for all URBs associated with an anchor to finish
|
||||
or a timeout, whichever comes first. Its return value will tell you
|
||||
whether the timeout was reached.
|
||||
|
||||
usb_anchor_empty()
|
||||
------------------
|
||||
:c:func:`usb_anchor_empty`
|
||||
--------------------------
|
||||
|
||||
Returns true if no URBs are associated with an anchor. Locking
|
||||
is the caller's responsibility.
|
||||
|
||||
usb_get_from_anchor()
|
||||
---------------------
|
||||
:c:func:`usb_get_from_anchor`
|
||||
-----------------------------
|
||||
|
||||
Returns the oldest anchored URB of an anchor. The URB is unanchored
|
||||
and returned with a reference. As you may mix URBs to several
|
|
@ -1,3 +1,6 @@
|
|||
USB bulk streams
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
|
@ -25,7 +28,9 @@ time.
|
|||
Driver implications
|
||||
===================
|
||||
|
||||
int usb_alloc_streams(struct usb_interface *interface,
|
||||
::
|
||||
|
||||
int usb_alloc_streams(struct usb_interface *interface,
|
||||
struct usb_host_endpoint **eps, unsigned int num_eps,
|
||||
unsigned int num_streams, gfp_t mem_flags);
|
||||
|
||||
|
@ -53,7 +58,7 @@ controller driver, and may change in the future.
|
|||
|
||||
|
||||
Picking new Stream IDs to use
|
||||
============================
|
||||
=============================
|
||||
|
||||
Stream ID 0 is reserved, and should not be used to communicate with devices. If
|
||||
usb_alloc_streams() returns with a value of N, you may use streams 1 though N.
|
||||
|
@ -68,9 +73,9 @@ Clean up
|
|||
========
|
||||
|
||||
If a driver wishes to stop using streams to communicate with the device, it
|
||||
should call
|
||||
should call::
|
||||
|
||||
void usb_free_streams(struct usb_interface *interface,
|
||||
void usb_free_streams(struct usb_interface *interface,
|
||||
struct usb_host_endpoint **eps, unsigned int num_eps,
|
||||
gfp_t mem_flags);
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
USB core callbacks
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
What callbacks will usbcore do?
|
||||
===============================
|
||||
|
||||
|
@ -5,40 +8,52 @@ Usbcore will call into a driver through callbacks defined in the driver
|
|||
structure and through the completion handler of URBs a driver submits.
|
||||
Only the former are in the scope of this document. These two kinds of
|
||||
callbacks are completely independent of each other. Information on the
|
||||
completion callback can be found in Documentation/usb/URB.txt.
|
||||
completion callback can be found in :ref:`usb-urb`.
|
||||
|
||||
The callbacks defined in the driver structure are:
|
||||
|
||||
1. Hotplugging callbacks:
|
||||
|
||||
* @probe: Called to see if the driver is willing to manage a particular
|
||||
* interface on a device.
|
||||
* @disconnect: Called when the interface is no longer accessible, usually
|
||||
* because its device has been (or is being) disconnected or the
|
||||
* driver module is being unloaded.
|
||||
- @probe:
|
||||
Called to see if the driver is willing to manage a particular
|
||||
interface on a device.
|
||||
|
||||
- @disconnect:
|
||||
Called when the interface is no longer accessible, usually
|
||||
because its device has been (or is being) disconnected or the
|
||||
driver module is being unloaded.
|
||||
|
||||
2. Odd backdoor through usbfs:
|
||||
|
||||
* @ioctl: Used for drivers that want to talk to userspace through
|
||||
* the "usbfs" filesystem. This lets devices provide ways to
|
||||
* expose information to user space regardless of where they
|
||||
* do (or don't) show up otherwise in the filesystem.
|
||||
- @ioctl:
|
||||
Used for drivers that want to talk to userspace through
|
||||
the "usbfs" filesystem. This lets devices provide ways to
|
||||
expose information to user space regardless of where they
|
||||
do (or don't) show up otherwise in the filesystem.
|
||||
|
||||
3. Power management (PM) callbacks:
|
||||
|
||||
* @suspend: Called when the device is going to be suspended.
|
||||
* @resume: Called when the device is being resumed.
|
||||
* @reset_resume: Called when the suspended device has been reset instead
|
||||
* of being resumed.
|
||||
- @suspend:
|
||||
Called when the device is going to be suspended.
|
||||
|
||||
- @resume:
|
||||
Called when the device is being resumed.
|
||||
|
||||
- @reset_resume:
|
||||
Called when the suspended device has been reset instead
|
||||
of being resumed.
|
||||
|
||||
4. Device level operations:
|
||||
|
||||
* @pre_reset: Called when the device is about to be reset.
|
||||
* @post_reset: Called after the device has been reset
|
||||
- @pre_reset:
|
||||
Called when the device is about to be reset.
|
||||
|
||||
- @post_reset:
|
||||
Called after the device has been reset
|
||||
|
||||
The ioctl interface (2) should be used only if you have a very good
|
||||
reason. Sysfs is preferred these days. The PM callbacks are covered
|
||||
separately in Documentation/usb/power-management.txt.
|
||||
separately in :ref:`usb-power-management`.
|
||||
|
||||
Calling conventions
|
||||
===================
|
||||
|
@ -58,7 +73,9 @@ an interface. A driver's bond to an interface is exclusive.
|
|||
The probe() callback
|
||||
--------------------
|
||||
|
||||
int (*probe) (struct usb_interface *intf,
|
||||
::
|
||||
|
||||
int (*probe) (struct usb_interface *intf,
|
||||
const struct usb_device_id *id);
|
||||
|
||||
Accept or decline an interface. If you accept the device return 0,
|
||||
|
@ -75,7 +92,9 @@ initialisation that doesn't take too long is a good idea here.
|
|||
The disconnect() callback
|
||||
-------------------------
|
||||
|
||||
void (*disconnect) (struct usb_interface *intf);
|
||||
::
|
||||
|
||||
void (*disconnect) (struct usb_interface *intf);
|
||||
|
||||
This callback is a signal to break any connection with an interface.
|
||||
You are not allowed any IO to a device after returning from this
|
||||
|
@ -93,7 +112,9 @@ Device level callbacks
|
|||
pre_reset
|
||||
---------
|
||||
|
||||
int (*pre_reset)(struct usb_interface *intf);
|
||||
::
|
||||
|
||||
int (*pre_reset)(struct usb_interface *intf);
|
||||
|
||||
A driver or user space is triggering a reset on the device which
|
||||
contains the interface passed as an argument. Cease IO, wait for all
|
||||
|
@ -107,7 +128,9 @@ are in atomic context.
|
|||
post_reset
|
||||
----------
|
||||
|
||||
int (*post_reset)(struct usb_interface *intf);
|
||||
::
|
||||
|
||||
int (*post_reset)(struct usb_interface *intf);
|
||||
|
||||
The reset has completed. Restore any saved device state and begin
|
||||
using the device again.
|
|
@ -1,16 +1,19 @@
|
|||
USB DMA
|
||||
~~~~~~~
|
||||
|
||||
In Linux 2.5 kernels (and later), USB device drivers have additional control
|
||||
over how DMA may be used to perform I/O operations. The APIs are detailed
|
||||
in the kernel usb programming guide (kerneldoc, from the source code).
|
||||
|
||||
|
||||
API OVERVIEW
|
||||
API overview
|
||||
============
|
||||
|
||||
The big picture is that USB drivers can continue to ignore most DMA issues,
|
||||
though they still must provide DMA-ready buffers (see
|
||||
Documentation/DMA-API-HOWTO.txt). That's how they've worked through
|
||||
the 2.4 (and earlier) kernels.
|
||||
``Documentation/DMA-API-HOWTO.txt``). That's how they've worked through
|
||||
the 2.4 (and earlier) kernels, or they can now be DMA-aware.
|
||||
|
||||
OR: they can now be DMA-aware.
|
||||
DMA-aware usb drivers:
|
||||
|
||||
- New calls enable DMA-aware drivers, letting them allocate dma buffers and
|
||||
manage dma mappings for existing dma-ready buffers (see below).
|
||||
|
@ -20,15 +23,15 @@ OR: they can now be DMA-aware.
|
|||
drivers must not use it.)
|
||||
|
||||
- "usbcore" will map this DMA address, if a DMA-aware driver didn't do
|
||||
it first and set URB_NO_TRANSFER_DMA_MAP. HCDs
|
||||
it first and set ``URB_NO_TRANSFER_DMA_MAP``. HCDs
|
||||
don't manage dma mappings for URBs.
|
||||
|
||||
- There's a new "generic DMA API", parts of which are usable by USB device
|
||||
drivers. Never use dma_set_mask() on any USB interface or device; that
|
||||
would potentially break all devices sharing that bus.
|
||||
|
||||
|
||||
ELIMINATING COPIES
|
||||
Eliminating copies
|
||||
==================
|
||||
|
||||
It's good to avoid making CPUs copy data needlessly. The costs can add up,
|
||||
and effects like cache-trashing can impose subtle penalties.
|
||||
|
@ -41,7 +44,7 @@ and effects like cache-trashing can impose subtle penalties.
|
|||
For those specific cases, USB has primitives to allocate less expensive
|
||||
memory. They work like kmalloc and kfree versions that give you the right
|
||||
kind of addresses to store in urb->transfer_buffer and urb->transfer_dma.
|
||||
You'd also set URB_NO_TRANSFER_DMA_MAP in urb->transfer_flags:
|
||||
You'd also set ``URB_NO_TRANSFER_DMA_MAP`` in urb->transfer_flags::
|
||||
|
||||
void *usb_alloc_coherent (struct usb_device *dev, size_t size,
|
||||
int mem_flags, dma_addr_t *dma);
|
||||
|
@ -49,15 +52,15 @@ and effects like cache-trashing can impose subtle penalties.
|
|||
void usb_free_coherent (struct usb_device *dev, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
Most drivers should *NOT* be using these primitives; they don't need
|
||||
Most drivers should **NOT** be using these primitives; they don't need
|
||||
to use this type of memory ("dma-coherent"), and memory returned from
|
||||
kmalloc() will work just fine.
|
||||
:c:func:`kmalloc` will work just fine.
|
||||
|
||||
The memory buffer returned is "dma-coherent"; sometimes you might need to
|
||||
force a consistent memory access ordering by using memory barriers. It's
|
||||
not using a streaming DMA mapping, so it's good for small transfers on
|
||||
systems where the I/O would otherwise thrash an IOMMU mapping. (See
|
||||
Documentation/DMA-API-HOWTO.txt for definitions of "coherent" and
|
||||
``Documentation/DMA-API-HOWTO.txt`` for definitions of "coherent" and
|
||||
"streaming" DMA mappings.)
|
||||
|
||||
Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
|
||||
|
@ -75,15 +78,15 @@ and effects like cache-trashing can impose subtle penalties.
|
|||
way to expose these capabilities ... and in any case, HIGHMEM is mostly a
|
||||
design wart specific to x86_32. So your best bet is to ensure you never
|
||||
pass a highmem buffer into a USB driver. That's easy; it's the default
|
||||
behavior. Just don't override it; e.g. with NETIF_F_HIGHDMA.
|
||||
behavior. Just don't override it; e.g. with ``NETIF_F_HIGHDMA``.
|
||||
|
||||
This may force your callers to do some bounce buffering, copying from
|
||||
high memory to "normal" DMA memory. If you can come up with a good way
|
||||
to fix this issue (for x86_32 machines with over 1 GByte of memory),
|
||||
feel free to submit patches.
|
||||
|
||||
|
||||
WORKING WITH EXISTING BUFFERS
|
||||
Working with existing buffers
|
||||
=============================
|
||||
|
||||
Existing buffers aren't usable for DMA without first being mapped into the
|
||||
DMA address space of the device. However, most buffers passed to your
|
||||
|
@ -92,7 +95,7 @@ of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
|
|||
|
||||
- When you're using scatterlists, you can map everything at once. On some
|
||||
systems, this kicks in an IOMMU and turns the scatterlists into single
|
||||
DMA transactions:
|
||||
DMA transactions::
|
||||
|
||||
int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
|
||||
struct scatterlist *sg, int nents);
|
||||
|
@ -103,7 +106,7 @@ of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
|
|||
void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
|
||||
struct scatterlist *sg, int n_hw_ents);
|
||||
|
||||
It's probably easier to use the new usb_sg_*() calls, which do the DMA
|
||||
It's probably easier to use the new ``usb_sg_*()`` calls, which do the DMA
|
||||
mapping and apply other tweaks to make scatterlist i/o be fast.
|
||||
|
||||
- Some drivers may prefer to work with the model that they're mapping large
|
||||
|
@ -112,10 +115,10 @@ of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
|
|||
here, since it's cheaper to just synchronize the buffer than to unmap it
|
||||
each time an urb completes and then re-map it on during resubmission.
|
||||
|
||||
These calls all work with initialized urbs: urb->dev, urb->pipe,
|
||||
urb->transfer_buffer, and urb->transfer_buffer_length must all be
|
||||
valid when these calls are used (urb->setup_packet must be valid too
|
||||
if urb is a control request):
|
||||
These calls all work with initialized urbs: ``urb->dev``, ``urb->pipe``,
|
||||
``urb->transfer_buffer``, and ``urb->transfer_buffer_length`` must all be
|
||||
valid when these calls are used (``urb->setup_packet`` must be valid too
|
||||
if urb is a control request)::
|
||||
|
||||
struct urb *usb_buffer_map (struct urb *urb);
|
||||
|
||||
|
@ -123,9 +126,9 @@ of Documentation/DMA-API-HOWTO.txt, titled "What memory is DMA-able?")
|
|||
|
||||
void usb_buffer_unmap (struct urb *urb);
|
||||
|
||||
The calls manage urb->transfer_dma for you, and set URB_NO_TRANSFER_DMA_MAP
|
||||
so that usbcore won't map or unmap the buffer. They cannot be used for
|
||||
setup_packet buffers in control requests.
|
||||
The calls manage ``urb->transfer_dma`` for you, and set
|
||||
``URB_NO_TRANSFER_DMA_MAP`` so that usbcore won't map or unmap the buffer.
|
||||
They cannot be used for setup_packet buffers in control requests.
|
||||
|
||||
Note that several of those interfaces are currently commented out, since
|
||||
they don't have current users. See the source code. Other than the dmasync
|
207
Documentation/driver-api/usb/error-codes.rst
Normal file
207
Documentation/driver-api/usb/error-codes.rst
Normal file
|
@ -0,0 +1,207 @@
|
|||
.. _usb-error-codes:
|
||||
|
||||
USB Error codes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
:Revised: 2004-Oct-21
|
||||
|
||||
This is the documentation of (hopefully) all possible error codes (and
|
||||
their interpretation) that can be returned from usbcore.
|
||||
|
||||
Some of them are returned by the Host Controller Drivers (HCDs), which
|
||||
device drivers only see through usbcore. As a rule, all the HCDs should
|
||||
behave the same except for transfer speed dependent behaviors and the
|
||||
way certain faults are reported.
|
||||
|
||||
|
||||
Error codes returned by :c:func:`usb_submit_urb`
|
||||
================================================
|
||||
|
||||
Non-USB-specific:
|
||||
|
||||
|
||||
=============== ===============================================
|
||||
0 URB submission went fine
|
||||
|
||||
``-ENOMEM`` no memory for allocation of internal structures
|
||||
=============== ===============================================
|
||||
|
||||
USB-specific:
|
||||
|
||||
======================= =======================================================
|
||||
``-EBUSY`` The URB is already active.
|
||||
|
||||
``-ENODEV`` specified USB-device or bus doesn't exist
|
||||
|
||||
``-ENOENT`` specified interface or endpoint does not exist or
|
||||
is not enabled
|
||||
|
||||
``-ENXIO`` host controller driver does not support queuing of
|
||||
this type of urb. (treat as a host controller bug.)
|
||||
|
||||
``-EINVAL`` a) Invalid transfer type specified (or not supported)
|
||||
b) Invalid or unsupported periodic transfer interval
|
||||
c) ISO: attempted to change transfer interval
|
||||
d) ISO: ``number_of_packets`` is < 0
|
||||
e) various other cases
|
||||
|
||||
``-EXDEV`` ISO: ``URB_ISO_ASAP`` wasn't specified and all the
|
||||
frames the URB would be scheduled in have already
|
||||
expired.
|
||||
|
||||
``-EFBIG`` Host controller driver can't schedule that many ISO
|
||||
frames.
|
||||
|
||||
``-EPIPE`` The pipe type specified in the URB doesn't match the
|
||||
endpoint's actual type.
|
||||
|
||||
``-EMSGSIZE`` (a) endpoint maxpacket size is zero; it is not usable
|
||||
in the current interface altsetting.
|
||||
(b) ISO packet is larger than the endpoint maxpacket.
|
||||
(c) requested data transfer length is invalid: negative
|
||||
or too large for the host controller.
|
||||
|
||||
``-ENOSPC`` This request would overcommit the usb bandwidth reserved
|
||||
for periodic transfers (interrupt, isochronous).
|
||||
|
||||
``-ESHUTDOWN`` The device or host controller has been disabled due to
|
||||
some problem that could not be worked around.
|
||||
|
||||
``-EPERM`` Submission failed because ``urb->reject`` was set.
|
||||
|
||||
``-EHOSTUNREACH`` URB was rejected because the device is suspended.
|
||||
|
||||
``-ENOEXEC`` A control URB doesn't contain a Setup packet.
|
||||
======================= =======================================================
|
||||
|
||||
Error codes returned by ``in urb->status`` or in ``iso_frame_desc[n].status`` (for ISO)
|
||||
=======================================================================================
|
||||
|
||||
USB device drivers may only test urb status values in completion handlers.
|
||||
This is because otherwise there would be a race between HCDs updating
|
||||
these values on one CPU, and device drivers testing them on another CPU.
|
||||
|
||||
A transfer's actual_length may be positive even when an error has been
|
||||
reported. That's because transfers often involve several packets, so that
|
||||
one or more packets could finish before an error stops further endpoint I/O.
|
||||
|
||||
For isochronous URBs, the urb status value is non-zero only if the URB is
|
||||
unlinked, the device is removed, the host controller is disabled, or the total
|
||||
transferred length is less than the requested length and the
|
||||
``URB_SHORT_NOT_OK`` flag is set. Completion handlers for isochronous URBs
|
||||
should only see ``urb->status`` set to zero, ``-ENOENT``, ``-ECONNRESET``,
|
||||
``-ESHUTDOWN``, or ``-EREMOTEIO``. Individual frame descriptor status fields
|
||||
may report more status codes.
|
||||
|
||||
|
||||
=============================== ===============================================
|
||||
0 Transfer completed successfully
|
||||
|
||||
``-ENOENT`` URB was synchronously unlinked by
|
||||
:c:func:`usb_unlink_urb`
|
||||
|
||||
``-EINPROGRESS`` URB still pending, no results yet
|
||||
(That is, if drivers see this it's a bug.)
|
||||
|
||||
``-EPROTO`` [#f1]_, [#f2]_ a) bitstuff error
|
||||
b) no response packet received within the
|
||||
prescribed bus turn-around time
|
||||
c) unknown USB error
|
||||
|
||||
``-EILSEQ`` [#f1]_, [#f2]_ a) CRC mismatch
|
||||
b) no response packet received within the
|
||||
prescribed bus turn-around time
|
||||
c) unknown USB error
|
||||
|
||||
Note that often the controller hardware does
|
||||
not distinguish among cases a), b), and c), so
|
||||
a driver cannot tell whether there was a
|
||||
protocol error, a failure to respond (often
|
||||
caused by device disconnect), or some other
|
||||
fault.
|
||||
|
||||
``-ETIME`` [#f2]_ No response packet received within the
|
||||
prescribed bus turn-around time. This error
|
||||
may instead be reported as
|
||||
``-EPROTO`` or ``-EILSEQ``.
|
||||
|
||||
``-ETIMEDOUT`` Synchronous USB message functions use this code
|
||||
to indicate timeout expired before the transfer
|
||||
completed, and no other error was reported
|
||||
by HC.
|
||||
|
||||
``-EPIPE`` [#f2]_ Endpoint stalled. For non-control endpoints,
|
||||
reset this status with
|
||||
:c:func:`usb_clear_halt`.
|
||||
|
||||
``-ECOMM`` During an IN transfer, the host controller
|
||||
received data from an endpoint faster than it
|
||||
could be written to system memory
|
||||
|
||||
``-ENOSR`` During an OUT transfer, the host controller
|
||||
could not retrieve data from system memory fast
|
||||
enough to keep up with the USB data rate
|
||||
|
||||
``-EOVERFLOW`` [#f1]_ The amount of data returned by the endpoint was
|
||||
greater than either the max packet size of the
|
||||
endpoint or the remaining buffer size.
|
||||
"Babble".
|
||||
|
||||
``-EREMOTEIO`` The data read from the endpoint did not fill
|
||||
the specified buffer, and ``URB_SHORT_NOT_OK``
|
||||
was set in ``urb->transfer_flags``.
|
||||
|
||||
``-ENODEV`` Device was removed. Often preceded by a burst
|
||||
of other errors, since the hub driver doesn't
|
||||
detect device removal events immediately.
|
||||
|
||||
``-EXDEV`` ISO transfer only partially completed
|
||||
(only set in ``iso_frame_desc[n].status``,
|
||||
not ``urb->status``)
|
||||
|
||||
``-EINVAL`` ISO madness, if this happens: Log off and
|
||||
go home
|
||||
|
||||
``-ECONNRESET`` URB was asynchronously unlinked by
|
||||
:c:func:`usb_unlink_urb`
|
||||
|
||||
``-ESHUTDOWN`` The device or host controller has been
|
||||
disabled due to some problem that could not
|
||||
be worked around, such as a physical
|
||||
disconnect.
|
||||
=============================== ===============================================
|
||||
|
||||
|
||||
.. [#f1]
|
||||
|
||||
Error codes like ``-EPROTO``, ``-EILSEQ`` and ``-EOVERFLOW`` normally
|
||||
indicate hardware problems such as bad devices (including firmware)
|
||||
or cables.
|
||||
|
||||
.. [#f2]
|
||||
|
||||
This is also one of several codes that different kinds of host
|
||||
controller use to indicate a transfer has failed because of device
|
||||
disconnect. In the interval before the hub driver starts disconnect
|
||||
processing, devices may receive such fault reports for every request.
|
||||
|
||||
|
||||
|
||||
Error codes returned by usbcore-functions
|
||||
=========================================
|
||||
|
||||
.. note:: expect also other submit and transfer status codes
|
||||
|
||||
:c:func:`usb_register`:
|
||||
|
||||
======================= ===================================
|
||||
``-EINVAL`` error during registering new driver
|
||||
======================= ===================================
|
||||
|
||||
``usb_get_*/usb_set_*()``,
|
||||
:c:func:`usb_control_msg`,
|
||||
:c:func:`usb_bulk_msg()`:
|
||||
|
||||
======================= ==============================================
|
||||
``-ETIMEDOUT`` Timeout expired before the transfer completed.
|
||||
======================= ==============================================
|
510
Documentation/driver-api/usb/gadget.rst
Normal file
510
Documentation/driver-api/usb/gadget.rst
Normal file
|
@ -0,0 +1,510 @@
|
|||
========================
|
||||
USB Gadget API for Linux
|
||||
========================
|
||||
|
||||
:Author: David Brownell
|
||||
:Date: 20 August 2004
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document presents a Linux-USB "Gadget" kernel mode API, for use
|
||||
within peripherals and other USB devices that embed Linux. It provides
|
||||
an overview of the API structure, and shows how that fits into a system
|
||||
development project. This is the first such API released on Linux to
|
||||
address a number of important problems, including:
|
||||
|
||||
- Supports USB 2.0, for high speed devices which can stream data at
|
||||
several dozen megabytes per second.
|
||||
|
||||
- Handles devices with dozens of endpoints just as well as ones with
|
||||
just two fixed-function ones. Gadget drivers can be written so
|
||||
they're easy to port to new hardware.
|
||||
|
||||
- Flexible enough to expose more complex USB device capabilities such
|
||||
as multiple configurations, multiple interfaces, composite devices,
|
||||
and alternate interface settings.
|
||||
|
||||
- USB "On-The-Go" (OTG) support, in conjunction with updates to the
|
||||
Linux-USB host side.
|
||||
|
||||
- Sharing data structures and API models with the Linux-USB host side
|
||||
API. This helps the OTG support, and looks forward to more-symmetric
|
||||
frameworks (where the same I/O model is used by both host and device
|
||||
side drivers).
|
||||
|
||||
- Minimalist, so it's easier to support new device controller hardware.
|
||||
I/O processing doesn't imply large demands for memory or CPU
|
||||
resources.
|
||||
|
||||
Most Linux developers will not be able to use this API, since they have
|
||||
USB ``host`` hardware in a PC, workstation, or server. Linux users with
|
||||
embedded systems are more likely to have USB peripheral hardware. To
|
||||
distinguish drivers running inside such hardware from the more familiar
|
||||
Linux "USB device drivers", which are host side proxies for the real USB
|
||||
devices, a different term is used: the drivers inside the peripherals
|
||||
are "USB gadget drivers". In USB protocol interactions, the device
|
||||
driver is the master (or "client driver") and the gadget driver is the
|
||||
slave (or "function driver").
|
||||
|
||||
The gadget API resembles the host side Linux-USB API in that both use
|
||||
queues of request objects to package I/O buffers, and those requests may
|
||||
be submitted or canceled. They share common definitions for the standard
|
||||
USB *Chapter 9* messages, structures, and constants. Also, both APIs
|
||||
bind and unbind drivers to devices. The APIs differ in detail, since the
|
||||
host side's current URB framework exposes a number of implementation
|
||||
details and assumptions that are inappropriate for a gadget API. While
|
||||
the model for control transfers and configuration management is
|
||||
necessarily different (one side is a hardware-neutral master, the other
|
||||
is a hardware-aware slave), the endpoint I/0 API used here should also
|
||||
be usable for an overhead-reduced host side API.
|
||||
|
||||
Structure of Gadget Drivers
|
||||
===========================
|
||||
|
||||
A system running inside a USB peripheral normally has at least three
|
||||
layers inside the kernel to handle USB protocol processing, and may have
|
||||
additional layers in user space code. The ``gadget`` API is used by the
|
||||
middle layer to interact with the lowest level (which directly handles
|
||||
hardware).
|
||||
|
||||
In Linux, from the bottom up, these layers are:
|
||||
|
||||
*USB Controller Driver*
|
||||
This is the lowest software level. It is the only layer that talks
|
||||
to hardware, through registers, fifos, dma, irqs, and the like. The
|
||||
``<linux/usb/gadget.h>`` API abstracts the peripheral controller
|
||||
endpoint hardware. That hardware is exposed through endpoint
|
||||
objects, which accept streams of IN/OUT buffers, and through
|
||||
callbacks that interact with gadget drivers. Since normal USB
|
||||
devices only have one upstream port, they only have one of these
|
||||
drivers. The controller driver can support any number of different
|
||||
gadget drivers, but only one of them can be used at a time.
|
||||
|
||||
Examples of such controller hardware include the PCI-based NetChip
|
||||
2280 USB 2.0 high speed controller, the SA-11x0 or PXA-25x UDC
|
||||
(found within many PDAs), and a variety of other products.
|
||||
|
||||
*Gadget Driver*
|
||||
The lower boundary of this driver implements hardware-neutral USB
|
||||
functions, using calls to the controller driver. Because such
|
||||
hardware varies widely in capabilities and restrictions, and is used
|
||||
in embedded environments where space is at a premium, the gadget
|
||||
driver is often configured at compile time to work with endpoints
|
||||
supported by one particular controller. Gadget drivers may be
|
||||
portable to several different controllers, using conditional
|
||||
compilation. (Recent kernels substantially simplify the work
|
||||
involved in supporting new hardware, by *autoconfiguring* endpoints
|
||||
automatically for many bulk-oriented drivers.) Gadget driver
|
||||
responsibilities include:
|
||||
|
||||
- handling setup requests (ep0 protocol responses) possibly
|
||||
including class-specific functionality
|
||||
|
||||
- returning configuration and string descriptors
|
||||
|
||||
- (re)setting configurations and interface altsettings, including
|
||||
enabling and configuring endpoints
|
||||
|
||||
- handling life cycle events, such as managing bindings to
|
||||
hardware, USB suspend/resume, remote wakeup, and disconnection
|
||||
from the USB host.
|
||||
|
||||
- managing IN and OUT transfers on all currently enabled endpoints
|
||||
|
||||
Such drivers may be modules of proprietary code, although that
|
||||
approach is discouraged in the Linux community.
|
||||
|
||||
*Upper Level*
|
||||
Most gadget drivers have an upper boundary that connects to some
|
||||
Linux driver or framework in Linux. Through that boundary flows the
|
||||
data which the gadget driver produces and/or consumes through
|
||||
protocol transfers over USB. Examples include:
|
||||
|
||||
- user mode code, using generic (gadgetfs) or application specific
|
||||
files in ``/dev``
|
||||
|
||||
- networking subsystem (for network gadgets, like the CDC Ethernet
|
||||
Model gadget driver)
|
||||
|
||||
- data capture drivers, perhaps video4Linux or a scanner driver; or
|
||||
test and measurement hardware.
|
||||
|
||||
- input subsystem (for HID gadgets)
|
||||
|
||||
- sound subsystem (for audio gadgets)
|
||||
|
||||
- file system (for PTP gadgets)
|
||||
|
||||
- block i/o subsystem (for usb-storage gadgets)
|
||||
|
||||
- ... and more
|
||||
|
||||
*Additional Layers*
|
||||
Other layers may exist. These could include kernel layers, such as
|
||||
network protocol stacks, as well as user mode applications building
|
||||
on standard POSIX system call APIs such as ``open()``, ``close()``,
|
||||
``read()`` and ``write()``. On newer systems, POSIX Async I/O calls may
|
||||
be an option. Such user mode code will not necessarily be subject to
|
||||
the GNU General Public License (GPL).
|
||||
|
||||
OTG-capable systems will also need to include a standard Linux-USB host
|
||||
side stack, with ``usbcore``, one or more *Host Controller Drivers*
|
||||
(HCDs), *USB Device Drivers* to support the OTG "Targeted Peripheral
|
||||
List", and so forth. There will also be an *OTG Controller Driver*,
|
||||
which is visible to gadget and device driver developers only indirectly.
|
||||
That helps the host and device side USB controllers implement the two
|
||||
new OTG protocols (HNP and SRP). Roles switch (host to peripheral, or
|
||||
vice versa) using HNP during USB suspend processing, and SRP can be
|
||||
viewed as a more battery-friendly kind of device wakeup protocol.
|
||||
|
||||
Over time, reusable utilities are evolving to help make some gadget
|
||||
driver tasks simpler. For example, building configuration descriptors
|
||||
from vectors of descriptors for the configurations interfaces and
|
||||
endpoints is now automated, and many drivers now use autoconfiguration
|
||||
to choose hardware endpoints and initialize their descriptors. A
|
||||
potential example of particular interest is code implementing standard
|
||||
USB-IF protocols for HID, networking, storage, or audio classes. Some
|
||||
developers are interested in KDB or KGDB hooks, to let target hardware
|
||||
be remotely debugged. Most such USB protocol code doesn't need to be
|
||||
hardware-specific, any more than network protocols like X11, HTTP, or
|
||||
NFS are. Such gadget-side interface drivers should eventually be
|
||||
combined, to implement composite devices.
|
||||
|
||||
Kernel Mode Gadget API
|
||||
======================
|
||||
|
||||
Gadget drivers declare themselves through a struct
|
||||
:c:type:`usb_gadget_driver`, which is responsible for most parts of enumeration
|
||||
for a struct :c:type:`usb_gadget`. The response to a set_configuration usually
|
||||
involves enabling one or more of the struct :c:type:`usb_ep` objects exposed by
|
||||
the gadget, and submitting one or more struct :c:type:`usb_request` buffers to
|
||||
transfer data. Understand those four data types, and their operations,
|
||||
and you will understand how this API works.
|
||||
|
||||
.. Note::
|
||||
|
||||
Other than the "Chapter 9" data types, most of the significant data
|
||||
types and functions are described here.
|
||||
|
||||
However, some relevant information is likely omitted from what you
|
||||
are reading. One example of such information is endpoint
|
||||
autoconfiguration. You'll have to read the header file, and use
|
||||
example source code (such as that for "Gadget Zero"), to fully
|
||||
understand the API.
|
||||
|
||||
The part of the API implementing some basic driver capabilities is
|
||||
specific to the version of the Linux kernel that's in use. The 2.6
|
||||
and upper kernel versions include a *driver model* framework that has
|
||||
no analogue on earlier kernels; so those parts of the gadget API are
|
||||
not fully portable. (They are implemented on 2.4 kernels, but in a
|
||||
different way.) The driver model state is another part of this API that is
|
||||
ignored by the kerneldoc tools.
|
||||
|
||||
The core API does not expose every possible hardware feature, only the
|
||||
most widely available ones. There are significant hardware features,
|
||||
such as device-to-device DMA (without temporary storage in a memory
|
||||
buffer) that would be added using hardware-specific APIs.
|
||||
|
||||
This API allows drivers to use conditional compilation to handle
|
||||
endpoint capabilities of different hardware, but doesn't require that.
|
||||
Hardware tends to have arbitrary restrictions, relating to transfer
|
||||
types, addressing, packet sizes, buffering, and availability. As a rule,
|
||||
such differences only matter for "endpoint zero" logic that handles
|
||||
device configuration and management. The API supports limited run-time
|
||||
detection of capabilities, through naming conventions for endpoints.
|
||||
Many drivers will be able to at least partially autoconfigure
|
||||
themselves. In particular, driver init sections will often have endpoint
|
||||
autoconfiguration logic that scans the hardware's list of endpoints to
|
||||
find ones matching the driver requirements (relying on those
|
||||
conventions), to eliminate some of the most common reasons for
|
||||
conditional compilation.
|
||||
|
||||
Like the Linux-USB host side API, this API exposes the "chunky" nature
|
||||
of USB messages: I/O requests are in terms of one or more "packets", and
|
||||
packet boundaries are visible to drivers. Compared to RS-232 serial
|
||||
protocols, USB resembles synchronous protocols like HDLC (N bytes per
|
||||
frame, multipoint addressing, host as the primary station and devices as
|
||||
secondary stations) more than asynchronous ones (tty style: 8 data bits
|
||||
per frame, no parity, one stop bit). So for example the controller
|
||||
drivers won't buffer two single byte writes into a single two-byte USB
|
||||
IN packet, although gadget drivers may do so when they implement
|
||||
protocols where packet boundaries (and "short packets") are not
|
||||
significant.
|
||||
|
||||
Driver Life Cycle
|
||||
-----------------
|
||||
|
||||
Gadget drivers make endpoint I/O requests to hardware without needing to
|
||||
know many details of the hardware, but driver setup/configuration code
|
||||
needs to handle some differences. Use the API like this:
|
||||
|
||||
1. Register a driver for the particular device side usb controller
|
||||
hardware, such as the net2280 on PCI (USB 2.0), sa11x0 or pxa25x as
|
||||
found in Linux PDAs, and so on. At this point the device is logically
|
||||
in the USB ch9 initial state (``attached``), drawing no power and not
|
||||
usable (since it does not yet support enumeration). Any host should
|
||||
not see the device, since it's not activated the data line pullup
|
||||
used by the host to detect a device, even if VBUS power is available.
|
||||
|
||||
2. Register a gadget driver that implements some higher level device
|
||||
function. That will then bind() to a :c:type:`usb_gadget`, which activates
|
||||
the data line pullup sometime after detecting VBUS.
|
||||
|
||||
3. The hardware driver can now start enumerating. The steps it handles
|
||||
are to accept USB ``power`` and ``set_address`` requests. Other steps are
|
||||
handled by the gadget driver. If the gadget driver module is unloaded
|
||||
before the host starts to enumerate, steps before step 7 are skipped.
|
||||
|
||||
4. The gadget driver's ``setup()`` call returns usb descriptors, based both
|
||||
on what the bus interface hardware provides and on the functionality
|
||||
being implemented. That can involve alternate settings or
|
||||
configurations, unless the hardware prevents such operation. For OTG
|
||||
devices, each configuration descriptor includes an OTG descriptor.
|
||||
|
||||
5. The gadget driver handles the last step of enumeration, when the USB
|
||||
host issues a ``set_configuration`` call. It enables all endpoints used
|
||||
in that configuration, with all interfaces in their default settings.
|
||||
That involves using a list of the hardware's endpoints, enabling each
|
||||
endpoint according to its descriptor. It may also involve using
|
||||
``usb_gadget_vbus_draw`` to let more power be drawn from VBUS, as
|
||||
allowed by that configuration. For OTG devices, setting a
|
||||
configuration may also involve reporting HNP capabilities through a
|
||||
user interface.
|
||||
|
||||
6. Do real work and perform data transfers, possibly involving changes
|
||||
to interface settings or switching to new configurations, until the
|
||||
device is disconnect()ed from the host. Queue any number of transfer
|
||||
requests to each endpoint. It may be suspended and resumed several
|
||||
times before being disconnected. On disconnect, the drivers go back
|
||||
to step 3 (above).
|
||||
|
||||
7. When the gadget driver module is being unloaded, the driver unbind()
|
||||
callback is issued. That lets the controller driver be unloaded.
|
||||
|
||||
Drivers will normally be arranged so that just loading the gadget driver
|
||||
module (or statically linking it into a Linux kernel) allows the
|
||||
peripheral device to be enumerated, but some drivers will defer
|
||||
enumeration until some higher level component (like a user mode daemon)
|
||||
enables it. Note that at this lowest level there are no policies about
|
||||
how ep0 configuration logic is implemented, except that it should obey
|
||||
USB specifications. Such issues are in the domain of gadget drivers,
|
||||
including knowing about implementation constraints imposed by some USB
|
||||
controllers or understanding that composite devices might happen to be
|
||||
built by integrating reusable components.
|
||||
|
||||
Note that the lifecycle above can be slightly different for OTG devices.
|
||||
Other than providing an additional OTG descriptor in each configuration,
|
||||
only the HNP-related differences are particularly visible to driver
|
||||
code. They involve reporting requirements during the ``SET_CONFIGURATION``
|
||||
request, and the option to invoke HNP during some suspend callbacks.
|
||||
Also, SRP changes the semantics of ``usb_gadget_wakeup`` slightly.
|
||||
|
||||
USB 2.0 Chapter 9 Types and Constants
|
||||
-------------------------------------
|
||||
|
||||
Gadget drivers rely on common USB structures and constants defined in
|
||||
the :ref:`linux/usb/ch9.h <usb_chapter9>` header file, which is standard in
|
||||
Linux 2.6+ kernels. These are the same types and constants used by host side
|
||||
drivers (and usbcore).
|
||||
|
||||
Core Objects and Methods
|
||||
------------------------
|
||||
|
||||
These are declared in ``<linux/usb/gadget.h>``, and are used by gadget
|
||||
drivers to interact with USB peripheral controller drivers.
|
||||
|
||||
.. kernel-doc:: include/linux/usb/gadget.h
|
||||
:internal:
|
||||
|
||||
Optional Utilities
|
||||
------------------
|
||||
|
||||
The core API is sufficient for writing a USB Gadget Driver, but some
|
||||
optional utilities are provided to simplify common tasks. These
|
||||
utilities include endpoint autoconfiguration.
|
||||
|
||||
.. kernel-doc:: drivers/usb/gadget/usbstring.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/usb/gadget/config.c
|
||||
:export:
|
||||
|
||||
Composite Device Framework
|
||||
--------------------------
|
||||
|
||||
The core API is sufficient for writing drivers for composite USB devices
|
||||
(with more than one function in a given configuration), and also
|
||||
multi-configuration devices (also more than one function, but not
|
||||
necessarily sharing a given configuration). There is however an optional
|
||||
framework which makes it easier to reuse and combine functions.
|
||||
|
||||
Devices using this framework provide a struct :c:type:`usb_composite_driver`,
|
||||
which in turn provides one or more struct :c:type:`usb_configuration`
|
||||
instances. Each such configuration includes at least one struct
|
||||
:c:type:`usb_function`, which packages a user visible role such as "network
|
||||
link" or "mass storage device". Management functions may also exist,
|
||||
such as "Device Firmware Upgrade".
|
||||
|
||||
.. kernel-doc:: include/linux/usb/composite.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/usb/gadget/composite.c
|
||||
:export:
|
||||
|
||||
Composite Device Functions
|
||||
--------------------------
|
||||
|
||||
At this writing, a few of the current gadget drivers have been converted
|
||||
to this framework. Near-term plans include converting all of them,
|
||||
except for ``gadgetfs``.
|
||||
|
||||
Peripheral Controller Drivers
|
||||
=============================
|
||||
|
||||
The first hardware supporting this API was the NetChip 2280 controller,
|
||||
which supports USB 2.0 high speed and is based on PCI. This is the
|
||||
``net2280`` driver module. The driver supports Linux kernel versions 2.4
|
||||
and 2.6; contact NetChip Technologies for development boards and product
|
||||
information.
|
||||
|
||||
Other hardware working in the ``gadget`` framework includes: Intel's PXA
|
||||
25x and IXP42x series processors (``pxa2xx_udc``), Toshiba TC86c001
|
||||
"Goku-S" (``goku_udc``), Renesas SH7705/7727 (``sh_udc``), MediaQ 11xx
|
||||
(``mq11xx_udc``), Hynix HMS30C7202 (``h7202_udc``), National 9303/4
|
||||
(``n9604_udc``), Texas Instruments OMAP (``omap_udc``), Sharp LH7A40x
|
||||
(``lh7a40x_udc``), and more. Most of those are full speed controllers.
|
||||
|
||||
At this writing, there are people at work on drivers in this framework
|
||||
for several other USB device controllers, with plans to make many of
|
||||
them be widely available.
|
||||
|
||||
A partial USB simulator, the ``dummy_hcd`` driver, is available. It can
|
||||
act like a net2280, a pxa25x, or an sa11x0 in terms of available
|
||||
endpoints and device speeds; and it simulates control, bulk, and to some
|
||||
extent interrupt transfers. That lets you develop some parts of a gadget
|
||||
driver on a normal PC, without any special hardware, and perhaps with
|
||||
the assistance of tools such as GDB running with User Mode Linux. At
|
||||
least one person has expressed interest in adapting that approach,
|
||||
hooking it up to a simulator for a microcontroller. Such simulators can
|
||||
help debug subsystems where the runtime hardware is unfriendly to
|
||||
software development, or is not yet available.
|
||||
|
||||
Support for other controllers is expected to be developed and
|
||||
contributed over time, as this driver framework evolves.
|
||||
|
||||
Gadget Drivers
|
||||
==============
|
||||
|
||||
In addition to *Gadget Zero* (used primarily for testing and development
|
||||
with drivers for usb controller hardware), other gadget drivers exist.
|
||||
|
||||
There's an ``ethernet`` gadget driver, which implements one of the most
|
||||
useful *Communications Device Class* (CDC) models. One of the standards
|
||||
for cable modem interoperability even specifies the use of this ethernet
|
||||
model as one of two mandatory options. Gadgets using this code look to a
|
||||
USB host as if they're an Ethernet adapter. It provides access to a
|
||||
network where the gadget's CPU is one host, which could easily be
|
||||
bridging, routing, or firewalling access to other networks. Since some
|
||||
hardware can't fully implement the CDC Ethernet requirements, this
|
||||
driver also implements a "good parts only" subset of CDC Ethernet. (That
|
||||
subset doesn't advertise itself as CDC Ethernet, to avoid creating
|
||||
problems.)
|
||||
|
||||
Support for Microsoft's ``RNDIS`` protocol has been contributed by
|
||||
Pengutronix and Auerswald GmbH. This is like CDC Ethernet, but it runs
|
||||
on more slightly USB hardware (but less than the CDC subset). However,
|
||||
its main claim to fame is being able to connect directly to recent
|
||||
versions of Windows, using drivers that Microsoft bundles and supports,
|
||||
making it much simpler to network with Windows.
|
||||
|
||||
There is also support for user mode gadget drivers, using ``gadgetfs``.
|
||||
This provides a *User Mode API* that presents each endpoint as a single
|
||||
file descriptor. I/O is done using normal ``read()`` and ``read()`` calls.
|
||||
Familiar tools like GDB and pthreads can be used to develop and debug
|
||||
user mode drivers, so that once a robust controller driver is available
|
||||
many applications for it won't require new kernel mode software. Linux
|
||||
2.6 *Async I/O (AIO)* support is available, so that user mode software
|
||||
can stream data with only slightly more overhead than a kernel driver.
|
||||
|
||||
There's a USB Mass Storage class driver, which provides a different
|
||||
solution for interoperability with systems such as MS-Windows and MacOS.
|
||||
That *Mass Storage* driver uses a file or block device as backing store
|
||||
for a drive, like the ``loop`` driver. The USB host uses the BBB, CB, or
|
||||
CBI versions of the mass storage class specification, using transparent
|
||||
SCSI commands to access the data from the backing store.
|
||||
|
||||
There's a "serial line" driver, useful for TTY style operation over USB.
|
||||
The latest version of that driver supports CDC ACM style operation, like
|
||||
a USB modem, and so on most hardware it can interoperate easily with
|
||||
MS-Windows. One interesting use of that driver is in boot firmware (like
|
||||
a BIOS), which can sometimes use that model with very small systems
|
||||
without real serial lines.
|
||||
|
||||
Support for other kinds of gadget is expected to be developed and
|
||||
contributed over time, as this driver framework evolves.
|
||||
|
||||
USB On-The-GO (OTG)
|
||||
===================
|
||||
|
||||
USB OTG support on Linux 2.6 was initially developed by Texas
|
||||
Instruments for `OMAP <http://www.omap.com>`__ 16xx and 17xx series
|
||||
processors. Other OTG systems should work in similar ways, but the
|
||||
hardware level details could be very different.
|
||||
|
||||
Systems need specialized hardware support to implement OTG, notably
|
||||
including a special *Mini-AB* jack and associated transceiver to support
|
||||
*Dual-Role* operation: they can act either as a host, using the standard
|
||||
Linux-USB host side driver stack, or as a peripheral, using this
|
||||
``gadget`` framework. To do that, the system software relies on small
|
||||
additions to those programming interfaces, and on a new internal
|
||||
component (here called an "OTG Controller") affecting which driver stack
|
||||
connects to the OTG port. In each role, the system can re-use the
|
||||
existing pool of hardware-neutral drivers, layered on top of the
|
||||
controller driver interfaces (:c:type:`usb_bus` or :c:type:`usb_gadget`).
|
||||
Such drivers need at most minor changes, and most of the calls added to
|
||||
support OTG can also benefit non-OTG products.
|
||||
|
||||
- Gadget drivers test the ``is_otg`` flag, and use it to determine
|
||||
whether or not to include an OTG descriptor in each of their
|
||||
configurations.
|
||||
|
||||
- Gadget drivers may need changes to support the two new OTG protocols,
|
||||
exposed in new gadget attributes such as ``b_hnp_enable`` flag. HNP
|
||||
support should be reported through a user interface (two LEDs could
|
||||
suffice), and is triggered in some cases when the host suspends the
|
||||
peripheral. SRP support can be user-initiated just like remote
|
||||
wakeup, probably by pressing the same button.
|
||||
|
||||
- On the host side, USB device drivers need to be taught to trigger HNP
|
||||
at appropriate moments, using ``usb_suspend_device()``. That also
|
||||
conserves battery power, which is useful even for non-OTG
|
||||
configurations.
|
||||
|
||||
- Also on the host side, a driver must support the OTG "Targeted
|
||||
Peripheral List". That's just a whitelist, used to reject peripherals
|
||||
not supported with a given Linux OTG host. *This whitelist is
|
||||
product-specific; each product must modify* ``otg_whitelist.h`` *to
|
||||
match its interoperability specification.*
|
||||
|
||||
Non-OTG Linux hosts, like PCs and workstations, normally have some
|
||||
solution for adding drivers, so that peripherals that aren't
|
||||
recognized can eventually be supported. That approach is unreasonable
|
||||
for consumer products that may never have their firmware upgraded,
|
||||
and where it's usually unrealistic to expect traditional
|
||||
PC/workstation/server kinds of support model to work. For example,
|
||||
it's often impractical to change device firmware once the product has
|
||||
been distributed, so driver bugs can't normally be fixed if they're
|
||||
found after shipment.
|
||||
|
||||
Additional changes are needed below those hardware-neutral :c:type:`usb_bus`
|
||||
and :c:type:`usb_gadget` driver interfaces; those aren't discussed here in any
|
||||
detail. Those affect the hardware-specific code for each USB Host or
|
||||
Peripheral controller, and how the HCD initializes (since OTG can be
|
||||
active only on a single port). They also involve what may be called an
|
||||
*OTG Controller Driver*, managing the OTG transceiver and the OTG state
|
||||
machine logic as well as much of the root hub behavior for the OTG port.
|
||||
The OTG controller driver needs to activate and deactivate USB
|
||||
controllers depending on the relevant device role. Some related changes
|
||||
were needed inside usbcore, so that it can identify OTG-capable devices
|
||||
and respond appropriately to HNP or SRP protocols.
|
|
@ -1,4 +1,9 @@
|
|||
LINUX HOTPLUGGING
|
||||
USB hotplugging
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Linux Hotplugging
|
||||
=================
|
||||
|
||||
|
||||
In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices
|
||||
into the bus with power on. In most cases, users expect the devices to become
|
||||
|
@ -30,11 +35,11 @@ Because some of those actions rely on information about drivers (metadata)
|
|||
that is currently available only when the drivers are dynamically linked,
|
||||
you get the best hotplugging when you configure a highly modular system.
|
||||
|
||||
Kernel Hotplug Helper (``/sbin/hotplug``)
|
||||
=========================================
|
||||
|
||||
KERNEL HOTPLUG HELPER (/sbin/hotplug)
|
||||
|
||||
There is a kernel parameter: /proc/sys/kernel/hotplug, which normally
|
||||
holds the pathname "/sbin/hotplug". That parameter names a program
|
||||
There is a kernel parameter: ``/proc/sys/kernel/hotplug``, which normally
|
||||
holds the pathname ``/sbin/hotplug``. That parameter names a program
|
||||
which the kernel may invoke at various times.
|
||||
|
||||
The /sbin/hotplug program can be invoked by any subsystem as part of its
|
||||
|
@ -51,26 +56,26 @@ Hotplug software and other resources is available at:
|
|||
Mailing list information is also available at that site.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
USB Policy Agent
|
||||
================
|
||||
|
||||
|
||||
USB POLICY AGENT
|
||||
|
||||
The USB subsystem currently invokes /sbin/hotplug when USB devices
|
||||
The USB subsystem currently invokes ``/sbin/hotplug`` when USB devices
|
||||
are added or removed from system. The invocation is done by the kernel
|
||||
hub workqueue [hub_wq], or else as part of root hub initialization
|
||||
(done by init, modprobe, kapmd, etc). Its single command line parameter
|
||||
is the string "usb", and it passes these environment variables:
|
||||
|
||||
ACTION ... "add", "remove"
|
||||
PRODUCT ... USB vendor, product, and version codes (hex)
|
||||
TYPE ... device class codes (decimal)
|
||||
INTERFACE ... interface 0 class codes (decimal)
|
||||
========== ============================================
|
||||
ACTION ``add``, ``remove``
|
||||
PRODUCT USB vendor, product, and version codes (hex)
|
||||
TYPE device class codes (decimal)
|
||||
INTERFACE interface 0 class codes (decimal)
|
||||
========== ============================================
|
||||
|
||||
If "usbdevfs" is configured, DEVICE and DEVFS are also passed. DEVICE is
|
||||
the pathname of the device, and is useful for devices with multiple and/or
|
||||
alternate interfaces that complicate driver selection. By design, USB
|
||||
hotplugging is independent of "usbdevfs": you can do most essential parts
|
||||
hotplugging is independent of ``usbdevfs``: you can do most essential parts
|
||||
of USB device setup without using that filesystem, and without running a
|
||||
user mode daemon to detect changes in system configuration.
|
||||
|
||||
|
@ -79,19 +84,20 @@ modules, and can invoke driver-specific setup scripts. The newest ones
|
|||
leverage USB module-init-tools support. Later agents might unload drivers.
|
||||
|
||||
|
||||
USB MODUTILS SUPPORT
|
||||
USB Modutils Support
|
||||
====================
|
||||
|
||||
Current versions of module-init-tools will create a "modules.usbmap" file
|
||||
which contains the entries from each driver's MODULE_DEVICE_TABLE. Such
|
||||
Current versions of module-init-tools will create a ``modules.usbmap`` file
|
||||
which contains the entries from each driver's ``MODULE_DEVICE_TABLE``. Such
|
||||
files can be used by various user mode policy agents to make sure all the
|
||||
right driver modules get loaded, either at boot time or later.
|
||||
|
||||
See <linux/usb.h> for full information about such table entries; or look
|
||||
See ``linux/usb.h`` for full information about such table entries; or look
|
||||
at existing drivers. Each table entry describes one or more criteria to
|
||||
be used when matching a driver to a device or class of devices. The
|
||||
specific criteria are identified by bits set in "match_flags", paired
|
||||
with field values. You can construct the criteria directly, or with
|
||||
macros such as these, and use driver_info to store more information.
|
||||
macros such as these, and use driver_info to store more information::
|
||||
|
||||
USB_DEVICE (vendorId, productId)
|
||||
... matching devices with specified vendor and product ids
|
||||
|
@ -103,7 +109,7 @@ macros such as these, and use driver_info to store more information.
|
|||
... matching specified device class info
|
||||
|
||||
A short example, for a driver that supports several specific USB devices
|
||||
and their quirks, might have a MODULE_DEVICE_TABLE like this:
|
||||
and their quirks, might have a MODULE_DEVICE_TABLE like this::
|
||||
|
||||
static const struct usb_device_id mydriver_id_table[] = {
|
||||
{ USB_DEVICE (0x9999, 0xaaaa), driver_info: QUIRK_X },
|
||||
|
@ -116,10 +122,10 @@ and their quirks, might have a MODULE_DEVICE_TABLE like this:
|
|||
Most USB device drivers should pass these tables to the USB subsystem as
|
||||
well as to the module management subsystem. Not all, though: some driver
|
||||
frameworks connect using interfaces layered over USB, and so they won't
|
||||
need such a "struct usb_driver".
|
||||
need such a struct :c:type:`usb_driver`.
|
||||
|
||||
Drivers that connect directly to the USB subsystem should be declared
|
||||
something like this:
|
||||
something like this::
|
||||
|
||||
static struct usb_driver mydriver = {
|
||||
.name = "mydriver",
|
||||
|
@ -138,11 +144,11 @@ something like this:
|
|||
|
||||
When the USB subsystem knows about a driver's device ID table, it's used when
|
||||
choosing drivers to probe(). The thread doing new device processing checks
|
||||
drivers' device ID entries from the MODULE_DEVICE_TABLE against interface and
|
||||
device descriptors for the device. It will only call probe() if there is a
|
||||
match, and the third argument to probe() will be the entry that matched.
|
||||
|
||||
If you don't provide an id_table for your driver, then your driver may get
|
||||
probed for each new device; the third parameter to probe() will be null.
|
||||
|
||||
drivers' device ID entries from the ``MODULE_DEVICE_TABLE`` against interface
|
||||
and device descriptors for the device. It will only call ``probe()`` if there
|
||||
is a match, and the third argument to ``probe()`` will be the entry that
|
||||
matched.
|
||||
|
||||
If you don't provide an ``id_table`` for your driver, then your driver may get
|
||||
probed for each new device; the third parameter to ``probe()`` will be
|
||||
``NULL``.
|
26
Documentation/driver-api/usb/index.rst
Normal file
26
Documentation/driver-api/usb/index.rst
Normal file
|
@ -0,0 +1,26 @@
|
|||
=============
|
||||
Linux USB API
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
|
||||
usb
|
||||
gadget
|
||||
anchors
|
||||
bulk-streams
|
||||
callbacks
|
||||
dma
|
||||
URB
|
||||
power-management
|
||||
hotplug
|
||||
persist
|
||||
error-codes
|
||||
writing_usb_driver
|
||||
writing_musb_glue_layer
|
||||
|
||||
.. only:: subproject and html
|
||||
|
||||
Indices
|
||||
=======
|
||||
|
||||
* :ref:`genindex`
|
|
@ -1,11 +1,14 @@
|
|||
USB device persistence during system suspend
|
||||
.. _usb-persist:
|
||||
|
||||
Alan Stern <stern@rowland.harvard.edu>
|
||||
USB device persistence during system suspend
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
September 2, 2006 (Updated February 25, 2008)
|
||||
:Author: Alan Stern <stern@rowland.harvard.edu>
|
||||
:Date: September 2, 2006 (Updated February 25, 2008)
|
||||
|
||||
|
||||
What is the problem?
|
||||
What is the problem?
|
||||
====================
|
||||
|
||||
According to the USB specification, when a USB bus is suspended the
|
||||
bus must continue to supply suspend current (around 1-5 mA). This
|
||||
|
@ -63,7 +66,8 @@ suspended -- but it will crash as soon as it wakes up, which isn't
|
|||
much better.)
|
||||
|
||||
|
||||
What is the solution?
|
||||
What is the solution?
|
||||
=====================
|
||||
|
||||
The kernel includes a feature called USB-persist. It tries to work
|
||||
around these issues by allowing the core USB device data structures to
|
||||
|
@ -99,7 +103,7 @@ now a good and happy place.
|
|||
|
||||
Note that the "USB-persist" feature will be applied only to those
|
||||
devices for which it is enabled. You can enable the feature by doing
|
||||
(as root):
|
||||
(as root)::
|
||||
|
||||
echo 1 >/sys/bus/usb/devices/.../power/persist
|
||||
|
||||
|
@ -110,7 +114,8 @@ doesn't even exist, so you only have to worry about setting it for
|
|||
devices where it really matters.
|
||||
|
||||
|
||||
Is this the best solution?
|
||||
Is this the best solution?
|
||||
==========================
|
||||
|
||||
Perhaps not. Arguably, keeping track of mounted filesystems and
|
||||
memory mappings across device disconnects should be handled by a
|
||||
|
@ -130,7 +135,8 @@ just mass-storage devices. It might turn out to be equally useful for
|
|||
other device types, such as network interfaces.
|
||||
|
||||
|
||||
WARNING: USB-persist can be dangerous!!
|
||||
WARNING: USB-persist can be dangerous!!
|
||||
=======================================
|
||||
|
||||
When recovering an interrupted power session the kernel does its best
|
||||
to make sure the USB device hasn't been changed; that is, the same
|
|
@ -1,10 +1,12 @@
|
|||
Power Management for USB
|
||||
.. _usb-power-management:
|
||||
|
||||
Alan Stern <stern@rowland.harvard.edu>
|
||||
|
||||
Last-updated: February 2014
|
||||
Power Management for USB
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:Author: Alan Stern <stern@rowland.harvard.edu>
|
||||
:Date: Last-updated: February 2014
|
||||
|
||||
..
|
||||
Contents:
|
||||
---------
|
||||
* What is Power Management?
|
||||
|
@ -25,14 +27,14 @@
|
|||
* Suggested Userspace Port Power Policy
|
||||
|
||||
|
||||
What is Power Management?
|
||||
-------------------------
|
||||
What is Power Management?
|
||||
-------------------------
|
||||
|
||||
Power Management (PM) is the practice of saving energy by suspending
|
||||
parts of a computer system when they aren't being used. While a
|
||||
component is "suspended" it is in a nonfunctional low-power state; it
|
||||
component is ``suspended`` it is in a nonfunctional low-power state; it
|
||||
might even be turned off completely. A suspended component can be
|
||||
"resumed" (returned to a functional full-power state) when the kernel
|
||||
``resumed`` (returned to a functional full-power state) when the kernel
|
||||
needs to use it. (There also are forms of PM in which components are
|
||||
placed in a less functional but still usable state instead of being
|
||||
suspended; an example would be reducing the CPU's clock rate. This
|
||||
|
@ -44,22 +46,25 @@ device is turned off while the system as a whole remains running, we
|
|||
call it a "dynamic suspend" (also known as a "runtime suspend" or
|
||||
"selective suspend"). This document concentrates mostly on how
|
||||
dynamic PM is implemented in the USB subsystem, although system PM is
|
||||
covered to some extent (see Documentation/power/*.txt for more
|
||||
covered to some extent (see ``Documentation/power/*.txt`` for more
|
||||
information about system PM).
|
||||
|
||||
System PM support is present only if the kernel was built with CONFIG_SUSPEND
|
||||
or CONFIG_HIBERNATION enabled. Dynamic PM support for USB is present whenever
|
||||
the kernel was built with CONFIG_PM enabled.
|
||||
System PM support is present only if the kernel was built with
|
||||
``CONFIG_SUSPEND`` or ``CONFIG_HIBERNATION`` enabled. Dynamic PM support
|
||||
|
||||
for USB is present whenever
|
||||
the kernel was built with ``CONFIG_PM`` enabled.
|
||||
|
||||
[Historically, dynamic PM support for USB was present only if the
|
||||
kernel had been built with CONFIG_USB_SUSPEND enabled (which depended on
|
||||
CONFIG_PM_RUNTIME). Starting with the 3.10 kernel release, dynamic PM support
|
||||
for USB was present whenever the kernel was built with CONFIG_PM_RUNTIME
|
||||
enabled. The CONFIG_USB_SUSPEND option had been eliminated.]
|
||||
kernel had been built with ``CONFIG_USB_SUSPEND`` enabled (which depended on
|
||||
``CONFIG_PM_RUNTIME``). Starting with the 3.10 kernel release, dynamic PM
|
||||
support for USB was present whenever the kernel was built with
|
||||
``CONFIG_PM_RUNTIME`` enabled. The ``CONFIG_USB_SUSPEND`` option had been
|
||||
eliminated.]
|
||||
|
||||
|
||||
What is Remote Wakeup?
|
||||
----------------------
|
||||
What is Remote Wakeup?
|
||||
----------------------
|
||||
|
||||
When a device has been suspended, it generally doesn't resume until
|
||||
the computer tells it to. Likewise, if the entire computer has been
|
||||
|
@ -76,8 +81,8 @@ event. Examples include a suspended keyboard resuming when a key is
|
|||
pressed, or a suspended USB hub resuming when a device is plugged in.
|
||||
|
||||
|
||||
When is a USB device idle?
|
||||
--------------------------
|
||||
When is a USB device idle?
|
||||
--------------------------
|
||||
|
||||
A device is idle whenever the kernel thinks it's not busy doing
|
||||
anything important and thus is a candidate for being suspended. The
|
||||
|
@ -92,11 +97,11 @@ If a USB device has no driver, its usbfs file isn't open, and it isn't
|
|||
being accessed through sysfs, then it definitely is idle.
|
||||
|
||||
|
||||
Forms of dynamic PM
|
||||
-------------------
|
||||
Forms of dynamic PM
|
||||
-------------------
|
||||
|
||||
Dynamic suspends occur when the kernel decides to suspend an idle
|
||||
device. This is called "autosuspend" for short. In general, a device
|
||||
device. This is called ``autosuspend`` for short. In general, a device
|
||||
won't be autosuspended unless it has been idle for some minimum period
|
||||
of time, the so-called idle-delay time.
|
||||
|
||||
|
@ -125,51 +130,51 @@ all dynamic suspend events are internal; external agents are not
|
|||
allowed to issue dynamic suspends.
|
||||
|
||||
|
||||
The user interface for dynamic PM
|
||||
---------------------------------
|
||||
The user interface for dynamic PM
|
||||
---------------------------------
|
||||
|
||||
The user interface for controlling dynamic PM is located in the power/
|
||||
The user interface for controlling dynamic PM is located in the ``power/``
|
||||
subdirectory of each USB device's sysfs directory, that is, in
|
||||
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
|
||||
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
|
||||
relevant attribute files are: wakeup, control, and
|
||||
autosuspend_delay_ms. (There may also be a file named "level"; this
|
||||
``autosuspend_delay_ms``. (There may also be a file named ``level``; this
|
||||
file was deprecated as of the 2.6.35 kernel and replaced by the
|
||||
"control" file. In 2.6.38 the "autosuspend" file will be deprecated
|
||||
and replaced by the "autosuspend_delay_ms" file. The only difference
|
||||
``control`` file. In 2.6.38 the ``autosuspend`` file will be deprecated
|
||||
and replaced by the ``autosuspend_delay_ms`` file. The only difference
|
||||
is that the newer file expresses the delay in milliseconds whereas the
|
||||
older file uses seconds. Confusingly, both files are present in 2.6.37
|
||||
but only "autosuspend" works.)
|
||||
but only ``autosuspend`` works.)
|
||||
|
||||
power/wakeup
|
||||
``power/wakeup``
|
||||
|
||||
This file is empty if the device does not support
|
||||
remote wakeup. Otherwise the file contains either the
|
||||
word "enabled" or the word "disabled", and you can
|
||||
word ``enabled`` or the word ``disabled``, and you can
|
||||
write those words to the file. The setting determines
|
||||
whether or not remote wakeup will be enabled when the
|
||||
device is next suspended. (If the setting is changed
|
||||
while the device is suspended, the change won't take
|
||||
effect until the following suspend.)
|
||||
|
||||
power/control
|
||||
``power/control``
|
||||
|
||||
This file contains one of two words: "on" or "auto".
|
||||
This file contains one of two words: ``on`` or ``auto``.
|
||||
You can write those words to the file to change the
|
||||
device's setting.
|
||||
|
||||
"on" means that the device should be resumed and
|
||||
autosuspend is not allowed. (Of course, system
|
||||
suspends are still allowed.)
|
||||
- ``on`` means that the device should be resumed and
|
||||
autosuspend is not allowed. (Of course, system
|
||||
suspends are still allowed.)
|
||||
|
||||
"auto" is the normal state in which the kernel is
|
||||
allowed to autosuspend and autoresume the device.
|
||||
- ``auto`` is the normal state in which the kernel is
|
||||
allowed to autosuspend and autoresume the device.
|
||||
|
||||
(In kernels up to 2.6.32, you could also specify
|
||||
"suspend", meaning that the device should remain
|
||||
``suspend``, meaning that the device should remain
|
||||
suspended and autoresume was not allowed. This
|
||||
setting is no longer supported.)
|
||||
|
||||
power/autosuspend_delay_ms
|
||||
``power/autosuspend_delay_ms``
|
||||
|
||||
This file contains an integer value, which is the
|
||||
number of milliseconds the device should remain idle
|
||||
|
@ -180,31 +185,31 @@ but only "autosuspend" works.)
|
|||
number to the file to change the autosuspend
|
||||
idle-delay time.
|
||||
|
||||
Writing "-1" to power/autosuspend_delay_ms and writing "on" to
|
||||
power/control do essentially the same thing -- they both prevent the
|
||||
Writing ``-1`` to ``power/autosuspend_delay_ms`` and writing ``on`` to
|
||||
``power/control`` do essentially the same thing -- they both prevent the
|
||||
device from being autosuspended. Yes, this is a redundancy in the
|
||||
API.
|
||||
|
||||
(In 2.6.21 writing "0" to power/autosuspend would prevent the device
|
||||
(In 2.6.21 writing ``0`` to ``power/autosuspend`` would prevent the device
|
||||
from being autosuspended; the behavior was changed in 2.6.22. The
|
||||
power/autosuspend attribute did not exist prior to 2.6.21, and the
|
||||
power/level attribute did not exist prior to 2.6.22. power/control
|
||||
was added in 2.6.34, and power/autosuspend_delay_ms was added in
|
||||
``power/autosuspend`` attribute did not exist prior to 2.6.21, and the
|
||||
``power/level`` attribute did not exist prior to 2.6.22. ``power/control``
|
||||
was added in 2.6.34, and ``power/autosuspend_delay_ms`` was added in
|
||||
2.6.37 but did not become functional until 2.6.38.)
|
||||
|
||||
|
||||
Changing the default idle-delay time
|
||||
------------------------------------
|
||||
Changing the default idle-delay time
|
||||
------------------------------------
|
||||
|
||||
The default autosuspend idle-delay time (in seconds) is controlled by
|
||||
a module parameter in usbcore. You can specify the value when usbcore
|
||||
is loaded. For example, to set it to 5 seconds instead of 2 you would
|
||||
do:
|
||||
do::
|
||||
|
||||
modprobe usbcore autosuspend=5
|
||||
|
||||
Equivalently, you could add to a configuration file in /etc/modprobe.d
|
||||
a line saying:
|
||||
a line saying::
|
||||
|
||||
options usbcore autosuspend=5
|
||||
|
||||
|
@ -214,14 +219,14 @@ image. To alter the parameter value you would have to rebuild that
|
|||
image.
|
||||
|
||||
If usbcore is compiled into the kernel rather than built as a loadable
|
||||
module, you can add
|
||||
module, you can add::
|
||||
|
||||
usbcore.autosuspend=5
|
||||
|
||||
to the kernel's boot command line.
|
||||
|
||||
Finally, the parameter value can be changed while the system is
|
||||
running. If you do:
|
||||
running. If you do::
|
||||
|
||||
echo 5 >/sys/module/usbcore/parameters/autosuspend
|
||||
|
||||
|
@ -234,8 +239,8 @@ autosuspend of any USB device. This has the benefit of allowing you
|
|||
then to enable autosuspend for selected devices.
|
||||
|
||||
|
||||
Warnings
|
||||
--------
|
||||
Warnings
|
||||
--------
|
||||
|
||||
The USB specification states that all USB devices must support power
|
||||
management. Nevertheless, the sad fact is that many devices do not
|
||||
|
@ -246,7 +251,7 @@ among printers and scanners, but plenty of other types of device have
|
|||
the same deficiency.
|
||||
|
||||
For this reason, by default the kernel disables autosuspend (the
|
||||
power/control attribute is initialized to "on") for all devices other
|
||||
``power/control`` attribute is initialized to ``on``) for all devices other
|
||||
than hubs. Hubs, at least, appear to be reasonably well-behaved in
|
||||
this regard.
|
||||
|
||||
|
@ -284,30 +289,30 @@ device by suspending it at the wrong time. (Highly unlikely, but
|
|||
possible.) Take care.
|
||||
|
||||
|
||||
The driver interface for Power Management
|
||||
-----------------------------------------
|
||||
The driver interface for Power Management
|
||||
-----------------------------------------
|
||||
|
||||
The requirements for a USB driver to support external power management
|
||||
are pretty modest; the driver need only define
|
||||
are pretty modest; the driver need only define::
|
||||
|
||||
.suspend
|
||||
.resume
|
||||
.reset_resume
|
||||
|
||||
methods in its usb_driver structure, and the reset_resume method is
|
||||
optional. The methods' jobs are quite simple:
|
||||
methods in its :c:type:`usb_driver` structure, and the ``reset_resume`` method
|
||||
is optional. The methods' jobs are quite simple:
|
||||
|
||||
The suspend method is called to warn the driver that the
|
||||
- The ``suspend`` method is called to warn the driver that the
|
||||
device is going to be suspended. If the driver returns a
|
||||
negative error code, the suspend will be aborted. Normally
|
||||
the driver will return 0, in which case it must cancel all
|
||||
outstanding URBs (usb_kill_urb()) and not submit any more.
|
||||
outstanding URBs (:c:func:`usb_kill_urb`) and not submit any more.
|
||||
|
||||
The resume method is called to tell the driver that the
|
||||
- The ``resume`` method is called to tell the driver that the
|
||||
device has been resumed and the driver can return to normal
|
||||
operation. URBs may once more be submitted.
|
||||
|
||||
The reset_resume method is called to tell the driver that
|
||||
- The ``reset_resume`` method is called to tell the driver that
|
||||
the device has been resumed and it also has been reset.
|
||||
The driver should redo any necessary device initialization,
|
||||
since the device has probably lost most or all of its state
|
||||
|
@ -315,22 +320,22 @@ optional. The methods' jobs are quite simple:
|
|||
before the suspend).
|
||||
|
||||
If the device is disconnected or powered down while it is suspended,
|
||||
the disconnect method will be called instead of the resume or
|
||||
reset_resume method. This is also quite likely to happen when
|
||||
the ``disconnect`` method will be called instead of the ``resume`` or
|
||||
``reset_resume`` method. This is also quite likely to happen when
|
||||
waking up from hibernation, as many systems do not maintain suspend
|
||||
current to the USB host controllers during hibernation. (It's
|
||||
possible to work around the hibernation-forces-disconnect problem by
|
||||
using the USB Persist facility.)
|
||||
|
||||
The reset_resume method is used by the USB Persist facility (see
|
||||
Documentation/usb/persist.txt) and it can also be used under certain
|
||||
circumstances when CONFIG_USB_PERSIST is not enabled. Currently, if a
|
||||
The ``reset_resume`` method is used by the USB Persist facility (see
|
||||
:ref:`usb-persist`) and it can also be used under certain
|
||||
circumstances when ``CONFIG_USB_PERSIST`` is not enabled. Currently, if a
|
||||
device is reset during a resume and the driver does not have a
|
||||
reset_resume method, the driver won't receive any notification about
|
||||
the resume. Later kernels will call the driver's disconnect method;
|
||||
``reset_resume`` method, the driver won't receive any notification about
|
||||
the resume. Later kernels will call the driver's ``disconnect`` method;
|
||||
2.6.23 doesn't do this.
|
||||
|
||||
USB drivers are bound to interfaces, so their suspend and resume
|
||||
USB drivers are bound to interfaces, so their ``suspend`` and ``resume``
|
||||
methods get called when the interfaces are suspended or resumed. In
|
||||
principle one might want to suspend some interfaces on a device (i.e.,
|
||||
force the drivers for those interface to stop all activity) without
|
||||
|
@ -341,15 +346,15 @@ to suspend or resume some but not all of a device's interfaces. The
|
|||
closest you can come is to unbind the interfaces' drivers.
|
||||
|
||||
|
||||
The driver interface for autosuspend and autoresume
|
||||
---------------------------------------------------
|
||||
The driver interface for autosuspend and autoresume
|
||||
---------------------------------------------------
|
||||
|
||||
To support autosuspend and autoresume, a driver should implement all
|
||||
three of the methods listed above. In addition, a driver indicates
|
||||
that it supports autosuspend by setting the .supports_autosuspend flag
|
||||
that it supports autosuspend by setting the ``.supports_autosuspend`` flag
|
||||
in its usb_driver structure. It is then responsible for informing the
|
||||
USB core whenever one of its interfaces becomes busy or idle. The
|
||||
driver does so by calling these six functions:
|
||||
driver does so by calling these six functions::
|
||||
|
||||
int usb_autopm_get_interface(struct usb_interface *intf);
|
||||
void usb_autopm_put_interface(struct usb_interface *intf);
|
||||
|
@ -368,41 +373,41 @@ autosuspend the device.
|
|||
Drivers need not be concerned about balancing changes to the usage
|
||||
counter; the USB core will undo any remaining "get"s when a driver
|
||||
is unbound from its interface. As a corollary, drivers must not call
|
||||
any of the usb_autopm_* functions after their disconnect() routine has
|
||||
returned.
|
||||
any of the ``usb_autopm_*`` functions after their ``disconnect``
|
||||
routine has returned.
|
||||
|
||||
Drivers using the async routines are responsible for their own
|
||||
synchronization and mutual exclusion.
|
||||
|
||||
usb_autopm_get_interface() increments the usage counter and
|
||||
:c:func:`usb_autopm_get_interface` increments the usage counter and
|
||||
does an autoresume if the device is suspended. If the
|
||||
autoresume fails, the counter is decremented back.
|
||||
|
||||
usb_autopm_put_interface() decrements the usage counter and
|
||||
:c:func:`usb_autopm_put_interface` decrements the usage counter and
|
||||
attempts an autosuspend if the new value is = 0.
|
||||
|
||||
usb_autopm_get_interface_async() and
|
||||
usb_autopm_put_interface_async() do almost the same things as
|
||||
:c:func:`usb_autopm_get_interface_async` and
|
||||
:c:func:`usb_autopm_put_interface_async` do almost the same things as
|
||||
their non-async counterparts. The big difference is that they
|
||||
use a workqueue to do the resume or suspend part of their
|
||||
jobs. As a result they can be called in an atomic context,
|
||||
such as an URB's completion handler, but when they return the
|
||||
device will generally not yet be in the desired state.
|
||||
|
||||
usb_autopm_get_interface_no_resume() and
|
||||
usb_autopm_put_interface_no_suspend() merely increment or
|
||||
:c:func:`usb_autopm_get_interface_no_resume` and
|
||||
:c:func:`usb_autopm_put_interface_no_suspend` merely increment or
|
||||
decrement the usage counter; they do not attempt to carry out
|
||||
an autoresume or an autosuspend. Hence they can be called in
|
||||
an atomic context.
|
||||
|
||||
The simplest usage pattern is that a driver calls
|
||||
usb_autopm_get_interface() in its open routine and
|
||||
usb_autopm_put_interface() in its close or release routine. But other
|
||||
:c:func:`usb_autopm_get_interface` in its open routine and
|
||||
:c:func:`usb_autopm_put_interface` in its close or release routine. But other
|
||||
patterns are possible.
|
||||
|
||||
The autosuspend attempts mentioned above will often fail for one
|
||||
reason or another. For example, the power/control attribute might be
|
||||
set to "on", or another interface in the same device might not be
|
||||
reason or another. For example, the ``power/control`` attribute might be
|
||||
set to ``on``, or another interface in the same device might not be
|
||||
idle. This is perfectly normal. If the reason for failure was that
|
||||
the device hasn't been idle for long enough, a timer is scheduled to
|
||||
carry out the operation automatically when the autosuspend idle-delay
|
||||
|
@ -413,37 +418,37 @@ the device is no longer present or operating properly. Unlike
|
|||
autosuspend, there's no idle-delay for an autoresume.
|
||||
|
||||
|
||||
Other parts of the driver interface
|
||||
-----------------------------------
|
||||
Other parts of the driver interface
|
||||
-----------------------------------
|
||||
|
||||
Drivers can enable autosuspend for their devices by calling
|
||||
Drivers can enable autosuspend for their devices by calling::
|
||||
|
||||
usb_enable_autosuspend(struct usb_device *udev);
|
||||
|
||||
in their probe() routine, if they know that the device is capable of
|
||||
in their :c:func:`probe` routine, if they know that the device is capable of
|
||||
suspending and resuming correctly. This is exactly equivalent to
|
||||
writing "auto" to the device's power/control attribute. Likewise,
|
||||
drivers can disable autosuspend by calling
|
||||
writing ``auto`` to the device's ``power/control`` attribute. Likewise,
|
||||
drivers can disable autosuspend by calling::
|
||||
|
||||
usb_disable_autosuspend(struct usb_device *udev);
|
||||
|
||||
This is exactly the same as writing "on" to the power/control attribute.
|
||||
This is exactly the same as writing ``on`` to the ``power/control`` attribute.
|
||||
|
||||
Sometimes a driver needs to make sure that remote wakeup is enabled
|
||||
during autosuspend. For example, there's not much point
|
||||
autosuspending a keyboard if the user can't cause the keyboard to do a
|
||||
remote wakeup by typing on it. If the driver sets
|
||||
intf->needs_remote_wakeup to 1, the kernel won't autosuspend the
|
||||
``intf->needs_remote_wakeup`` to 1, the kernel won't autosuspend the
|
||||
device if remote wakeup isn't available. (If the device is already
|
||||
autosuspended, though, setting this flag won't cause the kernel to
|
||||
autoresume it. Normally a driver would set this flag in its probe
|
||||
autoresume it. Normally a driver would set this flag in its ``probe``
|
||||
method, at which time the device is guaranteed not to be
|
||||
autosuspended.)
|
||||
|
||||
If a driver does its I/O asynchronously in interrupt context, it
|
||||
should call usb_autopm_get_interface_async() before starting output and
|
||||
usb_autopm_put_interface_async() when the output queue drains. When
|
||||
it receives an input event, it should call
|
||||
should call :c:func:`usb_autopm_get_interface_async` before starting output and
|
||||
:c:func:`usb_autopm_put_interface_async` when the output queue drains. When
|
||||
it receives an input event, it should call::
|
||||
|
||||
usb_mark_last_busy(struct usb_device *udev);
|
||||
|
||||
|
@ -453,41 +458,41 @@ be pushed back. Many of the usb_autopm_* routines also make this call,
|
|||
so drivers need to worry only when interrupt-driven input arrives.
|
||||
|
||||
Asynchronous operation is always subject to races. For example, a
|
||||
driver may call the usb_autopm_get_interface_async() routine at a time
|
||||
driver may call the :c:func:`usb_autopm_get_interface_async` routine at a time
|
||||
when the core has just finished deciding the device has been idle for
|
||||
long enough but not yet gotten around to calling the driver's suspend
|
||||
method. The suspend method must be responsible for synchronizing with
|
||||
long enough but not yet gotten around to calling the driver's ``suspend``
|
||||
method. The ``suspend`` method must be responsible for synchronizing with
|
||||
the I/O request routine and the URB completion handler; it should
|
||||
cause autosuspends to fail with -EBUSY if the driver needs to use the
|
||||
device.
|
||||
|
||||
External suspend calls should never be allowed to fail in this way,
|
||||
only autosuspend calls. The driver can tell them apart by applying
|
||||
the PMSG_IS_AUTO() macro to the message argument to the suspend
|
||||
the :c:func:`PMSG_IS_AUTO` macro to the message argument to the ``suspend``
|
||||
method; it will return True for internal PM events (autosuspend) and
|
||||
False for external PM events.
|
||||
|
||||
|
||||
Mutual exclusion
|
||||
----------------
|
||||
Mutual exclusion
|
||||
----------------
|
||||
|
||||
For external events -- but not necessarily for autosuspend or
|
||||
autoresume -- the device semaphore (udev->dev.sem) will be held when a
|
||||
suspend or resume method is called. This implies that external
|
||||
suspend/resume events are mutually exclusive with calls to probe,
|
||||
disconnect, pre_reset, and post_reset; the USB core guarantees that
|
||||
``suspend`` or ``resume`` method is called. This implies that external
|
||||
suspend/resume events are mutually exclusive with calls to ``probe``,
|
||||
``disconnect``, ``pre_reset``, and ``post_reset``; the USB core guarantees that
|
||||
this is true of autosuspend/autoresume events as well.
|
||||
|
||||
If a driver wants to block all suspend/resume calls during some
|
||||
critical section, the best way is to lock the device and call
|
||||
usb_autopm_get_interface() (and do the reverse at the end of the
|
||||
:c:func:`usb_autopm_get_interface` (and do the reverse at the end of the
|
||||
critical section). Holding the device semaphore will block all
|
||||
external PM calls, and the usb_autopm_get_interface() will prevent any
|
||||
external PM calls, and the :c:func:`usb_autopm_get_interface` will prevent any
|
||||
internal PM calls, even if it fails. (Exercise: Why?)
|
||||
|
||||
|
||||
Interaction between dynamic PM and system PM
|
||||
--------------------------------------------
|
||||
Interaction between dynamic PM and system PM
|
||||
--------------------------------------------
|
||||
|
||||
Dynamic power management and system power management can interact in
|
||||
a couple of ways.
|
||||
|
@ -512,8 +517,8 @@ wakeup may fail and get lost. Which outcome occurs depends on timing
|
|||
and on the hardware and firmware design.
|
||||
|
||||
|
||||
xHCI hardware link PM
|
||||
---------------------
|
||||
xHCI hardware link PM
|
||||
---------------------
|
||||
|
||||
xHCI host controller provides hardware link power management to usb2.0
|
||||
(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
|
||||
|
@ -522,11 +527,11 @@ lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
|
|||
which state device can enter and resume very quickly.
|
||||
|
||||
The user interface for controlling hardware LPM is located in the
|
||||
power/ subdirectory of each USB device's sysfs directory, that is, in
|
||||
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
|
||||
relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
|
||||
``power/`` subdirectory of each USB device's sysfs directory, that is, in
|
||||
``/sys/bus/usb/devices/.../power/`` where "..." is the device's ID. The
|
||||
relevant attribute files are ``usb2_hardware_lpm`` and ``usb3_hardware_lpm``.
|
||||
|
||||
power/usb2_hardware_lpm
|
||||
``power/usb2_hardware_lpm``
|
||||
|
||||
When a USB2 device which support LPM is plugged to a
|
||||
xHCI host root hub which support software LPM, the
|
||||
|
@ -537,8 +542,8 @@ relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
|
|||
can write y/Y/1 or n/N/0 to the file to enable/disable
|
||||
USB2 hardware LPM manually. This is for test purpose mainly.
|
||||
|
||||
power/usb3_hardware_lpm_u1
|
||||
power/usb3_hardware_lpm_u2
|
||||
``power/usb3_hardware_lpm_u1``
|
||||
``power/usb3_hardware_lpm_u2``
|
||||
|
||||
When a USB 3.0 lpm-capable device is plugged in to a
|
||||
xHCI host which supports link PM, it will check if U1
|
||||
|
@ -550,29 +555,31 @@ relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
|
|||
indicating whether or not USB3 hardware LPM U1 or U2
|
||||
is enabled for the device.
|
||||
|
||||
USB Port Power Control
|
||||
----------------------
|
||||
USB Port Power Control
|
||||
----------------------
|
||||
|
||||
In addition to suspending endpoint devices and enabling hardware
|
||||
controlled link power management, the USB subsystem also has the
|
||||
capability to disable power to ports under some conditions. Power is
|
||||
controlled through Set/ClearPortFeature(PORT_POWER) requests to a hub.
|
||||
controlled through ``Set/ClearPortFeature(PORT_POWER)`` requests to a hub.
|
||||
In the case of a root or platform-internal hub the host controller
|
||||
driver translates PORT_POWER requests into platform firmware (ACPI)
|
||||
driver translates ``PORT_POWER`` requests into platform firmware (ACPI)
|
||||
method calls to set the port power state. For more background see the
|
||||
Linux Plumbers Conference 2012 slides [1] and video [2]:
|
||||
Linux Plumbers Conference 2012 slides [#f1]_ and video [#f2]_:
|
||||
|
||||
Upon receiving a ClearPortFeature(PORT_POWER) request a USB port is
|
||||
logically off, and may trigger the actual loss of VBUS to the port [3].
|
||||
Upon receiving a ``ClearPortFeature(PORT_POWER)`` request a USB port is
|
||||
logically off, and may trigger the actual loss of VBUS to the port [#f3]_.
|
||||
VBUS may be maintained in the case where a hub gangs multiple ports into
|
||||
a shared power well causing power to remain until all ports in the gang
|
||||
are turned off. VBUS may also be maintained by hub ports configured for
|
||||
a charging application. In any event a logically off port will lose
|
||||
connection with its device, not respond to hotplug events, and not
|
||||
respond to remote wakeup events*.
|
||||
respond to remote wakeup events.
|
||||
|
||||
WARNING: turning off a port may result in the inability to hot add a device.
|
||||
Please see "User Interface for Port Power Control" for details.
|
||||
.. warning::
|
||||
|
||||
turning off a port may result in the inability to hot add a device.
|
||||
Please see "User Interface for Port Power Control" for details.
|
||||
|
||||
As far as the effect on the device itself it is similar to what a device
|
||||
goes through during system suspend, i.e. the power session is lost. Any
|
||||
|
@ -581,38 +588,49 @@ similarly affected by a port power cycle event. For this reason the
|
|||
implementation shares the same device recovery path (and honors the same
|
||||
quirks) as the system resume path for the hub.
|
||||
|
||||
[1]: http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
|
||||
[2]: http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
|
||||
[3]: USB 3.1 Section 10.12
|
||||
* wakeup note: if a device is configured to send wakeup events the port
|
||||
.. [#f1]
|
||||
|
||||
http://dl.dropbox.com/u/96820575/sarah-sharp-lpt-port-power-off2-mini.pdf
|
||||
|
||||
.. [#f2]
|
||||
|
||||
http://linuxplumbers.ubicast.tv/videos/usb-port-power-off-kerneluserspace-api/
|
||||
|
||||
.. [#f3]
|
||||
|
||||
USB 3.1 Section 10.12
|
||||
|
||||
wakeup note: if a device is configured to send wakeup events the port
|
||||
power control implementation will block poweroff attempts on that
|
||||
port.
|
||||
|
||||
|
||||
User Interface for Port Power Control
|
||||
-------------------------------------
|
||||
User Interface for Port Power Control
|
||||
-------------------------------------
|
||||
|
||||
The port power control mechanism uses the PM runtime system. Poweroff is
|
||||
requested by clearing the power/pm_qos_no_power_off flag of the port device
|
||||
requested by clearing the ``power/pm_qos_no_power_off`` flag of the port device
|
||||
(defaults to 1). If the port is disconnected it will immediately receive a
|
||||
ClearPortFeature(PORT_POWER) request. Otherwise, it will honor the pm runtime
|
||||
rules and require the attached child device and all descendants to be suspended.
|
||||
This mechanism is dependent on the hub advertising port power switching in its
|
||||
hub descriptor (wHubCharacteristics logical power switching mode field).
|
||||
``ClearPortFeature(PORT_POWER)`` request. Otherwise, it will honor the pm
|
||||
runtime rules and require the attached child device and all descendants to be
|
||||
suspended. This mechanism is dependent on the hub advertising port power
|
||||
switching in its hub descriptor (wHubCharacteristics logical power switching
|
||||
mode field).
|
||||
|
||||
Note, some interface devices/drivers do not support autosuspend. Userspace may
|
||||
need to unbind the interface drivers before the usb_device will suspend. An
|
||||
unbound interface device is suspended by default. When unbinding, be careful
|
||||
to unbind interface drivers, not the driver of the parent usb device. Also,
|
||||
leave hub interface drivers bound. If the driver for the usb device (not
|
||||
interface) is unbound the kernel is no longer able to resume the device. If a
|
||||
hub interface driver is unbound, control of its child ports is lost and all
|
||||
attached child-devices will disconnect. A good rule of thumb is that if the
|
||||
'driver/module' link for a device points to /sys/module/usbcore then unbinding
|
||||
it will interfere with port power control.
|
||||
need to unbind the interface drivers before the :c:type:`usb_device` will
|
||||
suspend. An unbound interface device is suspended by default. When unbinding,
|
||||
be careful to unbind interface drivers, not the driver of the parent usb
|
||||
device. Also, leave hub interface drivers bound. If the driver for the usb
|
||||
device (not interface) is unbound the kernel is no longer able to resume the
|
||||
device. If a hub interface driver is unbound, control of its child ports is
|
||||
lost and all attached child-devices will disconnect. A good rule of thumb is
|
||||
that if the 'driver/module' link for a device points to
|
||||
``/sys/module/usbcore`` then unbinding it will interfere with port power
|
||||
control.
|
||||
|
||||
Example of the relevant files for port power control. Note, in this example
|
||||
these files are relative to a usb hub device (prefix).
|
||||
these files are relative to a usb hub device (prefix)::
|
||||
|
||||
prefix=/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
|
||||
|
||||
|
@ -631,10 +649,10 @@ these files are relative to a usb hub device (prefix).
|
|||
|
||||
In addition to these files some ports may have a 'peer' link to a port on
|
||||
another hub. The expectation is that all superspeed ports have a
|
||||
hi-speed peer.
|
||||
hi-speed peer::
|
||||
|
||||
$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
|
||||
../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
|
||||
$prefix/3-1:1.0/3-1-port1/peer -> ../../../../usb2/2-1/2-1:1.0/2-1-port1
|
||||
../../../../usb2/2-1/2-1:1.0/2-1-port1/peer -> ../../../../usb3/3-1/3-1:1.0/3-1-port1
|
||||
|
||||
Distinct from 'companion ports', or 'ehci/xhci shared switchover ports'
|
||||
peer ports are simply the hi-speed and superspeed interface pins that
|
||||
|
@ -645,24 +663,26 @@ While a superspeed port is powered off a device may downgrade its
|
|||
connection and attempt to connect to the hi-speed pins. The
|
||||
implementation takes steps to prevent this:
|
||||
|
||||
1/ Port suspend is sequenced to guarantee that hi-speed ports are powered-off
|
||||
1. Port suspend is sequenced to guarantee that hi-speed ports are powered-off
|
||||
before their superspeed peer is permitted to power-off. The implication is
|
||||
that the setting pm_qos_no_power_off to zero on a superspeed port may not cause
|
||||
the port to power-off until its highspeed peer has gone to its runtime suspend
|
||||
state. Userspace must take care to order the suspensions if it wants to
|
||||
guarantee that a superspeed port will power-off.
|
||||
that the setting ``pm_qos_no_power_off`` to zero on a superspeed port may
|
||||
not cause the port to power-off until its highspeed peer has gone to its
|
||||
runtime suspend state. Userspace must take care to order the suspensions
|
||||
if it wants to guarantee that a superspeed port will power-off.
|
||||
|
||||
2/ Port resume is sequenced to force a superspeed port to power-on prior to its
|
||||
2. Port resume is sequenced to force a superspeed port to power-on prior to its
|
||||
highspeed peer.
|
||||
|
||||
3/ Port resume always triggers an attached child device to resume. After a
|
||||
3. Port resume always triggers an attached child device to resume. After a
|
||||
power session is lost the device may have been removed, or need reset.
|
||||
Resuming the child device when the parent port regains power resolves those
|
||||
states and clamps the maximum port power cycle frequency at the rate the child
|
||||
device can suspend (autosuspend-delay) and resume (reset-resume latency).
|
||||
states and clamps the maximum port power cycle frequency at the rate the
|
||||
child device can suspend (autosuspend-delay) and resume (reset-resume
|
||||
latency).
|
||||
|
||||
Sysfs files relevant for port power control:
|
||||
<hubdev-portX>/power/pm_qos_no_power_off:
|
||||
|
||||
``<hubdev-portX>/power/pm_qos_no_power_off``:
|
||||
This writable flag controls the state of an idle port.
|
||||
Once all children and descendants have suspended the
|
||||
port may suspend/poweroff provided that
|
||||
|
@ -670,24 +690,24 @@ Sysfs files relevant for port power control:
|
|||
'1' the port will remain active/powered regardless of
|
||||
the stats of descendants. Defaults to 1.
|
||||
|
||||
<hubdev-portX>/power/runtime_status:
|
||||
``<hubdev-portX>/power/runtime_status``:
|
||||
This file reflects whether the port is 'active' (power is on)
|
||||
or 'suspended' (logically off). There is no indication to
|
||||
userspace whether VBUS is still supplied.
|
||||
|
||||
<hubdev-portX>/connect_type:
|
||||
``<hubdev-portX>/connect_type``:
|
||||
An advisory read-only flag to userspace indicating the
|
||||
location and connection type of the port. It returns
|
||||
one of four values 'hotplug', 'hardwired', 'not used',
|
||||
and 'unknown'. All values, besides unknown, are set by
|
||||
platform firmware.
|
||||
|
||||
"hotplug" indicates an externally connectable/visible
|
||||
``hotplug`` indicates an externally connectable/visible
|
||||
port on the platform. Typically userspace would choose
|
||||
to keep such a port powered to handle new device
|
||||
connection events.
|
||||
|
||||
"hardwired" refers to a port that is not visible but
|
||||
``hardwired`` refers to a port that is not visible but
|
||||
connectable. Examples are internal ports for USB
|
||||
bluetooth that can be disconnected via an external
|
||||
switch or a port with a hardwired USB camera. It is
|
||||
|
@ -698,48 +718,50 @@ Sysfs files relevant for port power control:
|
|||
powering off, or to activate the port prior to enabling
|
||||
connection via a switch.
|
||||
|
||||
"not used" refers to an internal port that is expected
|
||||
``not used`` refers to an internal port that is expected
|
||||
to never have a device connected to it. These may be
|
||||
empty internal ports, or ports that are not physically
|
||||
exposed on a platform. Considered safe to be
|
||||
powered-off at all times.
|
||||
|
||||
"unknown" means platform firmware does not provide
|
||||
``unknown`` means platform firmware does not provide
|
||||
information for this port. Most commonly refers to
|
||||
external hub ports which should be considered 'hotplug'
|
||||
for policy decisions.
|
||||
|
||||
NOTE1: since we are relying on the BIOS to get this ACPI
|
||||
information correct, the USB port descriptions may be
|
||||
missing or wrong.
|
||||
.. note::
|
||||
|
||||
NOTE2: Take care in clearing pm_qos_no_power_off. Once
|
||||
power is off this port will
|
||||
not respond to new connect events.
|
||||
- since we are relying on the BIOS to get this ACPI
|
||||
information correct, the USB port descriptions may
|
||||
be missing or wrong.
|
||||
|
||||
- Take care in clearing ``pm_qos_no_power_off``. Once
|
||||
power is off this port will
|
||||
not respond to new connect events.
|
||||
|
||||
Once a child device is attached additional constraints are
|
||||
applied before the port is allowed to poweroff.
|
||||
|
||||
<child>/power/control:
|
||||
Must be 'auto', and the port will not
|
||||
power down until <child>/power/runtime_status
|
||||
``<child>/power/control``:
|
||||
Must be ``auto``, and the port will not
|
||||
power down until ``<child>/power/runtime_status``
|
||||
reflects the 'suspended' state. Default
|
||||
value is controlled by child device driver.
|
||||
|
||||
<child>/power/persist:
|
||||
This defaults to '1' for most devices and indicates if
|
||||
``<child>/power/persist``:
|
||||
This defaults to ``1`` for most devices and indicates if
|
||||
kernel can persist the device's configuration across a
|
||||
power session loss (suspend / port-power event). When
|
||||
this value is '0' (quirky devices), port poweroff is
|
||||
this value is ``0`` (quirky devices), port poweroff is
|
||||
disabled.
|
||||
|
||||
<child>/driver/unbind:
|
||||
``<child>/driver/unbind``:
|
||||
Wakeup capable devices will block port poweroff. At
|
||||
this time the only mechanism to clear the usb-internal
|
||||
wakeup-capability for an interface device is to unbind
|
||||
its driver.
|
||||
|
||||
Summary of poweroff pre-requisite settings relative to a port device:
|
||||
Summary of poweroff pre-requisite settings relative to a port device::
|
||||
|
||||
echo 0 > power/pm_qos_no_power_off
|
||||
echo 0 > peer/power/pm_qos_no_power_off # if it exists
|
||||
|
@ -747,14 +769,14 @@ Summary of poweroff pre-requisite settings relative to a port device:
|
|||
echo auto > <child>/power/control
|
||||
echo 1 > <child>/power/persist # this is the default value
|
||||
|
||||
Suggested Userspace Port Power Policy
|
||||
-------------------------------------
|
||||
Suggested Userspace Port Power Policy
|
||||
-------------------------------------
|
||||
|
||||
As noted above userspace needs to be careful and deliberate about what
|
||||
ports are enabled for poweroff.
|
||||
|
||||
The default configuration is that all ports start with
|
||||
power/pm_qos_no_power_off set to '1' causing ports to always remain
|
||||
``power/pm_qos_no_power_off`` set to ``1`` causing ports to always remain
|
||||
active.
|
||||
|
||||
Given confidence in the platform firmware's description of the ports
|
||||
|
@ -764,7 +786,7 @@ done for 'hardwired' ports provided poweroff is coordinated with any
|
|||
connection switch for the port.
|
||||
|
||||
A more aggressive userspace policy is to enable USB port power off for
|
||||
all ports (set <hubdev-portX>/power/pm_qos_no_power_off to '0') when
|
||||
all ports (set ``<hubdev-portX>/power/pm_qos_no_power_off`` to ``0``) when
|
||||
some external factor indicates the user has stopped interacting with the
|
||||
system. For example, a distro may want to enable power off all USB
|
||||
ports when the screen blanks, and re-power them when the screen becomes
|
|
@ -1,3 +1,5 @@
|
|||
.. _usb-hostside-api:
|
||||
|
||||
===========================
|
||||
The Linux-USB Host Side API
|
||||
===========================
|
||||
|
@ -102,16 +104,21 @@ disconnect testing (while the device is active) with each different host
|
|||
controller driver, to make sure drivers don't have bugs of their own as
|
||||
well as to make sure they aren't relying on some HCD-specific behavior.
|
||||
|
||||
.. _usb_chapter9:
|
||||
|
||||
USB-Standard Types
|
||||
==================
|
||||
|
||||
In ``<linux/usb/ch9.h>`` you will find the USB data types defined in
|
||||
chapter 9 of the USB specification. These data types are used throughout
|
||||
USB, and in APIs including this host side API, gadget APIs, and usbfs.
|
||||
USB, and in APIs including this host side API, gadget APIs, usb character
|
||||
devices and debugfs interfaces.
|
||||
|
||||
.. kernel-doc:: include/linux/usb/ch9.h
|
||||
:internal:
|
||||
|
||||
.. _usb_header:
|
||||
|
||||
Host-Side Data Types and Macros
|
||||
===============================
|
||||
|
||||
|
@ -198,173 +205,110 @@ significantly reduce hcd-specific behaviors.
|
|||
.. kernel-doc:: drivers/usb/core/buffer.c
|
||||
:internal:
|
||||
|
||||
The USB Filesystem (usbfs)
|
||||
==========================
|
||||
The USB character device nodes
|
||||
==============================
|
||||
|
||||
This chapter presents the Linux *usbfs*. You may prefer to avoid writing
|
||||
new kernel code for your USB driver; that's the problem that usbfs set
|
||||
out to solve. User mode device drivers are usually packaged as
|
||||
applications or libraries, and may use usbfs through some programming
|
||||
library that wraps it. Such libraries include
|
||||
`libusb <http://libusb.sourceforge.net>`__ for C/C++, and
|
||||
`jUSB <http://jUSB.sourceforge.net>`__ for Java.
|
||||
This chapter presents the Linux character device nodes. You may prefer
|
||||
to avoid writing new kernel code for your USB driver. User mode device
|
||||
drivers are usually packaged as applications or libraries, and may use
|
||||
character devices through some programming library that wraps it.
|
||||
Such libraries include:
|
||||
|
||||
**Note**
|
||||
- `libusb <http://libusb.sourceforge.net>`__ for C/C++, and
|
||||
- `jUSB <http://jUSB.sourceforge.net>`__ for Java.
|
||||
|
||||
This particular documentation is incomplete, especially with respect
|
||||
to the asynchronous mode. As of kernel 2.5.66 the code and this
|
||||
(new) documentation need to be cross-reviewed.
|
||||
Some old information about it can be seen at the "USB Device Filesystem"
|
||||
section of the USB Guide. The latest copy of the USB Guide can be found
|
||||
at http://www.linux-usb.org/
|
||||
|
||||
Configure usbfs into Linux kernels by enabling the *USB filesystem*
|
||||
option (CONFIG_USB_DEVICEFS), and you get basic support for user mode
|
||||
USB device drivers. Until relatively recently it was often (confusingly)
|
||||
called *usbdevfs* although it wasn't solving what *devfs* was. Every USB
|
||||
device will appear in usbfs, regardless of whether or not it has a
|
||||
kernel driver.
|
||||
.. note::
|
||||
|
||||
What files are in "usbfs"?
|
||||
--------------------------
|
||||
- They were used to be implemented via *usbfs*, but this is not part of
|
||||
the sysfs debug interface.
|
||||
|
||||
Conventionally mounted at ``/proc/bus/usb``, usbfs features include:
|
||||
- This particular documentation is incomplete, especially with respect
|
||||
to the asynchronous mode. As of kernel 2.5.66 the code and this
|
||||
(new) documentation need to be cross-reviewed.
|
||||
|
||||
- ``/proc/bus/usb/devices`` ... a text file showing each of the USB
|
||||
devices on known to the kernel, and their configuration descriptors.
|
||||
You can also poll() this to learn about new devices.
|
||||
What files are in "devtmpfs"?
|
||||
-----------------------------
|
||||
|
||||
- ``/proc/bus/usb/BBB/DDD`` ... magic files exposing the each device's
|
||||
Conventionally mounted at ``/dev/bus/usb/``, usbfs features include:
|
||||
|
||||
- ``/dev/bus/usb/BBB/DDD`` ... magic files exposing the each device's
|
||||
configuration descriptors, and supporting a series of ioctls for
|
||||
making device requests, including I/O to devices. (Purely for access
|
||||
by programs.)
|
||||
|
||||
Each bus is given a number (BBB) based on when it was enumerated; within
|
||||
each bus, each device is given a similar number (DDD). Those BBB/DDD
|
||||
Each bus is given a number (``BBB``) based on when it was enumerated; within
|
||||
each bus, each device is given a similar number (``DDD``). Those ``BBB/DDD``
|
||||
paths are not "stable" identifiers; expect them to change even if you
|
||||
always leave the devices plugged in to the same hub port. *Don't even
|
||||
think of saving these in application configuration files.* Stable
|
||||
identifiers are available, for user mode applications that want to use
|
||||
them. HID and networking devices expose these stable IDs, so that for
|
||||
example you can be sure that you told the right UPS to power down its
|
||||
second server. "usbfs" doesn't (yet) expose those IDs.
|
||||
second server. Pleast note that it doesn't (yet) expose those IDs.
|
||||
|
||||
Mounting and Access Control
|
||||
---------------------------
|
||||
|
||||
There are a number of mount options for usbfs, which will be of most
|
||||
interest to you if you need to override the default access control
|
||||
policy. That policy is that only root may read or write device files
|
||||
(``/proc/bus/BBB/DDD``) although anyone may read the ``devices`` or
|
||||
``drivers`` files. I/O requests to the device also need the
|
||||
CAP_SYS_RAWIO capability,
|
||||
|
||||
The significance of that is that by default, all user mode device
|
||||
drivers need super-user privileges. You can change modes or ownership in
|
||||
a driver setup when the device hotplugs, or maye just start the driver
|
||||
right then, as a privileged server (or some activity within one). That's
|
||||
the most secure approach for multi-user systems, but for single user
|
||||
systems ("trusted" by that user) it's more convenient just to grant
|
||||
everyone all access (using the *devmode=0666* option) so the driver can
|
||||
start whenever it's needed.
|
||||
|
||||
The mount options for usbfs, usable in /etc/fstab or in command line
|
||||
invocations of *mount*, are:
|
||||
|
||||
*busgid*\ =NNNNN
|
||||
Controls the GID used for the /proc/bus/usb/BBB directories.
|
||||
(Default: 0)
|
||||
|
||||
*busmode*\ =MMM
|
||||
Controls the file mode used for the /proc/bus/usb/BBB directories.
|
||||
(Default: 0555)
|
||||
|
||||
*busuid*\ =NNNNN
|
||||
Controls the UID used for the /proc/bus/usb/BBB directories.
|
||||
(Default: 0)
|
||||
|
||||
*devgid*\ =NNNNN
|
||||
Controls the GID used for the /proc/bus/usb/BBB/DDD files. (Default:
|
||||
0)
|
||||
|
||||
*devmode*\ =MMM
|
||||
Controls the file mode used for the /proc/bus/usb/BBB/DDD files.
|
||||
(Default: 0644)
|
||||
|
||||
*devuid*\ =NNNNN
|
||||
Controls the UID used for the /proc/bus/usb/BBB/DDD files. (Default:
|
||||
0)
|
||||
|
||||
*listgid*\ =NNNNN
|
||||
Controls the GID used for the /proc/bus/usb/devices and drivers
|
||||
files. (Default: 0)
|
||||
|
||||
*listmode*\ =MMM
|
||||
Controls the file mode used for the /proc/bus/usb/devices and
|
||||
drivers files. (Default: 0444)
|
||||
|
||||
*listuid*\ =NNNNN
|
||||
Controls the UID used for the /proc/bus/usb/devices and drivers
|
||||
files. (Default: 0)
|
||||
|
||||
Note that many Linux distributions hard-wire the mount options for usbfs
|
||||
in their init scripts, such as ``/etc/rc.d/rc.sysinit``, rather than
|
||||
making it easy to set this per-system policy in ``/etc/fstab``.
|
||||
|
||||
/proc/bus/usb/devices
|
||||
---------------------
|
||||
|
||||
This file is handy for status viewing tools in user mode, which can scan
|
||||
the text format and ignore most of it. More detailed device status
|
||||
(including class and vendor status) is available from device-specific
|
||||
files. For information about the current format of this file, see the
|
||||
``Documentation/usb/proc_usb_info.txt`` file in your Linux kernel
|
||||
sources.
|
||||
|
||||
This file, in combination with the poll() system call, can also be used
|
||||
to detect when devices are added or removed:
|
||||
|
||||
::
|
||||
|
||||
int fd;
|
||||
struct pollfd pfd;
|
||||
|
||||
fd = open("/proc/bus/usb/devices", O_RDONLY);
|
||||
pfd = { fd, POLLIN, 0 };
|
||||
for (;;) {
|
||||
/* The first time through, this call will return immediately. */
|
||||
poll(&pfd, 1, -1);
|
||||
|
||||
/* To see what's changed, compare the file's previous and current
|
||||
contents or scan the filesystem. (Scanning is more precise.) */
|
||||
}
|
||||
|
||||
Note that this behavior is intended to be used for informational and
|
||||
debug purposes. It would be more appropriate to use programs such as
|
||||
udev or HAL to initialize a device or start a user-mode helper program,
|
||||
for instance.
|
||||
|
||||
/proc/bus/usb/BBB/DDD
|
||||
---------------------
|
||||
/dev/bus/usb/BBB/DDD
|
||||
--------------------
|
||||
|
||||
Use these files in one of these basic ways:
|
||||
|
||||
*They can be read,* producing first the device descriptor (18 bytes) and
|
||||
then the descriptors for the current configuration. See the USB 2.0 spec
|
||||
for details about those binary data formats. You'll need to convert most
|
||||
multibyte values from little endian format to your native host byte
|
||||
order, although a few of the fields in the device descriptor (both of
|
||||
the BCD-encoded fields, and the vendor and product IDs) will be
|
||||
byteswapped for you. Note that configuration descriptors include
|
||||
descriptors for interfaces, altsettings, endpoints, and maybe additional
|
||||
class descriptors.
|
||||
- *They can be read,* producing first the device descriptor (18 bytes) and
|
||||
then the descriptors for the current configuration. See the USB 2.0 spec
|
||||
for details about those binary data formats. You'll need to convert most
|
||||
multibyte values from little endian format to your native host byte
|
||||
order, although a few of the fields in the device descriptor (both of
|
||||
the BCD-encoded fields, and the vendor and product IDs) will be
|
||||
byteswapped for you. Note that configuration descriptors include
|
||||
descriptors for interfaces, altsettings, endpoints, and maybe additional
|
||||
class descriptors.
|
||||
|
||||
- *Perform USB operations* using *ioctl()* requests to make endpoint I/O
|
||||
requests (synchronously or asynchronously) or manage the device. These
|
||||
requests need the ``CAP_SYS_RAWIO`` capability, as well as filesystem
|
||||
access permissions. Only one ioctl request can be made on one of these
|
||||
device files at a time. This means that if you are synchronously reading
|
||||
an endpoint from one thread, you won't be able to write to a different
|
||||
endpoint from another thread until the read completes. This works for
|
||||
*half duplex* protocols, but otherwise you'd use asynchronous i/o
|
||||
requests.
|
||||
|
||||
Each connected USB device has one file. The ``BBB`` indicates the bus
|
||||
number. The ``DDD`` indicates the device address on that bus. Both
|
||||
of these numbers are assigned sequentially, and can be reused, so
|
||||
you can't rely on them for stable access to devices. For example,
|
||||
it's relatively common for devices to re-enumerate while they are
|
||||
still connected (perhaps someone jostled their power supply, hub,
|
||||
or USB cable), so a device might be ``002/027`` when you first connect
|
||||
it and ``002/048`` sometime later.
|
||||
|
||||
These files can be read as binary data. The binary data consists
|
||||
of first the device descriptor, then the descriptors for each
|
||||
configuration of the device. Multi-byte fields in the device descriptor
|
||||
are converted to host endianness by the kernel. The configuration
|
||||
descriptors are in bus endian format! The configuration descriptor
|
||||
are wTotalLength bytes apart. If a device returns less configuration
|
||||
descriptor data than indicated by wTotalLength there will be a hole in
|
||||
the file for the missing bytes. This information is also shown
|
||||
in text form by the ``/sys/kernel/debug/usb/devices`` file, described later.
|
||||
|
||||
These files may also be used to write user-level drivers for the USB
|
||||
devices. You would open the ``/dev/bus/usb/BBB/DDD`` file read/write,
|
||||
read its descriptors to make sure it's the device you expect, and then
|
||||
bind to an interface (or perhaps several) using an ioctl call. You
|
||||
would issue more ioctls to the device to communicate to it using
|
||||
control, bulk, or other kinds of USB transfers. The IOCTLs are
|
||||
listed in the ``<linux/usbdevice_fs.h>`` file, and at this writing the
|
||||
source code (``linux/drivers/usb/core/devio.c``) is the primary reference
|
||||
for how to access devices through those files.
|
||||
|
||||
Note that since by default these ``BBB/DDD`` files are writable only by
|
||||
root, only root can write such user mode drivers. You can selectively
|
||||
grant read/write permissions to other users by using ``chmod``. Also,
|
||||
usbfs mount options such as ``devmode=0666`` may be helpful.
|
||||
|
||||
*Perform USB operations* using *ioctl()* requests to make endpoint I/O
|
||||
requests (synchronously or asynchronously) or manage the device. These
|
||||
requests need the CAP_SYS_RAWIO capability, as well as filesystem
|
||||
access permissions. Only one ioctl request can be made on one of these
|
||||
device files at a time. This means that if you are synchronously reading
|
||||
an endpoint from one thread, you won't be able to write to a different
|
||||
endpoint from another thread until the read completes. This works for
|
||||
*half duplex* protocols, but otherwise you'd use asynchronous i/o
|
||||
requests.
|
||||
|
||||
Life Cycle of User Mode Drivers
|
||||
-------------------------------
|
||||
|
@ -372,7 +316,7 @@ Life Cycle of User Mode Drivers
|
|||
Such a driver first needs to find a device file for a device it knows
|
||||
how to handle. Maybe it was told about it because a ``/sbin/hotplug``
|
||||
event handling agent chose that driver to handle the new device. Or
|
||||
maybe it's an application that scans all the /proc/bus/usb device files,
|
||||
maybe it's an application that scans all the ``/dev/bus/usb`` device files,
|
||||
and ignores most devices. In either case, it should :c:func:`read()`
|
||||
all the descriptors from the device file, and check them against what it
|
||||
knows how to handle. It might just reject everything except a particular
|
||||
|
@ -407,9 +351,7 @@ The ioctl() Requests
|
|||
--------------------
|
||||
|
||||
To use these ioctls, you need to include the following headers in your
|
||||
userspace program:
|
||||
|
||||
::
|
||||
userspace program::
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usbdevice_fs.h>
|
||||
|
@ -422,8 +364,8 @@ header.
|
|||
Unless noted otherwise, the ioctl requests described here will update
|
||||
the modification time on the usbfs file to which they are applied
|
||||
(unless they fail). A return of zero indicates success; otherwise, a
|
||||
standard USB error code is returned. (These are documented in
|
||||
``Documentation/usb/error-codes.txt`` in your kernel sources.)
|
||||
standard USB error code is returned (These are documented in
|
||||
:ref:`usb-error-codes`).
|
||||
|
||||
Each of these files multiplexes access to several I/O streams, one per
|
||||
endpoint. Each device has one control endpoint (endpoint zero) which
|
||||
|
@ -458,14 +400,12 @@ USBDEVFS_CLAIMINTERFACE
|
|||
|
||||
USBDEVFS_CONNECTINFO
|
||||
Says whether the device is lowspeed. The ioctl parameter points to a
|
||||
structure like this:
|
||||
structure like this::
|
||||
|
||||
::
|
||||
|
||||
struct usbdevfs_connectinfo {
|
||||
unsigned int devnum;
|
||||
unsigned char slow;
|
||||
};
|
||||
struct usbdevfs_connectinfo {
|
||||
unsigned int devnum;
|
||||
unsigned char slow;
|
||||
};
|
||||
|
||||
File modification time is not updated by this request.
|
||||
|
||||
|
@ -477,45 +417,41 @@ USBDEVFS_CONNECTINFO
|
|||
USBDEVFS_GETDRIVER
|
||||
Returns the name of the kernel driver bound to a given interface (a
|
||||
string). Parameter is a pointer to this structure, which is
|
||||
modified:
|
||||
modified::
|
||||
|
||||
::
|
||||
|
||||
struct usbdevfs_getdriver {
|
||||
unsigned int interface;
|
||||
char driver[USBDEVFS_MAXDRIVERNAME + 1];
|
||||
};
|
||||
struct usbdevfs_getdriver {
|
||||
unsigned int interface;
|
||||
char driver[USBDEVFS_MAXDRIVERNAME + 1];
|
||||
};
|
||||
|
||||
File modification time is not updated by this request.
|
||||
|
||||
USBDEVFS_IOCTL
|
||||
Passes a request from userspace through to a kernel driver that has
|
||||
an ioctl entry in the *struct usb_driver* it registered.
|
||||
an ioctl entry in the *struct usb_driver* it registered::
|
||||
|
||||
::
|
||||
struct usbdevfs_ioctl {
|
||||
int ifno;
|
||||
int ioctl_code;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct usbdevfs_ioctl {
|
||||
int ifno;
|
||||
int ioctl_code;
|
||||
void *data;
|
||||
};
|
||||
/* user mode call looks like this.
|
||||
* 'request' becomes the driver->ioctl() 'code' parameter.
|
||||
* the size of 'param' is encoded in 'request', and that data
|
||||
* is copied to or from the driver->ioctl() 'buf' parameter.
|
||||
*/
|
||||
static int
|
||||
usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
|
||||
{
|
||||
struct usbdevfs_ioctl wrapper;
|
||||
|
||||
/* user mode call looks like this.
|
||||
* 'request' becomes the driver->ioctl() 'code' parameter.
|
||||
* the size of 'param' is encoded in 'request', and that data
|
||||
* is copied to or from the driver->ioctl() 'buf' parameter.
|
||||
*/
|
||||
static int
|
||||
usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
|
||||
{
|
||||
struct usbdevfs_ioctl wrapper;
|
||||
wrapper.ifno = ifno;
|
||||
wrapper.ioctl_code = request;
|
||||
wrapper.data = param;
|
||||
|
||||
wrapper.ifno = ifno;
|
||||
wrapper.ioctl_code = request;
|
||||
wrapper.data = param;
|
||||
|
||||
return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
|
||||
}
|
||||
return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
|
||||
}
|
||||
|
||||
File modification time is not updated by this request.
|
||||
|
||||
|
@ -534,11 +470,11 @@ USBDEVFS_RELEASEINTERFACE
|
|||
the number of the interface (bInterfaceNumber from descriptor); File
|
||||
modification time is not updated by this request.
|
||||
|
||||
**Warning**
|
||||
.. warning::
|
||||
|
||||
*No security check is made to ensure that the task which made
|
||||
the claim is the one which is releasing it. This means that user
|
||||
mode driver may interfere other ones.*
|
||||
*No security check is made to ensure that the task which made
|
||||
the claim is the one which is releasing it. This means that user
|
||||
mode driver may interfere other ones.*
|
||||
|
||||
USBDEVFS_RESETEP
|
||||
Resets the data toggle value for an endpoint (bulk or interrupt) to
|
||||
|
@ -546,13 +482,13 @@ USBDEVFS_RESETEP
|
|||
as identified in the endpoint descriptor), with USB_DIR_IN added
|
||||
if the device's endpoint sends data to the host.
|
||||
|
||||
**Warning**
|
||||
.. Warning::
|
||||
|
||||
*Avoid using this request. It should probably be removed.* Using
|
||||
it typically means the device and driver will lose toggle
|
||||
synchronization. If you really lost synchronization, you likely
|
||||
need to completely handshake with the device, using a request
|
||||
like CLEAR_HALT or SET_INTERFACE.
|
||||
*Avoid using this request. It should probably be removed.* Using
|
||||
it typically means the device and driver will lose toggle
|
||||
synchronization. If you really lost synchronization, you likely
|
||||
need to completely handshake with the device, using a request
|
||||
like CLEAR_HALT or SET_INTERFACE.
|
||||
|
||||
USBDEVFS_DROP_PRIVILEGES
|
||||
This is used to relinquish the ability to do certain operations
|
||||
|
@ -574,21 +510,19 @@ a time.
|
|||
|
||||
USBDEVFS_BULK
|
||||
Issues a bulk read or write request to the device. The ioctl
|
||||
parameter is a pointer to this structure:
|
||||
parameter is a pointer to this structure::
|
||||
|
||||
::
|
||||
struct usbdevfs_bulktransfer {
|
||||
unsigned int ep;
|
||||
unsigned int len;
|
||||
unsigned int timeout; /* in milliseconds */
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct usbdevfs_bulktransfer {
|
||||
unsigned int ep;
|
||||
unsigned int len;
|
||||
unsigned int timeout; /* in milliseconds */
|
||||
void *data;
|
||||
};
|
||||
|
||||
The "ep" value identifies a bulk endpoint number (1 to 15, as
|
||||
The ``ep`` value identifies a bulk endpoint number (1 to 15, as
|
||||
identified in an endpoint descriptor), masked with USB_DIR_IN when
|
||||
referring to an endpoint which sends data to the host from the
|
||||
device. The length of the data buffer is identified by "len"; Recent
|
||||
device. The length of the data buffer is identified by ``len``; Recent
|
||||
kernels support requests up to about 128KBytes. *FIXME say how read
|
||||
length is returned, and how short reads are handled.*.
|
||||
|
||||
|
@ -600,31 +534,29 @@ USBDEVFS_CLEAR_HALT
|
|||
which sends data to the host from the device.
|
||||
|
||||
Use this on bulk or interrupt endpoints which have stalled,
|
||||
returning *-EPIPE* status to a data transfer request. Do not issue
|
||||
returning ``-EPIPE`` status to a data transfer request. Do not issue
|
||||
the control request directly, since that could invalidate the host's
|
||||
record of the data toggle.
|
||||
|
||||
USBDEVFS_CONTROL
|
||||
Issues a control request to the device. The ioctl parameter points
|
||||
to a structure like this:
|
||||
to a structure like this::
|
||||
|
||||
::
|
||||
|
||||
struct usbdevfs_ctrltransfer {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__u16 wValue;
|
||||
__u16 wIndex;
|
||||
__u16 wLength;
|
||||
__u32 timeout; /* in milliseconds */
|
||||
void *data;
|
||||
};
|
||||
struct usbdevfs_ctrltransfer {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__u16 wValue;
|
||||
__u16 wIndex;
|
||||
__u16 wLength;
|
||||
__u32 timeout; /* in milliseconds */
|
||||
void *data;
|
||||
};
|
||||
|
||||
The first eight bytes of this structure are the contents of the
|
||||
SETUP packet to be sent to the device; see the USB 2.0 specification
|
||||
for details. The bRequestType value is composed by combining a
|
||||
USB_TYPE_\* value, a USB_DIR_\* value, and a USB_RECIP_\*
|
||||
value (from *<linux/usb.h>*). If wLength is nonzero, it describes
|
||||
``USB_TYPE_*`` value, a ``USB_DIR_*`` value, and a ``USB_RECIP_*``
|
||||
value (from ``linux/usb.h``). If wLength is nonzero, it describes
|
||||
the length of the data buffer, which is either written to the device
|
||||
(USB_DIR_OUT) or read from the device (USB_DIR_IN).
|
||||
|
||||
|
@ -638,22 +570,20 @@ USBDEVFS_RESET
|
|||
the reset, this rebinds all device interfaces. File modification
|
||||
time is not updated by this request.
|
||||
|
||||
**Warning**
|
||||
.. warning::
|
||||
|
||||
*Avoid using this call* until some usbcore bugs get fixed, since
|
||||
it does not fully synchronize device, interface, and driver (not
|
||||
just usbfs) state.
|
||||
*Avoid using this call* until some usbcore bugs get fixed, since
|
||||
it does not fully synchronize device, interface, and driver (not
|
||||
just usbfs) state.
|
||||
|
||||
USBDEVFS_SETINTERFACE
|
||||
Sets the alternate setting for an interface. The ioctl parameter is
|
||||
a pointer to a structure like this:
|
||||
a pointer to a structure like this::
|
||||
|
||||
::
|
||||
|
||||
struct usbdevfs_setinterface {
|
||||
unsigned int interface;
|
||||
unsigned int altsetting;
|
||||
};
|
||||
struct usbdevfs_setinterface {
|
||||
unsigned int interface;
|
||||
unsigned int altsetting;
|
||||
};
|
||||
|
||||
File modification time is not updated by this request.
|
||||
|
||||
|
@ -669,11 +599,11 @@ USBDEVFS_SETCONFIGURATION
|
|||
configuration (bConfigurationValue from descriptor). File
|
||||
modification time is not updated by this request.
|
||||
|
||||
**Warning**
|
||||
.. warning::
|
||||
|
||||
*Avoid using this call* until some usbcore bugs get fixed, since
|
||||
it does not fully synchronize device, interface, and driver (not
|
||||
just usbfs) state.
|
||||
*Avoid using this call* until some usbcore bugs get fixed, since
|
||||
it does not fully synchronize device, interface, and driver (not
|
||||
just usbfs) state.
|
||||
|
||||
Asynchronous I/O Support
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -688,7 +618,7 @@ the blocking is separate.
|
|||
|
||||
These requests are packaged into a structure that resembles the URB used
|
||||
by kernel device drivers. (No POSIX Async I/O support here, sorry.) It
|
||||
identifies the endpoint type (USBDEVFS_URB_TYPE_\*), endpoint
|
||||
identifies the endpoint type (``USBDEVFS_URB_TYPE_*``), endpoint
|
||||
(number, masked with USB_DIR_IN as appropriate), buffer and length,
|
||||
and a user "context" value serving to uniquely identify each request.
|
||||
(It's usually a pointer to per-request data.) Flags can modify requests
|
||||
|
@ -702,30 +632,28 @@ When usbfs returns these urbs, the status value is updated, and the
|
|||
buffer may have been modified. Except for isochronous transfers, the
|
||||
actual_length is updated to say how many bytes were transferred; if the
|
||||
USBDEVFS_URB_DISABLE_SPD flag is set ("short packets are not OK"), if
|
||||
fewer bytes were read than were requested then you get an error report.
|
||||
|
||||
::
|
||||
fewer bytes were read than were requested then you get an error report::
|
||||
|
||||
struct usbdevfs_iso_packet_desc {
|
||||
unsigned int length;
|
||||
unsigned int actual_length;
|
||||
unsigned int status;
|
||||
unsigned int length;
|
||||
unsigned int actual_length;
|
||||
unsigned int status;
|
||||
};
|
||||
|
||||
struct usbdevfs_urb {
|
||||
unsigned char type;
|
||||
unsigned char endpoint;
|
||||
int status;
|
||||
unsigned int flags;
|
||||
void *buffer;
|
||||
int buffer_length;
|
||||
int actual_length;
|
||||
int start_frame;
|
||||
int number_of_packets;
|
||||
int error_count;
|
||||
unsigned int signr;
|
||||
void *usercontext;
|
||||
struct usbdevfs_iso_packet_desc iso_frame_desc[];
|
||||
unsigned char type;
|
||||
unsigned char endpoint;
|
||||
int status;
|
||||
unsigned int flags;
|
||||
void *buffer;
|
||||
int buffer_length;
|
||||
int actual_length;
|
||||
int start_frame;
|
||||
int number_of_packets;
|
||||
int error_count;
|
||||
unsigned int signr;
|
||||
void *usercontext;
|
||||
struct usbdevfs_iso_packet_desc iso_frame_desc[];
|
||||
};
|
||||
|
||||
For these asynchronous requests, the file modification time reflects
|
||||
|
@ -746,3 +674,374 @@ USBDEVFS_REAPURBNDELAY
|
|||
|
||||
USBDEVFS_SUBMITURB
|
||||
*TBS*
|
||||
|
||||
The USB devices
|
||||
===============
|
||||
|
||||
The USB devices are now exported via debugfs:
|
||||
|
||||
- ``/sys/kernel/debug/usb/devices`` ... a text file showing each of the USB
|
||||
devices on known to the kernel, and their configuration descriptors.
|
||||
You can also poll() this to learn about new devices.
|
||||
|
||||
/sys/kernel/debug/usb/devices
|
||||
-----------------------------
|
||||
|
||||
This file is handy for status viewing tools in user mode, which can scan
|
||||
the text format and ignore most of it. More detailed device status
|
||||
(including class and vendor status) is available from device-specific
|
||||
files. For information about the current format of this file, see the
|
||||
``Documentation/usb/proc_usb_info.txt`` file in your Linux kernel
|
||||
sources.
|
||||
|
||||
This file, in combination with the poll() system call, can also be used
|
||||
to detect when devices are added or removed::
|
||||
|
||||
int fd;
|
||||
struct pollfd pfd;
|
||||
|
||||
fd = open("/sys/kernel/debug/usb/devices", O_RDONLY);
|
||||
pfd = { fd, POLLIN, 0 };
|
||||
for (;;) {
|
||||
/* The first time through, this call will return immediately. */
|
||||
poll(&pfd, 1, -1);
|
||||
|
||||
/* To see what's changed, compare the file's previous and current
|
||||
contents or scan the filesystem. (Scanning is more precise.) */
|
||||
}
|
||||
|
||||
Note that this behavior is intended to be used for informational and
|
||||
debug purposes. It would be more appropriate to use programs such as
|
||||
udev or HAL to initialize a device or start a user-mode helper program,
|
||||
for instance.
|
||||
|
||||
In this file, each device's output has multiple lines of ASCII output.
|
||||
|
||||
I made it ASCII instead of binary on purpose, so that someone
|
||||
can obtain some useful data from it without the use of an
|
||||
auxiliary program. However, with an auxiliary program, the numbers
|
||||
in the first 4 columns of each ``T:`` line (topology info:
|
||||
Lev, Prnt, Port, Cnt) can be used to build a USB topology diagram.
|
||||
|
||||
Each line is tagged with a one-character ID for that line::
|
||||
|
||||
T = Topology (etc.)
|
||||
B = Bandwidth (applies only to USB host controllers, which are
|
||||
virtualized as root hubs)
|
||||
D = Device descriptor info.
|
||||
P = Product ID info. (from Device descriptor, but they won't fit
|
||||
together on one line)
|
||||
S = String descriptors.
|
||||
C = Configuration descriptor info. (* = active configuration)
|
||||
I = Interface descriptor info.
|
||||
E = Endpoint descriptor info.
|
||||
|
||||
/sys/kernel/debug/usb/devices output format
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Legend::
|
||||
d = decimal number (may have leading spaces or 0's)
|
||||
x = hexadecimal number (may have leading spaces or 0's)
|
||||
s = string
|
||||
|
||||
|
||||
|
||||
Topology info
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
|
||||
| | | | | | | | |__MaxChildren
|
||||
| | | | | | | |__Device Speed in Mbps
|
||||
| | | | | | |__DeviceNumber
|
||||
| | | | | |__Count of devices at this level
|
||||
| | | | |__Connector/Port on Parent for this device
|
||||
| | | |__Parent DeviceNumber
|
||||
| | |__Level in topology for this bus
|
||||
| |__Bus number
|
||||
|__Topology info tag
|
||||
|
||||
Speed may be:
|
||||
|
||||
======= ======================================================
|
||||
1.5 Mbit/s for low speed USB
|
||||
12 Mbit/s for full speed USB
|
||||
480 Mbit/s for high speed USB (added for USB 2.0);
|
||||
also used for Wireless USB, which has no fixed speed
|
||||
5000 Mbit/s for SuperSpeed USB (added for USB 3.0)
|
||||
======= ======================================================
|
||||
|
||||
For reasons lost in the mists of time, the Port number is always
|
||||
too low by 1. For example, a device plugged into port 4 will
|
||||
show up with ``Port=03``.
|
||||
|
||||
Bandwidth info
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
|
||||
| | | |__Number of isochronous requests
|
||||
| | |__Number of interrupt requests
|
||||
| |__Total Bandwidth allocated to this bus
|
||||
|__Bandwidth info tag
|
||||
|
||||
Bandwidth allocation is an approximation of how much of one frame
|
||||
(millisecond) is in use. It reflects only periodic transfers, which
|
||||
are the only transfers that reserve bandwidth. Control and bulk
|
||||
transfers use all other bandwidth, including reserved bandwidth that
|
||||
is not used for transfers (such as for short packets).
|
||||
|
||||
The percentage is how much of the "reserved" bandwidth is scheduled by
|
||||
those transfers. For a low or full speed bus (loosely, "USB 1.1"),
|
||||
90% of the bus bandwidth is reserved. For a high speed bus (loosely,
|
||||
"USB 2.0") 80% is reserved.
|
||||
|
||||
|
||||
Device descriptor info & Product ID info
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
D: Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
|
||||
P: Vendor=xxxx ProdID=xxxx Rev=xx.xx
|
||||
|
||||
where::
|
||||
|
||||
D: Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
|
||||
| | | | | | |__NumberConfigurations
|
||||
| | | | | |__MaxPacketSize of Default Endpoint
|
||||
| | | | |__DeviceProtocol
|
||||
| | | |__DeviceSubClass
|
||||
| | |__DeviceClass
|
||||
| |__Device USB version
|
||||
|__Device info tag #1
|
||||
|
||||
where::
|
||||
|
||||
P: Vendor=xxxx ProdID=xxxx Rev=xx.xx
|
||||
| | | |__Product revision number
|
||||
| | |__Product ID code
|
||||
| |__Vendor ID code
|
||||
|__Device info tag #2
|
||||
|
||||
|
||||
String descriptor info
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
::
|
||||
|
||||
S: Manufacturer=ssss
|
||||
| |__Manufacturer of this device as read from the device.
|
||||
| For USB host controller drivers (virtual root hubs) this may
|
||||
| be omitted, or (for newer drivers) will identify the kernel
|
||||
| version and the driver which provides this hub emulation.
|
||||
|__String info tag
|
||||
|
||||
S: Product=ssss
|
||||
| |__Product description of this device as read from the device.
|
||||
| For older USB host controller drivers (virtual root hubs) this
|
||||
| indicates the driver; for newer ones, it's a product (and vendor)
|
||||
| description that often comes from the kernel's PCI ID database.
|
||||
|__String info tag
|
||||
|
||||
S: SerialNumber=ssss
|
||||
| |__Serial Number of this device as read from the device.
|
||||
| For USB host controller drivers (virtual root hubs) this is
|
||||
| some unique ID, normally a bus ID (address or slot name) that
|
||||
| can't be shared with any other device.
|
||||
|__String info tag
|
||||
|
||||
|
||||
|
||||
Configuration descriptor info
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
::
|
||||
|
||||
C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
|
||||
| | | | | |__MaxPower in mA
|
||||
| | | | |__Attributes
|
||||
| | | |__ConfiguratioNumber
|
||||
| | |__NumberOfInterfaces
|
||||
| |__ "*" indicates the active configuration (others are " ")
|
||||
|__Config info tag
|
||||
|
||||
USB devices may have multiple configurations, each of which act
|
||||
rather differently. For example, a bus-powered configuration
|
||||
might be much less capable than one that is self-powered. Only
|
||||
one device configuration can be active at a time; most devices
|
||||
have only one configuration.
|
||||
|
||||
Each configuration consists of one or more interfaces. Each
|
||||
interface serves a distinct "function", which is typically bound
|
||||
to a different USB device driver. One common example is a USB
|
||||
speaker with an audio interface for playback, and a HID interface
|
||||
for use with software volume control.
|
||||
|
||||
Interface descriptor info (can be multiple per Config)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
::
|
||||
|
||||
I:* If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
|
||||
| | | | | | | | |__Driver name
|
||||
| | | | | | | | or "(none)"
|
||||
| | | | | | | |__InterfaceProtocol
|
||||
| | | | | | |__InterfaceSubClass
|
||||
| | | | | |__InterfaceClass
|
||||
| | | | |__NumberOfEndpoints
|
||||
| | | |__AlternateSettingNumber
|
||||
| | |__InterfaceNumber
|
||||
| |__ "*" indicates the active altsetting (others are " ")
|
||||
|__Interface info tag
|
||||
|
||||
A given interface may have one or more "alternate" settings.
|
||||
For example, default settings may not use more than a small
|
||||
amount of periodic bandwidth. To use significant fractions
|
||||
of bus bandwidth, drivers must select a non-default altsetting.
|
||||
|
||||
Only one setting for an interface may be active at a time, and
|
||||
only one driver may bind to an interface at a time. Most devices
|
||||
have only one alternate setting per interface.
|
||||
|
||||
|
||||
Endpoint descriptor info (can be multiple per Interface)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddss
|
||||
| | | | |__Interval (max) between transfers
|
||||
| | | |__EndpointMaxPacketSize
|
||||
| | |__Attributes(EndpointType)
|
||||
| |__EndpointAddress(I=In,O=Out)
|
||||
|__Endpoint info tag
|
||||
|
||||
The interval is nonzero for all periodic (interrupt or isochronous)
|
||||
endpoints. For high speed endpoints the transfer interval may be
|
||||
measured in microseconds rather than milliseconds.
|
||||
|
||||
For high speed periodic endpoints, the ``EndpointMaxPacketSize`` reflects
|
||||
the per-microframe data transfer size. For "high bandwidth"
|
||||
endpoints, that can reflect two or three packets (for up to
|
||||
3KBytes every 125 usec) per endpoint.
|
||||
|
||||
With the Linux-USB stack, periodic bandwidth reservations use the
|
||||
transfer intervals and sizes provided by URBs, which can be less
|
||||
than those found in endpoint descriptor.
|
||||
|
||||
Usage examples
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
If a user or script is interested only in Topology info, for
|
||||
example, use something like ``grep ^T: /sys/kernel/debug/usb/devices``
|
||||
for only the Topology lines. A command like
|
||||
``grep -i ^[tdp]: /sys/kernel/debug/usb/devices`` can be used to list
|
||||
only the lines that begin with the characters in square brackets,
|
||||
where the valid characters are TDPCIE. With a slightly more able
|
||||
script, it can display any selected lines (for example, only T, D,
|
||||
and P lines) and change their output format. (The ``procusb``
|
||||
Perl script is the beginning of this idea. It will list only
|
||||
selected lines [selected from TBDPSCIE] or "All" lines from
|
||||
``/sys/kernel/debug/usb/devices``.)
|
||||
|
||||
The Topology lines can be used to generate a graphic/pictorial
|
||||
of the USB devices on a system's root hub. (See more below
|
||||
on how to do this.)
|
||||
|
||||
The Interface lines can be used to determine what driver is
|
||||
being used for each device, and which altsetting it activated.
|
||||
|
||||
The Configuration lines could be used to list maximum power
|
||||
(in milliamps) that a system's USB devices are using.
|
||||
For example, ``grep ^C: /sys/kernel/debug/usb/devices``.
|
||||
|
||||
|
||||
Here's an example, from a system which has a UHCI root hub,
|
||||
an external hub connected to the root hub, and a mouse and
|
||||
a serial converter connected to the external hub.
|
||||
|
||||
::
|
||||
|
||||
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
|
||||
B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0
|
||||
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
|
||||
P: Vendor=0000 ProdID=0000 Rev= 0.00
|
||||
S: Product=USB UHCI Root Hub
|
||||
S: SerialNumber=dce0
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
|
||||
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
|
||||
|
||||
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
|
||||
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
|
||||
P: Vendor=0451 ProdID=1446 Rev= 1.00
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
|
||||
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
|
||||
|
||||
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
|
||||
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
|
||||
P: Vendor=04b4 ProdID=0001 Rev= 0.00
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
|
||||
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms
|
||||
|
||||
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
|
||||
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
|
||||
P: Vendor=0565 ProdID=0001 Rev= 1.08
|
||||
S: Manufacturer=Peracom Networks, Inc.
|
||||
S: Product=Peracom USB to Serial Converter
|
||||
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
|
||||
I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
|
||||
E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl= 16ms
|
||||
E: Ad=01(O) Atr=02(Bulk) MxPS= 16 Ivl= 16ms
|
||||
E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms
|
||||
|
||||
|
||||
Selecting only the ``T:`` and ``I:`` lines from this (for example, by using
|
||||
``procusb ti``), we have
|
||||
|
||||
::
|
||||
|
||||
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
|
||||
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
|
||||
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
|
||||
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
|
||||
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
|
||||
I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
|
||||
|
||||
|
||||
Physically this looks like (or could be converted to)::
|
||||
|
||||
+------------------+
|
||||
| PC/root_hub (12)| Dev# = 1
|
||||
+------------------+ (nn) is Mbps.
|
||||
Level 0 | CN.0 | CN.1 | [CN = connector/port #]
|
||||
+------------------+
|
||||
/
|
||||
/
|
||||
+-----------------------+
|
||||
Level 1 | Dev#2: 4-port hub (12)|
|
||||
+-----------------------+
|
||||
|CN.0 |CN.1 |CN.2 |CN.3 |
|
||||
+-----------------------+
|
||||
\ \____________________
|
||||
\_____ \
|
||||
\ \
|
||||
+--------------------+ +--------------------+
|
||||
Level 2 | Dev# 3: mouse (1.5)| | Dev# 4: serial (12)|
|
||||
+--------------------+ +--------------------+
|
||||
|
||||
|
||||
|
||||
Or, in a more tree-like structure (ports [Connectors] without
|
||||
connections could be omitted)::
|
||||
|
||||
PC: Dev# 1, root hub, 2 ports, 12 Mbps
|
||||
|_ CN.0: Dev# 2, hub, 4 ports, 12 Mbps
|
||||
|_ CN.0: Dev #3, mouse, 1.5 Mbps
|
||||
|_ CN.1:
|
||||
|_ CN.2: Dev #4, serial, 12 Mbps
|
||||
|_ CN.3:
|
||||
|_ CN.1:
|
723
Documentation/driver-api/usb/writing_musb_glue_layer.rst
Normal file
723
Documentation/driver-api/usb/writing_musb_glue_layer.rst
Normal file
|
@ -0,0 +1,723 @@
|
|||
=========================
|
||||
Writing a MUSB Glue Layer
|
||||
=========================
|
||||
|
||||
:Author: Apelete Seketeli
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The Linux MUSB subsystem is part of the larger Linux USB subsystem. It
|
||||
provides support for embedded USB Device Controllers (UDC) that do not
|
||||
use Universal Host Controller Interface (UHCI) or Open Host Controller
|
||||
Interface (OHCI).
|
||||
|
||||
Instead, these embedded UDC rely on the USB On-the-Go (OTG)
|
||||
specification which they implement at least partially. The silicon
|
||||
reference design used in most cases is the Multipoint USB Highspeed
|
||||
Dual-Role Controller (MUSB HDRC) found in the Mentor Graphics Inventra™
|
||||
design.
|
||||
|
||||
As a self-taught exercise I have written an MUSB glue layer for the
|
||||
Ingenic JZ4740 SoC, modelled after the many MUSB glue layers in the
|
||||
kernel source tree. This layer can be found at
|
||||
``drivers/usb/musb/jz4740.c``. In this documentation I will walk through the
|
||||
basics of the ``jz4740.c`` glue layer, explaining the different pieces and
|
||||
what needs to be done in order to write your own device glue layer.
|
||||
|
||||
.. _musb-basics:
|
||||
|
||||
Linux MUSB Basics
|
||||
=================
|
||||
|
||||
To get started on the topic, please read USB On-the-Go Basics (see
|
||||
Resources) which provides an introduction of USB OTG operation at the
|
||||
hardware level. A couple of wiki pages by Texas Instruments and Analog
|
||||
Devices also provide an overview of the Linux kernel MUSB configuration,
|
||||
albeit focused on some specific devices provided by these companies.
|
||||
Finally, getting acquainted with the USB specification at USB home page
|
||||
may come in handy, with practical instance provided through the Writing
|
||||
USB Device Drivers documentation (again, see Resources).
|
||||
|
||||
Linux USB stack is a layered architecture in which the MUSB controller
|
||||
hardware sits at the lowest. The MUSB controller driver abstract the
|
||||
MUSB controller hardware to the Linux USB stack::
|
||||
|
||||
------------------------
|
||||
| | <------- drivers/usb/gadget
|
||||
| Linux USB Core Stack | <------- drivers/usb/host
|
||||
| | <------- drivers/usb/core
|
||||
------------------------
|
||||
⬍
|
||||
--------------------------
|
||||
| | <------ drivers/usb/musb/musb_gadget.c
|
||||
| MUSB Controller driver | <------ drivers/usb/musb/musb_host.c
|
||||
| | <------ drivers/usb/musb/musb_core.c
|
||||
--------------------------
|
||||
⬍
|
||||
---------------------------------
|
||||
| MUSB Platform Specific Driver |
|
||||
| | <-- drivers/usb/musb/jz4740.c
|
||||
| aka "Glue Layer" |
|
||||
---------------------------------
|
||||
⬍
|
||||
---------------------------------
|
||||
| MUSB Controller Hardware |
|
||||
---------------------------------
|
||||
|
||||
As outlined above, the glue layer is actually the platform specific code
|
||||
sitting in between the controller driver and the controller hardware.
|
||||
|
||||
Just like a Linux USB driver needs to register itself with the Linux USB
|
||||
subsystem, the MUSB glue layer needs first to register itself with the
|
||||
MUSB controller driver. This will allow the controller driver to know
|
||||
about which device the glue layer supports and which functions to call
|
||||
when a supported device is detected or released; remember we are talking
|
||||
about an embedded controller chip here, so no insertion or removal at
|
||||
run-time.
|
||||
|
||||
All of this information is passed to the MUSB controller driver through
|
||||
a :c:type:`platform_driver` structure defined in the glue layer as::
|
||||
|
||||
static struct platform_driver jz4740_driver = {
|
||||
.probe = jz4740_probe,
|
||||
.remove = jz4740_remove,
|
||||
.driver = {
|
||||
.name = "musb-jz4740",
|
||||
},
|
||||
};
|
||||
|
||||
The probe and remove function pointers are called when a matching device
|
||||
is detected and, respectively, released. The name string describes the
|
||||
device supported by this glue layer. In the current case it matches a
|
||||
platform_device structure declared in ``arch/mips/jz4740/platform.c``. Note
|
||||
that we are not using device tree bindings here.
|
||||
|
||||
In order to register itself to the controller driver, the glue layer
|
||||
goes through a few steps, basically allocating the controller hardware
|
||||
resources and initialising a couple of circuits. To do so, it needs to
|
||||
keep track of the information used throughout these steps. This is done
|
||||
by defining a private ``jz4740_glue`` structure::
|
||||
|
||||
struct jz4740_glue {
|
||||
struct device *dev;
|
||||
struct platform_device *musb;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
|
||||
The dev and musb members are both device structure variables. The first
|
||||
one holds generic information about the device, since it's the basic
|
||||
device structure, and the latter holds information more closely related
|
||||
to the subsystem the device is registered to. The clk variable keeps
|
||||
information related to the device clock operation.
|
||||
|
||||
Let's go through the steps of the probe function that leads the glue
|
||||
layer to register itself to the controller driver.
|
||||
|
||||
.. note::
|
||||
|
||||
For the sake of readability each function will be split in logical
|
||||
parts, each part being shown as if it was independent from the others.
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 8,12,18
|
||||
|
||||
static int jz4740_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct platform_device *musb;
|
||||
struct jz4740_glue *glue;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
|
||||
if (!glue)
|
||||
return -ENOMEM;
|
||||
|
||||
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
|
||||
if (!musb) {
|
||||
dev_err(&pdev->dev, "failed to allocate musb device\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
clk = devm_clk_get(&pdev->dev, "udc");
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
ret = PTR_ERR(clk);
|
||||
goto err_platform_device_put;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable clock\n");
|
||||
goto err_platform_device_put;
|
||||
}
|
||||
|
||||
musb->dev.parent = &pdev->dev;
|
||||
|
||||
glue->dev = &pdev->dev;
|
||||
glue->musb = musb;
|
||||
glue->clk = clk;
|
||||
|
||||
return 0;
|
||||
|
||||
err_platform_device_put:
|
||||
platform_device_put(musb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
The first few lines of the probe function allocate and assign the glue,
|
||||
musb and clk variables. The ``GFP_KERNEL`` flag (line 8) allows the
|
||||
allocation process to sleep and wait for memory, thus being usable in a
|
||||
locking situation. The ``PLATFORM_DEVID_AUTO`` flag (line 12) allows
|
||||
automatic allocation and management of device IDs in order to avoid
|
||||
device namespace collisions with explicit IDs. With :c:func:`devm_clk_get`
|
||||
(line 18) the glue layer allocates the clock -- the ``devm_`` prefix
|
||||
indicates that :c:func:`clk_get` is managed: it automatically frees the
|
||||
allocated clock resource data when the device is released -- and enable
|
||||
it.
|
||||
|
||||
|
||||
|
||||
Then comes the registration steps:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 3,5,7,9,16
|
||||
|
||||
static int jz4740_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data;
|
||||
|
||||
pdata->platform_ops = &jz4740_musb_ops;
|
||||
|
||||
platform_set_drvdata(pdev, glue);
|
||||
|
||||
ret = platform_device_add_resources(musb, pdev->resource,
|
||||
pdev->num_resources);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add resources\n");
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add platform_data\n");
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
err_platform_device_put:
|
||||
platform_device_put(musb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
The first step is to pass the device data privately held by the glue
|
||||
layer on to the controller driver through :c:func:`platform_set_drvdata`
|
||||
(line 7). Next is passing on the device resources information, also privately
|
||||
held at that point, through :c:func:`platform_device_add_resources` (line 9).
|
||||
|
||||
Finally comes passing on the platform specific data to the controller
|
||||
driver (line 16). Platform data will be discussed in
|
||||
:ref:`musb-dev-platform-data`, but here we are looking at the
|
||||
``platform_ops`` function pointer (line 5) in ``musb_hdrc_platform_data``
|
||||
structure (line 3). This function pointer allows the MUSB controller
|
||||
driver to know which function to call for device operation::
|
||||
|
||||
static const struct musb_platform_ops jz4740_musb_ops = {
|
||||
.init = jz4740_musb_init,
|
||||
.exit = jz4740_musb_exit,
|
||||
};
|
||||
|
||||
Here we have the minimal case where only init and exit functions are
|
||||
called by the controller driver when needed. Fact is the JZ4740 MUSB
|
||||
controller is a basic controller, lacking some features found in other
|
||||
controllers, otherwise we may also have pointers to a few other
|
||||
functions like a power management function or a function to switch
|
||||
between OTG and non-OTG modes, for instance.
|
||||
|
||||
At that point of the registration process, the controller driver
|
||||
actually calls the init function:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 12,14
|
||||
|
||||
static int jz4740_musb_init(struct musb *musb)
|
||||
{
|
||||
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||
if (!musb->xceiv) {
|
||||
pr_err("HS UDC: no transceiver configured\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Silicon does not implement ConfigData register.
|
||||
* Set dyn_fifo to avoid reading EP config from hardware.
|
||||
*/
|
||||
musb->dyn_fifo = true;
|
||||
|
||||
musb->isr = jz4740_musb_interrupt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
The goal of ``jz4740_musb_init()`` is to get hold of the transceiver
|
||||
driver data of the MUSB controller hardware and pass it on to the MUSB
|
||||
controller driver, as usual. The transceiver is the circuitry inside the
|
||||
controller hardware responsible for sending/receiving the USB data.
|
||||
Since it is an implementation of the physical layer of the OSI model,
|
||||
the transceiver is also referred to as PHY.
|
||||
|
||||
Getting hold of the ``MUSB PHY`` driver data is done with ``usb_get_phy()``
|
||||
which returns a pointer to the structure containing the driver instance
|
||||
data. The next couple of instructions (line 12 and 14) are used as a
|
||||
quirk and to setup IRQ handling respectively. Quirks and IRQ handling
|
||||
will be discussed later in :ref:`musb-dev-quirks` and
|
||||
:ref:`musb-handling-irqs`\ ::
|
||||
|
||||
static int jz4740_musb_exit(struct musb *musb)
|
||||
{
|
||||
usb_put_phy(musb->xceiv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Acting as the counterpart of init, the exit function releases the MUSB
|
||||
PHY driver when the controller hardware itself is about to be released.
|
||||
|
||||
Again, note that init and exit are fairly simple in this case due to the
|
||||
basic set of features of the JZ4740 controller hardware. When writing an
|
||||
musb glue layer for a more complex controller hardware, you might need
|
||||
to take care of more processing in those two functions.
|
||||
|
||||
Returning from the init function, the MUSB controller driver jumps back
|
||||
into the probe function::
|
||||
|
||||
static int jz4740_probe(struct platform_device *pdev)
|
||||
{
|
||||
ret = platform_device_add(musb);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register musb device\n");
|
||||
goto err_clk_disable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_disable:
|
||||
clk_disable_unprepare(clk);
|
||||
err_platform_device_put:
|
||||
platform_device_put(musb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
This is the last part of the device registration process where the glue
|
||||
layer adds the controller hardware device to Linux kernel device
|
||||
hierarchy: at this stage, all known information about the device is
|
||||
passed on to the Linux USB core stack:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 5,6
|
||||
|
||||
static int jz4740_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct jz4740_glue *glue = platform_get_drvdata(pdev);
|
||||
|
||||
platform_device_unregister(glue->musb);
|
||||
clk_disable_unprepare(glue->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Acting as the counterpart of probe, the remove function unregister the
|
||||
MUSB controller hardware (line 5) and disable the clock (line 6),
|
||||
allowing it to be gated.
|
||||
|
||||
.. _musb-handling-irqs:
|
||||
|
||||
Handling IRQs
|
||||
=============
|
||||
|
||||
Additionally to the MUSB controller hardware basic setup and
|
||||
registration, the glue layer is also responsible for handling the IRQs:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 7,9-11,14,24
|
||||
|
||||
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
|
||||
{
|
||||
unsigned long flags;
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
struct musb *musb = __hci;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
|
||||
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
|
||||
musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
|
||||
|
||||
/*
|
||||
* The controller is gadget only, the state of the host mode IRQ bits is
|
||||
* undefined. Mask them to make sure that the musb driver core will
|
||||
* never see them set
|
||||
*/
|
||||
musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
|
||||
MUSB_INTR_RESET | MUSB_INTR_SOF;
|
||||
|
||||
if (musb->int_usb || musb->int_tx || musb->int_rx)
|
||||
retval = musb_interrupt(musb);
|
||||
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Here the glue layer mostly has to read the relevant hardware registers
|
||||
and pass their values on to the controller driver which will handle the
|
||||
actual event that triggered the IRQ.
|
||||
|
||||
The interrupt handler critical section is protected by the
|
||||
:c:func:`spin_lock_irqsave` and counterpart :c:func:`spin_unlock_irqrestore`
|
||||
functions (line 7 and 24 respectively), which prevent the interrupt
|
||||
handler code to be run by two different threads at the same time.
|
||||
|
||||
Then the relevant interrupt registers are read (line 9 to 11):
|
||||
|
||||
- ``MUSB_INTRUSB``: indicates which USB interrupts are currently active,
|
||||
|
||||
- ``MUSB_INTRTX``: indicates which of the interrupts for TX endpoints are
|
||||
currently active,
|
||||
|
||||
- ``MUSB_INTRRX``: indicates which of the interrupts for TX endpoints are
|
||||
currently active.
|
||||
|
||||
Note that :c:func:`musb_readb` is used to read 8-bit registers at most, while
|
||||
:c:func:`musb_readw` allows us to read at most 16-bit registers. There are
|
||||
other functions that can be used depending on the size of your device
|
||||
registers. See ``musb_io.h`` for more information.
|
||||
|
||||
Instruction on line 18 is another quirk specific to the JZ4740 USB
|
||||
device controller, which will be discussed later in :ref:`musb-dev-quirks`.
|
||||
|
||||
The glue layer still needs to register the IRQ handler though. Remember
|
||||
the instruction on line 14 of the init function::
|
||||
|
||||
static int jz4740_musb_init(struct musb *musb)
|
||||
{
|
||||
musb->isr = jz4740_musb_interrupt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
This instruction sets a pointer to the glue layer IRQ handler function,
|
||||
in order for the controller hardware to call the handler back when an
|
||||
IRQ comes from the controller hardware. The interrupt handler is now
|
||||
implemented and registered.
|
||||
|
||||
.. _musb-dev-platform-data:
|
||||
|
||||
Device Platform Data
|
||||
====================
|
||||
|
||||
In order to write an MUSB glue layer, you need to have some data
|
||||
describing the hardware capabilities of your controller hardware, which
|
||||
is called the platform data.
|
||||
|
||||
Platform data is specific to your hardware, though it may cover a broad
|
||||
range of devices, and is generally found somewhere in the ``arch/``
|
||||
directory, depending on your device architecture.
|
||||
|
||||
For instance, platform data for the JZ4740 SoC is found in
|
||||
``arch/mips/jz4740/platform.c``. In the ``platform.c`` file each device of the
|
||||
JZ4740 SoC is described through a set of structures.
|
||||
|
||||
Here is the part of ``arch/mips/jz4740/platform.c`` that covers the USB
|
||||
Device Controller (UDC):
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 2,7,14-17,21,22,25,26,28,29
|
||||
|
||||
/* USB Device Controller */
|
||||
struct platform_device jz4740_udc_xceiv_device = {
|
||||
.name = "usb_phy_gen_xceiv",
|
||||
.id = 0,
|
||||
};
|
||||
|
||||
static struct resource jz4740_udc_resources[] = {
|
||||
[0] = {
|
||||
.start = JZ4740_UDC_BASE_ADDR,
|
||||
.end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = JZ4740_IRQ_UDC,
|
||||
.end = JZ4740_IRQ_UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
.name = "mc",
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device jz4740_udc_device = {
|
||||
.name = "musb-jz4740",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &jz4740_udc_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(jz4740_udc_resources),
|
||||
.resource = jz4740_udc_resources,
|
||||
};
|
||||
|
||||
The ``jz4740_udc_xceiv_device`` platform device structure (line 2)
|
||||
describes the UDC transceiver with a name and id number.
|
||||
|
||||
At the time of this writing, note that ``usb_phy_gen_xceiv`` is the
|
||||
specific name to be used for all transceivers that are either built-in
|
||||
with reference USB IP or autonomous and doesn't require any PHY
|
||||
programming. You will need to set ``CONFIG_NOP_USB_XCEIV=y`` in the
|
||||
kernel configuration to make use of the corresponding transceiver
|
||||
driver. The id field could be set to -1 (equivalent to
|
||||
``PLATFORM_DEVID_NONE``), -2 (equivalent to ``PLATFORM_DEVID_AUTO``) or
|
||||
start with 0 for the first device of this kind if we want a specific id
|
||||
number.
|
||||
|
||||
The ``jz4740_udc_resources`` resource structure (line 7) defines the UDC
|
||||
registers base addresses.
|
||||
|
||||
The first array (line 9 to 11) defines the UDC registers base memory
|
||||
addresses: start points to the first register memory address, end points
|
||||
to the last register memory address and the flags member defines the
|
||||
type of resource we are dealing with. So ``IORESOURCE_MEM`` is used to
|
||||
define the registers memory addresses. The second array (line 14 to 17)
|
||||
defines the UDC IRQ registers addresses. Since there is only one IRQ
|
||||
register available for the JZ4740 UDC, start and end point at the same
|
||||
address. The ``IORESOURCE_IRQ`` flag tells that we are dealing with IRQ
|
||||
resources, and the name ``mc`` is in fact hard-coded in the MUSB core in
|
||||
order for the controller driver to retrieve this IRQ resource by
|
||||
querying it by its name.
|
||||
|
||||
Finally, the ``jz4740_udc_device`` platform device structure (line 21)
|
||||
describes the UDC itself.
|
||||
|
||||
The ``musb-jz4740`` name (line 22) defines the MUSB driver that is used
|
||||
for this device; remember this is in fact the name that we used in the
|
||||
``jz4740_driver`` platform driver structure in :ref:`musb-basics`.
|
||||
The id field (line 23) is set to -1 (equivalent to ``PLATFORM_DEVID_NONE``)
|
||||
since we do not need an id for the device: the MUSB controller driver was
|
||||
already set to allocate an automatic id in :ref:`musb-basics`. In the dev field
|
||||
we care for DMA related information here. The ``dma_mask`` field (line 25)
|
||||
defines the width of the DMA mask that is going to be used, and
|
||||
``coherent_dma_mask`` (line 26) has the same purpose but for the
|
||||
``alloc_coherent`` DMA mappings: in both cases we are using a 32 bits mask.
|
||||
Then the resource field (line 29) is simply a pointer to the resource
|
||||
structure defined before, while the ``num_resources`` field (line 28) keeps
|
||||
track of the number of arrays defined in the resource structure (in this
|
||||
case there were two resource arrays defined before).
|
||||
|
||||
With this quick overview of the UDC platform data at the ``arch/`` level now
|
||||
done, let's get back to the MUSB glue layer specific platform data in
|
||||
``drivers/usb/musb/jz4740.c``:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 3,5,7-9,11
|
||||
|
||||
static struct musb_hdrc_config jz4740_musb_config = {
|
||||
/* Silicon does not implement USB OTG. */
|
||||
.multipoint = 0,
|
||||
/* Max EPs scanned, driver will decide which EP can be used. */
|
||||
.num_eps = 4,
|
||||
/* RAMbits needed to configure EPs from table */
|
||||
.ram_bits = 9,
|
||||
.fifo_cfg = jz4740_musb_fifo_cfg,
|
||||
.fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
|
||||
};
|
||||
|
||||
static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
|
||||
.mode = MUSB_PERIPHERAL,
|
||||
.config = &jz4740_musb_config,
|
||||
};
|
||||
|
||||
First the glue layer configures some aspects of the controller driver
|
||||
operation related to the controller hardware specifics. This is done
|
||||
through the ``jz4740_musb_config`` :c:type:`musb_hdrc_config` structure.
|
||||
|
||||
Defining the OTG capability of the controller hardware, the multipoint
|
||||
member (line 3) is set to 0 (equivalent to false) since the JZ4740 UDC
|
||||
is not OTG compatible. Then ``num_eps`` (line 5) defines the number of USB
|
||||
endpoints of the controller hardware, including endpoint 0: here we have
|
||||
3 endpoints + endpoint 0. Next is ``ram_bits`` (line 7) which is the width
|
||||
of the RAM address bus for the MUSB controller hardware. This
|
||||
information is needed when the controller driver cannot automatically
|
||||
configure endpoints by reading the relevant controller hardware
|
||||
registers. This issue will be discussed when we get to device quirks in
|
||||
:ref:`musb-dev-quirks`. Last two fields (line 8 and 9) are also
|
||||
about device quirks: ``fifo_cfg`` points to the USB endpoints configuration
|
||||
table and ``fifo_cfg_size`` keeps track of the size of the number of
|
||||
entries in that configuration table. More on that later in
|
||||
:ref:`musb-dev-quirks`.
|
||||
|
||||
Then this configuration is embedded inside ``jz4740_musb_platform_data``
|
||||
:c:type:`musb_hdrc_platform_data` structure (line 11): config is a pointer to
|
||||
the configuration structure itself, and mode tells the controller driver
|
||||
if the controller hardware may be used as ``MUSB_HOST`` only,
|
||||
``MUSB_PERIPHERAL`` only or ``MUSB_OTG`` which is a dual mode.
|
||||
|
||||
Remember that ``jz4740_musb_platform_data`` is then used to convey
|
||||
platform data information as we have seen in the probe function in
|
||||
:ref:`musb-basics`.
|
||||
|
||||
.. _musb-dev-quirks:
|
||||
|
||||
Device Quirks
|
||||
=============
|
||||
|
||||
Completing the platform data specific to your device, you may also need
|
||||
to write some code in the glue layer to work around some device specific
|
||||
limitations. These quirks may be due to some hardware bugs, or simply be
|
||||
the result of an incomplete implementation of the USB On-the-Go
|
||||
specification.
|
||||
|
||||
The JZ4740 UDC exhibits such quirks, some of which we will discuss here
|
||||
for the sake of insight even though these might not be found in the
|
||||
controller hardware you are working on.
|
||||
|
||||
Let's get back to the init function first:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 12
|
||||
|
||||
static int jz4740_musb_init(struct musb *musb)
|
||||
{
|
||||
musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||
if (!musb->xceiv) {
|
||||
pr_err("HS UDC: no transceiver configured\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Silicon does not implement ConfigData register.
|
||||
* Set dyn_fifo to avoid reading EP config from hardware.
|
||||
*/
|
||||
musb->dyn_fifo = true;
|
||||
|
||||
musb->isr = jz4740_musb_interrupt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction on line 12 helps the MUSB controller driver to work around
|
||||
the fact that the controller hardware is missing registers that are used
|
||||
for USB endpoints configuration.
|
||||
|
||||
Without these registers, the controller driver is unable to read the
|
||||
endpoints configuration from the hardware, so we use line 12 instruction
|
||||
to bypass reading the configuration from silicon, and rely on a
|
||||
hard-coded table that describes the endpoints configuration instead::
|
||||
|
||||
static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
|
||||
{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
|
||||
{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
|
||||
{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
|
||||
};
|
||||
|
||||
Looking at the configuration table above, we see that each endpoints is
|
||||
described by three fields: ``hw_ep_num`` is the endpoint number, style is
|
||||
its direction (either ``FIFO_TX`` for the controller driver to send packets
|
||||
in the controller hardware, or ``FIFO_RX`` to receive packets from
|
||||
hardware), and maxpacket defines the maximum size of each data packet
|
||||
that can be transmitted over that endpoint. Reading from the table, the
|
||||
controller driver knows that endpoint 1 can be used to send and receive
|
||||
USB data packets of 512 bytes at once (this is in fact a bulk in/out
|
||||
endpoint), and endpoint 2 can be used to send data packets of 64 bytes
|
||||
at once (this is in fact an interrupt endpoint).
|
||||
|
||||
Note that there is no information about endpoint 0 here: that one is
|
||||
implemented by default in every silicon design, with a predefined
|
||||
configuration according to the USB specification. For more examples of
|
||||
endpoint configuration tables, see ``musb_core.c``.
|
||||
|
||||
Let's now get back to the interrupt handler function:
|
||||
|
||||
.. code-block:: c
|
||||
:emphasize-lines: 18-19
|
||||
|
||||
static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
|
||||
{
|
||||
unsigned long flags;
|
||||
irqreturn_t retval = IRQ_NONE;
|
||||
struct musb *musb = __hci;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
|
||||
musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
|
||||
musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
|
||||
|
||||
/*
|
||||
* The controller is gadget only, the state of the host mode IRQ bits is
|
||||
* undefined. Mask them to make sure that the musb driver core will
|
||||
* never see them set
|
||||
*/
|
||||
musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
|
||||
MUSB_INTR_RESET | MUSB_INTR_SOF;
|
||||
|
||||
if (musb->int_usb || musb->int_tx || musb->int_rx)
|
||||
retval = musb_interrupt(musb);
|
||||
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Instruction on line 18 above is a way for the controller driver to work
|
||||
around the fact that some interrupt bits used for USB host mode
|
||||
operation are missing in the ``MUSB_INTRUSB`` register, thus left in an
|
||||
undefined hardware state, since this MUSB controller hardware is used in
|
||||
peripheral mode only. As a consequence, the glue layer masks these
|
||||
missing bits out to avoid parasite interrupts by doing a logical AND
|
||||
operation between the value read from ``MUSB_INTRUSB`` and the bits that
|
||||
are actually implemented in the register.
|
||||
|
||||
These are only a couple of the quirks found in the JZ4740 USB device
|
||||
controller. Some others were directly addressed in the MUSB core since
|
||||
the fixes were generic enough to provide a better handling of the issues
|
||||
for others controller hardware eventually.
|
||||
|
||||
Conclusion
|
||||
==========
|
||||
|
||||
Writing a Linux MUSB glue layer should be a more accessible task, as
|
||||
this documentation tries to show the ins and outs of this exercise.
|
||||
|
||||
The JZ4740 USB device controller being fairly simple, I hope its glue
|
||||
layer serves as a good example for the curious mind. Used with the
|
||||
current MUSB glue layers, this documentation should provide enough
|
||||
guidance to get started; should anything gets out of hand, the linux-usb
|
||||
mailing list archive is another helpful resource to browse through.
|
||||
|
||||
Acknowledgements
|
||||
================
|
||||
|
||||
Many thanks to Lars-Peter Clausen and Maarten ter Huurne for answering
|
||||
my questions while I was writing the JZ4740 glue layer and for helping
|
||||
me out getting the code in good shape.
|
||||
|
||||
I would also like to thank the Qi-Hardware community at large for its
|
||||
cheerful guidance and support.
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
USB Home Page: http://www.usb.org
|
||||
|
||||
linux-usb Mailing List Archives: http://marc.info/?l=linux-usb
|
||||
|
||||
USB On-the-Go Basics:
|
||||
http://www.maximintegrated.com/app-notes/index.mvp/id/1822
|
||||
|
||||
:ref:`Writing USB Device Drivers <writing-usb-driver>`
|
||||
|
||||
Texas Instruments USB Configuration Wiki Page:
|
||||
http://processors.wiki.ti.com/index.php/Usbgeneralpage
|
||||
|
||||
Analog Devices Blackfin MUSB Configuration:
|
||||
http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb
|
326
Documentation/driver-api/usb/writing_usb_driver.rst
Normal file
326
Documentation/driver-api/usb/writing_usb_driver.rst
Normal file
|
@ -0,0 +1,326 @@
|
|||
.. _writing-usb-driver:
|
||||
|
||||
==========================
|
||||
Writing USB Device Drivers
|
||||
==========================
|
||||
|
||||
:Author: Greg Kroah-Hartman
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The Linux USB subsystem has grown from supporting only two different
|
||||
types of devices in the 2.2.7 kernel (mice and keyboards), to over 20
|
||||
different types of devices in the 2.4 kernel. Linux currently supports
|
||||
almost all USB class devices (standard types of devices like keyboards,
|
||||
mice, modems, printers and speakers) and an ever-growing number of
|
||||
vendor-specific devices (such as USB to serial converters, digital
|
||||
cameras, Ethernet devices and MP3 players). For a full list of the
|
||||
different USB devices currently supported, see Resources.
|
||||
|
||||
The remaining kinds of USB devices that do not have support on Linux are
|
||||
almost all vendor-specific devices. Each vendor decides to implement a
|
||||
custom protocol to talk to their device, so a custom driver usually
|
||||
needs to be created. Some vendors are open with their USB protocols and
|
||||
help with the creation of Linux drivers, while others do not publish
|
||||
them, and developers are forced to reverse-engineer. See Resources for
|
||||
some links to handy reverse-engineering tools.
|
||||
|
||||
Because each different protocol causes a new driver to be created, I
|
||||
have written a generic USB driver skeleton, modelled after the
|
||||
pci-skeleton.c file in the kernel source tree upon which many PCI
|
||||
network drivers have been based. This USB skeleton can be found at
|
||||
drivers/usb/usb-skeleton.c in the kernel source tree. In this article I
|
||||
will walk through the basics of the skeleton driver, explaining the
|
||||
different pieces and what needs to be done to customize it to your
|
||||
specific device.
|
||||
|
||||
Linux USB Basics
|
||||
================
|
||||
|
||||
If you are going to write a Linux USB driver, please become familiar
|
||||
with the USB protocol specification. It can be found, along with many
|
||||
other useful documents, at the USB home page (see Resources). An
|
||||
excellent introduction to the Linux USB subsystem can be found at the
|
||||
USB Working Devices List (see Resources). It explains how the Linux USB
|
||||
subsystem is structured and introduces the reader to the concept of USB
|
||||
urbs (USB Request Blocks), which are essential to USB drivers.
|
||||
|
||||
The first thing a Linux USB driver needs to do is register itself with
|
||||
the Linux USB subsystem, giving it some information about which devices
|
||||
the driver supports and which functions to call when a device supported
|
||||
by the driver is inserted or removed from the system. All of this
|
||||
information is passed to the USB subsystem in the :c:type:`usb_driver`
|
||||
structure. The skeleton driver declares a :c:type:`usb_driver` as::
|
||||
|
||||
static struct usb_driver skel_driver = {
|
||||
.name = "skeleton",
|
||||
.probe = skel_probe,
|
||||
.disconnect = skel_disconnect,
|
||||
.fops = &skel_fops,
|
||||
.minor = USB_SKEL_MINOR_BASE,
|
||||
.id_table = skel_table,
|
||||
};
|
||||
|
||||
|
||||
The variable name is a string that describes the driver. It is used in
|
||||
informational messages printed to the system log. The probe and
|
||||
disconnect function pointers are called when a device that matches the
|
||||
information provided in the ``id_table`` variable is either seen or
|
||||
removed.
|
||||
|
||||
The fops and minor variables are optional. Most USB drivers hook into
|
||||
another kernel subsystem, such as the SCSI, network or TTY subsystem.
|
||||
These types of drivers register themselves with the other kernel
|
||||
subsystem, and any user-space interactions are provided through that
|
||||
interface. But for drivers that do not have a matching kernel subsystem,
|
||||
such as MP3 players or scanners, a method of interacting with user space
|
||||
is needed. The USB subsystem provides a way to register a minor device
|
||||
number and a set of :c:type:`file_operations` function pointers that enable
|
||||
this user-space interaction. The skeleton driver needs this kind of
|
||||
interface, so it provides a minor starting number and a pointer to its
|
||||
:c:type:`file_operations` functions.
|
||||
|
||||
The USB driver is then registered with a call to :c:func:`usb_register`,
|
||||
usually in the driver's init function, as shown here::
|
||||
|
||||
static int __init usb_skel_init(void)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
result = usb_register(&skel_driver);
|
||||
if (result < 0) {
|
||||
err("usb_register failed for the "__FILE__ "driver."
|
||||
"Error number %d", result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(usb_skel_init);
|
||||
|
||||
|
||||
When the driver is unloaded from the system, it needs to deregister
|
||||
itself with the USB subsystem. This is done with the :c:func:`usb_deregister`
|
||||
function::
|
||||
|
||||
static void __exit usb_skel_exit(void)
|
||||
{
|
||||
/* deregister this driver with the USB subsystem */
|
||||
usb_deregister(&skel_driver);
|
||||
}
|
||||
module_exit(usb_skel_exit);
|
||||
|
||||
|
||||
To enable the linux-hotplug system to load the driver automatically when
|
||||
the device is plugged in, you need to create a ``MODULE_DEVICE_TABLE``.
|
||||
The following code tells the hotplug scripts that this module supports a
|
||||
single device with a specific vendor and product ID::
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static struct usb_device_id skel_table [] = {
|
||||
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE (usb, skel_table);
|
||||
|
||||
|
||||
There are other macros that can be used in describing a struct
|
||||
:c:type:`usb_device_id` for drivers that support a whole class of USB
|
||||
drivers. See :ref:`usb.h <usb_header>` for more information on this.
|
||||
|
||||
Device operation
|
||||
================
|
||||
|
||||
When a device is plugged into the USB bus that matches the device ID
|
||||
pattern that your driver registered with the USB core, the probe
|
||||
function is called. The :c:type:`usb_device` structure, interface number and
|
||||
the interface ID are passed to the function::
|
||||
|
||||
static int skel_probe(struct usb_interface *interface,
|
||||
const struct usb_device_id *id)
|
||||
|
||||
|
||||
The driver now needs to verify that this device is actually one that it
|
||||
can accept. If so, it returns 0. If not, or if any error occurs during
|
||||
initialization, an errorcode (such as ``-ENOMEM`` or ``-ENODEV``) is
|
||||
returned from the probe function.
|
||||
|
||||
In the skeleton driver, we determine what end points are marked as
|
||||
bulk-in and bulk-out. We create buffers to hold the data that will be
|
||||
sent and received from the device, and a USB urb to write data to the
|
||||
device is initialized.
|
||||
|
||||
Conversely, when the device is removed from the USB bus, the disconnect
|
||||
function is called with the device pointer. The driver needs to clean
|
||||
any private data that has been allocated at this time and to shut down
|
||||
any pending urbs that are in the USB system.
|
||||
|
||||
Now that the device is plugged into the system and the driver is bound
|
||||
to the device, any of the functions in the :c:type:`file_operations` structure
|
||||
that were passed to the USB subsystem will be called from a user program
|
||||
trying to talk to the device. The first function called will be open, as
|
||||
the program tries to open the device for I/O. We increment our private
|
||||
usage count and save a pointer to our internal structure in the file
|
||||
structure. This is done so that future calls to file operations will
|
||||
enable the driver to determine which device the user is addressing. All
|
||||
of this is done with the following code::
|
||||
|
||||
/* increment our usage count for the module */
|
||||
++skel->open_count;
|
||||
|
||||
/* save our object in the file's private structure */
|
||||
file->private_data = dev;
|
||||
|
||||
|
||||
After the open function is called, the read and write functions are
|
||||
called to receive and send data to the device. In the ``skel_write``
|
||||
function, we receive a pointer to some data that the user wants to send
|
||||
to the device and the size of the data. The function determines how much
|
||||
data it can send to the device based on the size of the write urb it has
|
||||
created (this size depends on the size of the bulk out end point that
|
||||
the device has). Then it copies the data from user space to kernel
|
||||
space, points the urb to the data and submits the urb to the USB
|
||||
subsystem. This can be seen in the following code::
|
||||
|
||||
/* we can only write as much as 1 urb will hold */
|
||||
bytes_written = (count > skel->bulk_out_size) ? skel->bulk_out_size : count;
|
||||
|
||||
/* copy the data from user space into our urb */
|
||||
copy_from_user(skel->write_urb->transfer_buffer, buffer, bytes_written);
|
||||
|
||||
/* set up our urb */
|
||||
usb_fill_bulk_urb(skel->write_urb,
|
||||
skel->dev,
|
||||
usb_sndbulkpipe(skel->dev, skel->bulk_out_endpointAddr),
|
||||
skel->write_urb->transfer_buffer,
|
||||
bytes_written,
|
||||
skel_write_bulk_callback,
|
||||
skel);
|
||||
|
||||
/* send the data out the bulk port */
|
||||
result = usb_submit_urb(skel->write_urb);
|
||||
if (result) {
|
||||
err("Failed submitting write urb, error %d", result);
|
||||
}
|
||||
|
||||
|
||||
When the write urb is filled up with the proper information using the
|
||||
:c:func:`usb_fill_bulk_urb` function, we point the urb's completion callback
|
||||
to call our own ``skel_write_bulk_callback`` function. This function is
|
||||
called when the urb is finished by the USB subsystem. The callback
|
||||
function is called in interrupt context, so caution must be taken not to
|
||||
do very much processing at that time. Our implementation of
|
||||
``skel_write_bulk_callback`` merely reports if the urb was completed
|
||||
successfully or not and then returns.
|
||||
|
||||
The read function works a bit differently from the write function in
|
||||
that we do not use an urb to transfer data from the device to the
|
||||
driver. Instead we call the :c:func:`usb_bulk_msg` function, which can be used
|
||||
to send or receive data from a device without having to create urbs and
|
||||
handle urb completion callback functions. We call the :c:func:`usb_bulk_msg`
|
||||
function, giving it a buffer into which to place any data received from
|
||||
the device and a timeout value. If the timeout period expires without
|
||||
receiving any data from the device, the function will fail and return an
|
||||
error message. This can be shown with the following code::
|
||||
|
||||
/* do an immediate bulk read to get data from the device */
|
||||
retval = usb_bulk_msg (skel->dev,
|
||||
usb_rcvbulkpipe (skel->dev,
|
||||
skel->bulk_in_endpointAddr),
|
||||
skel->bulk_in_buffer,
|
||||
skel->bulk_in_size,
|
||||
&count, HZ*10);
|
||||
/* if the read was successful, copy the data to user space */
|
||||
if (!retval) {
|
||||
if (copy_to_user (buffer, skel->bulk_in_buffer, count))
|
||||
retval = -EFAULT;
|
||||
else
|
||||
retval = count;
|
||||
}
|
||||
|
||||
|
||||
The :c:func:`usb_bulk_msg` function can be very useful for doing single reads
|
||||
or writes to a device; however, if you need to read or write constantly to
|
||||
a device, it is recommended to set up your own urbs and submit them to
|
||||
the USB subsystem.
|
||||
|
||||
When the user program releases the file handle that it has been using to
|
||||
talk to the device, the release function in the driver is called. In
|
||||
this function we decrement our private usage count and wait for possible
|
||||
pending writes::
|
||||
|
||||
/* decrement our usage count for the device */
|
||||
--skel->open_count;
|
||||
|
||||
|
||||
One of the more difficult problems that USB drivers must be able to
|
||||
handle smoothly is the fact that the USB device may be removed from the
|
||||
system at any point in time, even if a program is currently talking to
|
||||
it. It needs to be able to shut down any current reads and writes and
|
||||
notify the user-space programs that the device is no longer there. The
|
||||
following code (function ``skel_delete``) is an example of how to do
|
||||
this::
|
||||
|
||||
static inline void skel_delete (struct usb_skel *dev)
|
||||
{
|
||||
kfree (dev->bulk_in_buffer);
|
||||
if (dev->bulk_out_buffer != NULL)
|
||||
usb_free_coherent (dev->udev, dev->bulk_out_size,
|
||||
dev->bulk_out_buffer,
|
||||
dev->write_urb->transfer_dma);
|
||||
usb_free_urb (dev->write_urb);
|
||||
kfree (dev);
|
||||
}
|
||||
|
||||
|
||||
If a program currently has an open handle to the device, we reset the
|
||||
flag ``device_present``. For every read, write, release and other
|
||||
functions that expect a device to be present, the driver first checks
|
||||
this flag to see if the device is still present. If not, it releases
|
||||
that the device has disappeared, and a ``-ENODEV`` error is returned to the
|
||||
user-space program. When the release function is eventually called, it
|
||||
determines if there is no device and if not, it does the cleanup that
|
||||
the ``skel_disconnect`` function normally does if there are no open files
|
||||
on the device (see Listing 5).
|
||||
|
||||
Isochronous Data
|
||||
================
|
||||
|
||||
This usb-skeleton driver does not have any examples of interrupt or
|
||||
isochronous data being sent to or from the device. Interrupt data is
|
||||
sent almost exactly as bulk data is, with a few minor exceptions.
|
||||
Isochronous data works differently with continuous streams of data being
|
||||
sent to or from the device. The audio and video camera drivers are very
|
||||
good examples of drivers that handle isochronous data and will be useful
|
||||
if you also need to do this.
|
||||
|
||||
Conclusion
|
||||
==========
|
||||
|
||||
Writing Linux USB device drivers is not a difficult task as the
|
||||
usb-skeleton driver shows. This driver, combined with the other current
|
||||
USB drivers, should provide enough examples to help a beginning author
|
||||
create a working driver in a minimal amount of time. The linux-usb-devel
|
||||
mailing list archives also contain a lot of helpful information.
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
The Linux USB Project:
|
||||
http://www.linux-usb.org/
|
||||
|
||||
Linux Hotplug Project:
|
||||
http://linux-hotplug.sourceforge.net/
|
||||
|
||||
Linux USB Working Devices List:
|
||||
http://www.qbik.ch/usb/devices/
|
||||
|
||||
linux-usb-devel Mailing List Archives:
|
||||
http://marc.theaimsgroup.com/?l=linux-usb-devel
|
||||
|
||||
Programming Guide for Linux USB Device Drivers:
|
||||
http://usb.cs.tum.edu/usbdoc
|
||||
|
||||
USB Home Page: http://www.usb.org
|
|
@ -86,7 +86,7 @@ early userspace useful. The klibc distribution is currently
|
|||
maintained separately from the kernel.
|
||||
|
||||
You can obtain somewhat infrequent snapshots of klibc from
|
||||
ftp://ftp.kernel.org/pub/linux/libs/klibc/
|
||||
https://www.kernel.org/pub/linux/libs/klibc/
|
||||
|
||||
For active users, you are better off using the klibc git
|
||||
repository, at http://git.kernel.org/?p=libs/klibc/klibc.git
|
||||
|
|
|
@ -25,7 +25,7 @@ Note: More extensive information for getting started with ext4 can be
|
|||
|
||||
or
|
||||
|
||||
ftp://ftp.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/
|
||||
https://www.kernel.org/pub/linux/kernel/people/tytso/e2fsprogs/
|
||||
|
||||
or grab the latest git repository from:
|
||||
|
||||
|
|
|
@ -110,10 +110,10 @@ Installation
|
|||
- Install a Linux kernel with NFS/RDMA
|
||||
|
||||
The NFS/RDMA client and server are both included in the mainline Linux
|
||||
kernel version 2.6.25 and later. This and other versions of the 2.6 Linux
|
||||
kernel version 2.6.25 and later. This and other versions of the Linux
|
||||
kernel can be found at:
|
||||
|
||||
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
|
||||
https://www.kernel.org/pub/linux/kernel/
|
||||
|
||||
Download the sources and place them in an appropriate location.
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ of:
|
|||
BUS_HIL
|
||||
BUS_BLUETOOTH
|
||||
BUS_VIRTUAL
|
||||
which are defined in linux/input.h.
|
||||
which are defined in uapi/linux/input.h.
|
||||
|
||||
HIDIOCGRAWNAME(len): Get Raw Name
|
||||
This ioctl returns a string containing the vendor and product strings of
|
||||
|
|
|
@ -24,6 +24,18 @@ trying to get it to work optimally on a given system.
|
|||
|
||||
admin-guide/index
|
||||
|
||||
Application-developer documentation
|
||||
-----------------------------------
|
||||
|
||||
The user-space API manual gathers together documents describing aspects of
|
||||
the kernel interface as seen by application developers.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
userspace-api/index
|
||||
|
||||
|
||||
Introduction to kernel development
|
||||
----------------------------------
|
||||
|
||||
|
@ -76,6 +88,14 @@ Chinese translations
|
|||
|
||||
translations/zh_CN/index
|
||||
|
||||
Japanese translations
|
||||
---------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
translations/ja_JP/index
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
|
|
|
@ -106,9 +106,9 @@ allocate a new effect.
|
|||
|
||||
Effects are file descriptor specific.
|
||||
|
||||
See <linux/input.h> for a description of the ff_effect struct. You should also
|
||||
find help in a few sketches, contained in files shape.fig and interactive.fig.
|
||||
You need xfig to visualize these files.
|
||||
See <uapi/linux/input.h> for a description of the ff_effect struct. You should
|
||||
also find help in a few sketches, contained in files shape.fig and
|
||||
interactive.fig. You need xfig to visualize these files.
|
||||
|
||||
3.3 Removing an effect from the device
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -174,8 +174,8 @@ It's reported to the input system via:
|
|||
|
||||
input_report_key(struct input_dev *dev, int code, int value)
|
||||
|
||||
See linux/input.h for the allowable values of code (from 0 to KEY_MAX).
|
||||
Value is interpreted as a truth value, ie any nonzero value means key
|
||||
See uapi/linux/input-event-codes.h for the allowable values of code (from 0 to
|
||||
KEY_MAX). Value is interpreted as a truth value, ie any nonzero value means key
|
||||
pressed, zero value means key released. The input code generates events only
|
||||
in case the value is different from before.
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ Code Seq#(hex) Include File Comments
|
|||
'c' 00-1F linux/chio.h conflict!
|
||||
'c' 80-9F arch/s390/include/asm/chsc.h conflict!
|
||||
'c' A0-AF arch/x86/include/asm/msr.h conflict!
|
||||
'd' 00-FF linux/char/drm/drm/h conflict!
|
||||
'd' 00-FF linux/char/drm/drm.h conflict!
|
||||
'd' 02-40 pcmcia/ds.h conflict!
|
||||
'd' F0-FF linux/digi1.h
|
||||
'e' all linux/digi1.h conflict!
|
||||
|
|
|
@ -117,7 +117,7 @@ As soon as 'loading' is set to 0, registered callback is called.
|
|||
Inside the callback, the selected engine is loaded and memory is updated.
|
||||
To run programmed pattern, 'run_engine' attribute should be enabled.
|
||||
|
||||
The pattern sqeuence of LP8501 is similar to LP5523.
|
||||
The pattern sequence of LP8501 is similar to LP5523.
|
||||
However pattern data is specific.
|
||||
Ex 1) Engine 1 is used
|
||||
echo 1 > /sys/bus/i2c/devices/xxxx/select_engine
|
||||
|
|
|
@ -77,7 +77,7 @@ There are three groups of locks for managing the device:
|
|||
3.1.2 RESYNCING: informs other nodes that a resync is initiated or
|
||||
ended so that each node may suspend or resume the region. Each
|
||||
RESYNCING message identifies a range of the devices that the
|
||||
sending node is about to resync. This over-rides any pervious
|
||||
sending node is about to resync. This overrides any previous
|
||||
notification from that node: only one ranged can be resynced at a
|
||||
time per-node.
|
||||
|
||||
|
|
|
@ -1,51 +1,6 @@
|
|||
# Rules to convert DOT and SVG to Sphinx images
|
||||
|
||||
SRC_DIR=$(srctree)/Documentation/media
|
||||
|
||||
DOTS = \
|
||||
uapi/v4l/pipeline.dot \
|
||||
|
||||
IMAGES = \
|
||||
typical_media_device.svg \
|
||||
uapi/dvb/dvbstb.svg \
|
||||
uapi/v4l/bayer.svg \
|
||||
uapi/v4l/constraints.svg \
|
||||
uapi/v4l/crop.svg \
|
||||
uapi/v4l/fieldseq_bt.svg \
|
||||
uapi/v4l/fieldseq_tb.svg \
|
||||
uapi/v4l/nv12mt.svg \
|
||||
uapi/v4l/nv12mt_example.svg \
|
||||
uapi/v4l/pipeline.svg \
|
||||
uapi/v4l/selection.svg \
|
||||
uapi/v4l/subdev-image-processing-full.svg \
|
||||
uapi/v4l/subdev-image-processing-scaling-multi-source.svg \
|
||||
uapi/v4l/subdev-image-processing-crop.svg \
|
||||
uapi/v4l/vbi_525.svg \
|
||||
uapi/v4l/vbi_625.svg \
|
||||
uapi/v4l/vbi_hsync.svg \
|
||||
|
||||
DOTTGT := $(patsubst %.dot,%.svg,$(DOTS))
|
||||
IMGDOT := $(patsubst %,$(SRC_DIR)/%,$(DOTTGT))
|
||||
|
||||
IMGTGT := $(patsubst %.svg,%.pdf,$(IMAGES))
|
||||
IMGPDF := $(patsubst %,$(SRC_DIR)/%,$(IMGTGT))
|
||||
|
||||
cmd = $(echo-cmd) $(cmd_$(1))
|
||||
|
||||
quiet_cmd_genpdf = GENPDF $2
|
||||
cmd_genpdf = convert $2 $3
|
||||
|
||||
quiet_cmd_gendot = DOT $2
|
||||
cmd_gendot = dot -Tsvg $2 > $3 || { rm -f $3; exit 1; }
|
||||
|
||||
%.pdf: %.svg
|
||||
@$(call cmd,genpdf,$<,$@)
|
||||
|
||||
%.svg: %.dot
|
||||
@$(call cmd,gendot,$<,$@)
|
||||
|
||||
# Rules to convert a .h file to inline RST documentation
|
||||
|
||||
SRC_DIR=$(srctree)/Documentation/media
|
||||
PARSER = $(srctree)/Documentation/sphinx/parse-headers.pl
|
||||
UAPI = $(srctree)/include/uapi/linux
|
||||
KAPI = $(srctree)/include/linux
|
||||
|
|
|
@ -13,9 +13,9 @@ A typical media device hardware is shown at :ref:`typical_media_device`.
|
|||
|
||||
.. _typical_media_device:
|
||||
|
||||
.. figure:: typical_media_device.*
|
||||
:alt: typical_media_device.pdf / typical_media_device.svg
|
||||
:align: center
|
||||
.. kernel-figure:: typical_media_device.svg
|
||||
:alt: typical_media_device.svg
|
||||
:align: center
|
||||
|
||||
Typical Media Device
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ Overview
|
|||
|
||||
.. _stb_components:
|
||||
|
||||
.. figure:: dvbstb.*
|
||||
:alt: dvbstb.pdf / dvbstb.svg
|
||||
:align: center
|
||||
.. kernel-figure:: dvbstb.svg
|
||||
:alt: dvbstb.svg
|
||||
:align: center
|
||||
|
||||
Components of a DVB card/STB
|
||||
|
||||
|
|
|
@ -53,8 +53,8 @@ Cropping Structures
|
|||
|
||||
.. _crop-scale:
|
||||
|
||||
.. figure:: crop.*
|
||||
:alt: crop.pdf / crop.svg
|
||||
.. kernel-figure:: crop.svg
|
||||
:alt: crop.svg
|
||||
:align: center
|
||||
|
||||
Image Cropping, Insertion and Scaling
|
||||
|
|
|
@ -221,33 +221,29 @@ and always returns default parameters as :ref:`VIDIOC_G_FMT <VIDIOC_G_FMT>` does
|
|||
|
||||
.. _vbi-hsync:
|
||||
|
||||
.. figure:: vbi_hsync.*
|
||||
:alt: vbi_hsync.pdf / vbi_hsync.svg
|
||||
:align: center
|
||||
.. kernel-figure:: vbi_hsync.svg
|
||||
:alt: vbi_hsync.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.1. Line synchronization**
|
||||
|
||||
|
||||
.. _vbi-525:
|
||||
|
||||
.. figure:: vbi_525.*
|
||||
:alt: vbi_525.pdf / vbi_525.svg
|
||||
:align: center
|
||||
.. kernel-figure:: vbi_525.svg
|
||||
:alt: vbi_525.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.2. ITU-R 525 line numbering (M/NTSC and M/PAL)**
|
||||
|
||||
|
||||
|
||||
.. _vbi-625:
|
||||
|
||||
.. figure:: vbi_625.*
|
||||
:alt: vbi_625.pdf / vbi_625.svg
|
||||
:align: center
|
||||
.. kernel-figure:: vbi_625.svg
|
||||
:alt: vbi_625.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.3. ITU-R 625 line numbering**
|
||||
|
||||
|
||||
|
||||
Remember the VBI image format depends on the selected video standard,
|
||||
therefore the application must choose a new standard or query the
|
||||
current standard first. Attempts to read or write data ahead of format
|
||||
|
|
|
@ -99,9 +99,9 @@ the video sensor and the host image processing hardware.
|
|||
|
||||
.. _pipeline-scaling:
|
||||
|
||||
.. figure:: pipeline.*
|
||||
:alt: pipeline.pdf / pipeline.svg
|
||||
:align: center
|
||||
.. kernel-figure:: pipeline.dot
|
||||
:alt: pipeline.dot
|
||||
:align: center
|
||||
|
||||
Image Format Negotiation on Pipelines
|
||||
|
||||
|
@ -404,9 +404,9 @@ selection will refer to the sink pad format dimensions instead.
|
|||
|
||||
.. _subdev-image-processing-crop:
|
||||
|
||||
.. figure:: subdev-image-processing-crop.*
|
||||
:alt: subdev-image-processing-crop.pdf / subdev-image-processing-crop.svg
|
||||
:align: center
|
||||
.. kernel-figure:: subdev-image-processing-crop.svg
|
||||
:alt: subdev-image-processing-crop.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.5. Image processing in subdevs: simple crop example**
|
||||
|
||||
|
@ -421,9 +421,9 @@ pad.
|
|||
|
||||
.. _subdev-image-processing-scaling-multi-source:
|
||||
|
||||
.. figure:: subdev-image-processing-scaling-multi-source.*
|
||||
:alt: subdev-image-processing-scaling-multi-source.pdf / subdev-image-processing-scaling-multi-source.svg
|
||||
:align: center
|
||||
.. kernel-figure:: subdev-image-processing-scaling-multi-source.svg
|
||||
:alt: subdev-image-processing-scaling-multi-source.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.6. Image processing in subdevs: scaling with multiple sources**
|
||||
|
||||
|
@ -437,8 +437,8 @@ an area at location specified by the source crop rectangle from it.
|
|||
|
||||
.. _subdev-image-processing-full:
|
||||
|
||||
.. figure:: subdev-image-processing-full.*
|
||||
:alt: subdev-image-processing-full.pdf / subdev-image-processing-full.svg
|
||||
.. kernel-figure:: subdev-image-processing-full.svg
|
||||
:alt: subdev-image-processing-full.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.7. Image processing in subdevs: scaling and composition with multiple sinks and sources**
|
||||
|
|
|
@ -141,17 +141,20 @@ enum v4l2_field
|
|||
Field Order, Top Field First Transmitted
|
||||
========================================
|
||||
|
||||
.. figure:: fieldseq_tb.*
|
||||
:alt: fieldseq_tb.pdf / fieldseq_tb.svg
|
||||
.. kernel-figure:: fieldseq_tb.svg
|
||||
:alt: fieldseq_tb.svg
|
||||
:align: center
|
||||
|
||||
Field Order, Top Field First Transmitted
|
||||
|
||||
|
||||
.. _fieldseq-bt:
|
||||
|
||||
Field Order, Bottom Field First Transmitted
|
||||
===========================================
|
||||
|
||||
.. figure:: fieldseq_bt.*
|
||||
:alt: fieldseq_bt.pdf / fieldseq_bt.svg
|
||||
.. kernel-figure:: fieldseq_bt.svg
|
||||
:alt: fieldseq_bt.svg
|
||||
:align: center
|
||||
|
||||
Field Order, Bottom Field First Transmitted
|
||||
|
|
|
@ -33,8 +33,8 @@ Layout of macroblocks in memory is presented in the following figure.
|
|||
|
||||
.. _nv12mt:
|
||||
|
||||
.. figure:: nv12mt.*
|
||||
:alt: nv12mt.pdf / nv12mt.svg
|
||||
.. kernel-figure:: nv12mt.svg
|
||||
:alt: nv12mt.svg
|
||||
:align: center
|
||||
|
||||
V4L2_PIX_FMT_NV12MT macroblock Z shape memory layout
|
||||
|
@ -50,8 +50,8 @@ interleaved. Height of the buffer is aligned to 32.
|
|||
|
||||
.. _nv12mt_ex:
|
||||
|
||||
.. figure:: nv12mt_example.*
|
||||
:alt: nv12mt_example.pdf / nv12mt_example.svg
|
||||
.. kernel-figure:: nv12mt_example.svg
|
||||
:alt: nv12mt_example.svg
|
||||
:align: center
|
||||
|
||||
Example V4L2_PIX_FMT_NV12MT memory layout of macroblocks
|
||||
|
|
|
@ -7,9 +7,9 @@ Selection targets
|
|||
|
||||
.. _sel-targets-capture:
|
||||
|
||||
.. figure:: selection.*
|
||||
:alt: selection.pdf / selection.svg
|
||||
:align: center
|
||||
.. kernel-figure:: selection.svg
|
||||
:alt: selection.svg
|
||||
:align: center
|
||||
|
||||
Cropping and composing targets
|
||||
|
||||
|
|
|
@ -1514,8 +1514,8 @@ be named ``MEDIA_BUS_FMT_SRGGB10_2X8_PADHI_LE``.
|
|||
|
||||
.. _bayer-patterns:
|
||||
|
||||
.. figure:: bayer.*
|
||||
:alt: bayer.pdf / bayer.svg
|
||||
.. kernel-figure:: bayer.svg
|
||||
:alt: bayer.svg
|
||||
:align: center
|
||||
|
||||
**Figure 4.8 Bayer Patterns**
|
||||
|
|
|
@ -45,6 +45,7 @@ For more details see the file COPYING in the source distribution of Linux.
|
|||
meye
|
||||
omap3isp
|
||||
omap4_camera
|
||||
philips
|
||||
pvrusb2
|
||||
pxa_camera
|
||||
radiotrack
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
Philips webcams (pwc driver)
|
||||
============================
|
||||
|
||||
This file contains some additional information for the Philips and OEM webcams.
|
||||
E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19
|
||||
Site: http://www.smcc.demon.nl/webcam/
|
||||
|
||||
As of this moment, the following cameras are supported:
|
||||
|
||||
* Philips PCA645
|
||||
* Philips PCA646
|
||||
* Philips PCVC675
|
||||
|
@ -89,7 +93,8 @@ power_save
|
|||
compression (only useful with the plugin)
|
||||
With this option you can control the compression factor that the camera
|
||||
uses to squeeze the image through the USB bus. You can set the
|
||||
parameter between 0 and 3:
|
||||
parameter between 0 and 3::
|
||||
|
||||
0 = prefer uncompressed images; if the requested mode is not available
|
||||
in an uncompressed format, the driver will silently switch to low
|
||||
compression.
|
||||
|
@ -109,11 +114,11 @@ compression (only useful with the plugin)
|
|||
leds
|
||||
This settings takes 2 integers, that define the on/off time for the LED
|
||||
(in milliseconds). One of the interesting things that you can do with
|
||||
this is let the LED blink while the camera is in use. This:
|
||||
this is let the LED blink while the camera is in use. This::
|
||||
|
||||
leds=500,500
|
||||
|
||||
will blink the LED once every second. But with:
|
||||
will blink the LED once every second. But with::
|
||||
|
||||
leds=0,0
|
||||
|
||||
|
@ -141,7 +146,7 @@ dev_hint
|
|||
A camera is specified by its type (the number from the camera model,
|
||||
like PCA645, PCVC750VC, etc) and optionally the serial number (visible
|
||||
in /proc/bus/usb/devices). A hint consists of a string with the following
|
||||
format:
|
||||
format::
|
||||
|
||||
[type[.serialnumber]:]node
|
||||
|
||||
|
@ -150,7 +155,7 @@ dev_hint
|
|||
would be rather pointless). The serialnumber is separated from the type
|
||||
by a '.'; the node number by a ':'.
|
||||
|
||||
This somewhat cryptic syntax is best explained by a few examples:
|
||||
This somewhat cryptic syntax is best explained by a few examples::
|
||||
|
||||
dev_hint=3,5 The first detected cam gets assigned
|
||||
/dev/video3, the second /dev/video5. Any
|
||||
|
@ -170,6 +175,7 @@ dev_hint
|
|||
through /dev/video6.
|
||||
|
||||
Some points worth knowing:
|
||||
|
||||
- Serialnumbers are case sensitive and must be written full, including
|
||||
leading zeroes (it's treated as a string).
|
||||
- If a device node is already occupied, registration will fail and
|
||||
|
@ -189,8 +195,10 @@ trace
|
|||
If you want to trace something, look up the bit value(s) in the table
|
||||
below, add the values together and supply that to the trace variable.
|
||||
|
||||
====== ======= ================================================ =======
|
||||
Value Value Description Default
|
||||
(dec) (hex)
|
||||
====== ======= ================================================ =======
|
||||
1 0x1 Module initialization; this will log messages On
|
||||
while loading and unloading the module
|
||||
|
||||
|
@ -208,6 +216,7 @@ trace
|
|||
64 0x40 Show viewport and image sizes Off
|
||||
|
||||
128 0x80 PWCX debugging Off
|
||||
====== ======= ================================================ =======
|
||||
|
||||
For example, to trace the open() & read() functions, sum 8 + 4 = 12,
|
||||
so you would supply trace=12 during insmod or modprobe. If
|
||||
|
@ -216,7 +225,7 @@ trace
|
|||
|
||||
|
||||
|
||||
Example:
|
||||
Example::
|
||||
|
||||
# modprobe pwc size=cif fps=15 power_save=1
|
||||
|
|
@ -30,7 +30,7 @@ You can try the experience changing the vendor/product ID values (look
|
|||
at the source code).
|
||||
|
||||
You can get these values by looking at /var/log/messages when you plug
|
||||
your camera, or by typing : cat /proc/bus/usb/devices.
|
||||
your camera, or by typing : cat /sys/kernel/debug/usb/devices.
|
||||
|
||||
If you manage to use your cam with this code, you can send me a mail
|
||||
(royale@zerezo.com) with the name of your cam and a patch if needed.
|
||||
|
|
|
@ -13,7 +13,7 @@ SD and MMC Device Attributes
|
|||
|
||||
All attributes are read-only.
|
||||
|
||||
cid Card Identifaction Register
|
||||
cid Card Identification Register
|
||||
csd Card Specific Data Register
|
||||
scr SD Card Configuration Register (SD only)
|
||||
date Manufacturing Date (from CID Register)
|
||||
|
@ -71,6 +71,6 @@ Note on Erase Size and Preferred Erase Size:
|
|||
"preferred_erase_size" is in bytes.
|
||||
|
||||
Note on raw_rpmb_size_mult:
|
||||
"raw_rpmb_size_mult" is a mutliple of 128kB block.
|
||||
"raw_rpmb_size_mult" is a multiple of 128kB block.
|
||||
RPMB size in byte is calculated by using the following equation:
|
||||
RPMB partition size = 128kB x raw_rpmb_size_mult
|
||||
|
|
|
@ -332,7 +332,7 @@ References
|
|||
[5] "MBIM (Mobile Broadband Interface Model) Registry"
|
||||
- http://compliance.usb.org/mbim/
|
||||
|
||||
[6] "/proc/bus/usb filesystem output"
|
||||
[6] "/dev/bus/usb filesystem output"
|
||||
- Documentation/usb/proc_usb_info.txt
|
||||
|
||||
[7] "/sys/bus/usb/devices/.../descriptors"
|
||||
|
|
|
@ -130,7 +130,7 @@ Additional Configurations
|
|||
version 1.6 or later is required for this functionality.
|
||||
|
||||
The latest release of ethtool can be found from
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
Enabling Wake on LAN* (WoL)
|
||||
---------------------------
|
||||
|
|
|
@ -435,7 +435,7 @@ Additional Configurations
|
|||
version 1.6 or later is required for this functionality.
|
||||
|
||||
The latest release of ethtool can be found from
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
Enabling Wake on LAN* (WoL)
|
||||
---------------------------
|
||||
|
|
|
@ -274,7 +274,7 @@ Additional Configurations
|
|||
diagnostics, as well as displaying statistical information. We
|
||||
strongly recommend downloading the latest version of ethtool at:
|
||||
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://kernel.org/pub/software/network/ethtool/
|
||||
|
||||
NOTE: When validating enable/disable tests on some parts (82578, for example)
|
||||
you need to add a few seconds between tests when working with ethtool.
|
||||
|
|
|
@ -63,7 +63,7 @@ Additional Configurations
|
|||
diagnostics, as well as displaying statistical information. The latest
|
||||
version of ethtool can be found at:
|
||||
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
Enabling Wake on LAN* (WoL)
|
||||
---------------------------
|
||||
|
|
|
@ -62,7 +62,7 @@ Additional Configurations
|
|||
version 3.0 or later is required for this functionality, although we
|
||||
strongly recommend downloading the latest version at:
|
||||
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
Support
|
||||
=======
|
||||
|
|
|
@ -313,7 +313,7 @@ Additional Configurations
|
|||
version 1.6 or later is required for this functionality.
|
||||
|
||||
The latest release of ethtool can be found from
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
NOTE: The ethtool version 1.6 only supports a limited set of ethtool options.
|
||||
Support for a more complete ethtool feature set can be enabled by
|
||||
|
|
|
@ -272,7 +272,7 @@ Additional Configurations
|
|||
ethtool version is required for this functionality.
|
||||
|
||||
The latest release of ethtool can be found from
|
||||
http://ftp.kernel.org/pub/software/network/ethtool/
|
||||
https://www.kernel.org/pub/software/network/ethtool/
|
||||
|
||||
FCoE
|
||||
----
|
||||
|
|
|
@ -97,7 +97,7 @@ should contain the phy name as given in the dt data and in the case of
|
|||
non-dt boot, it should contain the label of the PHY. The two
|
||||
devm_phy_get associates the device with the PHY using devres on
|
||||
successful PHY get. On driver detach, release function is invoked on
|
||||
the the devres data and devres data is freed. phy_optional_get and
|
||||
the devres data and devres data is freed. phy_optional_get and
|
||||
devm_phy_optional_get should be used when the phy is optional. These
|
||||
two functions will never return -ENODEV, but instead returns NULL when
|
||||
the phy cannot be found.Some generic drivers, such as ehci, may use multiple
|
||||
|
|
|
@ -406,7 +406,7 @@ Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
|
|||
before suspending; then remount them after resuming.
|
||||
|
||||
There is a work-around for this problem. For more information, see
|
||||
Documentation/usb/persist.txt.
|
||||
Documentation/driver-api/usb/persist.rst.
|
||||
|
||||
Q: Can I suspend-to-disk using a swap partition under LVM?
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ Coding style
|
|||
************
|
||||
|
||||
The kernel has long had a standard coding style, described in
|
||||
Documentation/process/coding-style.rst. For much of that time, the policies described
|
||||
in that file were taken as being, at most, advisory. As a result, there is
|
||||
a substantial amount of code in the kernel which does not meet the coding
|
||||
style guidelines. The presence of that code leads to two independent
|
||||
hazards for kernel developers.
|
||||
:ref:`Documentation/process/coding-style.rst <codingstyle>`. For much of
|
||||
that time, the policies described in that file were taken as being, at most,
|
||||
advisory. As a result, there is a substantial amount of code in the kernel
|
||||
which does not meet the coding style guidelines. The presence of that code
|
||||
leads to two independent hazards for kernel developers.
|
||||
|
||||
The first of these is to believe that the kernel coding standards do not
|
||||
matter and are not enforced. The truth of the matter is that adding new
|
||||
|
@ -343,9 +343,10 @@ user-space developers to know what they are working with. See
|
|||
Documentation/ABI/README for a description of how this documentation should
|
||||
be formatted and what information needs to be provided.
|
||||
|
||||
The file Documentation/admin-guide/kernel-parameters.rst describes all of the kernel's
|
||||
boot-time parameters. Any patch which adds new parameters should add the
|
||||
appropriate entries to this file.
|
||||
The file :ref:`Documentation/admin-guide/kernel-parameters.rst
|
||||
<kernelparameters>` describes all of the kernel's boot-time parameters.
|
||||
Any patch which adds new parameters should add the appropriate entries to
|
||||
this file.
|
||||
|
||||
Any new configuration options must be accompanied by help text which
|
||||
clearly explains the options and when the user might want to select them.
|
||||
|
|
|
@ -250,17 +250,11 @@ specific homes.
|
|||
|
||||
The 4.x.y (-stable) and 4.x patches live at
|
||||
|
||||
ftp://ftp.kernel.org/pub/linux/kernel/v4.x/
|
||||
https://www.kernel.org/pub/linux/kernel/v4.x/
|
||||
|
||||
The -rc patches live at
|
||||
|
||||
ftp://ftp.kernel.org/pub/linux/kernel/v4.x/testing/
|
||||
|
||||
In place of ``ftp.kernel.org`` you can use ``ftp.cc.kernel.org``, where cc is a
|
||||
country code. This way you'll be downloading from a mirror site that's most
|
||||
likely geographically closer to you, resulting in faster downloads for you,
|
||||
less bandwidth used globally and less load on the main kernel.org servers --
|
||||
these are good things, so do use mirrors when possible.
|
||||
https://www.kernel.org/pub/linux/kernel/v4.x/testing/
|
||||
|
||||
|
||||
The 4.x kernels
|
||||
|
@ -317,7 +311,7 @@ the current stable kernel.
|
|||
The -stable team usually do make incremental patches available as well
|
||||
as patches against the latest mainline release, but I only cover the
|
||||
non-incremental ones below. The incremental ones can be found at
|
||||
ftp://ftp.kernel.org/pub/linux/kernel/v4.x/incr/
|
||||
https://www.kernel.org/pub/linux/kernel/v4.x/incr/
|
||||
|
||||
These patches are not incremental, meaning that for example the 4.7.3
|
||||
patch does not apply on top of the 4.7.2 kernel source, but rather on top
|
||||
|
|
|
@ -318,9 +318,10 @@ PDF outputs, it is recommended to use version 1.4.6.
|
|||
.. note::
|
||||
|
||||
Please notice that, for PDF and LaTeX output, you'll also need ``XeLaTeX``
|
||||
version 3.14159265. Depending on the distribution, you may also need
|
||||
to install a series of ``texlive`` packages that provide the minimal
|
||||
set of functionalities required for ``XeLaTex`` to work.
|
||||
version 3.14159265. Depending on the distribution, you may also need to
|
||||
install a series of ``texlive`` packages that provide the minimal set of
|
||||
functionalities required for ``XeLaTex`` to work. For PDF output you'll also
|
||||
need ``convert(1)`` from ImageMagick (https://www.imagemagick.org).
|
||||
|
||||
Other tools
|
||||
-----------
|
||||
|
@ -348,7 +349,7 @@ Make
|
|||
Binutils
|
||||
--------
|
||||
|
||||
- <ftp://ftp.kernel.org/pub/linux/devel/binutils/>
|
||||
- <https://www.kernel.org/pub/linux/devel/binutils/>
|
||||
|
||||
OpenSSL
|
||||
-------
|
||||
|
@ -361,17 +362,17 @@ System utilities
|
|||
Util-linux
|
||||
----------
|
||||
|
||||
- <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
|
||||
- <https://www.kernel.org/pub/linux/utils/util-linux/>
|
||||
|
||||
Ksymoops
|
||||
--------
|
||||
|
||||
- <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
|
||||
- <https://www.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
|
||||
|
||||
Module-Init-Tools
|
||||
-----------------
|
||||
|
||||
- <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
|
||||
- <https://www.kernel.org/pub/linux/utils/kernel/module-init-tools/>
|
||||
|
||||
Mkinitrd
|
||||
--------
|
||||
|
@ -401,7 +402,7 @@ Xfsprogs
|
|||
Pcmciautils
|
||||
-----------
|
||||
|
||||
- <ftp://ftp.kernel.org/pub/linux/utils/kernel/pcmcia/>
|
||||
- <https://www.kernel.org/pub/linux/utils/kernel/pcmcia/>
|
||||
|
||||
Quota-tools
|
||||
-----------
|
||||
|
|
|
@ -44,7 +44,7 @@ from sphinx.domains.c import CDomain as Base_CDomain
|
|||
__version__ = '1.0'
|
||||
|
||||
# Get Sphinx version
|
||||
major, minor, patch = map(int, sphinx.__version__.split("."))
|
||||
major, minor, patch = sphinx.version_info[:3]
|
||||
|
||||
def setup(app):
|
||||
|
||||
|
|
551
Documentation/sphinx/kfigure.py
Normal file
551
Documentation/sphinx/kfigure.py
Normal file
|
@ -0,0 +1,551 @@
|
|||
# -*- coding: utf-8; mode: python -*-
|
||||
# pylint: disable=C0103, R0903, R0912, R0915
|
||||
u"""
|
||||
scalable figure and image handling
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx extension which implements scalable image handling.
|
||||
|
||||
:copyright: Copyright (C) 2016 Markus Heiser
|
||||
:license: GPL Version 2, June 1991 see Linux/COPYING for details.
|
||||
|
||||
The build for image formats depend on image's source format and output's
|
||||
destination format. This extension implement methods to simplify image
|
||||
handling from the author's POV. Directives like ``kernel-figure`` implement
|
||||
methods *to* always get the best output-format even if some tools are not
|
||||
installed. For more details take a look at ``convert_image(...)`` which is
|
||||
the core of all conversions.
|
||||
|
||||
* ``.. kernel-image``: for image handling / a ``.. image::`` replacement
|
||||
|
||||
* ``.. kernel-figure``: for figure handling / a ``.. figure::`` replacement
|
||||
|
||||
* ``.. kernel-render``: for render markup / a concept to embed *render*
|
||||
markups (or languages). Supported markups (see ``RENDER_MARKUP_EXT``)
|
||||
|
||||
- ``DOT``: render embedded Graphviz's **DOC**
|
||||
- ``SVG``: render embedded Scalable Vector Graphics (**SVG**)
|
||||
- ... *developable*
|
||||
|
||||
Used tools:
|
||||
|
||||
* ``dot(1)``: Graphviz (http://www.graphviz.org). If Graphviz is not
|
||||
available, the DOT language is inserted as literal-block.
|
||||
|
||||
* SVG to PDF: To generate PDF, you need at least one of this tools:
|
||||
|
||||
- ``convert(1)``: ImageMagick (https://www.imagemagick.org)
|
||||
|
||||
List of customizations:
|
||||
|
||||
* generate PDF from SVG / used by PDF (LaTeX) builder
|
||||
|
||||
* generate SVG (html-builder) and PDF (latex-builder) from DOT files.
|
||||
DOT: see http://www.graphviz.org/content/dot-language
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
import subprocess
|
||||
from hashlib import sha1
|
||||
import sys
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.statemachine import ViewList
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives import images
|
||||
import sphinx
|
||||
|
||||
from sphinx.util.nodes import clean_astext
|
||||
from six import iteritems
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
_unicode = str
|
||||
else:
|
||||
_unicode = unicode
|
||||
|
||||
# Get Sphinx version
|
||||
major, minor, patch = sphinx.version_info[:3]
|
||||
if major == 1 and minor > 3:
|
||||
# patches.Figure only landed in Sphinx 1.4
|
||||
from sphinx.directives.patches import Figure # pylint: disable=C0413
|
||||
else:
|
||||
Figure = images.Figure
|
||||
|
||||
__version__ = '1.0.0'
|
||||
|
||||
# simple helper
|
||||
# -------------
|
||||
|
||||
def which(cmd):
|
||||
"""Searches the ``cmd`` in the ``PATH`` enviroment.
|
||||
|
||||
This *which* searches the PATH for executable ``cmd`` . First match is
|
||||
returned, if nothing is found, ``None` is returned.
|
||||
"""
|
||||
envpath = os.environ.get('PATH', None) or os.defpath
|
||||
for folder in envpath.split(os.pathsep):
|
||||
fname = folder + os.sep + cmd
|
||||
if path.isfile(fname):
|
||||
return fname
|
||||
|
||||
def mkdir(folder, mode=0o775):
|
||||
if not path.isdir(folder):
|
||||
os.makedirs(folder, mode)
|
||||
|
||||
def file2literal(fname):
|
||||
with open(fname, "r") as src:
|
||||
data = src.read()
|
||||
node = nodes.literal_block(data, data)
|
||||
return node
|
||||
|
||||
def isNewer(path1, path2):
|
||||
"""Returns True if ``path1`` is newer than ``path2``
|
||||
|
||||
If ``path1`` exists and is newer than ``path2`` the function returns
|
||||
``True`` is returned otherwise ``False``
|
||||
"""
|
||||
return (path.exists(path1)
|
||||
and os.stat(path1).st_ctime > os.stat(path2).st_ctime)
|
||||
|
||||
def pass_handle(self, node): # pylint: disable=W0613
|
||||
pass
|
||||
|
||||
# setup conversion tools and sphinx extension
|
||||
# -------------------------------------------
|
||||
|
||||
# Graphviz's dot(1) support
|
||||
dot_cmd = None
|
||||
|
||||
# ImageMagick' convert(1) support
|
||||
convert_cmd = None
|
||||
|
||||
|
||||
def setup(app):
|
||||
# check toolchain first
|
||||
app.connect('builder-inited', setupTools)
|
||||
|
||||
# image handling
|
||||
app.add_directive("kernel-image", KernelImage)
|
||||
app.add_node(kernel_image,
|
||||
html = (visit_kernel_image, pass_handle),
|
||||
latex = (visit_kernel_image, pass_handle),
|
||||
texinfo = (visit_kernel_image, pass_handle),
|
||||
text = (visit_kernel_image, pass_handle),
|
||||
man = (visit_kernel_image, pass_handle), )
|
||||
|
||||
# figure handling
|
||||
app.add_directive("kernel-figure", KernelFigure)
|
||||
app.add_node(kernel_figure,
|
||||
html = (visit_kernel_figure, pass_handle),
|
||||
latex = (visit_kernel_figure, pass_handle),
|
||||
texinfo = (visit_kernel_figure, pass_handle),
|
||||
text = (visit_kernel_figure, pass_handle),
|
||||
man = (visit_kernel_figure, pass_handle), )
|
||||
|
||||
# render handling
|
||||
app.add_directive('kernel-render', KernelRender)
|
||||
app.add_node(kernel_render,
|
||||
html = (visit_kernel_render, pass_handle),
|
||||
latex = (visit_kernel_render, pass_handle),
|
||||
texinfo = (visit_kernel_render, pass_handle),
|
||||
text = (visit_kernel_render, pass_handle),
|
||||
man = (visit_kernel_render, pass_handle), )
|
||||
|
||||
app.connect('doctree-read', add_kernel_figure_to_std_domain)
|
||||
|
||||
return dict(
|
||||
version = __version__,
|
||||
parallel_read_safe = True,
|
||||
parallel_write_safe = True
|
||||
)
|
||||
|
||||
|
||||
def setupTools(app):
|
||||
u"""
|
||||
Check available build tools and log some *verbose* messages.
|
||||
|
||||
This function is called once, when the builder is initiated.
|
||||
"""
|
||||
global dot_cmd, convert_cmd # pylint: disable=W0603
|
||||
app.verbose("kfigure: check installed tools ...")
|
||||
|
||||
dot_cmd = which('dot')
|
||||
convert_cmd = which('convert')
|
||||
|
||||
if dot_cmd:
|
||||
app.verbose("use dot(1) from: " + dot_cmd)
|
||||
else:
|
||||
app.warn("dot(1) not found, for better output quality install "
|
||||
"graphviz from http://www.graphviz.org")
|
||||
if convert_cmd:
|
||||
app.verbose("use convert(1) from: " + convert_cmd)
|
||||
else:
|
||||
app.warn(
|
||||
"convert(1) not found, for SVG to PDF conversion install "
|
||||
"ImageMagick (https://www.imagemagick.org)")
|
||||
|
||||
|
||||
# integrate conversion tools
|
||||
# --------------------------
|
||||
|
||||
RENDER_MARKUP_EXT = {
|
||||
# The '.ext' must be handled by convert_image(..) function's *in_ext* input.
|
||||
# <name> : <.ext>
|
||||
'DOT' : '.dot',
|
||||
'SVG' : '.svg'
|
||||
}
|
||||
|
||||
def convert_image(img_node, translator, src_fname=None):
|
||||
"""Convert a image node for the builder.
|
||||
|
||||
Different builder prefer different image formats, e.g. *latex* builder
|
||||
prefer PDF while *html* builder prefer SVG format for images.
|
||||
|
||||
This function handles output image formats in dependence of source the
|
||||
format (of the image) and the translator's output format.
|
||||
"""
|
||||
app = translator.builder.app
|
||||
|
||||
fname, in_ext = path.splitext(path.basename(img_node['uri']))
|
||||
if src_fname is None:
|
||||
src_fname = path.join(translator.builder.srcdir, img_node['uri'])
|
||||
if not path.exists(src_fname):
|
||||
src_fname = path.join(translator.builder.outdir, img_node['uri'])
|
||||
|
||||
dst_fname = None
|
||||
|
||||
# in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages
|
||||
|
||||
app.verbose('assert best format for: ' + img_node['uri'])
|
||||
|
||||
if in_ext == '.dot':
|
||||
|
||||
if not dot_cmd:
|
||||
app.verbose("dot from graphviz not available / include DOT raw.")
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
|
||||
elif translator.builder.format == 'latex':
|
||||
dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
|
||||
img_node['uri'] = fname + '.pdf'
|
||||
img_node['candidates'] = {'*': fname + '.pdf'}
|
||||
|
||||
|
||||
elif translator.builder.format == 'html':
|
||||
dst_fname = path.join(
|
||||
translator.builder.outdir,
|
||||
translator.builder.imagedir,
|
||||
fname + '.svg')
|
||||
img_node['uri'] = path.join(
|
||||
translator.builder.imgpath, fname + '.svg')
|
||||
img_node['candidates'] = {
|
||||
'*': path.join(translator.builder.imgpath, fname + '.svg')}
|
||||
|
||||
else:
|
||||
# all other builder formats will include DOT as raw
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
|
||||
elif in_ext == '.svg':
|
||||
|
||||
if translator.builder.format == 'latex':
|
||||
if convert_cmd is None:
|
||||
app.verbose("no SVG to PDF conversion available / include SVG raw.")
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
else:
|
||||
dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
|
||||
img_node['uri'] = fname + '.pdf'
|
||||
img_node['candidates'] = {'*': fname + '.pdf'}
|
||||
|
||||
if dst_fname:
|
||||
# the builder needs not to copy one more time, so pop it if exists.
|
||||
translator.builder.images.pop(img_node['uri'], None)
|
||||
_name = dst_fname[len(translator.builder.outdir) + 1:]
|
||||
|
||||
if isNewer(dst_fname, src_fname):
|
||||
app.verbose("convert: {out}/%s already exists and is newer" % _name)
|
||||
|
||||
else:
|
||||
ok = False
|
||||
mkdir(path.dirname(dst_fname))
|
||||
|
||||
if in_ext == '.dot':
|
||||
app.verbose('convert DOT to: {out}/' + _name)
|
||||
ok = dot2format(app, src_fname, dst_fname)
|
||||
|
||||
elif in_ext == '.svg':
|
||||
app.verbose('convert SVG to: {out}/' + _name)
|
||||
ok = svg2pdf(app, src_fname, dst_fname)
|
||||
|
||||
if not ok:
|
||||
img_node.replace_self(file2literal(src_fname))
|
||||
|
||||
|
||||
def dot2format(app, dot_fname, out_fname):
|
||||
"""Converts DOT file to ``out_fname`` using ``dot(1)``.
|
||||
|
||||
* ``dot_fname`` pathname of the input DOT file, including extension ``.dot``
|
||||
* ``out_fname`` pathname of the output file, including format extension
|
||||
|
||||
The *format extension* depends on the ``dot`` command (see ``man dot``
|
||||
option ``-Txxx``). Normally you will use one of the following extensions:
|
||||
|
||||
- ``.ps`` for PostScript,
|
||||
- ``.svg`` or ``svgz`` for Structured Vector Graphics,
|
||||
- ``.fig`` for XFIG graphics and
|
||||
- ``.png`` or ``gif`` for common bitmap graphics.
|
||||
|
||||
"""
|
||||
out_format = path.splitext(out_fname)[1][1:]
|
||||
cmd = [dot_cmd, '-T%s' % out_format, dot_fname]
|
||||
exit_code = 42
|
||||
|
||||
with open(out_fname, "w") as out:
|
||||
exit_code = subprocess.call(cmd, stdout = out)
|
||||
if exit_code != 0:
|
||||
app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
|
||||
return bool(exit_code == 0)
|
||||
|
||||
def svg2pdf(app, svg_fname, pdf_fname):
|
||||
"""Converts SVG to PDF with ``convert(1)`` command.
|
||||
|
||||
Uses ``convert(1)`` from ImageMagick (https://www.imagemagick.org) for
|
||||
conversion. Returns ``True`` on success and ``False`` if an error occurred.
|
||||
|
||||
* ``svg_fname`` pathname of the input SVG file with extension (``.svg``)
|
||||
* ``pdf_name`` pathname of the output PDF file with extension (``.pdf``)
|
||||
|
||||
"""
|
||||
cmd = [convert_cmd, svg_fname, pdf_fname]
|
||||
# use stdout and stderr from parent
|
||||
exit_code = subprocess.call(cmd)
|
||||
if exit_code != 0:
|
||||
app.warn("Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
|
||||
return bool(exit_code == 0)
|
||||
|
||||
|
||||
# image handling
|
||||
# ---------------------
|
||||
|
||||
def visit_kernel_image(self, node): # pylint: disable=W0613
|
||||
"""Visitor of the ``kernel_image`` Node.
|
||||
|
||||
Handles the ``image`` child-node with the ``convert_image(...)``.
|
||||
"""
|
||||
img_node = node[0]
|
||||
convert_image(img_node, self)
|
||||
|
||||
class kernel_image(nodes.image):
|
||||
"""Node for ``kernel-image`` directive."""
|
||||
pass
|
||||
|
||||
class KernelImage(images.Image):
|
||||
u"""KernelImage directive
|
||||
|
||||
Earns everything from ``.. image::`` directive, except *remote URI* and
|
||||
*glob* pattern. The KernelImage wraps a image node into a
|
||||
kernel_image node. See ``visit_kernel_image``.
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
uri = self.arguments[0]
|
||||
if uri.endswith('.*') or uri.find('://') != -1:
|
||||
raise self.severe(
|
||||
'Error in "%s: %s": glob pattern and remote images are not allowed'
|
||||
% (self.name, uri))
|
||||
result = images.Image.run(self)
|
||||
if len(result) == 2 or isinstance(result[0], nodes.system_message):
|
||||
return result
|
||||
(image_node,) = result
|
||||
# wrap image node into a kernel_image node / see visitors
|
||||
node = kernel_image('', image_node)
|
||||
return [node]
|
||||
|
||||
# figure handling
|
||||
# ---------------------
|
||||
|
||||
def visit_kernel_figure(self, node): # pylint: disable=W0613
|
||||
"""Visitor of the ``kernel_figure`` Node.
|
||||
|
||||
Handles the ``image`` child-node with the ``convert_image(...)``.
|
||||
"""
|
||||
img_node = node[0][0]
|
||||
convert_image(img_node, self)
|
||||
|
||||
class kernel_figure(nodes.figure):
|
||||
"""Node for ``kernel-figure`` directive."""
|
||||
|
||||
class KernelFigure(Figure):
|
||||
u"""KernelImage directive
|
||||
|
||||
Earns everything from ``.. figure::`` directive, except *remote URI* and
|
||||
*glob* pattern. The KernelFigure wraps a figure node into a kernel_figure
|
||||
node. See ``visit_kernel_figure``.
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
uri = self.arguments[0]
|
||||
if uri.endswith('.*') or uri.find('://') != -1:
|
||||
raise self.severe(
|
||||
'Error in "%s: %s":'
|
||||
' glob pattern and remote images are not allowed'
|
||||
% (self.name, uri))
|
||||
result = Figure.run(self)
|
||||
if len(result) == 2 or isinstance(result[0], nodes.system_message):
|
||||
return result
|
||||
(figure_node,) = result
|
||||
# wrap figure node into a kernel_figure node / see visitors
|
||||
node = kernel_figure('', figure_node)
|
||||
return [node]
|
||||
|
||||
|
||||
# render handling
|
||||
# ---------------------
|
||||
|
||||
def visit_kernel_render(self, node):
|
||||
"""Visitor of the ``kernel_render`` Node.
|
||||
|
||||
If rendering tools available, save the markup of the ``literal_block`` child
|
||||
node into a file and replace the ``literal_block`` node with a new created
|
||||
``image`` node, pointing to the saved markup file. Afterwards, handle the
|
||||
image child-node with the ``convert_image(...)``.
|
||||
"""
|
||||
app = self.builder.app
|
||||
srclang = node.get('srclang')
|
||||
|
||||
app.verbose('visit kernel-render node lang: "%s"' % (srclang))
|
||||
|
||||
tmp_ext = RENDER_MARKUP_EXT.get(srclang, None)
|
||||
if tmp_ext is None:
|
||||
app.warn('kernel-render: "%s" unknow / include raw.' % (srclang))
|
||||
return
|
||||
|
||||
if not dot_cmd and tmp_ext == '.dot':
|
||||
app.verbose("dot from graphviz not available / include raw.")
|
||||
return
|
||||
|
||||
literal_block = node[0]
|
||||
|
||||
code = literal_block.astext()
|
||||
hashobj = code.encode('utf-8') # str(node.attributes)
|
||||
fname = path.join('%s-%s' % (srclang, sha1(hashobj).hexdigest()))
|
||||
|
||||
tmp_fname = path.join(
|
||||
self.builder.outdir, self.builder.imagedir, fname + tmp_ext)
|
||||
|
||||
if not path.isfile(tmp_fname):
|
||||
mkdir(path.dirname(tmp_fname))
|
||||
with open(tmp_fname, "w") as out:
|
||||
out.write(code)
|
||||
|
||||
img_node = nodes.image(node.rawsource, **node.attributes)
|
||||
img_node['uri'] = path.join(self.builder.imgpath, fname + tmp_ext)
|
||||
img_node['candidates'] = {
|
||||
'*': path.join(self.builder.imgpath, fname + tmp_ext)}
|
||||
|
||||
literal_block.replace_self(img_node)
|
||||
convert_image(img_node, self, tmp_fname)
|
||||
|
||||
|
||||
class kernel_render(nodes.General, nodes.Inline, nodes.Element):
|
||||
"""Node for ``kernel-render`` directive."""
|
||||
pass
|
||||
|
||||
class KernelRender(Figure):
|
||||
u"""KernelRender directive
|
||||
|
||||
Render content by external tool. Has all the options known from the
|
||||
*figure* directive, plus option ``caption``. If ``caption`` has a
|
||||
value, a figure node with the *caption* is inserted. If not, a image node is
|
||||
inserted.
|
||||
|
||||
The KernelRender directive wraps the text of the directive into a
|
||||
literal_block node and wraps it into a kernel_render node. See
|
||||
``visit_kernel_render``.
|
||||
"""
|
||||
has_content = True
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = False
|
||||
|
||||
# earn options from 'figure'
|
||||
option_spec = Figure.option_spec.copy()
|
||||
option_spec['caption'] = directives.unchanged
|
||||
|
||||
def run(self):
|
||||
return [self.build_node()]
|
||||
|
||||
def build_node(self):
|
||||
|
||||
srclang = self.arguments[0].strip()
|
||||
if srclang not in RENDER_MARKUP_EXT.keys():
|
||||
return [self.state_machine.reporter.warning(
|
||||
'Unknow source language "%s", use one of: %s.' % (
|
||||
srclang, ",".join(RENDER_MARKUP_EXT.keys())),
|
||||
line=self.lineno)]
|
||||
|
||||
code = '\n'.join(self.content)
|
||||
if not code.strip():
|
||||
return [self.state_machine.reporter.warning(
|
||||
'Ignoring "%s" directive without content.' % (
|
||||
self.name),
|
||||
line=self.lineno)]
|
||||
|
||||
node = kernel_render()
|
||||
node['alt'] = self.options.get('alt','')
|
||||
node['srclang'] = srclang
|
||||
literal_node = nodes.literal_block(code, code)
|
||||
node += literal_node
|
||||
|
||||
caption = self.options.get('caption')
|
||||
if caption:
|
||||
# parse caption's content
|
||||
parsed = nodes.Element()
|
||||
self.state.nested_parse(
|
||||
ViewList([caption], source=''), self.content_offset, parsed)
|
||||
caption_node = nodes.caption(
|
||||
parsed[0].rawsource, '', *parsed[0].children)
|
||||
caption_node.source = parsed[0].source
|
||||
caption_node.line = parsed[0].line
|
||||
|
||||
figure_node = nodes.figure('', node)
|
||||
for k,v in self.options.items():
|
||||
figure_node[k] = v
|
||||
figure_node += caption_node
|
||||
|
||||
node = figure_node
|
||||
|
||||
return node
|
||||
|
||||
def add_kernel_figure_to_std_domain(app, doctree):
|
||||
"""Add kernel-figure anchors to 'std' domain.
|
||||
|
||||
The ``StandardDomain.process_doc(..)`` method does not know how to resolve
|
||||
the caption (label) of ``kernel-figure`` directive (it only knows about
|
||||
standard nodes, e.g. table, figure etc.). Without any additional handling
|
||||
this will result in a 'undefined label' for kernel-figures.
|
||||
|
||||
This handle adds labels of kernel-figure to the 'std' domain labels.
|
||||
"""
|
||||
|
||||
std = app.env.domains["std"]
|
||||
docname = app.env.docname
|
||||
labels = std.data["labels"]
|
||||
|
||||
for name, explicit in iteritems(doctree.nametypes):
|
||||
if not explicit:
|
||||
continue
|
||||
labelid = doctree.nameids[name]
|
||||
if labelid is None:
|
||||
continue
|
||||
node = doctree.ids[labelid]
|
||||
|
||||
if node.tagname == 'kernel_figure':
|
||||
for n in node.next_node():
|
||||
if n.tagname == 'caption':
|
||||
sectname = clean_astext(n)
|
||||
# add label to std domain
|
||||
labels[name] = docname, labelid, sectname
|
||||
break
|
|
@ -7,13 +7,22 @@
|
|||
# fix \_
|
||||
# title line?
|
||||
#
|
||||
set -eu
|
||||
|
||||
if [ "$#" != "2" ]; then
|
||||
echo "$0 <docbook file> <rst file>"
|
||||
exit
|
||||
fi
|
||||
|
||||
DIR=$(dirname $0)
|
||||
|
||||
in=$1
|
||||
rst=$2
|
||||
tmp=$rst.tmp
|
||||
|
||||
cp $in $tmp
|
||||
sed --in-place -f convert_template.sed $tmp
|
||||
sed --in-place -f $DIR/convert_template.sed $tmp
|
||||
pandoc -s -S -f docbook -t rst -o $rst $tmp
|
||||
sed --in-place -f post_convert.sed $rst
|
||||
sed --in-place -f $DIR/post_convert.sed $rst
|
||||
rm $tmp
|
||||
echo "book writen to $rst"
|
||||
|
|
|
@ -118,7 +118,7 @@ Or:
|
|||
|
||||
Keys defined via DEFINE_STATIC_KEY_TRUE(), or DEFINE_STATIC_KEY_FALSE, may
|
||||
be used in either static_branch_likely() or static_branch_unlikely()
|
||||
statemnts.
|
||||
statements.
|
||||
|
||||
Branch(es) can be set true via:
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ dma_fence_signal(), when it has finished using (or processing) that buffer.
|
|||
Out-fences are fences that the driver creates.
|
||||
|
||||
On the other hand if the driver receives fence(s) through a sync_file from
|
||||
userspace we call these fence(s) 'in-fences'. Receiveing in-fences means that
|
||||
userspace we call these fence(s) 'in-fences'. Receiving in-fences means that
|
||||
we need to wait for the fence(s) to signal before using any buffer related to
|
||||
the in-fences.
|
||||
|
||||
|
|
|
@ -268,6 +268,15 @@ cur_state:0
|
|||
max_state:50
|
||||
type:intel_powerclamp
|
||||
|
||||
cur_state allows user to set the desired idle percentage. Writing 0 to
|
||||
cur_state will stop idle injection. Writing a value between 1 and
|
||||
max_state will start the idle injection. Reading cur_state returns the
|
||||
actual and current idle percentage. This may not be the same value
|
||||
set by the user in that current idle percentage depends on workload
|
||||
and includes natural idle. When idle injection is disabled, reading
|
||||
cur_state returns value -1 instead of 0 which is to avoid confusing
|
||||
100% busy state with the disabled state.
|
||||
|
||||
Example usage:
|
||||
- To inject 25% idle time
|
||||
$ sudo sh -c "echo 25 > /sys/class/thermal/cooling_device80/cur_state
|
||||
|
@ -278,11 +287,12 @@ then the powerclamp driver will not start idle injection. Using Top
|
|||
will not show idle injection kernel threads.
|
||||
|
||||
If the system is busy (spin test below) and has less than 25% natural
|
||||
idle time, powerclamp kernel threads will do idle injection, which
|
||||
appear running to the scheduler. But the overall system idle is still
|
||||
reflected. In this example, 24.1% idle is shown. This helps the
|
||||
system admin or user determine the cause of slowdown, when a
|
||||
powerclamp driver is in action.
|
||||
idle time, powerclamp kernel threads will do idle injection. Forced
|
||||
idle time is accounted as normal idle in that common code path is
|
||||
taken as the idle task.
|
||||
|
||||
In this example, 24.1% idle is shown. This helps the system admin or
|
||||
user determine the cause of slowdown, when a powerclamp driver is in action.
|
||||
|
||||
|
||||
Tasks: 197 total, 1 running, 196 sleeping, 0 stopped, 0 zombie
|
||||
|
|
|
@ -1,95 +1,81 @@
|
|||
NOTE:
|
||||
This is a version of Documentation/HOWTO translated into Japanese.
|
||||
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
|
||||
and the JF Project team <www.linux.or.jp/JF>.
|
||||
If you find any difference between this document and the original file
|
||||
or a problem with the translation,
|
||||
please contact the maintainer of this file or JF project.
|
||||
If you find any difference between this document and the original file or
|
||||
a problem with the translation, please contact the maintainer of this file.
|
||||
|
||||
Please also note that the purpose of this file is to be easier to read
|
||||
for non English (read: Japanese) speakers and is not intended as a
|
||||
fork. So if you have any comments or updates for this file, please try
|
||||
to update the original English file first.
|
||||
Please also note that the purpose of this file is to be easier to
|
||||
read for non English (read: Japanese) speakers and is not intended as
|
||||
a fork. So if you have any comments or updates for this file, please
|
||||
try to update the original English file first.
|
||||
|
||||
Last Updated: 2013/07/19
|
||||
==================================
|
||||
これは、
|
||||
linux-3.10/Documentation/HOWTO
|
||||
----------------------------------
|
||||
|
||||
この文書は、
|
||||
Documentation/process/howto.rst
|
||||
の和訳です。
|
||||
|
||||
翻訳団体: JF プロジェクト < http://linuxjf.sourceforge.jp/ >
|
||||
翻訳日: 2013/7/19
|
||||
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
|
||||
校正者: 松倉さん <nbh--mats at nifty dot com>
|
||||
小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
|
||||
武井伸光さん、<takei at webmasters dot gr dot jp>
|
||||
かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
|
||||
野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
|
||||
河内さん (Takayoshi Kochi) <t-kochi at bq dot jp dot nec dot com>
|
||||
岩本さん (iwamoto) <iwamoto.kn at ncos dot nec dot co dot jp>
|
||||
内田さん (Satoshi Uchida) <s-uchida at ap dot jp dot nec dot com>
|
||||
==================================
|
||||
翻訳者: Tsugikazu Shibata <tshibata@ab.jp.nec.com>
|
||||
|
||||
----------------------------------
|
||||
|
||||
Linux カーネル開発のやり方
|
||||
-------------------------------
|
||||
==========================
|
||||
|
||||
これは上のトピック( Linux カーネル開発のやり方)の重要な事柄を網羅した
|
||||
ドキュメントです。ここには Linux カーネル開発者になるための方法と
|
||||
Linux カーネル開発コミュニティと共に活動するやり方を学ぶ方法が含まれて
|
||||
います。カーネルプログラミングに関する技術的な項目に関することは何も含
|
||||
めないようにしていますが、カーネル開発者となるための正しい方向に向かう
|
||||
手助けになります。
|
||||
ドキュメントです。ここには Linux カーネル開発者になるための方法とLinux
|
||||
カーネル開発コミュニティと共に活動するやり方を学ぶ方法が含まれています。
|
||||
カーネルプログラミングに関する技術的な項目に関することは何も含めないよ
|
||||
うにしていますが、カーネル開発者となるための正しい方向に向かう手助けに
|
||||
なります。
|
||||
|
||||
もし、このドキュメントのどこかが古くなっていた場合には、このドキュメン
|
||||
トの最後にリストしたメンテナにパッチを送ってください。
|
||||
もし、このドキュメントのどこかが古くなっていた場合には、このドキュメント
|
||||
の最後にリストしたメンテナにパッチを送ってください。
|
||||
|
||||
はじめに
|
||||
---------
|
||||
|
||||
あなたは Linux カーネルの開発者になる方法を学びたいのでしょうか? そ
|
||||
れともあなたは上司から「このデバイスの Linux ドライバを書くように」と
|
||||
言われているのでしょうか?
|
||||
この文書の目的は、あなたが踏むべき手順と、コミュニティと一緒にうまく働
|
||||
くヒントを書き下すことで、あなたが知るべき全てのことを教えることです。
|
||||
また、このコミュニティがなぜ今うまくまわっているのかという理由の一部も
|
||||
説明しようと試みています。
|
||||
あなたは Linux カーネルの開発者になる方法を学びたいのでしょうか? そ
|
||||
れとも上司から「このデバイスの Linux ドライバを書くように」と言われた
|
||||
のかもしれません。この文書の目的は、あなたが踏むべき手順と、コミュニティ
|
||||
と一緒にうまく働くヒントを書き下すことで、あなたが知るべき全てのことを
|
||||
教えることです。また、このコミュニティがなぜ今うまくまわっているのかと
|
||||
いう理由も説明しようと試みています。
|
||||
|
||||
カーネルは少量のアーキテクチャ依存部分がアセンブリ言語で書かれている以
|
||||
外の大部分は C 言語で書かれています。C言語をよく理解していることはカー
|
||||
ネル開発に必要です。低レベルのアーキテクチャ開発をするのでなければ、
|
||||
(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要ありません。以下
|
||||
の本は、C 言語の十分な知識や何年もの経験に取って代わるものではありませ
|
||||
んが、少なくともリファレンスとしては良い本です。
|
||||
|
||||
カーネルは 少量のアーキテクチャ依存部分がアセンブリ言語で書かれている
|
||||
以外は大部分は C 言語で書かれています。C言語をよく理解していることはカー
|
||||
ネル開発者には必要です。アーキテクチャ向けの低レベル部分の開発をするの
|
||||
でなければ、(どんなアーキテクチャでも)アセンブリ(訳注: 言語)は必要あり
|
||||
ません。以下の本は、C 言語の十分な知識や何年もの経験に取って代わるもの
|
||||
ではありませんが、少なくともリファレンスとしては良い本です。
|
||||
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
|
||||
-『プログラミング言語C第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
|
||||
- 『プログラミング言語C第2版』(B.W. カーニハン/D.M. リッチー著 石田晴久訳) [共立出版]
|
||||
- "Practical C Programming" by Steve Oualline [O'Reilly]
|
||||
- 『C実践プログラミング第3版』(Steve Oualline著 望月康司監訳 谷口功訳) [オライリージャパン]
|
||||
- "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
|
||||
- 『新・詳説 C 言語 H&S リファレンス』
|
||||
(サミュエル P ハービソン/ガイ L スティール共著 斉藤 信男監訳)[ソフトバンク]
|
||||
- 『新・詳説 C 言語 H&S リファレンス』 (サミュエル P ハービソン/ガイ L スティール共著 斉藤 信男監訳)[ソフトバンク]
|
||||
|
||||
カーネルは GNU C と GNU ツールチェインを使って書かれています。カーネル
|
||||
は ISO C89 仕様に準拠して書く一方で、標準には無い言語拡張を多く使って
|
||||
います。カーネルは標準 C ライブラリとは関係がないといった、C 言語フリー
|
||||
スタンディング環境です。そのため、C の標準で使えないものもあります。任
|
||||
意の long long の除算や浮動小数点は使えません。
|
||||
ときどき、カーネルがツールチェインや C 言語拡張に置いている前提がどう
|
||||
なっているのかわかりにくいことがあり、また、残念なことに決定的なリファ
|
||||
レンスは存在しません。情報を得るには、gcc の info ページ( info gcc )を
|
||||
見てください。
|
||||
います。カーネルは標準 C ライブラリに依存しない、C 言語非依存環境です。
|
||||
そのため、C の標準の中で使えないものもあります。特に任意の long long
|
||||
の除算や浮動小数点は使えません。カーネルがツールチェインや C 言語拡張
|
||||
に置いている前提がどうなっているのかわかりにくいことが時々あり、また、
|
||||
残念なことに決定的なリファレンスは存在しません。情報を得るには、gcc の
|
||||
info ページ( info gcc )を見てください。
|
||||
|
||||
あなたは既存の開発コミュニティと一緒に作業する方法を学ぼうとしているこ
|
||||
とに留意してください。そのコミュニティは、コーディング、スタイル、
|
||||
開発手順について高度な標準を持つ、多様な人の集まりです。
|
||||
地理的に分散した大規模なチームに対してもっともうまくいくとわかったこと
|
||||
をベースにしながら、これらの標準は長い時間をかけて築かれてきました。
|
||||
これらはきちんと文書化されていますから、事前にこれらの標準についてでき
|
||||
るだけたくさん学んでください。また皆があなたやあなたの会社のやり方に合わ
|
||||
せてくれると思わないでください。
|
||||
とに思い出してください。そのコミュニティは、コーディング、スタイル、開
|
||||
発手順について高度な標準を持つ、多様な人の集まりです。地理的に分散した
|
||||
大規模なチームに対してもっともうまくいくとわかったことをベースにしなが
|
||||
ら、これらの標準は長い時間をかけて築かれてきました。これらはきちんと文
|
||||
書化されていますから、事前にこれらの標準について事前にできるだけたくさ
|
||||
ん学んでください。また皆があなたやあなたの会社のやり方に合わせてくれる
|
||||
と思わないでください。
|
||||
|
||||
法的問題
|
||||
------------
|
||||
--------
|
||||
|
||||
Linux カーネルのソースコードは GPL ライセンスの下でリリースされていま
|
||||
す。ライセンスの詳細については、ソースツリーのメインディレクトリに存在
|
||||
|
@ -98,8 +84,9 @@ Linux カーネルのソースコードは GPL ライセンスの下でリリー
|
|||
法律家に相談してください。メーリングリストの人達は法律家ではなく、法的
|
||||
問題については彼らの声明はあてにするべきではありません。
|
||||
|
||||
GPL に関する共通の質問や回答については、以下を参照してください。
|
||||
http://www.gnu.org/licenses/gpl-faq.html
|
||||
GPL に関する共通の質問や回答については、以下を参照してください-
|
||||
|
||||
https://www.gnu.org/licenses/gpl-faq.html
|
||||
|
||||
ドキュメント
|
||||
------------
|
||||
|
@ -119,111 +106,129 @@ linux-api@vger.kernel.org に送ることを勧めます。
|
|||
README
|
||||
このファイルは Linuxカーネルの簡単な背景とカーネルを設定(訳注
|
||||
configure )し、生成(訳注 build )するために必要なことは何かが書かれ
|
||||
ています。カーネルに関して初めての人はここからスタートすると良いで
|
||||
しょう。
|
||||
ています。 カーネルに関して初めての人はここからスタートすると良い
|
||||
でしょう。
|
||||
|
||||
Documentation/Changes
|
||||
このファイルはカーネルをうまく生成(訳注 build )し、走らせるのに最
|
||||
小限のレベルで必要な数々のソフトウェアパッケージの一覧を示してい
|
||||
ます。
|
||||
:ref:`Documentation/Process/changes.rst <changes>`
|
||||
このファイルはカーネルをうまく生成(訳注 build )し、走らせるのに最
|
||||
小限のレベルで必要な数々のソフトウェアパッケージの一覧を示してい
|
||||
ます。
|
||||
|
||||
Documentation/process/coding-style.rst
|
||||
:ref:`Documentation/process/coding-style.rst <codingstyle>`
|
||||
これは Linux カーネルのコーディングスタイルと背景にある理由を記述
|
||||
しています。全ての新しいコードはこのドキュメントにあるガイドライン
|
||||
に従っていることを期待されています。大部分のメンテナはこれらのルー
|
||||
ルに従っているものだけを受け付け、多くの人は正しいスタイルのコード
|
||||
だけをレビューします。
|
||||
|
||||
Documentation/process/submitting-patches.rst
|
||||
Documentation/process/submitting-drivers.rst
|
||||
これらのファイルには、どうやってうまくパッチを作って投稿するかに
|
||||
ついて非常に詳しく書かれており、以下を含みます(これだけに限らない
|
||||
けれども)
|
||||
- Email に含むこと
|
||||
- Email の形式
|
||||
- だれに送るか
|
||||
これらのルールに従えばうまくいくことを保証することではありません
|
||||
が (すべてのパッチは内容とスタイルについて精査を受けるので)、
|
||||
ルールに従わなければ間違いなくうまくいかないでしょう。
|
||||
:ref:`Documentation/process/submitting-patches.rst <codingstyle>` と :ref:`Documentation/process/submitting-drivers.rst <submittingdrivers>`
|
||||
これらのファイルには、どうやってうまくパッチを作って投稿するかにつ
|
||||
いて非常に詳しく書かれており、以下を含みます (これだけに限らない
|
||||
けれども)
|
||||
|
||||
この他にパッチを作る方法についてのよくできた記述は-
|
||||
- Email に含むこと
|
||||
- Email の形式
|
||||
- だれに送るか
|
||||
|
||||
"The Perfect Patch"
|
||||
これらのルールに従えばうまくいくことを保証することではありません
|
||||
が (すべてのパッチは内容とスタイルについて精査を受けるので)、
|
||||
ルールに従わなければ間違いなくうまくいかないでしょう。
|
||||
|
||||
この他にパッチを作る方法についてのよくできた記述は-
|
||||
|
||||
"The Perfect Patch"
|
||||
http://www.ozlabs.org/~akpm/stuff/tpp.txt
|
||||
"Linux kernel patch submission format"
|
||||
"Linux kernel patch submission format"
|
||||
http://linux.yyz.us/patch-format.html
|
||||
|
||||
Documentation/process/stable-api-nonsense.rst
|
||||
このファイルはカーネルの中に不変のAPIを持たないことにした意識的な
|
||||
決断の背景にある理由について書かれています。以下のようなことを含
|
||||
んでいます-
|
||||
- サブシステムとの間に層を作ること(コンパチビリティのため?)
|
||||
- オペレーティングシステム間のドライバの移植性
|
||||
- カーネルソースツリーの素早い変更を遅らせる(もしくは素早い変更
|
||||
を妨げる)
|
||||
このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
|
||||
そして、他のOSでの開発者が Linux に移る時にとても重要です。
|
||||
:ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
|
||||
このファイルはカーネルの中に不変の API を持たないことにした意識的
|
||||
な決断の背景にある理由について書かれています。以下のようなことを含
|
||||
んでいます-
|
||||
|
||||
Documentation/admin-guide/security-bugs.rst
|
||||
- サブシステムとの間に層を作ること(コンパチビリティのため?)
|
||||
- オペレーティングシステム間のドライバの移植性
|
||||
- カーネルソースツリーの素早い変更を遅らせる(もしくは素早い変更を妨げる)
|
||||
|
||||
このドキュメントは Linux 開発の思想を理解するのに非常に重要です。
|
||||
そして、他のOSでの開発者が Linux に移る時にとても重要です。
|
||||
|
||||
:ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
|
||||
もし Linux カーネルでセキュリティ問題を発見したように思ったら、こ
|
||||
のドキュメントのステップに従ってカーネル開発者に連絡し、問題解決を
|
||||
支援してください。
|
||||
|
||||
Documentation/process/management-style.rst
|
||||
:ref:`Documentation/process/management-style.rst <managementstyle>`
|
||||
このドキュメントは Linux カーネルのメンテナ達がどう行動するか、
|
||||
彼らの手法の背景にある共有されている精神について記述しています。こ
|
||||
れはカーネル開発の初心者なら(もしくは、単に興味があるだけの人でも)
|
||||
重要です。なぜならこのドキュメントは、カーネルメンテナ達の独特な
|
||||
行動についての多くの誤解や混乱を解消するからです。
|
||||
|
||||
Documentation/process/stable-kernel-rules.rst
|
||||
:ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
|
||||
このファイルはどのように stable カーネルのリリースが行われるかのルー
|
||||
ルが記述されています。そしてこれらのリリースの中のどこかで変更を取
|
||||
り入れてもらいたい場合に何をすれば良いかが示されています。
|
||||
|
||||
Documentation/process/kernel-docs.rst
|
||||
カーネル開発に付随する外部ドキュメントのリストです。もしあなたが
|
||||
探しているものがカーネル内のドキュメントでみつからなかった場合、
|
||||
このリストをあたってみてください。
|
||||
:Ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
|
||||
カーネル開発に付随する外部ドキュメントのリストです。もしあなたが探
|
||||
しているものがカーネル内のドキュメントでみつからなかった場合、この
|
||||
リストをあたってみてください。
|
||||
|
||||
Documentation/process/applying-patches.rst
|
||||
:ref:`Documentation/process/applying-patches.rst <applying_patches>`
|
||||
パッチとはなにか、パッチをどうやって様々なカーネルの開発ブランチに
|
||||
適用するのかについて正確に記述した良い入門書です。
|
||||
|
||||
カーネルはソースコードから自動的に生成可能な多数のドキュメントを自分自
|
||||
身でもっています。これにはカーネル内 API のすべての記述や、どう正しく
|
||||
ロックをかけるかの規則が含まれます。このドキュメントは
|
||||
Documentation/DocBook/ ディレクトリに作られ、以下のように
|
||||
make pdfdocs
|
||||
make psdocs
|
||||
make htmldocs
|
||||
make mandocs
|
||||
コマンドを実行するとメインカーネルのソースディレクトリから
|
||||
それぞれ、PDF, Postscript, HTML, man page の形式で生成されます。
|
||||
カーネルはソースコードそのものや、このファイルのようなリストラクチャー
|
||||
ドテキストマークアップ(ReST)から自動的に生成可能な多数のドキュメントを
|
||||
もっています。これにはカーネル内APIの完全な記述や、正しくロックをかけ
|
||||
るための規則などが含まれます。
|
||||
|
||||
これら全てのドキュメントを PDF や HTML で生成するには以下を実行します - ::
|
||||
|
||||
make pdfdocs
|
||||
make htmldocs
|
||||
|
||||
それぞれメインカーネルのソースディレクトリから実行します。
|
||||
|
||||
ReSTマークアップを使ったドキュメントは Documentation/outputに生成され
|
||||
ます。Latex とePub 形式で生成するには - ::
|
||||
|
||||
make latexdocs
|
||||
make epubdocs
|
||||
|
||||
現在、幾つかの DocBook形式で書かれたドキュメントは ReST形式に転換中で
|
||||
す。それらのドキュメントはDocumentation/DocBook ディレクトリに生成され、
|
||||
Postscript または man ページの形式を生成するには以下のようにします - ::
|
||||
|
||||
make psdocs
|
||||
make mandocs
|
||||
|
||||
カーネル開発者になるには
|
||||
---------------------------
|
||||
------------------------
|
||||
|
||||
もしあなたが、Linux カーネル開発について何も知らないならば、
|
||||
もしあなたが、Linux カーネル開発について何も知らないのならば、
|
||||
KernelNewbies プロジェクトを見るべきです
|
||||
http://kernelnewbies.org
|
||||
|
||||
https://kernelnewbies.org
|
||||
|
||||
このサイトには役に立つメーリングリストがあり、基本的なカーネル開発に関
|
||||
するほとんどどんな種類の質問もできます (既に回答されているようなことを
|
||||
聞く前にまずはアーカイブを調べてください)。
|
||||
またここには、リアルタイムで質問を聞くことができる IRC チャネルや、Linux
|
||||
カーネルの開発に関して学ぶのに便利なたくさんの役に立つドキュメントがあ
|
||||
ります。
|
||||
聞く前にまずはアーカイブを調べてください)。またここには、リアルタイム
|
||||
で質問を聞くことができる IRC チャネルや、Linuxカーネルの開発に関して学
|
||||
ぶのに便利なたくさんの役に立つドキュメントがあります。
|
||||
|
||||
web サイトには、コードの構成、サブシステム、現在存在するプロジェクト(ツ
|
||||
リーにあるもの無いものの両方)の基本的な管理情報があります。
|
||||
ここには、また、カーネルのコンパイルのやり方やパッチの当て方などの間接
|
||||
的な基本情報も記述されています。
|
||||
Web サイトには、コードの構成、サブシステム、現在存在するプロジェクト
|
||||
(ツリーにあるもの無いものの両方)の基本的な管理情報があります。ここには、
|
||||
また、カーネルのコンパイルのやり方やパッチの当て方などの間接的な基本情
|
||||
報も記述されています。
|
||||
|
||||
あなたがどこからスタートして良いかわからないが、Linux カーネル開発コミュ
|
||||
ニティに参加して何かすることをさがしている場合には、Linux kernel
|
||||
ニティに参加して何かすることをさがしているのであれば、Linux kernel
|
||||
Janitor's プロジェクトにいけば良いでしょう -
|
||||
http://kernelnewbies.org/KernelJanitors
|
||||
|
||||
https://kernelnewbies.org/KernelJanitors
|
||||
|
||||
ここはそのようなスタートをするのにうってつけの場所です。ここには、
|
||||
Linux カーネルソースツリーの中に含まれる、きれいにし、修正しなければな
|
||||
らない、単純な問題のリストが記述されています。このプロジェクトに関わる
|
||||
|
@ -232,10 +237,11 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
|
|||
ていない場合には、次にやる仕事の方向性が見えてくるかもしれません。
|
||||
|
||||
もしあなたが、すでにひとまとまりコードを書いていて、カーネルツリーに入
|
||||
れたいと思っていたり、それに関する適切な支援を求めたい場合、カーネル
|
||||
メンターズプロジェクトはそのような皆さんを助けるためにできました。
|
||||
ここにはメーリングリストがあり、以下から参照できます
|
||||
http://selenic.com/mailman/listinfo/kernel-mentors
|
||||
れたいと思っていたり、それに関する適切な支援を求めたい場合、カーネルメ
|
||||
ンターズプロジェクトはそのような皆さんを助けるためにできました。ここに
|
||||
はメーリングリストがあり、以下から参照できます -
|
||||
|
||||
https://selenic.com/mailman/listinfo/kernel-mentors
|
||||
|
||||
実際に Linux カーネルのコードについて修正を加える前に、どうやってその
|
||||
コードが動作するのかを理解することが必要です。そのためには、特別なツー
|
||||
|
@ -244,27 +250,29 @@ Linux カーネルソースツリーの中に含まれる、きれいにし、
|
|||
特におすすめなのは、Linux クロスリファレンスプロジェクトです。これは、
|
||||
自己参照方式で、索引がついた web 形式で、ソースコードを参照することが
|
||||
できます。この最新の素晴しいカーネルコードのリポジトリは以下で見つかり
|
||||
ます-
|
||||
ます -
|
||||
|
||||
http://lxr.free-electrons.com/
|
||||
|
||||
開発プロセス
|
||||
-----------------------
|
||||
------------
|
||||
|
||||
Linux カーネルの開発プロセスは現在幾つかの異なるメインカーネル「ブラン
|
||||
チ」と多数のサブシステム毎のカーネルブランチから構成されます。
|
||||
これらのブランチとは-
|
||||
- メインの 3.x カーネルツリー
|
||||
- 3.x.y -stable カーネルツリー
|
||||
- 3.x -git カーネルパッチ
|
||||
チ」と多数のサブシステム毎のカーネルブランチから構成されます。これらの
|
||||
ブランチとは -
|
||||
|
||||
- メインの 4.x カーネルツリー
|
||||
- 4.x.y -stable カーネルツリー
|
||||
- 4.x -git カーネルパッチ
|
||||
- サブシステム毎のカーネルツリーとパッチ
|
||||
- 統合テストのための 3.x -next カーネルツリー
|
||||
- 統合テストのための 4.x -next カーネルツリー
|
||||
|
||||
3.x カーネルツリー
|
||||
-----------------
|
||||
4.x カーネルツリー
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
3.x カーネルは Linus Torvalds によってメンテナンスされ、kernel.org
|
||||
の pub/linux/kernel/v3.x/ ディレクトリに存在します。この開発プロセスは
|
||||
以下のとおり-
|
||||
4.x カーネルは Linus Torvalds によってメンテナンスされ、
|
||||
https://kernel.org の pub/linux/kernel/v4.x/ ディレクトリに存在します。
|
||||
この開発プロセスは以下のとおり -
|
||||
|
||||
- 新しいカーネルがリリースされた直後に、2週間の特別期間が設けられ、
|
||||
この期間中に、メンテナ達は Linus に大きな差分を送ることができます。
|
||||
|
@ -272,7 +280,6 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
|||
大きな変更は git(カーネルのソース管理ツール、詳細は
|
||||
http://git-scm.com/ 参照) を使って送るのが好ましいやり方ですが、パッ
|
||||
チファイルの形式のまま送るのでも十分です。
|
||||
|
||||
- 2週間後、-rc1 カーネルがリリースされ、この後にはカーネル全体の安定
|
||||
性に影響をあたえるような新機能は含まない類のパッチしか取り込むこと
|
||||
はできません。新しいドライバ(もしくはファイルシステム)のパッチは
|
||||
|
@ -282,44 +289,45 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
|||
Linus へパッチを送付するのに git を使うこともできますが、パッチは
|
||||
レビューのために、パブリックなメーリングリストへも同時に送る必要が
|
||||
あります。
|
||||
|
||||
- 新しい -rc は Linus が、最新の git ツリーがテスト目的であれば十分
|
||||
に安定した状態にあると判断したときにリリースされます。目標は毎週新
|
||||
しい -rc カーネルをリリースすることです。
|
||||
|
||||
- このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
|
||||
す。このプロセスはだいたい 6週間継続します。
|
||||
|
||||
Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ
|
||||
て書いたことをここで言っておくことは価値があります-
|
||||
「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現
|
||||
実に認識されたバグの状況によりリリースされるのであり、前もって決めら
|
||||
れた計画によってリリースされるものではないからです。」
|
||||
て書いたことをここで言っておくことは価値があります -
|
||||
|
||||
3.x.y -stable カーネルツリー
|
||||
---------------------------
|
||||
*「カーネルがいつリリースされるかは誰も知りません。なぜなら、
|
||||
これは現実に認識されたバグの状況によりリリースされるのであり、
|
||||
前もって決められた計画によってリリースされるものではないから
|
||||
です。」*
|
||||
|
||||
4.x.y -stable カーネルツリー
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
バージョン番号が3つの数字に分かれているカーネルは -stable カーネルです。
|
||||
これには、3.x カーネルで見つかったセキュリティ問題や重大な後戻りに対
|
||||
する比較的小さい重要な修正が含まれます。
|
||||
これには、4.x カーネルで見つかったセキュリティ問題や重大な後戻りに対す
|
||||
る比較的小さい重要な修正が含まれます。
|
||||
|
||||
これは、開発/実験的バージョンのテストに協力することに興味が無く、
|
||||
最新の安定したカーネルを使いたいユーザに推奨するブランチです。
|
||||
これは、開発/実験的バージョンのテストに協力することに興味が無く、最新
|
||||
の安定したカーネルを使いたいユーザに推奨するブランチです。
|
||||
|
||||
もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が
|
||||
最新の安定版カーネルです。
|
||||
もし、4.x.y カーネルが存在しない場合には、番号が一番大きい 4.x が最新
|
||||
の安定版カーネルです。
|
||||
|
||||
3.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、必
|
||||
要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
|
||||
た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
|
||||
の場合はこれに対してだいたいの場合、すぐにリリースがされます。
|
||||
4.x.y は "stable" チーム <stable@vger.kernel.org> でメンテされており、
|
||||
必要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差
|
||||
し迫った問題がなければもう少し長くなることもあります。セキュリティ関
|
||||
連の問題の場合はこれに対してだいたいの場合、すぐにリリースがされます。
|
||||
|
||||
カーネルツリーに入っている、Documentation/process/stable-kernel-rules.rst ファ
|
||||
イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ
|
||||
リースプロセスがどう動くかが記述されています。
|
||||
カーネルツリーに入っている、
|
||||
Documentation/process/stable-kernel-rules.rst ファイルにはどのような種
|
||||
類の変更が -stable ツリーに受け入れ可能か、またリリースプロセスがどう
|
||||
動くかが記述されています。
|
||||
|
||||
3.x -git パッチ
|
||||
------------------
|
||||
4.x -git パッチ
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
git リポジトリで管理されているLinus のカーネルツリーの毎日のスナップ
|
||||
ショットがあります。(だから -git という名前がついています)。これらのパッ
|
||||
|
@ -328,7 +336,7 @@ git リポジトリで管理されているLinus のカーネルツリーの毎
|
|||
に生成されるので、より実験的です。
|
||||
|
||||
サブシステム毎のカーネルツリーとパッチ
|
||||
-------------------------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
それぞれのカーネルサブシステムのメンテナ達は --- そして多くのカーネル
|
||||
サブシステムの開発者達も --- 各自の最新の開発状況をソースリポジトリに
|
||||
|
@ -340,42 +348,45 @@ git リポジトリで管理されているLinus のカーネルツリーの毎
|
|||
大部分のこれらのリポジトリは git ツリーです。しかしその他の SCM や
|
||||
quilt シリーズとして公開されているパッチキューも使われています。これら
|
||||
のサブシステムリポジトリのアドレスは MAINTAINERS ファイルにリストされ
|
||||
ています。これらの多くは http://git.kernel.org/ で参照することができま
|
||||
ています。これらの多くは https://git.kernel.org/ で参照することができま
|
||||
す。
|
||||
|
||||
提案されたパッチがこのようなサブシステムツリーにコミットされる前に、メー
|
||||
リングリストで事前にレビューにかけられます(以下の対応するセクションを
|
||||
参照)。いくつかのカーネルサブシステムでは、このレビューは patchwork
|
||||
というツールによって追跡されます。Patchwork は web インターフェイスに
|
||||
よってパッチ投稿の表示、パッチへのコメント付けや改訂などができ、そして
|
||||
メンテナはパッチに対して、レビュー中、受付済み、拒否というようなマーク
|
||||
をつけることができます。大部分のこれらの patchwork のサイトは
|
||||
http://patchwork.kernel.org/ でリストされています。
|
||||
参照)。いくつかのカーネルサブシステムでは、このレビューは patchworkと
|
||||
いうツールによって追跡されます。Patchwork は web インターフェイスによっ
|
||||
てパッチ投稿の表示、パッチへのコメント付けや改訂などができ、そしてメン
|
||||
テナはパッチに対して、レビュー中、受付済み、拒否というようなマークをつ
|
||||
けることができます。大部分のこれらの patchwork のサイトは
|
||||
https://patchwork.kernel.org/ でリストされています。
|
||||
|
||||
統合テストのための 3.x -next カーネルツリー
|
||||
---------------------------------------------
|
||||
統合テストのための 4.x -next カーネルツリー
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
サブシステムツリーの更新内容がメインラインの 3.x ツリーにマージされ
|
||||
る前に、それらは統合テストされる必要があります。この目的のため、実質的
|
||||
に全サブシステムツリーからほぼ毎日プルされてできる特別なテスト用のリ
|
||||
ポジトリが存在します-
|
||||
http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
|
||||
サブシステムツリーの更新内容がメインラインの 4.x ツリーにマージされる
|
||||
前に、それらは統合テストされる必要があります。この目的のため、実質的に
|
||||
全サブシステムツリーからほぼ毎日プルされてできる特別なテスト用のリポジ
|
||||
トリが存在します-
|
||||
|
||||
https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
|
||||
|
||||
このやり方によって、-next カーネルは次のマージ機会でどんなものがメイン
|
||||
ラインカーネルにマージされるか、おおまかなの展望を提供します。-next
|
||||
カーネルの実行テストを行う冒険好きなテスターは大いに歓迎されます
|
||||
ラインカーネルにマージされるか、おおまかなの展望を提供します。-next カー
|
||||
ネルの実行テストを行う冒険好きなテスターは大いに歓迎されます。
|
||||
|
||||
バグレポート
|
||||
-------------
|
||||
|
||||
bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
|
||||
場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。
|
||||
どう kernel bugzilla を使うかの詳細は、以下を参照してください-
|
||||
http://bugzilla.kernel.org/page.cgi?id=faq.html
|
||||
メインカーネルソースディレクトリにあるファイル admin-guide/reporting-bugs.rst はカーネ
|
||||
ルバグらしいものについてどうレポートするかの良いテンプレートであり、問
|
||||
題の追跡を助けるためにカーネル開発者にとってどんな情報が必要なのかの詳
|
||||
細が書かれています。
|
||||
https://bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
|
||||
場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。どう
|
||||
kernel bugzilla を使うかの詳細は、以下を参照してください -
|
||||
|
||||
https://bugzilla.kernel.org/page.cgi?id=faq.html
|
||||
|
||||
メインカーネルソースディレクトリにあるファイル
|
||||
admin-guide/reporting-bugs.rstはカーネルバグらしいものについてどうレポー
|
||||
トするかの良いテンプレートであり、問題の追跡を助けるためにカーネル開発
|
||||
者にとってどんな情報が必要なのかの詳細が書かれています。
|
||||
|
||||
バグレポートの管理
|
||||
-------------------
|
||||
|
@ -383,74 +394,78 @@ bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを
|
|||
あなたのハッキングのスキルを訓練する最高の方法のひとつに、他人がレポー
|
||||
トしたバグを修正することがあります。あなたがカーネルをより安定化させる
|
||||
こに寄与するということだけでなく、あなたは 現実の問題を修正することを
|
||||
学び、自分のスキルも強化でき、また他の開発者があなたの存在に気がつき
|
||||
ます。バグを修正することは、多くの開発者の中から自分が功績をあげる最善
|
||||
の道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好ま
|
||||
ないからです。
|
||||
学び、自分のスキルも強化でき、また他の開発者があなたの存在に気がつきま
|
||||
す。バグを修正することは、多くの開発者の中から自分が功績をあげる最善の
|
||||
道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好まな
|
||||
いからです。
|
||||
|
||||
すでにレポートされたバグのために仕事をするためには、
|
||||
http://bugzilla.kernel.org に行ってください。もし今後のバグレポートに
|
||||
https://bugzilla.kernel.org に行ってください。もし今後のバグレポートに
|
||||
ついてアドバイスを受けたいのであれば、bugme-new メーリングリスト(新し
|
||||
いバグレポートだけがここにメールされる) または bugme-janitor メーリン
|
||||
グリスト(bugzilla の変更毎にここにメールされる)を購読できます。
|
||||
|
||||
http://lists.linux-foundation.org/mailman/listinfo/bugme-new
|
||||
http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
|
||||
https://lists.linux-foundation.org/mailman/listinfo/bugme-new
|
||||
|
||||
https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
|
||||
|
||||
メーリングリスト
|
||||
-------------
|
||||
----------------
|
||||
|
||||
上のいくつかのドキュメントで述べていますが、コアカーネル開発者の大部分
|
||||
は Linux kernel メーリングリストに参加しています。このリストの登録/脱
|
||||
退の方法については以下を参照してください-
|
||||
|
||||
http://vger.kernel.org/vger-lists.html#linux-kernel
|
||||
|
||||
このメーリングリストのアーカイブは web 上の多数の場所に存在します。こ
|
||||
れらのアーカイブを探すにはサーチエンジンを使いましょう。例えば-
|
||||
|
||||
http://dir.gmane.org/gmane.linux.kernel
|
||||
|
||||
リストに投稿する前にすでにその話題がアーカイブに存在するかどうかを検索
|
||||
することを是非やってください。多数の事がすでに詳細に渡って議論されて
|
||||
おり、アーカイブにのみ記録されています。
|
||||
することを是非やってください。多数の事がすでに詳細に渡って議論されてお
|
||||
り、アーカイブにのみ記録されています。
|
||||
|
||||
大部分のカーネルサブシステムも自分の個別の開発を実施するメーリングリス
|
||||
トを持っています。個々のグループがどんなリストを持っているかは、
|
||||
MAINTAINERS ファイルにリストがありますので参照してください。
|
||||
|
||||
多くのリストは kernel.org でホストされています。これらの情報は以下にあ
|
||||
ります-
|
||||
ります -
|
||||
|
||||
http://vger.kernel.org/vger-lists.html
|
||||
|
||||
メーリングリストを使う場合、良い行動習慣に従うようにしましょう。
|
||||
少し安っぽいが、以下の URL は上のリスト(や他のリスト)で会話する場合の
|
||||
シンプルなガイドラインを示しています-
|
||||
メーリングリストを使う場合、良い行動習慣に従うようにしましょう。少し安っ
|
||||
ぽいが、以下の URL は上のリスト(や他のリスト)で会話する場合のシンプル
|
||||
なガイドラインを示しています -
|
||||
|
||||
http://www.albion.com/netiquette/
|
||||
|
||||
もし複数の人があなたのメールに返事をした場合、CC: で受ける人のリストは
|
||||
だいぶ多くなるでしょう。良い理由がない場合、CC: リストから誰かを削除を
|
||||
しないように、また、メーリングリストのアドレスだけにリプライすることの
|
||||
ないようにしましょう。1つは送信者から、もう1つはリストからのように、メー
|
||||
ルを2回受けることになってもそれに慣れ、しゃれたメールヘッダーを追加し
|
||||
てこの状態を変えようとしないように。人々はそのようなことは好みません。
|
||||
だいぶ多くなるでしょう。正当な理由がない限り、CC: リストから誰かを削除
|
||||
をしないように、また、メーリングリストのアドレスだけにリプライすること
|
||||
のないようにしましょう。1つは送信者から、もう1つはリストからのように、
|
||||
メールを2回受けることになってもそれに慣れ、しゃれたメールヘッダーを追
|
||||
加してこの状態を変えようとしないように。人々はそのようなことは好みませ
|
||||
ん。
|
||||
|
||||
今までのメールでのやりとりとその間のあなたの発言はそのまま残し、
|
||||
"John Kernelhacker wrote ...:" の行をあなたのリプライの先頭行にして、
|
||||
メールの先頭でなく、各引用行の間にあなたの言いたいことを追加するべきで
|
||||
す。
|
||||
|
||||
もしパッチをメールに付ける場合は、Documentation/process/submitting-patches.rst に提
|
||||
示されているように、それは プレーンな可読テキストにすることを忘れない
|
||||
ようにしましょう。カーネル開発者は 添付や圧縮したパッチを扱いたがりま
|
||||
せん-
|
||||
彼らはあなたのパッチの行毎にコメントを入れたいので、そのためにはそうす
|
||||
るしかありません。あなたのメールプログラムが空白やタブを圧縮しないよう
|
||||
に確認した方が良いです。最初の良いテストとしては、自分にメールを送って
|
||||
みて、そのパッチを自分で当ててみることです。もしそれがうまく行かないな
|
||||
ら、あなたのメールプログラムを直してもらうか、正しく動くように変えるべ
|
||||
きです。
|
||||
もしパッチをメールに付ける場合は、
|
||||
Documentation/process/submitting-patches.rst に提示されているように、そ
|
||||
れは プレーンな可読テキストにすることを忘れないようにしましょう。カー
|
||||
ネル開発者は 添付や圧縮したパッチを扱いたがりません。彼らはあなたのパッ
|
||||
チの行毎にコメントを入れたいので、そうするしかありません。あなたのメー
|
||||
ルプログラムが空白やタブを圧縮しないように確認しましょう。最初の良いテ
|
||||
ストとしては、自分にメールを送ってみて、そのパッチを自分で当ててみるこ
|
||||
とです。もしそれがうまく行かないなら、あなたのメールプログラムを直して
|
||||
もらうか、正しく動くように変えるべきです。
|
||||
|
||||
とりわけ、他の登録者に対する尊敬を表すようにすることを覚えておいてくだ
|
||||
さい。
|
||||
何をおいても、他の購読者に対する敬意を表すことを忘れないでください。
|
||||
|
||||
コミュニティと共に働くこと
|
||||
--------------------------
|
||||
|
@ -459,21 +474,22 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
|||
です。あなたがパッチを受け入れてもらうために投稿した場合、それは、技術
|
||||
的メリットだけがレビューされます。その際、あなたは何を予想すべきでしょ
|
||||
うか?
|
||||
|
||||
- 批判
|
||||
- コメント
|
||||
- 変更の要求
|
||||
- パッチの正当性の証明要求
|
||||
- 沈黙
|
||||
|
||||
思い出してください、ここはあなたのパッチをカーネルに入れる話です。あ
|
||||
なたは、あなたのパッチに対する批判とコメントを受け入れるべきで、それら
|
||||
を技術的レベルで評価して、パッチを再作成するか、なぜそれらの変更をすべ
|
||||
きでないかを明確で簡潔な理由の説明を提供してください。
|
||||
もし、あなたのパッチに何も反応がない場合、たまにはメールの山に埋もれて
|
||||
見逃され、あなたの投稿が忘れられてしまうこともあるので、数日待って再度
|
||||
投稿してください。
|
||||
思い出してください、これはあなたのパッチをカーネルに入れる話です。あな
|
||||
たは、あなたのパッチに対する批判とコメントを受け入れるべきで、それらを
|
||||
技術的レベルで評価して、パッチを再作成するか、なぜそれらの変更をすべき
|
||||
でないかを明確で簡潔な理由の説明を提供してください。もし、あなたのパッ
|
||||
チに何も反応がない場合、たまにはメールの山に埋もれて見逃され、あなたの
|
||||
投稿が忘れられてしまうこともあるので、数日待って再度投稿してください。
|
||||
|
||||
あなたがやるべきでないことは?
|
||||
|
||||
あなたがやるべきでないものは?
|
||||
- 質問なしにあなたのパッチが受け入れられると想像すること
|
||||
- 守りに入ること
|
||||
- コメントを無視すること
|
||||
|
@ -489,37 +505,37 @@ MAINTAINERS ファイルにリストがありますので参照してくださ
|
|||
|
||||
あなたの最初のパッチに単に 1ダースもの修正を求めるリストの返答になるこ
|
||||
とも普通のことです。これはあなたのパッチが受け入れられないということで
|
||||
は *ありません*、そしてあなた自身に反対することを意味するのでも *ありま
|
||||
せん*。単に自分のパッチに対して指摘された問題を全て修正して再送すれば
|
||||
良いのです。
|
||||
は **ありません**、そしてあなた自身に反対することを意味するのでも **あ
|
||||
りません**。単に自分のパッチに対して指摘された問題を全て修正して再送す
|
||||
れば良いのです。
|
||||
|
||||
|
||||
カーネルコミュニティと企業組織のちがい
|
||||
-----------------------------------------------------------------
|
||||
|
||||
カーネルコミュニティは大部分の伝統的な会社の開発環境とは異ったやり方で
|
||||
動いています。以下は問題を避けるためにできると良いことのリストです-
|
||||
動いています。以下は問題を避けるためにできると良いことのリストです。
|
||||
|
||||
あなたの提案する変更について言うときのうまい言い方:
|
||||
あなたの提案する変更について言うときのうまい言い方 -
|
||||
|
||||
- "これは複数の問題を解決します"
|
||||
- "これは2000行のコードを削除します"
|
||||
- "以下のパッチは、私が言おうとしていることを説明するものです"
|
||||
- "私はこれを5つの異なるアーキテクチャでテストしたのですが..."
|
||||
- "以下は一連の小さなパッチ群ですが..."
|
||||
- "これは典型的なマシンでの性能を向上させます.."
|
||||
- "これは典型的なマシンでの性能を向上させます..."
|
||||
|
||||
やめた方が良い悪い言い方:
|
||||
やめた方が良い悪い言い方 -
|
||||
|
||||
- このやり方で AIX/ptx/Solaris ではできたので、できるはずだ
|
||||
- 私はこれを20年もの間やってきた、だから
|
||||
- これは、私の会社が金儲けをするために必要だ
|
||||
- これは我々のエンタープライズ向け商品ラインのためである
|
||||
- これは 私が自分のアイディアを記述した、1000ページの設計資料である
|
||||
- 私はこれについて、6ケ月作業している。
|
||||
- 以下は ... に関する5000行のパッチです
|
||||
- 私は現在のぐちゃぐちゃを全部書き直した、それが以下です...
|
||||
- 私は〆切がある、そのためこのパッチは今すぐ適用される必要がある
|
||||
- "このやり方で AIX/ptx/Solaris ではできたので、できるはずだ..."
|
||||
- "私はこれを20年もの間やってきた、だから..."
|
||||
- "これは私の会社が金儲けをするために必要だ"
|
||||
- "これは我々のエンタープライズ向け商品ラインのためである"
|
||||
- "これは私が自分のアイディアを記述した、1000ページの設計資料である"
|
||||
- "私はこれについて、6ケ月作業している..."
|
||||
- "以下は ... に関する5000行のパッチです"
|
||||
- "私は現在のぐちゃぐちゃを全部書き直した、それが以下です..."
|
||||
- "私は〆切がある、そのためこのパッチは今すぐ適用される必要がある"
|
||||
|
||||
カーネルコミュニティが大部分の伝統的なソフトウェアエンジニアリングの労
|
||||
働環境と異なるもう一つの点は、やりとりに顔を合わせないということです。
|
||||
|
@ -535,13 +551,13 @@ Patricia (主に女性名)や Patrick (主に男性名)の略称)。
|
|||
Linux カーネルの活動をして、意見を表明したことがある大部分の女性は、前
|
||||
向きな経験をもっています。
|
||||
|
||||
言葉の壁は英語が得意でない一部の人には問題になります。
|
||||
メーリングリストの中できちんとアイディアを交換するには、相当うまく英語
|
||||
を操れる必要があることもあります。そのため、あなたは自分のメール
|
||||
を送る前に英語で意味が通じているかをチェックすることをお薦めします。
|
||||
言葉の壁は英語が得意でない一部の人には問題になります。メーリングリスト
|
||||
の中で、きちんとアイディアを交換するには、相当うまく英語を操れる必要が
|
||||
あることもあります。そのため、自分のメールを送る前に英語で意味が通じて
|
||||
いるかをチェックすることをお薦めします。
|
||||
|
||||
変更を分割する
|
||||
---------------------
|
||||
--------------
|
||||
|
||||
Linux カーネルコミュニティは、一度に大量のコードの塊を喜んで受容するこ
|
||||
とはありません。変更は正確に説明される必要があり、議論され、小さい、個
|
||||
|
@ -555,7 +571,7 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
|||
やってはいけません、あなたのパッチ群はいつもどんな時でもそれよりは小さ
|
||||
くなければなりません。
|
||||
|
||||
パッチを分割する理由は以下です-
|
||||
パッチを分割する理由は以下 -
|
||||
|
||||
1) 小さいパッチはあなたのパッチが適用される見込みを大きくします、カー
|
||||
ネルの人達はパッチが正しいかどうかを確認する時間や労力をかけないか
|
||||
|
@ -571,41 +587,41 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
|||
2) 小さいパッチを送るだけでなく、送るまえに、書き直して、シンプルにす
|
||||
る(もしくは、単に順番を変えるだけでも)ことも、とても重要です。
|
||||
|
||||
以下はカーネル開発者の Al Viro のたとえ話です:
|
||||
以下はカーネル開発者の Al Viro のたとえ話です -
|
||||
|
||||
"生徒の数学の宿題を採点する先生のことを考えてみてください、先
|
||||
生は生徒が解に到達するまでの試行錯誤を見たいとは思わないでしょ
|
||||
う。先生は簡潔な最高の解を見たいのです。良い生徒はこれを知って
|
||||
おり、そして最終解の前の中間作業を提出することは決してないので
|
||||
す"
|
||||
*"生徒の数学の宿題を採点する先生のことを考えてみてください、
|
||||
先生は生徒が解に到達するまでの試行錯誤を見たいとは思わないでし
|
||||
ょう。先生は簡潔な最高の解を見たいのです。良い生徒はこれを知っ
|
||||
ており、そして最終解の前の中間作業を提出することは決してないの
|
||||
です*
|
||||
|
||||
カーネル開発でもこれは同じです。メンテナ達とレビューア達は、
|
||||
*カーネル開発でもこれは同じです。メンテナ達とレビューア達は、
|
||||
問題を解決する解の背後になる思考プロセスを見たいとは思いません。
|
||||
彼らは単純であざやかな解決方法を見たいのです。
|
||||
彼らは単純であざやかな解決方法を見たいのです。"*
|
||||
|
||||
あざやかな解を説明するのと、コミュニティと共に仕事をし、未解決の仕事を
|
||||
議論することのバランスをキープするのは難しいかもしれません。
|
||||
ですから、開発プロセスの早期段階で改善のためのフィードバックをもらうよ
|
||||
うにするのも良いですが、変更点を小さい部分に分割して全体ではまだ完成し
|
||||
ていない仕事を(部分的に)取り込んでもらえるようにすることも良いことです。
|
||||
議論することのバランスをキープするのは難しいかもしれません。ですから、
|
||||
開発プロセスの早期段階で改善のためのフィードバックをもらうようにするの
|
||||
も良いですが、変更点を小さい部分に分割して全体ではまだ完成していない仕
|
||||
事を(部分的に)取り込んでもらえるようにすることも良いことです。
|
||||
|
||||
また、でき上がっていないものや、"将来直す" ようなパッチを、本流に含め
|
||||
てもらうように送っても、それは受け付けられないことを理解してください。
|
||||
|
||||
あなたの変更を正当化する
|
||||
-------------------
|
||||
------------------------
|
||||
|
||||
あなたのパッチを分割するのと同時に、なぜその変更を追加しなければならな
|
||||
いかを Linux コミュニティに知らせることはとても重要です。新機能は必要
|
||||
性と有用性で正当化されなければなりません。
|
||||
|
||||
あなたの変更の説明
|
||||
--------------------
|
||||
あなたの変更を説明する
|
||||
----------------------
|
||||
|
||||
あなたのパッチを送付する場合には、メールの中のテキストで何を言うかにつ
|
||||
いて、特別に注意を払ってください。この情報はパッチの ChangeLog に使わ
|
||||
れ、いつも皆がみられるように保管されます。これは次のような項目を含め、
|
||||
パッチを完全に記述するべきです-
|
||||
パッチを完全に記述するべきです -
|
||||
|
||||
- なぜ変更が必要か
|
||||
- パッチ全体の設計アプローチ
|
||||
|
@ -613,18 +629,24 @@ Linux カーネルコミュニティは、一度に大量のコードの塊を
|
|||
- テスト結果
|
||||
|
||||
これについて全てがどのようにあるべきかについての詳細は、以下のドキュメ
|
||||
ントの ChangeLog セクションを見てください-
|
||||
ントの ChangeLog セクションを見てください -
|
||||
|
||||
"The Perfect Patch"
|
||||
http://www.ozlabs.org/~akpm/stuff/tpp.txt
|
||||
|
||||
これらのどれもが、時にはとても困難です。これらの慣例を完璧に実施するに
|
||||
は数年かかるかもしれません。これは継続的な改善のプロセスであり、そのた
|
||||
めには多数の忍耐と決意を必要とするものです。でも、諦めないで、これは可
|
||||
能なことです。多数の人がすでにできていますし、彼らも皆最初はあなたと同
|
||||
じところからスタートしたのですから。
|
||||
これらはどれも、実行することが時にはとても困難です。これらの例を完璧に
|
||||
実施するには数年かかるかもしれません。これは継続的な改善のプロセスであ
|
||||
り、多くの忍耐と決意を必要とするものです。でも諦めないで、実現は可能で
|
||||
す。多数の人がすでにできていますし、彼らも最初はあなたと同じところから
|
||||
スタートしたのですから。
|
||||
|
||||
|
||||
|
||||
|
||||
----------
|
||||
|
||||
Paolo Ciarrocchi に感謝、彼は彼の書いた "Development Process"
|
||||
(http://lwn.net/Articles/94386/) セクションをこのテキストの原型にする
|
||||
(https://lwn.net/Articles/94386/) セクションをこのテキストの原型にする
|
||||
ことを許可してくれました。Rundy Dunlap と Gerrit Huizenga はメーリング
|
||||
リストでやるべきこととやってはいけないことのリストを提供してくれました。
|
||||
以下の人々のレビュー、コメント、貢献に感謝。
|
||||
|
@ -634,4 +656,6 @@ Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
|
|||
David A. Wheeler, Junio Hamano, Michael Kerrisk, と Alex Shepard
|
||||
彼らの支援なしでは、このドキュメントはできなかったでしょう。
|
||||
|
||||
|
||||
|
||||
Maintainer: Greg Kroah-Hartman <greg@kroah.com>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue