Merge commit 'v2.6.36' into kbuild/misc
Update to be able to fix a recent change to scripts/basic/docproc.c
(commit eda603f
).
This commit is contained in:
19
.gitignore
vendored
19
.gitignore
vendored
@@ -35,13 +35,18 @@ modules.builtin
|
|||||||
#
|
#
|
||||||
# Top-level generic files
|
# Top-level generic files
|
||||||
#
|
#
|
||||||
tags
|
/tags
|
||||||
TAGS
|
/TAGS
|
||||||
vmlinux
|
/linux
|
||||||
vmlinuz
|
/vmlinux
|
||||||
System.map
|
/vmlinuz
|
||||||
Module.markers
|
/System.map
|
||||||
Module.symvers
|
/Module.markers
|
||||||
|
/Module.symvers
|
||||||
|
|
||||||
|
#
|
||||||
|
# git files that we don't want to ignore even it they are dot-files
|
||||||
|
#
|
||||||
!.gitignore
|
!.gitignore
|
||||||
!.mailmap
|
!.mailmap
|
||||||
|
|
||||||
|
8
CREDITS
8
CREDITS
@@ -3554,12 +3554,12 @@ E: cvance@nai.com
|
|||||||
D: portions of the Linux Security Module (LSM) framework and security modules
|
D: portions of the Linux Security Module (LSM) framework and security modules
|
||||||
|
|
||||||
N: Petr Vandrovec
|
N: Petr Vandrovec
|
||||||
E: vandrove@vc.cvut.cz
|
E: petr@vandrovec.name
|
||||||
D: Small contributions to ncpfs
|
D: Small contributions to ncpfs
|
||||||
D: Matrox framebuffer driver
|
D: Matrox framebuffer driver
|
||||||
S: Chudenicka 8
|
S: 21513 Conradia Ct
|
||||||
S: 10200 Prague 10, Hostivar
|
S: Cupertino, CA 95014
|
||||||
S: Czech Republic
|
S: USA
|
||||||
|
|
||||||
N: Thibaut Varene
|
N: Thibaut Varene
|
||||||
E: T-Bone@parisc-linux.org
|
E: T-Bone@parisc-linux.org
|
||||||
|
@@ -32,8 +32,6 @@ DocBook/
|
|||||||
- directory with DocBook templates etc. for kernel documentation.
|
- directory with DocBook templates etc. for kernel documentation.
|
||||||
HOWTO
|
HOWTO
|
||||||
- the process and procedures of how to do Linux kernel development.
|
- the process and procedures of how to do Linux kernel development.
|
||||||
IO-mapping.txt
|
|
||||||
- how to access I/O mapped memory from within device drivers.
|
|
||||||
IPMI.txt
|
IPMI.txt
|
||||||
- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
|
- info on Linux Intelligent Platform Management Interface (IPMI) Driver.
|
||||||
IRQ-affinity.txt
|
IRQ-affinity.txt
|
||||||
@@ -84,6 +82,8 @@ blockdev/
|
|||||||
- info on block devices & drivers
|
- info on block devices & drivers
|
||||||
btmrvl.txt
|
btmrvl.txt
|
||||||
- info on Marvell Bluetooth driver usage.
|
- info on Marvell Bluetooth driver usage.
|
||||||
|
bus-virt-phys-mapping.txt
|
||||||
|
- how to access I/O mapped memory from within device drivers.
|
||||||
cachetlb.txt
|
cachetlb.txt
|
||||||
- describes the cache/TLB flushing interfaces Linux uses.
|
- describes the cache/TLB flushing interfaces Linux uses.
|
||||||
cdrom/
|
cdrom/
|
||||||
@@ -130,8 +130,6 @@ edac.txt
|
|||||||
- information on EDAC - Error Detection And Correction
|
- information on EDAC - Error Detection And Correction
|
||||||
eisa.txt
|
eisa.txt
|
||||||
- info on EISA bus support.
|
- info on EISA bus support.
|
||||||
exception.txt
|
|
||||||
- how Linux v2.2 handles exceptions without verify_area etc.
|
|
||||||
fault-injection/
|
fault-injection/
|
||||||
- dir with docs about the fault injection capabilities infrastructure.
|
- dir with docs about the fault injection capabilities infrastructure.
|
||||||
fb/
|
fb/
|
||||||
@@ -168,6 +166,8 @@ initrd.txt
|
|||||||
- how to use the RAM disk as an initial/temporary root filesystem.
|
- how to use the RAM disk as an initial/temporary root filesystem.
|
||||||
input/
|
input/
|
||||||
- info on Linux input device support.
|
- info on Linux input device support.
|
||||||
|
io-mapping.txt
|
||||||
|
- description of io_mapping functions in linux/io-mapping.h
|
||||||
io_ordering.txt
|
io_ordering.txt
|
||||||
- info on ordering I/O writes to memory-mapped addresses.
|
- info on ordering I/O writes to memory-mapped addresses.
|
||||||
ioctl/
|
ioctl/
|
||||||
@@ -232,6 +232,8 @@ memory.txt
|
|||||||
- info on typical Linux memory problems.
|
- info on typical Linux memory problems.
|
||||||
mips/
|
mips/
|
||||||
- directory with info about Linux on MIPS architecture.
|
- directory with info about Linux on MIPS architecture.
|
||||||
|
mmc/
|
||||||
|
- directory with info about the MMC subsystem
|
||||||
mono.txt
|
mono.txt
|
||||||
- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
|
- how to execute Mono-based .NET binaries with the help of BINFMT_MISC.
|
||||||
mutex-design.txt
|
mutex-design.txt
|
||||||
@@ -250,6 +252,8 @@ numastat.txt
|
|||||||
- info on how to read Numa policy hit/miss statistics in sysfs.
|
- info on how to read Numa policy hit/miss statistics in sysfs.
|
||||||
oops-tracing.txt
|
oops-tracing.txt
|
||||||
- how to decode those nasty internal kernel error dump messages.
|
- how to decode those nasty internal kernel error dump messages.
|
||||||
|
padata.txt
|
||||||
|
- An introduction to the "padata" parallel execution API
|
||||||
parisc/
|
parisc/
|
||||||
- directory with info on using Linux on PA-RISC architecture.
|
- directory with info on using Linux on PA-RISC architecture.
|
||||||
parport.txt
|
parport.txt
|
||||||
|
31
Documentation/ABI/obsolete/sysfs-bus-usb
Normal file
31
Documentation/ABI/obsolete/sysfs-bus-usb
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
What: /sys/bus/usb/devices/.../power/level
|
||||||
|
Date: March 2007
|
||||||
|
KernelVersion: 2.6.21
|
||||||
|
Contact: Alan Stern <stern@rowland.harvard.edu>
|
||||||
|
Description:
|
||||||
|
Each USB device directory will contain a file named
|
||||||
|
power/level. This file holds a power-level setting for
|
||||||
|
the device, either "on" or "auto".
|
||||||
|
|
||||||
|
"on" means that the device is not allowed to autosuspend,
|
||||||
|
although normal suspends for system sleep will still
|
||||||
|
be honored. "auto" means the device will autosuspend
|
||||||
|
and autoresume in the usual manner, according to the
|
||||||
|
capabilities of its driver.
|
||||||
|
|
||||||
|
During normal use, devices should be left in the "auto"
|
||||||
|
level. The "on" level is meant for administrative uses.
|
||||||
|
If you want to suspend a device immediately but leave it
|
||||||
|
free to wake up in response to I/O requests, you should
|
||||||
|
write "0" to power/autosuspend.
|
||||||
|
|
||||||
|
Device not capable of proper suspend and resume should be
|
||||||
|
left in the "on" level. Although the USB spec requires
|
||||||
|
devices to support suspend/resume, many of them do not.
|
||||||
|
In fact so many don't that by default, the USB core
|
||||||
|
initializes all non-hub devices in the "on" level. Some
|
||||||
|
drivers may change this setting when they are bound.
|
||||||
|
|
||||||
|
This file is deprecated and will be removed after 2010.
|
||||||
|
Use the power/control file instead; it does exactly the
|
||||||
|
same thing.
|
29
Documentation/ABI/obsolete/sysfs-class-rfkill
Normal file
29
Documentation/ABI/obsolete/sysfs-class-rfkill
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
rfkill - radio frequency (RF) connector kill switch support
|
||||||
|
|
||||||
|
For details to this subsystem look at Documentation/rfkill.txt.
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/state
|
||||||
|
Date: 09-Jul-2007
|
||||||
|
KernelVersion v2.6.22
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: Current state of the transmitter.
|
||||||
|
This file is deprecated and sheduled to be removed in 2014,
|
||||||
|
because its not possible to express the 'soft and hard block'
|
||||||
|
state of the rfkill driver.
|
||||||
|
Values: A numeric value.
|
||||||
|
0: RFKILL_STATE_SOFT_BLOCKED
|
||||||
|
transmitter is turned off by software
|
||||||
|
1: RFKILL_STATE_UNBLOCKED
|
||||||
|
transmitter is (potentially) active
|
||||||
|
2: RFKILL_STATE_HARD_BLOCKED
|
||||||
|
transmitter is forced off by something outside of
|
||||||
|
the driver's control.
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/claim
|
||||||
|
Date: 09-Jul-2007
|
||||||
|
KernelVersion v2.6.22
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: This file is deprecated because there no longer is a way to
|
||||||
|
claim just control over a single rfkill instance.
|
||||||
|
This file is scheduled to be removed in 2012.
|
||||||
|
Values: 0: Kernel handles events
|
67
Documentation/ABI/stable/sysfs-class-rfkill
Normal file
67
Documentation/ABI/stable/sysfs-class-rfkill
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
rfkill - radio frequency (RF) connector kill switch support
|
||||||
|
|
||||||
|
For details to this subsystem look at Documentation/rfkill.txt.
|
||||||
|
|
||||||
|
For the deprecated /sys/class/rfkill/*/state and
|
||||||
|
/sys/class/rfkill/*/claim knobs of this interface look in
|
||||||
|
Documentation/ABI/obsolete/sysfs-class-rfkill.
|
||||||
|
|
||||||
|
What: /sys/class/rfkill
|
||||||
|
Date: 09-Jul-2007
|
||||||
|
KernelVersion: v2.6.22
|
||||||
|
Contact: linux-wireless@vger.kernel.org,
|
||||||
|
Description: The rfkill class subsystem folder.
|
||||||
|
Each registered rfkill driver is represented by an rfkillX
|
||||||
|
subfolder (X being an integer > 0).
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/name
|
||||||
|
Date: 09-Jul-2007
|
||||||
|
KernelVersion v2.6.22
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: Name assigned by driver to this key (interface or driver name).
|
||||||
|
Values: arbitrary string.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/type
|
||||||
|
Date: 09-Jul-2007
|
||||||
|
KernelVersion v2.6.22
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: Driver type string ("wlan", "bluetooth", etc).
|
||||||
|
Values: See include/linux/rfkill.h.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/persistent
|
||||||
|
Date: 09-Jul-2007
|
||||||
|
KernelVersion v2.6.22
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: Whether the soft blocked state is initialised from non-volatile
|
||||||
|
storage at startup.
|
||||||
|
Values: A numeric value.
|
||||||
|
0: false
|
||||||
|
1: true
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/hard
|
||||||
|
Date: 12-March-2010
|
||||||
|
KernelVersion v2.6.34
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: Current hardblock state. This file is read only.
|
||||||
|
Values: A numeric value.
|
||||||
|
0: inactive
|
||||||
|
The transmitter is (potentially) active.
|
||||||
|
1: active
|
||||||
|
The transmitter is forced off by something outside of
|
||||||
|
the driver's control.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/rfkill/rfkill[0-9]+/soft
|
||||||
|
Date: 12-March-2010
|
||||||
|
KernelVersion v2.6.34
|
||||||
|
Contact: linux-wireless@vger.kernel.org
|
||||||
|
Description: Current softblock state. This file is read and write.
|
||||||
|
Values: A numeric value.
|
||||||
|
0: inactive
|
||||||
|
The transmitter is (potentially) active.
|
||||||
|
1: active
|
||||||
|
The transmitter is turned off by software.
|
7
Documentation/ABI/stable/sysfs-devices-node
Normal file
7
Documentation/ABI/stable/sysfs-devices-node
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
What: /sys/devices/system/node/nodeX
|
||||||
|
Date: October 2002
|
||||||
|
Contact: Linux Memory Management list <linux-mm@kvack.org>
|
||||||
|
Description:
|
||||||
|
When CONFIG_NUMA is enabled, this is a directory containing
|
||||||
|
information on node X such as what CPUs are local to the
|
||||||
|
node.
|
20
Documentation/ABI/testing/debugfs-ec
Normal file
20
Documentation/ABI/testing/debugfs-ec
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
What: /sys/kernel/debug/ec/*/{gpe,use_global_lock,io}
|
||||||
|
Date: July 2010
|
||||||
|
Contact: Thomas Renninger <trenn@suse.de>
|
||||||
|
Description:
|
||||||
|
|
||||||
|
General information like which GPE is assigned to the EC and whether
|
||||||
|
the global lock should get used.
|
||||||
|
Knowing the EC GPE one can watch the amount of HW events related to
|
||||||
|
the EC here (XY -> GPE number from /sys/kernel/debug/ec/*/gpe):
|
||||||
|
/sys/firmware/acpi/interrupts/gpeXY
|
||||||
|
|
||||||
|
The io file is binary and a userspace tool located here:
|
||||||
|
ftp://ftp.suse.com/pub/people/trenn/sources/ec/
|
||||||
|
should get used to read out the 256 Embedded Controller registers
|
||||||
|
or writing to them.
|
||||||
|
|
||||||
|
CAUTION: Do not write to the Embedded Controller if you don't know
|
||||||
|
what you are doing! Rebooting afterwards also is a good idea.
|
||||||
|
This can influence the way your machine is cooled and fans may
|
||||||
|
not get switched on again after you did a wrong write.
|
@@ -1,71 +0,0 @@
|
|||||||
What: /sys/kernel/debug/kmemtrace/
|
|
||||||
Date: July 2008
|
|
||||||
Contact: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
|
|
||||||
Description:
|
|
||||||
|
|
||||||
In kmemtrace-enabled kernels, the following files are created:
|
|
||||||
|
|
||||||
/sys/kernel/debug/kmemtrace/
|
|
||||||
cpu<n> (0400) Per-CPU tracing data, see below. (binary)
|
|
||||||
total_overruns (0400) Total number of bytes which were dropped from
|
|
||||||
cpu<n> files because of full buffer condition,
|
|
||||||
non-binary. (text)
|
|
||||||
abi_version (0400) Kernel's kmemtrace ABI version. (text)
|
|
||||||
|
|
||||||
Each per-CPU file should be read according to the relay interface. That is,
|
|
||||||
the reader should set affinity to that specific CPU and, as currently done by
|
|
||||||
the userspace application (though there are other methods), use poll() with
|
|
||||||
an infinite timeout before every read(). Otherwise, erroneous data may be
|
|
||||||
read. The binary data has the following _core_ format:
|
|
||||||
|
|
||||||
Event ID (1 byte) Unsigned integer, one of:
|
|
||||||
0 - represents an allocation (KMEMTRACE_EVENT_ALLOC)
|
|
||||||
1 - represents a freeing of previously allocated memory
|
|
||||||
(KMEMTRACE_EVENT_FREE)
|
|
||||||
Type ID (1 byte) Unsigned integer, one of:
|
|
||||||
0 - this is a kmalloc() / kfree()
|
|
||||||
1 - this is a kmem_cache_alloc() / kmem_cache_free()
|
|
||||||
2 - this is a __get_free_pages() et al.
|
|
||||||
Event size (2 bytes) Unsigned integer representing the
|
|
||||||
size of this event. Used to extend
|
|
||||||
kmemtrace. Discard the bytes you
|
|
||||||
don't know about.
|
|
||||||
Sequence number (4 bytes) Signed integer used to reorder data
|
|
||||||
logged on SMP machines. Wraparound
|
|
||||||
must be taken into account, although
|
|
||||||
it is unlikely.
|
|
||||||
Caller address (8 bytes) Return address to the caller.
|
|
||||||
Pointer to mem (8 bytes) Pointer to target memory area. Can be
|
|
||||||
NULL, but not all such calls might be
|
|
||||||
recorded.
|
|
||||||
|
|
||||||
In case of KMEMTRACE_EVENT_ALLOC events, the next fields follow:
|
|
||||||
|
|
||||||
Requested bytes (8 bytes) Total number of requested bytes,
|
|
||||||
unsigned, must not be zero.
|
|
||||||
Allocated bytes (8 bytes) Total number of actually allocated
|
|
||||||
bytes, unsigned, must not be lower
|
|
||||||
than requested bytes.
|
|
||||||
Requested flags (4 bytes) GFP flags supplied by the caller.
|
|
||||||
Target CPU (4 bytes) Signed integer, valid for event id 1.
|
|
||||||
If equal to -1, target CPU is the same
|
|
||||||
as origin CPU, but the reverse might
|
|
||||||
not be true.
|
|
||||||
|
|
||||||
The data is made available in the same endianness the machine has.
|
|
||||||
|
|
||||||
Other event ids and type ids may be defined and added. Other fields may be
|
|
||||||
added by increasing event size, but see below for details.
|
|
||||||
Every modification to the ABI, including new id definitions, are followed
|
|
||||||
by bumping the ABI version by one.
|
|
||||||
|
|
||||||
Adding new data to the packet (features) is done at the end of the mandatory
|
|
||||||
data:
|
|
||||||
Feature size (2 byte)
|
|
||||||
Feature ID (1 byte)
|
|
||||||
Feature data (Feature size - 3 bytes)
|
|
||||||
|
|
||||||
|
|
||||||
Users:
|
|
||||||
kmemtrace-user - git://repo.or.cz/kmemtrace-user.git
|
|
||||||
|
|
@@ -20,7 +20,7 @@ Description:
|
|||||||
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
||||||
[obj_user=] [obj_role=] [obj_type=]]
|
[obj_user=] [obj_role=] [obj_type=]]
|
||||||
|
|
||||||
base: func:= [BPRM_CHECK][FILE_MMAP][INODE_PERMISSION]
|
base: func:= [BPRM_CHECK][FILE_MMAP][FILE_CHECK]
|
||||||
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
|
mask:= [MAY_READ] [MAY_WRITE] [MAY_APPEND] [MAY_EXEC]
|
||||||
fsmagic:= hex value
|
fsmagic:= hex value
|
||||||
uid:= decimal value
|
uid:= decimal value
|
||||||
@@ -40,11 +40,11 @@ Description:
|
|||||||
|
|
||||||
measure func=BPRM_CHECK
|
measure func=BPRM_CHECK
|
||||||
measure func=FILE_MMAP mask=MAY_EXEC
|
measure func=FILE_MMAP mask=MAY_EXEC
|
||||||
measure func=INODE_PERM mask=MAY_READ uid=0
|
measure func=FILE_CHECK mask=MAY_READ uid=0
|
||||||
|
|
||||||
The default policy measures all executables in bprm_check,
|
The default policy measures all executables in bprm_check,
|
||||||
all files mmapped executable in file_mmap, and all files
|
all files mmapped executable in file_mmap, and all files
|
||||||
open for read by root in inode_permission.
|
open for read by root in do_filp_open.
|
||||||
|
|
||||||
Examples of LSM specific definitions:
|
Examples of LSM specific definitions:
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ Description:
|
|||||||
|
|
||||||
dont_measure obj_type=var_log_t
|
dont_measure obj_type=var_log_t
|
||||||
dont_measure obj_type=auditd_log_t
|
dont_measure obj_type=auditd_log_t
|
||||||
measure subj_user=system_u func=INODE_PERM mask=MAY_READ
|
measure subj_user=system_u func=FILE_CHECK mask=MAY_READ
|
||||||
measure subj_role=system_r func=INODE_PERM mask=MAY_READ
|
measure subj_role=system_r func=FILE_CHECK mask=MAY_READ
|
||||||
|
|
||||||
Smack:
|
Smack:
|
||||||
measure subj_user=_ func=INODE_PERM mask=MAY_READ
|
measure subj_user=_ func=FILE_CHECK mask=MAY_READ
|
||||||
|
@@ -128,3 +128,17 @@ Description:
|
|||||||
preferred request size for workloads where sustained
|
preferred request size for workloads where sustained
|
||||||
throughput is desired. If no optimal I/O size is
|
throughput is desired. If no optimal I/O size is
|
||||||
reported this file contains 0.
|
reported this file contains 0.
|
||||||
|
|
||||||
|
What: /sys/block/<disk>/queue/nomerges
|
||||||
|
Date: January 2010
|
||||||
|
Contact:
|
||||||
|
Description:
|
||||||
|
Standard I/O elevator operations include attempts to
|
||||||
|
merge contiguous I/Os. For known random I/O loads these
|
||||||
|
attempts will always fail and result in extra cycles
|
||||||
|
being spent in the kernel. This allows one to turn off
|
||||||
|
this behavior on one of two ways: When set to 1, complex
|
||||||
|
merge checks are disabled, but the simple one-shot merges
|
||||||
|
with the previous I/O request are enabled. When set to 2,
|
||||||
|
all merge tries are disabled. The default value is 0 -
|
||||||
|
which enables all types of merge tries.
|
||||||
|
21
Documentation/ABI/testing/sysfs-bus-i2c-devices-hm6352
Normal file
21
Documentation/ABI/testing/sysfs-bus-i2c-devices-hm6352
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Where: /sys/bus/i2c/devices/.../heading0_input
|
||||||
|
Date: April 2010
|
||||||
|
Kernel Version: 2.6.36?
|
||||||
|
Contact: alan.cox@intel.com
|
||||||
|
Description: Reports the current heading from the compass as a floating
|
||||||
|
point value in degrees.
|
||||||
|
|
||||||
|
Where: /sys/bus/i2c/devices/.../power_state
|
||||||
|
Date: April 2010
|
||||||
|
Kernel Version: 2.6.36?
|
||||||
|
Contact: alan.cox@intel.com
|
||||||
|
Description: Sets the power state of the device. 0 sets the device into
|
||||||
|
sleep mode, 1 wakes it up.
|
||||||
|
|
||||||
|
Where: /sys/bus/i2c/devices/.../calibration
|
||||||
|
Date: April 2010
|
||||||
|
Kernel Version: 2.6.36?
|
||||||
|
Contact: alan.cox@intel.com
|
||||||
|
Description: Sets the calibration on or off (1 = on, 0 = off). See the
|
||||||
|
chip data sheet.
|
||||||
|
|
@@ -139,3 +139,30 @@ Contact: linux-pci@vger.kernel.org
|
|||||||
Description:
|
Description:
|
||||||
This symbolic link points to the PCI hotplug controller driver
|
This symbolic link points to the PCI hotplug controller driver
|
||||||
module that manages the hotplug slot.
|
module that manages the hotplug slot.
|
||||||
|
|
||||||
|
What: /sys/bus/pci/devices/.../label
|
||||||
|
Date: July 2010
|
||||||
|
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||||
|
Description:
|
||||||
|
Reading this attribute will provide the firmware
|
||||||
|
given name(SMBIOS type 41 string) of the PCI device.
|
||||||
|
The attribute will be created only if the firmware
|
||||||
|
has given a name to the PCI device.
|
||||||
|
Users:
|
||||||
|
Userspace applications interested in knowing the
|
||||||
|
firmware assigned name of the PCI device.
|
||||||
|
|
||||||
|
What: /sys/bus/pci/devices/.../index
|
||||||
|
Date: July 2010
|
||||||
|
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||||
|
Description:
|
||||||
|
Reading this attribute will provide the firmware
|
||||||
|
given instance(SMBIOS type 41 device type instance)
|
||||||
|
of the PCI device. The attribute will be created
|
||||||
|
only if the firmware has given a device type instance
|
||||||
|
to the PCI device.
|
||||||
|
Users:
|
||||||
|
Userspace applications interested in knowing the
|
||||||
|
firmware assigned device type instance of the PCI
|
||||||
|
device that can help in understanding the firmware
|
||||||
|
intended order of the PCI device.
|
||||||
|
@@ -14,34 +14,6 @@ Description:
|
|||||||
The autosuspend delay for newly-created devices is set to
|
The autosuspend delay for newly-created devices is set to
|
||||||
the value of the usbcore.autosuspend module parameter.
|
the value of the usbcore.autosuspend module parameter.
|
||||||
|
|
||||||
What: /sys/bus/usb/devices/.../power/level
|
|
||||||
Date: March 2007
|
|
||||||
KernelVersion: 2.6.21
|
|
||||||
Contact: Alan Stern <stern@rowland.harvard.edu>
|
|
||||||
Description:
|
|
||||||
Each USB device directory will contain a file named
|
|
||||||
power/level. This file holds a power-level setting for
|
|
||||||
the device, either "on" or "auto".
|
|
||||||
|
|
||||||
"on" means that the device is not allowed to autosuspend,
|
|
||||||
although normal suspends for system sleep will still
|
|
||||||
be honored. "auto" means the device will autosuspend
|
|
||||||
and autoresume in the usual manner, according to the
|
|
||||||
capabilities of its driver.
|
|
||||||
|
|
||||||
During normal use, devices should be left in the "auto"
|
|
||||||
level. The "on" level is meant for administrative uses.
|
|
||||||
If you want to suspend a device immediately but leave it
|
|
||||||
free to wake up in response to I/O requests, you should
|
|
||||||
write "0" to power/autosuspend.
|
|
||||||
|
|
||||||
Device not capable of proper suspend and resume should be
|
|
||||||
left in the "on" level. Although the USB spec requires
|
|
||||||
devices to support suspend/resume, many of them do not.
|
|
||||||
In fact so many don't that by default, the USB core
|
|
||||||
initializes all non-hub devices in the "on" level. Some
|
|
||||||
drivers may change this setting when they are bound.
|
|
||||||
|
|
||||||
What: /sys/bus/usb/devices/.../power/persist
|
What: /sys/bus/usb/devices/.../power/persist
|
||||||
Date: May 2007
|
Date: May 2007
|
||||||
KernelVersion: 2.6.23
|
KernelVersion: 2.6.23
|
||||||
@@ -159,3 +131,14 @@ Description:
|
|||||||
device. This is useful to ensure auto probing won't
|
device. This is useful to ensure auto probing won't
|
||||||
match the driver to the device. For example:
|
match the driver to the device. For example:
|
||||||
# echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id
|
# echo "046d c315" > /sys/bus/usb/drivers/foo/remove_id
|
||||||
|
|
||||||
|
What: /sys/bus/usb/device/.../avoid_reset_quirk
|
||||||
|
Date: December 2009
|
||||||
|
Contact: Oliver Neukum <oliver@neukum.org>
|
||||||
|
Description:
|
||||||
|
Writing 1 to this file tells the kernel that this
|
||||||
|
device will morph into another mode when it is reset.
|
||||||
|
Drivers will not use reset for error handling for
|
||||||
|
such devices.
|
||||||
|
Users:
|
||||||
|
usb_modeswitch
|
||||||
|
20
Documentation/ABI/testing/sysfs-class-power
Normal file
20
Documentation/ABI/testing/sysfs-class-power
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
What: /sys/class/power/ds2760-battery.*/charge_now
|
||||||
|
Date: May 2010
|
||||||
|
KernelVersion: 2.6.35
|
||||||
|
Contact: Daniel Mack <daniel@caiaq.de>
|
||||||
|
Description:
|
||||||
|
This file is writeable and can be used to set the current
|
||||||
|
coloumb counter value inside the battery monitor chip. This
|
||||||
|
is needed for unavoidable corrections of aging batteries.
|
||||||
|
A userspace daemon can monitor the battery charging logic
|
||||||
|
and once the counter drops out of considerable bounds, take
|
||||||
|
appropriate action.
|
||||||
|
|
||||||
|
What: /sys/class/power/ds2760-battery.*/charge_full
|
||||||
|
Date: May 2010
|
||||||
|
KernelVersion: 2.6.35
|
||||||
|
Contact: Daniel Mack <daniel@caiaq.de>
|
||||||
|
Description:
|
||||||
|
This file is writeable and can be used to set the assumed
|
||||||
|
battery 'full level'. As batteries age, this value has to be
|
||||||
|
amended over time.
|
@@ -7,7 +7,7 @@ Description:
|
|||||||
added or removed dynamically to represent hot-add/remove
|
added or removed dynamically to represent hot-add/remove
|
||||||
operations.
|
operations.
|
||||||
Users: hotplug memory add/remove tools
|
Users: hotplug memory add/remove tools
|
||||||
https://w3.opensource.ibm.com/projects/powerpc-utils/
|
http://www.ibm.com/developerworks/wikis/display/LinuxP/powerpc-utils
|
||||||
|
|
||||||
What: /sys/devices/system/memory/memoryX/removable
|
What: /sys/devices/system/memory/memoryX/removable
|
||||||
Date: June 2008
|
Date: June 2008
|
||||||
@@ -19,7 +19,7 @@ Description:
|
|||||||
identify removable sections of the memory before attempting
|
identify removable sections of the memory before attempting
|
||||||
potentially expensive hot-remove memory operation
|
potentially expensive hot-remove memory operation
|
||||||
Users: hotplug memory remove tools
|
Users: hotplug memory remove tools
|
||||||
https://w3.opensource.ibm.com/projects/powerpc-utils/
|
http://www.ibm.com/developerworks/wikis/display/LinuxP/powerpc-utils
|
||||||
|
|
||||||
What: /sys/devices/system/memory/memoryX/phys_device
|
What: /sys/devices/system/memory/memoryX/phys_device
|
||||||
Date: September 2008
|
Date: September 2008
|
||||||
@@ -43,7 +43,7 @@ Date: September 2008
|
|||||||
Contact: Badari Pulavarty <pbadari@us.ibm.com>
|
Contact: Badari Pulavarty <pbadari@us.ibm.com>
|
||||||
Description:
|
Description:
|
||||||
The file /sys/devices/system/memory/memoryX/state
|
The file /sys/devices/system/memory/memoryX/state
|
||||||
is read-write. When read, it's contents show the
|
is read-write. When read, its contents show the
|
||||||
online/offline state of the memory section. When written,
|
online/offline state of the memory section. When written,
|
||||||
root can toggle the the online/offline state of a removable
|
root can toggle the the online/offline state of a removable
|
||||||
memory section (see removable file description above)
|
memory section (see removable file description above)
|
||||||
@@ -58,7 +58,7 @@ Description:
|
|||||||
by root to offline that section.
|
by root to offline that section.
|
||||||
# echo offline > /sys/devices/system/memory/memory22/state
|
# echo offline > /sys/devices/system/memory/memory22/state
|
||||||
Users: hotplug memory remove tools
|
Users: hotplug memory remove tools
|
||||||
https://w3.opensource.ibm.com/projects/powerpc-utils/
|
http://www.ibm.com/developerworks/wikis/display/LinuxP/powerpc-utils
|
||||||
|
|
||||||
|
|
||||||
What: /sys/devices/system/memoryX/nodeY
|
What: /sys/devices/system/memoryX/nodeY
|
||||||
|
7
Documentation/ABI/testing/sysfs-devices-node
Normal file
7
Documentation/ABI/testing/sysfs-devices-node
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
What: /sys/devices/system/node/nodeX/compact
|
||||||
|
Date: February 2010
|
||||||
|
Contact: Mel Gorman <mel@csn.ul.ie>
|
||||||
|
Description:
|
||||||
|
When this file is written to, all memory within that node
|
||||||
|
will be compacted. When it completes, memory will be freed
|
||||||
|
into blocks which have as many contiguous pages as possible
|
@@ -0,0 +1,21 @@
|
|||||||
|
What: /sys/devices/platform/_UDC_/gadget/suspended
|
||||||
|
Date: April 2010
|
||||||
|
Contact: Fabien Chouteau <fabien.chouteau@barco.com>
|
||||||
|
Description:
|
||||||
|
Show the suspend state of an USB composite gadget.
|
||||||
|
1 -> suspended
|
||||||
|
0 -> resumed
|
||||||
|
|
||||||
|
(_UDC_ is the name of the USB Device Controller driver)
|
||||||
|
|
||||||
|
What: /sys/devices/platform/_UDC_/gadget/gadget-lunX/nofua
|
||||||
|
Date: July 2010
|
||||||
|
Contact: Andy Shevchenko <andy.shevchenko@gmail.com>
|
||||||
|
Description:
|
||||||
|
Show or set the reaction on the FUA (Force Unit Access) bit in
|
||||||
|
the SCSI WRITE(10,12) commands when a gadget in USB Mass
|
||||||
|
Storage mode.
|
||||||
|
|
||||||
|
Possible values are:
|
||||||
|
1 -> ignore the FUA flag
|
||||||
|
0 -> obey the FUA flag
|
79
Documentation/ABI/testing/sysfs-devices-power
Normal file
79
Documentation/ABI/testing/sysfs-devices-power
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
What: /sys/devices/.../power/
|
||||||
|
Date: January 2009
|
||||||
|
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Description:
|
||||||
|
The /sys/devices/.../power directory contains attributes
|
||||||
|
allowing the user space to check and modify some power
|
||||||
|
management related properties of given device.
|
||||||
|
|
||||||
|
What: /sys/devices/.../power/wakeup
|
||||||
|
Date: January 2009
|
||||||
|
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Description:
|
||||||
|
The /sys/devices/.../power/wakeup attribute allows the user
|
||||||
|
space to check if the device is enabled to wake up the system
|
||||||
|
from sleep states, such as the memory sleep state (suspend to
|
||||||
|
RAM) and hibernation (suspend to disk), and to enable or disable
|
||||||
|
it to do that as desired.
|
||||||
|
|
||||||
|
Some devices support "wakeup" events, which are hardware signals
|
||||||
|
used to activate the system from a sleep state. Such devices
|
||||||
|
have one of the following two values for the sysfs power/wakeup
|
||||||
|
file:
|
||||||
|
|
||||||
|
+ "enabled\n" to issue the events;
|
||||||
|
+ "disabled\n" not to do so;
|
||||||
|
|
||||||
|
In that cases the user space can change the setting represented
|
||||||
|
by the contents of this file by writing either "enabled", or
|
||||||
|
"disabled" to it.
|
||||||
|
|
||||||
|
For the devices that are not capable of generating system wakeup
|
||||||
|
events this file contains "\n". In that cases the user space
|
||||||
|
cannot modify the contents of this file and the device cannot be
|
||||||
|
enabled to wake up the system.
|
||||||
|
|
||||||
|
What: /sys/devices/.../power/control
|
||||||
|
Date: January 2009
|
||||||
|
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Description:
|
||||||
|
The /sys/devices/.../power/control attribute allows the user
|
||||||
|
space to control the run-time power management of the device.
|
||||||
|
|
||||||
|
All devices have one of the following two values for the
|
||||||
|
power/control file:
|
||||||
|
|
||||||
|
+ "auto\n" to allow the device to be power managed at run time;
|
||||||
|
+ "on\n" to prevent the device from being power managed;
|
||||||
|
|
||||||
|
The default for all devices is "auto", which means that they may
|
||||||
|
be subject to automatic power management, depending on their
|
||||||
|
drivers. Changing this attribute to "on" prevents the driver
|
||||||
|
from power managing the device at run time. Doing that while
|
||||||
|
the device is suspended causes it to be woken up.
|
||||||
|
|
||||||
|
What: /sys/devices/.../power/async
|
||||||
|
Date: January 2009
|
||||||
|
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Description:
|
||||||
|
The /sys/devices/.../async attribute allows the user space to
|
||||||
|
enable or diasble the device's suspend and resume callbacks to
|
||||||
|
be executed asynchronously (ie. in separate threads, in parallel
|
||||||
|
with the main suspend/resume thread) during system-wide power
|
||||||
|
transitions (eg. suspend to RAM, hibernation).
|
||||||
|
|
||||||
|
All devices have one of the following two values for the
|
||||||
|
power/async file:
|
||||||
|
|
||||||
|
+ "enabled\n" to permit the asynchronous suspend/resume;
|
||||||
|
+ "disabled\n" to forbid it;
|
||||||
|
|
||||||
|
The value of this attribute may be changed by writing either
|
||||||
|
"enabled", or "disabled" to it.
|
||||||
|
|
||||||
|
It generally is unsafe to permit the asynchronous suspend/resume
|
||||||
|
of a device unless it is certain that all of the PM dependencies
|
||||||
|
of the device are known to the PM core. However, for some
|
||||||
|
devices this attribute is set to "enabled" by bus type code or
|
||||||
|
device drivers and in that cases it should be safe to leave the
|
||||||
|
default value.
|
@@ -197,7 +197,7 @@ Description: These files exist in every cpu's cache index directories.
|
|||||||
Currently, only AMD Family 10h Processors support cache index
|
Currently, only AMD Family 10h Processors support cache index
|
||||||
disable, and only for their L3 caches. See the BIOS and
|
disable, and only for their L3 caches. See the BIOS and
|
||||||
Kernel Developer's Guide at
|
Kernel Developer's Guide at
|
||||||
http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/31116-Public-GH-BKDG_3.20_2-4-09.pdf
|
http://support.amd.com/us/Embedded_TechDocs/31116-Public-GH-BKDG_3-28_5-28-09.pdf
|
||||||
for formatting information and other details on the
|
for formatting information and other details on the
|
||||||
cache index disable.
|
cache index disable.
|
||||||
Users: joachim.deguara@amd.com
|
Users: joachim.deguara@amd.com
|
||||||
|
43
Documentation/ABI/testing/sysfs-driver-hid-picolcd
Normal file
43
Documentation/ABI/testing/sysfs-driver-hid-picolcd
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Bruno Prémont <bonbons@linux-vserver.org>
|
||||||
|
Description: Make it possible to switch the PicoLCD device between LCD
|
||||||
|
(firmware) and bootloader (flasher) operation modes.
|
||||||
|
|
||||||
|
Reading: returns list of available modes, the active mode being
|
||||||
|
enclosed in brackets ('[' and ']')
|
||||||
|
|
||||||
|
Writing: causes operation mode switch. Permitted values are
|
||||||
|
the non-active mode names listed when read.
|
||||||
|
|
||||||
|
Note: when switching mode the current PicoLCD HID device gets
|
||||||
|
disconnected and reconnects after above delay (see attribute
|
||||||
|
operation_mode_delay for its value).
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/operation_mode_delay
|
||||||
|
Date: April 2010
|
||||||
|
Contact: Bruno Prémont <bonbons@linux-vserver.org>
|
||||||
|
Description: Delay PicoLCD waits before restarting in new mode when
|
||||||
|
operation_mode has changed.
|
||||||
|
|
||||||
|
Reading/Writing: It is expressed in ms and permitted range is
|
||||||
|
0..30000ms.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/fb_update_rate
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Bruno Prémont <bonbons@linux-vserver.org>
|
||||||
|
Description: Make it possible to adjust defio refresh rate.
|
||||||
|
|
||||||
|
Reading: returns list of available refresh rates (expressed in Hz),
|
||||||
|
the active refresh rate being enclosed in brackets ('[' and ']')
|
||||||
|
|
||||||
|
Writing: accepts new refresh rate expressed in integer Hz
|
||||||
|
within permitted rates.
|
||||||
|
|
||||||
|
Note: As device can barely do 2 complete refreshes a second
|
||||||
|
it only makes sense to adjust this value if only one or two
|
||||||
|
tiles get changed and it's not appropriate to expect the application
|
||||||
|
to flush it's tiny changes explicitely at higher than default rate.
|
||||||
|
|
29
Documentation/ABI/testing/sysfs-driver-hid-prodikeys
Normal file
29
Documentation/ABI/testing/sysfs-driver-hid-prodikeys
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
What: /sys/bus/hid/drivers/prodikeys/.../channel
|
||||||
|
Date: April 2010
|
||||||
|
KernelVersion: 2.6.34
|
||||||
|
Contact: Don Prince <dhprince.devel@yahoo.co.uk>
|
||||||
|
Description:
|
||||||
|
Allows control (via software) the midi channel to which
|
||||||
|
that the pc-midi keyboard will output.midi data.
|
||||||
|
Range: 0..15
|
||||||
|
Type: Read/write
|
||||||
|
What: /sys/bus/hid/drivers/prodikeys/.../sustain
|
||||||
|
Date: April 2010
|
||||||
|
KernelVersion: 2.6.34
|
||||||
|
Contact: Don Prince <dhprince.devel@yahoo.co.uk>
|
||||||
|
Description:
|
||||||
|
Allows control (via software) the sustain duration of a
|
||||||
|
note held by the pc-midi driver.
|
||||||
|
0 means sustain mode is disabled.
|
||||||
|
Range: 0..5000 (milliseconds)
|
||||||
|
Type: Read/write
|
||||||
|
What: /sys/bus/hid/drivers/prodikeys/.../octave
|
||||||
|
Date: April 2010
|
||||||
|
KernelVersion: 2.6.34
|
||||||
|
Contact: Don Prince <dhprince.devel@yahoo.co.uk>
|
||||||
|
Description:
|
||||||
|
Controls the octave shift modifier in the pc-midi driver.
|
||||||
|
The octave can be shifted via software up/down 2 octaves.
|
||||||
|
0 means the no ocatve shift.
|
||||||
|
Range: -2..2 (minus 2 to plus 2)
|
||||||
|
Type: Read/Write
|
98
Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
Normal file
98
Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_dpi
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: It is possible to switch the dpi setting of the mouse with the
|
||||||
|
press of a button.
|
||||||
|
When read, this file returns the raw number of the actual dpi
|
||||||
|
setting reported by the mouse. This number has to be further
|
||||||
|
processed to receive the real dpi value.
|
||||||
|
|
||||||
|
VALUE DPI
|
||||||
|
1 800
|
||||||
|
2 1200
|
||||||
|
3 1600
|
||||||
|
4 2000
|
||||||
|
5 2400
|
||||||
|
6 3200
|
||||||
|
|
||||||
|
This file is readonly.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/actual_profile
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: When read, this file returns the number of the actual profile.
|
||||||
|
This file is readonly.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/firmware_version
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: When read, this file returns the raw integer version number of the
|
||||||
|
firmware reported by the mouse. Using the integer value eases
|
||||||
|
further usage in other programs. To receive the real version
|
||||||
|
number the decimal point has to be shifted 2 positions to the
|
||||||
|
left. E.g. a returned value of 138 means 1.38
|
||||||
|
This file is readonly.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/profile[1-5]
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: The mouse can store 5 profiles which can be switched by the
|
||||||
|
press of a button. A profile holds informations like button
|
||||||
|
mappings, sensitivity, the colors of the 5 leds and light
|
||||||
|
effects.
|
||||||
|
When read, these files return the respective profile. The
|
||||||
|
returned data is 975 bytes in size.
|
||||||
|
When written, this file lets one write the respective profile
|
||||||
|
data back to the mouse. The data has to be 975 bytes long.
|
||||||
|
The mouse will reject invalid data, whereas the profile number
|
||||||
|
stored in the profile doesn't need to fit the number of the
|
||||||
|
store.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/settings
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: When read, this file returns the settings stored in the mouse.
|
||||||
|
The size of the data is 36 bytes and holds information like the
|
||||||
|
startup_profile, tcu state and calibration_data.
|
||||||
|
When written, this file lets write settings back to the mouse.
|
||||||
|
The data has to be 36 bytes long. The mouse will reject invalid
|
||||||
|
data.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/startup_profile
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: The integer value of this attribute ranges from 1 to 5.
|
||||||
|
When read, this attribute returns the number of the profile
|
||||||
|
that's active when the mouse is powered on.
|
||||||
|
When written, this file sets the number of the startup profile
|
||||||
|
and the mouse activates this profile immediately.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/tcu
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: The mouse has a "Tracking Control Unit" which lets the user
|
||||||
|
calibrate the laser power to fit the mousepad surface.
|
||||||
|
When read, this file returns the current state of the TCU,
|
||||||
|
where 0 means off and 1 means on.
|
||||||
|
Writing 0 in this file will switch the TCU off.
|
||||||
|
Writing 1 in this file will start the calibration which takes
|
||||||
|
around 6 seconds to complete and activates the TCU.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/weight
|
||||||
|
Date: March 2010
|
||||||
|
Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
|
||||||
|
Description: The mouse can be equipped with one of four supplied weights
|
||||||
|
ranging from 5 to 20 grams which are recognized by the mouse
|
||||||
|
and its value can be read out. When read, this file returns the
|
||||||
|
raw value returned by the mouse which eases further processing
|
||||||
|
in other software.
|
||||||
|
The values map to the weights as follows:
|
||||||
|
|
||||||
|
VALUE WEIGHT
|
||||||
|
0 none
|
||||||
|
1 5g
|
||||||
|
2 10g
|
||||||
|
3 15g
|
||||||
|
4 20g
|
||||||
|
|
||||||
|
This file is readonly.
|
15
Documentation/ABI/testing/sysfs-firmware-sfi
Normal file
15
Documentation/ABI/testing/sysfs-firmware-sfi
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
What: /sys/firmware/sfi/tables/
|
||||||
|
Date: May 2010
|
||||||
|
Contact: Len Brown <lenb@kernel.org>
|
||||||
|
Description:
|
||||||
|
SFI defines a number of small static memory tables
|
||||||
|
so the kernel can get platform information from firmware.
|
||||||
|
|
||||||
|
The tables are defined in the latest SFI specification:
|
||||||
|
http://simplefirmware.org/documentation
|
||||||
|
|
||||||
|
While the tables are used by the kernel, user-space
|
||||||
|
can observe them this way:
|
||||||
|
|
||||||
|
# cd /sys/firmware/sfi/tables
|
||||||
|
# cat $TABLENAME > $TABLENAME.bin
|
31
Documentation/ABI/testing/sysfs-i2c-bmp085
Normal file
31
Documentation/ABI/testing/sysfs-i2c-bmp085
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
What: /sys/bus/i2c/devices/<busnum>-<devaddr>/pressure0_input
|
||||||
|
Date: June 2010
|
||||||
|
Contact: Christoph Mair <christoph.mair@gmail.com>
|
||||||
|
Description: Start a pressure measurement and read the result. Values
|
||||||
|
represent the ambient air pressure in pascal (0.01 millibar).
|
||||||
|
|
||||||
|
Reading: returns the current air pressure.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/bus/i2c/devices/<busnum>-<devaddr>/temp0_input
|
||||||
|
Date: June 2010
|
||||||
|
Contact: Christoph Mair <christoph.mair@gmail.com>
|
||||||
|
Description: Measure the ambient temperature. The returned value represents
|
||||||
|
the ambient temperature in units of 0.1 degree celsius.
|
||||||
|
|
||||||
|
Reading: returns the current temperature.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/bus/i2c/devices/<busnum>-<devaddr>/oversampling
|
||||||
|
Date: June 2010
|
||||||
|
Contact: Christoph Mair <christoph.mair@gmail.com>
|
||||||
|
Description: Tell the bmp085 to use more samples to calculate a pressure
|
||||||
|
value. When writing to this file the chip will use 2^x samples
|
||||||
|
to calculate the next pressure value with x being the value
|
||||||
|
written. Using this feature will decrease RMS noise and
|
||||||
|
increase the measurement time.
|
||||||
|
|
||||||
|
Reading: returns the current oversampling setting.
|
||||||
|
|
||||||
|
Writing: sets a new oversampling setting.
|
||||||
|
Accepted values: 0..3.
|
@@ -1,4 +1,4 @@
|
|||||||
What: /sys/devices/platform/asus-laptop/display
|
What: /sys/devices/platform/asus_laptop/display
|
||||||
Date: January 2007
|
Date: January 2007
|
||||||
KernelVersion: 2.6.20
|
KernelVersion: 2.6.20
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
@@ -13,7 +13,7 @@ Description:
|
|||||||
Ex: - 0 (0000b) means no display
|
Ex: - 0 (0000b) means no display
|
||||||
- 3 (0011b) CRT+LCD.
|
- 3 (0011b) CRT+LCD.
|
||||||
|
|
||||||
What: /sys/devices/platform/asus-laptop/gps
|
What: /sys/devices/platform/asus_laptop/gps
|
||||||
Date: January 2007
|
Date: January 2007
|
||||||
KernelVersion: 2.6.20
|
KernelVersion: 2.6.20
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
@@ -21,7 +21,7 @@ Description:
|
|||||||
Control the gps device. 1 means on, 0 means off.
|
Control the gps device. 1 means on, 0 means off.
|
||||||
Users: Lapsus
|
Users: Lapsus
|
||||||
|
|
||||||
What: /sys/devices/platform/asus-laptop/ledd
|
What: /sys/devices/platform/asus_laptop/ledd
|
||||||
Date: January 2007
|
Date: January 2007
|
||||||
KernelVersion: 2.6.20
|
KernelVersion: 2.6.20
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
@@ -29,11 +29,11 @@ Description:
|
|||||||
Some models like the W1N have a LED display that can be
|
Some models like the W1N have a LED display that can be
|
||||||
used to display several informations.
|
used to display several informations.
|
||||||
To control the LED display, use the following :
|
To control the LED display, use the following :
|
||||||
echo 0x0T000DDD > /sys/devices/platform/asus-laptop/
|
echo 0x0T000DDD > /sys/devices/platform/asus_laptop/
|
||||||
where T control the 3 letters display, and DDD the 3 digits display.
|
where T control the 3 letters display, and DDD the 3 digits display.
|
||||||
The DDD table can be found in Documentation/laptops/asus-laptop.txt
|
The DDD table can be found in Documentation/laptops/asus-laptop.txt
|
||||||
|
|
||||||
What: /sys/devices/platform/asus-laptop/bluetooth
|
What: /sys/devices/platform/asus_laptop/bluetooth
|
||||||
Date: January 2007
|
Date: January 2007
|
||||||
KernelVersion: 2.6.20
|
KernelVersion: 2.6.20
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
@@ -42,7 +42,7 @@ Description:
|
|||||||
This may control the led, the device or both.
|
This may control the led, the device or both.
|
||||||
Users: Lapsus
|
Users: Lapsus
|
||||||
|
|
||||||
What: /sys/devices/platform/asus-laptop/wlan
|
What: /sys/devices/platform/asus_laptop/wlan
|
||||||
Date: January 2007
|
Date: January 2007
|
||||||
KernelVersion: 2.6.20
|
KernelVersion: 2.6.20
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
What: /sys/devices/platform/eeepc-laptop/disp
|
What: /sys/devices/platform/eeepc/disp
|
||||||
Date: May 2008
|
Date: May 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
@@ -9,21 +9,21 @@ Description:
|
|||||||
- 3 = LCD+CRT
|
- 3 = LCD+CRT
|
||||||
If you run X11, you should use xrandr instead.
|
If you run X11, you should use xrandr instead.
|
||||||
|
|
||||||
What: /sys/devices/platform/eeepc-laptop/camera
|
What: /sys/devices/platform/eeepc/camera
|
||||||
Date: May 2008
|
Date: May 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
Description:
|
Description:
|
||||||
Control the camera. 1 means on, 0 means off.
|
Control the camera. 1 means on, 0 means off.
|
||||||
|
|
||||||
What: /sys/devices/platform/eeepc-laptop/cardr
|
What: /sys/devices/platform/eeepc/cardr
|
||||||
Date: May 2008
|
Date: May 2008
|
||||||
KernelVersion: 2.6.26
|
KernelVersion: 2.6.26
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
Description:
|
Description:
|
||||||
Control the card reader. 1 means on, 0 means off.
|
Control the card reader. 1 means on, 0 means off.
|
||||||
|
|
||||||
What: /sys/devices/platform/eeepc-laptop/cpufv
|
What: /sys/devices/platform/eeepc/cpufv
|
||||||
Date: Jun 2009
|
Date: Jun 2009
|
||||||
KernelVersion: 2.6.31
|
KernelVersion: 2.6.31
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
@@ -42,7 +42,7 @@ Description:
|
|||||||
`------------ Availables modes
|
`------------ Availables modes
|
||||||
For example, 0x301 means: mode 1 selected, 3 available modes.
|
For example, 0x301 means: mode 1 selected, 3 available modes.
|
||||||
|
|
||||||
What: /sys/devices/platform/eeepc-laptop/available_cpufv
|
What: /sys/devices/platform/eeepc/available_cpufv
|
||||||
Date: Jun 2009
|
Date: Jun 2009
|
||||||
KernelVersion: 2.6.31
|
KernelVersion: 2.6.31
|
||||||
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
Contact: "Corentin Chary" <corentincj@iksaif.net>
|
||||||
|
@@ -101,3 +101,31 @@ Description:
|
|||||||
|
|
||||||
CAUTION: Using it will cause your machine's real-time (CMOS)
|
CAUTION: Using it will cause your machine's real-time (CMOS)
|
||||||
clock to be set to a random invalid time after a resume.
|
clock to be set to a random invalid time after a resume.
|
||||||
|
|
||||||
|
What: /sys/power/pm_async
|
||||||
|
Date: January 2009
|
||||||
|
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Description:
|
||||||
|
The /sys/power/pm_async file controls the switch allowing the
|
||||||
|
user space to enable or disable asynchronous suspend and resume
|
||||||
|
of devices. If enabled, this feature will cause some device
|
||||||
|
drivers' suspend and resume callbacks to be executed in parallel
|
||||||
|
with each other and with the main suspend thread. It is enabled
|
||||||
|
if this file contains "1", which is the default. It may be
|
||||||
|
disabled by writing "0" to this file, in which case all devices
|
||||||
|
will be suspended and resumed synchronously.
|
||||||
|
|
||||||
|
What: /sys/power/wakeup_count
|
||||||
|
Date: July 2010
|
||||||
|
Contact: Rafael J. Wysocki <rjw@sisk.pl>
|
||||||
|
Description:
|
||||||
|
The /sys/power/wakeup_count file allows user space to put the
|
||||||
|
system into a sleep state while taking into account the
|
||||||
|
concurrent arrival of wakeup events. Reading from it returns
|
||||||
|
the current number of registered wakeup events and it blocks if
|
||||||
|
some wakeup events are being processed at the time the file is
|
||||||
|
read from. Writing to it will only succeed if the current
|
||||||
|
number of wakeup events is equal to the written value and, if
|
||||||
|
successful, will make the kernel abort a subsequent transition
|
||||||
|
to a sleep state if any wakeup events are reported after the
|
||||||
|
write has returned.
|
||||||
|
10
Documentation/ABI/testing/sysfs-wacom
Normal file
10
Documentation/ABI/testing/sysfs-wacom
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
What: /sys/class/hidraw/hidraw*/device/speed
|
||||||
|
Date: April 2010
|
||||||
|
Kernel Version: 2.6.35
|
||||||
|
Contact: linux-bluetooth@vger.kernel.org
|
||||||
|
Description:
|
||||||
|
The /sys/class/hidraw/hidraw*/device/speed file controls
|
||||||
|
reporting speed of wacom bluetooth tablet. Reading from
|
||||||
|
this file returns 1 if tablet reports in high speed mode
|
||||||
|
or 0 otherwise. Writing to this file one of these values
|
||||||
|
switches reporting speed.
|
@@ -49,7 +49,7 @@ o oprofile 0.9 # oprofiled --version
|
|||||||
o udev 081 # udevinfo -V
|
o udev 081 # udevinfo -V
|
||||||
o grub 0.93 # grub --version
|
o grub 0.93 # grub --version
|
||||||
o mcelog 0.6
|
o mcelog 0.6
|
||||||
o iptables 1.4.1 # iptables -V
|
o iptables 1.4.2 # iptables -V
|
||||||
|
|
||||||
|
|
||||||
Kernel compilation
|
Kernel compilation
|
||||||
@@ -331,7 +331,7 @@ o <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
|
|||||||
|
|
||||||
Mkinitrd
|
Mkinitrd
|
||||||
--------
|
--------
|
||||||
o <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/>
|
o <https://code.launchpad.net/initrd-tools/main>
|
||||||
|
|
||||||
E2fsprogs
|
E2fsprogs
|
||||||
---------
|
---------
|
||||||
@@ -343,11 +343,11 @@ o <http://jfs.sourceforge.net/>
|
|||||||
|
|
||||||
Reiserfsprogs
|
Reiserfsprogs
|
||||||
-------------
|
-------------
|
||||||
o <http://www.namesys.com/pub/reiserfsprogs/reiserfsprogs-3.6.3.tar.gz>
|
o <http://www.kernel.org/pub/linux/utils/fs/reiserfs/>
|
||||||
|
|
||||||
Xfsprogs
|
Xfsprogs
|
||||||
--------
|
--------
|
||||||
o <ftp://oss.sgi.com/projects/xfs/download/>
|
o <ftp://oss.sgi.com/projects/xfs/>
|
||||||
|
|
||||||
Pcmciautils
|
Pcmciautils
|
||||||
-----------
|
-----------
|
||||||
@@ -387,18 +387,18 @@ o <http://sourceforge.net/projects/fuse>
|
|||||||
|
|
||||||
mcelog
|
mcelog
|
||||||
------
|
------
|
||||||
o <ftp://ftp.kernel.org/pub/linux/utils/cpu/mce/mcelog/>
|
o <ftp://ftp.kernel.org/pub/linux/utils/cpu/mce/>
|
||||||
|
|
||||||
Networking
|
Networking
|
||||||
**********
|
**********
|
||||||
|
|
||||||
PPP
|
PPP
|
||||||
---
|
---
|
||||||
o <ftp://ftp.samba.org/pub/ppp/ppp-2.4.0.tar.gz>
|
o <ftp://ftp.samba.org/pub/ppp/>
|
||||||
|
|
||||||
Isdn4k-utils
|
Isdn4k-utils
|
||||||
------------
|
------------
|
||||||
o <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/isdn4k-utils.v3.1pre1.tar.gz>
|
o <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/>
|
||||||
|
|
||||||
NFS-utils
|
NFS-utils
|
||||||
---------
|
---------
|
||||||
|
781
Documentation/DMA-API-HOWTO.txt
Normal file
781
Documentation/DMA-API-HOWTO.txt
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
Dynamic DMA mapping Guide
|
||||||
|
=========================
|
||||||
|
|
||||||
|
David S. Miller <davem@redhat.com>
|
||||||
|
Richard Henderson <rth@cygnus.com>
|
||||||
|
Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
This is a guide to device driver writers on how to use the DMA API
|
||||||
|
with example pseudo-code. For a concise description of the API, see
|
||||||
|
DMA-API.txt.
|
||||||
|
|
||||||
|
Most of the 64bit platforms have special hardware that translates bus
|
||||||
|
addresses (DMA addresses) into physical addresses. This is similar to
|
||||||
|
how page tables and/or a TLB translates virtual addresses to physical
|
||||||
|
addresses on a CPU. This is needed so that e.g. PCI devices can
|
||||||
|
access with a Single Address Cycle (32bit DMA address) any page in the
|
||||||
|
64bit physical address space. Previously in Linux those 64bit
|
||||||
|
platforms had to set artificial limits on the maximum RAM size in the
|
||||||
|
system, so that the virt_to_bus() static scheme works (the DMA address
|
||||||
|
translation tables were simply filled on bootup to map each bus
|
||||||
|
address to the physical page __pa(bus_to_virt())).
|
||||||
|
|
||||||
|
So that Linux can use the dynamic DMA mapping, it needs some help from the
|
||||||
|
drivers, namely it has to take into account that DMA addresses should be
|
||||||
|
mapped only for the time they are actually used and unmapped after the DMA
|
||||||
|
transfer.
|
||||||
|
|
||||||
|
The following API will work of course even on platforms where no such
|
||||||
|
hardware exists.
|
||||||
|
|
||||||
|
Note that the DMA API works with any bus independent of the underlying
|
||||||
|
microprocessor architecture. You should use the DMA API rather than
|
||||||
|
the bus specific DMA API (e.g. pci_dma_*).
|
||||||
|
|
||||||
|
First of all, you should make sure
|
||||||
|
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
|
|
||||||
|
is in your driver. This file will obtain for you the definition of the
|
||||||
|
dma_addr_t (which can hold any valid DMA address for the platform)
|
||||||
|
type which should be used everywhere you hold a DMA (bus) address
|
||||||
|
returned from the DMA mapping functions.
|
||||||
|
|
||||||
|
What memory is DMA'able?
|
||||||
|
|
||||||
|
The first piece of information you must know is what kernel memory can
|
||||||
|
be used with the DMA mapping facilities. There has been an unwritten
|
||||||
|
set of rules regarding this, and this text is an attempt to finally
|
||||||
|
write them down.
|
||||||
|
|
||||||
|
If you acquired your memory via the page allocator
|
||||||
|
(i.e. __get_free_page*()) or the generic memory allocators
|
||||||
|
(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
|
||||||
|
that memory using the addresses returned from those routines.
|
||||||
|
|
||||||
|
This means specifically that you may _not_ use the memory/addresses
|
||||||
|
returned from vmalloc() for DMA. It is possible to DMA to the
|
||||||
|
_underlying_ memory mapped into a vmalloc() area, but this requires
|
||||||
|
walking page tables to get the physical addresses, and then
|
||||||
|
translating each of those pages back to a kernel address using
|
||||||
|
something like __va(). [ EDIT: Update this when we integrate
|
||||||
|
Gerd Knorr's generic code which does this. ]
|
||||||
|
|
||||||
|
This rule also means that you may use neither kernel image addresses
|
||||||
|
(items in data/text/bss segments), nor module image addresses, nor
|
||||||
|
stack addresses for DMA. These could all be mapped somewhere entirely
|
||||||
|
different than the rest of physical memory. Even if those classes of
|
||||||
|
memory could physically work with DMA, you'd need to ensure the I/O
|
||||||
|
buffers were cacheline-aligned. Without that, you'd see cacheline
|
||||||
|
sharing problems (data corruption) on CPUs with DMA-incoherent caches.
|
||||||
|
(The CPU could write to one word, DMA would write to a different one
|
||||||
|
in the same cache line, and one of them could be overwritten.)
|
||||||
|
|
||||||
|
Also, this means that you cannot take the return of a kmap()
|
||||||
|
call and DMA to/from that. This is similar to vmalloc().
|
||||||
|
|
||||||
|
What about block I/O and networking buffers? The block I/O and
|
||||||
|
networking subsystems make sure that the buffers they use are valid
|
||||||
|
for you to DMA from/to.
|
||||||
|
|
||||||
|
DMA addressing limitations
|
||||||
|
|
||||||
|
Does your device have any DMA addressing limitations? For example, is
|
||||||
|
your device only capable of driving the low order 24-bits of address?
|
||||||
|
If so, you need to inform the kernel of this fact.
|
||||||
|
|
||||||
|
By default, the kernel assumes that your device can address the full
|
||||||
|
32-bits. For a 64-bit capable device, this needs to be increased.
|
||||||
|
And for a device with limitations, as discussed in the previous
|
||||||
|
paragraph, it needs to be decreased.
|
||||||
|
|
||||||
|
Special note about PCI: PCI-X specification requires PCI-X devices to
|
||||||
|
support 64-bit addressing (DAC) for all transactions. And at least
|
||||||
|
one platform (SGI SN2) requires 64-bit consistent allocations to
|
||||||
|
operate correctly when the IO bus is in PCI-X mode.
|
||||||
|
|
||||||
|
For correct operation, you must interrogate the kernel in your device
|
||||||
|
probe routine to see if the DMA controller on the machine can properly
|
||||||
|
support the DMA addressing limitation your device has. It is good
|
||||||
|
style to do this even if your device holds the default setting,
|
||||||
|
because this shows that you did think about these issues wrt. your
|
||||||
|
device.
|
||||||
|
|
||||||
|
The query is performed via a call to dma_set_mask():
|
||||||
|
|
||||||
|
int dma_set_mask(struct device *dev, u64 mask);
|
||||||
|
|
||||||
|
The query for consistent allocations is performed via a call to
|
||||||
|
dma_set_coherent_mask():
|
||||||
|
|
||||||
|
int dma_set_coherent_mask(struct device *dev, u64 mask);
|
||||||
|
|
||||||
|
Here, dev is a pointer to the device struct of your device, and mask
|
||||||
|
is a bit mask describing which bits of an address your device
|
||||||
|
supports. It returns zero if your card can perform DMA properly on
|
||||||
|
the machine given the address mask you provided. In general, the
|
||||||
|
device struct of your device is embedded in the bus specific device
|
||||||
|
struct of your device. For example, a pointer to the device struct of
|
||||||
|
your PCI device is pdev->dev (pdev is a pointer to the PCI device
|
||||||
|
struct of your device).
|
||||||
|
|
||||||
|
If it returns non-zero, your device cannot perform DMA properly on
|
||||||
|
this platform, and attempting to do so will result in undefined
|
||||||
|
behavior. You must either use a different mask, or not use DMA.
|
||||||
|
|
||||||
|
This means that in the failure case, you have three options:
|
||||||
|
|
||||||
|
1) Use another DMA mask, if possible (see below).
|
||||||
|
2) Use some non-DMA mode for data transfer, if possible.
|
||||||
|
3) Ignore this device and do not initialize it.
|
||||||
|
|
||||||
|
It is recommended that your driver print a kernel KERN_WARNING message
|
||||||
|
when you end up performing either #2 or #3. In this manner, if a user
|
||||||
|
of your driver reports that performance is bad or that the device is not
|
||||||
|
even detected, you can ask them for the kernel messages to find out
|
||||||
|
exactly why.
|
||||||
|
|
||||||
|
The standard 32-bit addressing device would do something like this:
|
||||||
|
|
||||||
|
if (dma_set_mask(dev, DMA_BIT_MASK(32))) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"mydev: No suitable DMA available.\n");
|
||||||
|
goto ignore_this_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
Another common scenario is a 64-bit capable device. The approach here
|
||||||
|
is to try for 64-bit addressing, but back down to a 32-bit mask that
|
||||||
|
should not fail. The kernel may fail the 64-bit mask not because the
|
||||||
|
platform is not capable of 64-bit addressing. Rather, it may fail in
|
||||||
|
this case simply because 32-bit addressing is done more efficiently
|
||||||
|
than 64-bit addressing. For example, Sparc64 PCI SAC addressing is
|
||||||
|
more efficient than DAC addressing.
|
||||||
|
|
||||||
|
Here is how you would handle a 64-bit capable device which can drive
|
||||||
|
all 64-bits when accessing streaming DMA:
|
||||||
|
|
||||||
|
int using_dac;
|
||||||
|
|
||||||
|
if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
|
||||||
|
using_dac = 1;
|
||||||
|
} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
|
||||||
|
using_dac = 0;
|
||||||
|
} else {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"mydev: No suitable DMA available.\n");
|
||||||
|
goto ignore_this_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
If a card is capable of using 64-bit consistent allocations as well,
|
||||||
|
the case would look like this:
|
||||||
|
|
||||||
|
int using_dac, consistent_using_dac;
|
||||||
|
|
||||||
|
if (!dma_set_mask(dev, DMA_BIT_MASK(64))) {
|
||||||
|
using_dac = 1;
|
||||||
|
consistent_using_dac = 1;
|
||||||
|
dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
|
||||||
|
} else if (!dma_set_mask(dev, DMA_BIT_MASK(32))) {
|
||||||
|
using_dac = 0;
|
||||||
|
consistent_using_dac = 0;
|
||||||
|
dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
|
||||||
|
} else {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"mydev: No suitable DMA available.\n");
|
||||||
|
goto ignore_this_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_set_coherent_mask() will always be able to set the same or a
|
||||||
|
smaller mask as dma_set_mask(). However for the rare case that a
|
||||||
|
device driver only uses consistent allocations, one would have to
|
||||||
|
check the return value from dma_set_coherent_mask().
|
||||||
|
|
||||||
|
Finally, if your device can only drive the low 24-bits of
|
||||||
|
address you might do something like:
|
||||||
|
|
||||||
|
if (dma_set_mask(dev, DMA_BIT_MASK(24))) {
|
||||||
|
printk(KERN_WARNING
|
||||||
|
"mydev: 24-bit DMA addressing not available.\n");
|
||||||
|
goto ignore_this_device;
|
||||||
|
}
|
||||||
|
|
||||||
|
When dma_set_mask() is successful, and returns zero, the kernel saves
|
||||||
|
away this mask you have provided. The kernel will use this
|
||||||
|
information later when you make DMA mappings.
|
||||||
|
|
||||||
|
There is a case which we are aware of at this time, which is worth
|
||||||
|
mentioning in this documentation. If your device supports multiple
|
||||||
|
functions (for example a sound card provides playback and record
|
||||||
|
functions) and the various different functions have _different_
|
||||||
|
DMA addressing limitations, you may wish to probe each mask and
|
||||||
|
only provide the functionality which the machine can handle. It
|
||||||
|
is important that the last call to dma_set_mask() be for the
|
||||||
|
most specific mask.
|
||||||
|
|
||||||
|
Here is pseudo-code showing how this might be done:
|
||||||
|
|
||||||
|
#define PLAYBACK_ADDRESS_BITS DMA_BIT_MASK(32)
|
||||||
|
#define RECORD_ADDRESS_BITS DMA_BIT_MASK(24)
|
||||||
|
|
||||||
|
struct my_sound_card *card;
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
...
|
||||||
|
if (!dma_set_mask(dev, PLAYBACK_ADDRESS_BITS)) {
|
||||||
|
card->playback_enabled = 1;
|
||||||
|
} else {
|
||||||
|
card->playback_enabled = 0;
|
||||||
|
printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
|
||||||
|
card->name);
|
||||||
|
}
|
||||||
|
if (!dma_set_mask(dev, RECORD_ADDRESS_BITS)) {
|
||||||
|
card->record_enabled = 1;
|
||||||
|
} else {
|
||||||
|
card->record_enabled = 0;
|
||||||
|
printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n",
|
||||||
|
card->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
A sound card was used as an example here because this genre of PCI
|
||||||
|
devices seems to be littered with ISA chips given a PCI front end,
|
||||||
|
and thus retaining the 16MB DMA addressing limitations of ISA.
|
||||||
|
|
||||||
|
Types of DMA mappings
|
||||||
|
|
||||||
|
There are two types of DMA mappings:
|
||||||
|
|
||||||
|
- Consistent DMA mappings which are usually mapped at driver
|
||||||
|
initialization, unmapped at the end and for which the hardware should
|
||||||
|
guarantee that the device and the CPU can access the data
|
||||||
|
in parallel and will see updates made by each other without any
|
||||||
|
explicit software flushing.
|
||||||
|
|
||||||
|
Think of "consistent" as "synchronous" or "coherent".
|
||||||
|
|
||||||
|
The current default is to return consistent memory in the low 32
|
||||||
|
bits of the bus space. However, for future compatibility you should
|
||||||
|
set the consistent mask even if this default is fine for your
|
||||||
|
driver.
|
||||||
|
|
||||||
|
Good examples of what to use consistent mappings for are:
|
||||||
|
|
||||||
|
- Network card DMA ring descriptors.
|
||||||
|
- SCSI adapter mailbox command data structures.
|
||||||
|
- Device firmware microcode executed out of
|
||||||
|
main memory.
|
||||||
|
|
||||||
|
The invariant these examples all require is that any CPU store
|
||||||
|
to memory is immediately visible to the device, and vice
|
||||||
|
versa. Consistent mappings guarantee this.
|
||||||
|
|
||||||
|
IMPORTANT: Consistent DMA memory does not preclude the usage of
|
||||||
|
proper memory barriers. The CPU may reorder stores to
|
||||||
|
consistent memory just as it may normal memory. Example:
|
||||||
|
if it is important for the device to see the first word
|
||||||
|
of a descriptor updated before the second, you must do
|
||||||
|
something like:
|
||||||
|
|
||||||
|
desc->word0 = address;
|
||||||
|
wmb();
|
||||||
|
desc->word1 = DESC_VALID;
|
||||||
|
|
||||||
|
in order to get correct behavior on all platforms.
|
||||||
|
|
||||||
|
Also, on some platforms your driver may need to flush CPU write
|
||||||
|
buffers in much the same way as it needs to flush write buffers
|
||||||
|
found in PCI bridges (such as by reading a register's value
|
||||||
|
after writing it).
|
||||||
|
|
||||||
|
- Streaming DMA mappings which are usually mapped for one DMA
|
||||||
|
transfer, unmapped right after it (unless you use dma_sync_* below)
|
||||||
|
and for which hardware can optimize for sequential accesses.
|
||||||
|
|
||||||
|
This of "streaming" as "asynchronous" or "outside the coherency
|
||||||
|
domain".
|
||||||
|
|
||||||
|
Good examples of what to use streaming mappings for are:
|
||||||
|
|
||||||
|
- Networking buffers transmitted/received by a device.
|
||||||
|
- Filesystem buffers written/read by a SCSI device.
|
||||||
|
|
||||||
|
The interfaces for using this type of mapping were designed in
|
||||||
|
such a way that an implementation can make whatever performance
|
||||||
|
optimizations the hardware allows. To this end, when using
|
||||||
|
such mappings you must be explicit about what you want to happen.
|
||||||
|
|
||||||
|
Neither type of DMA mapping has alignment restrictions that come from
|
||||||
|
the underlying bus, although some devices may have such restrictions.
|
||||||
|
Also, systems with caches that aren't DMA-coherent will work better
|
||||||
|
when the underlying buffers don't share cache lines with other data.
|
||||||
|
|
||||||
|
|
||||||
|
Using Consistent DMA mappings.
|
||||||
|
|
||||||
|
To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
|
||||||
|
you should do:
|
||||||
|
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
|
||||||
|
cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp);
|
||||||
|
|
||||||
|
where device is a struct device *. This may be called in interrupt
|
||||||
|
context with the GFP_ATOMIC flag.
|
||||||
|
|
||||||
|
Size is the length of the region you want to allocate, in bytes.
|
||||||
|
|
||||||
|
This routine will allocate RAM for that region, so it acts similarly to
|
||||||
|
__get_free_pages (but takes size instead of a page order). If your
|
||||||
|
driver needs regions sized smaller than a page, you may prefer using
|
||||||
|
the dma_pool interface, described below.
|
||||||
|
|
||||||
|
The consistent DMA mapping interfaces, for non-NULL dev, will by
|
||||||
|
default return a DMA address which is 32-bit addressable. Even if the
|
||||||
|
device indicates (via DMA mask) that it may address the upper 32-bits,
|
||||||
|
consistent allocation will only return > 32-bit addresses for DMA if
|
||||||
|
the consistent DMA mask has been explicitly changed via
|
||||||
|
dma_set_coherent_mask(). This is true of the dma_pool interface as
|
||||||
|
well.
|
||||||
|
|
||||||
|
dma_alloc_coherent returns two values: the virtual address which you
|
||||||
|
can use to access it from the CPU and dma_handle which you pass to the
|
||||||
|
card.
|
||||||
|
|
||||||
|
The cpu return address and the DMA bus master address are both
|
||||||
|
guaranteed to be aligned to the smallest PAGE_SIZE order which
|
||||||
|
is greater than or equal to the requested size. This invariant
|
||||||
|
exists (for example) to guarantee that if you allocate a chunk
|
||||||
|
which is smaller than or equal to 64 kilobytes, the extent of the
|
||||||
|
buffer you receive will not cross a 64K boundary.
|
||||||
|
|
||||||
|
To unmap and free such a DMA region, you call:
|
||||||
|
|
||||||
|
dma_free_coherent(dev, size, cpu_addr, dma_handle);
|
||||||
|
|
||||||
|
where dev, size are the same as in the above call and cpu_addr and
|
||||||
|
dma_handle are the values dma_alloc_coherent returned to you.
|
||||||
|
This function may not be called in interrupt context.
|
||||||
|
|
||||||
|
If your driver needs lots of smaller memory regions, you can write
|
||||||
|
custom code to subdivide pages returned by dma_alloc_coherent,
|
||||||
|
or you can use the dma_pool API to do that. A dma_pool is like
|
||||||
|
a kmem_cache, but it uses dma_alloc_coherent not __get_free_pages.
|
||||||
|
Also, it understands common hardware constraints for alignment,
|
||||||
|
like queue heads needing to be aligned on N byte boundaries.
|
||||||
|
|
||||||
|
Create a dma_pool like this:
|
||||||
|
|
||||||
|
struct dma_pool *pool;
|
||||||
|
|
||||||
|
pool = dma_pool_create(name, dev, size, align, alloc);
|
||||||
|
|
||||||
|
The "name" is for diagnostics (like a kmem_cache name); dev and size
|
||||||
|
are as above. The device's hardware alignment requirement for this
|
||||||
|
type of data is "align" (which is expressed in bytes, and must be a
|
||||||
|
power of two). If your device has no boundary crossing restrictions,
|
||||||
|
pass 0 for alloc; passing 4096 says memory allocated from this pool
|
||||||
|
must not cross 4KByte boundaries (but at that time it may be better to
|
||||||
|
go for dma_alloc_coherent directly instead).
|
||||||
|
|
||||||
|
Allocate memory from a dma pool like this:
|
||||||
|
|
||||||
|
cpu_addr = dma_pool_alloc(pool, flags, &dma_handle);
|
||||||
|
|
||||||
|
flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
|
||||||
|
holding SMP locks), SLAB_ATOMIC otherwise. Like dma_alloc_coherent,
|
||||||
|
this returns two values, cpu_addr and dma_handle.
|
||||||
|
|
||||||
|
Free memory that was allocated from a dma_pool like this:
|
||||||
|
|
||||||
|
dma_pool_free(pool, cpu_addr, dma_handle);
|
||||||
|
|
||||||
|
where pool is what you passed to dma_pool_alloc, and cpu_addr and
|
||||||
|
dma_handle are the values dma_pool_alloc returned. This function
|
||||||
|
may be called in interrupt context.
|
||||||
|
|
||||||
|
Destroy a dma_pool by calling:
|
||||||
|
|
||||||
|
dma_pool_destroy(pool);
|
||||||
|
|
||||||
|
Make sure you've called dma_pool_free for all memory allocated
|
||||||
|
from a pool before you destroy the pool. This function may not
|
||||||
|
be called in interrupt context.
|
||||||
|
|
||||||
|
DMA Direction
|
||||||
|
|
||||||
|
The interfaces described in subsequent portions of this document
|
||||||
|
take a DMA direction argument, which is an integer and takes on
|
||||||
|
one of the following values:
|
||||||
|
|
||||||
|
DMA_BIDIRECTIONAL
|
||||||
|
DMA_TO_DEVICE
|
||||||
|
DMA_FROM_DEVICE
|
||||||
|
DMA_NONE
|
||||||
|
|
||||||
|
One should provide the exact DMA direction if you know it.
|
||||||
|
|
||||||
|
DMA_TO_DEVICE means "from main memory to the device"
|
||||||
|
DMA_FROM_DEVICE means "from the device to main memory"
|
||||||
|
It is the direction in which the data moves during the DMA
|
||||||
|
transfer.
|
||||||
|
|
||||||
|
You are _strongly_ encouraged to specify this as precisely
|
||||||
|
as you possibly can.
|
||||||
|
|
||||||
|
If you absolutely cannot know the direction of the DMA transfer,
|
||||||
|
specify DMA_BIDIRECTIONAL. It means that the DMA can go in
|
||||||
|
either direction. The platform guarantees that you may legally
|
||||||
|
specify this, and that it will work, but this may be at the
|
||||||
|
cost of performance for example.
|
||||||
|
|
||||||
|
The value DMA_NONE is to be used for debugging. One can
|
||||||
|
hold this in a data structure before you come to know the
|
||||||
|
precise direction, and this will help catch cases where your
|
||||||
|
direction tracking logic has failed to set things up properly.
|
||||||
|
|
||||||
|
Another advantage of specifying this value precisely (outside of
|
||||||
|
potential platform-specific optimizations of such) is for debugging.
|
||||||
|
Some platforms actually have a write permission boolean which DMA
|
||||||
|
mappings can be marked with, much like page protections in the user
|
||||||
|
program address space. Such platforms can and do report errors in the
|
||||||
|
kernel logs when the DMA controller hardware detects violation of the
|
||||||
|
permission setting.
|
||||||
|
|
||||||
|
Only streaming mappings specify a direction, consistent mappings
|
||||||
|
implicitly have a direction attribute setting of
|
||||||
|
DMA_BIDIRECTIONAL.
|
||||||
|
|
||||||
|
The SCSI subsystem tells you the direction to use in the
|
||||||
|
'sc_data_direction' member of the SCSI command your driver is
|
||||||
|
working on.
|
||||||
|
|
||||||
|
For Networking drivers, it's a rather simple affair. For transmit
|
||||||
|
packets, map/unmap them with the DMA_TO_DEVICE direction
|
||||||
|
specifier. For receive packets, just the opposite, map/unmap them
|
||||||
|
with the DMA_FROM_DEVICE direction specifier.
|
||||||
|
|
||||||
|
Using Streaming DMA mappings
|
||||||
|
|
||||||
|
The streaming DMA mapping routines can be called from interrupt
|
||||||
|
context. There are two versions of each map/unmap, one which will
|
||||||
|
map/unmap a single memory region, and one which will map/unmap a
|
||||||
|
scatterlist.
|
||||||
|
|
||||||
|
To map a single region, you do:
|
||||||
|
|
||||||
|
struct device *dev = &my_dev->dev;
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
void *addr = buffer->ptr;
|
||||||
|
size_t size = buffer->len;
|
||||||
|
|
||||||
|
dma_handle = dma_map_single(dev, addr, size, direction);
|
||||||
|
|
||||||
|
and to unmap it:
|
||||||
|
|
||||||
|
dma_unmap_single(dev, dma_handle, size, direction);
|
||||||
|
|
||||||
|
You should call dma_unmap_single when the DMA activity is finished, e.g.
|
||||||
|
from the interrupt which told you that the DMA transfer is done.
|
||||||
|
|
||||||
|
Using cpu pointers like this for single mappings has a disadvantage,
|
||||||
|
you cannot reference HIGHMEM memory in this way. Thus, there is a
|
||||||
|
map/unmap interface pair akin to dma_{map,unmap}_single. These
|
||||||
|
interfaces deal with page/offset pairs instead of cpu pointers.
|
||||||
|
Specifically:
|
||||||
|
|
||||||
|
struct device *dev = &my_dev->dev;
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
struct page *page = buffer->page;
|
||||||
|
unsigned long offset = buffer->offset;
|
||||||
|
size_t size = buffer->len;
|
||||||
|
|
||||||
|
dma_handle = dma_map_page(dev, page, offset, size, direction);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
dma_unmap_page(dev, dma_handle, size, direction);
|
||||||
|
|
||||||
|
Here, "offset" means byte offset within the given page.
|
||||||
|
|
||||||
|
With scatterlists, you map a region gathered from several regions by:
|
||||||
|
|
||||||
|
int i, count = dma_map_sg(dev, sglist, nents, direction);
|
||||||
|
struct scatterlist *sg;
|
||||||
|
|
||||||
|
for_each_sg(sglist, sg, count, i) {
|
||||||
|
hw_address[i] = sg_dma_address(sg);
|
||||||
|
hw_len[i] = sg_dma_len(sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
where nents is the number of entries in the sglist.
|
||||||
|
|
||||||
|
The implementation is free to merge several consecutive sglist entries
|
||||||
|
into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
|
||||||
|
consecutive sglist entries can be merged into one provided the first one
|
||||||
|
ends and the second one starts on a page boundary - in fact this is a huge
|
||||||
|
advantage for cards which either cannot do scatter-gather or have very
|
||||||
|
limited number of scatter-gather entries) and returns the actual number
|
||||||
|
of sg entries it mapped them to. On failure 0 is returned.
|
||||||
|
|
||||||
|
Then you should loop count times (note: this can be less than nents times)
|
||||||
|
and use sg_dma_address() and sg_dma_len() macros where you previously
|
||||||
|
accessed sg->address and sg->length as shown above.
|
||||||
|
|
||||||
|
To unmap a scatterlist, just call:
|
||||||
|
|
||||||
|
dma_unmap_sg(dev, sglist, nents, direction);
|
||||||
|
|
||||||
|
Again, make sure DMA activity has already finished.
|
||||||
|
|
||||||
|
PLEASE NOTE: The 'nents' argument to the dma_unmap_sg call must be
|
||||||
|
the _same_ one you passed into the dma_map_sg call,
|
||||||
|
it should _NOT_ be the 'count' value _returned_ from the
|
||||||
|
dma_map_sg call.
|
||||||
|
|
||||||
|
Every dma_map_{single,sg} call should have its dma_unmap_{single,sg}
|
||||||
|
counterpart, because the bus address space is a shared resource (although
|
||||||
|
in some ports the mapping is per each BUS so less devices contend for the
|
||||||
|
same bus address space) and you could render the machine unusable by eating
|
||||||
|
all bus addresses.
|
||||||
|
|
||||||
|
If you need to use the same streaming DMA region multiple times and touch
|
||||||
|
the data in between the DMA transfers, the buffer needs to be synced
|
||||||
|
properly in order for the cpu and device to see the most uptodate and
|
||||||
|
correct copy of the DMA buffer.
|
||||||
|
|
||||||
|
So, firstly, just map it with dma_map_{single,sg}, and after each DMA
|
||||||
|
transfer call either:
|
||||||
|
|
||||||
|
dma_sync_single_for_cpu(dev, dma_handle, size, direction);
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
dma_sync_sg_for_cpu(dev, sglist, nents, direction);
|
||||||
|
|
||||||
|
as appropriate.
|
||||||
|
|
||||||
|
Then, if you wish to let the device get at the DMA area again,
|
||||||
|
finish accessing the data with the cpu, and then before actually
|
||||||
|
giving the buffer to the hardware call either:
|
||||||
|
|
||||||
|
dma_sync_single_for_device(dev, dma_handle, size, direction);
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
dma_sync_sg_for_device(dev, sglist, nents, direction);
|
||||||
|
|
||||||
|
as appropriate.
|
||||||
|
|
||||||
|
After the last DMA transfer call one of the DMA unmap routines
|
||||||
|
dma_unmap_{single,sg}. If you don't touch the data from the first dma_map_*
|
||||||
|
call till dma_unmap_*, then you don't have to call the dma_sync_*
|
||||||
|
routines at all.
|
||||||
|
|
||||||
|
Here is pseudo code which shows a situation in which you would need
|
||||||
|
to use the dma_sync_*() interfaces.
|
||||||
|
|
||||||
|
my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
|
||||||
|
{
|
||||||
|
dma_addr_t mapping;
|
||||||
|
|
||||||
|
mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
cp->rx_buf = buffer;
|
||||||
|
cp->rx_len = len;
|
||||||
|
cp->rx_dma = mapping;
|
||||||
|
|
||||||
|
give_rx_buf_to_card(cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct my_card *cp = devid;
|
||||||
|
|
||||||
|
...
|
||||||
|
if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
|
||||||
|
struct my_card_header *hp;
|
||||||
|
|
||||||
|
/* Examine the header to see if we wish
|
||||||
|
* to accept the data. But synchronize
|
||||||
|
* the DMA transfer with the CPU first
|
||||||
|
* so that we see updated contents.
|
||||||
|
*/
|
||||||
|
dma_sync_single_for_cpu(&cp->dev, cp->rx_dma,
|
||||||
|
cp->rx_len,
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
/* Now it is safe to examine the buffer. */
|
||||||
|
hp = (struct my_card_header *) cp->rx_buf;
|
||||||
|
if (header_is_ok(hp)) {
|
||||||
|
dma_unmap_single(&cp->dev, cp->rx_dma, cp->rx_len,
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
|
pass_to_upper_layers(cp->rx_buf);
|
||||||
|
make_and_setup_new_rx_buf(cp);
|
||||||
|
} else {
|
||||||
|
/* Just sync the buffer and give it back
|
||||||
|
* to the card.
|
||||||
|
*/
|
||||||
|
dma_sync_single_for_device(&cp->dev,
|
||||||
|
cp->rx_dma,
|
||||||
|
cp->rx_len,
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
|
give_rx_buf_to_card(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Drivers converted fully to this interface should not use virt_to_bus any
|
||||||
|
longer, nor should they use bus_to_virt. Some drivers have to be changed a
|
||||||
|
little bit, because there is no longer an equivalent to bus_to_virt in the
|
||||||
|
dynamic DMA mapping scheme - you have to always store the DMA addresses
|
||||||
|
returned by the dma_alloc_coherent, dma_pool_alloc, and dma_map_single
|
||||||
|
calls (dma_map_sg stores them in the scatterlist itself if the platform
|
||||||
|
supports dynamic DMA mapping in hardware) in your driver structures and/or
|
||||||
|
in the card registers.
|
||||||
|
|
||||||
|
All drivers should be using these interfaces with no exceptions. It
|
||||||
|
is planned to completely remove virt_to_bus() and bus_to_virt() as
|
||||||
|
they are entirely deprecated. Some ports already do not provide these
|
||||||
|
as it is impossible to correctly support them.
|
||||||
|
|
||||||
|
Handling Errors
|
||||||
|
|
||||||
|
DMA address space is limited on some architectures and an allocation
|
||||||
|
failure can be determined by:
|
||||||
|
|
||||||
|
- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0
|
||||||
|
|
||||||
|
- checking the returned dma_addr_t of dma_map_single and dma_map_page
|
||||||
|
by using dma_mapping_error():
|
||||||
|
|
||||||
|
dma_addr_t dma_handle;
|
||||||
|
|
||||||
|
dma_handle = dma_map_single(dev, addr, size, direction);
|
||||||
|
if (dma_mapping_error(dev, dma_handle)) {
|
||||||
|
/*
|
||||||
|
* reduce current DMA mapping usage,
|
||||||
|
* delay and try again later or
|
||||||
|
* reset driver.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
Networking drivers must call dev_kfree_skb to free the socket buffer
|
||||||
|
and return NETDEV_TX_OK if the DMA mapping fails on the transmit hook
|
||||||
|
(ndo_start_xmit). This means that the socket buffer is just dropped in
|
||||||
|
the failure case.
|
||||||
|
|
||||||
|
SCSI drivers must return SCSI_MLQUEUE_HOST_BUSY if the DMA mapping
|
||||||
|
fails in the queuecommand hook. This means that the SCSI subsystem
|
||||||
|
passes the command to the driver again later.
|
||||||
|
|
||||||
|
Optimizing Unmap State Space Consumption
|
||||||
|
|
||||||
|
On many platforms, dma_unmap_{single,page}() is simply a nop.
|
||||||
|
Therefore, keeping track of the mapping address and length is a waste
|
||||||
|
of space. Instead of filling your drivers up with ifdefs and the like
|
||||||
|
to "work around" this (which would defeat the whole purpose of a
|
||||||
|
portable API) the following facilities are provided.
|
||||||
|
|
||||||
|
Actually, instead of describing the macros one by one, we'll
|
||||||
|
transform some example code.
|
||||||
|
|
||||||
|
1) Use DEFINE_DMA_UNMAP_{ADDR,LEN} in state saving structures.
|
||||||
|
Example, before:
|
||||||
|
|
||||||
|
struct ring_state {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
dma_addr_t mapping;
|
||||||
|
__u32 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
after:
|
||||||
|
|
||||||
|
struct ring_state {
|
||||||
|
struct sk_buff *skb;
|
||||||
|
DEFINE_DMA_UNMAP_ADDR(mapping);
|
||||||
|
DEFINE_DMA_UNMAP_LEN(len);
|
||||||
|
};
|
||||||
|
|
||||||
|
2) Use dma_unmap_{addr,len}_set to set these values.
|
||||||
|
Example, before:
|
||||||
|
|
||||||
|
ringp->mapping = FOO;
|
||||||
|
ringp->len = BAR;
|
||||||
|
|
||||||
|
after:
|
||||||
|
|
||||||
|
dma_unmap_addr_set(ringp, mapping, FOO);
|
||||||
|
dma_unmap_len_set(ringp, len, BAR);
|
||||||
|
|
||||||
|
3) Use dma_unmap_{addr,len} to access these values.
|
||||||
|
Example, before:
|
||||||
|
|
||||||
|
dma_unmap_single(dev, ringp->mapping, ringp->len,
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
after:
|
||||||
|
|
||||||
|
dma_unmap_single(dev,
|
||||||
|
dma_unmap_addr(ringp, mapping),
|
||||||
|
dma_unmap_len(ringp, len),
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
|
|
||||||
|
It really should be self-explanatory. We treat the ADDR and LEN
|
||||||
|
separately, because it is possible for an implementation to only
|
||||||
|
need the address in order to perform the unmap operation.
|
||||||
|
|
||||||
|
Platform Issues
|
||||||
|
|
||||||
|
If you are just writing drivers for Linux and do not maintain
|
||||||
|
an architecture port for the kernel, you can safely skip down
|
||||||
|
to "Closing".
|
||||||
|
|
||||||
|
1) Struct scatterlist requirements.
|
||||||
|
|
||||||
|
Don't invent the architecture specific struct scatterlist; just use
|
||||||
|
<asm-generic/scatterlist.h>. You need to enable
|
||||||
|
CONFIG_NEED_SG_DMA_LENGTH if the architecture supports IOMMUs
|
||||||
|
(including software IOMMU).
|
||||||
|
|
||||||
|
2) ARCH_DMA_MINALIGN
|
||||||
|
|
||||||
|
Architectures must ensure that kmalloc'ed buffer is
|
||||||
|
DMA-safe. Drivers and subsystems depend on it. If an architecture
|
||||||
|
isn't fully DMA-coherent (i.e. hardware doesn't ensure that data in
|
||||||
|
the CPU cache is identical to data in main memory),
|
||||||
|
ARCH_DMA_MINALIGN must be set so that the memory allocator
|
||||||
|
makes sure that kmalloc'ed buffer doesn't share a cache line with
|
||||||
|
the others. See arch/arm/include/asm/cache.h as an example.
|
||||||
|
|
||||||
|
Note that ARCH_DMA_MINALIGN is about DMA memory alignment
|
||||||
|
constraints. You don't need to worry about the architecture data
|
||||||
|
alignment constraints (e.g. the alignment constraints about 64-bit
|
||||||
|
objects).
|
||||||
|
|
||||||
|
3) Supporting multiple types of IOMMUs
|
||||||
|
|
||||||
|
If your architecture needs to support multiple types of IOMMUs, you
|
||||||
|
can use include/linux/asm-generic/dma-mapping-common.h. It's a
|
||||||
|
library to support the DMA API with multiple types of IOMMUs. Lots
|
||||||
|
of architectures (x86, powerpc, sh, alpha, ia64, microblaze and
|
||||||
|
sparc) use it. Choose one to see how it can be used. If you need to
|
||||||
|
support multiple types of IOMMUs in a single system, the example of
|
||||||
|
x86 or powerpc helps.
|
||||||
|
|
||||||
|
Closing
|
||||||
|
|
||||||
|
This document, and the API itself, would not be in its current
|
||||||
|
form without the feedback and suggestions from numerous individuals.
|
||||||
|
We would like to specifically mention, in no particular order, the
|
||||||
|
following people:
|
||||||
|
|
||||||
|
Russell King <rmk@arm.linux.org.uk>
|
||||||
|
Leo Dagum <dagum@barrel.engr.sgi.com>
|
||||||
|
Ralf Baechle <ralf@oss.sgi.com>
|
||||||
|
Grant Grundler <grundler@cup.hp.com>
|
||||||
|
Jay Estabrook <Jay.Estabrook@compaq.com>
|
||||||
|
Thomas Sailer <sailer@ife.ee.ethz.ch>
|
||||||
|
Andrea Arcangeli <andrea@suse.de>
|
||||||
|
Jens Axboe <jens.axboe@oracle.com>
|
||||||
|
David Mosberger-Tang <davidm@hpl.hp.com>
|
@@ -4,20 +4,18 @@
|
|||||||
James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
|
James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
|
||||||
|
|
||||||
This document describes the DMA API. For a more gentle introduction
|
This document describes the DMA API. For a more gentle introduction
|
||||||
phrased in terms of the pci_ equivalents (and actual examples) see
|
of the API (and actual examples) see
|
||||||
Documentation/PCI/PCI-DMA-mapping.txt.
|
Documentation/DMA-API-HOWTO.txt.
|
||||||
|
|
||||||
This API is split into two pieces. Part I describes the API and the
|
This API is split into two pieces. Part I describes the API. Part II
|
||||||
corresponding pci_ API. Part II describes the extensions to the API
|
describes the extensions to the API for supporting non-consistent
|
||||||
for supporting non-consistent memory machines. Unless you know that
|
memory machines. Unless you know that your driver absolutely has to
|
||||||
your driver absolutely has to support non-consistent platforms (this
|
support non-consistent platforms (this is usually only legacy
|
||||||
is usually only legacy platforms) you should only use the API
|
platforms) you should only use the API described in part I.
|
||||||
described in part I.
|
|
||||||
|
|
||||||
Part I - pci_ and dma_ Equivalent API
|
Part I - dma_ API
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
To get the pci_ API, you must #include <linux/pci.h>
|
|
||||||
To get the dma_ API, you must #include <linux/dma-mapping.h>
|
To get the dma_ API, you must #include <linux/dma-mapping.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -27,9 +25,6 @@ Part Ia - Using large dma-coherent buffers
|
|||||||
void *
|
void *
|
||||||
dma_alloc_coherent(struct device *dev, size_t size,
|
dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
dma_addr_t *dma_handle, gfp_t flag)
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
void *
|
|
||||||
pci_alloc_consistent(struct pci_dev *dev, size_t size,
|
|
||||||
dma_addr_t *dma_handle)
|
|
||||||
|
|
||||||
Consistent memory is memory for which a write by either the device or
|
Consistent memory is memory for which a write by either the device or
|
||||||
the processor can immediately be read by the processor or device
|
the processor can immediately be read by the processor or device
|
||||||
@@ -53,15 +48,11 @@ The simplest way to do that is to use the dma_pool calls (see below).
|
|||||||
The flag parameter (dma_alloc_coherent only) allows the caller to
|
The flag parameter (dma_alloc_coherent only) allows the caller to
|
||||||
specify the GFP_ flags (see kmalloc) for the allocation (the
|
specify the GFP_ flags (see kmalloc) for the allocation (the
|
||||||
implementation may choose to ignore flags that affect the location of
|
implementation may choose to ignore flags that affect the location of
|
||||||
the returned memory, like GFP_DMA). For pci_alloc_consistent, you
|
the returned memory, like GFP_DMA).
|
||||||
must assume GFP_ATOMIC behaviour.
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
||||||
dma_addr_t dma_handle)
|
dma_addr_t dma_handle)
|
||||||
void
|
|
||||||
pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr,
|
|
||||||
dma_addr_t dma_handle)
|
|
||||||
|
|
||||||
Free the region of consistent memory you previously allocated. dev,
|
Free the region of consistent memory you previously allocated. dev,
|
||||||
size and dma_handle must all be the same as those passed into the
|
size and dma_handle must all be the same as those passed into the
|
||||||
@@ -89,10 +80,6 @@ for alignment, like queue heads needing to be aligned on N-byte boundaries.
|
|||||||
dma_pool_create(const char *name, struct device *dev,
|
dma_pool_create(const char *name, struct device *dev,
|
||||||
size_t size, size_t align, size_t alloc);
|
size_t size, size_t align, size_t alloc);
|
||||||
|
|
||||||
struct pci_pool *
|
|
||||||
pci_pool_create(const char *name, struct pci_device *dev,
|
|
||||||
size_t size, size_t align, size_t alloc);
|
|
||||||
|
|
||||||
The pool create() routines initialize a pool of dma-coherent buffers
|
The pool create() routines initialize a pool of dma-coherent buffers
|
||||||
for use with a given device. It must be called in a context which
|
for use with a given device. It must be called in a context which
|
||||||
can sleep.
|
can sleep.
|
||||||
@@ -108,9 +95,6 @@ from this pool must not cross 4KByte boundaries.
|
|||||||
void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags,
|
void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags,
|
||||||
dma_addr_t *dma_handle);
|
dma_addr_t *dma_handle);
|
||||||
|
|
||||||
void *pci_pool_alloc(struct pci_pool *pool, gfp_t gfp_flags,
|
|
||||||
dma_addr_t *dma_handle);
|
|
||||||
|
|
||||||
This allocates memory from the pool; the returned memory will meet the size
|
This allocates memory from the pool; the returned memory will meet the size
|
||||||
and alignment requirements specified at creation time. Pass GFP_ATOMIC to
|
and alignment requirements specified at creation time. Pass GFP_ATOMIC to
|
||||||
prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks),
|
prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks),
|
||||||
@@ -122,9 +106,6 @@ pool's device.
|
|||||||
void dma_pool_free(struct dma_pool *pool, void *vaddr,
|
void dma_pool_free(struct dma_pool *pool, void *vaddr,
|
||||||
dma_addr_t addr);
|
dma_addr_t addr);
|
||||||
|
|
||||||
void pci_pool_free(struct pci_pool *pool, void *vaddr,
|
|
||||||
dma_addr_t addr);
|
|
||||||
|
|
||||||
This puts memory back into the pool. The pool is what was passed to
|
This puts memory back into the pool. The pool is what was passed to
|
||||||
the pool allocation routine; the cpu (vaddr) and dma addresses are what
|
the pool allocation routine; the cpu (vaddr) and dma addresses are what
|
||||||
were returned when that routine allocated the memory being freed.
|
were returned when that routine allocated the memory being freed.
|
||||||
@@ -132,8 +113,6 @@ were returned when that routine allocated the memory being freed.
|
|||||||
|
|
||||||
void dma_pool_destroy(struct dma_pool *pool);
|
void dma_pool_destroy(struct dma_pool *pool);
|
||||||
|
|
||||||
void pci_pool_destroy(struct pci_pool *pool);
|
|
||||||
|
|
||||||
The pool destroy() routines free the resources of the pool. They must be
|
The pool destroy() routines free the resources of the pool. They must be
|
||||||
called in a context which can sleep. Make sure you've freed all allocated
|
called in a context which can sleep. Make sure you've freed all allocated
|
||||||
memory back to the pool before you destroy it.
|
memory back to the pool before you destroy it.
|
||||||
@@ -144,8 +123,6 @@ Part Ic - DMA addressing limitations
|
|||||||
|
|
||||||
int
|
int
|
||||||
dma_supported(struct device *dev, u64 mask)
|
dma_supported(struct device *dev, u64 mask)
|
||||||
int
|
|
||||||
pci_dma_supported(struct pci_dev *hwdev, u64 mask)
|
|
||||||
|
|
||||||
Checks to see if the device can support DMA to the memory described by
|
Checks to see if the device can support DMA to the memory described by
|
||||||
mask.
|
mask.
|
||||||
@@ -159,8 +136,14 @@ driver writers.
|
|||||||
|
|
||||||
int
|
int
|
||||||
dma_set_mask(struct device *dev, u64 mask)
|
dma_set_mask(struct device *dev, u64 mask)
|
||||||
|
|
||||||
|
Checks to see if the mask is possible and updates the device
|
||||||
|
parameters if it is.
|
||||||
|
|
||||||
|
Returns: 0 if successful and a negative error if not.
|
||||||
|
|
||||||
int
|
int
|
||||||
pci_set_dma_mask(struct pci_device *dev, u64 mask)
|
dma_set_coherent_mask(struct device *dev, u64 mask)
|
||||||
|
|
||||||
Checks to see if the mask is possible and updates the device
|
Checks to see if the mask is possible and updates the device
|
||||||
parameters if it is.
|
parameters if it is.
|
||||||
@@ -187,9 +170,6 @@ Part Id - Streaming DMA mappings
|
|||||||
dma_addr_t
|
dma_addr_t
|
||||||
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
dma_addr_t
|
|
||||||
pci_map_single(struct pci_dev *hwdev, void *cpu_addr, size_t size,
|
|
||||||
int direction)
|
|
||||||
|
|
||||||
Maps a piece of processor virtual memory so it can be accessed by the
|
Maps a piece of processor virtual memory so it can be accessed by the
|
||||||
device and returns the physical handle of the memory.
|
device and returns the physical handle of the memory.
|
||||||
@@ -198,14 +178,10 @@ The direction for both api's may be converted freely by casting.
|
|||||||
However the dma_ API uses a strongly typed enumerator for its
|
However the dma_ API uses a strongly typed enumerator for its
|
||||||
direction:
|
direction:
|
||||||
|
|
||||||
DMA_NONE = PCI_DMA_NONE no direction (used for
|
DMA_NONE no direction (used for debugging)
|
||||||
debugging)
|
DMA_TO_DEVICE data is going from the memory to the device
|
||||||
DMA_TO_DEVICE = PCI_DMA_TODEVICE data is going from the
|
DMA_FROM_DEVICE data is coming from the device to the memory
|
||||||
memory to the device
|
DMA_BIDIRECTIONAL direction isn't known
|
||||||
DMA_FROM_DEVICE = PCI_DMA_FROMDEVICE data is coming from
|
|
||||||
the device to the
|
|
||||||
memory
|
|
||||||
DMA_BIDIRECTIONAL = PCI_DMA_BIDIRECTIONAL direction isn't known
|
|
||||||
|
|
||||||
Notes: Not all memory regions in a machine can be mapped by this
|
Notes: Not all memory regions in a machine can be mapped by this
|
||||||
API. Further, regions that appear to be physically contiguous in
|
API. Further, regions that appear to be physically contiguous in
|
||||||
@@ -268,9 +244,6 @@ cache lines are updated with data that the device may have changed).
|
|||||||
void
|
void
|
||||||
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
void
|
|
||||||
pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
|
|
||||||
size_t size, int direction)
|
|
||||||
|
|
||||||
Unmaps the region previously mapped. All the parameters passed in
|
Unmaps the region previously mapped. All the parameters passed in
|
||||||
must be identical to those passed in (and returned) by the mapping
|
must be identical to those passed in (and returned) by the mapping
|
||||||
@@ -280,15 +253,9 @@ dma_addr_t
|
|||||||
dma_map_page(struct device *dev, struct page *page,
|
dma_map_page(struct device *dev, struct page *page,
|
||||||
unsigned long offset, size_t size,
|
unsigned long offset, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
dma_addr_t
|
|
||||||
pci_map_page(struct pci_dev *hwdev, struct page *page,
|
|
||||||
unsigned long offset, size_t size, int direction)
|
|
||||||
void
|
void
|
||||||
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
void
|
|
||||||
pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
|
|
||||||
size_t size, int direction)
|
|
||||||
|
|
||||||
API for mapping and unmapping for pages. All the notes and warnings
|
API for mapping and unmapping for pages. All the notes and warnings
|
||||||
for the other mapping APIs apply here. Also, although the <offset>
|
for the other mapping APIs apply here. Also, although the <offset>
|
||||||
@@ -299,9 +266,6 @@ cache width is.
|
|||||||
int
|
int
|
||||||
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||||
|
|
||||||
int
|
|
||||||
pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
|
|
||||||
|
|
||||||
In some circumstances dma_map_single and dma_map_page will fail to create
|
In some circumstances dma_map_single and dma_map_page will fail to create
|
||||||
a mapping. A driver can check for these errors by testing the returned
|
a mapping. A driver can check for these errors by testing the returned
|
||||||
dma address with dma_mapping_error(). A non-zero return value means the mapping
|
dma address with dma_mapping_error(). A non-zero return value means the mapping
|
||||||
@@ -311,9 +275,6 @@ reduce current DMA mapping usage or delay and try again later).
|
|||||||
int
|
int
|
||||||
dma_map_sg(struct device *dev, struct scatterlist *sg,
|
dma_map_sg(struct device *dev, struct scatterlist *sg,
|
||||||
int nents, enum dma_data_direction direction)
|
int nents, enum dma_data_direction direction)
|
||||||
int
|
|
||||||
pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
|
||||||
int nents, int direction)
|
|
||||||
|
|
||||||
Returns: the number of physical segments mapped (this may be shorter
|
Returns: the number of physical segments mapped (this may be shorter
|
||||||
than <nents> passed in if some elements of the scatter/gather list are
|
than <nents> passed in if some elements of the scatter/gather list are
|
||||||
@@ -353,9 +314,6 @@ accessed sg->address and sg->length as shown above.
|
|||||||
void
|
void
|
||||||
dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
||||||
int nhwentries, enum dma_data_direction direction)
|
int nhwentries, enum dma_data_direction direction)
|
||||||
void
|
|
||||||
pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
|
||||||
int nents, int direction)
|
|
||||||
|
|
||||||
Unmap the previously mapped scatter/gather list. All the parameters
|
Unmap the previously mapped scatter/gather list. All the parameters
|
||||||
must be the same as those and passed in to the scatter/gather mapping
|
must be the same as those and passed in to the scatter/gather mapping
|
||||||
@@ -365,21 +323,23 @@ Note: <nents> must be the number you passed in, *not* the number of
|
|||||||
physical entries returned.
|
physical entries returned.
|
||||||
|
|
||||||
void
|
void
|
||||||
dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
|
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
void
|
void
|
||||||
pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle,
|
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||||
size_t size, int direction)
|
|
||||||
void
|
|
||||||
dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
|
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
void
|
void
|
||||||
pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg,
|
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
|
||||||
int nelems, int direction)
|
enum dma_data_direction direction)
|
||||||
|
void
|
||||||
|
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
Synchronise a single contiguous or scatter/gather mapping. All the
|
Synchronise a single contiguous or scatter/gather mapping for the cpu
|
||||||
parameters must be the same as those passed into the single mapping
|
and device. With the sync_sg API, all the parameters must be the same
|
||||||
API.
|
as those passed into the single mapping API. With the sync_single API,
|
||||||
|
you can use dma_handle and size parameters that aren't identical to
|
||||||
|
those passed into the single mapping API to do a partial sync.
|
||||||
|
|
||||||
Notes: You must do this:
|
Notes: You must do this:
|
||||||
|
|
||||||
@@ -461,9 +421,9 @@ void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
|
|||||||
Part II - Advanced dma_ usage
|
Part II - Advanced dma_ usage
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
Warning: These pieces of the DMA API have no PCI equivalent. They
|
Warning: These pieces of the DMA API should not be used in the
|
||||||
should also not be used in the majority of cases, since they cater for
|
majority of cases, since they cater for unlikely corner cases that
|
||||||
unlikely corner cases that don't belong in usual drivers.
|
don't belong in usual drivers.
|
||||||
|
|
||||||
If you don't understand how cache line coherency works between a
|
If you don't understand how cache line coherency works between a
|
||||||
processor and an I/O device, you should not be using this part of the
|
processor and an I/O device, you should not be using this part of the
|
||||||
@@ -495,12 +455,6 @@ Free memory allocated by the nonconsistent API. All parameters must
|
|||||||
be identical to those passed in (and returned by
|
be identical to those passed in (and returned by
|
||||||
dma_alloc_noncoherent()).
|
dma_alloc_noncoherent()).
|
||||||
|
|
||||||
int
|
|
||||||
dma_is_consistent(struct device *dev, dma_addr_t dma_handle)
|
|
||||||
|
|
||||||
Returns true if the device dev is performing consistent DMA on the memory
|
|
||||||
area pointed to by the dma_handle.
|
|
||||||
|
|
||||||
int
|
int
|
||||||
dma_get_cache_alignment(void)
|
dma_get_cache_alignment(void)
|
||||||
|
|
||||||
@@ -513,16 +467,6 @@ line, but it will guarantee that one or more cache lines fit exactly
|
|||||||
into the width returned by this call. It will also always be a power
|
into the width returned by this call. It will also always be a power
|
||||||
of two for easy alignment.
|
of two for easy alignment.
|
||||||
|
|
||||||
void
|
|
||||||
dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
|
|
||||||
unsigned long offset, size_t size,
|
|
||||||
enum dma_data_direction direction)
|
|
||||||
|
|
||||||
Does a partial sync, starting at offset and continuing for size. You
|
|
||||||
must be careful to observe the cache alignment and width when doing
|
|
||||||
anything like this. You must also be extra careful about accessing
|
|
||||||
memory you intend to sync partially.
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
|
@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
|
|||||||
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
|
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
|
||||||
mac80211.xml debugobjects.xml sh.xml regulator.xml \
|
mac80211.xml debugobjects.xml sh.xml regulator.xml \
|
||||||
alsa-driver-api.xml writing-an-alsa-driver.xml \
|
alsa-driver-api.xml writing-an-alsa-driver.xml \
|
||||||
tracepoint.xml media.xml
|
tracepoint.xml media.xml drm.xml
|
||||||
|
|
||||||
###
|
###
|
||||||
# The build process is as follows (targets):
|
# The build process is as follows (targets):
|
||||||
@@ -35,7 +35,7 @@ PS_METHOD = $(prefer-db2x)
|
|||||||
PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
|
PHONY += xmldocs sgmldocs psdocs pdfdocs htmldocs mandocs installmandocs cleandocs xmldoclinks
|
||||||
|
|
||||||
BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
|
BOOKS := $(addprefix $(obj)/,$(DOCBOOKS))
|
||||||
xmldocs: $(BOOKS) xmldoclinks
|
xmldocs: $(BOOKS)
|
||||||
sgmldocs: xmldocs
|
sgmldocs: xmldocs
|
||||||
|
|
||||||
PS := $(patsubst %.xml, %.ps, $(BOOKS))
|
PS := $(patsubst %.xml, %.ps, $(BOOKS))
|
||||||
@@ -45,7 +45,7 @@ PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
|
|||||||
pdfdocs: $(PDF)
|
pdfdocs: $(PDF)
|
||||||
|
|
||||||
HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
|
HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
|
||||||
htmldocs: $(HTML)
|
htmldocs: $(HTML) xmldoclinks
|
||||||
$(call build_main_index)
|
$(call build_main_index)
|
||||||
$(call build_images)
|
$(call build_images)
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ define rule_docproc
|
|||||||
) > $(dir $@).$(notdir $@).cmd
|
) > $(dir $@).$(notdir $@).cmd
|
||||||
endef
|
endef
|
||||||
|
|
||||||
%.xml: %.tmpl FORCE
|
%.xml: %.tmpl xmldoclinks FORCE
|
||||||
$(call if_changed_rule,docproc)
|
$(call if_changed_rule,docproc)
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@@ -45,8 +45,7 @@
|
|||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1><title>Atomic and pointer manipulation</title>
|
<sect1><title>Atomic and pointer manipulation</title>
|
||||||
!Iarch/x86/include/asm/atomic_32.h
|
!Iarch/x86/include/asm/atomic.h
|
||||||
!Iarch/x86/include/asm/unaligned.h
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1><title>Delaying, scheduling, and timer routines</title>
|
<sect1><title>Delaying, scheduling, and timer routines</title>
|
||||||
@@ -111,6 +110,7 @@ X!Edrivers/base/attribute_container.c
|
|||||||
<!--
|
<!--
|
||||||
X!Edrivers/base/interface.c
|
X!Edrivers/base/interface.c
|
||||||
-->
|
-->
|
||||||
|
!Iinclude/linux/platform_device.h
|
||||||
!Edrivers/base/platform.c
|
!Edrivers/base/platform.c
|
||||||
!Edrivers/base/bus.c
|
!Edrivers/base/bus.c
|
||||||
</sect1>
|
</sect1>
|
||||||
|
@@ -316,7 +316,7 @@ CPU B: spin_unlock_irqrestore(&dev_lock, flags)
|
|||||||
|
|
||||||
<chapter id="pubfunctions">
|
<chapter id="pubfunctions">
|
||||||
<title>Public Functions Provided</title>
|
<title>Public Functions Provided</title>
|
||||||
!Iarch/x86/include/asm/io_32.h
|
!Iarch/x86/include/asm/io.h
|
||||||
!Elib/iomap.c
|
!Elib/iomap.c
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
839
Documentation/DocBook/drm.tmpl
Normal file
839
Documentation/DocBook/drm.tmpl
Normal file
@@ -0,0 +1,839 @@
|
|||||||
|
<?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="drmDevelopersGuide">
|
||||||
|
<bookinfo>
|
||||||
|
<title>Linux DRM Developer's Guide</title>
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
<year>2008-2009</year>
|
||||||
|
<holder>
|
||||||
|
Intel Corporation (Jesse Barnes <jesse.barnes@intel.com>)
|
||||||
|
</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<legalnotice>
|
||||||
|
<para>
|
||||||
|
The contents of this file may be used under the terms of the GNU
|
||||||
|
General Public License version 2 (the "GPL") as distributed in
|
||||||
|
the kernel source COPYING file.
|
||||||
|
</para>
|
||||||
|
</legalnotice>
|
||||||
|
</bookinfo>
|
||||||
|
|
||||||
|
<toc></toc>
|
||||||
|
|
||||||
|
<!-- Introduction -->
|
||||||
|
|
||||||
|
<chapter id="drmIntroduction">
|
||||||
|
<title>Introduction</title>
|
||||||
|
<para>
|
||||||
|
The Linux DRM layer contains code intended to support the needs
|
||||||
|
of complex graphics devices, usually containing programmable
|
||||||
|
pipelines well suited to 3D graphics acceleration. Graphics
|
||||||
|
drivers in the kernel can make use of DRM functions to make
|
||||||
|
tasks like memory management, interrupt handling and DMA easier,
|
||||||
|
and provide a uniform interface to applications.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A note on versions: this guide covers features found in the DRM
|
||||||
|
tree, including the TTM memory manager, output configuration and
|
||||||
|
mode setting, and the new vblank internals, in addition to all
|
||||||
|
the regular features found in current kernels.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
[Insert diagram of typical DRM stack here]
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<!-- Internals -->
|
||||||
|
|
||||||
|
<chapter id="drmInternals">
|
||||||
|
<title>DRM Internals</title>
|
||||||
|
<para>
|
||||||
|
This chapter documents DRM internals relevant to driver authors
|
||||||
|
and developers working to add support for the latest features to
|
||||||
|
existing drivers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
First, we'll go over some typical driver initialization
|
||||||
|
requirements, like setting up command buffers, creating an
|
||||||
|
initial output configuration, and initializing core services.
|
||||||
|
Subsequent sections will cover core internals in more detail,
|
||||||
|
providing implementation notes and examples.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The DRM layer provides several services to graphics drivers,
|
||||||
|
many of them driven by the application interfaces it provides
|
||||||
|
through libdrm, the library that wraps most of the DRM ioctls.
|
||||||
|
These include vblank event handling, memory
|
||||||
|
management, output management, framebuffer management, command
|
||||||
|
submission & fencing, suspend/resume support, and DMA
|
||||||
|
services.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The core of every DRM driver is struct drm_device. Drivers
|
||||||
|
will typically statically initialize a drm_device structure,
|
||||||
|
then pass it to drm_init() at load time.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<!-- Internals: driver init -->
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Driver initialization</title>
|
||||||
|
<para>
|
||||||
|
Before calling the DRM initialization routines, the driver must
|
||||||
|
first create and fill out a struct drm_device structure.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
static struct drm_driver driver = {
|
||||||
|
/* don't use mtrr's here, the Xserver or user space app should
|
||||||
|
* deal with them for intel hardware.
|
||||||
|
*/
|
||||||
|
.driver_features =
|
||||||
|
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
|
||||||
|
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_MODESET,
|
||||||
|
.load = i915_driver_load,
|
||||||
|
.unload = i915_driver_unload,
|
||||||
|
.firstopen = i915_driver_firstopen,
|
||||||
|
.lastclose = i915_driver_lastclose,
|
||||||
|
.preclose = i915_driver_preclose,
|
||||||
|
.save = i915_save,
|
||||||
|
.restore = i915_restore,
|
||||||
|
.device_is_agp = i915_driver_device_is_agp,
|
||||||
|
.get_vblank_counter = i915_get_vblank_counter,
|
||||||
|
.enable_vblank = i915_enable_vblank,
|
||||||
|
.disable_vblank = i915_disable_vblank,
|
||||||
|
.irq_preinstall = i915_driver_irq_preinstall,
|
||||||
|
.irq_postinstall = i915_driver_irq_postinstall,
|
||||||
|
.irq_uninstall = i915_driver_irq_uninstall,
|
||||||
|
.irq_handler = i915_driver_irq_handler,
|
||||||
|
.reclaim_buffers = drm_core_reclaim_buffers,
|
||||||
|
.get_map_ofs = drm_core_get_map_ofs,
|
||||||
|
.get_reg_ofs = drm_core_get_reg_ofs,
|
||||||
|
.fb_probe = intelfb_probe,
|
||||||
|
.fb_remove = intelfb_remove,
|
||||||
|
.fb_resize = intelfb_resize,
|
||||||
|
.master_create = i915_master_create,
|
||||||
|
.master_destroy = i915_master_destroy,
|
||||||
|
#if defined(CONFIG_DEBUG_FS)
|
||||||
|
.debugfs_init = i915_debugfs_init,
|
||||||
|
.debugfs_cleanup = i915_debugfs_cleanup,
|
||||||
|
#endif
|
||||||
|
.gem_init_object = i915_gem_init_object,
|
||||||
|
.gem_free_object = i915_gem_free_object,
|
||||||
|
.gem_vm_ops = &i915_gem_vm_ops,
|
||||||
|
.ioctls = i915_ioctls,
|
||||||
|
.fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = drm_open,
|
||||||
|
.release = drm_release,
|
||||||
|
.ioctl = drm_ioctl,
|
||||||
|
.mmap = drm_mmap,
|
||||||
|
.poll = drm_poll,
|
||||||
|
.fasync = drm_fasync,
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
.compat_ioctl = i915_compat_ioctl,
|
||||||
|
#endif
|
||||||
|
},
|
||||||
|
.pci_driver = {
|
||||||
|
.name = DRIVER_NAME,
|
||||||
|
.id_table = pciidlist,
|
||||||
|
.probe = probe,
|
||||||
|
.remove = __devexit_p(drm_cleanup_pci),
|
||||||
|
},
|
||||||
|
.name = DRIVER_NAME,
|
||||||
|
.desc = DRIVER_DESC,
|
||||||
|
.date = DRIVER_DATE,
|
||||||
|
.major = DRIVER_MAJOR,
|
||||||
|
.minor = DRIVER_MINOR,
|
||||||
|
.patchlevel = DRIVER_PATCHLEVEL,
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
In the example above, taken from the i915 DRM driver, the driver
|
||||||
|
sets several flags indicating what core features it supports.
|
||||||
|
We'll go over the individual callbacks in later sections. Since
|
||||||
|
flags indicate which features your driver supports to the DRM
|
||||||
|
core, you need to set most of them prior to calling drm_init(). Some,
|
||||||
|
like DRIVER_MODESET can be set later based on user supplied parameters,
|
||||||
|
but that's the exception rather than the rule.
|
||||||
|
</para>
|
||||||
|
<variablelist>
|
||||||
|
<title>Driver flags</title>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_USE_AGP</term>
|
||||||
|
<listitem><para>
|
||||||
|
Driver uses AGP interface
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_REQUIRE_AGP</term>
|
||||||
|
<listitem><para>
|
||||||
|
Driver needs AGP interface to function.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_USE_MTRR</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Driver uses MTRR interface for mapping memory. Deprecated.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_PCI_DMA</term>
|
||||||
|
<listitem><para>
|
||||||
|
Driver is capable of PCI DMA. Deprecated.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_SG</term>
|
||||||
|
<listitem><para>
|
||||||
|
Driver can perform scatter/gather DMA. Deprecated.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_HAVE_DMA</term>
|
||||||
|
<listitem><para>Driver supports DMA. Deprecated.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
DRIVER_HAVE_IRQ indicates whether the driver has a IRQ
|
||||||
|
handler, DRIVER_IRQ_SHARED indicates whether the device &
|
||||||
|
handler support shared IRQs (note that this is required of
|
||||||
|
PCI drivers).
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_DMA_QUEUE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
If the driver queues DMA requests and completes them
|
||||||
|
asynchronously, this flag should be set. Deprecated.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_FB_DMA</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Driver supports DMA to/from the framebuffer. Deprecated.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>DRIVER_MODESET</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Driver supports mode setting interfaces.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
<para>
|
||||||
|
In this specific case, the driver requires AGP and supports
|
||||||
|
IRQs. DMA, as we'll see, is handled by device specific ioctls
|
||||||
|
in this case. It also supports the kernel mode setting APIs, though
|
||||||
|
unlike in the actual i915 driver source, this example unconditionally
|
||||||
|
exports KMS capability.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<!-- Internals: driver load -->
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Driver load</title>
|
||||||
|
<para>
|
||||||
|
In the previous section, we saw what a typical drm_driver
|
||||||
|
structure might look like. One of the more important fields in
|
||||||
|
the structure is the hook for the load function.
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
static struct drm_driver driver = {
|
||||||
|
...
|
||||||
|
.load = i915_driver_load,
|
||||||
|
...
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
The load function has many responsibilities: allocating a driver
|
||||||
|
private structure, specifying supported performance counters,
|
||||||
|
configuring the device (e.g. mapping registers & command
|
||||||
|
buffers), initializing the memory manager, and setting up the
|
||||||
|
initial output configuration.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note that the tasks performed at driver load time must not
|
||||||
|
conflict with DRM client requirements. For instance, if user
|
||||||
|
level mode setting drivers are in use, it would be problematic
|
||||||
|
to perform output discovery & configuration at load time.
|
||||||
|
Likewise, if pre-memory management aware user level drivers are
|
||||||
|
in use, memory management and command buffer setup may need to
|
||||||
|
be omitted. These requirements are driver specific, and care
|
||||||
|
needs to be taken to keep both old and new applications and
|
||||||
|
libraries working. The i915 driver supports the "modeset"
|
||||||
|
module parameter to control whether advanced features are
|
||||||
|
enabled at load time or in legacy fashion. If compatibility is
|
||||||
|
a concern (e.g. with drivers converted over to the new interfaces
|
||||||
|
from the old ones), care must be taken to prevent incompatible
|
||||||
|
device initialization and control with the currently active
|
||||||
|
userspace drivers.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Driver private & performance counters</title>
|
||||||
|
<para>
|
||||||
|
The driver private hangs off the main drm_device structure and
|
||||||
|
can be used for tracking various device specific bits of
|
||||||
|
information, like register offsets, command buffer status,
|
||||||
|
register state for suspend/resume, etc. At load time, a
|
||||||
|
driver can simply allocate one and set drm_device.dev_priv
|
||||||
|
appropriately; at unload the driver can free it and set
|
||||||
|
drm_device.dev_priv to NULL.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The DRM supports several counters which can be used for rough
|
||||||
|
performance characterization. Note that the DRM stat counter
|
||||||
|
system is not often used by applications, and supporting
|
||||||
|
additional counters is completely optional.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
These interfaces are deprecated and should not be used. If performance
|
||||||
|
monitoring is desired, the developer should investigate and
|
||||||
|
potentially enhance the kernel perf and tracing infrastructure to export
|
||||||
|
GPU related performance information to performance monitoring
|
||||||
|
tools and applications.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Configuring the device</title>
|
||||||
|
<para>
|
||||||
|
Obviously, device configuration will be device specific.
|
||||||
|
However, there are several common operations: finding a
|
||||||
|
device's PCI resources, mapping them, and potentially setting
|
||||||
|
up an IRQ handler.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Finding & mapping resources is fairly straightforward. The
|
||||||
|
DRM wrapper functions, drm_get_resource_start() and
|
||||||
|
drm_get_resource_len() can be used to find BARs on the given
|
||||||
|
drm_device struct. Once those values have been retrieved, the
|
||||||
|
driver load function can call drm_addmap() to create a new
|
||||||
|
mapping for the BAR in question. Note you'll probably want a
|
||||||
|
drm_local_map_t in your driver private structure to track any
|
||||||
|
mappings you create.
|
||||||
|
<!-- !Fdrivers/gpu/drm/drm_bufs.c drm_get_resource_* -->
|
||||||
|
<!-- !Finclude/drm/drmP.h drm_local_map_t -->
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
if compatibility with other operating systems isn't a concern
|
||||||
|
(DRM drivers can run under various BSD variants and OpenSolaris),
|
||||||
|
native Linux calls can be used for the above, e.g. pci_resource_*
|
||||||
|
and iomap*/iounmap. See the Linux device driver book for more
|
||||||
|
info.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Once you have a register map, you can use the DRM_READn() and
|
||||||
|
DRM_WRITEn() macros to access the registers on your device, or
|
||||||
|
use driver specific versions to offset into your MMIO space
|
||||||
|
relative to a driver specific base pointer (see I915_READ for
|
||||||
|
example).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If your device supports interrupt generation, you may want to
|
||||||
|
setup an interrupt handler at driver load time as well. This
|
||||||
|
is done using the drm_irq_install() function. If your device
|
||||||
|
supports vertical blank interrupts, it should call
|
||||||
|
drm_vblank_init() to initialize the core vblank handling code before
|
||||||
|
enabling interrupts on your device. This ensures the vblank related
|
||||||
|
structures are allocated and allows the core to handle vblank events.
|
||||||
|
</para>
|
||||||
|
<!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
|
||||||
|
<para>
|
||||||
|
Once your interrupt handler is registered (it'll use your
|
||||||
|
drm_driver.irq_handler as the actual interrupt handling
|
||||||
|
function), you can safely enable interrupts on your device,
|
||||||
|
assuming any other state your interrupt handler uses is also
|
||||||
|
initialized.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Another task that may be necessary during configuration is
|
||||||
|
mapping the video BIOS. On many devices, the VBIOS describes
|
||||||
|
device configuration, LCD panel timings (if any), and contains
|
||||||
|
flags indicating device state. Mapping the BIOS can be done
|
||||||
|
using the pci_map_rom() call, a convenience function that
|
||||||
|
takes care of mapping the actual ROM, whether it has been
|
||||||
|
shadowed into memory (typically at address 0xc0000) or exists
|
||||||
|
on the PCI device in the ROM BAR. Note that once you've
|
||||||
|
mapped the ROM and extracted any necessary information, be
|
||||||
|
sure to unmap it; on many devices the ROM address decoder is
|
||||||
|
shared with other BARs, so leaving it mapped can cause
|
||||||
|
undesired behavior like hangs or memory corruption.
|
||||||
|
<!--!Fdrivers/pci/rom.c pci_map_rom-->
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Memory manager initialization</title>
|
||||||
|
<para>
|
||||||
|
In order to allocate command buffers, cursor memory, scanout
|
||||||
|
buffers, etc., as well as support the latest features provided
|
||||||
|
by packages like Mesa and the X.Org X server, your driver
|
||||||
|
should support a memory manager.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If your driver supports memory management (it should!), you'll
|
||||||
|
need to set that up at load time as well. How you initialize
|
||||||
|
it depends on which memory manager you're using, TTM or GEM.
|
||||||
|
</para>
|
||||||
|
<sect3>
|
||||||
|
<title>TTM initialization</title>
|
||||||
|
<para>
|
||||||
|
TTM (for Translation Table Manager) manages video memory and
|
||||||
|
aperture space for graphics devices. TTM supports both UMA devices
|
||||||
|
and devices with dedicated video RAM (VRAM), i.e. most discrete
|
||||||
|
graphics devices. If your device has dedicated RAM, supporting
|
||||||
|
TTM is desirable. TTM also integrates tightly with your
|
||||||
|
driver specific buffer execution function. See the radeon
|
||||||
|
driver for examples.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The core TTM structure is the ttm_bo_driver struct. It contains
|
||||||
|
several fields with function pointers for initializing the TTM,
|
||||||
|
allocating and freeing memory, waiting for command completion
|
||||||
|
and fence synchronization, and memory migration. See the
|
||||||
|
radeon_ttm.c file for an example of usage.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The ttm_global_reference structure is made up of several fields:
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
struct ttm_global_reference {
|
||||||
|
enum ttm_global_types global_type;
|
||||||
|
size_t size;
|
||||||
|
void *object;
|
||||||
|
int (*init) (struct ttm_global_reference *);
|
||||||
|
void (*release) (struct ttm_global_reference *);
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
There should be one global reference structure for your memory
|
||||||
|
manager as a whole, and there will be others for each object
|
||||||
|
created by the memory manager at runtime. Your global TTM should
|
||||||
|
have a type of TTM_GLOBAL_TTM_MEM. The size field for the global
|
||||||
|
object should be sizeof(struct ttm_mem_global), and the init and
|
||||||
|
release hooks should point at your driver specific init and
|
||||||
|
release routines, which will probably eventually call
|
||||||
|
ttm_mem_global_init and ttm_mem_global_release respectively.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Once your global TTM accounting structure is set up and initialized
|
||||||
|
(done by calling ttm_global_item_ref on the global object you
|
||||||
|
just created), you'll need to create a buffer object TTM to
|
||||||
|
provide a pool for buffer object allocation by clients and the
|
||||||
|
kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO,
|
||||||
|
and its size should be sizeof(struct ttm_bo_global). Again,
|
||||||
|
driver specific init and release functions can be provided,
|
||||||
|
likely eventually calling ttm_bo_global_init and
|
||||||
|
ttm_bo_global_release, respectively. Also like the previous
|
||||||
|
object, ttm_global_item_ref is used to create an initial reference
|
||||||
|
count for the TTM, which will call your initialization function.
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
<sect3>
|
||||||
|
<title>GEM initialization</title>
|
||||||
|
<para>
|
||||||
|
GEM is an alternative to TTM, designed specifically for UMA
|
||||||
|
devices. It has simpler initialization and execution requirements
|
||||||
|
than TTM, but has no VRAM management capability. Core GEM
|
||||||
|
initialization is comprised of a basic drm_mm_init call to create
|
||||||
|
a GTT DRM MM object, which provides an address space pool for
|
||||||
|
object allocation. In a KMS configuration, the driver will
|
||||||
|
need to allocate and initialize a command ring buffer following
|
||||||
|
basic GEM initialization. Most UMA devices have a so-called
|
||||||
|
"stolen" memory region, which provides space for the initial
|
||||||
|
framebuffer and large, contiguous memory regions required by the
|
||||||
|
device. This space is not typically managed by GEM, and must
|
||||||
|
be initialized separately into its own DRM MM object.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Initialization will be driver specific, and will depend on
|
||||||
|
the architecture of the device. In the case of Intel
|
||||||
|
integrated graphics chips like 965GM, GEM initialization can
|
||||||
|
be done by calling the internal GEM init function,
|
||||||
|
i915_gem_do_init(). Since the 965GM is a UMA device
|
||||||
|
(i.e. it doesn't have dedicated VRAM), GEM will manage
|
||||||
|
making regular RAM available for GPU operations. Memory set
|
||||||
|
aside by the BIOS (called "stolen" memory by the i915
|
||||||
|
driver) will be managed by the DRM memrange allocator; the
|
||||||
|
rest of the aperture will be managed by GEM.
|
||||||
|
<programlisting>
|
||||||
|
/* Basic memrange allocator for stolen space (aka vram) */
|
||||||
|
drm_memrange_init(&dev_priv->vram, 0, prealloc_size);
|
||||||
|
/* Let GEM Manage from end of prealloc space to end of aperture */
|
||||||
|
i915_gem_do_init(dev, prealloc_size, agp_size);
|
||||||
|
</programlisting>
|
||||||
|
<!--!Edrivers/char/drm/drm_memrange.c-->
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Once the memory manager has been set up, we can allocate the
|
||||||
|
command buffer. In the i915 case, this is also done with a
|
||||||
|
GEM function, i915_gem_init_ringbuffer().
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>Output configuration</title>
|
||||||
|
<para>
|
||||||
|
The final initialization task is output configuration. This involves
|
||||||
|
finding and initializing the CRTCs, encoders and connectors
|
||||||
|
for your device, creating an initial configuration and
|
||||||
|
registering a framebuffer console driver.
|
||||||
|
</para>
|
||||||
|
<sect3>
|
||||||
|
<title>Output discovery and initialization</title>
|
||||||
|
<para>
|
||||||
|
Several core functions exist to create CRTCs, encoders and
|
||||||
|
connectors, namely drm_crtc_init(), drm_connector_init() and
|
||||||
|
drm_encoder_init(), along with several "helper" functions to
|
||||||
|
perform common tasks.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Connectors should be registered with sysfs once they've been
|
||||||
|
detected and initialized, using the
|
||||||
|
drm_sysfs_connector_add() function. Likewise, when they're
|
||||||
|
removed from the system, they should be destroyed with
|
||||||
|
drm_sysfs_connector_remove().
|
||||||
|
</para>
|
||||||
|
<programlisting>
|
||||||
|
<![CDATA[
|
||||||
|
void intel_crt_init(struct drm_device *dev)
|
||||||
|
{
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct intel_output *intel_output;
|
||||||
|
|
||||||
|
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
|
||||||
|
if (!intel_output)
|
||||||
|
return;
|
||||||
|
|
||||||
|
connector = &intel_output->base;
|
||||||
|
drm_connector_init(dev, &intel_output->base,
|
||||||
|
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
|
||||||
|
|
||||||
|
drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs,
|
||||||
|
DRM_MODE_ENCODER_DAC);
|
||||||
|
|
||||||
|
drm_mode_connector_attach_encoder(&intel_output->base,
|
||||||
|
&intel_output->enc);
|
||||||
|
|
||||||
|
/* Set up the DDC bus. */
|
||||||
|
intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
|
||||||
|
if (!intel_output->ddc_bus) {
|
||||||
|
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
|
||||||
|
"failed.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
intel_output->type = INTEL_OUTPUT_ANALOG;
|
||||||
|
connector->interlace_allowed = 0;
|
||||||
|
connector->doublescan_allowed = 0;
|
||||||
|
|
||||||
|
drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
|
||||||
|
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
|
||||||
|
|
||||||
|
drm_sysfs_connector_add(connector);
|
||||||
|
}
|
||||||
|
]]>
|
||||||
|
</programlisting>
|
||||||
|
<para>
|
||||||
|
In the example above (again, taken from the i915 driver), a
|
||||||
|
CRT connector and encoder combination is created. A device
|
||||||
|
specific i2c bus is also created, for fetching EDID data and
|
||||||
|
performing monitor detection. Once the process is complete,
|
||||||
|
the new connector is registered with sysfs, to make its
|
||||||
|
properties available to applications.
|
||||||
|
</para>
|
||||||
|
<sect4>
|
||||||
|
<title>Helper functions and core functions</title>
|
||||||
|
<para>
|
||||||
|
Since many PC-class graphics devices have similar display output
|
||||||
|
designs, the DRM provides a set of helper functions to make
|
||||||
|
output management easier. The core helper routines handle
|
||||||
|
encoder re-routing and disabling of unused functions following
|
||||||
|
mode set. Using the helpers is optional, but recommended for
|
||||||
|
devices with PC-style architectures (i.e. a set of display planes
|
||||||
|
for feeding pixels to encoders which are in turn routed to
|
||||||
|
connectors). Devices with more complex requirements needing
|
||||||
|
finer grained management can opt to use the core callbacks
|
||||||
|
directly.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
[Insert typical diagram here.] [Insert OMAP style config here.]
|
||||||
|
</para>
|
||||||
|
</sect4>
|
||||||
|
<para>
|
||||||
|
For each encoder, CRTC and connector, several functions must
|
||||||
|
be provided, depending on the object type. Encoder objects
|
||||||
|
need to provide a DPMS (basically on/off) function, mode fixup
|
||||||
|
(for converting requested modes into native hardware timings),
|
||||||
|
and prepare, set and commit functions for use by the core DRM
|
||||||
|
helper functions. Connector helpers need to provide mode fetch and
|
||||||
|
validity functions as well as an encoder matching function for
|
||||||
|
returning an ideal encoder for a given connector. The core
|
||||||
|
connector functions include a DPMS callback, (deprecated)
|
||||||
|
save/restore routines, detection, mode probing, property handling,
|
||||||
|
and cleanup functions.
|
||||||
|
</para>
|
||||||
|
<!--!Edrivers/char/drm/drm_crtc.h-->
|
||||||
|
<!--!Edrivers/char/drm/drm_crtc.c-->
|
||||||
|
<!--!Edrivers/char/drm/drm_crtc_helper.c-->
|
||||||
|
</sect3>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<!-- Internals: vblank handling -->
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>VBlank event handling</title>
|
||||||
|
<para>
|
||||||
|
The DRM core exposes two vertical blank related ioctls:
|
||||||
|
DRM_IOCTL_WAIT_VBLANK and DRM_IOCTL_MODESET_CTL.
|
||||||
|
<!--!Edrivers/char/drm/drm_irq.c-->
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
DRM_IOCTL_WAIT_VBLANK takes a struct drm_wait_vblank structure
|
||||||
|
as its argument, and is used to block or request a signal when a
|
||||||
|
specified vblank event occurs.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
DRM_IOCTL_MODESET_CTL should be called by application level
|
||||||
|
drivers before and after mode setting, since on many devices the
|
||||||
|
vertical blank counter will be reset at that time. Internally,
|
||||||
|
the DRM snapshots the last vblank count when the ioctl is called
|
||||||
|
with the _DRM_PRE_MODESET command so that the counter won't go
|
||||||
|
backwards (which is dealt with when _DRM_POST_MODESET is used).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
To support the functions above, the DRM core provides several
|
||||||
|
helper functions for tracking vertical blank counters, and
|
||||||
|
requires drivers to provide several callbacks:
|
||||||
|
get_vblank_counter(), enable_vblank() and disable_vblank(). The
|
||||||
|
core uses get_vblank_counter() to keep the counter accurate
|
||||||
|
across interrupt disable periods. It should return the current
|
||||||
|
vertical blank event count, which is often tracked in a device
|
||||||
|
register. The enable and disable vblank callbacks should enable
|
||||||
|
and disable vertical blank interrupts, respectively. In the
|
||||||
|
absence of DRM clients waiting on vblank events, the core DRM
|
||||||
|
code will use the disable_vblank() function to disable
|
||||||
|
interrupts, which saves power. They'll be re-enabled again when
|
||||||
|
a client calls the vblank wait ioctl above.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Devices that don't provide a count register can simply use an
|
||||||
|
internal atomic counter incremented on every vertical blank
|
||||||
|
interrupt, and can make their enable and disable vblank
|
||||||
|
functions into no-ops.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Memory management</title>
|
||||||
|
<para>
|
||||||
|
The memory manager lies at the heart of many DRM operations, and
|
||||||
|
is also required to support advanced client features like OpenGL
|
||||||
|
pbuffers. The DRM currently contains two memory managers, TTM
|
||||||
|
and GEM.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>The Translation Table Manager (TTM)</title>
|
||||||
|
<para>
|
||||||
|
TTM was developed by Tungsten Graphics, primarily by Thomas
|
||||||
|
Hellström, and is intended to be a flexible, high performance
|
||||||
|
graphics memory manager.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Drivers wishing to support TTM must fill out a drm_bo_driver
|
||||||
|
structure.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
TTM design background and information belongs here.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>The Graphics Execution Manager (GEM)</title>
|
||||||
|
<para>
|
||||||
|
GEM is an Intel project, authored by Eric Anholt and Keith
|
||||||
|
Packard. It provides simpler interfaces than TTM, and is well
|
||||||
|
suited for UMA devices.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
GEM-enabled drivers must provide gem_init_object() and
|
||||||
|
gem_free_object() callbacks to support the core memory
|
||||||
|
allocation routines. They should also provide several driver
|
||||||
|
specific ioctls to support command execution, pinning, buffer
|
||||||
|
read & write, mapping, and domain ownership transfers.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
On a fundamental level, GEM involves several operations: memory
|
||||||
|
allocation and freeing, command execution, and aperture management
|
||||||
|
at command execution time. Buffer object allocation is relatively
|
||||||
|
straightforward and largely provided by Linux's shmem layer, which
|
||||||
|
provides memory to back each object. When mapped into the GTT
|
||||||
|
or used in a command buffer, the backing pages for an object are
|
||||||
|
flushed to memory and marked write combined so as to be coherent
|
||||||
|
with the GPU. Likewise, when the GPU finishes rendering to an object,
|
||||||
|
if the CPU accesses it, it must be made coherent with the CPU's view
|
||||||
|
of memory, usually involving GPU cache flushing of various kinds.
|
||||||
|
This core CPU<->GPU coherency management is provided by the GEM
|
||||||
|
set domain function, which evaluates an object's current domain and
|
||||||
|
performs any necessary flushing or synchronization to put the object
|
||||||
|
into the desired coherency domain (note that the object may be busy,
|
||||||
|
i.e. an active render target; in that case the set domain function
|
||||||
|
will block the client and wait for rendering to complete before
|
||||||
|
performing any necessary flushing operations).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Perhaps the most important GEM function is providing a command
|
||||||
|
execution interface to clients. Client programs construct command
|
||||||
|
buffers containing references to previously allocated memory objects
|
||||||
|
and submit them to GEM. At that point, GEM will take care to bind
|
||||||
|
all the objects into the GTT, execute the buffer, and provide
|
||||||
|
necessary synchronization between clients accessing the same buffers.
|
||||||
|
This often involves evicting some objects from the GTT and re-binding
|
||||||
|
others (a fairly expensive operation), and providing relocation
|
||||||
|
support which hides fixed GTT offsets from clients. Clients must
|
||||||
|
take care not to submit command buffers that reference more objects
|
||||||
|
than can fit in the GTT or GEM will reject them and no rendering
|
||||||
|
will occur. Similarly, if several objects in the buffer require
|
||||||
|
fence registers to be allocated for correct rendering (e.g. 2D blits
|
||||||
|
on pre-965 chips), care must be taken not to require more fence
|
||||||
|
registers than are available to the client. Such resource management
|
||||||
|
should be abstracted from the client in libdrm.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<!-- Output management -->
|
||||||
|
<sect1>
|
||||||
|
<title>Output management</title>
|
||||||
|
<para>
|
||||||
|
At the core of the DRM output management code is a set of
|
||||||
|
structures representing CRTCs, encoders and connectors.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A CRTC is an abstraction representing a part of the chip that
|
||||||
|
contains a pointer to a scanout buffer. Therefore, the number
|
||||||
|
of CRTCs available determines how many independent scanout
|
||||||
|
buffers can be active at any given time. The CRTC structure
|
||||||
|
contains several fields to support this: a pointer to some video
|
||||||
|
memory, a display mode, and an (x, y) offset into the video
|
||||||
|
memory to support panning or configurations where one piece of
|
||||||
|
video memory spans multiple CRTCs.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
An encoder takes pixel data from a CRTC and converts it to a
|
||||||
|
format suitable for any attached connectors. On some devices,
|
||||||
|
it may be possible to have a CRTC send data to more than one
|
||||||
|
encoder. In that case, both encoders would receive data from
|
||||||
|
the same scanout buffer, resulting in a "cloned" display
|
||||||
|
configuration across the connectors attached to each encoder.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
A connector is the final destination for pixel data on a device,
|
||||||
|
and usually connects directly to an external display device like
|
||||||
|
a monitor or laptop panel. A connector can only be attached to
|
||||||
|
one encoder at a time. The connector is also the structure
|
||||||
|
where information about the attached display is kept, so it
|
||||||
|
contains fields for display data, EDID data, DPMS &
|
||||||
|
connection status, and information about modes supported on the
|
||||||
|
attached displays.
|
||||||
|
</para>
|
||||||
|
<!--!Edrivers/char/drm/drm_crtc.c-->
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Framebuffer management</title>
|
||||||
|
<para>
|
||||||
|
In order to set a mode on a given CRTC, encoder and connector
|
||||||
|
configuration, clients need to provide a framebuffer object which
|
||||||
|
will provide a source of pixels for the CRTC to deliver to the encoder(s)
|
||||||
|
and ultimately the connector(s) in the configuration. A framebuffer
|
||||||
|
is fundamentally a driver specific memory object, made into an opaque
|
||||||
|
handle by the DRM addfb function. Once an fb has been created this
|
||||||
|
way it can be passed to the KMS mode setting routines for use in
|
||||||
|
a configuration.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Command submission & fencing</title>
|
||||||
|
<para>
|
||||||
|
This should cover a few device specific command submission
|
||||||
|
implementations.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Suspend/resume</title>
|
||||||
|
<para>
|
||||||
|
The DRM core provides some suspend/resume code, but drivers
|
||||||
|
wanting full suspend/resume support should provide save() and
|
||||||
|
restore() functions. These will be called at suspend,
|
||||||
|
hibernate, or resume time, and should perform any state save or
|
||||||
|
restore required by your device across suspend or hibernate
|
||||||
|
states.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>DMA services</title>
|
||||||
|
<para>
|
||||||
|
This should cover how DMA mapping etc. is supported by the core.
|
||||||
|
These functions are deprecated and should not be used.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<!-- External interfaces -->
|
||||||
|
|
||||||
|
<chapter id="drmExternals">
|
||||||
|
<title>Userland interfaces</title>
|
||||||
|
<para>
|
||||||
|
The DRM core exports several interfaces to applications,
|
||||||
|
generally intended to be used through corresponding libdrm
|
||||||
|
wrapper functions. In addition, drivers export device specific
|
||||||
|
interfaces for use by userspace drivers & device aware
|
||||||
|
applications through ioctls and sysfs files.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
External interfaces include: memory mapping, context management,
|
||||||
|
DMA operations, AGP management, vblank control, fence
|
||||||
|
management, memory management, and output management.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Cover generic ioctls and sysfs layout here. Only need high
|
||||||
|
level info, since man pages will cover the rest.
|
||||||
|
</para>
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<!-- API reference -->
|
||||||
|
|
||||||
|
<appendix id="drmDriverApi">
|
||||||
|
<title>DRM Driver API</title>
|
||||||
|
<para>
|
||||||
|
Include auto-generated API reference here (need to reference it
|
||||||
|
from paragraphs above too).
|
||||||
|
</para>
|
||||||
|
</appendix>
|
||||||
|
|
||||||
|
</book>
|
@@ -12,10 +12,12 @@
|
|||||||
<othername role="mi">O. C.</othername>
|
<othername role="mi">O. C.</othername>
|
||||||
<affiliation><address><email>rjkm@metzlerbros.de</email></address></affiliation>
|
<affiliation><address><email>rjkm@metzlerbros.de</email></address></affiliation>
|
||||||
</author>
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
<authorgroup>
|
||||||
<author>
|
<author>
|
||||||
<firstname>Mauro</firstname>
|
<firstname>Mauro</firstname>
|
||||||
<surname>Chehab</surname>
|
|
||||||
<othername role="mi">Carvalho</othername>
|
<othername role="mi">Carvalho</othername>
|
||||||
|
<surname>Chehab</surname>
|
||||||
<affiliation><address><email>mchehab@redhat.com</email></address></affiliation>
|
<affiliation><address><email>mchehab@redhat.com</email></address></affiliation>
|
||||||
<contrib>Ported document to Docbook XML.</contrib>
|
<contrib>Ported document to Docbook XML.</contrib>
|
||||||
</author>
|
</author>
|
||||||
@@ -23,12 +25,23 @@
|
|||||||
<copyright>
|
<copyright>
|
||||||
<year>2002</year>
|
<year>2002</year>
|
||||||
<year>2003</year>
|
<year>2003</year>
|
||||||
<year>2009</year>
|
|
||||||
<holder>Convergence GmbH</holder>
|
<holder>Convergence GmbH</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
<copyright>
|
||||||
|
<year>2009-2010</year>
|
||||||
|
<holder>Mauro Carvalho Chehab</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
<revhistory>
|
<revhistory>
|
||||||
<!-- Put document revisions here, newest first. -->
|
<!-- Put document revisions here, newest first. -->
|
||||||
|
<revision>
|
||||||
|
<revnumber>2.0.3</revnumber>
|
||||||
|
<date>2010-07-03</date>
|
||||||
|
<authorinitials>mcc</authorinitials>
|
||||||
|
<revremark>
|
||||||
|
Add some frontend capabilities flags, present on kernel, but missing at the specs.
|
||||||
|
</revremark>
|
||||||
|
</revision>
|
||||||
<revision>
|
<revision>
|
||||||
<revnumber>2.0.2</revnumber>
|
<revnumber>2.0.2</revnumber>
|
||||||
<date>2009-10-25</date>
|
<date>2009-10-25</date>
|
||||||
@@ -63,7 +76,7 @@ Added ISDB-T test originally written by Patrick Boettcher
|
|||||||
|
|
||||||
|
|
||||||
<title>LINUX DVB API</title>
|
<title>LINUX DVB API</title>
|
||||||
<subtitle>Version 3</subtitle>
|
<subtitle>Version 5.2</subtitle>
|
||||||
<!-- ADD THE CHAPTERS HERE -->
|
<!-- ADD THE CHAPTERS HERE -->
|
||||||
<chapter id="dvb_introdution">
|
<chapter id="dvb_introdution">
|
||||||
&sub-intro;
|
&sub-intro;
|
||||||
|
@@ -63,6 +63,7 @@ typedef enum fe_caps {
|
|||||||
FE_CAN_8VSB = 0x200000,
|
FE_CAN_8VSB = 0x200000,
|
||||||
FE_CAN_16VSB = 0x400000,
|
FE_CAN_16VSB = 0x400000,
|
||||||
FE_HAS_EXTENDED_CAPS = 0x800000, /* We need more bitspace for newer APIs, indicate this. */
|
FE_HAS_EXTENDED_CAPS = 0x800000, /* We need more bitspace for newer APIs, indicate this. */
|
||||||
|
FE_CAN_TURBO_FEC = 0x8000000, /* frontend supports "turbo fec modulation" */
|
||||||
FE_CAN_2G_MODULATION = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
|
FE_CAN_2G_MODULATION = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
|
||||||
FE_NEEDS_BENDING = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
|
FE_NEEDS_BENDING = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
|
||||||
FE_CAN_RECOVER = 0x40000000, /* frontend can recover from a cable unplug automatically */
|
FE_CAN_RECOVER = 0x40000000, /* frontend can recover from a cable unplug automatically */
|
||||||
|
@@ -64,8 +64,14 @@ a specific frontend type.</para>
|
|||||||
FE_CAN_BANDWIDTH_AUTO = 0x40000,
|
FE_CAN_BANDWIDTH_AUTO = 0x40000,
|
||||||
FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
|
FE_CAN_GUARD_INTERVAL_AUTO = 0x80000,
|
||||||
FE_CAN_HIERARCHY_AUTO = 0x100000,
|
FE_CAN_HIERARCHY_AUTO = 0x100000,
|
||||||
FE_CAN_MUTE_TS = 0x80000000,
|
FE_CAN_8VSB = 0x200000,
|
||||||
FE_CAN_CLEAN_SETUP = 0x40000000
|
FE_CAN_16VSB = 0x400000,
|
||||||
|
FE_HAS_EXTENDED_CAPS = 0x800000,
|
||||||
|
FE_CAN_TURBO_FEC = 0x8000000,
|
||||||
|
FE_CAN_2G_MODULATION = 0x10000000,
|
||||||
|
FE_NEEDS_BENDING = 0x20000000,
|
||||||
|
FE_CAN_RECOVER = 0x40000000,
|
||||||
|
FE_CAN_MUTE_TS = 0x80000000
|
||||||
} fe_caps_t;
|
} fe_caps_t;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</section>
|
</section>
|
||||||
|
@@ -57,7 +57,6 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect1><title>String Conversions</title>
|
<sect1><title>String Conversions</title>
|
||||||
!Ilib/vsprintf.c
|
|
||||||
!Elib/vsprintf.c
|
!Elib/vsprintf.c
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1><title>String Manipulation</title>
|
<sect1><title>String Manipulation</title>
|
||||||
@@ -132,7 +131,6 @@ X!Ilib/string.c
|
|||||||
<title>FIFO Buffer</title>
|
<title>FIFO Buffer</title>
|
||||||
<sect1><title>kfifo interface</title>
|
<sect1><title>kfifo interface</title>
|
||||||
!Iinclude/linux/kfifo.h
|
!Iinclude/linux/kfifo.h
|
||||||
!Ekernel/kfifo.c
|
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
@@ -1922,9 +1922,12 @@ machines due to caching.
|
|||||||
<function>mutex_lock()</function>
|
<function>mutex_lock()</function>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
There is a <function>mutex_trylock()</function> which can be
|
There is a <function>mutex_trylock()</function> which does not
|
||||||
used inside interrupt context, as it will not sleep.
|
sleep. Still, it must not be used inside interrupt context since
|
||||||
|
its implementation is not safe for that.
|
||||||
<function>mutex_unlock()</function> will also never sleep.
|
<function>mutex_unlock()</function> will also never sleep.
|
||||||
|
It cannot be used in interrupt context either since a mutex
|
||||||
|
must be released by the same task that acquired it.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
@@ -1958,6 +1961,12 @@ machines due to caching.
|
|||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="apiref">
|
||||||
|
<title>Mutex API reference</title>
|
||||||
|
!Iinclude/linux/mutex.h
|
||||||
|
!Ekernel/mutex.c
|
||||||
|
</chapter>
|
||||||
|
|
||||||
<chapter id="references">
|
<chapter id="references">
|
||||||
<title>Further reading</title>
|
<title>Further reading</title>
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<book id="kgdbOnLinux">
|
<book id="kgdbOnLinux">
|
||||||
<bookinfo>
|
<bookinfo>
|
||||||
<title>Using kgdb and the kgdb Internals</title>
|
<title>Using kgdb, kdb and the kernel debugger internals</title>
|
||||||
|
|
||||||
<authorgroup>
|
<authorgroup>
|
||||||
<author>
|
<author>
|
||||||
@@ -17,33 +17,8 @@
|
|||||||
</affiliation>
|
</affiliation>
|
||||||
</author>
|
</author>
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
|
|
||||||
<authorgroup>
|
|
||||||
<author>
|
|
||||||
<firstname>Tom</firstname>
|
|
||||||
<surname>Rini</surname>
|
|
||||||
<affiliation>
|
|
||||||
<address>
|
|
||||||
<email>trini@kernel.crashing.org</email>
|
|
||||||
</address>
|
|
||||||
</affiliation>
|
|
||||||
</author>
|
|
||||||
</authorgroup>
|
|
||||||
|
|
||||||
<authorgroup>
|
|
||||||
<author>
|
|
||||||
<firstname>Amit S.</firstname>
|
|
||||||
<surname>Kale</surname>
|
|
||||||
<affiliation>
|
|
||||||
<address>
|
|
||||||
<email>amitkale@linsyssoft.com</email>
|
|
||||||
</address>
|
|
||||||
</affiliation>
|
|
||||||
</author>
|
|
||||||
</authorgroup>
|
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2008</year>
|
<year>2008,2010</year>
|
||||||
<holder>Wind River Systems, Inc.</holder>
|
<holder>Wind River Systems, Inc.</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
<copyright>
|
<copyright>
|
||||||
@@ -69,41 +44,76 @@
|
|||||||
<chapter id="Introduction">
|
<chapter id="Introduction">
|
||||||
<title>Introduction</title>
|
<title>Introduction</title>
|
||||||
<para>
|
<para>
|
||||||
kgdb is a source level debugger for linux kernel. It is used along
|
The kernel has two different debugger front ends (kdb and kgdb)
|
||||||
with gdb to debug a linux kernel. The expectation is that gdb can
|
which interface to the debug core. It is possible to use either
|
||||||
be used to "break in" to the kernel to inspect memory, variables
|
of the debugger front ends and dynamically transition between them
|
||||||
and look through call stack information similar to what an
|
if you configure the kernel properly at compile and runtime.
|
||||||
application developer would use gdb for. It is possible to place
|
|
||||||
breakpoints in kernel code and perform some limited execution
|
|
||||||
stepping.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Two machines are required for using kgdb. One of these machines is a
|
Kdb is simplistic shell-style interface which you can use on a
|
||||||
development machine and the other is a test machine. The kernel
|
system console with a keyboard or serial console. You can use it
|
||||||
to be debugged runs on the test machine. The development machine
|
to inspect memory, registers, process lists, dmesg, and even set
|
||||||
runs an instance of gdb against the vmlinux file which contains
|
breakpoints to stop in a certain location. Kdb is not a source
|
||||||
the symbols (not boot image such as bzImage, zImage, uImage...).
|
level debugger, although you can set breakpoints and execute some
|
||||||
In gdb the developer specifies the connection parameters and
|
basic kernel run control. Kdb is mainly aimed at doing some
|
||||||
connects to kgdb. The type of connection a developer makes with
|
analysis to aid in development or diagnosing kernel problems. You
|
||||||
gdb depends on the availability of kgdb I/O modules compiled as
|
can access some symbols by name in kernel built-ins or in kernel
|
||||||
builtin's or kernel modules in the test machine's kernel.
|
modules if the code was built
|
||||||
|
with <symbol>CONFIG_KALLSYMS</symbol>.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Kgdb is intended to be used as a source level debugger for the
|
||||||
|
Linux kernel. It is used along with gdb to debug a Linux kernel.
|
||||||
|
The expectation is that gdb can be used to "break in" to the
|
||||||
|
kernel to inspect memory, variables and look through call stack
|
||||||
|
information similar to the way an application developer would use
|
||||||
|
gdb to debug an application. It is possible to place breakpoints
|
||||||
|
in kernel code and perform some limited execution stepping.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Two machines are required for using kgdb. One of these machines is
|
||||||
|
a development machine and the other is the target machine. The
|
||||||
|
kernel to be debugged runs on the target machine. The development
|
||||||
|
machine runs an instance of gdb against the vmlinux file which
|
||||||
|
contains the symbols (not boot image such as bzImage, zImage,
|
||||||
|
uImage...). In gdb the developer specifies the connection
|
||||||
|
parameters and connects to kgdb. The type of connection a
|
||||||
|
developer makes with gdb depends on the availability of kgdb I/O
|
||||||
|
modules compiled as built-ins or loadable kernel modules in the test
|
||||||
|
machine's kernel.
|
||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="CompilingAKernel">
|
<chapter id="CompilingAKernel">
|
||||||
<title>Compiling a kernel</title>
|
<title>Compiling a kernel</title>
|
||||||
<para>
|
<para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>In order to enable compilation of kdb, you must first enable kgdb.</para></listitem>
|
||||||
|
<listitem><para>The kgdb test compile options are described in the kgdb test suite chapter.</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<sect1 id="CompileKGDB">
|
||||||
|
<title>Kernel config options for kgdb</title>
|
||||||
|
<para>
|
||||||
To enable <symbol>CONFIG_KGDB</symbol> you should first turn on
|
To enable <symbol>CONFIG_KGDB</symbol> you should first turn on
|
||||||
"Prompt for development and/or incomplete code/drivers"
|
"Prompt for development and/or incomplete code/drivers"
|
||||||
(CONFIG_EXPERIMENTAL) in "General setup", then under the
|
(CONFIG_EXPERIMENTAL) in "General setup", then under the
|
||||||
"Kernel debugging" select "KGDB: kernel debugging with remote gdb".
|
"Kernel debugging" select "KGDB: kernel debugger".
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
While it is not a hard requirement that you have symbols in your
|
||||||
|
vmlinux file, gdb tends not to be very useful without the symbolic
|
||||||
|
data, so you will want to turn
|
||||||
|
on <symbol>CONFIG_DEBUG_INFO</symbol> which is called "Compile the
|
||||||
|
kernel with debug info" in the config menu.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It is advised, but not required that you turn on the
|
It is advised, but not required that you turn on the
|
||||||
CONFIG_FRAME_POINTER kernel option. This option inserts code to
|
<symbol>CONFIG_FRAME_POINTER</symbol> kernel option which is called "Compile the
|
||||||
into the compiled executable which saves the frame information in
|
kernel with frame pointers" in the config menu. This option
|
||||||
registers or on the stack at different points which will allow a
|
inserts code to into the compiled executable which saves the frame
|
||||||
debugger such as gdb to more accurately construct stack back traces
|
information in registers or on the stack at different points which
|
||||||
while debugging the kernel.
|
allows a debugger such as gdb to more accurately construct
|
||||||
|
stack back traces while debugging the kernel.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If the architecture that you are using supports the kernel option
|
If the architecture that you are using supports the kernel option
|
||||||
@@ -116,38 +126,192 @@
|
|||||||
this option.
|
this option.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Next you should choose one of more I/O drivers to interconnect debugging
|
Next you should choose one of more I/O drivers to interconnect
|
||||||
host and debugged target. Early boot debugging requires a KGDB
|
debugging host and debugged target. Early boot debugging requires
|
||||||
I/O driver that supports early debugging and the driver must be
|
a KGDB I/O driver that supports early debugging and the driver
|
||||||
built into the kernel directly. Kgdb I/O driver configuration
|
must be built into the kernel directly. Kgdb I/O driver
|
||||||
takes place via kernel or module parameters, see following
|
configuration takes place via kernel or module parameters which
|
||||||
chapter.
|
you can learn more about in the in the section that describes the
|
||||||
|
parameter "kgdboc".
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>Here is an example set of .config symbols to enable or
|
||||||
The kgdb test compile options are described in the kgdb test suite chapter.
|
disable for kgdb:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para># CONFIG_DEBUG_RODATA is not set</para></listitem>
|
||||||
|
<listitem><para>CONFIG_FRAME_POINTER=y</para></listitem>
|
||||||
|
<listitem><para>CONFIG_KGDB=y</para></listitem>
|
||||||
|
<listitem><para>CONFIG_KGDB_SERIAL_CONSOLE=y</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="CompileKDB">
|
||||||
|
<title>Kernel config options for kdb</title>
|
||||||
|
<para>Kdb is quite a bit more complex than the simple gdbstub
|
||||||
|
sitting on top of the kernel's debug core. Kdb must implement a
|
||||||
|
shell, and also adds some helper functions in other parts of the
|
||||||
|
kernel, responsible for printing out interesting data such as what
|
||||||
|
you would see if you ran "lsmod", or "ps". In order to build kdb
|
||||||
|
into the kernel you follow the same steps as you would for kgdb.
|
||||||
|
</para>
|
||||||
|
<para>The main config option for kdb
|
||||||
|
is <symbol>CONFIG_KGDB_KDB</symbol> which is called "KGDB_KDB:
|
||||||
|
include kdb frontend for kgdb" in the config menu. In theory you
|
||||||
|
would have already also selected an I/O driver such as the
|
||||||
|
CONFIG_KGDB_SERIAL_CONSOLE interface if you plan on using kdb on a
|
||||||
|
serial port, when you were configuring kgdb.
|
||||||
|
</para>
|
||||||
|
<para>If you want to use a PS/2-style keyboard with kdb, you would
|
||||||
|
select CONFIG_KDB_KEYBOARD which is called "KGDB_KDB: keyboard as
|
||||||
|
input device" in the config menu. The CONFIG_KDB_KEYBOARD option
|
||||||
|
is not used for anything in the gdb interface to kgdb. The
|
||||||
|
CONFIG_KDB_KEYBOARD option only works with kdb.
|
||||||
|
</para>
|
||||||
|
<para>Here is an example set of .config symbols to enable/disable kdb:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para># CONFIG_DEBUG_RODATA is not set</para></listitem>
|
||||||
|
<listitem><para>CONFIG_FRAME_POINTER=y</para></listitem>
|
||||||
|
<listitem><para>CONFIG_KGDB=y</para></listitem>
|
||||||
|
<listitem><para>CONFIG_KGDB_SERIAL_CONSOLE=y</para></listitem>
|
||||||
|
<listitem><para>CONFIG_KGDB_KDB=y</para></listitem>
|
||||||
|
<listitem><para>CONFIG_KDB_KEYBOARD=y</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="EnableKGDB">
|
<chapter id="kgdbKernelArgs">
|
||||||
<title>Enable kgdb for debugging</title>
|
<title>Kernel Debugger Boot Arguments</title>
|
||||||
<para>
|
<para>This section describes the various runtime kernel
|
||||||
In order to use kgdb you must activate it by passing configuration
|
parameters that affect the configuration of the kernel debugger.
|
||||||
information to one of the kgdb I/O drivers. If you do not pass any
|
The following chapter covers using kdb and kgdb as well as
|
||||||
configuration information kgdb will not do anything at all. Kgdb
|
provides some examples of the configuration parameters.</para>
|
||||||
will only actively hook up to the kernel trap hooks if a kgdb I/O
|
<sect1 id="kgdboc">
|
||||||
driver is loaded and configured. If you unconfigure a kgdb I/O
|
<title>Kernel parameter: kgdboc</title>
|
||||||
driver, kgdb will unregister all the kernel hook points.
|
<para>The kgdboc driver was originally an abbreviation meant to
|
||||||
|
stand for "kgdb over console". Today it is the primary mechanism
|
||||||
|
to configure how to communicate from gdb to kgdb as well as the
|
||||||
|
devices you want to use to interact with the kdb shell.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>For kgdb/gdb, kgdboc is designed to work with a single serial
|
||||||
All drivers can be reconfigured at run time, if
|
port. It is intended to cover the circumstance where you want to
|
||||||
<symbol>CONFIG_SYSFS</symbol> and <symbol>CONFIG_MODULES</symbol>
|
use a serial console as your primary console as well as using it to
|
||||||
are enabled, by echo'ing a new config string to
|
perform kernel debugging. It is also possible to use kgdb on a
|
||||||
<constant>/sys/module/<driver>/parameter/<option></constant>.
|
serial port which is not designated as a system console. Kgdboc
|
||||||
The driver can be unconfigured by passing an empty string. You cannot
|
may be configured as a kernel built-in or a kernel loadable module.
|
||||||
change the configuration while the debugger is attached. Make sure
|
You can only make use of <constant>kgdbwait</constant> and early
|
||||||
to detach the debugger with the <constant>detach</constant> command
|
debugging if you build kgdboc into the kernel as a built-in.
|
||||||
prior to trying unconfigure a kgdb I/O driver.
|
<para>Optionally you can elect to activate kms (Kernel Mode
|
||||||
|
Setting) integration. When you use kms with kgdboc and you have a
|
||||||
|
video driver that has atomic mode setting hooks, it is possible to
|
||||||
|
enter the debugger on the graphics console. When the kernel
|
||||||
|
execution is resumed, the previous graphics mode will be restored.
|
||||||
|
This integration can serve as a useful tool to aid in diagnosing
|
||||||
|
crashes or doing analysis of memory with kdb while allowing the
|
||||||
|
full graphics console applications to run.
|
||||||
</para>
|
</para>
|
||||||
|
</para>
|
||||||
|
<sect2 id="kgdbocArgs">
|
||||||
|
<title>kgdboc arguments</title>
|
||||||
|
<para>Usage: <constant>kgdboc=[kms][[,]kbd][[,]serial_device][,baud]</constant></para>
|
||||||
|
<para>The order listed above must be observed if you use any of the
|
||||||
|
optional configurations together.
|
||||||
|
</para>
|
||||||
|
<para>Abbreviations:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>kms = Kernel Mode Setting</para></listitem>
|
||||||
|
<listitem><para>kbd = Keyboard</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
<para>You can configure kgdboc to use the keyboard, and or a serial
|
||||||
|
device depending on if you are using kdb and or kgdb, in one of the
|
||||||
|
following scenarios. The order listed above must be observed if
|
||||||
|
you use any of the optional configurations together. Using kms +
|
||||||
|
only gdb is generally not a useful combination.</para>
|
||||||
|
<sect3 id="kgdbocArgs1">
|
||||||
|
<title>Using loadable module or built-in</title>
|
||||||
|
<para>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>As a kernel built-in:</para>
|
||||||
|
<para>Use the kernel boot argument: <constant>kgdboc=<tty-device>,[baud]</constant></para></listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>As a kernel loadable module:</para>
|
||||||
|
<para>Use the command: <constant>modprobe kgdboc kgdboc=<tty-device>,[baud]</constant></para>
|
||||||
|
<para>Here are two examples of how you might format the kgdboc
|
||||||
|
string. The first is for an x86 target using the first serial port.
|
||||||
|
The second example is for the ARM Versatile AB using the second
|
||||||
|
serial port.
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para><constant>kgdboc=ttyS0,115200</constant></para></listitem>
|
||||||
|
<listitem><para><constant>kgdboc=ttyAMA1,115200</constant></para></listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist></para>
|
||||||
|
</sect3>
|
||||||
|
<sect3 id="kgdbocArgs2">
|
||||||
|
<title>Configure kgdboc at runtime with sysfs</title>
|
||||||
|
<para>At run time you can enable or disable kgdboc by echoing a
|
||||||
|
parameters into the sysfs. Here are two examples:</para>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>Enable kgdboc on ttyS0</para>
|
||||||
|
<para><constant>echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc</constant></para></listitem>
|
||||||
|
<listitem><para>Disable kgdboc</para>
|
||||||
|
<para><constant>echo "" > /sys/module/kgdboc/parameters/kgdboc</constant></para></listitem>
|
||||||
|
</orderedlist>
|
||||||
|
<para>NOTE: You do not need to specify the baud if you are
|
||||||
|
configuring the console on tty which is already configured or
|
||||||
|
open.</para>
|
||||||
|
</sect3>
|
||||||
|
<sect3 id="kgdbocArgs3">
|
||||||
|
<title>More examples</title>
|
||||||
|
<para>You can configure kgdboc to use the keyboard, and or a serial
|
||||||
|
device depending on if you are using kdb and or kgdb, in one of the
|
||||||
|
following scenarios.</para>
|
||||||
|
<para>You can configure kgdboc to use the keyboard, and or a serial device
|
||||||
|
depending on if you are using kdb and or kgdb, in one of the
|
||||||
|
following scenarios.
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>kdb and kgdb over only a serial port</para>
|
||||||
|
<para><constant>kgdboc=<serial_device>[,baud]</constant></para>
|
||||||
|
<para>Example: <constant>kgdboc=ttyS0,115200</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>kdb and kgdb with keyboard and a serial port</para>
|
||||||
|
<para><constant>kgdboc=kbd,<serial_device>[,baud]</constant></para>
|
||||||
|
<para>Example: <constant>kgdboc=kbd,ttyS0,115200</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>kdb with a keyboard</para>
|
||||||
|
<para><constant>kgdboc=kbd</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>kdb with kernel mode setting</para>
|
||||||
|
<para><constant>kgdboc=kms,kbd</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>kdb with kernel mode setting and kgdb over a serial port</para>
|
||||||
|
<para><constant>kgdboc=kms,kbd,ttyS0,115200</constant></para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
</sect3>
|
||||||
|
<para>NOTE: Kgdboc does not support interrupting the target via the
|
||||||
|
gdb remote protocol. You must manually send a sysrq-g unless you
|
||||||
|
have a proxy that splits console output to a terminal program.
|
||||||
|
A console proxy has a separate TCP port for the debugger and a separate
|
||||||
|
TCP port for the "human" console. The proxy can take care of sending
|
||||||
|
the sysrq-g for you.
|
||||||
|
</para>
|
||||||
|
<para>When using kgdboc with no debugger proxy, you can end up
|
||||||
|
connecting the debugger at one of two entry points. If an
|
||||||
|
exception occurs after you have loaded kgdboc, a message should
|
||||||
|
print on the console stating it is waiting for the debugger. In
|
||||||
|
this case you disconnect your terminal program and then connect the
|
||||||
|
debugger in its place. If you want to interrupt the target system
|
||||||
|
and forcibly enter a debug session you have to issue a Sysrq
|
||||||
|
sequence and then type the letter <constant>g</constant>. Then
|
||||||
|
you disconnect the terminal session and connect gdb. Your options
|
||||||
|
if you don't like this are to hack gdb to send the sysrq-g for you
|
||||||
|
as well as on the initial connect, or to use a debugger proxy that
|
||||||
|
allows an unmodified gdb to do the debugging.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
<sect1 id="kgdbwait">
|
<sect1 id="kgdbwait">
|
||||||
<title>Kernel parameter: kgdbwait</title>
|
<title>Kernel parameter: kgdbwait</title>
|
||||||
<para>
|
<para>
|
||||||
@@ -162,71 +326,25 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The kernel will stop and wait as early as the I/O driver and
|
The kernel will stop and wait as early as the I/O driver and
|
||||||
architecture will allow when you use this option. If you build the
|
architecture allows when you use this option. If you build the
|
||||||
kgdb I/O driver as a kernel module kgdbwait will not do anything.
|
kgdb I/O driver as a loadable kernel module kgdbwait will not do
|
||||||
|
anything.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1 id="kgdboc">
|
|
||||||
<title>Kernel parameter: kgdboc</title>
|
|
||||||
<para>
|
|
||||||
The kgdboc driver was originally an abbreviation meant to stand for
|
|
||||||
"kgdb over console". Kgdboc is designed to work with a single
|
|
||||||
serial port. It was meant to cover the circumstance
|
|
||||||
where you wanted to use a serial console as your primary console as
|
|
||||||
well as using it to perform kernel debugging. Of course you can
|
|
||||||
also use kgdboc without assigning a console to the same port.
|
|
||||||
</para>
|
|
||||||
<sect2 id="UsingKgdboc">
|
|
||||||
<title>Using kgdboc</title>
|
|
||||||
<para>
|
|
||||||
You can configure kgdboc via sysfs or a module or kernel boot line
|
|
||||||
parameter depending on if you build with CONFIG_KGDBOC as a module
|
|
||||||
or built-in.
|
|
||||||
<orderedlist>
|
|
||||||
<listitem><para>From the module load or build-in</para>
|
|
||||||
<para><constant>kgdboc=<tty-device>,[baud]</constant></para>
|
|
||||||
<para>
|
|
||||||
The example here would be if your console port was typically ttyS0, you would use something like <constant>kgdboc=ttyS0,115200</constant> or on the ARM Versatile AB you would likely use <constant>kgdboc=ttyAMA0,115200</constant>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem><para>From sysfs</para>
|
|
||||||
<para><constant>echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc</constant></para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
NOTE: Kgdboc does not support interrupting the target via the
|
|
||||||
gdb remote protocol. You must manually send a sysrq-g unless you
|
|
||||||
have a proxy that splits console output to a terminal problem and
|
|
||||||
has a separate port for the debugger to connect to that sends the
|
|
||||||
sysrq-g for you.
|
|
||||||
</para>
|
|
||||||
<para>When using kgdboc with no debugger proxy, you can end up
|
|
||||||
connecting the debugger for one of two entry points. If an
|
|
||||||
exception occurs after you have loaded kgdboc a message should print
|
|
||||||
on the console stating it is waiting for the debugger. In case you
|
|
||||||
disconnect your terminal program and then connect the debugger in
|
|
||||||
its place. If you want to interrupt the target system and forcibly
|
|
||||||
enter a debug session you have to issue a Sysrq sequence and then
|
|
||||||
type the letter <constant>g</constant>. Then you disconnect the
|
|
||||||
terminal session and connect gdb. Your options if you don't like
|
|
||||||
this are to hack gdb to send the sysrq-g for you as well as on the
|
|
||||||
initial connect, or to use a debugger proxy that allows an
|
|
||||||
unmodified gdb to do the debugging.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
<sect1 id="kgdbcon">
|
<sect1 id="kgdbcon">
|
||||||
<title>Kernel parameter: kgdbcon</title>
|
<title>Kernel parameter: kgdbcon</title>
|
||||||
<para>
|
<para> The kgdbcon feature allows you to see printk() messages
|
||||||
Kgdb supports using the gdb serial protocol to send console messages
|
inside gdb while gdb is connected to the kernel. Kdb does not make
|
||||||
to the debugger when the debugger is connected and running. There
|
use of the kgdbcon feature.
|
||||||
are two ways to activate this feature.
|
</para>
|
||||||
|
<para>Kgdb supports using the gdb serial protocol to send console
|
||||||
|
messages to the debugger when the debugger is connected and running.
|
||||||
|
There are two ways to activate this feature.
|
||||||
<orderedlist>
|
<orderedlist>
|
||||||
<listitem><para>Activate with the kernel command line option:</para>
|
<listitem><para>Activate with the kernel command line option:</para>
|
||||||
<para><constant>kgdbcon</constant></para>
|
<para><constant>kgdbcon</constant></para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem><para>Use sysfs before configuring an io driver</para>
|
<listitem><para>Use sysfs before configuring an I/O driver</para>
|
||||||
<para>
|
<para>
|
||||||
<constant>echo 1 > /sys/module/kgdb/parameters/kgdb_use_con</constant>
|
<constant>echo 1 > /sys/module/kgdb/parameters/kgdb_use_con</constant>
|
||||||
</para>
|
</para>
|
||||||
@@ -237,28 +355,175 @@
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
|
<para>IMPORTANT NOTE: You cannot use kgdboc + kgdbcon on a tty that is an
|
||||||
|
active system console. An example incorrect usage is <constant>console=ttyS0,115200 kgdboc=ttyS0 kgdbcon</constant>
|
||||||
|
</para>
|
||||||
|
<para>It is possible to use this option with kgdboc on a tty that is not a system console.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
IMPORTANT NOTE: Using this option with kgdb over the console
|
|
||||||
(kgdboc) is not supported.
|
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="ConnectingGDB">
|
<chapter id="usingKDB">
|
||||||
<title>Connecting gdb</title>
|
<title>Using kdb</title>
|
||||||
<para>
|
<para>
|
||||||
If you are using kgdboc, you need to have used kgdbwait as a boot
|
|
||||||
argument, issued a sysrq-g, or the system you are going to debug
|
|
||||||
has already taken an exception and is waiting for the debugger to
|
|
||||||
attach before you can connect gdb.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<sect1 id="quickKDBserial">
|
||||||
If you are not using different kgdb I/O driver other than kgdboc,
|
<title>Quick start for kdb on a serial port</title>
|
||||||
you should be able to connect and the target will automatically
|
<para>This is a quick example of how to use kdb.</para>
|
||||||
respond.
|
<para><orderedlist>
|
||||||
|
<listitem><para>Boot kernel with arguments:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><constant>console=ttyS0,115200 kgdboc=ttyS0,115200</constant></para></listitem>
|
||||||
|
</itemizedlist></para>
|
||||||
|
<para>OR</para>
|
||||||
|
<para>Configure kgdboc after the kernel booted; assuming you are using a serial port console:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><constant>echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc</constant></para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>Enter the kernel debugger manually or by waiting for an oops or fault. There are several ways you can enter the kernel debugger manually; all involve using the sysrq-g, which means you must have enabled CONFIG_MAGIC_SYSRQ=y in your kernel config.</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>When logged in as root or with a super user session you can run:</para>
|
||||||
|
<para><constant>echo g > /proc/sysrq-trigger</constant></para></listitem>
|
||||||
|
<listitem><para>Example using minicom 2.2</para>
|
||||||
|
<para>Press: <constant>Control-a</constant></para>
|
||||||
|
<para>Press: <constant>f</constant></para>
|
||||||
|
<para>Press: <constant>g</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>When you have telneted to a terminal server that supports sending a remote break</para>
|
||||||
|
<para>Press: <constant>Control-]</constant></para>
|
||||||
|
<para>Type in:<constant>send break</constant></para>
|
||||||
|
<para>Press: <constant>Enter</constant></para>
|
||||||
|
<para>Press: <constant>g</constant></para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>From the kdb prompt you can run the "help" command to see a complete list of the commands that are available.</para>
|
||||||
|
<para>Some useful commands in kdb include:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>lsmod -- Shows where kernel modules are loaded</para></listitem>
|
||||||
|
<listitem><para>ps -- Displays only the active processes</para></listitem>
|
||||||
|
<listitem><para>ps A -- Shows all the processes</para></listitem>
|
||||||
|
<listitem><para>summary -- Shows kernel version info and memory usage</para></listitem>
|
||||||
|
<listitem><para>bt -- Get a backtrace of the current process using dump_stack()</para></listitem>
|
||||||
|
<listitem><para>dmesg -- View the kernel syslog buffer</para></listitem>
|
||||||
|
<listitem><para>go -- Continue the system</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>When you are done using kdb you need to consider rebooting the
|
||||||
|
system or using the "go" command to resuming normal kernel
|
||||||
|
execution. If you have paused the kernel for a lengthy period of
|
||||||
|
time, applications that rely on timely networking or anything to do
|
||||||
|
with real wall clock time could be adversely affected, so you
|
||||||
|
should take this into consideration when using the kernel
|
||||||
|
debugger.</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist></para>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="quickKDBkeyboard">
|
||||||
|
<title>Quick start for kdb using a keyboard connected console</title>
|
||||||
|
<para>This is a quick example of how to use kdb with a keyboard.</para>
|
||||||
|
<para><orderedlist>
|
||||||
|
<listitem><para>Boot kernel with arguments:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><constant>kgdboc=kbd</constant></para></listitem>
|
||||||
|
</itemizedlist></para>
|
||||||
|
<para>OR</para>
|
||||||
|
<para>Configure kgdboc after the kernel booted:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><constant>echo kbd > /sys/module/kgdboc/parameters/kgdboc</constant></para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>Enter the kernel debugger manually or by waiting for an oops or fault. There are several ways you can enter the kernel debugger manually; all involve using the sysrq-g, which means you must have enabled CONFIG_MAGIC_SYSRQ=y in your kernel config.</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>When logged in as root or with a super user session you can run:</para>
|
||||||
|
<para><constant>echo g > /proc/sysrq-trigger</constant></para></listitem>
|
||||||
|
<listitem><para>Example using a laptop keyboard</para>
|
||||||
|
<para>Press and hold down: <constant>Alt</constant></para>
|
||||||
|
<para>Press and hold down: <constant>Fn</constant></para>
|
||||||
|
<para>Press and release the key with the label: <constant>SysRq</constant></para>
|
||||||
|
<para>Release: <constant>Fn</constant></para>
|
||||||
|
<para>Press and release: <constant>g</constant></para>
|
||||||
|
<para>Release: <constant>Alt</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>Example using a PS/2 101-key keyboard</para>
|
||||||
|
<para>Press and hold down: <constant>Alt</constant></para>
|
||||||
|
<para>Press and release the key with the label: <constant>SysRq</constant></para>
|
||||||
|
<para>Press and release: <constant>g</constant></para>
|
||||||
|
<para>Release: <constant>Alt</constant></para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Now type in a kdb command such as "help", "dmesg", "bt" or "go" to continue kernel execution.</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist></para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="EnableKGDB">
|
||||||
|
<title>Using kgdb / gdb</title>
|
||||||
|
<para>In order to use kgdb you must activate it by passing
|
||||||
|
configuration information to one of the kgdb I/O drivers. If you
|
||||||
|
do not pass any configuration information kgdb will not do anything
|
||||||
|
at all. Kgdb will only actively hook up to the kernel trap hooks
|
||||||
|
if a kgdb I/O driver is loaded and configured. If you unconfigure
|
||||||
|
a kgdb I/O driver, kgdb will unregister all the kernel hook points.
|
||||||
|
</para>
|
||||||
|
<para> All kgdb I/O drivers can be reconfigured at run time, if
|
||||||
|
<symbol>CONFIG_SYSFS</symbol> and <symbol>CONFIG_MODULES</symbol>
|
||||||
|
are enabled, by echo'ing a new config string to
|
||||||
|
<constant>/sys/module/<driver>/parameter/<option></constant>.
|
||||||
|
The driver can be unconfigured by passing an empty string. You cannot
|
||||||
|
change the configuration while the debugger is attached. Make sure
|
||||||
|
to detach the debugger with the <constant>detach</constant> command
|
||||||
|
prior to trying to unconfigure a kgdb I/O driver.
|
||||||
|
</para>
|
||||||
|
<sect1 id="ConnectingGDB">
|
||||||
|
<title>Connecting with gdb to a serial port</title>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>Configure kgdboc</para>
|
||||||
|
<para>Boot kernel with arguments:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><constant>kgdboc=ttyS0,115200</constant></para></listitem>
|
||||||
|
</itemizedlist></para>
|
||||||
|
<para>OR</para>
|
||||||
|
<para>Configure kgdboc after the kernel booted:
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para><constant>echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc</constant></para></listitem>
|
||||||
|
</itemizedlist></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Stop kernel execution (break into the debugger)</para>
|
||||||
|
<para>In order to connect to gdb via kgdboc, the kernel must
|
||||||
|
first be stopped. There are several ways to stop the kernel which
|
||||||
|
include using kgdbwait as a boot argument, via a sysrq-g, or running
|
||||||
|
the kernel until it takes an exception where it waits for the
|
||||||
|
debugger to attach.
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>When logged in as root or with a super user session you can run:</para>
|
||||||
|
<para><constant>echo g > /proc/sysrq-trigger</constant></para></listitem>
|
||||||
|
<listitem><para>Example using minicom 2.2</para>
|
||||||
|
<para>Press: <constant>Control-a</constant></para>
|
||||||
|
<para>Press: <constant>f</constant></para>
|
||||||
|
<para>Press: <constant>g</constant></para>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>When you have telneted to a terminal server that supports sending a remote break</para>
|
||||||
|
<para>Press: <constant>Control-]</constant></para>
|
||||||
|
<para>Type in:<constant>send break</constant></para>
|
||||||
|
<para>Press: <constant>Enter</constant></para>
|
||||||
|
<para>Press: <constant>g</constant></para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>Connect from from gdb</para>
|
||||||
<para>
|
<para>
|
||||||
Example (using a serial port):
|
Example (using a directly connected port):
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
% gdb ./vmlinux
|
% gdb ./vmlinux
|
||||||
@@ -266,7 +531,7 @@
|
|||||||
(gdb) target remote /dev/ttyS0
|
(gdb) target remote /dev/ttyS0
|
||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
Example (kgdb to a terminal server on tcp port 2012):
|
Example (kgdb to a terminal server on TCP port 2012):
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
% gdb ./vmlinux
|
% gdb ./vmlinux
|
||||||
@@ -283,6 +548,83 @@
|
|||||||
communications. You do this prior to issuing the <constant>target
|
communications. You do this prior to issuing the <constant>target
|
||||||
remote</constant> command by typing in: <constant>set debug remote 1</constant>
|
remote</constant> command by typing in: <constant>set debug remote 1</constant>
|
||||||
</para>
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
<para>Remember if you continue in gdb, and need to "break in" again,
|
||||||
|
you need to issue an other sysrq-g. It is easy to create a simple
|
||||||
|
entry point by putting a breakpoint at <constant>sys_sync</constant>
|
||||||
|
and then you can run "sync" from a shell or script to break into the
|
||||||
|
debugger.</para>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="switchKdbKgdb">
|
||||||
|
<title>kgdb and kdb interoperability</title>
|
||||||
|
<para>It is possible to transition between kdb and kgdb dynamically.
|
||||||
|
The debug core will remember which you used the last time and
|
||||||
|
automatically start in the same mode.</para>
|
||||||
|
<sect1>
|
||||||
|
<title>Switching between kdb and kgdb</title>
|
||||||
|
<sect2>
|
||||||
|
<title>Switching from kgdb to kdb</title>
|
||||||
|
<para>
|
||||||
|
There are two ways to switch from kgdb to kdb: you can use gdb to
|
||||||
|
issue a maintenance packet, or you can blindly type the command $3#33.
|
||||||
|
Whenever kernel debugger stops in kgdb mode it will print the
|
||||||
|
message <constant>KGDB or $3#33 for KDB</constant>. It is important
|
||||||
|
to note that you have to type the sequence correctly in one pass.
|
||||||
|
You cannot type a backspace or delete because kgdb will interpret
|
||||||
|
that as part of the debug stream.
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>Change from kgdb to kdb by blindly typing:</para>
|
||||||
|
<para><constant>$3#33</constant></para></listitem>
|
||||||
|
<listitem><para>Change from kgdb to kdb with gdb</para>
|
||||||
|
<para><constant>maintenance packet 3</constant></para>
|
||||||
|
<para>NOTE: Now you must kill gdb. Typically you press control-z and
|
||||||
|
issue the command: kill -9 %</para></listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
<sect2>
|
||||||
|
<title>Change from kdb to kgdb</title>
|
||||||
|
<para>There are two ways you can change from kdb to kgdb. You can
|
||||||
|
manually enter kgdb mode by issuing the kgdb command from the kdb
|
||||||
|
shell prompt, or you can connect gdb while the kdb shell prompt is
|
||||||
|
active. The kdb shell looks for the typical first commands that gdb
|
||||||
|
would issue with the gdb remote protocol and if it sees one of those
|
||||||
|
commands it automatically changes into kgdb mode.</para>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem><para>From kdb issue the command:</para>
|
||||||
|
<para><constant>kgdb</constant></para>
|
||||||
|
<para>Now disconnect your terminal program and connect gdb in its place</para></listitem>
|
||||||
|
<listitem><para>At the kdb prompt, disconnect the terminal program and connect gdb in its place.</para></listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
<sect1>
|
||||||
|
<title>Running kdb commands from gdb</title>
|
||||||
|
<para>It is possible to run a limited set of kdb commands from gdb,
|
||||||
|
using the gdb monitor command. You don't want to execute any of the
|
||||||
|
run control or breakpoint operations, because it can disrupt the
|
||||||
|
state of the kernel debugger. You should be using gdb for
|
||||||
|
breakpoints and run control operations if you have gdb connected.
|
||||||
|
The more useful commands to run are things like lsmod, dmesg, ps or
|
||||||
|
possibly some of the memory information commands. To see all the kdb
|
||||||
|
commands you can run <constant>monitor help</constant>.</para>
|
||||||
|
<para>Example:
|
||||||
|
<informalexample><programlisting>
|
||||||
|
(gdb) monitor ps
|
||||||
|
1 idle process (state I) and
|
||||||
|
27 sleeping system daemon (state M) processes suppressed,
|
||||||
|
use 'ps A' to see all.
|
||||||
|
Task Addr Pid Parent [*] cpu State Thread Command
|
||||||
|
|
||||||
|
0xc78291d0 1 0 0 0 S 0xc7829404 init
|
||||||
|
0xc7954150 942 1 0 0 S 0xc7954384 dropbear
|
||||||
|
0xc78789c0 944 1 0 0 S 0xc7878bf4 sh
|
||||||
|
(gdb)
|
||||||
|
</programlisting></informalexample>
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="KGDBTestSuite">
|
<chapter id="KGDBTestSuite">
|
||||||
<title>kgdb Test Suite</title>
|
<title>kgdb Test Suite</title>
|
||||||
@@ -309,34 +651,38 @@
|
|||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="CommonBackEndReq">
|
<chapter id="CommonBackEndReq">
|
||||||
<title>KGDB Internals</title>
|
<title>Kernel Debugger Internals</title>
|
||||||
<sect1 id="kgdbArchitecture">
|
<sect1 id="kgdbArchitecture">
|
||||||
<title>Architecture Specifics</title>
|
<title>Architecture Specifics</title>
|
||||||
<para>
|
<para>
|
||||||
Kgdb is organized into three basic components:
|
The kernel debugger is organized into a number of components:
|
||||||
<orderedlist>
|
<orderedlist>
|
||||||
<listitem><para>kgdb core</para>
|
<listitem><para>The debug core</para>
|
||||||
<para>
|
<para>
|
||||||
The kgdb core is found in kernel/kgdb.c. It contains:
|
The debug core is found in kernel/debugger/debug_core.c. It contains:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>All the logic to implement the gdb serial protocol</para></listitem>
|
<listitem><para>A generic OS exception handler which includes
|
||||||
<listitem><para>A generic OS exception handler which includes sync'ing the processors into a stopped state on an multi cpu system.</para></listitem>
|
sync'ing the processors into a stopped state on an multi-CPU
|
||||||
|
system.</para></listitem>
|
||||||
<listitem><para>The API to talk to the kgdb I/O drivers</para></listitem>
|
<listitem><para>The API to talk to the kgdb I/O drivers</para></listitem>
|
||||||
<listitem><para>The API to make calls to the arch specific kgdb implementation</para></listitem>
|
<listitem><para>The API to make calls to the arch-specific kgdb implementation</para></listitem>
|
||||||
<listitem><para>The logic to perform safe memory reads and writes to memory while using the debugger</para></listitem>
|
<listitem><para>The logic to perform safe memory reads and writes to memory while using the debugger</para></listitem>
|
||||||
<listitem><para>A full implementation for software breakpoints unless overridden by the arch</para></listitem>
|
<listitem><para>A full implementation for software breakpoints unless overridden by the arch</para></listitem>
|
||||||
|
<listitem><para>The API to invoke either the kdb or kgdb frontend to the debug core.</para></listitem>
|
||||||
|
<listitem><para>The structures and callback API for atomic kernel mode setting.</para>
|
||||||
|
<para>NOTE: kgdboc is where the kms callbacks are invoked.</para></listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem><para>kgdb arch specific implementation</para>
|
<listitem><para>kgdb arch-specific implementation</para>
|
||||||
<para>
|
<para>
|
||||||
This implementation is generally found in arch/*/kernel/kgdb.c.
|
This implementation is generally found in arch/*/kernel/kgdb.c.
|
||||||
As an example, arch/x86/kernel/kgdb.c contains the specifics to
|
As an example, arch/x86/kernel/kgdb.c contains the specifics to
|
||||||
implement HW breakpoint as well as the initialization to
|
implement HW breakpoint as well as the initialization to
|
||||||
dynamically register and unregister for the trap handlers on
|
dynamically register and unregister for the trap handlers on
|
||||||
this architecture. The arch specific portion implements:
|
this architecture. The arch-specific portion implements:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>contains an arch specific trap catcher which
|
<listitem><para>contains an arch-specific trap catcher which
|
||||||
invokes kgdb_handle_exception() to start kgdb about doing its
|
invokes kgdb_handle_exception() to start kgdb about doing its
|
||||||
work</para></listitem>
|
work</para></listitem>
|
||||||
<listitem><para>translation to and from gdb specific packet format to pt_regs</para></listitem>
|
<listitem><para>translation to and from gdb specific packet format to pt_regs</para></listitem>
|
||||||
@@ -347,11 +693,35 @@
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem><para>gdbstub frontend (aka kgdb)</para>
|
||||||
|
<para>The gdbstub is located in kernel/debug/gdbstub.c. It contains:</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>All the logic to implement the gdb serial protocol</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</listitem>
|
||||||
|
<listitem><para>kdb frontend</para>
|
||||||
|
<para>The kdb debugger shell is broken down into a number of
|
||||||
|
components. The kdb core is located in kernel/debug/kdb. There
|
||||||
|
are a number of helper functions in some of the other kernel
|
||||||
|
components to make it possible for kdb to examine and report
|
||||||
|
information about the kernel without taking locks that could
|
||||||
|
cause a kernel deadlock. The kdb core contains implements the following functionality.</para>
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>A simple shell</para></listitem>
|
||||||
|
<listitem><para>The kdb core command set</para></listitem>
|
||||||
|
<listitem><para>A registration API to register additional kdb shell commands.</para>
|
||||||
|
<para>A good example of a self-contained kdb module is the "ftdump" command for dumping the ftrace buffer. See: kernel/trace/trace_kdb.c</para></listitem>
|
||||||
|
<listitem><para>The implementation for kdb_printf() which
|
||||||
|
emits messages directly to I/O drivers, bypassing the kernel
|
||||||
|
log.</para></listitem>
|
||||||
|
<listitem><para>SW / HW breakpoint management for the kdb shell</para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
</listitem>
|
||||||
<listitem><para>kgdb I/O driver</para>
|
<listitem><para>kgdb I/O driver</para>
|
||||||
<para>
|
<para>
|
||||||
Each kgdb I/O driver has to provide an implemenation for the following:
|
Each kgdb I/O driver has to provide an implementation for the following:
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>configuration via builtin or module</para></listitem>
|
<listitem><para>configuration via built-in or module</para></listitem>
|
||||||
<listitem><para>dynamic configuration and kgdb hook registration calls</para></listitem>
|
<listitem><para>dynamic configuration and kgdb hook registration calls</para></listitem>
|
||||||
<listitem><para>read and write character interface</para></listitem>
|
<listitem><para>read and write character interface</para></listitem>
|
||||||
<listitem><para>A cleanup handler for unconfiguring from the kgdb core</para></listitem>
|
<listitem><para>A cleanup handler for unconfiguring from the kgdb core</para></listitem>
|
||||||
@@ -411,20 +781,19 @@
|
|||||||
</sect1>
|
</sect1>
|
||||||
<sect1 id="kgdbocDesign">
|
<sect1 id="kgdbocDesign">
|
||||||
<title>kgdboc internals</title>
|
<title>kgdboc internals</title>
|
||||||
|
<sect2>
|
||||||
|
<title>kgdboc and uarts</title>
|
||||||
<para>
|
<para>
|
||||||
The kgdboc driver is actually a very thin driver that relies on the
|
The kgdboc driver is actually a very thin driver that relies on the
|
||||||
underlying low level to the hardware driver having "polling hooks"
|
underlying low level to the hardware driver having "polling hooks"
|
||||||
which the to which the tty driver is attached. In the initial
|
which the to which the tty driver is attached. In the initial
|
||||||
implementation of kgdboc it the serial_core was changed to expose a
|
implementation of kgdboc it the serial_core was changed to expose a
|
||||||
low level uart hook for doing polled mode reading and writing of a
|
low level UART hook for doing polled mode reading and writing of a
|
||||||
single character while in an atomic context. When kgdb makes an I/O
|
single character while in an atomic context. When kgdb makes an I/O
|
||||||
request to the debugger, kgdboc invokes a call back in the serial
|
request to the debugger, kgdboc invokes a callback in the serial
|
||||||
core which in turn uses the call back in the uart driver. It is
|
core which in turn uses the callback in the UART driver.</para>
|
||||||
certainly possible to extend kgdboc to work with non-uart based
|
|
||||||
consoles in the future.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
When using kgdboc with a uart, the uart driver must implement two callbacks in the <constant>struct uart_ops</constant>. Example from drivers/8250.c:<programlisting>
|
When using kgdboc with a UART, the UART driver must implement two callbacks in the <constant>struct uart_ops</constant>. Example from drivers/8250.c:<programlisting>
|
||||||
#ifdef CONFIG_CONSOLE_POLL
|
#ifdef CONFIG_CONSOLE_POLL
|
||||||
.poll_get_char = serial8250_get_poll_char,
|
.poll_get_char = serial8250_get_poll_char,
|
||||||
.poll_put_char = serial8250_put_poll_char,
|
.poll_put_char = serial8250_put_poll_char,
|
||||||
@@ -434,11 +803,70 @@
|
|||||||
<constant>#ifdef CONFIG_CONSOLE_POLL</constant>, as shown above.
|
<constant>#ifdef CONFIG_CONSOLE_POLL</constant>, as shown above.
|
||||||
Keep in mind that polling hooks have to be implemented in such a way
|
Keep in mind that polling hooks have to be implemented in such a way
|
||||||
that they can be called from an atomic context and have to restore
|
that they can be called from an atomic context and have to restore
|
||||||
the state of the uart chip on return such that the system can return
|
the state of the UART chip on return such that the system can return
|
||||||
to normal when the debugger detaches. You need to be very careful
|
to normal when the debugger detaches. You need to be very careful
|
||||||
with any kind of lock you consider, because failing here is most
|
with any kind of lock you consider, because failing here is most likely
|
||||||
going to mean pressing the reset button.
|
going to mean pressing the reset button.
|
||||||
</para>
|
</para>
|
||||||
|
</sect2>
|
||||||
|
<sect2 id="kgdbocKbd">
|
||||||
|
<title>kgdboc and keyboards</title>
|
||||||
|
<para>The kgdboc driver contains logic to configure communications
|
||||||
|
with an attached keyboard. The keyboard infrastructure is only
|
||||||
|
compiled into the kernel when CONFIG_KDB_KEYBOARD=y is set in the
|
||||||
|
kernel configuration.</para>
|
||||||
|
<para>The core polled keyboard driver driver for PS/2 type keyboards
|
||||||
|
is in drivers/char/kdb_keyboard.c. This driver is hooked into the
|
||||||
|
debug core when kgdboc populates the callback in the array
|
||||||
|
called <constant>kdb_poll_funcs[]</constant>. The
|
||||||
|
kdb_get_kbd_char() is the top-level function which polls hardware
|
||||||
|
for single character input.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
<sect2 id="kgdbocKms">
|
||||||
|
<title>kgdboc and kms</title>
|
||||||
|
<para>The kgdboc driver contains logic to request the graphics
|
||||||
|
display to switch to a text context when you are using
|
||||||
|
"kgdboc=kms,kbd", provided that you have a video driver which has a
|
||||||
|
frame buffer console and atomic kernel mode setting support.</para>
|
||||||
|
<para>
|
||||||
|
Every time the kernel
|
||||||
|
debugger is entered it calls kgdboc_pre_exp_handler() which in turn
|
||||||
|
calls con_debug_enter() in the virtual console layer. On resuming kernel
|
||||||
|
execution, the kernel debugger calls kgdboc_post_exp_handler() which
|
||||||
|
in turn calls con_debug_leave().</para>
|
||||||
|
<para>Any video driver that wants to be compatible with the kernel
|
||||||
|
debugger and the atomic kms callbacks must implement the
|
||||||
|
mode_set_base_atomic, fb_debug_enter and fb_debug_leave operations.
|
||||||
|
For the fb_debug_enter and fb_debug_leave the option exists to use
|
||||||
|
the generic drm fb helper functions or implement something custom for
|
||||||
|
the hardware. The following example shows the initialization of the
|
||||||
|
.mode_set_base_atomic operation in
|
||||||
|
drivers/gpu/drm/i915/intel_display.c:
|
||||||
|
<informalexample>
|
||||||
|
<programlisting>
|
||||||
|
static const struct drm_crtc_helper_funcs intel_helper_funcs = {
|
||||||
|
[...]
|
||||||
|
.mode_set_base_atomic = intel_pipe_set_base_atomic,
|
||||||
|
[...]
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
</informalexample>
|
||||||
|
</para>
|
||||||
|
<para>Here is an example of how the i915 driver initializes the fb_debug_enter and fb_debug_leave functions to use the generic drm helpers in
|
||||||
|
drivers/gpu/drm/i915/intel_fb.c:
|
||||||
|
<informalexample>
|
||||||
|
<programlisting>
|
||||||
|
static struct fb_ops intelfb_ops = {
|
||||||
|
[...]
|
||||||
|
.fb_debug_enter = drm_fb_helper_debug_enter,
|
||||||
|
.fb_debug_leave = drm_fb_helper_debug_leave,
|
||||||
|
[...]
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
</informalexample>
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="credits">
|
<chapter id="credits">
|
||||||
@@ -453,6 +881,10 @@
|
|||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><para>Jason Wessel<email>jason.wessel@windriver.com</email></para></listitem>
|
<listitem><para>Jason Wessel<email>jason.wessel@windriver.com</email></para></listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
In Jan 2010 this document was updated to include kdb.
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem><para>Jason Wessel<email>jason.wessel@windriver.com</email></para></listitem>
|
||||||
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
</book>
|
</book>
|
||||||
|
@@ -81,16 +81,14 @@ void (*port_disable) (struct ata_port *);
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Called from ata_bus_probe() and ata_bus_reset() error paths,
|
Called from ata_bus_probe() error path, as well as when
|
||||||
as well as when unregistering from the SCSI module (rmmod, hot
|
unregistering from the SCSI module (rmmod, hot unplug).
|
||||||
unplug).
|
|
||||||
This function should do whatever needs to be done to take the
|
This function should do whatever needs to be done to take the
|
||||||
port out of use. In most cases, ata_port_disable() can be used
|
port out of use. In most cases, ata_port_disable() can be used
|
||||||
as this hook.
|
as this hook.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Called from ata_bus_probe() on a failed probe.
|
Called from ata_bus_probe() on a failed probe.
|
||||||
Called from ata_bus_reset() on a failed bus reset.
|
|
||||||
Called from ata_scsi_release().
|
Called from ata_scsi_release().
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -107,10 +105,6 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
|
|||||||
issue of SET FEATURES - XFER MODE, and prior to operation.
|
issue of SET FEATURES - XFER MODE, and prior to operation.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Called by ata_device_add() after ata_dev_identify() determines
|
|
||||||
a device is present.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This entry may be specified as NULL in ata_port_operations.
|
This entry may be specified as NULL in ata_port_operations.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -154,8 +148,8 @@ unsigned int (*mode_filter) (struct ata_port *, struct ata_device *, unsigned in
|
|||||||
|
|
||||||
<sect2><title>Taskfile read/write</title>
|
<sect2><title>Taskfile read/write</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
void (*sff_tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
|
void (*sff_tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -164,36 +158,35 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
|
|||||||
hardware registers / DMA buffers, to obtain the current set of
|
hardware registers / DMA buffers, to obtain the current set of
|
||||||
taskfile register values.
|
taskfile register values.
|
||||||
Most drivers for taskfile-based hardware (PIO or MMIO) use
|
Most drivers for taskfile-based hardware (PIO or MMIO) use
|
||||||
ata_tf_load() and ata_tf_read() for these hooks.
|
ata_sff_tf_load() and ata_sff_tf_read() for these hooks.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2><title>PIO data read/write</title>
|
<sect2><title>PIO data read/write</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
|
void (*sff_data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
All bmdma-style drivers must implement this hook. This is the low-level
|
All bmdma-style drivers must implement this hook. This is the low-level
|
||||||
operation that actually copies the data bytes during a PIO data
|
operation that actually copies the data bytes during a PIO data
|
||||||
transfer.
|
transfer.
|
||||||
Typically the driver
|
Typically the driver will choose one of ata_sff_data_xfer_noirq(),
|
||||||
will choose one of ata_pio_data_xfer_noirq(), ata_pio_data_xfer(), or
|
ata_sff_data_xfer(), or ata_sff_data_xfer32().
|
||||||
ata_mmio_data_xfer().
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2><title>ATA command execute</title>
|
<sect2><title>ATA command execute</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
void (*sff_exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
causes an ATA command, previously loaded with
|
causes an ATA command, previously loaded with
|
||||||
->tf_load(), to be initiated in hardware.
|
->tf_load(), to be initiated in hardware.
|
||||||
Most drivers for taskfile-based hardware use ata_exec_command()
|
Most drivers for taskfile-based hardware use ata_sff_exec_command()
|
||||||
for this hook.
|
for this hook.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -218,8 +211,8 @@ command.
|
|||||||
|
|
||||||
<sect2><title>Read specific ATA shadow registers</title>
|
<sect2><title>Read specific ATA shadow registers</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
u8 (*check_status)(struct ata_port *ap);
|
u8 (*sff_check_status)(struct ata_port *ap);
|
||||||
u8 (*check_altstatus)(struct ata_port *ap);
|
u8 (*sff_check_altstatus)(struct ata_port *ap);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -227,20 +220,26 @@ u8 (*check_altstatus)(struct ata_port *ap);
|
|||||||
hardware. On some hardware, reading the Status register has
|
hardware. On some hardware, reading the Status register has
|
||||||
the side effect of clearing the interrupt condition.
|
the side effect of clearing the interrupt condition.
|
||||||
Most drivers for taskfile-based hardware use
|
Most drivers for taskfile-based hardware use
|
||||||
ata_check_status() for this hook.
|
ata_sff_check_status() for this hook.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Write specific ATA shadow register</title>
|
||||||
|
<programlisting>
|
||||||
|
void (*sff_set_devctl)(struct ata_port *ap, u8 ctl);
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Note that because this is called from ata_device_add(), at
|
Write the device control ATA shadow register to the hardware.
|
||||||
least a dummy function that clears device interrupts must be
|
Most drivers don't need to define this.
|
||||||
provided for all drivers, even if the controller doesn't
|
|
||||||
actually have a taskfile status register.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2><title>Select ATA device on bus</title>
|
<sect2><title>Select ATA device on bus</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
void (*sff_dev_select)(struct ata_port *ap, unsigned int device);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -251,9 +250,7 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Most drivers for taskfile-based hardware use
|
Most drivers for taskfile-based hardware use
|
||||||
ata_std_dev_select() for this hook. Controllers which do not
|
ata_sff_dev_select() for this hook.
|
||||||
support second drives on a port (such as SATA contollers) will
|
|
||||||
use ata_noop_dev_select().
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
@@ -441,13 +438,13 @@ void (*irq_clear) (struct ata_port *);
|
|||||||
to struct ata_host_set.
|
to struct ata_host_set.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Most legacy IDE drivers use ata_interrupt() for the
|
Most legacy IDE drivers use ata_sff_interrupt() for the
|
||||||
irq_handler hook, which scans all ports in the host_set,
|
irq_handler hook, which scans all ports in the host_set,
|
||||||
determines which queued command was active (if any), and calls
|
determines which queued command was active (if any), and calls
|
||||||
ata_host_intr(ap,qc).
|
ata_sff_host_intr(ap,qc).
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Most legacy IDE drivers use ata_bmdma_irq_clear() for the
|
Most legacy IDE drivers use ata_sff_irq_clear() for the
|
||||||
irq_clear() hook, which simply clears the interrupt and error
|
irq_clear() hook, which simply clears the interrupt and error
|
||||||
flags in the DMA status register.
|
flags in the DMA status register.
|
||||||
</para>
|
</para>
|
||||||
@@ -490,16 +487,12 @@ void (*host_stop) (struct ata_host_set *host_set);
|
|||||||
allocates space for a legacy IDE PRD table and returns.
|
allocates space for a legacy IDE PRD table and returns.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
->port_stop() is called after ->host_stop(). It's sole function
|
->port_stop() is called after ->host_stop(). Its sole function
|
||||||
is to release DMA/memory resources, now that they are no longer
|
is to release DMA/memory resources, now that they are no longer
|
||||||
actively being used. Many drivers also free driver-private
|
actively being used. Many drivers also free driver-private
|
||||||
data from port at this time.
|
data from port at this time.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Many drivers use ata_port_stop() as this hook, which frees the
|
|
||||||
PRD table.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
->host_stop() is called after all ->port_stop() calls
|
->host_stop() is called after all ->port_stop() calls
|
||||||
have completed. The hook must finalize hardware shutdown, release DMA
|
have completed. The hook must finalize hardware shutdown, release DMA
|
||||||
and other resources, etc.
|
and other resources, etc.
|
||||||
|
@@ -144,7 +144,7 @@ usage should require reading the full document.
|
|||||||
this though and the recommendation to allow only a single
|
this though and the recommendation to allow only a single
|
||||||
interface in STA mode at first!
|
interface in STA mode at first!
|
||||||
</para>
|
</para>
|
||||||
!Finclude/net/mac80211.h ieee80211_if_init_conf
|
!Finclude/net/mac80211.h ieee80211_vif
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="rx-tx">
|
<chapter id="rx-tx">
|
||||||
@@ -234,7 +234,6 @@ usage should require reading the full document.
|
|||||||
<title>Multiple queues and QoS support</title>
|
<title>Multiple queues and QoS support</title>
|
||||||
<para>TBD</para>
|
<para>TBD</para>
|
||||||
!Finclude/net/mac80211.h ieee80211_tx_queue_params
|
!Finclude/net/mac80211.h ieee80211_tx_queue_params
|
||||||
!Finclude/net/mac80211.h ieee80211_tx_queue_stats
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="AP">
|
<chapter id="AP">
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
<!ENTITY VIDIOC-DBG-G-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_G_REGISTER</constant></link>">
|
<!ENTITY VIDIOC-DBG-G-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_G_REGISTER</constant></link>">
|
||||||
<!ENTITY VIDIOC-DBG-S-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_S_REGISTER</constant></link>">
|
<!ENTITY VIDIOC-DBG-S-REGISTER "<link linkend='vidioc-dbg-g-register'><constant>VIDIOC_DBG_S_REGISTER</constant></link>">
|
||||||
<!ENTITY VIDIOC-DQBUF "<link linkend='vidioc-qbuf'><constant>VIDIOC_DQBUF</constant></link>">
|
<!ENTITY VIDIOC-DQBUF "<link linkend='vidioc-qbuf'><constant>VIDIOC_DQBUF</constant></link>">
|
||||||
|
<!ENTITY VIDIOC-DQEVENT "<link linkend='vidioc-dqevent'><constant>VIDIOC_DQEVENT</constant></link>">
|
||||||
<!ENTITY VIDIOC-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_ENCODER_CMD</constant></link>">
|
<!ENTITY VIDIOC-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_ENCODER_CMD</constant></link>">
|
||||||
<!ENTITY VIDIOC-ENUMAUDIO "<link linkend='vidioc-enumaudio'><constant>VIDIOC_ENUMAUDIO</constant></link>">
|
<!ENTITY VIDIOC-ENUMAUDIO "<link linkend='vidioc-enumaudio'><constant>VIDIOC_ENUMAUDIO</constant></link>">
|
||||||
<!ENTITY VIDIOC-ENUMAUDOUT "<link linkend='vidioc-enumaudioout'><constant>VIDIOC_ENUMAUDOUT</constant></link>">
|
<!ENTITY VIDIOC-ENUMAUDOUT "<link linkend='vidioc-enumaudioout'><constant>VIDIOC_ENUMAUDOUT</constant></link>">
|
||||||
@@ -60,6 +61,7 @@
|
|||||||
<!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>">
|
<!ENTITY VIDIOC-REQBUFS "<link linkend='vidioc-reqbufs'><constant>VIDIOC_REQBUFS</constant></link>">
|
||||||
<!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>">
|
<!ENTITY VIDIOC-STREAMOFF "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMOFF</constant></link>">
|
||||||
<!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>">
|
<!ENTITY VIDIOC-STREAMON "<link linkend='vidioc-streamon'><constant>VIDIOC_STREAMON</constant></link>">
|
||||||
|
<!ENTITY VIDIOC-SUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_SUBSCRIBE_EVENT</constant></link>">
|
||||||
<!ENTITY VIDIOC-S-AUDIO "<link linkend='vidioc-g-audio'><constant>VIDIOC_S_AUDIO</constant></link>">
|
<!ENTITY VIDIOC-S-AUDIO "<link linkend='vidioc-g-audio'><constant>VIDIOC_S_AUDIO</constant></link>">
|
||||||
<!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>">
|
<!ENTITY VIDIOC-S-AUDOUT "<link linkend='vidioc-g-audioout'><constant>VIDIOC_S_AUDOUT</constant></link>">
|
||||||
<!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>">
|
<!ENTITY VIDIOC-S-CROP "<link linkend='vidioc-g-crop'><constant>VIDIOC_S_CROP</constant></link>">
|
||||||
@@ -83,6 +85,7 @@
|
|||||||
<!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
|
<!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
|
||||||
<!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
|
<!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
|
||||||
<!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
|
<!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
|
||||||
|
<!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>">
|
||||||
|
|
||||||
<!-- Types -->
|
<!-- Types -->
|
||||||
<!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
|
<!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
|
||||||
@@ -141,6 +144,9 @@
|
|||||||
<!ENTITY v4l2-enc-idx "struct <link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>">
|
<!ENTITY v4l2-enc-idx "struct <link linkend='v4l2-enc-idx'>v4l2_enc_idx</link>">
|
||||||
<!ENTITY v4l2-enc-idx-entry "struct <link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>">
|
<!ENTITY v4l2-enc-idx-entry "struct <link linkend='v4l2-enc-idx-entry'>v4l2_enc_idx_entry</link>">
|
||||||
<!ENTITY v4l2-encoder-cmd "struct <link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>">
|
<!ENTITY v4l2-encoder-cmd "struct <link linkend='v4l2-encoder-cmd'>v4l2_encoder_cmd</link>">
|
||||||
|
<!ENTITY v4l2-event "struct <link linkend='v4l2-event'>v4l2_event</link>">
|
||||||
|
<!ENTITY v4l2-event-subscription "struct <link linkend='v4l2-event-subscription'>v4l2_event_subscription</link>">
|
||||||
|
<!ENTITY v4l2-event-vsync "struct <link linkend='v4l2-event-vsync'>v4l2_event_vsync</link>">
|
||||||
<!ENTITY v4l2-ext-control "struct <link linkend='v4l2-ext-control'>v4l2_ext_control</link>">
|
<!ENTITY v4l2-ext-control "struct <link linkend='v4l2-ext-control'>v4l2_ext_control</link>">
|
||||||
<!ENTITY v4l2-ext-controls "struct <link linkend='v4l2-ext-controls'>v4l2_ext_controls</link>">
|
<!ENTITY v4l2-ext-controls "struct <link linkend='v4l2-ext-controls'>v4l2_ext_controls</link>">
|
||||||
<!ENTITY v4l2-fmtdesc "struct <link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link>">
|
<!ENTITY v4l2-fmtdesc "struct <link linkend='v4l2-fmtdesc'>v4l2_fmtdesc</link>">
|
||||||
@@ -200,6 +206,7 @@
|
|||||||
<!ENTITY sub-controls SYSTEM "v4l/controls.xml">
|
<!ENTITY sub-controls SYSTEM "v4l/controls.xml">
|
||||||
<!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml">
|
<!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml">
|
||||||
<!ENTITY sub-dev-codec SYSTEM "v4l/dev-codec.xml">
|
<!ENTITY sub-dev-codec SYSTEM "v4l/dev-codec.xml">
|
||||||
|
<!ENTITY sub-dev-event SYSTEM "v4l/dev-event.xml">
|
||||||
<!ENTITY sub-dev-effect SYSTEM "v4l/dev-effect.xml">
|
<!ENTITY sub-dev-effect SYSTEM "v4l/dev-effect.xml">
|
||||||
<!ENTITY sub-dev-osd SYSTEM "v4l/dev-osd.xml">
|
<!ENTITY sub-dev-osd SYSTEM "v4l/dev-osd.xml">
|
||||||
<!ENTITY sub-dev-output SYSTEM "v4l/dev-output.xml">
|
<!ENTITY sub-dev-output SYSTEM "v4l/dev-output.xml">
|
||||||
@@ -211,6 +218,7 @@
|
|||||||
<!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
|
<!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
|
||||||
<!ENTITY sub-driver SYSTEM "v4l/driver.xml">
|
<!ENTITY sub-driver SYSTEM "v4l/driver.xml">
|
||||||
<!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
|
<!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
|
||||||
|
<!ENTITY sub-lirc_device_interface SYSTEM "v4l/lirc_device_interface.xml">
|
||||||
<!ENTITY sub-remote_controllers SYSTEM "v4l/remote_controllers.xml">
|
<!ENTITY sub-remote_controllers SYSTEM "v4l/remote_controllers.xml">
|
||||||
<!ENTITY sub-fdl-appendix SYSTEM "v4l/fdl-appendix.xml">
|
<!ENTITY sub-fdl-appendix SYSTEM "v4l/fdl-appendix.xml">
|
||||||
<!ENTITY sub-close SYSTEM "v4l/func-close.xml">
|
<!ENTITY sub-close SYSTEM "v4l/func-close.xml">
|
||||||
@@ -292,6 +300,8 @@
|
|||||||
<!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
|
<!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
|
||||||
<!ENTITY sub-videodev2-h SYSTEM "v4l/videodev2.h.xml">
|
<!ENTITY sub-videodev2-h SYSTEM "v4l/videodev2.h.xml">
|
||||||
<!ENTITY sub-v4l2 SYSTEM "v4l/v4l2.xml">
|
<!ENTITY sub-v4l2 SYSTEM "v4l/v4l2.xml">
|
||||||
|
<!ENTITY sub-dqevent SYSTEM "v4l/vidioc-dqevent.xml">
|
||||||
|
<!ENTITY sub-subscribe-event SYSTEM "v4l/vidioc-subscribe-event.xml">
|
||||||
<!ENTITY sub-intro SYSTEM "dvb/intro.xml">
|
<!ENTITY sub-intro SYSTEM "dvb/intro.xml">
|
||||||
<!ENTITY sub-frontend SYSTEM "dvb/frontend.xml">
|
<!ENTITY sub-frontend SYSTEM "dvb/frontend.xml">
|
||||||
<!ENTITY sub-dvbproperty SYSTEM "dvb/dvbproperty.xml">
|
<!ENTITY sub-dvbproperty SYSTEM "dvb/dvbproperty.xml">
|
||||||
@@ -381,3 +391,5 @@
|
|||||||
<!ENTITY reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
|
<!ENTITY reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
|
||||||
<!ENTITY s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
|
<!ENTITY s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
|
||||||
<!ENTITY streamon SYSTEM "v4l/vidioc-streamon.xml">
|
<!ENTITY streamon SYSTEM "v4l/vidioc-streamon.xml">
|
||||||
|
<!ENTITY dqevent SYSTEM "v4l/vidioc-dqevent.xml">
|
||||||
|
<!ENTITY subscribe_event SYSTEM "v4l/vidioc-subscribe-event.xml">
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
<title>LINUX MEDIA INFRASTRUCTURE API</title>
|
<title>LINUX MEDIA INFRASTRUCTURE API</title>
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2009</year>
|
<year>2009-2010</year>
|
||||||
<holder>LinuxTV Developers</holder>
|
<holder>LinuxTV Developers</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||||||
in fact it covers several different video standards including
|
in fact it covers several different video standards including
|
||||||
DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
|
DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
|
||||||
to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
|
to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
|
||||||
<para>The third part covers other API's used by all media infrastructure devices</para>
|
<para>The third part covers Remote Controller API</para>
|
||||||
<para>For additional information and for the latest development code,
|
<para>For additional information and for the latest development code,
|
||||||
see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
|
see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
|
||||||
<para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
|
<para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
|
||||||
@@ -86,7 +86,7 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||||||
</author>
|
</author>
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2009</year>
|
<year>2009-2010</year>
|
||||||
<holder>Mauro Carvalho Chehab</holder>
|
<holder>Mauro Carvalho Chehab</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ Foundation. A copy of the license is included in the chapter entitled
|
|||||||
</revhistory>
|
</revhistory>
|
||||||
</partinfo>
|
</partinfo>
|
||||||
|
|
||||||
<title>Other API's used by media infrastructure drivers</title>
|
<title>Remote Controller API</title>
|
||||||
<chapter id="remote_controllers">
|
<chapter id="remote_controllers">
|
||||||
&sub-remote_controllers;
|
&sub-remote_controllers;
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@@ -269,7 +269,7 @@ static void board_hwcontrol(struct mtd_info *mtd, int cmd)
|
|||||||
information about the device.
|
information about the device.
|
||||||
</para>
|
</para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
int __init board_init (void)
|
static int __init board_init (void)
|
||||||
{
|
{
|
||||||
struct nand_chip *this;
|
struct nand_chip *this;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -488,7 +488,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
|
|||||||
The ECC bytes must be placed immidiately after the data
|
The ECC bytes must be placed immidiately after the data
|
||||||
bytes in order to make the syndrome generator work. This
|
bytes in order to make the syndrome generator work. This
|
||||||
is contrary to the usual layout used by software ECC. The
|
is contrary to the usual layout used by software ECC. The
|
||||||
seperation of data and out of band area is not longer
|
separation of data and out of band area is not longer
|
||||||
possible. The nand driver code handles this layout and
|
possible. The nand driver code handles this layout and
|
||||||
the remaining free bytes in the oob area are managed by
|
the remaining free bytes in the oob area are managed by
|
||||||
the autoplacement code. Provide a matching oob-layout
|
the autoplacement code. Provide a matching oob-layout
|
||||||
@@ -560,7 +560,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
|
|||||||
bad blocks. They have factory marked good blocks. The marker pattern
|
bad blocks. They have factory marked good blocks. The marker pattern
|
||||||
is erased when the block is erased to be reused. So in case of
|
is erased when the block is erased to be reused. So in case of
|
||||||
powerloss before writing the pattern back to the chip this block
|
powerloss before writing the pattern back to the chip this block
|
||||||
would be lost and added to the bad blocks. Therefor we scan the
|
would be lost and added to the bad blocks. Therefore we scan the
|
||||||
chip(s) when we detect them the first time for good blocks and
|
chip(s) when we detect them the first time for good blocks and
|
||||||
store this information in a bad block table before erasing any
|
store this information in a bad block table before erasing any
|
||||||
of the blocks.
|
of the blocks.
|
||||||
@@ -1094,7 +1094,7 @@ in this page</entry>
|
|||||||
manufacturers specifications. This applies similar to the spare area.
|
manufacturers specifications. This applies similar to the spare area.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Therefor NAND aware filesystems must either write in page size chunks
|
Therefore NAND aware filesystems must either write in page size chunks
|
||||||
or hold a writebuffer to collect smaller writes until they sum up to
|
or hold a writebuffer to collect smaller writes until they sum up to
|
||||||
pagesize. Available NAND aware filesystems: JFFS2, YAFFS.
|
pagesize. Available NAND aware filesystems: JFFS2, YAFFS.
|
||||||
</para>
|
</para>
|
||||||
|
@@ -393,7 +393,7 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For documentation see
|
For documentation see
|
||||||
<ulink url='http://www.torque.net/sg/sdebug26.html'>http://www.torque.net/sg/sdebug26.html</ulink>
|
<ulink url='http://sg.danny.cz/sg/sdebug26.html'>http://sg.danny.cz/sg/sdebug26.html</ulink>
|
||||||
</para>
|
</para>
|
||||||
<!-- !Edrivers/scsi/scsi_debug.c -->
|
<!-- !Edrivers/scsi/scsi_debug.c -->
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@@ -19,13 +19,17 @@
|
|||||||
</authorgroup>
|
</authorgroup>
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2008</year>
|
<year>2008-2010</year>
|
||||||
<holder>Paul Mundt</holder>
|
<holder>Paul Mundt</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2008</year>
|
<year>2008-2010</year>
|
||||||
<holder>Renesas Technology Corp.</holder>
|
<holder>Renesas Technology Corp.</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
<copyright>
|
||||||
|
<year>2010</year>
|
||||||
|
<holder>Renesas Electronics Corp.</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
<legalnotice>
|
<legalnotice>
|
||||||
<para>
|
<para>
|
||||||
@@ -77,7 +81,7 @@
|
|||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="clk">
|
<chapter id="clk">
|
||||||
<title>Clock Framework Extensions</title>
|
<title>Clock Framework Extensions</title>
|
||||||
!Iarch/sh/include/asm/clock.h
|
!Iinclude/linux/sh_clk.h
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="mach">
|
<chapter id="mach">
|
||||||
<title>Machine Specific Interfaces</title>
|
<title>Machine Specific Interfaces</title>
|
||||||
|
@@ -6,4 +6,5 @@
|
|||||||
<param name="callout.graphics">0</param>
|
<param name="callout.graphics">0</param>
|
||||||
<!-- <param name="paper.type">A4</param> -->
|
<!-- <param name="paper.type">A4</param> -->
|
||||||
<param name="generate.section.toc.level">2</param>
|
<param name="generate.section.toc.level">2</param>
|
||||||
|
<param name="use.id.as.filename">1</param>
|
||||||
</stylesheet>
|
</stylesheet>
|
||||||
|
@@ -16,6 +16,15 @@
|
|||||||
</address>
|
</address>
|
||||||
</affiliation>
|
</affiliation>
|
||||||
</author>
|
</author>
|
||||||
|
<author>
|
||||||
|
<firstname>William</firstname>
|
||||||
|
<surname>Cohen</surname>
|
||||||
|
<affiliation>
|
||||||
|
<address>
|
||||||
|
<email>wcohen@redhat.com</email>
|
||||||
|
</address>
|
||||||
|
</affiliation>
|
||||||
|
</author>
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
|
|
||||||
<legalnotice>
|
<legalnotice>
|
||||||
@@ -91,4 +100,13 @@
|
|||||||
!Iinclude/trace/events/signal.h
|
!Iinclude/trace/events/signal.h
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="block">
|
||||||
|
<title>Block IO</title>
|
||||||
|
!Iinclude/trace/events/block.h
|
||||||
|
</chapter>
|
||||||
|
|
||||||
|
<chapter id="workqueue">
|
||||||
|
<title>Workqueue</title>
|
||||||
|
!Iinclude/trace/events/workqueue.h
|
||||||
|
</chapter>
|
||||||
</book>
|
</book>
|
||||||
|
@@ -1170,7 +1170,7 @@ frames per second. If less than this number of frames is to be
|
|||||||
captured or output, applications can request frame skipping or
|
captured or output, applications can request frame skipping or
|
||||||
duplicating on the driver side. This is especially useful when using
|
duplicating on the driver side. This is especially useful when using
|
||||||
the &func-read; or &func-write;, which are not augmented by timestamps
|
the &func-read; or &func-write;, which are not augmented by timestamps
|
||||||
or sequence counters, and to avoid unneccessary data copying.</para>
|
or sequence counters, and to avoid unnecessary data copying.</para>
|
||||||
|
|
||||||
<para>Finally these ioctls can be used to determine the number of
|
<para>Finally these ioctls can be used to determine the number of
|
||||||
buffers used internally by a driver in read/write mode. For
|
buffers used internally by a driver in read/write mode. For
|
||||||
|
@@ -1091,8 +1091,9 @@ signed 64-bit integer. Output devices should not send a buffer out
|
|||||||
until the time in the timestamp field has arrived. I would like to
|
until the time in the timestamp field has arrived. I would like to
|
||||||
follow SGI's lead, and adopt a multimedia timestamping system like
|
follow SGI's lead, and adopt a multimedia timestamping system like
|
||||||
their UST (Unadjusted System Time). See
|
their UST (Unadjusted System Time). See
|
||||||
http://reality.sgi.com/cpirazzi_engr/lg/time/intro.html. [This link is
|
http://web.archive.org/web/*/http://reality.sgi.com
|
||||||
no longer valid.] UST uses timestamps that are 64-bit signed integers
|
/cpirazzi_engr/lg/time/intro.html.
|
||||||
|
UST uses timestamps that are 64-bit signed integers
|
||||||
(not struct timeval's) and given in nanosecond units. The UST clock
|
(not struct timeval's) and given in nanosecond units. The UST clock
|
||||||
starts at zero when the system is booted and runs continuously and
|
starts at zero when the system is booted and runs continuously and
|
||||||
uniformly. It takes a little over 292 years for UST to overflow. There
|
uniformly. It takes a little over 292 years for UST to overflow. There
|
||||||
@@ -2332,6 +2333,17 @@ more information.</para>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</orderedlist>
|
</orderedlist>
|
||||||
</section>
|
</section>
|
||||||
|
<section>
|
||||||
|
<title>V4L2 in Linux 2.6.34</title>
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>Added
|
||||||
|
<constant>V4L2_CID_IRIS_ABSOLUTE</constant> and
|
||||||
|
<constant>V4L2_CID_IRIS_RELATIVE</constant> controls to the
|
||||||
|
<link linkend="camera-controls">Camera controls class</link>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="other">
|
<section id="other">
|
||||||
@@ -2455,6 +2467,7 @@ interfaces and should not be implemented in new drivers.</para>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</section>
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Local Variables:
|
Local Variables:
|
||||||
|
@@ -266,6 +266,12 @@ minimum value disables backlight compensation.</entry>
|
|||||||
<entry>boolean</entry>
|
<entry>boolean</entry>
|
||||||
<entry>Chroma automatic gain control.</entry>
|
<entry>Chroma automatic gain control.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_CID_CHROMA_GAIN</constant></entry>
|
||||||
|
<entry>integer</entry>
|
||||||
|
<entry>Adjusts the Chroma gain control (for use when chroma AGC
|
||||||
|
is disabled).</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_CID_COLOR_KILLER</constant></entry>
|
<entry><constant>V4L2_CID_COLOR_KILLER</constant></entry>
|
||||||
<entry>boolean</entry>
|
<entry>boolean</entry>
|
||||||
@@ -277,8 +283,15 @@ minimum value disables backlight compensation.</entry>
|
|||||||
<entry>Selects a color effect. Possible values for
|
<entry>Selects a color effect. Possible values for
|
||||||
<constant>enum v4l2_colorfx</constant> are:
|
<constant>enum v4l2_colorfx</constant> are:
|
||||||
<constant>V4L2_COLORFX_NONE</constant> (0),
|
<constant>V4L2_COLORFX_NONE</constant> (0),
|
||||||
<constant>V4L2_COLORFX_BW</constant> (1) and
|
<constant>V4L2_COLORFX_BW</constant> (1),
|
||||||
<constant>V4L2_COLORFX_SEPIA</constant> (2).</entry>
|
<constant>V4L2_COLORFX_SEPIA</constant> (2),
|
||||||
|
<constant>V4L2_COLORFX_NEGATIVE</constant> (3),
|
||||||
|
<constant>V4L2_COLORFX_EMBOSS</constant> (4),
|
||||||
|
<constant>V4L2_COLORFX_SKETCH</constant> (5),
|
||||||
|
<constant>V4L2_COLORFX_SKY_BLUE</constant> (6),
|
||||||
|
<constant>V4L2_COLORFX_GRASS_GREEN</constant> (7),
|
||||||
|
<constant>V4L2_COLORFX_SKIN_WHITEN</constant> (8) and
|
||||||
|
<constant>V4L2_COLORFX_VIVID</constant> (9).</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_CID_ROTATE</constant></entry>
|
<entry><constant>V4L2_CID_ROTATE</constant></entry>
|
||||||
@@ -1824,6 +1837,25 @@ wide-angle direction. The zoom speed unit is driver-specific.</entry>
|
|||||||
</row>
|
</row>
|
||||||
<row><entry></entry></row>
|
<row><entry></entry></row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry spanname="id"><constant>V4L2_CID_IRIS_ABSOLUTE</constant> </entry>
|
||||||
|
<entry>integer</entry>
|
||||||
|
</row><row><entry spanname="descr">This control sets the
|
||||||
|
camera's aperture to the specified value. The unit is undefined.
|
||||||
|
Larger values open the iris wider, smaller values close it.</entry>
|
||||||
|
</row>
|
||||||
|
<row><entry></entry></row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry spanname="id"><constant>V4L2_CID_IRIS_RELATIVE</constant> </entry>
|
||||||
|
<entry>integer</entry>
|
||||||
|
</row><row><entry spanname="descr">This control modifies the
|
||||||
|
camera's aperture by the specified amount. The unit is undefined.
|
||||||
|
Positive values open the iris one step further, negative values close
|
||||||
|
it one step further. This is a write-only control.</entry>
|
||||||
|
</row>
|
||||||
|
<row><entry></entry></row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry spanname="id"><constant>V4L2_CID_PRIVACY</constant> </entry>
|
<entry spanname="id"><constant>V4L2_CID_PRIVACY</constant> </entry>
|
||||||
<entry>boolean</entry>
|
<entry>boolean</entry>
|
||||||
|
31
Documentation/DocBook/v4l/dev-event.xml
Normal file
31
Documentation/DocBook/v4l/dev-event.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<title>Event Interface</title>
|
||||||
|
|
||||||
|
<para>The V4L2 event interface provides means for user to get
|
||||||
|
immediately notified on certain conditions taking place on a device.
|
||||||
|
This might include start of frame or loss of signal events, for
|
||||||
|
example.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>To receive events, the events the user is interested in first must
|
||||||
|
be subscribed using the &VIDIOC-SUBSCRIBE-EVENT; ioctl. Once an event is
|
||||||
|
subscribed, the events of subscribed types are dequeueable using the
|
||||||
|
&VIDIOC-DQEVENT; ioctl. Events may be unsubscribed using
|
||||||
|
VIDIOC_UNSUBSCRIBE_EVENT ioctl. The special event type V4L2_EVENT_ALL may
|
||||||
|
be used to unsubscribe all the events the driver supports.</para>
|
||||||
|
|
||||||
|
<para>The event subscriptions and event queues are specific to file
|
||||||
|
handles. Subscribing an event on one file handle does not affect
|
||||||
|
other file handles.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>The information on dequeueable events is obtained by using select or
|
||||||
|
poll system calls on video devices. The V4L2 events use POLLPRI events on
|
||||||
|
poll system call and exceptions on select system call. </para>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Local Variables:
|
||||||
|
mode: sgml
|
||||||
|
sgml-parent-document: "v4l2.sgml"
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
-->
|
@@ -2,7 +2,7 @@
|
|||||||
The GNU Free Documentation License 1.1 in DocBook
|
The GNU Free Documentation License 1.1 in DocBook
|
||||||
Markup by Eric Baudais <baudais@okstate.edu>
|
Markup by Eric Baudais <baudais@okstate.edu>
|
||||||
Maintained by the GNOME Documentation Project
|
Maintained by the GNOME Documentation Project
|
||||||
http://developer.gnome.org/projects/gdp
|
http://live.gnome.org/DocumentationProject
|
||||||
Version: 1.0.1
|
Version: 1.0.1
|
||||||
Last Modified: Nov 16, 2000
|
Last Modified: Nov 16, 2000
|
||||||
-->
|
-->
|
||||||
|
@@ -589,7 +589,8 @@ number of a video input as in &v4l2-input; field
|
|||||||
<entry></entry>
|
<entry></entry>
|
||||||
<entry>A place holder for future extensions and custom
|
<entry>A place holder for future extensions and custom
|
||||||
(driver defined) buffer types
|
(driver defined) buffer types
|
||||||
<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher.</entry>
|
<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher. Applications
|
||||||
|
should set this to 0.</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
@@ -700,6 +701,16 @@ buffer cannot be on both queues at the same time, the
|
|||||||
They can be both cleared however, then the buffer is in "dequeued"
|
They can be both cleared however, then the buffer is in "dequeued"
|
||||||
state, in the application domain to say so.</entry>
|
state, in the application domain to say so.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_BUF_FLAG_ERROR</constant></entry>
|
||||||
|
<entry>0x0040</entry>
|
||||||
|
<entry>When this flag is set, the buffer has been dequeued
|
||||||
|
successfully, although the data might have been corrupted.
|
||||||
|
This is recoverable, streaming may continue as normal and
|
||||||
|
the buffer may be reused normally.
|
||||||
|
Drivers set this flag when the <constant>VIDIOC_DQBUF</constant>
|
||||||
|
ioctl is called.</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_BUF_FLAG_KEYFRAME</constant></entry>
|
<entry><constant>V4L2_BUF_FLAG_KEYFRAME</constant></entry>
|
||||||
<entry>0x0008</entry>
|
<entry>0x0008</entry>
|
||||||
@@ -917,8 +928,8 @@ order</emphasis>.</para>
|
|||||||
|
|
||||||
<para>When the driver provides or accepts images field by field
|
<para>When the driver provides or accepts images field by field
|
||||||
rather than interleaved, it is also important applications understand
|
rather than interleaved, it is also important applications understand
|
||||||
how the fields combine to frames. We distinguish between top and
|
how the fields combine to frames. We distinguish between top (aka odd) and
|
||||||
bottom fields, the <emphasis>spatial order</emphasis>: The first line
|
bottom (aka even) fields, the <emphasis>spatial order</emphasis>: The first line
|
||||||
of the top field is the first line of an interlaced frame, the first
|
of the top field is the first line of an interlaced frame, the first
|
||||||
line of the bottom field is the second line of that frame.</para>
|
line of the bottom field is the second line of that frame.</para>
|
||||||
|
|
||||||
@@ -971,12 +982,12 @@ between <constant>V4L2_FIELD_TOP</constant> and
|
|||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_FIELD_TOP</constant></entry>
|
<entry><constant>V4L2_FIELD_TOP</constant></entry>
|
||||||
<entry>2</entry>
|
<entry>2</entry>
|
||||||
<entry>Images consist of the top field only.</entry>
|
<entry>Images consist of the top (aka odd) field only.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_FIELD_BOTTOM</constant></entry>
|
<entry><constant>V4L2_FIELD_BOTTOM</constant></entry>
|
||||||
<entry>3</entry>
|
<entry>3</entry>
|
||||||
<entry>Images consist of the bottom field only.
|
<entry>Images consist of the bottom (aka even) field only.
|
||||||
Applications may wish to prevent a device from capturing interlaced
|
Applications may wish to prevent a device from capturing interlaced
|
||||||
images because they will have "comb" or "feathering" artefacts around
|
images because they will have "comb" or "feathering" artefacts around
|
||||||
moving objects.</entry>
|
moving objects.</entry>
|
||||||
|
251
Documentation/DocBook/v4l/lirc_device_interface.xml
Normal file
251
Documentation/DocBook/v4l/lirc_device_interface.xml
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
<section id="lirc_dev">
|
||||||
|
<title>LIRC Device Interface</title>
|
||||||
|
|
||||||
|
|
||||||
|
<section id="lirc_dev_intro">
|
||||||
|
<title>Introduction</title>
|
||||||
|
|
||||||
|
<para>The LIRC device interface is a bi-directional interface for
|
||||||
|
transporting raw IR data between userspace and kernelspace. Fundamentally,
|
||||||
|
it is just a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number
|
||||||
|
of standard struct file_operations defined on it. With respect to
|
||||||
|
transporting raw IR data to and fro, the essential fops are read, write
|
||||||
|
and ioctl.</para>
|
||||||
|
|
||||||
|
<para>Example dmesg output upon a driver registering w/LIRC:</para>
|
||||||
|
<blockquote>
|
||||||
|
<para>$ dmesg |grep lirc_dev</para>
|
||||||
|
<para>lirc_dev: IR Remote Control driver registered, major 248</para>
|
||||||
|
<para>rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0</para>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<para>What you should see for a chardev:</para>
|
||||||
|
<blockquote>
|
||||||
|
<para>$ ls -l /dev/lirc*</para>
|
||||||
|
<para>crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0</para>
|
||||||
|
</blockquote>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="lirc_read">
|
||||||
|
<title>LIRC read fop</title>
|
||||||
|
|
||||||
|
<para>The lircd userspace daemon reads raw IR data from the LIRC chardev. The
|
||||||
|
exact format of the data depends on what modes a driver supports, and what
|
||||||
|
mode has been selected. lircd obtains supported modes and sets the active mode
|
||||||
|
via the ioctl interface, detailed at <xref linkend="lirc_ioctl"/>. The generally
|
||||||
|
preferred mode is LIRC_MODE_MODE2, in which packets containing an int value
|
||||||
|
describing an IR signal are read from the chardev.</para>
|
||||||
|
|
||||||
|
<para>See also <ulink url="http://www.lirc.org/html/technical.html">http://www.lirc.org/html/technical.html</ulink> for more info.</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="lirc_write">
|
||||||
|
<title>LIRC write fop</title>
|
||||||
|
|
||||||
|
<para>The data written to the chardev is a pulse/space sequence of integer
|
||||||
|
values. Pulses and spaces are only marked implicitly by their position. The
|
||||||
|
data must start and end with a pulse, therefore, the data must always include
|
||||||
|
an unevent number of samples. The write function must block until the data has
|
||||||
|
been transmitted by the hardware.</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="lirc_ioctl">
|
||||||
|
<title>LIRC ioctl fop</title>
|
||||||
|
|
||||||
|
<para>The LIRC device's ioctl definition is bound by the ioctl function
|
||||||
|
definition of struct file_operations, leaving us with an unsigned int
|
||||||
|
for the ioctl command and an unsigned long for the arg. For the purposes
|
||||||
|
of ioctl portability across 32-bit and 64-bit, these values are capped
|
||||||
|
to their 32-bit sizes.</para>
|
||||||
|
|
||||||
|
<para>The following ioctls can be used to change specific hardware settings.
|
||||||
|
In general each driver should have a default set of settings. The driver
|
||||||
|
implementation is expected to re-apply the default settings when the device
|
||||||
|
is closed by user-space, so that every application opening the device can rely
|
||||||
|
on working with the default settings initially.</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_FEATURES</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Obviously, get the underlying hardware device's features. If a driver
|
||||||
|
does not announce support of certain features, calling of the corresponding
|
||||||
|
ioctls is undefined.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_SEND_MODE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Get supported transmit mode. Only LIRC_MODE_PULSE is supported by lircd.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_REC_MODE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Get supported receive modes. Only LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE
|
||||||
|
are supported by lircd.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_SEND_CARRIER</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Get carrier frequency (in Hz) currently used for transmit.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_REC_CARRIER</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Get carrier frequency (in Hz) currently used for IR reception.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_{G,S}ET_{SEND,REC}_DUTY_CYCLE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Get/set the duty cycle (from 0 to 100) of the carrier signal. Currently,
|
||||||
|
no special meaning is defined for 0 or 100, but this could be used to switch
|
||||||
|
off carrier generation in the future, so these values should be reserved.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_REC_RESOLUTION</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Some receiver have maximum resolution which is defined by internal
|
||||||
|
sample rate or data format limitations. E.g. it's common that signals can
|
||||||
|
only be reported in 50 microsecond steps. This integer value is used by
|
||||||
|
lircd to automatically adjust the aeps tolerance value in the lircd
|
||||||
|
config file.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_M{IN,AX}_TIMEOUT</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Some devices have internal timers that can be used to detect when
|
||||||
|
there's no IR activity for a long time. This can help lircd in detecting
|
||||||
|
that a IR signal is finished and can speed up the decoding process.
|
||||||
|
Returns an integer value with the minimum/maximum timeout that can be
|
||||||
|
set. Some devices have a fixed timeout, in that case both ioctls will
|
||||||
|
return the same value even though the timeout cannot be changed.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_M{IN,AX}_FILTER_{PULSE,SPACE}</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Some devices are able to filter out spikes in the incoming signal
|
||||||
|
using given filter rules. These ioctls return the hardware capabilities
|
||||||
|
that describe the bounds of the possible filters. Filter settings depend
|
||||||
|
on the IR protocols that are expected. lircd derives the settings from
|
||||||
|
all protocols definitions found in its config file.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_GET_LENGTH</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Retrieves the code length in bits (only for LIRC_MODE_LIRCCODE).
|
||||||
|
Reads on the device must be done in blocks matching the bit count.
|
||||||
|
The bit could should be rounded up so that it matches full bytes.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_{SEND,REC}_MODE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Set send/receive mode. Largely obsolete for send, as only
|
||||||
|
LIRC_MODE_PULSE is supported.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_{SEND,REC}_CARRIER</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Set send/receive carrier (in Hz).</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_TRANSMITTER_MASK</term>
|
||||||
|
<listitem>
|
||||||
|
<para>This enables the given set of transmitters. The first transmitter
|
||||||
|
is encoded by the least significant bit, etc. When an invalid bit mask
|
||||||
|
is given, i.e. a bit is set, even though the device does not have so many
|
||||||
|
transitters, then this ioctl returns the number of available transitters
|
||||||
|
and does nothing otherwise.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_REC_TIMEOUT</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Sets the integer value for IR inactivity timeout (cf.
|
||||||
|
LIRC_GET_MIN_TIMEOUT and LIRC_GET_MAX_TIMEOUT). A value of 0 (if
|
||||||
|
supported by the hardware) disables all hardware timeouts and data should
|
||||||
|
be reported as soon as possible. If the exact value cannot be set, then
|
||||||
|
the next possible value _greater_ than the given value should be set.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_REC_TIMEOUT_REPORTS</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Enable (1) or disable (0) timeout reports in LIRC_MODE_MODE2. By
|
||||||
|
default, timeout reports should be turned off.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_REC_FILTER_{,PULSE,SPACE}</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Pulses/spaces shorter than this are filtered out by hardware. If
|
||||||
|
filters cannot be set independently for pulse/space, the corresponding
|
||||||
|
ioctls must return an error and LIRC_SET_REC_FILTER shall be used instead.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_MEASURE_CARRIER_MODE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Enable (1)/disable (0) measure mode. If enabled, from the next key
|
||||||
|
press on, the driver will send LIRC_MODE2_FREQUENCY packets. By default
|
||||||
|
this should be turned off.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_REC_{DUTY_CYCLE,CARRIER}_RANGE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>To set a range use LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE
|
||||||
|
with the lower bound first and later LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER
|
||||||
|
with the upper bound.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_NOTIFY_DECODE</term>
|
||||||
|
<listitem>
|
||||||
|
<para>This ioctl is called by lircd whenever a successful decoding of an
|
||||||
|
incoming IR signal could be done. This can be used by supporting hardware
|
||||||
|
to give visual feedback to the user e.g. by flashing a LED.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SETUP_{START,END}</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Setting of several driver parameters can be optimized by encapsulating
|
||||||
|
the according ioctl calls with LIRC_SETUP_START/LIRC_SETUP_END. When a
|
||||||
|
driver receives a LIRC_SETUP_START ioctl it can choose to not commit
|
||||||
|
further setting changes to the hardware until a LIRC_SETUP_END is received.
|
||||||
|
But this is open to the driver implementation and every driver must also
|
||||||
|
handle parameter changes which are not encapsulated by LIRC_SETUP_START
|
||||||
|
and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term>LIRC_SET_WIDEBAND_RECEIVER</term>
|
||||||
|
<listitem>
|
||||||
|
<para>Some receivers are equipped with special wide band receiver which is intended
|
||||||
|
to be used to learn output of existing remote.
|
||||||
|
Calling that ioctl with (1) will enable it, and with (0) disable it.
|
||||||
|
This might be useful of receivers that have otherwise narrow band receiver
|
||||||
|
that prevents them to be used with some remotes.
|
||||||
|
Wide band receiver might also be more precise
|
||||||
|
On the other hand its disadvantage it usually reduced range of reception.
|
||||||
|
Note: wide band receiver might be implictly enabled if you enable
|
||||||
|
carrier reports. In that case it will be disabled as soon as you disable
|
||||||
|
carrier reports. Trying to disable wide band receiver while carrier
|
||||||
|
reports are active will do nothing.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</section>
|
@@ -240,6 +240,45 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
|
|||||||
<entry>r<subscript>1</subscript></entry>
|
<entry>r<subscript>1</subscript></entry>
|
||||||
<entry>r<subscript>0</subscript></entry>
|
<entry>r<subscript>0</subscript></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row id="V4L2-PIX-FMT-BGR666">
|
||||||
|
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
|
||||||
|
<entry>'BGRH'</entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>b<subscript>5</subscript></entry>
|
||||||
|
<entry>b<subscript>4</subscript></entry>
|
||||||
|
<entry>b<subscript>3</subscript></entry>
|
||||||
|
<entry>b<subscript>2</subscript></entry>
|
||||||
|
<entry>b<subscript>1</subscript></entry>
|
||||||
|
<entry>b<subscript>0</subscript></entry>
|
||||||
|
<entry>g<subscript>5</subscript></entry>
|
||||||
|
<entry>g<subscript>4</subscript></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>g<subscript>3</subscript></entry>
|
||||||
|
<entry>g<subscript>2</subscript></entry>
|
||||||
|
<entry>g<subscript>1</subscript></entry>
|
||||||
|
<entry>g<subscript>0</subscript></entry>
|
||||||
|
<entry>r<subscript>5</subscript></entry>
|
||||||
|
<entry>r<subscript>4</subscript></entry>
|
||||||
|
<entry>r<subscript>3</subscript></entry>
|
||||||
|
<entry>r<subscript>2</subscript></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>r<subscript>1</subscript></entry>
|
||||||
|
<entry>r<subscript>0</subscript></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
</row>
|
||||||
<row id="V4L2-PIX-FMT-BGR24">
|
<row id="V4L2-PIX-FMT-BGR24">
|
||||||
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
|
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
|
||||||
<entry>'BGR3'</entry>
|
<entry>'BGR3'</entry>
|
||||||
@@ -700,6 +739,45 @@ defined in error. Drivers may interpret them as in <xref
|
|||||||
<entry>b<subscript>1</subscript></entry>
|
<entry>b<subscript>1</subscript></entry>
|
||||||
<entry>b<subscript>0</subscript></entry>
|
<entry>b<subscript>0</subscript></entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row id="V4L2-PIX-FMT-BGR666">
|
||||||
|
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
|
||||||
|
<entry>'BGRH'</entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>b<subscript>5</subscript></entry>
|
||||||
|
<entry>b<subscript>4</subscript></entry>
|
||||||
|
<entry>b<subscript>3</subscript></entry>
|
||||||
|
<entry>b<subscript>2</subscript></entry>
|
||||||
|
<entry>b<subscript>1</subscript></entry>
|
||||||
|
<entry>b<subscript>0</subscript></entry>
|
||||||
|
<entry>g<subscript>5</subscript></entry>
|
||||||
|
<entry>g<subscript>4</subscript></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>g<subscript>3</subscript></entry>
|
||||||
|
<entry>g<subscript>2</subscript></entry>
|
||||||
|
<entry>g<subscript>1</subscript></entry>
|
||||||
|
<entry>g<subscript>0</subscript></entry>
|
||||||
|
<entry>r<subscript>5</subscript></entry>
|
||||||
|
<entry>r<subscript>4</subscript></entry>
|
||||||
|
<entry>r<subscript>3</subscript></entry>
|
||||||
|
<entry>r<subscript>2</subscript></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>r<subscript>1</subscript></entry>
|
||||||
|
<entry>r<subscript>0</subscript></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
</row>
|
||||||
<row><!-- id="V4L2-PIX-FMT-BGR24" -->
|
<row><!-- id="V4L2-PIX-FMT-BGR24" -->
|
||||||
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
|
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
|
||||||
<entry>'BGR3'</entry>
|
<entry>'BGR3'</entry>
|
||||||
|
@@ -792,6 +792,18 @@ http://www.thedirks.org/winnov/</ulink></para></entry>
|
|||||||
<entry>'YYUV'</entry>
|
<entry>'YYUV'</entry>
|
||||||
<entry>unknown</entry>
|
<entry>unknown</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row id="V4L2-PIX-FMT-Y4">
|
||||||
|
<entry><constant>V4L2_PIX_FMT_Y4</constant></entry>
|
||||||
|
<entry>'Y04 '</entry>
|
||||||
|
<entry>Old 4-bit greyscale format. Only the least significant 4 bits of each byte are used,
|
||||||
|
the other bits are set to 0.</entry>
|
||||||
|
</row>
|
||||||
|
<row id="V4L2-PIX-FMT-Y6">
|
||||||
|
<entry><constant>V4L2_PIX_FMT_Y6</constant></entry>
|
||||||
|
<entry>'Y06 '</entry>
|
||||||
|
<entry>Old 6-bit greyscale format. Only the least significant 6 bits of each byte are used,
|
||||||
|
the other bits are set to 0.</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -173,3 +173,5 @@ keymapping.</para>
|
|||||||
<para>This program demonstrates how to replace the keymap tables.</para>
|
<para>This program demonstrates how to replace the keymap tables.</para>
|
||||||
&sub-keytable-c;
|
&sub-keytable-c;
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
&sub-lirc_device_interface;
|
||||||
|
@@ -58,7 +58,7 @@ MPEG stream embedded, sliced VBI data format in this specification.
|
|||||||
</contrib>
|
</contrib>
|
||||||
<affiliation>
|
<affiliation>
|
||||||
<address>
|
<address>
|
||||||
<email>awalls@radix.net</email>
|
<email>awalls@md.metrocast.net</email>
|
||||||
</address>
|
</address>
|
||||||
</affiliation>
|
</affiliation>
|
||||||
</author>
|
</author>
|
||||||
@@ -401,6 +401,7 @@ and discussions on the V4L mailing list.</revremark>
|
|||||||
<section id="ttx"> &sub-dev-teletext; </section>
|
<section id="ttx"> &sub-dev-teletext; </section>
|
||||||
<section id="radio"> &sub-dev-radio; </section>
|
<section id="radio"> &sub-dev-radio; </section>
|
||||||
<section id="rds"> &sub-dev-rds; </section>
|
<section id="rds"> &sub-dev-rds; </section>
|
||||||
|
<section id="event"> &sub-dev-event; </section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="driver">
|
<chapter id="driver">
|
||||||
@@ -426,6 +427,7 @@ and discussions on the V4L mailing list.</revremark>
|
|||||||
&sub-cropcap;
|
&sub-cropcap;
|
||||||
&sub-dbg-g-chip-ident;
|
&sub-dbg-g-chip-ident;
|
||||||
&sub-dbg-g-register;
|
&sub-dbg-g-register;
|
||||||
|
&sub-dqevent;
|
||||||
&sub-encoder-cmd;
|
&sub-encoder-cmd;
|
||||||
&sub-enumaudio;
|
&sub-enumaudio;
|
||||||
&sub-enumaudioout;
|
&sub-enumaudioout;
|
||||||
@@ -467,6 +469,7 @@ and discussions on the V4L mailing list.</revremark>
|
|||||||
&sub-reqbufs;
|
&sub-reqbufs;
|
||||||
&sub-s-hw-freq-seek;
|
&sub-s-hw-freq-seek;
|
||||||
&sub-streamon;
|
&sub-streamon;
|
||||||
|
&sub-subscribe-event;
|
||||||
<!-- End of ioctls. -->
|
<!-- End of ioctls. -->
|
||||||
&sub-mmap;
|
&sub-mmap;
|
||||||
&sub-munmap;
|
&sub-munmap;
|
||||||
|
@@ -1018,6 +1018,13 @@ enum <link linkend="v4l2-colorfx">v4l2_colorfx</link> {
|
|||||||
V4L2_COLORFX_NONE = 0,
|
V4L2_COLORFX_NONE = 0,
|
||||||
V4L2_COLORFX_BW = 1,
|
V4L2_COLORFX_BW = 1,
|
||||||
V4L2_COLORFX_SEPIA = 2,
|
V4L2_COLORFX_SEPIA = 2,
|
||||||
|
V4L2_COLORFX_NEGATIVE = 3,
|
||||||
|
V4L2_COLORFX_EMBOSS = 4,
|
||||||
|
V4L2_COLORFX_SKETCH = 5,
|
||||||
|
V4L2_COLORFX_SKY_BLUE = 6,
|
||||||
|
V4L2_COLORFX_GRASS_GREEN = 7,
|
||||||
|
V4L2_COLORFX_SKIN_WHITEN = 8,
|
||||||
|
V4L2_COLORFX_VIVID = 9.
|
||||||
};
|
};
|
||||||
#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32)
|
#define V4L2_CID_AUTOBRIGHTNESS (V4L2_CID_BASE+32)
|
||||||
#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33)
|
#define V4L2_CID_BAND_STOP_FILTER (V4L2_CID_BASE+33)
|
||||||
@@ -1271,6 +1278,9 @@ enum <link linkend="v4l2-exposure-auto-type">v4l2_exposure_auto_type</link> {
|
|||||||
|
|
||||||
#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16)
|
#define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16)
|
||||||
|
|
||||||
|
#define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17)
|
||||||
|
#define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18)
|
||||||
|
|
||||||
/* FM Modulator class control IDs */
|
/* FM Modulator class control IDs */
|
||||||
#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900)
|
#define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900)
|
||||||
#define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1)
|
#define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1)
|
||||||
|
131
Documentation/DocBook/v4l/vidioc-dqevent.xml
Normal file
131
Documentation/DocBook/v4l/vidioc-dqevent.xml
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
<refentry id="vidioc-dqevent">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>ioctl VIDIOC_DQEVENT</refentrytitle>
|
||||||
|
&manvol;
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>VIDIOC_DQEVENT</refname>
|
||||||
|
<refpurpose>Dequeue event</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<funcsynopsis>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>int <function>ioctl</function></funcdef>
|
||||||
|
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>request</parameter></paramdef>
|
||||||
|
<paramdef>struct v4l2_event
|
||||||
|
*<parameter>argp</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
</funcsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Arguments</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter>fd</parameter></term>
|
||||||
|
<listitem>
|
||||||
|
<para>&fd;</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter>request</parameter></term>
|
||||||
|
<listitem>
|
||||||
|
<para>VIDIOC_DQEVENT</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter>argp</parameter></term>
|
||||||
|
<listitem>
|
||||||
|
<para></para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>Dequeue an event from a video device. No input is required
|
||||||
|
for this ioctl. All the fields of the &v4l2-event; structure are
|
||||||
|
filled by the driver. The file handle will also receive exceptions
|
||||||
|
which the application may get by e.g. using the select system
|
||||||
|
call.</para>
|
||||||
|
|
||||||
|
<table frame="none" pgwide="1" id="v4l2-event">
|
||||||
|
<title>struct <structname>v4l2_event</structname></title>
|
||||||
|
<tgroup cols="4">
|
||||||
|
&cs-str;
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry>__u32</entry>
|
||||||
|
<entry><structfield>type</structfield></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Type of the event.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>union</entry>
|
||||||
|
<entry><structfield>u</structfield></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry></entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>&v4l2-event-vsync;</entry>
|
||||||
|
<entry><structfield>vsync</structfield></entry>
|
||||||
|
<entry>Event data for event V4L2_EVENT_VSYNC.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>__u8</entry>
|
||||||
|
<entry><structfield>data</structfield>[64]</entry>
|
||||||
|
<entry>Event data. Defined by the event type. The union
|
||||||
|
should be used to define easily accessible type for
|
||||||
|
events.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>__u32</entry>
|
||||||
|
<entry><structfield>pending</structfield></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Number of pending events excluding this one.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>__u32</entry>
|
||||||
|
<entry><structfield>sequence</structfield></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Event sequence number. The sequence number is
|
||||||
|
incremented for every subscribed event that takes place.
|
||||||
|
If sequence numbers are not contiguous it means that
|
||||||
|
events have been lost.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>struct timespec</entry>
|
||||||
|
<entry><structfield>timestamp</structfield></entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Event timestamp.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>__u32</entry>
|
||||||
|
<entry><structfield>reserved</structfield>[9]</entry>
|
||||||
|
<entry></entry>
|
||||||
|
<entry>Reserved for future extensions. Drivers must set
|
||||||
|
the array to zero.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
<!--
|
||||||
|
Local Variables:
|
||||||
|
mode: sgml
|
||||||
|
sgml-parent-document: "v4l2.sgml"
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
-->
|
@@ -283,7 +283,7 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
|
|||||||
<entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
|
<entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry>
|
<entry><constant>V4L2_IN_CAP_CUSTOM_TIMINGS</constant></entry>
|
||||||
<entry>0x00000002</entry>
|
<entry>0x00000002</entry>
|
||||||
<entry>This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry>
|
<entry>This input supports setting custom video timings by using VIDIOC_S_DV_TIMINGS.</entry>
|
||||||
</row>
|
</row>
|
||||||
|
@@ -55,7 +55,7 @@ captured or output, applications can request frame skipping or
|
|||||||
duplicating on the driver side. This is especially useful when using
|
duplicating on the driver side. This is especially useful when using
|
||||||
the <function>read()</function> or <function>write()</function>, which
|
the <function>read()</function> or <function>write()</function>, which
|
||||||
are not augmented by timestamps or sequence counters, and to avoid
|
are not augmented by timestamps or sequence counters, and to avoid
|
||||||
unneccessary data copying.</para>
|
unnecessary data copying.</para>
|
||||||
|
|
||||||
<para>Further these ioctls can be used to determine the number of
|
<para>Further these ioctls can be used to determine the number of
|
||||||
buffers used internally by a driver in read/write mode. For
|
buffers used internally by a driver in read/write mode. For
|
||||||
|
@@ -54,12 +54,10 @@ to enqueue an empty (capturing) or filled (output) buffer in the
|
|||||||
driver's incoming queue. The semantics depend on the selected I/O
|
driver's incoming queue. The semantics depend on the selected I/O
|
||||||
method.</para>
|
method.</para>
|
||||||
|
|
||||||
<para>To enqueue a <link linkend="mmap">memory mapped</link>
|
<para>To enqueue a buffer applications set the <structfield>type</structfield>
|
||||||
buffer applications set the <structfield>type</structfield> field of a
|
field of a &v4l2-buffer; to the same buffer type as was previously used
|
||||||
&v4l2-buffer; to the same buffer type as previously &v4l2-format;
|
with &v4l2-format; <structfield>type</structfield> and &v4l2-requestbuffers;
|
||||||
<structfield>type</structfield> and &v4l2-requestbuffers;
|
<structfield>type</structfield>. Applications must also set the
|
||||||
<structfield>type</structfield>, the <structfield>memory</structfield>
|
|
||||||
field to <constant>V4L2_MEMORY_MMAP</constant> and the
|
|
||||||
<structfield>index</structfield> field. Valid index numbers range from
|
<structfield>index</structfield> field. Valid index numbers range from
|
||||||
zero to the number of buffers allocated with &VIDIOC-REQBUFS;
|
zero to the number of buffers allocated with &VIDIOC-REQBUFS;
|
||||||
(&v4l2-requestbuffers; <structfield>count</structfield>) minus one. The
|
(&v4l2-requestbuffers; <structfield>count</structfield>) minus one. The
|
||||||
@@ -70,8 +68,19 @@ intended for output (<structfield>type</structfield> is
|
|||||||
<constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant>) applications must also
|
<constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant>) applications must also
|
||||||
initialize the <structfield>bytesused</structfield>,
|
initialize the <structfield>bytesused</structfield>,
|
||||||
<structfield>field</structfield> and
|
<structfield>field</structfield> and
|
||||||
<structfield>timestamp</structfield> fields. See <xref
|
<structfield>timestamp</structfield> fields, see <xref
|
||||||
linkend="buffer" /> for details. When
|
linkend="buffer" /> for details.
|
||||||
|
Applications must also set <structfield>flags</structfield> to 0. If a driver
|
||||||
|
supports capturing from specific video inputs and you want to specify a video
|
||||||
|
input, then <structfield>flags</structfield> should be set to
|
||||||
|
<constant>V4L2_BUF_FLAG_INPUT</constant> and the field
|
||||||
|
<structfield>input</structfield> must be initialized to the desired input.
|
||||||
|
The <structfield>reserved</structfield> field must be set to 0.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>To enqueue a <link linkend="mmap">memory mapped</link>
|
||||||
|
buffer applications set the <structfield>memory</structfield>
|
||||||
|
field to <constant>V4L2_MEMORY_MMAP</constant>. When
|
||||||
<constant>VIDIOC_QBUF</constant> is called with a pointer to this
|
<constant>VIDIOC_QBUF</constant> is called with a pointer to this
|
||||||
structure the driver sets the
|
structure the driver sets the
|
||||||
<constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
<constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
||||||
@@ -81,14 +90,10 @@ structure the driver sets the
|
|||||||
&EINVAL;.</para>
|
&EINVAL;.</para>
|
||||||
|
|
||||||
<para>To enqueue a <link linkend="userp">user pointer</link>
|
<para>To enqueue a <link linkend="userp">user pointer</link>
|
||||||
buffer applications set the <structfield>type</structfield> field of a
|
buffer applications set the <structfield>memory</structfield>
|
||||||
&v4l2-buffer; to the same buffer type as previously &v4l2-format;
|
field to <constant>V4L2_MEMORY_USERPTR</constant>, the
|
||||||
<structfield>type</structfield> and &v4l2-requestbuffers;
|
|
||||||
<structfield>type</structfield>, the <structfield>memory</structfield>
|
|
||||||
field to <constant>V4L2_MEMORY_USERPTR</constant> and the
|
|
||||||
<structfield>m.userptr</structfield> field to the address of the
|
<structfield>m.userptr</structfield> field to the address of the
|
||||||
buffer and <structfield>length</structfield> to its size. When the
|
buffer and <structfield>length</structfield> to its size.
|
||||||
buffer is intended for output additional fields must be set as above.
|
|
||||||
When <constant>VIDIOC_QBUF</constant> is called with a pointer to this
|
When <constant>VIDIOC_QBUF</constant> is called with a pointer to this
|
||||||
structure the driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant>
|
structure the driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant>
|
||||||
flag and clears the <constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
flag and clears the <constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
||||||
@@ -96,16 +101,21 @@ flag and clears the <constant>V4L2_BUF_FLAG_MAPPED</constant> and
|
|||||||
<structfield>flags</structfield> field, or it returns an error code.
|
<structfield>flags</structfield> field, or it returns an error code.
|
||||||
This ioctl locks the memory pages of the buffer in physical memory,
|
This ioctl locks the memory pages of the buffer in physical memory,
|
||||||
they cannot be swapped out to disk. Buffers remain locked until
|
they cannot be swapped out to disk. Buffers remain locked until
|
||||||
dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl are
|
dequeued, until the &VIDIOC-STREAMOFF; or &VIDIOC-REQBUFS; ioctl is
|
||||||
called, or until the device is closed.</para>
|
called, or until the device is closed.</para>
|
||||||
|
|
||||||
<para>Applications call the <constant>VIDIOC_DQBUF</constant>
|
<para>Applications call the <constant>VIDIOC_DQBUF</constant>
|
||||||
ioctl to dequeue a filled (capturing) or displayed (output) buffer
|
ioctl to dequeue a filled (capturing) or displayed (output) buffer
|
||||||
from the driver's outgoing queue. They just set the
|
from the driver's outgoing queue. They just set the
|
||||||
<structfield>type</structfield> and <structfield>memory</structfield>
|
<structfield>type</structfield>, <structfield>memory</structfield>
|
||||||
|
and <structfield>reserved</structfield>
|
||||||
fields of a &v4l2-buffer; as above, when <constant>VIDIOC_DQBUF</constant>
|
fields of a &v4l2-buffer; as above, when <constant>VIDIOC_DQBUF</constant>
|
||||||
is called with a pointer to this structure the driver fills the
|
is called with a pointer to this structure the driver fills the
|
||||||
remaining fields or returns an error code.</para>
|
remaining fields or returns an error code. The driver may also set
|
||||||
|
<constant>V4L2_BUF_FLAG_ERROR</constant> in the <structfield>flags</structfield>
|
||||||
|
field. It indicates a non-critical (recoverable) streaming error. In such case
|
||||||
|
the application may continue as normal, but should be aware that data in the
|
||||||
|
dequeued buffer might be corrupted.</para>
|
||||||
|
|
||||||
<para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
|
<para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
|
||||||
buffer is in the outgoing queue. When the
|
buffer is in the outgoing queue. When the
|
||||||
@@ -152,7 +162,13 @@ enqueue a user pointer buffer.</para>
|
|||||||
<para><constant>VIDIOC_DQBUF</constant> failed due to an
|
<para><constant>VIDIOC_DQBUF</constant> failed due to an
|
||||||
internal error. Can also indicate temporary problems like signal
|
internal error. Can also indicate temporary problems like signal
|
||||||
loss. Note the driver might dequeue an (empty) buffer despite
|
loss. Note the driver might dequeue an (empty) buffer despite
|
||||||
returning an error, or even stop capturing.</para>
|
returning an error, or even stop capturing. Reusing such buffer may be unsafe
|
||||||
|
though and its details (e.g. <structfield>index</structfield>) may not be
|
||||||
|
returned either. It is recommended that drivers indicate recoverable errors
|
||||||
|
by setting the <constant>V4L2_BUF_FLAG_ERROR</constant> and returning 0 instead.
|
||||||
|
In that case the application should be able to safely reuse the buffer and
|
||||||
|
continue streaming.
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
@@ -53,8 +53,10 @@ input</refpurpose>
|
|||||||
automatically, similar to sensing the video standard. To do so, applications
|
automatically, similar to sensing the video standard. To do so, applications
|
||||||
call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
|
call <constant> VIDIOC_QUERY_DV_PRESET</constant> with a pointer to a
|
||||||
&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
|
&v4l2-dv-preset; type. Once the hardware detects a preset, that preset is
|
||||||
returned in the preset field of &v4l2-dv-preset;. When detection is not
|
returned in the preset field of &v4l2-dv-preset;. If the preset could not be
|
||||||
possible or fails, the value V4L2_DV_INVALID is returned.</para>
|
detected because there was no signal, or the signal was unreliable, or the
|
||||||
|
signal did not map to a supported preset, then the value V4L2_DV_INVALID is
|
||||||
|
returned.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@@ -54,12 +54,13 @@ buffer at any time after buffers have been allocated with the
|
|||||||
&VIDIOC-REQBUFS; ioctl.</para>
|
&VIDIOC-REQBUFS; ioctl.</para>
|
||||||
|
|
||||||
<para>Applications set the <structfield>type</structfield> field
|
<para>Applications set the <structfield>type</structfield> field
|
||||||
of a &v4l2-buffer; to the same buffer type as previously
|
of a &v4l2-buffer; to the same buffer type as was previously used with
|
||||||
&v4l2-format; <structfield>type</structfield> and &v4l2-requestbuffers;
|
&v4l2-format; <structfield>type</structfield> and &v4l2-requestbuffers;
|
||||||
<structfield>type</structfield>, and the <structfield>index</structfield>
|
<structfield>type</structfield>, and the <structfield>index</structfield>
|
||||||
field. Valid index numbers range from zero
|
field. Valid index numbers range from zero
|
||||||
to the number of buffers allocated with &VIDIOC-REQBUFS;
|
to the number of buffers allocated with &VIDIOC-REQBUFS;
|
||||||
(&v4l2-requestbuffers; <structfield>count</structfield>) minus one.
|
(&v4l2-requestbuffers; <structfield>count</structfield>) minus one.
|
||||||
|
The <structfield>reserved</structfield> field should to set to 0.
|
||||||
After calling <constant>VIDIOC_QUERYBUF</constant> with a pointer to
|
After calling <constant>VIDIOC_QUERYBUF</constant> with a pointer to
|
||||||
this structure drivers return an error code or fill the rest of
|
this structure drivers return an error code or fill the rest of
|
||||||
the structure.</para>
|
the structure.</para>
|
||||||
@@ -68,8 +69,8 @@ the structure.</para>
|
|||||||
<constant>V4L2_BUF_FLAG_MAPPED</constant>,
|
<constant>V4L2_BUF_FLAG_MAPPED</constant>,
|
||||||
<constant>V4L2_BUF_FLAG_QUEUED</constant> and
|
<constant>V4L2_BUF_FLAG_QUEUED</constant> and
|
||||||
<constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
|
<constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
|
||||||
<structfield>memory</structfield> field will be set to
|
<structfield>memory</structfield> field will be set to the current
|
||||||
<constant>V4L2_MEMORY_MMAP</constant>, the <structfield>m.offset</structfield>
|
I/O method, the <structfield>m.offset</structfield>
|
||||||
contains the offset of the buffer from the start of the device memory,
|
contains the offset of the buffer from the start of the device memory,
|
||||||
the <structfield>length</structfield> field its size. The driver may
|
the <structfield>length</structfield> field its size. The driver may
|
||||||
or may not set the remaining fields and flags, they are meaningless in
|
or may not set the remaining fields and flags, they are meaningless in
|
||||||
|
@@ -325,7 +325,7 @@ should be part of the control documentation.</entry>
|
|||||||
<entry>n/a</entry>
|
<entry>n/a</entry>
|
||||||
<entry>This is not a control. When
|
<entry>This is not a control. When
|
||||||
<constant>VIDIOC_QUERYCTRL</constant> is called with a control ID
|
<constant>VIDIOC_QUERYCTRL</constant> is called with a control ID
|
||||||
equal to a control class code (see <xref linkend="ctrl-class" />), the
|
equal to a control class code (see <xref linkend="ctrl-class" />) + 1, the
|
||||||
ioctl returns the name of the control class and this control type.
|
ioctl returns the name of the control class and this control type.
|
||||||
Older drivers which do not support this feature return an
|
Older drivers which do not support this feature return an
|
||||||
&EINVAL;.</entry>
|
&EINVAL;.</entry>
|
||||||
|
@@ -54,23 +54,23 @@ I/O. Memory mapped buffers are located in device memory and must be
|
|||||||
allocated with this ioctl before they can be mapped into the
|
allocated with this ioctl before they can be mapped into the
|
||||||
application's address space. User buffers are allocated by
|
application's address space. User buffers are allocated by
|
||||||
applications themselves, and this ioctl is merely used to switch the
|
applications themselves, and this ioctl is merely used to switch the
|
||||||
driver into user pointer I/O mode.</para>
|
driver into user pointer I/O mode and to setup some internal structures.</para>
|
||||||
|
|
||||||
<para>To allocate device buffers applications initialize three
|
<para>To allocate device buffers applications initialize all
|
||||||
fields of a <structname>v4l2_requestbuffers</structname> structure.
|
fields of the <structname>v4l2_requestbuffers</structname> structure.
|
||||||
They set the <structfield>type</structfield> field to the respective
|
They set the <structfield>type</structfield> field to the respective
|
||||||
stream or buffer type, the <structfield>count</structfield> field to
|
stream or buffer type, the <structfield>count</structfield> field to
|
||||||
the desired number of buffers, and <structfield>memory</structfield>
|
the desired number of buffers, <structfield>memory</structfield>
|
||||||
must be set to <constant>V4L2_MEMORY_MMAP</constant>. When the ioctl
|
must be set to the requested I/O method and the <structfield>reserved</structfield> array
|
||||||
is called with a pointer to this structure the driver attempts to
|
must be zeroed. When the ioctl
|
||||||
allocate the requested number of buffers and stores the actual number
|
is called with a pointer to this structure the driver will attempt to allocate
|
||||||
|
the requested number of buffers and it stores the actual number
|
||||||
allocated in the <structfield>count</structfield> field. It can be
|
allocated in the <structfield>count</structfield> field. It can be
|
||||||
smaller than the number requested, even zero, when the driver runs out
|
smaller than the number requested, even zero, when the driver runs out
|
||||||
of free memory. A larger number is possible when the driver requires
|
of free memory. A larger number is also possible when the driver requires
|
||||||
more buffers to function correctly.<footnote>
|
more buffers to function correctly. For example video output requires at least two buffers,
|
||||||
<para>For example video output requires at least two buffers,
|
|
||||||
one displayed and one filled by the application.</para>
|
one displayed and one filled by the application.</para>
|
||||||
</footnote> When memory mapping I/O is not supported the ioctl
|
<para>When the I/O method is not supported the ioctl
|
||||||
returns an &EINVAL;.</para>
|
returns an &EINVAL;.</para>
|
||||||
|
|
||||||
<para>Applications can call <constant>VIDIOC_REQBUFS</constant>
|
<para>Applications can call <constant>VIDIOC_REQBUFS</constant>
|
||||||
@@ -81,14 +81,6 @@ in progress, an implicit &VIDIOC-STREAMOFF;. <!-- mhs: I see no
|
|||||||
reason why munmap()ping one or even all buffers must imply
|
reason why munmap()ping one or even all buffers must imply
|
||||||
streamoff.--></para>
|
streamoff.--></para>
|
||||||
|
|
||||||
<para>To negotiate user pointer I/O, applications initialize only
|
|
||||||
the <structfield>type</structfield> field and set
|
|
||||||
<structfield>memory</structfield> to
|
|
||||||
<constant>V4L2_MEMORY_USERPTR</constant>. When the ioctl is called
|
|
||||||
with a pointer to this structure the driver prepares for user pointer
|
|
||||||
I/O, when this I/O method is not supported the ioctl returns an
|
|
||||||
&EINVAL;.</para>
|
|
||||||
|
|
||||||
<table pgwide="1" frame="none" id="v4l2-requestbuffers">
|
<table pgwide="1" frame="none" id="v4l2-requestbuffers">
|
||||||
<title>struct <structname>v4l2_requestbuffers</structname></title>
|
<title>struct <structname>v4l2_requestbuffers</structname></title>
|
||||||
<tgroup cols="3">
|
<tgroup cols="3">
|
||||||
@@ -97,9 +89,7 @@ I/O, when this I/O method is not supported the ioctl returns an
|
|||||||
<row>
|
<row>
|
||||||
<entry>__u32</entry>
|
<entry>__u32</entry>
|
||||||
<entry><structfield>count</structfield></entry>
|
<entry><structfield>count</structfield></entry>
|
||||||
<entry>The number of buffers requested or granted. This
|
<entry>The number of buffers requested or granted.</entry>
|
||||||
field is only used when <structfield>memory</structfield> is set to
|
|
||||||
<constant>V4L2_MEMORY_MMAP</constant>.</entry>
|
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>&v4l2-buf-type;</entry>
|
<entry>&v4l2-buf-type;</entry>
|
||||||
@@ -120,7 +110,7 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
|
|||||||
<entry><structfield>reserved</structfield>[2]</entry>
|
<entry><structfield>reserved</structfield>[2]</entry>
|
||||||
<entry>A place holder for future extensions and custom
|
<entry>A place holder for future extensions and custom
|
||||||
(driver defined) buffer types <constant>V4L2_BUF_TYPE_PRIVATE</constant> and
|
(driver defined) buffer types <constant>V4L2_BUF_TYPE_PRIVATE</constant> and
|
||||||
higher.</entry>
|
higher. This array should be zeroed by applications.</entry>
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
|
133
Documentation/DocBook/v4l/vidioc-subscribe-event.xml
Normal file
133
Documentation/DocBook/v4l/vidioc-subscribe-event.xml
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<refentry id="vidioc-subscribe-event">
|
||||||
|
<refmeta>
|
||||||
|
<refentrytitle>ioctl VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refentrytitle>
|
||||||
|
&manvol;
|
||||||
|
</refmeta>
|
||||||
|
|
||||||
|
<refnamediv>
|
||||||
|
<refname>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</refname>
|
||||||
|
<refpurpose>Subscribe or unsubscribe event</refpurpose>
|
||||||
|
</refnamediv>
|
||||||
|
|
||||||
|
<refsynopsisdiv>
|
||||||
|
<funcsynopsis>
|
||||||
|
<funcprototype>
|
||||||
|
<funcdef>int <function>ioctl</function></funcdef>
|
||||||
|
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||||
|
<paramdef>int <parameter>request</parameter></paramdef>
|
||||||
|
<paramdef>struct v4l2_event_subscription
|
||||||
|
*<parameter>argp</parameter></paramdef>
|
||||||
|
</funcprototype>
|
||||||
|
</funcsynopsis>
|
||||||
|
</refsynopsisdiv>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Arguments</title>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter>fd</parameter></term>
|
||||||
|
<listitem>
|
||||||
|
<para>&fd;</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter>request</parameter></term>
|
||||||
|
<listitem>
|
||||||
|
<para>VIDIOC_SUBSCRIBE_EVENT, VIDIOC_UNSUBSCRIBE_EVENT</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
<varlistentry>
|
||||||
|
<term><parameter>argp</parameter></term>
|
||||||
|
<listitem>
|
||||||
|
<para></para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Description</title>
|
||||||
|
|
||||||
|
<para>Subscribe or unsubscribe V4L2 event. Subscribed events are
|
||||||
|
dequeued by using the &VIDIOC-DQEVENT; ioctl.</para>
|
||||||
|
|
||||||
|
<table frame="none" pgwide="1" id="v4l2-event-subscription">
|
||||||
|
<title>struct <structname>v4l2_event_subscription</structname></title>
|
||||||
|
<tgroup cols="3">
|
||||||
|
&cs-str;
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry>__u32</entry>
|
||||||
|
<entry><structfield>type</structfield></entry>
|
||||||
|
<entry>Type of the event.</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>__u32</entry>
|
||||||
|
<entry><structfield>reserved</structfield>[7]</entry>
|
||||||
|
<entry>Reserved for future extensions. Drivers and applications
|
||||||
|
must set the array to zero.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table frame="none" pgwide="1" id="event-type">
|
||||||
|
<title>Event Types</title>
|
||||||
|
<tgroup cols="3">
|
||||||
|
&cs-def;
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_EVENT_ALL</constant></entry>
|
||||||
|
<entry>0</entry>
|
||||||
|
<entry>All events. V4L2_EVENT_ALL is valid only for
|
||||||
|
VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_EVENT_VSYNC</constant></entry>
|
||||||
|
<entry>1</entry>
|
||||||
|
<entry>This event is triggered on the vertical sync.
|
||||||
|
This event has &v4l2-event-vsync; associated with it.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_EVENT_EOS</constant></entry>
|
||||||
|
<entry>2</entry>
|
||||||
|
<entry>This event is triggered when the end of a stream is reached.
|
||||||
|
This is typically used with MPEG decoders to report to the application
|
||||||
|
when the last of the MPEG stream has been decoded.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
|
||||||
|
<entry>0x08000000</entry>
|
||||||
|
<entry>Base event number for driver-private events.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table frame="none" pgwide="1" id="v4l2-event-vsync">
|
||||||
|
<title>struct <structname>v4l2_event_vsync</structname></title>
|
||||||
|
<tgroup cols="3">
|
||||||
|
&cs-str;
|
||||||
|
<tbody valign="top">
|
||||||
|
<row>
|
||||||
|
<entry>__u8</entry>
|
||||||
|
<entry><structfield>field</structfield></entry>
|
||||||
|
<entry>The upcoming field. See &v4l2-field;.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</refsect1>
|
||||||
|
</refentry>
|
||||||
|
<!--
|
||||||
|
Local Variables:
|
||||||
|
mode: sgml
|
||||||
|
sgml-parent-document: "v4l2.sgml"
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
-->
|
@@ -5518,34 +5518,41 @@ struct _snd_pcm_runtime {
|
|||||||
]]>
|
]]>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</informalexample>
|
</informalexample>
|
||||||
|
|
||||||
|
For the raw data, <structfield>size</structfield> field must be
|
||||||
|
set properly. This specifies the maximum size of the proc file access.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The callback is much more complicated than the text-file
|
The read/write callbacks of raw mode are more direct than the text mode.
|
||||||
version. You need to use a low-level I/O functions such as
|
You need to use a low-level I/O functions such as
|
||||||
<function>copy_from/to_user()</function> to transfer the
|
<function>copy_from/to_user()</function> to transfer the
|
||||||
data.
|
data.
|
||||||
|
|
||||||
<informalexample>
|
<informalexample>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
static long my_file_io_read(struct snd_info_entry *entry,
|
static ssize_t my_file_io_read(struct snd_info_entry *entry,
|
||||||
void *file_private_data,
|
void *file_private_data,
|
||||||
struct file *file,
|
struct file *file,
|
||||||
char *buf,
|
char *buf,
|
||||||
unsigned long count,
|
size_t count,
|
||||||
unsigned long pos)
|
loff_t pos)
|
||||||
{
|
{
|
||||||
long size = count;
|
if (copy_to_user(buf, local_data + pos, count))
|
||||||
if (pos + size > local_max_size)
|
|
||||||
size = local_max_size - pos;
|
|
||||||
if (copy_to_user(buf, local_data + pos, size))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return size;
|
return count;
|
||||||
}
|
}
|
||||||
]]>
|
]]>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</informalexample>
|
</informalexample>
|
||||||
|
|
||||||
|
If the size of the info entry has been set up properly,
|
||||||
|
<structfield>count</structfield> and <structfield>pos</structfield> are
|
||||||
|
guaranteed to fit within 0 and the given size.
|
||||||
|
You don't have to check the range in the callbacks unless any
|
||||||
|
other condition is required.
|
||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@@ -342,7 +342,7 @@ static inline void skel_delete (struct usb_skel *dev)
|
|||||||
{
|
{
|
||||||
kfree (dev->bulk_in_buffer);
|
kfree (dev->bulk_in_buffer);
|
||||||
if (dev->bulk_out_buffer != NULL)
|
if (dev->bulk_out_buffer != NULL)
|
||||||
usb_buffer_free (dev->udev, dev->bulk_out_size,
|
usb_free_coherent (dev->udev, dev->bulk_out_size,
|
||||||
dev->bulk_out_buffer,
|
dev->bulk_out_buffer,
|
||||||
dev->write_urb->transfer_dma);
|
dev->write_urb->transfer_dma);
|
||||||
usb_free_urb (dev->write_urb);
|
usb_free_urb (dev->write_urb);
|
||||||
|
@@ -187,7 +187,7 @@ apply a patch.
|
|||||||
If you do not know where you want to start, but you want to look for
|
If you do not know where you want to start, but you want to look for
|
||||||
some task to start doing to join into the kernel development community,
|
some task to start doing to join into the kernel development community,
|
||||||
go to the Linux Kernel Janitor's project:
|
go to the Linux Kernel Janitor's project:
|
||||||
http://janitor.kernelnewbies.org/
|
http://kernelnewbies.org/KernelJanitors
|
||||||
It is a great place to start. It describes a list of relatively simple
|
It is a great place to start. It describes a list of relatively simple
|
||||||
problems that need to be cleaned up and fixed within the Linux kernel
|
problems that need to be cleaned up and fixed within the Linux kernel
|
||||||
source tree. Working with the developers in charge of this project, you
|
source tree. Working with the developers in charge of this project, you
|
||||||
@@ -221,8 +221,8 @@ branches. These different branches are:
|
|||||||
- main 2.6.x kernel tree
|
- main 2.6.x kernel tree
|
||||||
- 2.6.x.y -stable kernel tree
|
- 2.6.x.y -stable kernel tree
|
||||||
- 2.6.x -git kernel patches
|
- 2.6.x -git kernel patches
|
||||||
- 2.6.x -mm kernel patches
|
|
||||||
- subsystem specific kernel trees and patches
|
- subsystem specific kernel trees and patches
|
||||||
|
- the 2.6.x -next kernel tree for integration tests
|
||||||
|
|
||||||
2.6.x kernel tree
|
2.6.x kernel tree
|
||||||
-----------------
|
-----------------
|
||||||
@@ -232,9 +232,9 @@ process is as follows:
|
|||||||
- As soon as a new kernel is released a two weeks window is open,
|
- As soon as a new kernel is released a two weeks window is open,
|
||||||
during this period of time maintainers can submit big diffs to
|
during this period of time maintainers can submit big diffs to
|
||||||
Linus, usually the patches that have already been included in the
|
Linus, usually the patches that have already been included in the
|
||||||
-mm kernel for a few weeks. The preferred way to submit big changes
|
-next kernel for a few weeks. The preferred way to submit big changes
|
||||||
is using git (the kernel's source management tool, more information
|
is using git (the kernel's source management tool, more information
|
||||||
can be found at http://git.or.cz/) but plain patches are also just
|
can be found at http://git-scm.com/) but plain patches are also just
|
||||||
fine.
|
fine.
|
||||||
- After two weeks a -rc1 kernel is released it is now possible to push
|
- After two weeks a -rc1 kernel is released it is now possible to push
|
||||||
only patches that do not include new features that could affect the
|
only patches that do not include new features that could affect the
|
||||||
@@ -293,84 +293,43 @@ daily and represent the current state of Linus' tree. They are more
|
|||||||
experimental than -rc kernels since they are generated automatically
|
experimental than -rc kernels since they are generated automatically
|
||||||
without even a cursory glance to see if they are sane.
|
without even a cursory glance to see if they are sane.
|
||||||
|
|
||||||
2.6.x -mm kernel patches
|
|
||||||
------------------------
|
|
||||||
These are experimental kernel patches released by Andrew Morton. Andrew
|
|
||||||
takes all of the different subsystem kernel trees and patches and mushes
|
|
||||||
them together, along with a lot of patches that have been plucked from
|
|
||||||
the linux-kernel mailing list. This tree serves as a proving ground for
|
|
||||||
new features and patches. Once a patch has proved its worth in -mm for
|
|
||||||
a while Andrew or the subsystem maintainer pushes it on to Linus for
|
|
||||||
inclusion in mainline.
|
|
||||||
|
|
||||||
It is heavily encouraged that all new patches get tested in the -mm tree
|
|
||||||
before they are sent to Linus for inclusion in the main kernel tree. Code
|
|
||||||
which does not make an appearance in -mm before the opening of the merge
|
|
||||||
window will prove hard to merge into the mainline.
|
|
||||||
|
|
||||||
These kernels are not appropriate for use on systems that are supposed
|
|
||||||
to be stable and they are more risky to run than any of the other
|
|
||||||
branches.
|
|
||||||
|
|
||||||
If you wish to help out with the kernel development process, please test
|
|
||||||
and use these kernel releases and provide feedback to the linux-kernel
|
|
||||||
mailing list if you have any problems, and if everything works properly.
|
|
||||||
|
|
||||||
In addition to all the other experimental patches, these kernels usually
|
|
||||||
also contain any changes in the mainline -git kernels available at the
|
|
||||||
time of release.
|
|
||||||
|
|
||||||
The -mm kernels are not released on a fixed schedule, but usually a few
|
|
||||||
-mm kernels are released in between each -rc kernel (1 to 3 is common).
|
|
||||||
|
|
||||||
Subsystem Specific kernel trees and patches
|
Subsystem Specific kernel trees and patches
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
A number of the different kernel subsystem developers expose their
|
The maintainers of the various kernel subsystems --- and also many
|
||||||
development trees so that others can see what is happening in the
|
kernel subsystem developers --- expose their current state of
|
||||||
different areas of the kernel. These trees are pulled into the -mm
|
development in source repositories. That way, others can see what is
|
||||||
kernel releases as described above.
|
happening in the different areas of the kernel. In areas where
|
||||||
|
development is rapid, a developer may be asked to base his submissions
|
||||||
|
onto such a subsystem kernel tree so that conflicts between the
|
||||||
|
submission and other already ongoing work are avoided.
|
||||||
|
|
||||||
Here is a list of some of the different kernel trees available:
|
Most of these repositories are git trees, but there are also other SCMs
|
||||||
git trees:
|
in use, or patch queues being published as quilt series. Addresses of
|
||||||
- Kbuild development tree, Sam Ravnborg <sam@ravnborg.org>
|
these subsystem repositories are listed in the MAINTAINERS file. Many
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
|
of them can be browsed at http://git.kernel.org/.
|
||||||
|
|
||||||
- ACPI development tree, Len Brown <len.brown@intel.com>
|
Before a proposed patch is committed to such a subsystem tree, it is
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
|
subject to review which primarily happens on mailing lists (see the
|
||||||
|
respective section below). For several kernel subsystems, this review
|
||||||
|
process is tracked with the tool patchwork. Patchwork offers a web
|
||||||
|
interface which shows patch postings, any comments on a patch or
|
||||||
|
revisions to it, and maintainers can mark patches as under review,
|
||||||
|
accepted, or rejected. Most of these patchwork sites are listed at
|
||||||
|
http://patchwork.kernel.org/.
|
||||||
|
|
||||||
- Block development tree, Jens Axboe <jens.axboe@oracle.com>
|
2.6.x -next kernel tree for integration tests
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
|
---------------------------------------------
|
||||||
|
Before updates from subsystem trees are merged into the mainline 2.6.x
|
||||||
|
tree, they need to be integration-tested. For this purpose, a special
|
||||||
|
testing repository exists into which virtually all subsystem trees are
|
||||||
|
pulled on an almost daily basis:
|
||||||
|
http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
|
||||||
|
http://linux.f-seidel.de/linux-next/pmwiki/
|
||||||
|
|
||||||
- DRM development tree, Dave Airlie <airlied@linux.ie>
|
This way, the -next kernel gives a summary outlook onto what will be
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
|
expected to go into the mainline kernel at the next merge period.
|
||||||
|
Adventurous testers are very welcome to runtime-test the -next kernel.
|
||||||
|
|
||||||
- ia64 development tree, Tony Luck <tony.luck@intel.com>
|
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
|
|
||||||
|
|
||||||
- infiniband, Roland Dreier <rolandd@cisco.com>
|
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
|
|
||||||
|
|
||||||
- libata, Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
|
|
||||||
|
|
||||||
- network drivers, Jeff Garzik <jgarzik@pobox.com>
|
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
|
|
||||||
|
|
||||||
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
|
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
|
|
||||||
|
|
||||||
- SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
|
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
|
|
||||||
|
|
||||||
- x86, Ingo Molnar <mingo@elte.hu>
|
|
||||||
git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
|
|
||||||
|
|
||||||
quilt trees:
|
|
||||||
- USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
|
|
||||||
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
|
|
||||||
|
|
||||||
Other kernel trees can be found listed at http://git.kernel.org/ and in
|
|
||||||
the MAINTAINERS file.
|
|
||||||
|
|
||||||
Bug Reporting
|
Bug Reporting
|
||||||
-------------
|
-------------
|
||||||
@@ -636,7 +595,7 @@ start exactly where you are now.
|
|||||||
|
|
||||||
----------
|
----------
|
||||||
Thanks to Paolo Ciarrocchi who allowed the "Development Process"
|
Thanks to Paolo Ciarrocchi who allowed the "Development Process"
|
||||||
(http://linux.tar.bz/articles/2.6-development_process) section
|
(http://lwn.net/Articles/94386/) section
|
||||||
to be based on text he had written, and to Randy Dunlap and Gerrit
|
to be based on text he had written, and to Randy Dunlap and Gerrit
|
||||||
Huizenga for some of the list of things you should and should not say.
|
Huizenga for some of the list of things you should and should not say.
|
||||||
Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
|
Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
|
||||||
|
@@ -365,6 +365,7 @@ You can change this at module load time (for a module) with:
|
|||||||
regshifts=<shift1>,<shift2>,...
|
regshifts=<shift1>,<shift2>,...
|
||||||
slave_addrs=<addr1>,<addr2>,...
|
slave_addrs=<addr1>,<addr2>,...
|
||||||
force_kipmid=<enable1>,<enable2>,...
|
force_kipmid=<enable1>,<enable2>,...
|
||||||
|
kipmid_max_busy_us=<ustime1>,<ustime2>,...
|
||||||
unload_when_empty=[0|1]
|
unload_when_empty=[0|1]
|
||||||
|
|
||||||
Each of these except si_trydefaults is a list, the first item for the
|
Each of these except si_trydefaults is a list, the first item for the
|
||||||
@@ -433,6 +434,7 @@ kernel command line as:
|
|||||||
ipmi_si.regshifts=<shift1>,<shift2>,...
|
ipmi_si.regshifts=<shift1>,<shift2>,...
|
||||||
ipmi_si.slave_addrs=<addr1>,<addr2>,...
|
ipmi_si.slave_addrs=<addr1>,<addr2>,...
|
||||||
ipmi_si.force_kipmid=<enable1>,<enable2>,...
|
ipmi_si.force_kipmid=<enable1>,<enable2>,...
|
||||||
|
ipmi_si.kipmid_max_busy_us=<ustime1>,<ustime2>,...
|
||||||
|
|
||||||
It works the same as the module parameters of the same names.
|
It works the same as the module parameters of the same names.
|
||||||
|
|
||||||
@@ -450,6 +452,16 @@ force this thread on or off. If you force it off and don't have
|
|||||||
interrupts, the driver will run VERY slowly. Don't blame me,
|
interrupts, the driver will run VERY slowly. Don't blame me,
|
||||||
these interfaces suck.
|
these interfaces suck.
|
||||||
|
|
||||||
|
Unfortunately, this thread can use a lot of CPU depending on the
|
||||||
|
interface's performance. This can waste a lot of CPU and cause
|
||||||
|
various issues with detecting idle CPU and using extra power. To
|
||||||
|
avoid this, the kipmid_max_busy_us sets the maximum amount of time, in
|
||||||
|
microseconds, that kipmid will spin before sleeping for a tick. This
|
||||||
|
value sets a balance between performance and CPU waste and needs to be
|
||||||
|
tuned to your needs. Maybe, someday, auto-tuning will be added, but
|
||||||
|
that's not a simple thing and even the auto-tuning would need to be
|
||||||
|
tuned to the user's desired performance.
|
||||||
|
|
||||||
The driver supports a hot add and remove of interfaces. This way,
|
The driver supports a hot add and remove of interfaces. This way,
|
||||||
interfaces can be added or removed after the kernel is up and running.
|
interfaces can be added or removed after the kernel is up and running.
|
||||||
This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a
|
This is done using /sys/modules/ipmi_si/parameters/hotmod, which is a
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
|
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
|
||||||
filesystems/configfs/ ia64/ networking/ \
|
filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
|
||||||
pcmcia/ spi/ video4linux/ vm/ watchdog/src/
|
pcmcia/ spi/ timers/ video4linux/ vm/ watchdog/src/
|
||||||
|
@@ -1,766 +0,0 @@
|
|||||||
Dynamic DMA mapping
|
|
||||||
===================
|
|
||||||
|
|
||||||
David S. Miller <davem@redhat.com>
|
|
||||||
Richard Henderson <rth@cygnus.com>
|
|
||||||
Jakub Jelinek <jakub@redhat.com>
|
|
||||||
|
|
||||||
This document describes the DMA mapping system in terms of the pci_
|
|
||||||
API. For a similar API that works for generic devices, see
|
|
||||||
DMA-API.txt.
|
|
||||||
|
|
||||||
Most of the 64bit platforms have special hardware that translates bus
|
|
||||||
addresses (DMA addresses) into physical addresses. This is similar to
|
|
||||||
how page tables and/or a TLB translates virtual addresses to physical
|
|
||||||
addresses on a CPU. This is needed so that e.g. PCI devices can
|
|
||||||
access with a Single Address Cycle (32bit DMA address) any page in the
|
|
||||||
64bit physical address space. Previously in Linux those 64bit
|
|
||||||
platforms had to set artificial limits on the maximum RAM size in the
|
|
||||||
system, so that the virt_to_bus() static scheme works (the DMA address
|
|
||||||
translation tables were simply filled on bootup to map each bus
|
|
||||||
address to the physical page __pa(bus_to_virt())).
|
|
||||||
|
|
||||||
So that Linux can use the dynamic DMA mapping, it needs some help from the
|
|
||||||
drivers, namely it has to take into account that DMA addresses should be
|
|
||||||
mapped only for the time they are actually used and unmapped after the DMA
|
|
||||||
transfer.
|
|
||||||
|
|
||||||
The following API will work of course even on platforms where no such
|
|
||||||
hardware exists, see e.g. arch/x86/include/asm/pci.h for how it is implemented on
|
|
||||||
top of the virt_to_bus interface.
|
|
||||||
|
|
||||||
First of all, you should make sure
|
|
||||||
|
|
||||||
#include <linux/pci.h>
|
|
||||||
|
|
||||||
is in your driver. This file will obtain for you the definition of the
|
|
||||||
dma_addr_t (which can hold any valid DMA address for the platform)
|
|
||||||
type which should be used everywhere you hold a DMA (bus) address
|
|
||||||
returned from the DMA mapping functions.
|
|
||||||
|
|
||||||
What memory is DMA'able?
|
|
||||||
|
|
||||||
The first piece of information you must know is what kernel memory can
|
|
||||||
be used with the DMA mapping facilities. There has been an unwritten
|
|
||||||
set of rules regarding this, and this text is an attempt to finally
|
|
||||||
write them down.
|
|
||||||
|
|
||||||
If you acquired your memory via the page allocator
|
|
||||||
(i.e. __get_free_page*()) or the generic memory allocators
|
|
||||||
(i.e. kmalloc() or kmem_cache_alloc()) then you may DMA to/from
|
|
||||||
that memory using the addresses returned from those routines.
|
|
||||||
|
|
||||||
This means specifically that you may _not_ use the memory/addresses
|
|
||||||
returned from vmalloc() for DMA. It is possible to DMA to the
|
|
||||||
_underlying_ memory mapped into a vmalloc() area, but this requires
|
|
||||||
walking page tables to get the physical addresses, and then
|
|
||||||
translating each of those pages back to a kernel address using
|
|
||||||
something like __va(). [ EDIT: Update this when we integrate
|
|
||||||
Gerd Knorr's generic code which does this. ]
|
|
||||||
|
|
||||||
This rule also means that you may use neither kernel image addresses
|
|
||||||
(items in data/text/bss segments), nor module image addresses, nor
|
|
||||||
stack addresses for DMA. These could all be mapped somewhere entirely
|
|
||||||
different than the rest of physical memory. Even if those classes of
|
|
||||||
memory could physically work with DMA, you'd need to ensure the I/O
|
|
||||||
buffers were cacheline-aligned. Without that, you'd see cacheline
|
|
||||||
sharing problems (data corruption) on CPUs with DMA-incoherent caches.
|
|
||||||
(The CPU could write to one word, DMA would write to a different one
|
|
||||||
in the same cache line, and one of them could be overwritten.)
|
|
||||||
|
|
||||||
Also, this means that you cannot take the return of a kmap()
|
|
||||||
call and DMA to/from that. This is similar to vmalloc().
|
|
||||||
|
|
||||||
What about block I/O and networking buffers? The block I/O and
|
|
||||||
networking subsystems make sure that the buffers they use are valid
|
|
||||||
for you to DMA from/to.
|
|
||||||
|
|
||||||
DMA addressing limitations
|
|
||||||
|
|
||||||
Does your device have any DMA addressing limitations? For example, is
|
|
||||||
your device only capable of driving the low order 24-bits of address
|
|
||||||
on the PCI bus for SAC DMA transfers? If so, you need to inform the
|
|
||||||
PCI layer of this fact.
|
|
||||||
|
|
||||||
By default, the kernel assumes that your device can address the full
|
|
||||||
32-bits in a SAC cycle. For a 64-bit DAC capable device, this needs
|
|
||||||
to be increased. And for a device with limitations, as discussed in
|
|
||||||
the previous paragraph, it needs to be decreased.
|
|
||||||
|
|
||||||
pci_alloc_consistent() by default will return 32-bit DMA addresses.
|
|
||||||
PCI-X specification requires PCI-X devices to support 64-bit
|
|
||||||
addressing (DAC) for all transactions. And at least one platform (SGI
|
|
||||||
SN2) requires 64-bit consistent allocations to operate correctly when
|
|
||||||
the IO bus is in PCI-X mode. Therefore, like with pci_set_dma_mask(),
|
|
||||||
it's good practice to call pci_set_consistent_dma_mask() to set the
|
|
||||||
appropriate mask even if your device only supports 32-bit DMA
|
|
||||||
(default) and especially if it's a PCI-X device.
|
|
||||||
|
|
||||||
For correct operation, you must interrogate the PCI layer in your
|
|
||||||
device probe routine to see if the PCI controller on the machine can
|
|
||||||
properly support the DMA addressing limitation your device has. It is
|
|
||||||
good style to do this even if your device holds the default setting,
|
|
||||||
because this shows that you did think about these issues wrt. your
|
|
||||||
device.
|
|
||||||
|
|
||||||
The query is performed via a call to pci_set_dma_mask():
|
|
||||||
|
|
||||||
int pci_set_dma_mask(struct pci_dev *pdev, u64 device_mask);
|
|
||||||
|
|
||||||
The query for consistent allocations is performed via a call to
|
|
||||||
pci_set_consistent_dma_mask():
|
|
||||||
|
|
||||||
int pci_set_consistent_dma_mask(struct pci_dev *pdev, u64 device_mask);
|
|
||||||
|
|
||||||
Here, pdev is a pointer to the PCI device struct of your device, and
|
|
||||||
device_mask is a bit mask describing which bits of a PCI address your
|
|
||||||
device supports. It returns zero if your card can perform DMA
|
|
||||||
properly on the machine given the address mask you provided.
|
|
||||||
|
|
||||||
If it returns non-zero, your device cannot perform DMA properly on
|
|
||||||
this platform, and attempting to do so will result in undefined
|
|
||||||
behavior. You must either use a different mask, or not use DMA.
|
|
||||||
|
|
||||||
This means that in the failure case, you have three options:
|
|
||||||
|
|
||||||
1) Use another DMA mask, if possible (see below).
|
|
||||||
2) Use some non-DMA mode for data transfer, if possible.
|
|
||||||
3) Ignore this device and do not initialize it.
|
|
||||||
|
|
||||||
It is recommended that your driver print a kernel KERN_WARNING message
|
|
||||||
when you end up performing either #2 or #3. In this manner, if a user
|
|
||||||
of your driver reports that performance is bad or that the device is not
|
|
||||||
even detected, you can ask them for the kernel messages to find out
|
|
||||||
exactly why.
|
|
||||||
|
|
||||||
The standard 32-bit addressing PCI device would do something like
|
|
||||||
this:
|
|
||||||
|
|
||||||
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"mydev: No suitable DMA available.\n");
|
|
||||||
goto ignore_this_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
Another common scenario is a 64-bit capable device. The approach
|
|
||||||
here is to try for 64-bit DAC addressing, but back down to a
|
|
||||||
32-bit mask should that fail. The PCI platform code may fail the
|
|
||||||
64-bit mask not because the platform is not capable of 64-bit
|
|
||||||
addressing. Rather, it may fail in this case simply because
|
|
||||||
32-bit SAC addressing is done more efficiently than DAC addressing.
|
|
||||||
Sparc64 is one platform which behaves in this way.
|
|
||||||
|
|
||||||
Here is how you would handle a 64-bit capable device which can drive
|
|
||||||
all 64-bits when accessing streaming DMA:
|
|
||||||
|
|
||||||
int using_dac;
|
|
||||||
|
|
||||||
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
|
|
||||||
using_dac = 1;
|
|
||||||
} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
|
||||||
using_dac = 0;
|
|
||||||
} else {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"mydev: No suitable DMA available.\n");
|
|
||||||
goto ignore_this_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
If a card is capable of using 64-bit consistent allocations as well,
|
|
||||||
the case would look like this:
|
|
||||||
|
|
||||||
int using_dac, consistent_using_dac;
|
|
||||||
|
|
||||||
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
|
|
||||||
using_dac = 1;
|
|
||||||
consistent_using_dac = 1;
|
|
||||||
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
|
|
||||||
} else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
|
||||||
using_dac = 0;
|
|
||||||
consistent_using_dac = 0;
|
|
||||||
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
|
|
||||||
} else {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"mydev: No suitable DMA available.\n");
|
|
||||||
goto ignore_this_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_set_consistent_dma_mask() will always be able to set the same or a
|
|
||||||
smaller mask as pci_set_dma_mask(). However for the rare case that a
|
|
||||||
device driver only uses consistent allocations, one would have to
|
|
||||||
check the return value from pci_set_consistent_dma_mask().
|
|
||||||
|
|
||||||
Finally, if your device can only drive the low 24-bits of
|
|
||||||
address during PCI bus mastering you might do something like:
|
|
||||||
|
|
||||||
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(24))) {
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"mydev: 24-bit DMA addressing not available.\n");
|
|
||||||
goto ignore_this_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
When pci_set_dma_mask() is successful, and returns zero, the PCI layer
|
|
||||||
saves away this mask you have provided. The PCI layer will use this
|
|
||||||
information later when you make DMA mappings.
|
|
||||||
|
|
||||||
There is a case which we are aware of at this time, which is worth
|
|
||||||
mentioning in this documentation. If your device supports multiple
|
|
||||||
functions (for example a sound card provides playback and record
|
|
||||||
functions) and the various different functions have _different_
|
|
||||||
DMA addressing limitations, you may wish to probe each mask and
|
|
||||||
only provide the functionality which the machine can handle. It
|
|
||||||
is important that the last call to pci_set_dma_mask() be for the
|
|
||||||
most specific mask.
|
|
||||||
|
|
||||||
Here is pseudo-code showing how this might be done:
|
|
||||||
|
|
||||||
#define PLAYBACK_ADDRESS_BITS DMA_BIT_MASK(32)
|
|
||||||
#define RECORD_ADDRESS_BITS DMA_BIT_MASK(24)
|
|
||||||
|
|
||||||
struct my_sound_card *card;
|
|
||||||
struct pci_dev *pdev;
|
|
||||||
|
|
||||||
...
|
|
||||||
if (!pci_set_dma_mask(pdev, PLAYBACK_ADDRESS_BITS)) {
|
|
||||||
card->playback_enabled = 1;
|
|
||||||
} else {
|
|
||||||
card->playback_enabled = 0;
|
|
||||||
printk(KERN_WARNING "%s: Playback disabled due to DMA limitations.\n",
|
|
||||||
card->name);
|
|
||||||
}
|
|
||||||
if (!pci_set_dma_mask(pdev, RECORD_ADDRESS_BITS)) {
|
|
||||||
card->record_enabled = 1;
|
|
||||||
} else {
|
|
||||||
card->record_enabled = 0;
|
|
||||||
printk(KERN_WARNING "%s: Record disabled due to DMA limitations.\n",
|
|
||||||
card->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
A sound card was used as an example here because this genre of PCI
|
|
||||||
devices seems to be littered with ISA chips given a PCI front end,
|
|
||||||
and thus retaining the 16MB DMA addressing limitations of ISA.
|
|
||||||
|
|
||||||
Types of DMA mappings
|
|
||||||
|
|
||||||
There are two types of DMA mappings:
|
|
||||||
|
|
||||||
- Consistent DMA mappings which are usually mapped at driver
|
|
||||||
initialization, unmapped at the end and for which the hardware should
|
|
||||||
guarantee that the device and the CPU can access the data
|
|
||||||
in parallel and will see updates made by each other without any
|
|
||||||
explicit software flushing.
|
|
||||||
|
|
||||||
Think of "consistent" as "synchronous" or "coherent".
|
|
||||||
|
|
||||||
The current default is to return consistent memory in the low 32
|
|
||||||
bits of the PCI bus space. However, for future compatibility you
|
|
||||||
should set the consistent mask even if this default is fine for your
|
|
||||||
driver.
|
|
||||||
|
|
||||||
Good examples of what to use consistent mappings for are:
|
|
||||||
|
|
||||||
- Network card DMA ring descriptors.
|
|
||||||
- SCSI adapter mailbox command data structures.
|
|
||||||
- Device firmware microcode executed out of
|
|
||||||
main memory.
|
|
||||||
|
|
||||||
The invariant these examples all require is that any CPU store
|
|
||||||
to memory is immediately visible to the device, and vice
|
|
||||||
versa. Consistent mappings guarantee this.
|
|
||||||
|
|
||||||
IMPORTANT: Consistent DMA memory does not preclude the usage of
|
|
||||||
proper memory barriers. The CPU may reorder stores to
|
|
||||||
consistent memory just as it may normal memory. Example:
|
|
||||||
if it is important for the device to see the first word
|
|
||||||
of a descriptor updated before the second, you must do
|
|
||||||
something like:
|
|
||||||
|
|
||||||
desc->word0 = address;
|
|
||||||
wmb();
|
|
||||||
desc->word1 = DESC_VALID;
|
|
||||||
|
|
||||||
in order to get correct behavior on all platforms.
|
|
||||||
|
|
||||||
Also, on some platforms your driver may need to flush CPU write
|
|
||||||
buffers in much the same way as it needs to flush write buffers
|
|
||||||
found in PCI bridges (such as by reading a register's value
|
|
||||||
after writing it).
|
|
||||||
|
|
||||||
- Streaming DMA mappings which are usually mapped for one DMA transfer,
|
|
||||||
unmapped right after it (unless you use pci_dma_sync_* below) and for which
|
|
||||||
hardware can optimize for sequential accesses.
|
|
||||||
|
|
||||||
This of "streaming" as "asynchronous" or "outside the coherency
|
|
||||||
domain".
|
|
||||||
|
|
||||||
Good examples of what to use streaming mappings for are:
|
|
||||||
|
|
||||||
- Networking buffers transmitted/received by a device.
|
|
||||||
- Filesystem buffers written/read by a SCSI device.
|
|
||||||
|
|
||||||
The interfaces for using this type of mapping were designed in
|
|
||||||
such a way that an implementation can make whatever performance
|
|
||||||
optimizations the hardware allows. To this end, when using
|
|
||||||
such mappings you must be explicit about what you want to happen.
|
|
||||||
|
|
||||||
Neither type of DMA mapping has alignment restrictions that come
|
|
||||||
from PCI, although some devices may have such restrictions.
|
|
||||||
Also, systems with caches that aren't DMA-coherent will work better
|
|
||||||
when the underlying buffers don't share cache lines with other data.
|
|
||||||
|
|
||||||
|
|
||||||
Using Consistent DMA mappings.
|
|
||||||
|
|
||||||
To allocate and map large (PAGE_SIZE or so) consistent DMA regions,
|
|
||||||
you should do:
|
|
||||||
|
|
||||||
dma_addr_t dma_handle;
|
|
||||||
|
|
||||||
cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
|
|
||||||
|
|
||||||
where pdev is a struct pci_dev *. This may be called in interrupt context.
|
|
||||||
You should use dma_alloc_coherent (see DMA-API.txt) for buses
|
|
||||||
where devices don't have struct pci_dev (like ISA, EISA).
|
|
||||||
|
|
||||||
This argument is needed because the DMA translations may be bus
|
|
||||||
specific (and often is private to the bus which the device is attached
|
|
||||||
to).
|
|
||||||
|
|
||||||
Size is the length of the region you want to allocate, in bytes.
|
|
||||||
|
|
||||||
This routine will allocate RAM for that region, so it acts similarly to
|
|
||||||
__get_free_pages (but takes size instead of a page order). If your
|
|
||||||
driver needs regions sized smaller than a page, you may prefer using
|
|
||||||
the pci_pool interface, described below.
|
|
||||||
|
|
||||||
The consistent DMA mapping interfaces, for non-NULL pdev, will by
|
|
||||||
default return a DMA address which is SAC (Single Address Cycle)
|
|
||||||
addressable. Even if the device indicates (via PCI dma mask) that it
|
|
||||||
may address the upper 32-bits and thus perform DAC cycles, consistent
|
|
||||||
allocation will only return > 32-bit PCI addresses for DMA if the
|
|
||||||
consistent dma mask has been explicitly changed via
|
|
||||||
pci_set_consistent_dma_mask(). This is true of the pci_pool interface
|
|
||||||
as well.
|
|
||||||
|
|
||||||
pci_alloc_consistent returns two values: the virtual address which you
|
|
||||||
can use to access it from the CPU and dma_handle which you pass to the
|
|
||||||
card.
|
|
||||||
|
|
||||||
The cpu return address and the DMA bus master address are both
|
|
||||||
guaranteed to be aligned to the smallest PAGE_SIZE order which
|
|
||||||
is greater than or equal to the requested size. This invariant
|
|
||||||
exists (for example) to guarantee that if you allocate a chunk
|
|
||||||
which is smaller than or equal to 64 kilobytes, the extent of the
|
|
||||||
buffer you receive will not cross a 64K boundary.
|
|
||||||
|
|
||||||
To unmap and free such a DMA region, you call:
|
|
||||||
|
|
||||||
pci_free_consistent(pdev, size, cpu_addr, dma_handle);
|
|
||||||
|
|
||||||
where pdev, size are the same as in the above call and cpu_addr and
|
|
||||||
dma_handle are the values pci_alloc_consistent returned to you.
|
|
||||||
This function may not be called in interrupt context.
|
|
||||||
|
|
||||||
If your driver needs lots of smaller memory regions, you can write
|
|
||||||
custom code to subdivide pages returned by pci_alloc_consistent,
|
|
||||||
or you can use the pci_pool API to do that. A pci_pool is like
|
|
||||||
a kmem_cache, but it uses pci_alloc_consistent not __get_free_pages.
|
|
||||||
Also, it understands common hardware constraints for alignment,
|
|
||||||
like queue heads needing to be aligned on N byte boundaries.
|
|
||||||
|
|
||||||
Create a pci_pool like this:
|
|
||||||
|
|
||||||
struct pci_pool *pool;
|
|
||||||
|
|
||||||
pool = pci_pool_create(name, pdev, size, align, alloc);
|
|
||||||
|
|
||||||
The "name" is for diagnostics (like a kmem_cache name); pdev and size
|
|
||||||
are as above. The device's hardware alignment requirement for this
|
|
||||||
type of data is "align" (which is expressed in bytes, and must be a
|
|
||||||
power of two). If your device has no boundary crossing restrictions,
|
|
||||||
pass 0 for alloc; passing 4096 says memory allocated from this pool
|
|
||||||
must not cross 4KByte boundaries (but at that time it may be better to
|
|
||||||
go for pci_alloc_consistent directly instead).
|
|
||||||
|
|
||||||
Allocate memory from a pci pool like this:
|
|
||||||
|
|
||||||
cpu_addr = pci_pool_alloc(pool, flags, &dma_handle);
|
|
||||||
|
|
||||||
flags are SLAB_KERNEL if blocking is permitted (not in_interrupt nor
|
|
||||||
holding SMP locks), SLAB_ATOMIC otherwise. Like pci_alloc_consistent,
|
|
||||||
this returns two values, cpu_addr and dma_handle.
|
|
||||||
|
|
||||||
Free memory that was allocated from a pci_pool like this:
|
|
||||||
|
|
||||||
pci_pool_free(pool, cpu_addr, dma_handle);
|
|
||||||
|
|
||||||
where pool is what you passed to pci_pool_alloc, and cpu_addr and
|
|
||||||
dma_handle are the values pci_pool_alloc returned. This function
|
|
||||||
may be called in interrupt context.
|
|
||||||
|
|
||||||
Destroy a pci_pool by calling:
|
|
||||||
|
|
||||||
pci_pool_destroy(pool);
|
|
||||||
|
|
||||||
Make sure you've called pci_pool_free for all memory allocated
|
|
||||||
from a pool before you destroy the pool. This function may not
|
|
||||||
be called in interrupt context.
|
|
||||||
|
|
||||||
DMA Direction
|
|
||||||
|
|
||||||
The interfaces described in subsequent portions of this document
|
|
||||||
take a DMA direction argument, which is an integer and takes on
|
|
||||||
one of the following values:
|
|
||||||
|
|
||||||
PCI_DMA_BIDIRECTIONAL
|
|
||||||
PCI_DMA_TODEVICE
|
|
||||||
PCI_DMA_FROMDEVICE
|
|
||||||
PCI_DMA_NONE
|
|
||||||
|
|
||||||
One should provide the exact DMA direction if you know it.
|
|
||||||
|
|
||||||
PCI_DMA_TODEVICE means "from main memory to the PCI device"
|
|
||||||
PCI_DMA_FROMDEVICE means "from the PCI device to main memory"
|
|
||||||
It is the direction in which the data moves during the DMA
|
|
||||||
transfer.
|
|
||||||
|
|
||||||
You are _strongly_ encouraged to specify this as precisely
|
|
||||||
as you possibly can.
|
|
||||||
|
|
||||||
If you absolutely cannot know the direction of the DMA transfer,
|
|
||||||
specify PCI_DMA_BIDIRECTIONAL. It means that the DMA can go in
|
|
||||||
either direction. The platform guarantees that you may legally
|
|
||||||
specify this, and that it will work, but this may be at the
|
|
||||||
cost of performance for example.
|
|
||||||
|
|
||||||
The value PCI_DMA_NONE is to be used for debugging. One can
|
|
||||||
hold this in a data structure before you come to know the
|
|
||||||
precise direction, and this will help catch cases where your
|
|
||||||
direction tracking logic has failed to set things up properly.
|
|
||||||
|
|
||||||
Another advantage of specifying this value precisely (outside of
|
|
||||||
potential platform-specific optimizations of such) is for debugging.
|
|
||||||
Some platforms actually have a write permission boolean which DMA
|
|
||||||
mappings can be marked with, much like page protections in the user
|
|
||||||
program address space. Such platforms can and do report errors in the
|
|
||||||
kernel logs when the PCI controller hardware detects violation of the
|
|
||||||
permission setting.
|
|
||||||
|
|
||||||
Only streaming mappings specify a direction, consistent mappings
|
|
||||||
implicitly have a direction attribute setting of
|
|
||||||
PCI_DMA_BIDIRECTIONAL.
|
|
||||||
|
|
||||||
The SCSI subsystem tells you the direction to use in the
|
|
||||||
'sc_data_direction' member of the SCSI command your driver is
|
|
||||||
working on.
|
|
||||||
|
|
||||||
For Networking drivers, it's a rather simple affair. For transmit
|
|
||||||
packets, map/unmap them with the PCI_DMA_TODEVICE direction
|
|
||||||
specifier. For receive packets, just the opposite, map/unmap them
|
|
||||||
with the PCI_DMA_FROMDEVICE direction specifier.
|
|
||||||
|
|
||||||
Using Streaming DMA mappings
|
|
||||||
|
|
||||||
The streaming DMA mapping routines can be called from interrupt
|
|
||||||
context. There are two versions of each map/unmap, one which will
|
|
||||||
map/unmap a single memory region, and one which will map/unmap a
|
|
||||||
scatterlist.
|
|
||||||
|
|
||||||
To map a single region, you do:
|
|
||||||
|
|
||||||
struct pci_dev *pdev = mydev->pdev;
|
|
||||||
dma_addr_t dma_handle;
|
|
||||||
void *addr = buffer->ptr;
|
|
||||||
size_t size = buffer->len;
|
|
||||||
|
|
||||||
dma_handle = pci_map_single(pdev, addr, size, direction);
|
|
||||||
|
|
||||||
and to unmap it:
|
|
||||||
|
|
||||||
pci_unmap_single(pdev, dma_handle, size, direction);
|
|
||||||
|
|
||||||
You should call pci_unmap_single when the DMA activity is finished, e.g.
|
|
||||||
from the interrupt which told you that the DMA transfer is done.
|
|
||||||
|
|
||||||
Using cpu pointers like this for single mappings has a disadvantage,
|
|
||||||
you cannot reference HIGHMEM memory in this way. Thus, there is a
|
|
||||||
map/unmap interface pair akin to pci_{map,unmap}_single. These
|
|
||||||
interfaces deal with page/offset pairs instead of cpu pointers.
|
|
||||||
Specifically:
|
|
||||||
|
|
||||||
struct pci_dev *pdev = mydev->pdev;
|
|
||||||
dma_addr_t dma_handle;
|
|
||||||
struct page *page = buffer->page;
|
|
||||||
unsigned long offset = buffer->offset;
|
|
||||||
size_t size = buffer->len;
|
|
||||||
|
|
||||||
dma_handle = pci_map_page(pdev, page, offset, size, direction);
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
pci_unmap_page(pdev, dma_handle, size, direction);
|
|
||||||
|
|
||||||
Here, "offset" means byte offset within the given page.
|
|
||||||
|
|
||||||
With scatterlists, you map a region gathered from several regions by:
|
|
||||||
|
|
||||||
int i, count = pci_map_sg(pdev, sglist, nents, direction);
|
|
||||||
struct scatterlist *sg;
|
|
||||||
|
|
||||||
for_each_sg(sglist, sg, count, i) {
|
|
||||||
hw_address[i] = sg_dma_address(sg);
|
|
||||||
hw_len[i] = sg_dma_len(sg);
|
|
||||||
}
|
|
||||||
|
|
||||||
where nents is the number of entries in the sglist.
|
|
||||||
|
|
||||||
The implementation is free to merge several consecutive sglist entries
|
|
||||||
into one (e.g. if DMA mapping is done with PAGE_SIZE granularity, any
|
|
||||||
consecutive sglist entries can be merged into one provided the first one
|
|
||||||
ends and the second one starts on a page boundary - in fact this is a huge
|
|
||||||
advantage for cards which either cannot do scatter-gather or have very
|
|
||||||
limited number of scatter-gather entries) and returns the actual number
|
|
||||||
of sg entries it mapped them to. On failure 0 is returned.
|
|
||||||
|
|
||||||
Then you should loop count times (note: this can be less than nents times)
|
|
||||||
and use sg_dma_address() and sg_dma_len() macros where you previously
|
|
||||||
accessed sg->address and sg->length as shown above.
|
|
||||||
|
|
||||||
To unmap a scatterlist, just call:
|
|
||||||
|
|
||||||
pci_unmap_sg(pdev, sglist, nents, direction);
|
|
||||||
|
|
||||||
Again, make sure DMA activity has already finished.
|
|
||||||
|
|
||||||
PLEASE NOTE: The 'nents' argument to the pci_unmap_sg call must be
|
|
||||||
the _same_ one you passed into the pci_map_sg call,
|
|
||||||
it should _NOT_ be the 'count' value _returned_ from the
|
|
||||||
pci_map_sg call.
|
|
||||||
|
|
||||||
Every pci_map_{single,sg} call should have its pci_unmap_{single,sg}
|
|
||||||
counterpart, because the bus address space is a shared resource (although
|
|
||||||
in some ports the mapping is per each BUS so less devices contend for the
|
|
||||||
same bus address space) and you could render the machine unusable by eating
|
|
||||||
all bus addresses.
|
|
||||||
|
|
||||||
If you need to use the same streaming DMA region multiple times and touch
|
|
||||||
the data in between the DMA transfers, the buffer needs to be synced
|
|
||||||
properly in order for the cpu and device to see the most uptodate and
|
|
||||||
correct copy of the DMA buffer.
|
|
||||||
|
|
||||||
So, firstly, just map it with pci_map_{single,sg}, and after each DMA
|
|
||||||
transfer call either:
|
|
||||||
|
|
||||||
pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
|
|
||||||
|
|
||||||
or:
|
|
||||||
|
|
||||||
pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
|
|
||||||
|
|
||||||
as appropriate.
|
|
||||||
|
|
||||||
Then, if you wish to let the device get at the DMA area again,
|
|
||||||
finish accessing the data with the cpu, and then before actually
|
|
||||||
giving the buffer to the hardware call either:
|
|
||||||
|
|
||||||
pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
|
|
||||||
|
|
||||||
or:
|
|
||||||
|
|
||||||
pci_dma_sync_sg_for_device(dev, sglist, nents, direction);
|
|
||||||
|
|
||||||
as appropriate.
|
|
||||||
|
|
||||||
After the last DMA transfer call one of the DMA unmap routines
|
|
||||||
pci_unmap_{single,sg}. If you don't touch the data from the first pci_map_*
|
|
||||||
call till pci_unmap_*, then you don't have to call the pci_dma_sync_*
|
|
||||||
routines at all.
|
|
||||||
|
|
||||||
Here is pseudo code which shows a situation in which you would need
|
|
||||||
to use the pci_dma_sync_*() interfaces.
|
|
||||||
|
|
||||||
my_card_setup_receive_buffer(struct my_card *cp, char *buffer, int len)
|
|
||||||
{
|
|
||||||
dma_addr_t mapping;
|
|
||||||
|
|
||||||
mapping = pci_map_single(cp->pdev, buffer, len, PCI_DMA_FROMDEVICE);
|
|
||||||
|
|
||||||
cp->rx_buf = buffer;
|
|
||||||
cp->rx_len = len;
|
|
||||||
cp->rx_dma = mapping;
|
|
||||||
|
|
||||||
give_rx_buf_to_card(cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
my_card_interrupt_handler(int irq, void *devid, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
struct my_card *cp = devid;
|
|
||||||
|
|
||||||
...
|
|
||||||
if (read_card_status(cp) == RX_BUF_TRANSFERRED) {
|
|
||||||
struct my_card_header *hp;
|
|
||||||
|
|
||||||
/* Examine the header to see if we wish
|
|
||||||
* to accept the data. But synchronize
|
|
||||||
* the DMA transfer with the CPU first
|
|
||||||
* so that we see updated contents.
|
|
||||||
*/
|
|
||||||
pci_dma_sync_single_for_cpu(cp->pdev, cp->rx_dma,
|
|
||||||
cp->rx_len,
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
|
|
||||||
/* Now it is safe to examine the buffer. */
|
|
||||||
hp = (struct my_card_header *) cp->rx_buf;
|
|
||||||
if (header_is_ok(hp)) {
|
|
||||||
pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len,
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
pass_to_upper_layers(cp->rx_buf);
|
|
||||||
make_and_setup_new_rx_buf(cp);
|
|
||||||
} else {
|
|
||||||
/* Just sync the buffer and give it back
|
|
||||||
* to the card.
|
|
||||||
*/
|
|
||||||
pci_dma_sync_single_for_device(cp->pdev,
|
|
||||||
cp->rx_dma,
|
|
||||||
cp->rx_len,
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
give_rx_buf_to_card(cp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Drivers converted fully to this interface should not use virt_to_bus any
|
|
||||||
longer, nor should they use bus_to_virt. Some drivers have to be changed a
|
|
||||||
little bit, because there is no longer an equivalent to bus_to_virt in the
|
|
||||||
dynamic DMA mapping scheme - you have to always store the DMA addresses
|
|
||||||
returned by the pci_alloc_consistent, pci_pool_alloc, and pci_map_single
|
|
||||||
calls (pci_map_sg stores them in the scatterlist itself if the platform
|
|
||||||
supports dynamic DMA mapping in hardware) in your driver structures and/or
|
|
||||||
in the card registers.
|
|
||||||
|
|
||||||
All PCI drivers should be using these interfaces with no exceptions.
|
|
||||||
It is planned to completely remove virt_to_bus() and bus_to_virt() as
|
|
||||||
they are entirely deprecated. Some ports already do not provide these
|
|
||||||
as it is impossible to correctly support them.
|
|
||||||
|
|
||||||
Optimizing Unmap State Space Consumption
|
|
||||||
|
|
||||||
On many platforms, pci_unmap_{single,page}() is simply a nop.
|
|
||||||
Therefore, keeping track of the mapping address and length is a waste
|
|
||||||
of space. Instead of filling your drivers up with ifdefs and the like
|
|
||||||
to "work around" this (which would defeat the whole purpose of a
|
|
||||||
portable API) the following facilities are provided.
|
|
||||||
|
|
||||||
Actually, instead of describing the macros one by one, we'll
|
|
||||||
transform some example code.
|
|
||||||
|
|
||||||
1) Use DECLARE_PCI_UNMAP_{ADDR,LEN} in state saving structures.
|
|
||||||
Example, before:
|
|
||||||
|
|
||||||
struct ring_state {
|
|
||||||
struct sk_buff *skb;
|
|
||||||
dma_addr_t mapping;
|
|
||||||
__u32 len;
|
|
||||||
};
|
|
||||||
|
|
||||||
after:
|
|
||||||
|
|
||||||
struct ring_state {
|
|
||||||
struct sk_buff *skb;
|
|
||||||
DECLARE_PCI_UNMAP_ADDR(mapping)
|
|
||||||
DECLARE_PCI_UNMAP_LEN(len)
|
|
||||||
};
|
|
||||||
|
|
||||||
NOTE: DO NOT put a semicolon at the end of the DECLARE_*()
|
|
||||||
macro.
|
|
||||||
|
|
||||||
2) Use pci_unmap_{addr,len}_set to set these values.
|
|
||||||
Example, before:
|
|
||||||
|
|
||||||
ringp->mapping = FOO;
|
|
||||||
ringp->len = BAR;
|
|
||||||
|
|
||||||
after:
|
|
||||||
|
|
||||||
pci_unmap_addr_set(ringp, mapping, FOO);
|
|
||||||
pci_unmap_len_set(ringp, len, BAR);
|
|
||||||
|
|
||||||
3) Use pci_unmap_{addr,len} to access these values.
|
|
||||||
Example, before:
|
|
||||||
|
|
||||||
pci_unmap_single(pdev, ringp->mapping, ringp->len,
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
|
|
||||||
after:
|
|
||||||
|
|
||||||
pci_unmap_single(pdev,
|
|
||||||
pci_unmap_addr(ringp, mapping),
|
|
||||||
pci_unmap_len(ringp, len),
|
|
||||||
PCI_DMA_FROMDEVICE);
|
|
||||||
|
|
||||||
It really should be self-explanatory. We treat the ADDR and LEN
|
|
||||||
separately, because it is possible for an implementation to only
|
|
||||||
need the address in order to perform the unmap operation.
|
|
||||||
|
|
||||||
Platform Issues
|
|
||||||
|
|
||||||
If you are just writing drivers for Linux and do not maintain
|
|
||||||
an architecture port for the kernel, you can safely skip down
|
|
||||||
to "Closing".
|
|
||||||
|
|
||||||
1) Struct scatterlist requirements.
|
|
||||||
|
|
||||||
Struct scatterlist must contain, at a minimum, the following
|
|
||||||
members:
|
|
||||||
|
|
||||||
struct page *page;
|
|
||||||
unsigned int offset;
|
|
||||||
unsigned int length;
|
|
||||||
|
|
||||||
The base address is specified by a "page+offset" pair.
|
|
||||||
|
|
||||||
Previous versions of struct scatterlist contained a "void *address"
|
|
||||||
field that was sometimes used instead of page+offset. As of Linux
|
|
||||||
2.5., page+offset is always used, and the "address" field has been
|
|
||||||
deleted.
|
|
||||||
|
|
||||||
2) More to come...
|
|
||||||
|
|
||||||
Handling Errors
|
|
||||||
|
|
||||||
DMA address space is limited on some architectures and an allocation
|
|
||||||
failure can be determined by:
|
|
||||||
|
|
||||||
- checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0
|
|
||||||
|
|
||||||
- checking the returned dma_addr_t of pci_map_single and pci_map_page
|
|
||||||
by using pci_dma_mapping_error():
|
|
||||||
|
|
||||||
dma_addr_t dma_handle;
|
|
||||||
|
|
||||||
dma_handle = pci_map_single(pdev, addr, size, direction);
|
|
||||||
if (pci_dma_mapping_error(pdev, dma_handle)) {
|
|
||||||
/*
|
|
||||||
* reduce current DMA mapping usage,
|
|
||||||
* delay and try again later or
|
|
||||||
* reset driver.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
Closing
|
|
||||||
|
|
||||||
This document, and the API itself, would not be in it's current
|
|
||||||
form without the feedback and suggestions from numerous individuals.
|
|
||||||
We would like to specifically mention, in no particular order, the
|
|
||||||
following people:
|
|
||||||
|
|
||||||
Russell King <rmk@arm.linux.org.uk>
|
|
||||||
Leo Dagum <dagum@barrel.engr.sgi.com>
|
|
||||||
Ralf Baechle <ralf@oss.sgi.com>
|
|
||||||
Grant Grundler <grundler@cup.hp.com>
|
|
||||||
Jay Estabrook <Jay.Estabrook@compaq.com>
|
|
||||||
Thomas Sailer <sailer@ife.ee.ethz.ch>
|
|
||||||
Andrea Arcangeli <andrea@suse.de>
|
|
||||||
Jens Axboe <jens.axboe@oracle.com>
|
|
||||||
David Mosberger-Tang <davidm@hpl.hp.com>
|
|
@@ -216,7 +216,7 @@ The driver should return one of the following result codes:
|
|||||||
|
|
||||||
- PCI_ERS_RESULT_NEED_RESET
|
- PCI_ERS_RESULT_NEED_RESET
|
||||||
Driver returns this if it thinks the device is not
|
Driver returns this if it thinks the device is not
|
||||||
recoverable in it's current state and it needs a slot
|
recoverable in its current state and it needs a slot
|
||||||
reset to proceed.
|
reset to proceed.
|
||||||
|
|
||||||
- PCI_ERS_RESULT_DISCONNECT
|
- PCI_ERS_RESULT_DISCONNECT
|
||||||
@@ -241,7 +241,7 @@ in working condition.
|
|||||||
|
|
||||||
The driver is not supposed to restart normal driver I/O operations
|
The driver is not supposed to restart normal driver I/O operations
|
||||||
at this point. It should limit itself to "probing" the device to
|
at this point. It should limit itself to "probing" the device to
|
||||||
check it's recoverability status. If all is right, then the platform
|
check its recoverability status. If all is right, then the platform
|
||||||
will call resume() once all drivers have ack'd link_reset().
|
will call resume() once all drivers have ack'd link_reset().
|
||||||
|
|
||||||
Result codes:
|
Result codes:
|
||||||
|
@@ -581,7 +581,7 @@ to be handled by platform and generic code, not individual drivers.
|
|||||||
8. Vendor and device identifications
|
8. Vendor and device identifications
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
One is not not required to add new device ids to include/linux/pci_ids.h.
|
One is not required to add new device ids to include/linux/pci_ids.h.
|
||||||
Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
|
Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids.
|
||||||
|
|
||||||
PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
|
PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary
|
||||||
|
@@ -13,7 +13,7 @@ Reporting (AER) driver and provides information on how to use it, as
|
|||||||
well as how to enable the drivers of endpoint devices to conform with
|
well as how to enable the drivers of endpoint devices to conform with
|
||||||
PCI Express AER driver.
|
PCI Express AER driver.
|
||||||
|
|
||||||
1.2 Copyright <EFBFBD> Intel Corporation 2006.
|
1.2 Copyright (C) Intel Corporation 2006.
|
||||||
|
|
||||||
1.3 What is the PCI Express AER Driver?
|
1.3 What is the PCI Express AER Driver?
|
||||||
|
|
||||||
@@ -71,15 +71,11 @@ console. If it's a correctable error, it is outputed as a warning.
|
|||||||
Otherwise, it is printed as an error. So users could choose different
|
Otherwise, it is printed as an error. So users could choose different
|
||||||
log level to filter out correctable error messages.
|
log level to filter out correctable error messages.
|
||||||
|
|
||||||
Below shows an example.
|
Below shows an example:
|
||||||
+------ PCI-Express Device Error -----+
|
0000:50:00.0: PCIe Bus Error: severity=Uncorrected (Fatal), type=Transaction Layer, id=0500(Requester ID)
|
||||||
Error Severity : Uncorrected (Fatal)
|
0000:50:00.0: device [8086:0329] error status/mask=00100000/00000000
|
||||||
PCIE Bus Error type : Transaction Layer
|
0000:50:00.0: [20] Unsupported Request (First)
|
||||||
Unsupported Request : First
|
0000:50:00.0: TLP Header: 04000001 00200a03 05010000 00050100
|
||||||
Requester ID : 0500
|
|
||||||
VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
|
|
||||||
TLB Header:
|
|
||||||
04000001 00200a03 05010000 00050100
|
|
||||||
|
|
||||||
In the example, 'Requester ID' means the ID of the device who sends
|
In the example, 'Requester ID' means the ID of the device who sends
|
||||||
the error message to root port. Pls. refer to pci express specs for
|
the error message to root port. Pls. refer to pci express specs for
|
||||||
@@ -112,7 +108,7 @@ but the PCI Express link itself is fully functional. Fatal errors, on
|
|||||||
the other hand, cause the link to be unreliable.
|
the other hand, cause the link to be unreliable.
|
||||||
|
|
||||||
When AER is enabled, a PCI Express device will automatically send an
|
When AER is enabled, a PCI Express device will automatically send an
|
||||||
error message to the PCIE root port above it when the device captures
|
error message to the PCIe root port above it when the device captures
|
||||||
an error. The Root Port, upon receiving an error reporting message,
|
an error. The Root Port, upon receiving an error reporting message,
|
||||||
internally processes and logs the error message in its PCI Express
|
internally processes and logs the error message in its PCI Express
|
||||||
capability structure. Error information being logged includes storing
|
capability structure. Error information being logged includes storing
|
||||||
@@ -198,8 +194,9 @@ to reset link, AER port service driver is required to provide the
|
|||||||
function to reset link. Firstly, kernel looks for if the upstream
|
function to reset link. Firstly, kernel looks for if the upstream
|
||||||
component has an aer driver. If it has, kernel uses the reset_link
|
component has an aer driver. If it has, kernel uses the reset_link
|
||||||
callback of the aer driver. If the upstream component has no aer driver
|
callback of the aer driver. If the upstream component has no aer driver
|
||||||
and the port is downstream port, we will use the aer driver of the
|
and the port is downstream port, we will perform a hot reset as the
|
||||||
root port who reports the AER error. As for upstream ports,
|
default by setting the Secondary Bus Reset bit of the Bridge Control
|
||||||
|
register associated with the downstream port. As for upstream ports,
|
||||||
they should provide their own aer service drivers with reset_link
|
they should provide their own aer service drivers with reset_link
|
||||||
function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
|
function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
|
||||||
reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
|
reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
|
||||||
@@ -253,11 +250,11 @@ cleanup uncorrectable status register. Pls. refer to section 3.3.
|
|||||||
|
|
||||||
4. Software error injection
|
4. Software error injection
|
||||||
|
|
||||||
Debugging PCIE AER error recovery code is quite difficult because it
|
Debugging PCIe AER error recovery code is quite difficult because it
|
||||||
is hard to trigger real hardware errors. Software based error
|
is hard to trigger real hardware errors. Software based error
|
||||||
injection can be used to fake various kinds of PCIE errors.
|
injection can be used to fake various kinds of PCIe errors.
|
||||||
|
|
||||||
First you should enable PCIE AER software error injection in kernel
|
First you should enable PCIe AER software error injection in kernel
|
||||||
configuration, that is, following item should be in your .config.
|
configuration, that is, following item should be in your .config.
|
||||||
|
|
||||||
CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
|
CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
|
||||||
|
@@ -6,16 +6,22 @@ checklist.txt
|
|||||||
- Review Checklist for RCU Patches
|
- Review Checklist for RCU Patches
|
||||||
listRCU.txt
|
listRCU.txt
|
||||||
- Using RCU to Protect Read-Mostly Linked Lists
|
- Using RCU to Protect Read-Mostly Linked Lists
|
||||||
|
lockdep.txt
|
||||||
|
- RCU and lockdep checking
|
||||||
NMI-RCU.txt
|
NMI-RCU.txt
|
||||||
- Using RCU to Protect Dynamic NMI Handlers
|
- Using RCU to Protect Dynamic NMI Handlers
|
||||||
|
rcubarrier.txt
|
||||||
|
- RCU and Unloadable Modules
|
||||||
|
rculist_nulls.txt
|
||||||
|
- RCU list primitives for use with SLAB_DESTROY_BY_RCU
|
||||||
rcuref.txt
|
rcuref.txt
|
||||||
- Reference-count design for elements of lists/arrays protected by RCU
|
- Reference-count design for elements of lists/arrays protected by RCU
|
||||||
rcu.txt
|
rcu.txt
|
||||||
- RCU Concepts
|
- RCU Concepts
|
||||||
rcubarrier.txt
|
|
||||||
- Unloading modules that use RCU callbacks
|
|
||||||
RTFP.txt
|
RTFP.txt
|
||||||
- List of RCU papers (bibliography) going back to 1980.
|
- List of RCU papers (bibliography) going back to 1980.
|
||||||
|
stallwarn.txt
|
||||||
|
- RCU CPU stall warnings (CONFIG_RCU_CPU_STALL_DETECTOR)
|
||||||
torture.txt
|
torture.txt
|
||||||
- RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST)
|
- RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST)
|
||||||
trace.txt
|
trace.txt
|
||||||
|
@@ -34,7 +34,7 @@ NMI handler.
|
|||||||
cpu = smp_processor_id();
|
cpu = smp_processor_id();
|
||||||
++nmi_count(cpu);
|
++nmi_count(cpu);
|
||||||
|
|
||||||
if (!rcu_dereference(nmi_callback)(regs, cpu))
|
if (!rcu_dereference_sched(nmi_callback)(regs, cpu))
|
||||||
default_do_nmi(regs);
|
default_do_nmi(regs);
|
||||||
|
|
||||||
nmi_exit();
|
nmi_exit();
|
||||||
@@ -47,12 +47,13 @@ function pointer. If this handler returns zero, do_nmi() invokes the
|
|||||||
default_do_nmi() function to handle a machine-specific NMI. Finally,
|
default_do_nmi() function to handle a machine-specific NMI. Finally,
|
||||||
preemption is restored.
|
preemption is restored.
|
||||||
|
|
||||||
Strictly speaking, rcu_dereference() is not needed, since this code runs
|
In theory, rcu_dereference_sched() is not needed, since this code runs
|
||||||
only on i386, which does not need rcu_dereference() anyway. However,
|
only on i386, which in theory does not need rcu_dereference_sched()
|
||||||
it is a good documentation aid, particularly for anyone attempting to
|
anyway. However, in practice it is a good documentation aid, particularly
|
||||||
do something similar on Alpha.
|
for anyone attempting to do something similar on Alpha or on systems
|
||||||
|
with aggressive optimizing compilers.
|
||||||
|
|
||||||
Quick Quiz: Why might the rcu_dereference() be necessary on Alpha,
|
Quick Quiz: Why might the rcu_dereference_sched() be necessary on Alpha,
|
||||||
given that the code referenced by the pointer is read-only?
|
given that the code referenced by the pointer is read-only?
|
||||||
|
|
||||||
|
|
||||||
@@ -99,17 +100,21 @@ invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
|
|||||||
|
|
||||||
Answer to Quick Quiz
|
Answer to Quick Quiz
|
||||||
|
|
||||||
Why might the rcu_dereference() be necessary on Alpha, given
|
Why might the rcu_dereference_sched() be necessary on Alpha, given
|
||||||
that the code referenced by the pointer is read-only?
|
that the code referenced by the pointer is read-only?
|
||||||
|
|
||||||
Answer: The caller to set_nmi_callback() might well have
|
Answer: The caller to set_nmi_callback() might well have
|
||||||
initialized some data that is to be used by the
|
initialized some data that is to be used by the new NMI
|
||||||
new NMI handler. In this case, the rcu_dereference()
|
handler. In this case, the rcu_dereference_sched() would
|
||||||
would be needed, because otherwise a CPU that received
|
be needed, because otherwise a CPU that received an NMI
|
||||||
an NMI just after the new handler was set might see
|
just after the new handler was set might see the pointer
|
||||||
the pointer to the new NMI handler, but the old
|
to the new NMI handler, but the old pre-initialized
|
||||||
pre-initialized version of the handler's data.
|
version of the handler's data.
|
||||||
|
|
||||||
More important, the rcu_dereference() makes it clear
|
This same sad story can happen on other CPUs when using
|
||||||
to someone reading the code that the pointer is being
|
a compiler with aggressive pointer-value speculation
|
||||||
protected by RCU.
|
optimizations.
|
||||||
|
|
||||||
|
More important, the rcu_dereference_sched() makes it
|
||||||
|
clear to someone reading the code that the pointer is
|
||||||
|
being protected by RCU-sched.
|
||||||
|
@@ -25,10 +25,10 @@ to be referencing the data structure. However, this mechanism was not
|
|||||||
optimized for modern computer systems, which is not surprising given
|
optimized for modern computer systems, which is not surprising given
|
||||||
that these overheads were not so expensive in the mid-80s. Nonetheless,
|
that these overheads were not so expensive in the mid-80s. Nonetheless,
|
||||||
passive serialization appears to be the first deferred-destruction
|
passive serialization appears to be the first deferred-destruction
|
||||||
mechanism to be used in production. Furthermore, the relevant patent has
|
mechanism to be used in production. Furthermore, the relevant patent
|
||||||
lapsed, so this approach may be used in non-GPL software, if desired.
|
has lapsed, so this approach may be used in non-GPL software, if desired.
|
||||||
(In contrast, use of RCU is permitted only in software licensed under
|
(In contrast, implementation of RCU is permitted only in software licensed
|
||||||
GPL. Sorry!!!)
|
under either GPL or LGPL. Sorry!!!)
|
||||||
|
|
||||||
In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
|
In 1990, Pugh [Pugh90] noted that explicitly tracking which threads
|
||||||
were reading a given data structure permitted deferred free to operate
|
were reading a given data structure permitted deferred free to operate
|
||||||
@@ -150,6 +150,18 @@ preemptible RCU [PaulEMcKenney2007PreemptibleRCU], and the three-part
|
|||||||
LWN "What is RCU?" series [PaulEMcKenney2007WhatIsRCUFundamentally,
|
LWN "What is RCU?" series [PaulEMcKenney2007WhatIsRCUFundamentally,
|
||||||
PaulEMcKenney2008WhatIsRCUUsage, and PaulEMcKenney2008WhatIsRCUAPI].
|
PaulEMcKenney2008WhatIsRCUUsage, and PaulEMcKenney2008WhatIsRCUAPI].
|
||||||
|
|
||||||
|
2008 saw a journal paper on real-time RCU [DinakarGuniguntala2008IBMSysJ],
|
||||||
|
a history of how Linux changed RCU more than RCU changed Linux
|
||||||
|
[PaulEMcKenney2008RCUOSR], and a design overview of hierarchical RCU
|
||||||
|
[PaulEMcKenney2008HierarchicalRCU].
|
||||||
|
|
||||||
|
2009 introduced user-level RCU algorithms [PaulEMcKenney2009MaliciousURCU],
|
||||||
|
which Mathieu Desnoyers is now maintaining [MathieuDesnoyers2009URCU]
|
||||||
|
[MathieuDesnoyersPhD]. TINY_RCU [PaulEMcKenney2009BloatWatchRCU] made
|
||||||
|
its appearance, as did expedited RCU [PaulEMcKenney2009expeditedRCU].
|
||||||
|
The problem of resizeable RCU-protected hash tables may now be on a path
|
||||||
|
to a solution [JoshTriplett2009RPHash].
|
||||||
|
|
||||||
Bibtex Entries
|
Bibtex Entries
|
||||||
|
|
||||||
@article{Kung80
|
@article{Kung80
|
||||||
@@ -594,7 +606,7 @@ Suparna Bhattacharya"
|
|||||||
,Year="2006"
|
,Year="2006"
|
||||||
,pages="v2 123-138"
|
,pages="v2 123-138"
|
||||||
,note="Available:
|
,note="Available:
|
||||||
\url{http://www.linuxsymposium.org/2006/view_abstract.php?content_key=184}
|
\url{http://www.linuxsymposium.org/2006/index_2006.php}
|
||||||
\url{http://www.rdrop.com/users/paulmck/RCU/OLSrtRCU.2006.08.11a.pdf}
|
\url{http://www.rdrop.com/users/paulmck/RCU/OLSrtRCU.2006.08.11a.pdf}
|
||||||
[Viewed January 1, 2007]"
|
[Viewed January 1, 2007]"
|
||||||
,annotation="
|
,annotation="
|
||||||
@@ -730,6 +742,11 @@ Revised:
|
|||||||
"
|
"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# "What is RCU?" LWN series.
|
||||||
|
#
|
||||||
|
########################################################################
|
||||||
|
|
||||||
@article{DinakarGuniguntala2008IBMSysJ
|
@article{DinakarGuniguntala2008IBMSysJ
|
||||||
,author="D. Guniguntala and P. E. McKenney and J. Triplett and J. Walpole"
|
,author="D. Guniguntala and P. E. McKenney and J. Triplett and J. Walpole"
|
||||||
,title="The read-copy-update mechanism for supporting real-time applications on shared-memory multiprocessor systems with {Linux}"
|
,title="The read-copy-update mechanism for supporting real-time applications on shared-memory multiprocessor systems with {Linux}"
|
||||||
@@ -820,3 +837,39 @@ Revised:
|
|||||||
Uniprocessor assumptions allow simplified RCU implementation.
|
Uniprocessor assumptions allow simplified RCU implementation.
|
||||||
"
|
"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@unpublished{PaulEMcKenney2009expeditedRCU
|
||||||
|
,Author="Paul E. McKenney"
|
||||||
|
,Title="[{PATCH} -tip 0/3] expedited 'big hammer' {RCU} grace periods"
|
||||||
|
,month="June"
|
||||||
|
,day="25"
|
||||||
|
,year="2009"
|
||||||
|
,note="Available:
|
||||||
|
\url{http://lkml.org/lkml/2009/6/25/306}
|
||||||
|
[Viewed August 16, 2009]"
|
||||||
|
,annotation="
|
||||||
|
First posting of expedited RCU to be accepted into -tip.
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
@unpublished{JoshTriplett2009RPHash
|
||||||
|
,Author="Josh Triplett"
|
||||||
|
,Title="Scalable concurrent hash tables via relativistic programming"
|
||||||
|
,month="September"
|
||||||
|
,year="2009"
|
||||||
|
,note="Linux Plumbers Conference presentation"
|
||||||
|
,annotation="
|
||||||
|
RP fun with hash tables.
|
||||||
|
"
|
||||||
|
}
|
||||||
|
|
||||||
|
@phdthesis{MathieuDesnoyersPhD
|
||||||
|
, title = "Low-Impact Operating System Tracing"
|
||||||
|
, author = "Mathieu Desnoyers"
|
||||||
|
, school = "Ecole Polytechnique de Montr\'{e}al"
|
||||||
|
, month = "December"
|
||||||
|
, year = 2009
|
||||||
|
,note="Available:
|
||||||
|
\url{http://www.lttng.org/pub/thesis/desnoyers-dissertation-2009-12.pdf}
|
||||||
|
[Viewed December 9, 2009]"
|
||||||
|
}
|
||||||
|
@@ -8,13 +8,12 @@ would cause. This list is based on experiences reviewing such patches
|
|||||||
over a rather long period of time, but improvements are always welcome!
|
over a rather long period of time, but improvements are always welcome!
|
||||||
|
|
||||||
0. Is RCU being applied to a read-mostly situation? If the data
|
0. Is RCU being applied to a read-mostly situation? If the data
|
||||||
structure is updated more than about 10% of the time, then
|
structure is updated more than about 10% of the time, then you
|
||||||
you should strongly consider some other approach, unless
|
should strongly consider some other approach, unless detailed
|
||||||
detailed performance measurements show that RCU is nonetheless
|
performance measurements show that RCU is nonetheless the right
|
||||||
the right tool for the job. Yes, you might think of RCU
|
tool for the job. Yes, RCU does reduce read-side overhead by
|
||||||
as simply cutting overhead off of the readers and imposing it
|
increasing write-side overhead, which is exactly why normal uses
|
||||||
on the writers. That is exactly why normal uses of RCU will
|
of RCU will do much more reading than updating.
|
||||||
do much more reading than updating.
|
|
||||||
|
|
||||||
Another exception is where performance is not an issue, and RCU
|
Another exception is where performance is not an issue, and RCU
|
||||||
provides a simpler implementation. An example of this situation
|
provides a simpler implementation. An example of this situation
|
||||||
@@ -35,13 +34,13 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
|
|
||||||
If you choose #b, be prepared to describe how you have handled
|
If you choose #b, be prepared to describe how you have handled
|
||||||
memory barriers on weakly ordered machines (pretty much all of
|
memory barriers on weakly ordered machines (pretty much all of
|
||||||
them -- even x86 allows reads to be reordered), and be prepared
|
them -- even x86 allows later loads to be reordered to precede
|
||||||
to explain why this added complexity is worthwhile. If you
|
earlier stores), and be prepared to explain why this added
|
||||||
choose #c, be prepared to explain how this single task does not
|
complexity is worthwhile. If you choose #c, be prepared to
|
||||||
become a major bottleneck on big multiprocessor machines (for
|
explain how this single task does not become a major bottleneck on
|
||||||
example, if the task is updating information relating to itself
|
big multiprocessor machines (for example, if the task is updating
|
||||||
that other tasks can read, there by definition can be no
|
information relating to itself that other tasks can read, there
|
||||||
bottleneck).
|
by definition can be no bottleneck).
|
||||||
|
|
||||||
2. Do the RCU read-side critical sections make proper use of
|
2. Do the RCU read-side critical sections make proper use of
|
||||||
rcu_read_lock() and friends? These primitives are needed
|
rcu_read_lock() and friends? These primitives are needed
|
||||||
@@ -51,8 +50,10 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
actuarial risk of your kernel.
|
actuarial risk of your kernel.
|
||||||
|
|
||||||
As a rough rule of thumb, any dereference of an RCU-protected
|
As a rough rule of thumb, any dereference of an RCU-protected
|
||||||
pointer must be covered by rcu_read_lock() or rcu_read_lock_bh()
|
pointer must be covered by rcu_read_lock(), rcu_read_lock_bh(),
|
||||||
or by the appropriate update-side lock.
|
rcu_read_lock_sched(), or by the appropriate update-side lock.
|
||||||
|
Disabling of preemption can serve as rcu_read_lock_sched(), but
|
||||||
|
is less readable.
|
||||||
|
|
||||||
3. Does the update code tolerate concurrent accesses?
|
3. Does the update code tolerate concurrent accesses?
|
||||||
|
|
||||||
@@ -62,25 +63,27 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
of ways to handle this concurrency, depending on the situation:
|
of ways to handle this concurrency, depending on the situation:
|
||||||
|
|
||||||
a. Use the RCU variants of the list and hlist update
|
a. Use the RCU variants of the list and hlist update
|
||||||
primitives to add, remove, and replace elements on an
|
primitives to add, remove, and replace elements on
|
||||||
RCU-protected list. Alternatively, use the RCU-protected
|
an RCU-protected list. Alternatively, use the other
|
||||||
trees that have been added to the Linux kernel.
|
RCU-protected data structures that have been added to
|
||||||
|
the Linux kernel.
|
||||||
|
|
||||||
This is almost always the best approach.
|
This is almost always the best approach.
|
||||||
|
|
||||||
b. Proceed as in (a) above, but also maintain per-element
|
b. Proceed as in (a) above, but also maintain per-element
|
||||||
locks (that are acquired by both readers and writers)
|
locks (that are acquired by both readers and writers)
|
||||||
that guard per-element state. Of course, fields that
|
that guard per-element state. Of course, fields that
|
||||||
the readers refrain from accessing can be guarded by the
|
the readers refrain from accessing can be guarded by
|
||||||
update-side lock.
|
some other lock acquired only by updaters, if desired.
|
||||||
|
|
||||||
This works quite well, also.
|
This works quite well, also.
|
||||||
|
|
||||||
c. Make updates appear atomic to readers. For example,
|
c. Make updates appear atomic to readers. For example,
|
||||||
pointer updates to properly aligned fields will appear
|
pointer updates to properly aligned fields will
|
||||||
atomic, as will individual atomic primitives. Operations
|
appear atomic, as will individual atomic primitives.
|
||||||
performed under a lock and sequences of multiple atomic
|
Sequences of perations performed under a lock will -not-
|
||||||
primitives will -not- appear to be atomic.
|
appear to be atomic to RCU readers, nor will sequences
|
||||||
|
of multiple atomic primitives.
|
||||||
|
|
||||||
This can work, but is starting to get a bit tricky.
|
This can work, but is starting to get a bit tricky.
|
||||||
|
|
||||||
@@ -98,9 +101,9 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
a new structure containing updated values.
|
a new structure containing updated values.
|
||||||
|
|
||||||
4. Weakly ordered CPUs pose special challenges. Almost all CPUs
|
4. Weakly ordered CPUs pose special challenges. Almost all CPUs
|
||||||
are weakly ordered -- even i386 CPUs allow reads to be reordered.
|
are weakly ordered -- even x86 CPUs allow later loads to be
|
||||||
RCU code must take all of the following measures to prevent
|
reordered to precede earlier stores. RCU code must take all of
|
||||||
memory-corruption problems:
|
the following measures to prevent memory-corruption problems:
|
||||||
|
|
||||||
a. Readers must maintain proper ordering of their memory
|
a. Readers must maintain proper ordering of their memory
|
||||||
accesses. The rcu_dereference() primitive ensures that
|
accesses. The rcu_dereference() primitive ensures that
|
||||||
@@ -113,14 +116,25 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
The rcu_dereference() primitive is also an excellent
|
The rcu_dereference() primitive is also an excellent
|
||||||
documentation aid, letting the person reading the code
|
documentation aid, letting the person reading the code
|
||||||
know exactly which pointers are protected by RCU.
|
know exactly which pointers are protected by RCU.
|
||||||
|
Please note that compilers can also reorder code, and
|
||||||
|
they are becoming increasingly aggressive about doing
|
||||||
|
just that. The rcu_dereference() primitive therefore
|
||||||
|
also prevents destructive compiler optimizations.
|
||||||
|
|
||||||
The rcu_dereference() primitive is used by the various
|
The rcu_dereference() primitive is used by the
|
||||||
"_rcu()" list-traversal primitives, such as the
|
various "_rcu()" list-traversal primitives, such
|
||||||
list_for_each_entry_rcu(). Note that it is perfectly
|
as the list_for_each_entry_rcu(). Note that it is
|
||||||
legal (if redundant) for update-side code to use
|
perfectly legal (if redundant) for update-side code to
|
||||||
rcu_dereference() and the "_rcu()" list-traversal
|
use rcu_dereference() and the "_rcu()" list-traversal
|
||||||
primitives. This is particularly useful in code
|
primitives. This is particularly useful in code that
|
||||||
that is common to readers and updaters.
|
is common to readers and updaters. However, lockdep
|
||||||
|
will complain if you access rcu_dereference() outside
|
||||||
|
of an RCU read-side critical section. See lockdep.txt
|
||||||
|
to learn what to do about this.
|
||||||
|
|
||||||
|
Of course, neither rcu_dereference() nor the "_rcu()"
|
||||||
|
list-traversal primitives can substitute for a good
|
||||||
|
concurrency design coordinating among multiple updaters.
|
||||||
|
|
||||||
b. If the list macros are being used, the list_add_tail_rcu()
|
b. If the list macros are being used, the list_add_tail_rcu()
|
||||||
and list_add_rcu() primitives must be used in order
|
and list_add_rcu() primitives must be used in order
|
||||||
@@ -135,11 +149,14 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
readers. Similarly, if the hlist macros are being used,
|
readers. Similarly, if the hlist macros are being used,
|
||||||
the hlist_del_rcu() primitive is required.
|
the hlist_del_rcu() primitive is required.
|
||||||
|
|
||||||
The list_replace_rcu() primitive may be used to
|
The list_replace_rcu() and hlist_replace_rcu() primitives
|
||||||
replace an old structure with a new one in an
|
may be used to replace an old structure with a new one
|
||||||
RCU-protected list.
|
in their respective types of RCU-protected lists.
|
||||||
|
|
||||||
d. Updates must ensure that initialization of a given
|
d. Rules similar to (4b) and (4c) apply to the "hlist_nulls"
|
||||||
|
type of RCU-protected linked lists.
|
||||||
|
|
||||||
|
e. Updates must ensure that initialization of a given
|
||||||
structure happens before pointers to that structure are
|
structure happens before pointers to that structure are
|
||||||
publicized. Use the rcu_assign_pointer() primitive
|
publicized. Use the rcu_assign_pointer() primitive
|
||||||
when publicizing a pointer to a structure that can
|
when publicizing a pointer to a structure that can
|
||||||
@@ -151,16 +168,31 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
it cannot block.
|
it cannot block.
|
||||||
|
|
||||||
6. Since synchronize_rcu() can block, it cannot be called from
|
6. Since synchronize_rcu() can block, it cannot be called from
|
||||||
any sort of irq context. Ditto for synchronize_sched() and
|
any sort of irq context. The same rule applies for
|
||||||
synchronize_srcu().
|
synchronize_rcu_bh(), synchronize_sched(), synchronize_srcu(),
|
||||||
|
synchronize_rcu_expedited(), synchronize_rcu_bh_expedited(),
|
||||||
|
synchronize_sched_expedite(), and synchronize_srcu_expedited().
|
||||||
|
|
||||||
7. If the updater uses call_rcu(), then the corresponding readers
|
The expedited forms of these primitives have the same semantics
|
||||||
must use rcu_read_lock() and rcu_read_unlock(). If the updater
|
as the non-expedited forms, but expediting is both expensive
|
||||||
uses call_rcu_bh(), then the corresponding readers must use
|
and unfriendly to real-time workloads. Use of the expedited
|
||||||
rcu_read_lock_bh() and rcu_read_unlock_bh(). If the updater
|
primitives should be restricted to rare configuration-change
|
||||||
uses call_rcu_sched(), then the corresponding readers must
|
operations that would not normally be undertaken while a real-time
|
||||||
disable preemption. Mixing things up will result in confusion
|
workload is running.
|
||||||
and broken kernels.
|
|
||||||
|
7. If the updater uses call_rcu() or synchronize_rcu(), then the
|
||||||
|
corresponding readers must use rcu_read_lock() and
|
||||||
|
rcu_read_unlock(). If the updater uses call_rcu_bh() or
|
||||||
|
synchronize_rcu_bh(), then the corresponding readers must
|
||||||
|
use rcu_read_lock_bh() and rcu_read_unlock_bh(). If the
|
||||||
|
updater uses call_rcu_sched() or synchronize_sched(), then
|
||||||
|
the corresponding readers must disable preemption, possibly
|
||||||
|
by calling rcu_read_lock_sched() and rcu_read_unlock_sched().
|
||||||
|
If the updater uses synchronize_srcu(), the the corresponding
|
||||||
|
readers must use srcu_read_lock() and srcu_read_unlock(),
|
||||||
|
and with the same srcu_struct. The rules for the expedited
|
||||||
|
primitives are the same as for their non-expedited counterparts.
|
||||||
|
Mixing things up will result in confusion and broken kernels.
|
||||||
|
|
||||||
One exception to this rule: rcu_read_lock() and rcu_read_unlock()
|
One exception to this rule: rcu_read_lock() and rcu_read_unlock()
|
||||||
may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
|
may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
|
||||||
@@ -212,6 +244,8 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
e. Periodically invoke synchronize_rcu(), permitting a limited
|
e. Periodically invoke synchronize_rcu(), permitting a limited
|
||||||
number of updates per grace period.
|
number of updates per grace period.
|
||||||
|
|
||||||
|
The same cautions apply to call_rcu_bh() and call_rcu_sched().
|
||||||
|
|
||||||
9. All RCU list-traversal primitives, which include
|
9. All RCU list-traversal primitives, which include
|
||||||
rcu_dereference(), list_for_each_entry_rcu(),
|
rcu_dereference(), list_for_each_entry_rcu(),
|
||||||
list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
|
list_for_each_continue_rcu(), and list_for_each_safe_rcu(),
|
||||||
@@ -219,17 +253,21 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
must be protected by appropriate update-side locks. RCU
|
must be protected by appropriate update-side locks. RCU
|
||||||
read-side critical sections are delimited by rcu_read_lock()
|
read-side critical sections are delimited by rcu_read_lock()
|
||||||
and rcu_read_unlock(), or by similar primitives such as
|
and rcu_read_unlock(), or by similar primitives such as
|
||||||
rcu_read_lock_bh() and rcu_read_unlock_bh().
|
rcu_read_lock_bh() and rcu_read_unlock_bh(), in which case
|
||||||
|
the matching rcu_dereference() primitive must be used in order
|
||||||
|
to keep lockdep happy, in this case, rcu_dereference_bh().
|
||||||
|
|
||||||
The reason that it is permissible to use RCU list-traversal
|
The reason that it is permissible to use RCU list-traversal
|
||||||
primitives when the update-side lock is held is that doing so
|
primitives when the update-side lock is held is that doing so
|
||||||
can be quite helpful in reducing code bloat when common code is
|
can be quite helpful in reducing code bloat when common code is
|
||||||
shared between readers and updaters.
|
shared between readers and updaters. Additional primitives
|
||||||
|
are provided for this case, as discussed in lockdep.txt.
|
||||||
|
|
||||||
10. Conversely, if you are in an RCU read-side critical section,
|
10. Conversely, if you are in an RCU read-side critical section,
|
||||||
and you don't hold the appropriate update-side lock, you -must-
|
and you don't hold the appropriate update-side lock, you -must-
|
||||||
use the "_rcu()" variants of the list macros. Failing to do so
|
use the "_rcu()" variants of the list macros. Failing to do so
|
||||||
will break Alpha and confuse people reading your code.
|
will break Alpha, cause aggressive compilers to generate bad code,
|
||||||
|
and confuse people trying to read your code.
|
||||||
|
|
||||||
11. Note that synchronize_rcu() -only- guarantees to wait until
|
11. Note that synchronize_rcu() -only- guarantees to wait until
|
||||||
all currently executing rcu_read_lock()-protected RCU read-side
|
all currently executing rcu_read_lock()-protected RCU read-side
|
||||||
@@ -239,15 +277,21 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
rcu_read_lock()-protected read-side critical sections, do -not-
|
rcu_read_lock()-protected read-side critical sections, do -not-
|
||||||
use synchronize_rcu().
|
use synchronize_rcu().
|
||||||
|
|
||||||
If you want to wait for some of these other things, you might
|
Similarly, disabling preemption is not an acceptable substitute
|
||||||
instead need to use synchronize_irq() or synchronize_sched().
|
for rcu_read_lock(). Code that attempts to use preemption
|
||||||
|
disabling where it should be using rcu_read_lock() will break
|
||||||
|
in real-time kernel builds.
|
||||||
|
|
||||||
|
If you want to wait for interrupt handlers, NMI handlers, and
|
||||||
|
code under the influence of preempt_disable(), you instead
|
||||||
|
need to use synchronize_irq() or synchronize_sched().
|
||||||
|
|
||||||
12. Any lock acquired by an RCU callback must be acquired elsewhere
|
12. Any lock acquired by an RCU callback must be acquired elsewhere
|
||||||
with softirq disabled, e.g., via spin_lock_irqsave(),
|
with softirq disabled, e.g., via spin_lock_irqsave(),
|
||||||
spin_lock_bh(), etc. Failing to disable irq on a given
|
spin_lock_bh(), etc. Failing to disable irq on a given
|
||||||
acquisition of that lock will result in deadlock as soon as the
|
acquisition of that lock will result in deadlock as soon as
|
||||||
RCU callback happens to interrupt that acquisition's critical
|
the RCU softirq handler happens to run your RCU callback while
|
||||||
section.
|
interrupting that acquisition's critical section.
|
||||||
|
|
||||||
13. RCU callbacks can be and are executed in parallel. In many cases,
|
13. RCU callbacks can be and are executed in parallel. In many cases,
|
||||||
the callback code simply wrappers around kfree(), so that this
|
the callback code simply wrappers around kfree(), so that this
|
||||||
@@ -265,29 +309,30 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
not the case, a self-spawning RCU callback would prevent the
|
not the case, a self-spawning RCU callback would prevent the
|
||||||
victim CPU from ever going offline.)
|
victim CPU from ever going offline.)
|
||||||
|
|
||||||
14. SRCU (srcu_read_lock(), srcu_read_unlock(), and synchronize_srcu())
|
14. SRCU (srcu_read_lock(), srcu_read_unlock(), srcu_dereference(),
|
||||||
may only be invoked from process context. Unlike other forms of
|
synchronize_srcu(), and synchronize_srcu_expedited()) may only
|
||||||
RCU, it -is- permissible to block in an SRCU read-side critical
|
be invoked from process context. Unlike other forms of RCU, it
|
||||||
section (demarked by srcu_read_lock() and srcu_read_unlock()),
|
-is- permissible to block in an SRCU read-side critical section
|
||||||
hence the "SRCU": "sleepable RCU". Please note that if you
|
(demarked by srcu_read_lock() and srcu_read_unlock()), hence the
|
||||||
don't need to sleep in read-side critical sections, you should
|
"SRCU": "sleepable RCU". Please note that if you don't need
|
||||||
be using RCU rather than SRCU, because RCU is almost always
|
to sleep in read-side critical sections, you should be using
|
||||||
faster and easier to use than is SRCU.
|
RCU rather than SRCU, because RCU is almost always faster and
|
||||||
|
easier to use than is SRCU.
|
||||||
|
|
||||||
Also unlike other forms of RCU, explicit initialization
|
Also unlike other forms of RCU, explicit initialization
|
||||||
and cleanup is required via init_srcu_struct() and
|
and cleanup is required via init_srcu_struct() and
|
||||||
cleanup_srcu_struct(). These are passed a "struct srcu_struct"
|
cleanup_srcu_struct(). These are passed a "struct srcu_struct"
|
||||||
that defines the scope of a given SRCU domain. Once initialized,
|
that defines the scope of a given SRCU domain. Once initialized,
|
||||||
the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
|
the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
|
||||||
and synchronize_srcu(). A given synchronize_srcu() waits only
|
synchronize_srcu(), and synchronize_srcu_expedited(). A given
|
||||||
for SRCU read-side critical sections governed by srcu_read_lock()
|
synchronize_srcu() waits only for SRCU read-side critical
|
||||||
and srcu_read_unlock() calls that have been passd the same
|
sections governed by srcu_read_lock() and srcu_read_unlock()
|
||||||
srcu_struct. This property is what makes sleeping read-side
|
calls that have been passed the same srcu_struct. This property
|
||||||
critical sections tolerable -- a given subsystem delays only
|
is what makes sleeping read-side critical sections tolerable --
|
||||||
its own updates, not those of other subsystems using SRCU.
|
a given subsystem delays only its own updates, not those of other
|
||||||
Therefore, SRCU is less prone to OOM the system than RCU would
|
subsystems using SRCU. Therefore, SRCU is less prone to OOM the
|
||||||
be if RCU's read-side critical sections were permitted to
|
system than RCU would be if RCU's read-side critical sections
|
||||||
sleep.
|
were permitted to sleep.
|
||||||
|
|
||||||
The ability to sleep in read-side critical sections does not
|
The ability to sleep in read-side critical sections does not
|
||||||
come for free. First, corresponding srcu_read_lock() and
|
come for free. First, corresponding srcu_read_lock() and
|
||||||
@@ -300,8 +345,8 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
requiring SRCU's read-side deadlock immunity or low read-side
|
requiring SRCU's read-side deadlock immunity or low read-side
|
||||||
realtime latency.
|
realtime latency.
|
||||||
|
|
||||||
Note that, rcu_assign_pointer() and rcu_dereference() relate to
|
Note that, rcu_assign_pointer() relates to SRCU just as they do
|
||||||
SRCU just as they do to other forms of RCU.
|
to other forms of RCU.
|
||||||
|
|
||||||
15. The whole point of call_rcu(), synchronize_rcu(), and friends
|
15. The whole point of call_rcu(), synchronize_rcu(), and friends
|
||||||
is to wait until all pre-existing readers have finished before
|
is to wait until all pre-existing readers have finished before
|
||||||
@@ -311,12 +356,12 @@ over a rather long period of time, but improvements are always welcome!
|
|||||||
destructive operation, and -only- -then- invoke call_rcu(),
|
destructive operation, and -only- -then- invoke call_rcu(),
|
||||||
synchronize_rcu(), or friends.
|
synchronize_rcu(), or friends.
|
||||||
|
|
||||||
Because these primitives only wait for pre-existing readers,
|
Because these primitives only wait for pre-existing readers, it
|
||||||
it is the caller's responsibility to guarantee safety to
|
is the caller's responsibility to guarantee that any subsequent
|
||||||
any subsequent readers.
|
readers will execute safely.
|
||||||
|
|
||||||
16. The various RCU read-side primitives do -not- contain memory
|
16. The various RCU read-side primitives do -not- necessarily contain
|
||||||
barriers. The CPU (and in some cases, the compiler) is free
|
memory barriers. You should therefore plan for the CPU
|
||||||
to reorder code into and out of RCU read-side critical sections.
|
and the compiler to freely reorder code into and out of RCU
|
||||||
It is the responsibility of the RCU update-side primitives to
|
read-side critical sections. It is the responsibility of the
|
||||||
deal with this.
|
RCU update-side primitives to deal with this.
|
||||||
|
91
Documentation/RCU/lockdep.txt
Normal file
91
Documentation/RCU/lockdep.txt
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
RCU and lockdep checking
|
||||||
|
|
||||||
|
All flavors of RCU have lockdep checking available, so that lockdep is
|
||||||
|
aware of when each task enters and leaves any flavor of RCU read-side
|
||||||
|
critical section. Each flavor of RCU is tracked separately (but note
|
||||||
|
that this is not the case in 2.6.32 and earlier). This allows lockdep's
|
||||||
|
tracking to include RCU state, which can sometimes help when debugging
|
||||||
|
deadlocks and the like.
|
||||||
|
|
||||||
|
In addition, RCU provides the following primitives that check lockdep's
|
||||||
|
state:
|
||||||
|
|
||||||
|
rcu_read_lock_held() for normal RCU.
|
||||||
|
rcu_read_lock_bh_held() for RCU-bh.
|
||||||
|
rcu_read_lock_sched_held() for RCU-sched.
|
||||||
|
srcu_read_lock_held() for SRCU.
|
||||||
|
|
||||||
|
These functions are conservative, and will therefore return 1 if they
|
||||||
|
aren't certain (for example, if CONFIG_DEBUG_LOCK_ALLOC is not set).
|
||||||
|
This prevents things like WARN_ON(!rcu_read_lock_held()) from giving false
|
||||||
|
positives when lockdep is disabled.
|
||||||
|
|
||||||
|
In addition, a separate kernel config parameter CONFIG_PROVE_RCU enables
|
||||||
|
checking of rcu_dereference() primitives:
|
||||||
|
|
||||||
|
rcu_dereference(p):
|
||||||
|
Check for RCU read-side critical section.
|
||||||
|
rcu_dereference_bh(p):
|
||||||
|
Check for RCU-bh read-side critical section.
|
||||||
|
rcu_dereference_sched(p):
|
||||||
|
Check for RCU-sched read-side critical section.
|
||||||
|
srcu_dereference(p, sp):
|
||||||
|
Check for SRCU read-side critical section.
|
||||||
|
rcu_dereference_check(p, c):
|
||||||
|
Use explicit check expression "c". This is useful in
|
||||||
|
code that is invoked by both readers and updaters.
|
||||||
|
rcu_dereference_raw(p)
|
||||||
|
Don't check. (Use sparingly, if at all.)
|
||||||
|
rcu_dereference_protected(p, c):
|
||||||
|
Use explicit check expression "c", and omit all barriers
|
||||||
|
and compiler constraints. This is useful when the data
|
||||||
|
structure cannot change, for example, in code that is
|
||||||
|
invoked only by updaters.
|
||||||
|
rcu_access_pointer(p):
|
||||||
|
Return the value of the pointer and omit all barriers,
|
||||||
|
but retain the compiler constraints that prevent duplicating
|
||||||
|
or coalescsing. This is useful when when testing the
|
||||||
|
value of the pointer itself, for example, against NULL.
|
||||||
|
|
||||||
|
The rcu_dereference_check() check expression can be any boolean
|
||||||
|
expression, but would normally include one of the rcu_read_lock_held()
|
||||||
|
family of functions and a lockdep expression. However, any boolean
|
||||||
|
expression can be used. For a moderately ornate example, consider
|
||||||
|
the following:
|
||||||
|
|
||||||
|
file = rcu_dereference_check(fdt->fd[fd],
|
||||||
|
rcu_read_lock_held() ||
|
||||||
|
lockdep_is_held(&files->file_lock) ||
|
||||||
|
atomic_read(&files->count) == 1);
|
||||||
|
|
||||||
|
This expression picks up the pointer "fdt->fd[fd]" in an RCU-safe manner,
|
||||||
|
and, if CONFIG_PROVE_RCU is configured, verifies that this expression
|
||||||
|
is used in:
|
||||||
|
|
||||||
|
1. An RCU read-side critical section, or
|
||||||
|
2. with files->file_lock held, or
|
||||||
|
3. on an unshared files_struct.
|
||||||
|
|
||||||
|
In case (1), the pointer is picked up in an RCU-safe manner for vanilla
|
||||||
|
RCU read-side critical sections, in case (2) the ->file_lock prevents
|
||||||
|
any change from taking place, and finally, in case (3) the current task
|
||||||
|
is the only task accessing the file_struct, again preventing any change
|
||||||
|
from taking place. If the above statement was invoked only from updater
|
||||||
|
code, it could instead be written as follows:
|
||||||
|
|
||||||
|
file = rcu_dereference_protected(fdt->fd[fd],
|
||||||
|
lockdep_is_held(&files->file_lock) ||
|
||||||
|
atomic_read(&files->count) == 1);
|
||||||
|
|
||||||
|
This would verify cases #2 and #3 above, and furthermore lockdep would
|
||||||
|
complain if this was used in an RCU read-side critical section unless one
|
||||||
|
of these two cases held. Because rcu_dereference_protected() omits all
|
||||||
|
barriers and compiler constraints, it generates better code than do the
|
||||||
|
other flavors of rcu_dereference(). On the other hand, it is illegal
|
||||||
|
to use rcu_dereference_protected() if either the RCU-protected pointer
|
||||||
|
or the RCU-protected data that it points to can change concurrently.
|
||||||
|
|
||||||
|
There are currently only "universal" versions of the rcu_assign_pointer()
|
||||||
|
and RCU list-/tree-traversal primitives, which do not (yet) check for
|
||||||
|
being in an RCU read-side critical section. In the future, separate
|
||||||
|
versions of these primitives might be created.
|
@@ -75,6 +75,8 @@ o I hear that RCU is patented? What is with that?
|
|||||||
search for the string "Patent" in RTFP.txt to find them.
|
search for the string "Patent" in RTFP.txt to find them.
|
||||||
Of these, one was allowed to lapse by the assignee, and the
|
Of these, one was allowed to lapse by the assignee, and the
|
||||||
others have been contributed to the Linux kernel under GPL.
|
others have been contributed to the Linux kernel under GPL.
|
||||||
|
There are now also LGPL implementations of user-level RCU
|
||||||
|
available (http://lttng.org/?q=node/18).
|
||||||
|
|
||||||
o I hear that RCU needs work in order to support realtime kernels?
|
o I hear that RCU needs work in order to support realtime kernels?
|
||||||
|
|
||||||
@@ -91,48 +93,4 @@ o Where can I find more information on RCU?
|
|||||||
|
|
||||||
o What are all these files in this directory?
|
o What are all these files in this directory?
|
||||||
|
|
||||||
|
See 00-INDEX for the list.
|
||||||
NMI-RCU.txt
|
|
||||||
|
|
||||||
Describes how to use RCU to implement dynamic
|
|
||||||
NMI handlers, which can be revectored on the fly,
|
|
||||||
without rebooting.
|
|
||||||
|
|
||||||
RTFP.txt
|
|
||||||
|
|
||||||
List of RCU-related publications and web sites.
|
|
||||||
|
|
||||||
UP.txt
|
|
||||||
|
|
||||||
Discussion of RCU usage in UP kernels.
|
|
||||||
|
|
||||||
arrayRCU.txt
|
|
||||||
|
|
||||||
Describes how to use RCU to protect arrays, with
|
|
||||||
resizeable arrays whose elements reference other
|
|
||||||
data structures being of the most interest.
|
|
||||||
|
|
||||||
checklist.txt
|
|
||||||
|
|
||||||
Lists things to check for when inspecting code that
|
|
||||||
uses RCU.
|
|
||||||
|
|
||||||
listRCU.txt
|
|
||||||
|
|
||||||
Describes how to use RCU to protect linked lists.
|
|
||||||
This is the simplest and most common use of RCU
|
|
||||||
in the Linux kernel.
|
|
||||||
|
|
||||||
rcu.txt
|
|
||||||
|
|
||||||
You are reading it!
|
|
||||||
|
|
||||||
rcuref.txt
|
|
||||||
|
|
||||||
Describes how to combine use of reference counts
|
|
||||||
with RCU.
|
|
||||||
|
|
||||||
whatisRCU.txt
|
|
||||||
|
|
||||||
Overview of how the RCU implementation works. Along
|
|
||||||
the way, presents a conceptual view of RCU.
|
|
||||||
|
106
Documentation/RCU/stallwarn.txt
Normal file
106
Documentation/RCU/stallwarn.txt
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
Using RCU's CPU Stall Detector
|
||||||
|
|
||||||
|
The CONFIG_RCU_CPU_STALL_DETECTOR kernel config parameter enables
|
||||||
|
RCU's CPU stall detector, which detects conditions that unduly delay
|
||||||
|
RCU grace periods. The stall detector's idea of what constitutes
|
||||||
|
"unduly delayed" is controlled by a set of C preprocessor macros:
|
||||||
|
|
||||||
|
RCU_SECONDS_TILL_STALL_CHECK
|
||||||
|
|
||||||
|
This macro defines the period of time that RCU will wait from
|
||||||
|
the beginning of a grace period until it issues an RCU CPU
|
||||||
|
stall warning. This time period is normally ten seconds.
|
||||||
|
|
||||||
|
RCU_SECONDS_TILL_STALL_RECHECK
|
||||||
|
|
||||||
|
This macro defines the period of time that RCU will wait after
|
||||||
|
issuing a stall warning until it issues another stall warning
|
||||||
|
for the same stall. This time period is normally set to thirty
|
||||||
|
seconds.
|
||||||
|
|
||||||
|
RCU_STALL_RAT_DELAY
|
||||||
|
|
||||||
|
The CPU stall detector tries to make the offending CPU print its
|
||||||
|
own warnings, as this often gives better-quality stack traces.
|
||||||
|
However, if the offending CPU does not detect its own stall in
|
||||||
|
the number of jiffies specified by RCU_STALL_RAT_DELAY, then
|
||||||
|
some other CPU will complain. This delay is normally set to
|
||||||
|
two jiffies.
|
||||||
|
|
||||||
|
When a CPU detects that it is stalling, it will print a message similar
|
||||||
|
to the following:
|
||||||
|
|
||||||
|
INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies)
|
||||||
|
|
||||||
|
This message indicates that CPU 5 detected that it was causing a stall,
|
||||||
|
and that the stall was affecting RCU-sched. This message will normally be
|
||||||
|
followed by a stack dump of the offending CPU. On TREE_RCU kernel builds,
|
||||||
|
RCU and RCU-sched are implemented by the same underlying mechanism,
|
||||||
|
while on TREE_PREEMPT_RCU kernel builds, RCU is instead implemented
|
||||||
|
by rcu_preempt_state.
|
||||||
|
|
||||||
|
On the other hand, if the offending CPU fails to print out a stall-warning
|
||||||
|
message quickly enough, some other CPU will print a message similar to
|
||||||
|
the following:
|
||||||
|
|
||||||
|
INFO: rcu_bh_state detected stalls on CPUs/tasks: { 3 5 } (detected by 2, 2502 jiffies)
|
||||||
|
|
||||||
|
This message indicates that CPU 2 detected that CPUs 3 and 5 were both
|
||||||
|
causing stalls, and that the stall was affecting RCU-bh. This message
|
||||||
|
will normally be followed by stack dumps for each CPU. Please note that
|
||||||
|
TREE_PREEMPT_RCU builds can be stalled by tasks as well as by CPUs,
|
||||||
|
and that the tasks will be indicated by PID, for example, "P3421".
|
||||||
|
It is even possible for a rcu_preempt_state stall to be caused by both
|
||||||
|
CPUs -and- tasks, in which case the offending CPUs and tasks will all
|
||||||
|
be called out in the list.
|
||||||
|
|
||||||
|
Finally, if the grace period ends just as the stall warning starts
|
||||||
|
printing, there will be a spurious stall-warning message:
|
||||||
|
|
||||||
|
INFO: rcu_bh_state detected stalls on CPUs/tasks: { } (detected by 4, 2502 jiffies)
|
||||||
|
|
||||||
|
This is rare, but does happen from time to time in real life.
|
||||||
|
|
||||||
|
So your kernel printed an RCU CPU stall warning. The next question is
|
||||||
|
"What caused it?" The following problems can result in RCU CPU stall
|
||||||
|
warnings:
|
||||||
|
|
||||||
|
o A CPU looping in an RCU read-side critical section.
|
||||||
|
|
||||||
|
o A CPU looping with interrupts disabled. This condition can
|
||||||
|
result in RCU-sched and RCU-bh stalls.
|
||||||
|
|
||||||
|
o A CPU looping with preemption disabled. This condition can
|
||||||
|
result in RCU-sched stalls and, if ksoftirqd is in use, RCU-bh
|
||||||
|
stalls.
|
||||||
|
|
||||||
|
o A CPU looping with bottom halves disabled. This condition can
|
||||||
|
result in RCU-sched and RCU-bh stalls.
|
||||||
|
|
||||||
|
o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel
|
||||||
|
without invoking schedule().
|
||||||
|
|
||||||
|
o A bug in the RCU implementation.
|
||||||
|
|
||||||
|
o A hardware failure. This is quite unlikely, but has occurred
|
||||||
|
at least once in real life. A CPU failed in a running system,
|
||||||
|
becoming unresponsive, but not causing an immediate crash.
|
||||||
|
This resulted in a series of RCU CPU stall warnings, eventually
|
||||||
|
leading the realization that the CPU had failed.
|
||||||
|
|
||||||
|
The RCU, RCU-sched, and RCU-bh implementations have CPU stall
|
||||||
|
warning. SRCU does not have its own CPU stall warnings, but its
|
||||||
|
calls to synchronize_sched() will result in RCU-sched detecting
|
||||||
|
RCU-sched-related CPU stalls. Please note that RCU only detects
|
||||||
|
CPU stalls when there is a grace period in progress. No grace period,
|
||||||
|
no CPU stall warnings.
|
||||||
|
|
||||||
|
To diagnose the cause of the stall, inspect the stack traces.
|
||||||
|
The offending function will usually be near the top of the stack.
|
||||||
|
If you have a series of stall warnings from a single extended stall,
|
||||||
|
comparing the stack traces can often help determine where the stall
|
||||||
|
is occurring, which will usually be in the function nearest the top of
|
||||||
|
that portion of the stack which remains the same from trace to trace.
|
||||||
|
If you can reliably trigger the stall, ftrace can be quite helpful.
|
||||||
|
|
||||||
|
RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE.
|
@@ -30,6 +30,18 @@ MODULE PARAMETERS
|
|||||||
|
|
||||||
This module has the following parameters:
|
This module has the following parameters:
|
||||||
|
|
||||||
|
fqs_duration Duration (in microseconds) of artificially induced bursts
|
||||||
|
of force_quiescent_state() invocations. In RCU
|
||||||
|
implementations having force_quiescent_state(), these
|
||||||
|
bursts help force races between forcing a given grace
|
||||||
|
period and that grace period ending on its own.
|
||||||
|
|
||||||
|
fqs_holdoff Holdoff time (in microseconds) between consecutive calls
|
||||||
|
to force_quiescent_state() within a burst.
|
||||||
|
|
||||||
|
fqs_stutter Wait time (in seconds) between consecutive bursts
|
||||||
|
of calls to force_quiescent_state().
|
||||||
|
|
||||||
irqreaders Says to invoke RCU readers from irq level. This is currently
|
irqreaders Says to invoke RCU readers from irq level. This is currently
|
||||||
done via timers. Defaults to "1" for variants of RCU that
|
done via timers. Defaults to "1" for variants of RCU that
|
||||||
permit this. (Or, more accurately, variants of RCU that do
|
permit this. (Or, more accurately, variants of RCU that do
|
||||||
@@ -170,16 +182,6 @@ Similarly, sched_expedited RCU provides the following:
|
|||||||
sched_expedited-torture: Reader Pipe: 12660320201 95875 0 0 0 0 0 0 0 0 0
|
sched_expedited-torture: Reader Pipe: 12660320201 95875 0 0 0 0 0 0 0 0 0
|
||||||
sched_expedited-torture: Reader Batch: 12660424885 0 0 0 0 0 0 0 0 0 0
|
sched_expedited-torture: Reader Batch: 12660424885 0 0 0 0 0 0 0 0 0 0
|
||||||
sched_expedited-torture: Free-Block Circulation: 1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0
|
sched_expedited-torture: Free-Block Circulation: 1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0
|
||||||
state: -1 / 0:0 3:0 4:0
|
|
||||||
|
|
||||||
As before, the first four lines are similar to those for RCU.
|
|
||||||
The last line shows the task-migration state. The first number is
|
|
||||||
-1 if synchronize_sched_expedited() is idle, -2 if in the process of
|
|
||||||
posting wakeups to the migration kthreads, and N when waiting on CPU N.
|
|
||||||
Each of the colon-separated fields following the "/" is a CPU:state pair.
|
|
||||||
Valid states are "0" for idle, "1" for waiting for quiescent state,
|
|
||||||
"2" for passed through quiescent state, and "3" when a race with a
|
|
||||||
CPU-hotplug event forces use of the synchronize_sched() primitive.
|
|
||||||
|
|
||||||
|
|
||||||
USAGE
|
USAGE
|
||||||
|
@@ -256,23 +256,23 @@ o Each element of the form "1/1 0:127 ^0" represents one struct
|
|||||||
The output of "cat rcu/rcu_pending" looks as follows:
|
The output of "cat rcu/rcu_pending" looks as follows:
|
||||||
|
|
||||||
rcu_sched:
|
rcu_sched:
|
||||||
0 np=255892 qsp=53936 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
|
0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741
|
||||||
1 np=261224 qsp=54638 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
|
1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792
|
||||||
2 np=237496 qsp=49664 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
|
2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629
|
||||||
3 np=236249 qsp=48766 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
|
3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723
|
||||||
4 np=221310 qsp=46850 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
|
4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110
|
||||||
5 np=237332 qsp=48449 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
|
5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456
|
||||||
6 np=219995 qsp=46718 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
|
6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834
|
||||||
7 np=249893 qsp=49390 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
|
7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888
|
||||||
rcu_bh:
|
rcu_bh:
|
||||||
0 np=146741 qsp=1419 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
|
0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314
|
||||||
1 np=155792 qsp=12597 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
|
1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180
|
||||||
2 np=136629 qsp=18680 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
|
2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936
|
||||||
3 np=137723 qsp=2843 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
|
3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863
|
||||||
4 np=123110 qsp=12433 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
|
4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671
|
||||||
5 np=137456 qsp=4210 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
|
5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235
|
||||||
6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
|
6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921
|
||||||
7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
|
7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542
|
||||||
|
|
||||||
As always, this is once again split into "rcu_sched" and "rcu_bh"
|
As always, this is once again split into "rcu_sched" and "rcu_bh"
|
||||||
portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional
|
portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional
|
||||||
@@ -284,6 +284,9 @@ o "np" is the number of times that __rcu_pending() has been invoked
|
|||||||
o "qsp" is the number of times that the RCU was waiting for a
|
o "qsp" is the number of times that the RCU was waiting for a
|
||||||
quiescent state from this CPU.
|
quiescent state from this CPU.
|
||||||
|
|
||||||
|
o "rpq" is the number of times that the CPU had passed through
|
||||||
|
a quiescent state, but not yet reported it to RCU.
|
||||||
|
|
||||||
o "cbr" is the number of times that this CPU had RCU callbacks
|
o "cbr" is the number of times that this CPU had RCU callbacks
|
||||||
that had passed through a grace period, and were thus ready
|
that had passed through a grace period, and were thus ready
|
||||||
to be invoked.
|
to be invoked.
|
||||||
|
@@ -323,14 +323,17 @@ used as follows:
|
|||||||
Defer Protect
|
Defer Protect
|
||||||
|
|
||||||
a. synchronize_rcu() rcu_read_lock() / rcu_read_unlock()
|
a. synchronize_rcu() rcu_read_lock() / rcu_read_unlock()
|
||||||
call_rcu()
|
call_rcu() rcu_dereference()
|
||||||
|
|
||||||
b. call_rcu_bh() rcu_read_lock_bh() / rcu_read_unlock_bh()
|
b. call_rcu_bh() rcu_read_lock_bh() / rcu_read_unlock_bh()
|
||||||
|
rcu_dereference_bh()
|
||||||
|
|
||||||
c. synchronize_sched() preempt_disable() / preempt_enable()
|
c. synchronize_sched() rcu_read_lock_sched() / rcu_read_unlock_sched()
|
||||||
|
preempt_disable() / preempt_enable()
|
||||||
local_irq_save() / local_irq_restore()
|
local_irq_save() / local_irq_restore()
|
||||||
hardirq enter / hardirq exit
|
hardirq enter / hardirq exit
|
||||||
NMI enter / NMI exit
|
NMI enter / NMI exit
|
||||||
|
rcu_dereference_sched()
|
||||||
|
|
||||||
These three mechanisms are used as follows:
|
These three mechanisms are used as follows:
|
||||||
|
|
||||||
@@ -780,9 +783,8 @@ Linux-kernel source code, but it helps to have a full list of the
|
|||||||
APIs, since there does not appear to be a way to categorize them
|
APIs, since there does not appear to be a way to categorize them
|
||||||
in docbook. Here is the list, by category.
|
in docbook. Here is the list, by category.
|
||||||
|
|
||||||
RCU pointer/list traversal:
|
RCU list traversal:
|
||||||
|
|
||||||
rcu_dereference
|
|
||||||
list_for_each_entry_rcu
|
list_for_each_entry_rcu
|
||||||
hlist_for_each_entry_rcu
|
hlist_for_each_entry_rcu
|
||||||
hlist_nulls_for_each_entry_rcu
|
hlist_nulls_for_each_entry_rcu
|
||||||
@@ -808,7 +810,7 @@ RCU: Critical sections Grace period Barrier
|
|||||||
|
|
||||||
rcu_read_lock synchronize_net rcu_barrier
|
rcu_read_lock synchronize_net rcu_barrier
|
||||||
rcu_read_unlock synchronize_rcu
|
rcu_read_unlock synchronize_rcu
|
||||||
synchronize_rcu_expedited
|
rcu_dereference synchronize_rcu_expedited
|
||||||
call_rcu
|
call_rcu
|
||||||
|
|
||||||
|
|
||||||
@@ -816,7 +818,7 @@ bh: Critical sections Grace period Barrier
|
|||||||
|
|
||||||
rcu_read_lock_bh call_rcu_bh rcu_barrier_bh
|
rcu_read_lock_bh call_rcu_bh rcu_barrier_bh
|
||||||
rcu_read_unlock_bh synchronize_rcu_bh
|
rcu_read_unlock_bh synchronize_rcu_bh
|
||||||
synchronize_rcu_bh_expedited
|
rcu_dereference_bh synchronize_rcu_bh_expedited
|
||||||
|
|
||||||
|
|
||||||
sched: Critical sections Grace period Barrier
|
sched: Critical sections Grace period Barrier
|
||||||
@@ -825,17 +827,25 @@ sched: Critical sections Grace period Barrier
|
|||||||
rcu_read_unlock_sched call_rcu_sched
|
rcu_read_unlock_sched call_rcu_sched
|
||||||
[preempt_disable] synchronize_sched_expedited
|
[preempt_disable] synchronize_sched_expedited
|
||||||
[and friends]
|
[and friends]
|
||||||
|
rcu_dereference_sched
|
||||||
|
|
||||||
|
|
||||||
SRCU: Critical sections Grace period Barrier
|
SRCU: Critical sections Grace period Barrier
|
||||||
|
|
||||||
srcu_read_lock synchronize_srcu N/A
|
srcu_read_lock synchronize_srcu N/A
|
||||||
srcu_read_unlock synchronize_srcu_expedited
|
srcu_read_unlock synchronize_srcu_expedited
|
||||||
|
srcu_dereference
|
||||||
|
|
||||||
SRCU: Initialization/cleanup
|
SRCU: Initialization/cleanup
|
||||||
init_srcu_struct
|
init_srcu_struct
|
||||||
cleanup_srcu_struct
|
cleanup_srcu_struct
|
||||||
|
|
||||||
|
All: lockdep-checked RCU-protected pointer access
|
||||||
|
|
||||||
|
rcu_dereference_check
|
||||||
|
rcu_dereference_protected
|
||||||
|
rcu_access_pointer
|
||||||
|
|
||||||
See the comment headers in the source code (or the docbook generated
|
See the comment headers in the source code (or the docbook generated
|
||||||
from them) for more information.
|
from them) for more information.
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@ NOTE: Smack labels are limited to 23 characters. The attr command
|
|||||||
If you don't do anything special all users will get the floor ("_")
|
If you don't do anything special all users will get the floor ("_")
|
||||||
label when they log in. If you do want to log in via the hacked ssh
|
label when they log in. If you do want to log in via the hacked ssh
|
||||||
at other labels use the attr command to set the smack value on the
|
at other labels use the attr command to set the smack value on the
|
||||||
home directory and it's contents.
|
home directory and its contents.
|
||||||
|
|
||||||
You can add access rules in /etc/smack/accesses. They take the form:
|
You can add access rules in /etc/smack/accesses. They take the form:
|
||||||
|
|
||||||
|
@@ -9,10 +9,16 @@ Documentation/SubmittingPatches and elsewhere regarding submitting Linux
|
|||||||
kernel patches.
|
kernel patches.
|
||||||
|
|
||||||
|
|
||||||
1: Builds cleanly with applicable or modified CONFIG options =y, =m, and
|
1: If you use a facility then #include the file that defines/declares
|
||||||
|
that facility. Don't depend on other header files pulling in ones
|
||||||
|
that you use.
|
||||||
|
|
||||||
|
2: Builds cleanly with applicable or modified CONFIG options =y, =m, and
|
||||||
=n. No gcc warnings/errors, no linker warnings/errors.
|
=n. No gcc warnings/errors, no linker warnings/errors.
|
||||||
|
|
||||||
2: Passes allnoconfig, allmodconfig
|
2b: Passes allnoconfig, allmodconfig
|
||||||
|
|
||||||
|
2c: Builds successfully when using O=builddir
|
||||||
|
|
||||||
3: Builds on multiple CPU architectures by using local cross-compile tools
|
3: Builds on multiple CPU architectures by using local cross-compile tools
|
||||||
or some other build farm.
|
or some other build farm.
|
||||||
@@ -91,3 +97,13 @@ kernel patches.
|
|||||||
|
|
||||||
25: If any ioctl's are added by the patch, then also update
|
25: If any ioctl's are added by the patch, then also update
|
||||||
Documentation/ioctl/ioctl-number.txt.
|
Documentation/ioctl/ioctl-number.txt.
|
||||||
|
|
||||||
|
26: If your modified source code depends on or uses any of the kernel
|
||||||
|
APIs or features that are related to the following kconfig symbols,
|
||||||
|
then test multiple builds with the related kconfig symbols disabled
|
||||||
|
and/or =m (if that option is available) [not all of these at the
|
||||||
|
same time, just various/random combinations of them]:
|
||||||
|
|
||||||
|
CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI,
|
||||||
|
CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ,
|
||||||
|
CONFIG_NET, CONFIG_INET=n (but latter with CONFIG_NET=y)
|
||||||
|
@@ -130,6 +130,8 @@ Linux kernel master tree:
|
|||||||
ftp.??.kernel.org:/pub/linux/kernel/...
|
ftp.??.kernel.org:/pub/linux/kernel/...
|
||||||
?? == your country code, such as "us", "uk", "fr", etc.
|
?? == your country code, such as "us", "uk", "fr", etc.
|
||||||
|
|
||||||
|
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git
|
||||||
|
|
||||||
Linux kernel mailing list:
|
Linux kernel mailing list:
|
||||||
linux-kernel@vger.kernel.org
|
linux-kernel@vger.kernel.org
|
||||||
[mail majordomo@vger.kernel.org to subscribe]
|
[mail majordomo@vger.kernel.org to subscribe]
|
||||||
@@ -159,4 +161,7 @@ How to NOT write kernel driver by Arjan van de Ven:
|
|||||||
http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
|
http://www.fenrus.org/how-to-not-write-a-device-driver-paper.pdf
|
||||||
|
|
||||||
Kernel Janitor:
|
Kernel Janitor:
|
||||||
http://janitor.kernelnewbies.org/
|
http://kernelnewbies.org/KernelJanitors
|
||||||
|
|
||||||
|
GIT, Fast Version Control System:
|
||||||
|
http://git-scm.com/
|
||||||
|
@@ -98,6 +98,17 @@ system, git, as a "commit log". See #15, below.
|
|||||||
If your description starts to get long, that's a sign that you probably
|
If your description starts to get long, that's a sign that you probably
|
||||||
need to split up your patch. See #3, next.
|
need to split up your patch. See #3, next.
|
||||||
|
|
||||||
|
When you submit or resubmit a patch or patch series, include the
|
||||||
|
complete patch description and justification for it. Don't just
|
||||||
|
say that this is version N of the patch (series). Don't expect the
|
||||||
|
patch merger to refer back to earlier patch versions or referenced
|
||||||
|
URLs to find the patch description and put that into the patch.
|
||||||
|
I.e., the patch (series) and its description should be self-contained.
|
||||||
|
This benefits both the patch merger(s) and reviewers. Some reviewers
|
||||||
|
probably didn't even receive earlier versions of the patch.
|
||||||
|
|
||||||
|
If the patch fixes a logged bug entry, refer to that bug entry by
|
||||||
|
number and URL.
|
||||||
|
|
||||||
|
|
||||||
3) Separate your changes.
|
3) Separate your changes.
|
||||||
|
59
Documentation/acpi/apei/einj.txt
Normal file
59
Documentation/acpi/apei/einj.txt
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
APEI Error INJection
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
EINJ provides a hardware error injection mechanism
|
||||||
|
It is very useful for debugging and testing of other APEI and RAS features.
|
||||||
|
|
||||||
|
To use EINJ, make sure the following are enabled in your kernel
|
||||||
|
configuration:
|
||||||
|
|
||||||
|
CONFIG_DEBUG_FS
|
||||||
|
CONFIG_ACPI_APEI
|
||||||
|
CONFIG_ACPI_APEI_EINJ
|
||||||
|
|
||||||
|
The user interface of EINJ is debug file system, under the
|
||||||
|
directory apei/einj. The following files are provided.
|
||||||
|
|
||||||
|
- available_error_type
|
||||||
|
Reading this file returns the error injection capability of the
|
||||||
|
platform, that is, which error types are supported. The error type
|
||||||
|
definition is as follow, the left field is the error type value, the
|
||||||
|
right field is error description.
|
||||||
|
|
||||||
|
0x00000001 Processor Correctable
|
||||||
|
0x00000002 Processor Uncorrectable non-fatal
|
||||||
|
0x00000004 Processor Uncorrectable fatal
|
||||||
|
0x00000008 Memory Correctable
|
||||||
|
0x00000010 Memory Uncorrectable non-fatal
|
||||||
|
0x00000020 Memory Uncorrectable fatal
|
||||||
|
0x00000040 PCI Express Correctable
|
||||||
|
0x00000080 PCI Express Uncorrectable fatal
|
||||||
|
0x00000100 PCI Express Uncorrectable non-fatal
|
||||||
|
0x00000200 Platform Correctable
|
||||||
|
0x00000400 Platform Uncorrectable non-fatal
|
||||||
|
0x00000800 Platform Uncorrectable fatal
|
||||||
|
|
||||||
|
The format of file contents are as above, except there are only the
|
||||||
|
available error type lines.
|
||||||
|
|
||||||
|
- error_type
|
||||||
|
This file is used to set the error type value. The error type value
|
||||||
|
is defined in "available_error_type" description.
|
||||||
|
|
||||||
|
- error_inject
|
||||||
|
Write any integer to this file to trigger the error
|
||||||
|
injection. Before this, please specify all necessary error
|
||||||
|
parameters.
|
||||||
|
|
||||||
|
- param1
|
||||||
|
This file is used to set the first error parameter value. Effect of
|
||||||
|
parameter depends on error_type specified. For memory error, this is
|
||||||
|
physical memory address.
|
||||||
|
|
||||||
|
- param2
|
||||||
|
This file is used to set the second error parameter value. Effect of
|
||||||
|
parameter depends on error_type specified. For memory error, this is
|
||||||
|
physical memory address mask.
|
||||||
|
|
||||||
|
For more information about EINJ, please refer to ACPI specification
|
||||||
|
version 4.0, section 17.5.
|
@@ -19,6 +19,8 @@ Note: Only ACPI METHOD can be overridden, any other object types like
|
|||||||
"Device", "OperationRegion", are not recognized.
|
"Device", "OperationRegion", are not recognized.
|
||||||
Note: The same ACPI control method can be overridden for many times,
|
Note: The same ACPI control method can be overridden for many times,
|
||||||
and it's always the latest one that used by Linux/kernel.
|
and it's always the latest one that used by Linux/kernel.
|
||||||
|
Note: To get the ACPI debug object output (Store (AAAA, Debug)),
|
||||||
|
please run "echo 1 > /sys/module/acpi/parameters/aml_debug_output".
|
||||||
|
|
||||||
1. override an existing method
|
1. override an existing method
|
||||||
a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT,
|
a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ...
|
The EtherDrive (R) HOWTO for users of 2.6 kernels is found at ...
|
||||||
|
|
||||||
http://www.coraid.com/support/linux/EtherDrive-2.6-HOWTO.html
|
http://www.coraid.com/SUPPORT/EtherDrive-HBA
|
||||||
|
|
||||||
It has many tips and hints!
|
It has many tips and hints!
|
||||||
|
|
||||||
|
39
Documentation/apparmor.txt
Normal file
39
Documentation/apparmor.txt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
--- What is AppArmor? ---
|
||||||
|
|
||||||
|
AppArmor is MAC style security extension for the Linux kernel. It implements
|
||||||
|
a task centered policy, with task "profiles" being created and loaded
|
||||||
|
from user space. Tasks on the system that do not have a profile defined for
|
||||||
|
them run in an unconfined state which is equivalent to standard Linux DAC
|
||||||
|
permissions.
|
||||||
|
|
||||||
|
--- How to enable/disable ---
|
||||||
|
|
||||||
|
set CONFIG_SECURITY_APPARMOR=y
|
||||||
|
|
||||||
|
If AppArmor should be selected as the default security module then
|
||||||
|
set CONFIG_DEFAULT_SECURITY="apparmor"
|
||||||
|
and CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
|
||||||
|
|
||||||
|
Build the kernel
|
||||||
|
|
||||||
|
If AppArmor is not the default security module it can be enabled by passing
|
||||||
|
security=apparmor on the kernel's command line.
|
||||||
|
|
||||||
|
If AppArmor is the default security module it can be disabled by passing
|
||||||
|
apparmor=0, security=XXXX (where XXX is valid security module), on the
|
||||||
|
kernel's command line
|
||||||
|
|
||||||
|
For AppArmor to enforce any restrictions beyond standard Linux DAC permissions
|
||||||
|
policy must be loaded into the kernel from user space (see the Documentation
|
||||||
|
and tools links).
|
||||||
|
|
||||||
|
--- Documentation ---
|
||||||
|
|
||||||
|
Documentation can be found on the wiki.
|
||||||
|
|
||||||
|
--- Links ---
|
||||||
|
|
||||||
|
Mailing List - apparmor@lists.ubuntu.com
|
||||||
|
Wiki - http://apparmor.wiki.kernel.org/
|
||||||
|
User space tools - https://launchpad.net/apparmor
|
||||||
|
Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
|
@@ -20,6 +20,8 @@ Samsung-S3C24XX
|
|||||||
- S3C24XX ARM Linux Overview
|
- S3C24XX ARM Linux Overview
|
||||||
Sharp-LH
|
Sharp-LH
|
||||||
- Linux on Sharp LH79524 and LH7A40X System On a Chip (SOC)
|
- Linux on Sharp LH79524 and LH7A40X System On a Chip (SOC)
|
||||||
|
SPEAr
|
||||||
|
- ST SPEAr platform Linux Overview
|
||||||
VFP/
|
VFP/
|
||||||
- Release notes for Linux Kernel Vector Floating Point support code
|
- Release notes for Linux Kernel Vector Floating Point support code
|
||||||
empeg/
|
empeg/
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user