提交 af7a5356 编写于 作者: B Ben Dooks

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
...@@ -317,6 +317,14 @@ S: 2322 37th Ave SW ...@@ -317,6 +317,14 @@ S: 2322 37th Ave SW
S: Seattle, Washington 98126-2010 S: Seattle, Washington 98126-2010
S: USA S: USA
N: Muli Ben-Yehuda
E: mulix@mulix.org
E: muli@il.ibm.com
W: http://www.mulix.org
D: trident OSS sound driver, x86-64 dma-ops and Calgary IOMMU,
D: KVM and Xen bits and other misc. hackery.
S: Haifa, Israel
N: Johannes Berg N: Johannes Berg
E: johannes@sipsolutions.net E: johannes@sipsolutions.net
W: http://johannes.sipsolutions.net/ W: http://johannes.sipsolutions.net/
...@@ -3344,8 +3352,7 @@ S: Spain ...@@ -3344,8 +3352,7 @@ S: Spain
N: Linus Torvalds N: Linus Torvalds
E: torvalds@linux-foundation.org E: torvalds@linux-foundation.org
D: Original kernel hacker D: Original kernel hacker
S: 12725 SW Millikan Way, Suite 400 S: Portland, Oregon 97005
S: Beaverton, Oregon 97005
S: USA S: USA
N: Marcelo Tosatti N: Marcelo Tosatti
......
...@@ -89,8 +89,6 @@ cciss.txt ...@@ -89,8 +89,6 @@ cciss.txt
- info, major/minor #'s for Compaq's SMART Array Controllers. - info, major/minor #'s for Compaq's SMART Array Controllers.
cdrom/ cdrom/
- directory with information on the CD-ROM drivers that Linux has. - directory with information on the CD-ROM drivers that Linux has.
cli-sti-removal.txt
- cli()/sti() removal guide.
computone.txt computone.txt
- info on Computone Intelliport II/Plus Multiport Serial Driver. - info on Computone Intelliport II/Plus Multiport Serial Driver.
connector/ connector/
...@@ -361,8 +359,6 @@ telephony/ ...@@ -361,8 +359,6 @@ telephony/
- directory with info on telephony (e.g. voice over IP) support. - directory with info on telephony (e.g. voice over IP) support.
time_interpolators.txt time_interpolators.txt
- info on time interpolators. - info on time interpolators.
tipar.txt
- information about Parallel link cable for Texas Instruments handhelds.
tty.txt tty.txt
- guide to the locking policies of the tty layer. - guide to the locking policies of the tty layer.
uml/ uml/
......
What: /sys/class/regulator/.../state
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
state. This holds the regulator output state.
This will be one of the following strings:
'enabled'
'disabled'
'unknown'
'enabled' means the regulator output is ON and is supplying
power to the system.
'disabled' means the regulator output is OFF and is not
supplying power to the system..
'unknown' means software cannot determine the state.
NOTE: this field can be used in conjunction with microvolts
and microamps to determine regulator output levels.
What: /sys/class/regulator/.../type
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
type. This holds the regulator type.
This will be one of the following strings:
'voltage'
'current'
'unknown'
'voltage' means the regulator output voltage can be controlled
by software.
'current' means the regulator output current limit can be
controlled by software.
'unknown' means software cannot control either voltage or
current limit.
What: /sys/class/regulator/.../microvolts
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
microvolts. This holds the regulator output voltage setting
measured in microvolts (i.e. E-6 Volts).
NOTE: This value should not be used to determine the regulator
output voltage level as this value is the same regardless of
whether the regulator is enabled or disabled.
What: /sys/class/regulator/.../microamps
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
microamps. This holds the regulator output current limit
setting measured in microamps (i.e. E-6 Amps).
NOTE: This value should not be used to determine the regulator
output current level as this value is the same regardless of
whether the regulator is enabled or disabled.
What: /sys/class/regulator/.../opmode
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
opmode. This holds the regulator operating mode setting.
The opmode value can be one of the following strings:
'fast'
'normal'
'idle'
'standby'
'unknown'
The modes are described in include/linux/regulator/regulator.h
NOTE: This value should not be used to determine the regulator
output operating mode as this value is the same regardless of
whether the regulator is enabled or disabled.
What: /sys/class/regulator/.../min_microvolts
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
min_microvolts. This holds the minimum safe working regulator
output voltage setting for this domain measured in microvolts.
NOTE: this will return the string 'constraint not defined' if
the power domain has no min microvolts constraint defined by
platform code.
What: /sys/class/regulator/.../max_microvolts
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
max_microvolts. This holds the maximum safe working regulator
output voltage setting for this domain measured in microvolts.
NOTE: this will return the string 'constraint not defined' if
the power domain has no max microvolts constraint defined by
platform code.
What: /sys/class/regulator/.../min_microamps
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
min_microamps. This holds the minimum safe working regulator
output current limit setting for this domain measured in
microamps.
NOTE: this will return the string 'constraint not defined' if
the power domain has no min microamps constraint defined by
platform code.
What: /sys/class/regulator/.../max_microamps
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
max_microamps. This holds the maximum safe working regulator
output current limit setting for this domain measured in
microamps.
NOTE: this will return the string 'constraint not defined' if
the power domain has no max microamps constraint defined by
platform code.
What: /sys/class/regulator/.../num_users
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
num_users. This holds the number of consumer devices that
have called regulator_enable() on this regulator.
What: /sys/class/regulator/.../requested_microamps
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
requested_microamps. This holds the total requested load
current in microamps for this regulator from all its consumer
devices.
What: /sys/class/regulator/.../parent
Date: April 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Some regulator directories will contain a link called parent.
This points to the parent or supply regulator if one exists.
What: /sys/class/regulator/.../suspend_mem_microvolts
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_mem_microvolts. This holds the regulator output
voltage setting for this domain measured in microvolts when
the system is suspended to memory.
NOTE: this will return the string 'not defined' if
the power domain has no suspend to memory voltage defined by
platform code.
What: /sys/class/regulator/.../suspend_disk_microvolts
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_disk_microvolts. This holds the regulator output
voltage setting for this domain measured in microvolts when
the system is suspended to disk.
NOTE: this will return the string 'not defined' if
the power domain has no suspend to disk voltage defined by
platform code.
What: /sys/class/regulator/.../suspend_standby_microvolts
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_standby_microvolts. This holds the regulator output
voltage setting for this domain measured in microvolts when
the system is suspended to standby.
NOTE: this will return the string 'not defined' if
the power domain has no suspend to standby voltage defined by
platform code.
What: /sys/class/regulator/.../suspend_mem_mode
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_mem_mode. This holds the regulator operating mode
setting for this domain when the system is suspended to
memory.
NOTE: this will return the string 'not defined' if
the power domain has no suspend to memory mode defined by
platform code.
What: /sys/class/regulator/.../suspend_disk_mode
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_disk_mode. This holds the regulator operating mode
setting for this domain when the system is suspended to disk.
NOTE: this will return the string 'not defined' if
the power domain has no suspend to disk mode defined by
platform code.
What: /sys/class/regulator/.../suspend_standby_mode
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_standby_mode. This holds the regulator operating mode
setting for this domain when the system is suspended to
standby.
NOTE: this will return the string 'not defined' if
the power domain has no suspend to standby mode defined by
platform code.
What: /sys/class/regulator/.../suspend_mem_state
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_mem_state. This holds the regulator operating state
when suspended to memory.
This will be one of the following strings:
'enabled'
'disabled'
'not defined'
What: /sys/class/regulator/.../suspend_disk_state
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_disk_state. This holds the regulator operating state
when suspended to disk.
This will be one of the following strings:
'enabled'
'disabled'
'not defined'
What: /sys/class/regulator/.../suspend_standby_state
Date: May 2008
KernelVersion: 2.6.26
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Description:
Each regulator directory will contain a field called
suspend_standby_state. This holds the regulator operating
state when suspended to standby.
This will be one of the following strings:
'enabled'
'disabled'
'not defined'
What: /sys/dev
Date: April 2008
KernelVersion: 2.6.26
Contact: Dan Williams <dan.j.williams@intel.com>
Description: The /sys/dev tree provides a method to look up the sysfs
path for a device using the information returned from
stat(2). There are two directories, 'block' and 'char',
beneath /sys/dev containing symbolic links with names of
the form "<major>:<minor>". These links point to the
corresponding sysfs path for the given device.
Example:
$ readlink /sys/dev/block/8:32
../../block/sdc
Entries in /sys/dev/char and /sys/dev/block will be
dynamically created and destroyed as devices enter and
leave the system.
Users: mdadm <linux-raid@vger.kernel.org>
What: /sys/devices/system/memory
Date: June 2008
Contact: Badari Pulavarty <pbadari@us.ibm.com>
Description:
The /sys/devices/system/memory contains a snapshot of the
internal state of the kernel memory blocks. Files could be
added or removed dynamically to represent hot-add/remove
operations.
Users: hotplug memory add/remove tools
https://w3.opensource.ibm.com/projects/powerpc-utils/
What: /sys/devices/system/memory/memoryX/removable
Date: June 2008
Contact: Badari Pulavarty <pbadari@us.ibm.com>
Description:
The file /sys/devices/system/memory/memoryX/removable
indicates whether this memory block is removable or not.
This is useful for a user-level agent to determine
identify removable sections of the memory before attempting
potentially expensive hot-remove memory operation
Users: hotplug memory remove tools
https://w3.opensource.ibm.com/projects/powerpc-utils/
...@@ -29,46 +29,46 @@ Description: ...@@ -29,46 +29,46 @@ Description:
$ cd /sys/firmware/acpi/interrupts $ cd /sys/firmware/acpi/interrupts
$ grep . * $ grep . *
error:0 error: 0
ff_gbl_lock:0 ff_gbl_lock: 0 enable
ff_pmtimer:0 ff_pmtimer: 0 invalid
ff_pwr_btn:0 ff_pwr_btn: 0 enable
ff_rt_clk:0 ff_rt_clk: 2 disable
ff_slp_btn:0 ff_slp_btn: 0 invalid
gpe00:0 gpe00: 0 invalid
gpe01:0 gpe01: 0 enable
gpe02:0 gpe02: 108 enable
gpe03:0 gpe03: 0 invalid
gpe04:0 gpe04: 0 invalid
gpe05:0 gpe05: 0 invalid
gpe06:0 gpe06: 0 enable
gpe07:0 gpe07: 0 enable
gpe08:0 gpe08: 0 invalid
gpe09:174 gpe09: 0 invalid
gpe0A:0 gpe0A: 0 invalid
gpe0B:0 gpe0B: 0 invalid
gpe0C:0 gpe0C: 0 invalid
gpe0D:0 gpe0D: 0 invalid
gpe0E:0 gpe0E: 0 invalid
gpe0F:0 gpe0F: 0 invalid
gpe10:0 gpe10: 0 invalid
gpe11:60 gpe11: 0 invalid
gpe12:0 gpe12: 0 invalid
gpe13:0 gpe13: 0 invalid
gpe14:0 gpe14: 0 invalid
gpe15:0 gpe15: 0 invalid
gpe16:0 gpe16: 0 invalid
gpe17:0 gpe17: 1084 enable
gpe18:0 gpe18: 0 enable
gpe19:7 gpe19: 0 invalid
gpe1A:0 gpe1A: 0 invalid
gpe1B:0 gpe1B: 0 invalid
gpe1C:0 gpe1C: 0 invalid
gpe1D:0 gpe1D: 0 invalid
gpe1E:0 gpe1E: 0 invalid
gpe1F:0 gpe1F: 0 invalid
gpe_all:241 gpe_all: 1192
sci:241 sci: 1194
sci - The total number of times the ACPI SCI sci - The total number of times the ACPI SCI
has claimed an interrupt. has claimed an interrupt.
...@@ -89,6 +89,13 @@ Description: ...@@ -89,6 +89,13 @@ Description:
error - an interrupt that can't be accounted for above. error - an interrupt that can't be accounted for above.
invalid: it's either a wakeup GPE or a GPE/Fixed Event that
doesn't have an event handler.
disable: the GPE/Fixed Event is valid but disabled.
enable: the GPE/Fixed Event is valid and enabled.
Root has permission to clear any of these counters. Eg. Root has permission to clear any of these counters. Eg.
# echo 0 > gpe11 # echo 0 > gpe11
...@@ -97,3 +104,43 @@ Description: ...@@ -97,3 +104,43 @@ Description:
None of these counters has an effect on the function None of these counters has an effect on the function
of the system, they are simply statistics. of the system, they are simply statistics.
Besides this, user can also write specific strings to these files
to enable/disable/clear ACPI interrupts in user space, which can be
used to debug some ACPI interrupt storm issues.
Note that only writting to VALID GPE/Fixed Event is allowed,
i.e. user can only change the status of runtime GPE and
Fixed Event with event handler installed.
Let's take power button fixed event for example, please kill acpid
and other user space applications so that the machine won't shutdown
when pressing the power button.
# cat ff_pwr_btn
0
# press the power button for 3 times;
# cat ff_pwr_btn
3
# echo disable > ff_pwr_btn
# cat ff_pwr_btn
disable
# press the power button for 3 times;
# cat ff_pwr_btn
disable
# echo enable > ff_pwr_btn
# cat ff_pwr_btn
4
/*
* this is because the status bit is set even if the enable bit is cleared,
* and it triggers an ACPI fixed event when the enable bit is set again
*/
# press the power button for 3 times;
# cat ff_pwr_btn
7
# echo disable > ff_pwr_btn
# press the power button for 3 times;
# echo clear > ff_pwr_btn /* clear the status bit */
# echo disable > ff_pwr_btn
# cat ff_pwr_btn
7
What: /sys/kernel/mm
Date: July 2008
Contact: Nishanth Aravamudan <nacc@us.ibm.com>, VM maintainers
Description:
/sys/kernel/mm/ should contain any and all VM
related information in /sys/kernel/.
What: /sys/kernel/mm/hugepages/
Date: June 2008
Contact: Nishanth Aravamudan <nacc@us.ibm.com>, hugetlb maintainers
Description:
/sys/kernel/mm/hugepages/ contains a number of subdirectories
of the form hugepages-<size>kB, where <size> is the page size
of the hugepages supported by the kernel/CPU combination.
Under these directories are a number of files:
nr_hugepages
nr_overcommit_hugepages
free_hugepages
surplus_hugepages
resv_hugepages
See Documentation/vm/hugetlbpage.txt for details.
...@@ -474,25 +474,29 @@ make a good program). ...@@ -474,25 +474,29 @@ make a good program).
So, you can either get rid of GNU emacs, or change it to use saner So, you can either get rid of GNU emacs, or change it to use saner
values. To do the latter, you can stick the following in your .emacs file: values. To do the latter, you can stick the following in your .emacs file:
(defun linux-c-mode () (defun c-lineup-arglist-tabs-only (ignored)
"C mode with adjusted defaults for use with the Linux kernel." "Line up argument lists by tabs, not spaces"
(interactive) (let* ((anchor (c-langelem-pos c-syntactic-element))
(c-mode) (column (c-langelem-2nd-pos c-syntactic-element))
(c-set-style "K&R") (offset (- (1+ column) anchor))
(setq tab-width 8) (steps (floor offset c-basic-offset)))
(setq indent-tabs-mode t) (* (max steps 1)
(setq c-basic-offset 8)) c-basic-offset)))
This will define the M-x linux-c-mode command. When hacking on a (add-hook 'c-mode-hook
module, if you put the string -*- linux-c -*- somewhere on the first (lambda ()
two lines, this mode will be automatically invoked. Also, you may want (let ((filename (buffer-file-name)))
to add ;; Enable kernel mode for the appropriate files
(when (and filename
(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) (string-match "~/src/linux-trees" filename))
auto-mode-alist)) (setq indent-tabs-mode t)
(c-set-style "linux")
to your .emacs file if you want to have linux-c-mode switched on (c-set-offset 'arglist-cont-nonempty
automagically when you edit source files under /usr/src/linux. '(c-lineup-gcc-asm-reg
c-lineup-arglist-tabs-only))))))
This will make emacs go better with the kernel coding style for C
files below ~/src/linux-trees.
But even if you fail in getting emacs to do sane formatting, not But even if you fail in getting emacs to do sane formatting, not
everything is lost: use "indent". everything is lost: use "indent".
......
...@@ -298,10 +298,10 @@ recommended that you never use these unless you really know what the ...@@ -298,10 +298,10 @@ recommended that you never use these unless you really know what the
cache width is. cache width is.
int int
dma_mapping_error(dma_addr_t dma_addr) dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
int int
pci_dma_mapping_error(dma_addr_t dma_addr) 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
......
...@@ -22,3 +22,12 @@ ready and available in memory. The DMA of the "completion indication" ...@@ -22,3 +22,12 @@ ready and available in memory. The DMA of the "completion indication"
could race with data DMA. Mapping the memory used for completion could race with data DMA. Mapping the memory used for completion
indications with DMA_ATTR_WRITE_BARRIER would prevent the race. indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
DMA_ATTR_WEAK_ORDERING
----------------------
DMA_ATTR_WEAK_ORDERING specifies that reads and writes to the mapping
may be weakly ordered, that is that reads and writes may pass each other.
Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
those that do not will simply ignore the attribute and exhibit default
behavior.
...@@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ ...@@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
mac80211.xml debugobjects.xml mac80211.xml debugobjects.xml sh.xml
### ###
# The build process is as follows (targets): # The build process is as follows (targets):
......
...@@ -524,6 +524,44 @@ These utilities include endpoint autoconfiguration. ...@@ -524,6 +524,44 @@ These utilities include endpoint autoconfiguration.
<!-- !Edrivers/usb/gadget/epautoconf.c --> <!-- !Edrivers/usb/gadget/epautoconf.c -->
</sect1> </sect1>
<sect1 id="composite"><title>Composite Device Framework</title>
<para>The core API is sufficient for writing drivers for composite
USB devices (with more than one function in a given configuration),
and also multi-configuration devices (also more than one function,
but not necessarily sharing a given configuration).
There is however an optional framework which makes it easier to
reuse and combine functions.
</para>
<para>Devices using this framework provide a <emphasis>struct
usb_composite_driver</emphasis>, which in turn provides one or
more <emphasis>struct usb_configuration</emphasis> instances.
Each such configuration includes at least one
<emphasis>struct usb_function</emphasis>, which packages a user
visible role such as "network link" or "mass storage device".
Management functions may also exist, such as "Device Firmware
Upgrade".
</para>
!Iinclude/linux/usb/composite.h
!Edrivers/usb/gadget/composite.c
</sect1>
<sect1 id="functions"><title>Composite Device Functions</title>
<para>At this writing, a few of the current gadget drivers have
been converted to this framework.
Near-term plans include converting all of them, except for "gadgetfs".
</para>
!Edrivers/usb/gadget/f_acm.c
!Edrivers/usb/gadget/f_serial.c
</sect1>
</chapter> </chapter>
<chapter id="controllers"><title>Peripheral Controller Drivers</title> <chapter id="controllers"><title>Peripheral Controller Drivers</title>
......
...@@ -219,10 +219,10 @@ ...@@ -219,10 +219,10 @@
</para> </para>
<sect1 id="lock-intro"> <sect1 id="lock-intro">
<title>Three Main Types of Kernel Locks: Spinlocks, Mutexes and Semaphores</title> <title>Two Main Types of Kernel Locks: Spinlocks and Mutexes</title>
<para> <para>
There are three main types of kernel locks. The fundamental type There are two main types of kernel locks. The fundamental type
is the spinlock is the spinlock
(<filename class="headerfile">include/asm/spinlock.h</filename>), (<filename class="headerfile">include/asm/spinlock.h</filename>),
which is a very simple single-holder lock: if you can't get the which is a very simple single-holder lock: if you can't get the
...@@ -239,14 +239,6 @@ ...@@ -239,14 +239,6 @@
can't sleep (see <xref linkend="sleeping-things"/>), and so have to can't sleep (see <xref linkend="sleeping-things"/>), and so have to
use a spinlock instead. use a spinlock instead.
</para> </para>
<para>
The third type is a semaphore
(<filename class="headerfile">include/linux/semaphore.h</filename>): it
can have more than one holder at any time (the number decided at
initialization time), although it is most commonly used as a
single-holder lock (a mutex). If you can't get a semaphore, your
task will be suspended and later on woken up - just like for mutexes.
</para>
<para> <para>
Neither type of lock is recursive: see Neither type of lock is recursive: see
<xref linkend="deadlock"/>. <xref linkend="deadlock"/>.
...@@ -278,7 +270,7 @@ ...@@ -278,7 +270,7 @@
</para> </para>
<para> <para>
Semaphores still exist, because they are required for Mutexes still exist, because they are required for
synchronization between <firstterm linkend="gloss-usercontext">user synchronization between <firstterm linkend="gloss-usercontext">user
contexts</firstterm>, as we will see below. contexts</firstterm>, as we will see below.
</para> </para>
...@@ -289,18 +281,17 @@ ...@@ -289,18 +281,17 @@
<para> <para>
If you have a data structure which is only ever accessed from If you have a data structure which is only ever accessed from
user context, then you can use a simple semaphore user context, then you can use a simple mutex
(<filename>linux/linux/semaphore.h</filename>) to protect it. This (<filename>include/linux/mutex.h</filename>) to protect it. This
is the most trivial case: you initialize the semaphore to the number is the most trivial case: you initialize the mutex. Then you can
of resources available (usually 1), and call call <function>mutex_lock_interruptible()</function> to grab the mutex,
<function>down_interruptible()</function> to grab the semaphore, and and <function>mutex_unlock()</function> to release it. There is also a
<function>up()</function> to release it. There is also a <function>mutex_lock()</function>, which should be avoided, because it
<function>down()</function>, which should be avoided, because it
will not return if a signal is received. will not return if a signal is received.
</para> </para>
<para> <para>
Example: <filename>linux/net/core/netfilter.c</filename> allows Example: <filename>net/netfilter/nf_sockopt.c</filename> allows
registration of new <function>setsockopt()</function> and registration of new <function>setsockopt()</function> and
<function>getsockopt()</function> calls, with <function>getsockopt()</function> calls, with
<function>nf_register_sockopt()</function>. Registration and <function>nf_register_sockopt()</function>. Registration and
...@@ -515,7 +506,7 @@ ...@@ -515,7 +506,7 @@
<listitem> <listitem>
<para> <para>
If you are in a process context (any syscall) and want to If you are in a process context (any syscall) and want to
lock other process out, use a semaphore. You can take a semaphore lock other process out, use a mutex. You can take a mutex
and sleep (<function>copy_from_user*(</function> or and sleep (<function>copy_from_user*(</function> or
<function>kmalloc(x,GFP_KERNEL)</function>). <function>kmalloc(x,GFP_KERNEL)</function>).
</para> </para>
...@@ -662,7 +653,7 @@ ...@@ -662,7 +653,7 @@
<entry>SLBH</entry> <entry>SLBH</entry>
<entry>SLBH</entry> <entry>SLBH</entry>
<entry>SLBH</entry> <entry>SLBH</entry>
<entry>DI</entry> <entry>MLI</entry>
<entry>None</entry> <entry>None</entry>
</row> </row>
...@@ -692,8 +683,8 @@ ...@@ -692,8 +683,8 @@
<entry>spin_lock_bh</entry> <entry>spin_lock_bh</entry>
</row> </row>
<row> <row>
<entry>DI</entry> <entry>MLI</entry>
<entry>down_interruptible</entry> <entry>mutex_lock_interruptible</entry>
</row> </row>
</tbody> </tbody>
...@@ -1310,7 +1301,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>. ...@@ -1310,7 +1301,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
<para> <para>
There is a coding bug where a piece of code tries to grab a There is a coding bug where a piece of code tries to grab a
spinlock twice: it will spin forever, waiting for the lock to spinlock twice: it will spin forever, waiting for the lock to
be released (spinlocks, rwlocks and semaphores are not be released (spinlocks, rwlocks and mutexes are not
recursive in Linux). This is trivial to diagnose: not a recursive in Linux). This is trivial to diagnose: not a
stay-up-five-nights-talk-to-fluffy-code-bunnies kind of stay-up-five-nights-talk-to-fluffy-code-bunnies kind of
problem. problem.
...@@ -1335,7 +1326,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>. ...@@ -1335,7 +1326,7 @@ as Alan Cox says, <quote>Lock data, not code</quote>.
<para> <para>
This complete lockup is easy to diagnose: on SMP boxes the This complete lockup is easy to diagnose: on SMP boxes the
watchdog timer or compiling with <symbol>DEBUG_SPINLOCKS</symbol> set watchdog timer or compiling with <symbol>DEBUG_SPINLOCK</symbol> set
(<filename>include/linux/spinlock.h</filename>) will show this up (<filename>include/linux/spinlock.h</filename>) will show this up
immediately when it happens. immediately when it happens.
</para> </para>
...@@ -1558,7 +1549,7 @@ the amount of locking which needs to be done. ...@@ -1558,7 +1549,7 @@ the amount of locking which needs to be done.
<title>Read/Write Lock Variants</title> <title>Read/Write Lock Variants</title>
<para> <para>
Both spinlocks and semaphores have read/write variants: Both spinlocks and mutexes have read/write variants:
<type>rwlock_t</type> and <structname>struct rw_semaphore</structname>. <type>rwlock_t</type> and <structname>struct rw_semaphore</structname>.
These divide users into two classes: the readers and the writers. If These divide users into two classes: the readers and the writers. If
you are only reading the data, you can get a read lock, but to write to you are only reading the data, you can get a read lock, but to write to
...@@ -1681,7 +1672,7 @@ the amount of locking which needs to be done. ...@@ -1681,7 +1672,7 @@ the amount of locking which needs to be done.
#include &lt;linux/slab.h&gt; #include &lt;linux/slab.h&gt;
#include &lt;linux/string.h&gt; #include &lt;linux/string.h&gt;
+#include &lt;linux/rcupdate.h&gt; +#include &lt;linux/rcupdate.h&gt;
#include &lt;linux/semaphore.h&gt; #include &lt;linux/mutex.h&gt;
#include &lt;asm/errno.h&gt; #include &lt;asm/errno.h&gt;
struct object struct object
...@@ -1913,7 +1904,7 @@ machines due to caching. ...@@ -1913,7 +1904,7 @@ machines due to caching.
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function> put_user()</function> <function>put_user()</function>
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -1927,13 +1918,13 @@ machines due to caching. ...@@ -1927,13 +1918,13 @@ machines due to caching.
<listitem> <listitem>
<para> <para>
<function>down_interruptible()</function> and <function>mutex_lock_interruptible()</function> and
<function>down()</function> <function>mutex_lock()</function>
</para> </para>
<para> <para>
There is a <function>down_trylock()</function> which can be There is a <function>mutex_trylock()</function> which can be
used inside interrupt context, as it will not sleep. used inside interrupt context, as it will not sleep.
<function>up()</function> will also never sleep. <function>mutex_unlock()</function> will also never sleep.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -2023,7 +2014,7 @@ machines due to caching. ...@@ -2023,7 +2014,7 @@ machines due to caching.
<para> <para>
Prior to 2.5, or when <symbol>CONFIG_PREEMPT</symbol> is Prior to 2.5, or when <symbol>CONFIG_PREEMPT</symbol> is
unset, processes in user context inside the kernel would not unset, processes in user context inside the kernel would not
preempt each other (ie. you had that CPU until you have it up, preempt each other (ie. you had that CPU until you gave it up,
except for interrupts). With the addition of except for interrupts). With the addition of
<symbol>CONFIG_PREEMPT</symbol> in 2.5.4, this changed: when <symbol>CONFIG_PREEMPT</symbol> in 2.5.4, this changed: when
in user context, higher priority tasks can "cut in": spinlocks in user context, higher priority tasks can "cut in": spinlocks
......
...@@ -98,6 +98,24 @@ ...@@ -98,6 +98,24 @@
"Kernel debugging" select "KGDB: kernel debugging with remote gdb". "Kernel debugging" select "KGDB: kernel debugging with remote gdb".
</para> </para>
<para> <para>
It is advised, but not required that you turn on the
CONFIG_FRAME_POINTER kernel option. This option inserts code to
into the compiled executable which saves the frame information in
registers or on the stack at different points which will allow a
debugger such as gdb to more accurately construct stack back traces
while debugging the kernel.
</para>
<para>
If the architecture that you are using supports the kernel option
CONFIG_DEBUG_RODATA, you should consider turning it off. This
option will prevent the use of software breakpoints because it
marks certain regions of the kernel's memory space as read-only.
If kgdb supports it for the architecture you are using, you can
use hardware breakpoints if you desire to run with the
CONFIG_DEBUG_RODATA option turned on, else you need to turn off
this option.
</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 debugging
host and debugged target. Early boot debugging requires a KGDB host and debugged target. Early boot debugging requires a KGDB
I/O driver that supports early debugging and the driver must be I/O driver that supports early debugging and the driver must be
......
...@@ -29,12 +29,12 @@ ...@@ -29,12 +29,12 @@
<revhistory> <revhistory>
<revision> <revision>
<revnumber>1.0&nbsp;</revnumber> <revnumber>1.0</revnumber>
<date>May 30, 2001</date> <date>May 30, 2001</date>
<revremark>Initial revision posted to linux-kernel</revremark> <revremark>Initial revision posted to linux-kernel</revremark>
</revision> </revision>
<revision> <revision>
<revnumber>1.1&nbsp;</revnumber> <revnumber>1.1</revnumber>
<date>June 3, 2001</date> <date>June 3, 2001</date>
<revremark>Revised after comments from linux-kernel</revremark> <revremark>Revised after comments from linux-kernel</revremark>
</revision> </revision>
......
...@@ -100,7 +100,7 @@ ...@@ -100,7 +100,7 @@
the hardware structures represented here, please consult the Principles the hardware structures represented here, please consult the Principles
of Operation. of Operation.
</para> </para>
!Iinclude/asm-s390/cio.h !Iarch/s390/include/asm/cio.h
</sect1> </sect1>
<sect1 id="ccwdev"> <sect1 id="ccwdev">
<title>ccw devices</title> <title>ccw devices</title>
...@@ -114,7 +114,7 @@ ...@@ -114,7 +114,7 @@
ccw device structure. Device drivers must not bypass those functions ccw device structure. Device drivers must not bypass those functions
or strange side effects may happen. or strange side effects may happen.
</para> </para>
!Iinclude/asm-s390/ccwdev.h !Iarch/s390/include/asm/ccwdev.h
!Edrivers/s390/cio/device.c !Edrivers/s390/cio/device.c
!Edrivers/s390/cio/device_ops.c !Edrivers/s390/cio/device_ops.c
</sect1> </sect1>
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
measurement data which is made available by the channel subsystem measurement data which is made available by the channel subsystem
for each channel attached device. for each channel attached device.
</para> </para>
!Iinclude/asm-s390/cmb.h !Iarch/s390/include/asm/cmb.h
!Edrivers/s390/cio/cmf.c !Edrivers/s390/cio/cmf.c
</sect1> </sect1>
</chapter> </chapter>
...@@ -142,7 +142,7 @@ ...@@ -142,7 +142,7 @@
</para> </para>
<sect1 id="ccwgroupdevices"> <sect1 id="ccwgroupdevices">
<title>ccw group devices</title> <title>ccw group devices</title>
!Iinclude/asm-s390/ccwgroup.h !Iarch/s390/include/asm/ccwgroup.h
!Edrivers/s390/cio/ccwgroup.c !Edrivers/s390/cio/ccwgroup.c
</sect1> </sect1>
</chapter> </chapter>
......
<?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="sh-drivers">
<bookinfo>
<title>SuperH Interfaces Guide</title>
<authorgroup>
<author>
<firstname>Paul</firstname>
<surname>Mundt</surname>
<affiliation>
<address>
<email>lethal@linux-sh.org</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2008</year>
<holder>Paul Mundt</holder>
</copyright>
<copyright>
<year>2008</year>
<holder>Renesas Technology Corp.</holder>
</copyright>
<legalnotice>
<para>
This documentation is free software; you can redistribute
it and/or modify it under the terms of the GNU General Public
License version 2 as published by the Free Software Foundation.
</para>
<para>
This program is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
</para>
<para>
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="mm">
<title>Memory Management</title>
<sect1 id="sh4">
<title>SH-4</title>
<sect2 id="sq">
<title>Store Queue API</title>
!Earch/sh/kernel/cpu/sh4/sq.c
</sect2>
</sect1>
<sect1 id="sh5">
<title>SH-5</title>
<sect2 id="tlb">
<title>TLB Interfaces</title>
!Iarch/sh/mm/tlb-sh5.c
!Iarch/sh/include/asm/tlb_64.h
</sect2>
</sect1>
</chapter>
<chapter id="clk">
<title>Clock Framework Extensions</title>
!Iarch/sh/include/asm/clock.h
</chapter>
<chapter id="mach">
<title>Machine Specific Interfaces</title>
<sect1 id="dreamcast">
<title>mach-dreamcast</title>
!Iarch/sh/boards/mach-dreamcast/rtc.c
</sect1>
<sect1 id="x3proto">
<title>mach-x3proto</title>
!Earch/sh/boards/mach-x3proto/ilsel.c
</sect1>
</chapter>
<chapter id="busses">
<title>Busses</title>
<sect1 id="superhyway">
<title>SuperHyway</title>
!Edrivers/sh/superhyway/superhyway.c
</sect1>
<sect1 id="maple">
<title>Maple</title>
!Edrivers/sh/maple/maple.c
</sect1>
</chapter>
</book>
...@@ -21,6 +21,18 @@ ...@@ -21,6 +21,18 @@
</affiliation> </affiliation>
</author> </author>
<copyright>
<year>2006-2008</year>
<holder>Hans-Jürgen Koch.</holder>
</copyright>
<legalnotice>
<para>
This documentation is Free Software licensed under the terms of the
GPL version 2.
</para>
</legalnotice>
<pubdate>2006-12-11</pubdate> <pubdate>2006-12-11</pubdate>
<abstract> <abstract>
...@@ -29,6 +41,12 @@ ...@@ -29,6 +41,12 @@
</abstract> </abstract>
<revhistory> <revhistory>
<revision>
<revnumber>0.5</revnumber>
<date>2008-05-22</date>
<authorinitials>hjk</authorinitials>
<revremark>Added description of write() function.</revremark>
</revision>
<revision> <revision>
<revnumber>0.4</revnumber> <revnumber>0.4</revnumber>
<date>2007-11-26</date> <date>2007-11-26</date>
...@@ -57,20 +75,9 @@ ...@@ -57,20 +75,9 @@
</bookinfo> </bookinfo>
<chapter id="aboutthisdoc"> <chapter id="aboutthisdoc">
<?dbhtml filename="about.html"?> <?dbhtml filename="aboutthis.html"?>
<title>About this document</title> <title>About this document</title>
<sect1 id="copyright">
<?dbhtml filename="copyright.html"?>
<title>Copyright and License</title>
<para>
Copyright (c) 2006 by Hans-Jürgen Koch.</para>
<para>
This documentation is Free Software licensed under the terms of the
GPL version 2.
</para>
</sect1>
<sect1 id="translations"> <sect1 id="translations">
<?dbhtml filename="translations.html"?> <?dbhtml filename="translations.html"?>
<title>Translations</title> <title>Translations</title>
...@@ -189,6 +196,30 @@ interested in translating it, please email me ...@@ -189,6 +196,30 @@ interested in translating it, please email me
represents the total interrupt count. You can use this number represents the total interrupt count. You can use this number
to figure out if you missed some interrupts. to figure out if you missed some interrupts.
</para> </para>
<para>
For some hardware that has more than one interrupt source internally,
but not separate IRQ mask and status registers, there might be
situations where userspace cannot determine what the interrupt source
was if the kernel handler disables them by writing to the chip's IRQ
register. In such a case, the kernel has to disable the IRQ completely
to leave the chip's register untouched. Now the userspace part can
determine the cause of the interrupt, but it cannot re-enable
interrupts. Another cornercase is chips where re-enabling interrupts
is a read-modify-write operation to a combined IRQ status/acknowledge
register. This would be racy if a new interrupt occurred
simultaneously.
</para>
<para>
To address these problems, UIO also implements a write() function. It
is normally not used and can be ignored for hardware that has only a
single interrupt source or has separate IRQ mask and status registers.
If you need it, however, a write to <filename>/dev/uioX</filename>
will call the <function>irqcontrol()</function> function implemented
by the driver. You have to write a 32-bit value that is usually either
0 or 1 to disable or enable interrupts. If a driver does not implement
<function>irqcontrol()</function>, <function>write()</function> will
return with <varname>-ENOSYS</varname>.
</para>
<para> <para>
To handle interrupts properly, your custom kernel module can To handle interrupts properly, your custom kernel module can
...@@ -362,6 +393,14 @@ device is actually used. ...@@ -362,6 +393,14 @@ device is actually used.
<function>open()</function>, you will probably also want a custom <function>open()</function>, you will probably also want a custom
<function>release()</function> function. <function>release()</function> function.
</para></listitem> </para></listitem>
<listitem><para>
<varname>int (*irqcontrol)(struct uio_info *info, s32 irq_on)
</varname>: Optional. If you need to be able to enable or disable
interrupts from userspace by writing to <filename>/dev/uioX</filename>,
you can implement this function. The parameter <varname>irq_on</varname>
will be 0 to disable interrupts and 1 to enable them.
</para></listitem>
</itemizedlist> </itemizedlist>
<para> <para>
......
...@@ -358,7 +358,7 @@ Here is a list of some of the different kernel trees available: ...@@ -358,7 +358,7 @@ Here is a list of some of the different kernel trees available:
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net> - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
- SCSI, James Bottomley <James.Bottomley@SteelEye.com> - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
- x86, Ingo Molnar <mingo@elte.hu> - x86, Ingo Molnar <mingo@elte.hu>
......
...@@ -48,7 +48,7 @@ IOVA generation is pretty generic. We used the same technique as vmalloc() ...@@ -48,7 +48,7 @@ IOVA generation is pretty generic. We used the same technique as vmalloc()
but these are not global address spaces, but separate for each domain. but these are not global address spaces, but separate for each domain.
Different DMA engines may support different number of domains. Different DMA engines may support different number of domains.
We also allocate gaurd pages with each mapping, so we can attempt to catch We also allocate guard pages with each mapping, so we can attempt to catch
any overflow that might happen. any overflow that might happen.
...@@ -112,4 +112,4 @@ TBD ...@@ -112,4 +112,4 @@ TBD
- For compatibility testing, could use unity map domain for all devices, just - For compatibility testing, could use unity map domain for all devices, just
provide a 1-1 for all useful memory under a single domain for all devices. provide a 1-1 for all useful memory under a single domain for all devices.
- API for paravirt ops for abstracting functionlity for VMM folks. - API for paravirt ops for abstracting functionality for VMM folks.
...@@ -93,6 +93,9 @@ Since NMI handlers disable preemption, synchronize_sched() is guaranteed ...@@ -93,6 +93,9 @@ Since NMI handlers disable preemption, synchronize_sched() is guaranteed
not to return until all ongoing NMI handlers exit. It is therefore safe not to return until all ongoing NMI handlers exit. It is therefore safe
to free up the handler's data as soon as synchronize_sched() returns. to free up the handler's data as soon as synchronize_sched() returns.
Important note: for this to work, the architecture in question must
invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
Answer to Quick Quiz Answer to Quick Quiz
......
...@@ -52,6 +52,10 @@ of each iteration. Unfortunately, chaotic relaxation requires highly ...@@ -52,6 +52,10 @@ of each iteration. Unfortunately, chaotic relaxation requires highly
structured data, such as the matrices used in scientific programs, and structured data, such as the matrices used in scientific programs, and
is thus inapplicable to most data structures in operating-system kernels. is thus inapplicable to most data structures in operating-system kernels.
In 1992, Henry (now Alexia) Massalin completed a dissertation advising
parallel programmers to defer processing when feasible to simplify
synchronization. RCU makes extremely heavy use of this advice.
In 1993, Jacobson [Jacobson93] verbally described what is perhaps the In 1993, Jacobson [Jacobson93] verbally described what is perhaps the
simplest deferred-free technique: simply waiting a fixed amount of time simplest deferred-free technique: simply waiting a fixed amount of time
before freeing blocks awaiting deferred free. Jacobson did not describe before freeing blocks awaiting deferred free. Jacobson did not describe
...@@ -138,6 +142,13 @@ blocking in read-side critical sections appeared [PaulEMcKenney2006c], ...@@ -138,6 +142,13 @@ blocking in read-side critical sections appeared [PaulEMcKenney2006c],
Robert Olsson described an RCU-protected trie-hash combination Robert Olsson described an RCU-protected trie-hash combination
[RobertOlsson2006a]. [RobertOlsson2006a].
2007 saw the journal version of the award-winning RCU paper from 2006
[ThomasEHart2007a], as well as a paper demonstrating use of Promela
and Spin to mechanically verify an optimization to Oleg Nesterov's
QRCU [PaulEMcKenney2007QRCUspin], a design document describing
preemptible RCU [PaulEMcKenney2007PreemptibleRCU], and the three-part
LWN "What is RCU?" series [PaulEMcKenney2007WhatIsRCUFundamentally,
PaulEMcKenney2008WhatIsRCUUsage, and PaulEMcKenney2008WhatIsRCUAPI].
Bibtex Entries Bibtex Entries
...@@ -202,6 +213,20 @@ Bibtex Entries ...@@ -202,6 +213,20 @@ Bibtex Entries
,Year="1991" ,Year="1991"
} }
@phdthesis{HMassalinPhD
,author="H. Massalin"
,title="Synthesis: An Efficient Implementation of Fundamental Operating
System Services"
,school="Columbia University"
,address="New York, NY"
,year="1992"
,annotation="
Mondo optimizing compiler.
Wait-free stuff.
Good advice: defer work to avoid synchronization.
"
}
@unpublished{Jacobson93 @unpublished{Jacobson93
,author="Van Jacobson" ,author="Van Jacobson"
,title="Avoid Read-Side Locking Via Delayed Free" ,title="Avoid Read-Side Locking Via Delayed Free"
...@@ -635,3 +660,86 @@ Revised: ...@@ -635,3 +660,86 @@ Revised:
" "
} }
@unpublished{PaulEMcKenney2007PreemptibleRCU
,Author="Paul E. McKenney"
,Title="The design of preemptible read-copy-update"
,month="October"
,day="8"
,year="2007"
,note="Available:
\url{http://lwn.net/Articles/253651/}
[Viewed October 25, 2007]"
,annotation="
LWN article describing the design of preemptible RCU.
"
}
########################################################################
#
# "What is RCU?" LWN series.
#
@unpublished{PaulEMcKenney2007WhatIsRCUFundamentally
,Author="Paul E. McKenney and Jonathan Walpole"
,Title="What is {RCU}, Fundamentally?"
,month="December"
,day="17"
,year="2007"
,note="Available:
\url{http://lwn.net/Articles/262464/}
[Viewed December 27, 2007]"
,annotation="
Lays out the three basic components of RCU: (1) publish-subscribe,
(2) wait for pre-existing readers to complete, and (2) maintain
multiple versions.
"
}
@unpublished{PaulEMcKenney2008WhatIsRCUUsage
,Author="Paul E. McKenney"
,Title="What is {RCU}? Part 2: Usage"
,month="January"
,day="4"
,year="2008"
,note="Available:
\url{http://lwn.net/Articles/263130/}
[Viewed January 4, 2008]"
,annotation="
Lays out six uses of RCU:
1. RCU is a Reader-Writer Lock Replacement
2. RCU is a Restricted Reference-Counting Mechanism
3. RCU is a Bulk Reference-Counting Mechanism
4. RCU is a Poor Man's Garbage Collector
5. RCU is a Way of Providing Existence Guarantees
6. RCU is a Way of Waiting for Things to Finish
"
}
@unpublished{PaulEMcKenney2008WhatIsRCUAPI
,Author="Paul E. McKenney"
,Title="{RCU} part 3: the {RCU} {API}"
,month="January"
,day="17"
,year="2008"
,note="Available:
\url{http://lwn.net/Articles/264090/}
[Viewed January 10, 2008]"
,annotation="
Gives an overview of the Linux-kernel RCU API and a brief annotated RCU
bibliography.
"
}
@article{DinakarGuniguntala2008IBMSysJ
,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}"
,Year="2008"
,Month="April"
,journal="IBM Systems Journal"
,volume="47"
,number="2"
,pages="@@-@@"
,annotation="
RCU, realtime RCU, sleepable RCU, performance.
"
}
...@@ -13,10 +13,13 @@ over a rather long period of time, but improvements are always welcome! ...@@ -13,10 +13,13 @@ over a rather long period of time, but improvements are always welcome!
detailed performance measurements show that RCU is nonetheless detailed performance measurements show that RCU is nonetheless
the right tool for the job. the right tool for the job.
The other exception would be where performance is not an issue, Another exception is where performance is not an issue, and RCU
and RCU provides a simpler implementation. An example of this provides a simpler implementation. An example of this situation
situation is the dynamic NMI code in the Linux 2.6 kernel, is the dynamic NMI code in the Linux 2.6 kernel, at least on
at least on architectures where NMIs are rare. architectures where NMIs are rare.
Yet another exception is where the low real-time latency of RCU's
read-side primitives is critically important.
1. Does the update code have proper mutual exclusion? 1. Does the update code have proper mutual exclusion?
...@@ -39,9 +42,10 @@ over a rather long period of time, but improvements are always welcome! ...@@ -39,9 +42,10 @@ over a rather long period of time, but improvements are always welcome!
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
to suppress preemption (or bottom halves, in the case of to prevent grace periods from ending prematurely, which
rcu_read_lock_bh()) in the read-side critical sections, could result in data being unceremoniously freed out from
and are also an excellent aid to readability. under your read-side code, which can greatly increase the
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() or rcu_read_lock_bh()
...@@ -54,15 +58,30 @@ over a rather long period of time, but improvements are always welcome! ...@@ -54,15 +58,30 @@ over a rather long period of time, but improvements are always welcome!
be running while updates are in progress. There are a number be running while updates are in progress. There are a number
of ways to handle this concurrency, depending on the situation: of ways to handle this concurrency, depending on the situation:
a. Make updates appear atomic to readers. For example, a. Use the RCU variants of the list and hlist update
primitives to add, remove, and replace elements on an
RCU-protected list. Alternatively, use the RCU-protected
trees that have been added to the Linux kernel.
This is almost always the best approach.
b. Proceed as in (a) above, but also maintain per-element
locks (that are acquired by both readers and writers)
that guard per-element state. Of course, fields that
the readers refrain from accessing can be guarded by the
update-side lock.
This works quite well, also.
c. Make updates appear atomic to readers. For example,
pointer updates to properly aligned fields will appear pointer updates to properly aligned fields will appear
atomic, as will individual atomic primitives. Operations atomic, as will individual atomic primitives. Operations
performed under a lock and sequences of multiple atomic performed under a lock and sequences of multiple atomic
primitives will -not- appear to be atomic. primitives will -not- appear to be atomic.
This is almost always the best approach. This can work, but is starting to get a bit tricky.
b. Carefully order the updates and the reads so that d. Carefully order the updates and the reads so that
readers see valid data at all phases of the update. readers see valid data at all phases of the update.
This is often more difficult than it sounds, especially This is often more difficult than it sounds, especially
given modern CPUs' tendency to reorder memory references. given modern CPUs' tendency to reorder memory references.
...@@ -123,18 +142,22 @@ over a rather long period of time, but improvements are always welcome! ...@@ -123,18 +142,22 @@ over a rather long period of time, but improvements are always welcome!
when publicizing a pointer to a structure that can when publicizing a pointer to a structure that can
be traversed by an RCU read-side critical section. be traversed by an RCU read-side critical section.
5. If call_rcu(), or a related primitive such as call_rcu_bh(), 5. If call_rcu(), or a related primitive such as call_rcu_bh() or
is used, the callback function must be written to be called call_rcu_sched(), is used, the callback function must be
from softirq context. In particular, it cannot block. written to be called from softirq context. In particular,
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. any sort of irq context. Ditto for synchronize_sched() and
synchronize_srcu().
7. If the updater uses call_rcu(), then the corresponding readers 7. If the updater uses call_rcu(), then the corresponding readers
must use rcu_read_lock() and rcu_read_unlock(). If the updater must use rcu_read_lock() and rcu_read_unlock(). If the updater
uses call_rcu_bh(), then the corresponding readers must use uses call_rcu_bh(), then the corresponding readers must use
rcu_read_lock_bh() and rcu_read_unlock_bh(). Mixing things up rcu_read_lock_bh() and rcu_read_unlock_bh(). If the updater
will result in confusion and broken kernels. uses call_rcu_sched(), then the corresponding readers must
disable preemption. 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()
...@@ -143,9 +166,9 @@ over a rather long period of time, but improvements are always welcome! ...@@ -143,9 +166,9 @@ over a rather long period of time, but improvements are always welcome!
such cases is a must, of course! And the jury is still out on such cases is a must, of course! And the jury is still out on
whether the increased speed is worth it. whether the increased speed is worth it.
8. Although synchronize_rcu() is a bit slower than is call_rcu(), 8. Although synchronize_rcu() is slower than is call_rcu(), it
it usually results in simpler code. So, unless update usually results in simpler code. So, unless update performance
performance is critically important or the updaters cannot block, is critically important or the updaters cannot block,
synchronize_rcu() should be used in preference to call_rcu(). synchronize_rcu() should be used in preference to call_rcu().
An especially important property of the synchronize_rcu() An especially important property of the synchronize_rcu()
...@@ -187,23 +210,23 @@ over a rather long period of time, but improvements are always welcome! ...@@ -187,23 +210,23 @@ over a rather long period of time, but improvements are always welcome!
number of updates per grace period. number of updates per grace period.
9. All RCU list-traversal primitives, which include 9. All RCU list-traversal primitives, which include
list_for_each_rcu(), list_for_each_entry_rcu(), rcu_dereference(), list_for_each_rcu(), 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(),
must be within an RCU read-side critical section. RCU must be either within an RCU read-side critical section or
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().
Use of the _rcu() list-traversal primitives outside of an The reason that it is permissible to use RCU list-traversal
RCU read-side critical section causes no harm other than primitives when the update-side lock is held is that doing so
a slight performance degradation on Alpha CPUs. It can can be quite helpful in reducing code bloat when common code is
also be quite helpful in reducing code bloat when common shared between readers and updaters.
code is shared between readers and updaters.
10. Conversely, if you are in an RCU read-side critical section, 10. Conversely, if you are in an RCU read-side critical section,
you -must- use the "_rcu()" variants of the list macros. and you don't hold the appropriate update-side lock, you -must-
Failing to do so will break Alpha and confuse people reading use the "_rcu()" variants of the list macros. Failing to do so
your code. will break Alpha and confuse people reading 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
...@@ -230,6 +253,14 @@ over a rather long period of time, but improvements are always welcome! ...@@ -230,6 +253,14 @@ over a rather long period of time, but improvements are always welcome!
must use whatever locking or other synchronization is required must use whatever locking or other synchronization is required
to safely access and/or modify that data structure. to safely access and/or modify that data structure.
RCU callbacks are -usually- executed on the same CPU that executed
the corresponding call_rcu(), call_rcu_bh(), or call_rcu_sched(),
but are by -no- means guaranteed to be. For example, if a given
CPU goes offline while having an RCU callback pending, then that
RCU callback will execute on some surviving CPU. (If this was
not the case, a self-spawning RCU callback would prevent the
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(), and synchronize_srcu())
may only be invoked from process context. Unlike other forms of may only be invoked from process context. Unlike other forms of
RCU, it -is- permissible to block in an SRCU read-side critical RCU, it -is- permissible to block in an SRCU read-side critical
......
...@@ -10,23 +10,30 @@ status messages via printk(), which can be examined via the dmesg ...@@ -10,23 +10,30 @@ status messages via printk(), which can be examined via the dmesg
command (perhaps grepping for "torture"). The test is started command (perhaps grepping for "torture"). The test is started
when the module is loaded, and stops when the module is unloaded. when the module is loaded, and stops when the module is unloaded.
However, actually setting this config option to "y" results in the system CONFIG_RCU_TORTURE_TEST_RUNNABLE
running the test immediately upon boot, and ending only when the system
is taken down. Normally, one will instead want to build the system It is also possible to specify CONFIG_RCU_TORTURE_TEST=y, which will
with CONFIG_RCU_TORTURE_TEST=m and to use modprobe and rmmod to control result in the tests being loaded into the base kernel. In this case,
the test, perhaps using a script similar to the one shown at the end of the CONFIG_RCU_TORTURE_TEST_RUNNABLE config option is used to specify
this document. Note that you will need CONFIG_MODULE_UNLOAD in order whether the RCU torture tests are to be started immediately during
to be able to end the test. boot or whether the /proc/sys/kernel/rcutorture_runnable file is used
to enable them. This /proc file can be used to repeatedly pause and
restart the tests, regardless of the initial state specified by the
CONFIG_RCU_TORTURE_TEST_RUNNABLE config option.
You will normally -not- want to start the RCU torture tests during boot
(and thus the default is CONFIG_RCU_TORTURE_TEST_RUNNABLE=n), but doing
this can sometimes be useful in finding boot-time bugs.
MODULE PARAMETERS MODULE PARAMETERS
This module has the following parameters: This module has the following parameters:
nreaders This is the number of RCU reading threads supported. irqreaders Says to invoke RCU readers from irq level. This is currently
The default is twice the number of CPUs. Why twice? done via timers. Defaults to "1" for variants of RCU that
To properly exercise RCU implementations with preemptible permit this. (Or, more accurately, variants of RCU that do
read-side critical sections. -not- permit this know to ignore this variable.)
nfakewriters This is the number of RCU fake writer threads to run. Fake nfakewriters This is the number of RCU fake writer threads to run. Fake
writer threads repeatedly use the synchronous "wait for writer threads repeatedly use the synchronous "wait for
...@@ -37,6 +44,16 @@ nfakewriters This is the number of RCU fake writer threads to run. Fake ...@@ -37,6 +44,16 @@ nfakewriters This is the number of RCU fake writer threads to run. Fake
to trigger special cases caused by multiple writers, such as to trigger special cases caused by multiple writers, such as
the synchronize_srcu() early return optimization. the synchronize_srcu() early return optimization.
nreaders This is the number of RCU reading threads supported.
The default is twice the number of CPUs. Why twice?
To properly exercise RCU implementations with preemptible
read-side critical sections.
shuffle_interval
The number of seconds to keep the test threads affinitied
to a particular subset of the CPUs, defaults to 3 seconds.
Used in conjunction with test_no_idle_hz.
stat_interval The number of seconds between output of torture stat_interval The number of seconds between output of torture
statistics (via printk()). Regardless of the interval, statistics (via printk()). Regardless of the interval,
statistics are printed when the module is unloaded. statistics are printed when the module is unloaded.
...@@ -44,10 +61,11 @@ stat_interval The number of seconds between output of torture ...@@ -44,10 +61,11 @@ stat_interval The number of seconds between output of torture
be printed -only- when the module is unloaded, and this be printed -only- when the module is unloaded, and this
is the default. is the default.
shuffle_interval stutter The length of time to run the test before pausing for this
The number of seconds to keep the test threads affinitied same period of time. Defaults to "stutter=5", so as
to a particular subset of the CPUs, defaults to 5 seconds. to run and pause for (roughly) five-second intervals.
Used in conjunction with test_no_idle_hz. Specifying "stutter=0" causes the test to run continuously
without pausing, which is the old default behavior.
test_no_idle_hz Whether or not to test the ability of RCU to operate in test_no_idle_hz Whether or not to test the ability of RCU to operate in
a kernel that disables the scheduling-clock interrupt to a kernel that disables the scheduling-clock interrupt to
......
Please note that the "What is RCU?" LWN series is an excellent place
to start learning about RCU:
1. What is RCU, Fundamentally? http://lwn.net/Articles/262464/
2. What is RCU? Part 2: Usage http://lwn.net/Articles/263130/
3. RCU part 3: the RCU API http://lwn.net/Articles/264090/
What is RCU? What is RCU?
RCU is a synchronization mechanism that was added to the Linux kernel RCU is a synchronization mechanism that was added to the Linux kernel
...@@ -772,26 +780,18 @@ Linux-kernel source code, but it helps to have a full list of the ...@@ -772,26 +780,18 @@ 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.
Markers for RCU read-side critical sections:
rcu_read_lock
rcu_read_unlock
rcu_read_lock_bh
rcu_read_unlock_bh
srcu_read_lock
srcu_read_unlock
RCU pointer/list traversal: RCU pointer/list traversal:
rcu_dereference rcu_dereference
list_for_each_entry_rcu
hlist_for_each_entry_rcu
list_for_each_rcu (to be deprecated in favor of list_for_each_rcu (to be deprecated in favor of
list_for_each_entry_rcu) list_for_each_entry_rcu)
list_for_each_entry_rcu
list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_continue_rcu (to be deprecated in favor of new
list_for_each_entry_continue_rcu) list_for_each_entry_continue_rcu)
hlist_for_each_entry_rcu
RCU pointer update: RCU pointer/list update:
rcu_assign_pointer rcu_assign_pointer
list_add_rcu list_add_rcu
...@@ -799,16 +799,36 @@ RCU pointer update: ...@@ -799,16 +799,36 @@ RCU pointer update:
list_del_rcu list_del_rcu
list_replace_rcu list_replace_rcu
hlist_del_rcu hlist_del_rcu
hlist_add_after_rcu
hlist_add_before_rcu
hlist_add_head_rcu hlist_add_head_rcu
hlist_replace_rcu
list_splice_init_rcu()
RCU grace period: RCU: Critical sections Grace period Barrier
rcu_read_lock synchronize_net rcu_barrier
rcu_read_unlock synchronize_rcu
call_rcu
bh: Critical sections Grace period Barrier
rcu_read_lock_bh call_rcu_bh rcu_barrier_bh
rcu_read_unlock_bh
sched: Critical sections Grace period Barrier
[preempt_disable] synchronize_sched rcu_barrier_sched
[and friends] call_rcu_sched
SRCU: Critical sections Grace period Barrier
srcu_read_lock synchronize_srcu N/A
srcu_read_unlock
synchronize_net
synchronize_sched
synchronize_rcu
synchronize_srcu
call_rcu
call_rcu_bh
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.
......
...@@ -528,7 +528,33 @@ See more details on the proper patch format in the following ...@@ -528,7 +528,33 @@ See more details on the proper patch format in the following
references. references.
16) Sending "git pull" requests (from Linus emails)
Please write the git repo address and branch name alone on the same line
so that I can't even by mistake pull from the wrong branch, and so
that a triple-click just selects the whole thing.
So the proper format is something along the lines of:
"Please pull from
git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
to get these changes:"
so that I don't have to hunt-and-peck for the address and inevitably
get it wrong (actually, I've only gotten it wrong a few times, and
checking against the diffstat tells me when I get it wrong, but I'm
just a lot more comfortable when I don't have to "look for" the right
thing to pull, and double-check that I have the right branch-name).
Please use "git diff -M --stat --summary" to generate the diffstat:
the -M enables rename detection, and the summary enables a summary of
new/deleted or renamed files.
With rename detection, the statistics are rather different [...]
because git will notice that a fair number of the changes are renames.
----------------------------------- -----------------------------------
SECTION 2 - HINTS, TIPS, AND TRICKS SECTION 2 - HINTS, TIPS, AND TRICKS
......
...@@ -11,6 +11,7 @@ the delays experienced by a task while ...@@ -11,6 +11,7 @@ the delays experienced by a task while
a) waiting for a CPU (while being runnable) a) waiting for a CPU (while being runnable)
b) completion of synchronous block I/O initiated by the task b) completion of synchronous block I/O initiated by the task
c) swapping in pages c) swapping in pages
d) memory reclaim
and makes these statistics available to userspace through and makes these statistics available to userspace through
the taskstats interface. the taskstats interface.
...@@ -41,7 +42,7 @@ this structure. See ...@@ -41,7 +42,7 @@ this structure. See
include/linux/taskstats.h include/linux/taskstats.h
for a description of the fields pertaining to delay accounting. for a description of the fields pertaining to delay accounting.
It will generally be in the form of counters returning the cumulative It will generally be in the form of counters returning the cumulative
delay seen for cpu, sync block I/O, swapin etc. delay seen for cpu, sync block I/O, swapin, memory reclaim etc.
Taking the difference of two successive readings of a given Taking the difference of two successive readings of a given
counter (say cpu_delay_total) for a task will give the delay counter (say cpu_delay_total) for a task will give the delay
...@@ -94,7 +95,9 @@ CPU count real total virtual total delay total ...@@ -94,7 +95,9 @@ CPU count real total virtual total delay total
7876 92005750 100000000 24001500 7876 92005750 100000000 24001500
IO count delay total IO count delay total
0 0 0 0
MEM count delay total SWAP count delay total
0 0
RECLAIM count delay total
0 0 0 0
Get delays seen in executing a given simple command Get delays seen in executing a given simple command
...@@ -108,5 +111,7 @@ CPU count real total virtual total delay total ...@@ -108,5 +111,7 @@ CPU count real total virtual total delay total
6 4000250 4000000 0 6 4000250 4000000 0
IO count delay total IO count delay total
0 0 0 0
MEM count delay total SWAP count delay total
0 0
RECLAIM count delay total
0 0 0 0
...@@ -196,14 +196,18 @@ void print_delayacct(struct taskstats *t) ...@@ -196,14 +196,18 @@ void print_delayacct(struct taskstats *t)
" %15llu%15llu%15llu%15llu\n" " %15llu%15llu%15llu%15llu\n"
"IO %15s%15s\n" "IO %15s%15s\n"
" %15llu%15llu\n" " %15llu%15llu\n"
"MEM %15s%15s\n" "SWAP %15s%15s\n"
" %15llu%15llu\n"
"RECLAIM %12s%15s\n"
" %15llu%15llu\n", " %15llu%15llu\n",
"count", "real total", "virtual total", "delay total", "count", "real total", "virtual total", "delay total",
t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total, t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
t->cpu_delay_total, t->cpu_delay_total,
"count", "delay total", "count", "delay total",
t->blkio_count, t->blkio_delay_total, t->blkio_count, t->blkio_delay_total,
"count", "delay total", t->swapin_count, t->swapin_delay_total); "count", "delay total", t->swapin_count, t->swapin_delay_total,
"count", "delay total",
t->freepages_count, t->freepages_delay_total);
} }
void task_context_switch_counts(struct taskstats *t) void task_context_switch_counts(struct taskstats *t)
......
...@@ -6,7 +6,7 @@ This document contains an explanation of the struct taskstats fields. ...@@ -6,7 +6,7 @@ This document contains an explanation of the struct taskstats fields.
There are three different groups of fields in the struct taskstats: There are three different groups of fields in the struct taskstats:
1) Common and basic accounting fields 1) Common and basic accounting fields
If CONFIG_TASKSTATS is set, the taskstats inteface is enabled and If CONFIG_TASKSTATS is set, the taskstats interface is enabled and
the common fields and basic accounting fields are collected for the common fields and basic accounting fields are collected for
delivery at do_exit() of a task. delivery at do_exit() of a task.
2) Delay accounting fields 2) Delay accounting fields
...@@ -26,6 +26,8 @@ There are three different groups of fields in the struct taskstats: ...@@ -26,6 +26,8 @@ There are three different groups of fields in the struct taskstats:
5) Time accounting for SMT machines 5) Time accounting for SMT machines
6) Extended delay accounting fields for memory reclaim
Future extension should add fields to the end of the taskstats struct, and Future extension should add fields to the end of the taskstats struct, and
should not change the relative position of each field within the struct. should not change the relative position of each field within the struct.
...@@ -170,4 +172,9 @@ struct taskstats { ...@@ -170,4 +172,9 @@ struct taskstats {
__u64 ac_utimescaled; /* utime scaled on frequency etc */ __u64 ac_utimescaled; /* utime scaled on frequency etc */
__u64 ac_stimescaled; /* stime scaled on frequency etc */ __u64 ac_stimescaled; /* stime scaled on frequency etc */
__u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */ __u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
6) Extended delay accounting fields for memory reclaim
/* Delay waiting for memory reclaim */
__u64 freepages_count;
__u64 freepages_delay_total;
} }
...@@ -32,7 +32,7 @@ Linux currently supports the following features on the IXP4xx chips: ...@@ -32,7 +32,7 @@ Linux currently supports the following features on the IXP4xx chips:
- Flash access (MTD/JFFS) - Flash access (MTD/JFFS)
- I2C through GPIO on IXP42x - I2C through GPIO on IXP42x
- GPIO for input/output/interrupts - GPIO for input/output/interrupts
See include/asm-arm/arch-ixp4xx/platform.h for access functions. See arch/arm/mach-ixp4xx/include/mach/platform.h for access functions.
- Timers (watchdog, OS) - Timers (watchdog, OS)
The following components of the chips are not supported by Linux and The following components of the chips are not supported by Linux and
......
...@@ -138,14 +138,8 @@ So, what's changed? ...@@ -138,14 +138,8 @@ So, what's changed?
Set active the IRQ edge(s)/level. This replaces the Set active the IRQ edge(s)/level. This replaces the
SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge() SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
function. Type should be one of the following: function. Type should be one of IRQ_TYPE_xxx defined in
<linux/irq.h>
#define IRQT_NOEDGE (0)
#define IRQT_RISING (__IRQT_RISEDGE)
#define IRQT_FALLING (__IRQT_FALEDGE)
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
#define IRQT_LOW (__IRQT_LOWLVL)
#define IRQT_HIGH (__IRQT_HIGHLVL)
3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type. 3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
...@@ -164,7 +158,7 @@ So, what's changed? ...@@ -164,7 +158,7 @@ So, what's changed?
be re-checked for pending events. (see the Neponset IRQ handler for be re-checked for pending events. (see the Neponset IRQ handler for
details). details).
7. fixup_irq() is gone, as is include/asm-arm/arch-*/irq.h 7. fixup_irq() is gone, as is arch/arm/mach-*/include/mach/irq.h
Please note that this will not solve all problems - some of them are Please note that this will not solve all problems - some of them are
hardware based. Mixing level-based and edge-based IRQs on the same hardware based. Mixing level-based and edge-based IRQs on the same
......
...@@ -79,7 +79,7 @@ Machine/Platform support ...@@ -79,7 +79,7 @@ Machine/Platform support
To this end, we now have arch/arm/mach-$(MACHINE) directories which are To this end, we now have arch/arm/mach-$(MACHINE) directories which are
designed to house the non-driver files for a particular machine (eg, PCI, designed to house the non-driver files for a particular machine (eg, PCI,
memory management, architecture definitions etc). For all future memory management, architecture definitions etc). For all future
machines, there should be a corresponding include/asm-arm/arch-$(MACHINE) machines, there should be a corresponding arch/arm/mach-$(MACHINE)/include/mach
directory. directory.
...@@ -176,7 +176,7 @@ Kernel entry (head.S) ...@@ -176,7 +176,7 @@ Kernel entry (head.S)
class typically based around one or more system on a chip devices, and class typically based around one or more system on a chip devices, and
acts as a natural container around the actual implementations. These acts as a natural container around the actual implementations. These
classes are given directories - arch/arm/mach-<class> and classes are given directories - arch/arm/mach-<class> and
include/asm-arm/arch-<class> - which contain the source files to arch/arm/mach-<class> - which contain the source files to/include/mach
support the machine class. This directories also contain any machine support the machine class. This directories also contain any machine
specific supporting code. specific supporting code.
......
...@@ -16,13 +16,13 @@ Introduction ...@@ -16,13 +16,13 @@ Introduction
Headers Headers
------- -------
See include/asm-arm/arch-s3c2410/regs-gpio.h for the list See arch/arm/mach-s3c2410/include/mach/regs-gpio.h for the list
of GPIO pins, and the configuration values for them. This of GPIO pins, and the configuration values for them. This
is included by using #include <asm/arch/regs-gpio.h> is included by using #include <mach/regs-gpio.h>
The GPIO management functions are defined in the hardware The GPIO management functions are defined in the hardware
header include/asm-arm/arch-s3c2410/hardware.h which can be header arch/arm/mach-s3c2410/include/mach/hardware.h which can be
included by #include <asm/arch/hardware.h> included by #include <mach/hardware.h>
A useful amount of documentation can be found in the hardware A useful amount of documentation can be found in the hardware
header on how the GPIO functions (and others) work. header on how the GPIO functions (and others) work.
......
...@@ -36,7 +36,7 @@ Layout ...@@ -36,7 +36,7 @@ Layout
in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440 in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
Register, kernel and platform data definitions are held in the Register, kernel and platform data definitions are held in the
include/asm-arm/arch-s3c2410 directory. arch/arm/mach-s3c2410 directory./include/mach
Machines Machines
......
...@@ -49,7 +49,7 @@ Board Support ...@@ -49,7 +49,7 @@ Board Support
Platform Data Platform Data
------------- -------------
See linux/include/asm-arm/arch-s3c2410/usb-control.h for the See arch/arm/mach-s3c2410/include/mach/usb-control.h for the
descriptions of the platform device data. An implementation descriptions of the platform device data. An implementation
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c . can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
......
===============================================================
== BT8XXGPIO driver ==
== ==
== A driver for a selfmade cheap BT8xx based PCI GPIO-card ==
== ==
== For advanced documentation, see ==
== http://www.bu3sch.de/btgpio.php ==
===============================================================
A generic digital 24-port PCI GPIO card can be built out of an ordinary
Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The
Brooktree chip is used in old analog Hauppauge WinTV PCI cards. You can easily
find them used for low prices on the net.
The bt8xx chip does have 24 digital GPIO ports.
These ports are accessible via 24 pins on the SMD chip package.
==============================================
== How to physically access the GPIO pins ==
==============================================
The are several ways to access these pins. One might unsolder the whole chip
and put it on a custom PCI board, or one might only unsolder each individual
GPIO pin and solder that to some tiny wire. As the chip package really is tiny
there are some advanced soldering skills needed in any case.
The physical pinouts are drawn in the following ASCII art.
The GPIO pins are marked with G00-G23
G G G G G G G G G G G G G G G G G G
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
---------------------------------------------------------------------------
--| ^ ^ |--
--| pin 86 pin 67 |--
--| |--
--| pin 61 > |-- G18
--| |-- G19
--| |-- G20
--| |-- G21
--| |-- G22
--| pin 56 > |-- G23
--| |--
--| Brooktree 878/879 |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| |--
--| O |--
--| |--
---------------------------------------------------------------------------
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
^
This is pin 1
#### cli()/sti() removal guide, started by Ingo Molnar <mingo@redhat.com>
as of 2.5.28, five popular macros have been removed on SMP, and
are being phased out on UP:
cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags)
until now it was possible to protect driver code against interrupt
handlers via a cli(), but from now on other, more lightweight methods
have to be used for synchronization, such as spinlocks or semaphores.
for example, driver code that used to do something like:
struct driver_data;
irq_handler (...)
{
....
driver_data.finish = 1;
driver_data.new_work = 0;
....
}
...
ioctl_func (...)
{
...
cli();
...
driver_data.finish = 0;
driver_data.new_work = 2;
...
sti();
...
}
was SMP-correct because the cli() function ensured that no
interrupt handler (amongst them the above irq_handler()) function
would execute while the cli()-ed section is executing.
but from now on a more direct method of locking has to be used:
DEFINE_SPINLOCK(driver_lock);
struct driver_data;
irq_handler (...)
{
unsigned long flags;
....
spin_lock_irqsave(&driver_lock, flags);
....
driver_data.finish = 1;
driver_data.new_work = 0;
....
spin_unlock_irqrestore(&driver_lock, flags);
....
}
...
ioctl_func (...)
{
...
spin_lock_irq(&driver_lock);
...
driver_data.finish = 0;
driver_data.new_work = 2;
...
spin_unlock_irq(&driver_lock);
...
}
the above code has a number of advantages:
- the locking relation is easier to understand - actual lock usage
pinpoints the critical sections. cli() usage is too opaque.
Easier to understand means it's easier to debug.
- it's faster, because spinlocks are faster to acquire than the
potentially heavily-used IRQ lock. Furthermore, your driver does
not have to wait eg. for a big heavy SCSI interrupt to finish,
because the driver_lock spinlock is only used by your driver.
cli() on the other hand was used by many drivers, and extended
the critical section to the whole IRQ handler function - creating
serious lock contention.
to make the transition easier, we've still kept the cli(), sti(),
save_flags(), save_flags_cli() and restore_flags() macros defined
on UP systems - but their usage will be phased out until 2.6 is
released.
drivers that want to disable local interrupts (interrupts on the
current CPU), can use the following five macros:
local_irq_disable(), local_irq_enable(), local_save_flags(flags),
local_irq_save(flags), local_irq_restore(flags)
but beware, their meaning and semantics are much simpler, far from
that of the old cli(), sti(), save_flags(flags) and restore_flags(flags)
SMP meaning:
local_irq_disable() => turn local IRQs off
local_irq_enable() => turn local IRQs on
local_save_flags(flags) => save the current IRQ state into flags. The
state can be on or off. (on some
architectures there's even more bits in it.)
local_irq_save(flags) => save the current IRQ state into flags and
disable interrupts.
local_irq_restore(flags) => restore the IRQ state from flags.
(local_irq_save can save both irqs on and irqs off state, and
local_irq_restore can restore into both irqs on and irqs off state.)
another related change is that synchronize_irq() now takes a parameter:
synchronize_irq(irq). This change too has the purpose of making SMP
synchronization more lightweight - this way you can wait for your own
interrupt handler to finish, no need to wait for other IRQ sources.
why were these changes done? The main reason was the architectural burden
of maintaining the cli()/sti() interface - it became a real problem. The
new interrupt system is much more streamlined, easier to understand, debug,
and it's also a bit faster - the same happened to it that will happen to
cli()/sti() using drivers once they convert to spinlocks :-)
...@@ -242,8 +242,7 @@ rmdir() if there are no tasks. ...@@ -242,8 +242,7 @@ rmdir() if there are no tasks.
1. Add support for accounting huge pages (as a separate controller) 1. Add support for accounting huge pages (as a separate controller)
2. Make per-cgroup scanner reclaim not-shared pages first 2. Make per-cgroup scanner reclaim not-shared pages first
3. Teach controller to account for shared-pages 3. Teach controller to account for shared-pages
4. Start reclamation when the limit is lowered 4. Start reclamation in the background when the limit is
5. Start reclamation in the background when the limit is
not yet hit but the usage is getting closer not yet hit but the usage is getting closer
Summary Summary
......
...@@ -122,7 +122,7 @@ around '10000' or more. ...@@ -122,7 +122,7 @@ around '10000' or more.
show_sampling_rate_(min|max): the minimum and maximum sampling rates show_sampling_rate_(min|max): the minimum and maximum sampling rates
available that you may set 'sampling_rate' to. available that you may set 'sampling_rate' to.
up_threshold: defines what the average CPU usaged between the samplings up_threshold: defines what the average CPU usage between the samplings
of 'sampling_rate' needs to be for the kernel to make a decision on of 'sampling_rate' needs to be for the kernel to make a decision on
whether it should increase the frequency. For example when it is set whether it should increase the frequency. For example when it is set
to its default value of '80' it means that between the checking to its default value of '80' it means that between the checking
......
...@@ -222,74 +222,9 @@ both csrow2 and csrow3 are populated, this indicates a dual ranked ...@@ -222,74 +222,9 @@ both csrow2 and csrow3 are populated, this indicates a dual ranked
set of DIMMs for channels 0 and 1. set of DIMMs for channels 0 and 1.
Within each of the 'mc','mcX' and 'csrowX' directories are several Within each of the 'mcX' and 'csrowX' directories are several
EDAC control and attribute files. EDAC control and attribute files.
============================================================================
DIRECTORY 'mc'
In directory 'mc' are EDAC system overall control and attribute files:
Panic on UE control file:
'edac_mc_panic_on_ue'
An uncorrectable error will cause a machine panic. This is usually
desirable. It is a bad idea to continue when an uncorrectable error
occurs - it is indeterminate what was uncorrected and the operating
system context might be so mangled that continuing will lead to further
corruption. If the kernel has MCE configured, then EDAC will never
notice the UE.
LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_panic_on_ue
Log UE control file:
'edac_mc_log_ue'
Generate kernel messages describing uncorrectable errors. These errors
are reported through the system message log system. UE statistics
will be accumulated even when UE logging is disabled.
LOAD TIME: module/kernel parameter: log_ue=[0|1]
RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ue
Log CE control file:
'edac_mc_log_ce'
Generate kernel messages describing correctable errors. These
errors are reported through the system message log system.
CE statistics will be accumulated even when CE logging is disabled.
LOAD TIME: module/kernel parameter: log_ce=[0|1]
RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ce
Polling period control file:
'edac_mc_poll_msec'
The time period, in milliseconds, for polling for error information.
Too small a value wastes resources. Too large a value might delay
necessary handling of errors and might loose valuable information for
locating the error. 1000 milliseconds (once each second) is the current
default. Systems which require all the bandwidth they can get, may
increase this.
LOAD TIME: module/kernel parameter: poll_msec=[0|1]
RUN TIME: echo "1000" >/sys/devices/system/edac/mc/edac_mc_poll_msec
============================================================================ ============================================================================
'mcX' DIRECTORIES 'mcX' DIRECTORIES
...@@ -392,7 +327,7 @@ Sdram memory scrubbing rate: ...@@ -392,7 +327,7 @@ Sdram memory scrubbing rate:
'sdram_scrub_rate' 'sdram_scrub_rate'
Read/Write attribute file that controls memory scrubbing. The scrubbing Read/Write attribute file that controls memory scrubbing. The scrubbing
rate is set by writing a minimum bandwith in bytes/sec to the attribute rate is set by writing a minimum bandwidth in bytes/sec to the attribute
file. The rate will be translated to an internal value that gives at file. The rate will be translated to an internal value that gives at
least the specified rate. least the specified rate.
...@@ -537,7 +472,6 @@ Channel 1 DIMM Label control file: ...@@ -537,7 +472,6 @@ Channel 1 DIMM Label control file:
motherboard specific and determination of this information motherboard specific and determination of this information
must occur in userland at this time. must occur in userland at this time.
============================================================================ ============================================================================
SYSTEM LOGGING SYSTEM LOGGING
...@@ -570,7 +504,6 @@ error type, a notice of "no info" and then an optional, ...@@ -570,7 +504,6 @@ error type, a notice of "no info" and then an optional,
driver-specific error message. driver-specific error message.
============================================================================ ============================================================================
PCI Bus Parity Detection PCI Bus Parity Detection
...@@ -604,6 +537,74 @@ Enable/Disable PCI Parity checking control file: ...@@ -604,6 +537,74 @@ Enable/Disable PCI Parity checking control file:
echo "0" >/sys/devices/system/edac/pci/check_pci_parity echo "0" >/sys/devices/system/edac/pci/check_pci_parity
Parity Count:
'pci_parity_count'
This attribute file will display the number of parity errors that
have been detected.
============================================================================
MODULE PARAMETERS
Panic on UE control file:
'edac_mc_panic_on_ue'
An uncorrectable error will cause a machine panic. This is usually
desirable. It is a bad idea to continue when an uncorrectable error
occurs - it is indeterminate what was uncorrected and the operating
system context might be so mangled that continuing will lead to further
corruption. If the kernel has MCE configured, then EDAC will never
notice the UE.
LOAD TIME: module/kernel parameter: edac_mc_panic_on_ue=[0|1]
RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
Log UE control file:
'edac_mc_log_ue'
Generate kernel messages describing uncorrectable errors. These errors
are reported through the system message log system. UE statistics
will be accumulated even when UE logging is disabled.
LOAD TIME: module/kernel parameter: edac_mc_log_ue=[0|1]
RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
Log CE control file:
'edac_mc_log_ce'
Generate kernel messages describing correctable errors. These
errors are reported through the system message log system.
CE statistics will be accumulated even when CE logging is disabled.
LOAD TIME: module/kernel parameter: edac_mc_log_ce=[0|1]
RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
Polling period control file:
'edac_mc_poll_msec'
The time period, in milliseconds, for polling for error information.
Too small a value wastes resources. Too large a value might delay
necessary handling of errors and might loose valuable information for
locating the error. 1000 milliseconds (once each second) is the current
default. Systems which require all the bandwidth they can get, may
increase this.
LOAD TIME: module/kernel parameter: edac_mc_poll_msec=[0|1]
RUN TIME: echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
Panic on PCI PARITY Error: Panic on PCI PARITY Error:
...@@ -614,21 +615,13 @@ Panic on PCI PARITY Error: ...@@ -614,21 +615,13 @@ Panic on PCI PARITY Error:
error has been detected. error has been detected.
module/kernel parameter: panic_on_pci_parity=[0|1] module/kernel parameter: edac_panic_on_pci_pe=[0|1]
Enable: Enable:
echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
Disable: Disable:
echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
Parity Count:
'pci_parity_count'
This attribute file will display the number of parity errors that
have been detected.
......
SH7760/SH7763 integrated LCDC Framebuffer driver
================================================
0. Overwiew
-----------
The SH7760/SH7763 have an integrated LCD Display controller (LCDC) which
supports (in theory) resolutions ranging from 1x1 to 1024x1024,
with color depths ranging from 1 to 16 bits, on STN, DSTN and TFT Panels.
Caveats:
* Framebuffer memory must be a large chunk allocated at the top
of Area3 (HW requirement). Because of this requirement you should NOT
make the driver a module since at runtime it may become impossible to
get a large enough contiguous chunk of memory.
* The driver does not support changing resolution while loaded
(displays aren't hotpluggable anyway)
* Heavy flickering may be observed
a) if you're using 15/16bit color modes at >= 640x480 px resolutions,
b) during PCMCIA (or any other slow bus) activity.
* Rotation works only 90degress clockwise, and only if horizontal
resolution is <= 320 pixels.
files: drivers/video/sh7760fb.c
include/asm-sh/sh7760fb.h
Documentation/fb/sh7760fb.txt
1. Platform setup
-----------------
SH7760:
Video data is fetched via the DMABRG DMA engine, so you have to
configure the SH DMAC for DMABRG mode (write 0x94808080 to the
DMARSRA register somewhere at boot).
PFC registers PCCR and PCDR must be set to peripheral mode.
(write zeros to both).
The driver does NOT do the above for you since board setup is, well, job
of the board setup code.
2. Panel definitions
--------------------
The LCDC must explicitly be told about the type of LCD panel
attached. Data must be wrapped in a "struct sh7760fb_platdata" and
passed to the driver as platform_data.
Suggest you take a closer look at the SH7760 Manual, Section 30.
(http://documentation.renesas.com/eng/products/mpumcu/e602291_sh7760.pdf)
The following code illustrates what needs to be done to
get the framebuffer working on a 640x480 TFT:
====================== cut here ======================================
#include <linux/fb.h>
#include <asm/sh7760fb.h>
/*
* NEC NL6440bc26-01 640x480 TFT
* dotclock 25175 kHz
* Xres 640 Yres 480
* Htotal 800 Vtotal 525
* HsynStart 656 VsynStart 490
* HsynLenn 30 VsynLenn 2
*
* The linux framebuffer layer does not use the syncstart/synclen
* values but right/left/upper/lower margin values. The comments
* for the x_margin explain how to calculate those from given
* panel sync timings.
*/
static struct fb_videomode nl6448bc26 = {
.name = "NL6448BC26",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39683, /* in picoseconds! */
.hsync_len = 30,
.vsync_len = 2,
.left_margin = 114, /* HTOT - (HSYNSLEN + HSYNSTART) */
.right_margin = 16, /* HSYNSTART - XRES */
.upper_margin = 33, /* VTOT - (VSYNLEN + VSYNSTART) */
.lower_margin = 10, /* VSYNSTART - YRES */
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
.flag = 0,
};
static struct sh7760fb_platdata sh7760fb_nl6448 = {
.def_mode = &nl6448bc26,
.ldmtr = LDMTR_TFT_COLOR_16, /* 16bit TFT panel */
.lddfr = LDDFR_8BPP, /* we want 8bit output */
.ldpmmr = 0x0070,
.ldpspr = 0x0500,
.ldaclnr = 0,
.ldickr = LDICKR_CLKSRC(LCDC_CLKSRC_EXTERNAL) |
LDICKR_CLKDIV(1),
.rotate = 0,
.novsync = 1,
.blank = NULL,
};
/* SH7760:
* 0xFE300800: 256 * 4byte xRGB palette ram
* 0xFE300C00: 42 bytes ctrl registers
*/
static struct resource sh7760_lcdc_res[] = {
[0] = {
.start = 0xFE300800,
.end = 0xFE300CFF,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 65,
.end = 65,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device sh7760_lcdc_dev = {
.dev = {
.platform_data = &sh7760fb_nl6448,
},
.name = "sh7760-lcdc",
.id = -1,
.resource = sh7760_lcdc_res,
.num_resources = ARRAY_SIZE(sh7760_lcdc_res),
};
====================== cut here ======================================
...@@ -3,11 +3,25 @@ Tridentfb is a framebuffer driver for some Trident chip based cards. ...@@ -3,11 +3,25 @@ Tridentfb is a framebuffer driver for some Trident chip based cards.
The following list of chips is thought to be supported although not all are The following list of chips is thought to be supported although not all are
tested: tested:
those from the Image series with Cyber in their names - accelerated those from the TGUI series 9440/96XX and with Cyber in their names
those with Blade in their names (Blade3D,CyberBlade...) - accelerated those from the Image series and with Cyber in their names
the newer CyberBladeXP family - nonaccelerated those with Blade in their names (Blade3D,CyberBlade...)
the newer CyberBladeXP family
Only PCI/AGP based cards are supported, none of the older Tridents.
All families are accelerated. Only PCI/AGP based cards are supported,
none of the older Tridents.
The driver supports 8, 16 and 32 bits per pixel depths.
The TGUI family requires a line length to be power of 2 if acceleration
is enabled. This means that range of possible resolutions and bpp is
limited comparing to the range if acceleration is disabled (see list
of parameters below).
Known bugs:
1. The driver randomly locks up on 3DImage975 chip with acceleration
enabled. The same happens in X11 (Xorg).
2. The ramdac speeds require some more fine tuning. It is possible to
switch resolution which the chip does not support at some depths for
older chips.
How to use it? How to use it?
============== ==============
...@@ -17,12 +31,11 @@ video=tridentfb ...@@ -17,12 +31,11 @@ video=tridentfb
The parameters for tridentfb are concatenated with a ':' as in this example. The parameters for tridentfb are concatenated with a ':' as in this example.
video=tridentfb:800x600,bpp=16,noaccel video=tridentfb:800x600-16@75,noaccel
The second level parameters that tridentfb understands are: The second level parameters that tridentfb understands are:
noaccel - turns off acceleration (when it doesn't work for your card) noaccel - turns off acceleration (when it doesn't work for your card)
accel - force text acceleration (for boards which by default are noacceled)
fp - use flat panel related stuff fp - use flat panel related stuff
crt - assume monitor is present instead of fp crt - assume monitor is present instead of fp
...@@ -31,21 +44,24 @@ center - for flat panels and resolutions smaller than native size center the ...@@ -31,21 +44,24 @@ center - for flat panels and resolutions smaller than native size center the
image, otherwise use image, otherwise use
stretch stretch
memsize - integer value in Kb, use if your card's memory size is misdetected. memsize - integer value in KB, use if your card's memory size is misdetected.
look at the driver output to see what it says when initializing. look at the driver output to see what it says when initializing.
memdiff - integer value in Kb,should be nonzero if your card reports
more memory than it actually has.For instance mine is 192K less than memdiff - integer value in KB, should be nonzero if your card reports
more memory than it actually has. For instance mine is 192K less than
detection says in all three BIOS selectable situations 2M, 4M, 8M. detection says in all three BIOS selectable situations 2M, 4M, 8M.
Only use if your video memory is taken from main memory hence of Only use if your video memory is taken from main memory hence of
configurable size.Otherwise use memsize. configurable size. Otherwise use memsize.
If in some modes which barely fit the memory you see garbage at the bottom If in some modes which barely fit the memory you see garbage
this might help by not letting change to that mode anymore. at the bottom this might help by not letting change to that mode
anymore.
nativex - the width in pixels of the flat panel.If you know it (usually 1024 nativex - the width in pixels of the flat panel.If you know it (usually 1024
800 or 1280) and it is not what the driver seems to detect use it. 800 or 1280) and it is not what the driver seems to detect use it.
bpp - bits per pixel (8,16 or 32) bpp - bits per pixel (8,16 or 32)
mode - a mode name like 800x600 (as described in Documentation/fb/modedb.txt) mode - a mode name like 800x600-8@75 as described in
Documentation/fb/modedb.txt
Using insane values for the above parameters will probably result in driver Using insane values for the above parameters will probably result in driver
misbehaviour so take care(for instance memsize=12345678 or memdiff=23784 or misbehaviour so take care(for instance memsize=12345678 or memdiff=23784 or
......
...@@ -47,6 +47,30 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org> ...@@ -47,6 +47,30 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
--------------------------- ---------------------------
What: old tuner-3036 i2c driver
When: 2.6.28
Why: This driver is for VERY old i2c-over-parallel port teletext receiver
boxes. Rather then spending effort on converting this driver to V4L2,
and since it is extremely unlikely that anyone still uses one of these
devices, it was decided to drop it.
Who: Hans Verkuil <hverkuil@xs4all.nl>
Mauro Carvalho Chehab <mchehab@infradead.org>
---------------------------
What: V4L2 dpc7146 driver
When: 2.6.28
Why: Old driver for the dpc7146 demonstration board that is no longer
relevant. The last time this was tested on actual hardware was
probably around 2002. Since this is a driver for a demonstration
board the decision was made to remove it rather than spending a
lot of effort continually updating this driver to stay in sync
with the latest internal V4L2 or I2C API.
Who: Hans Verkuil <hverkuil@xs4all.nl>
Mauro Carvalho Chehab <mchehab@infradead.org>
---------------------------
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl]) What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
When: November 2005 When: November 2005
Files: drivers/pcmcia/: pcmcia_ioctl.c Files: drivers/pcmcia/: pcmcia_ioctl.c
...@@ -138,24 +162,6 @@ Who: Kay Sievers <kay.sievers@suse.de> ...@@ -138,24 +162,6 @@ Who: Kay Sievers <kay.sievers@suse.de>
--------------------------- ---------------------------
What: find_task_by_pid
When: 2.6.26
Why: With pid namespaces, calling this funciton will return the
wrong task when called from inside a namespace.
The best way to save a task pid and find a task by this
pid later, is to find this task's struct pid pointer (or get
it directly from the task) and call pid_task() later.
If someone really needs to get a task by its pid_t, then
he most likely needs the find_task_by_vpid() to get the
task from the same namespace as the current task is in, but
this may be not so in general.
Who: Pavel Emelyanov <xemul@openvz.org>
---------------------------
What: ACPI procfs interface What: ACPI procfs interface
When: July 2008 When: July 2008
Why: ACPI sysfs conversion should be finished by January 2008. Why: ACPI sysfs conversion should be finished by January 2008.
...@@ -300,11 +306,15 @@ Who: ocfs2-devel@oss.oracle.com ...@@ -300,11 +306,15 @@ Who: ocfs2-devel@oss.oracle.com
--------------------------- ---------------------------
What: asm/semaphore.h What: SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD,
When: 2.6.26 SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD
Why: Implementation became generic; users should now include When: June 2009
linux/semaphore.h instead. Why: A newer version of the options have been introduced in 2005 that
Who: Matthew Wilcox <willy@linux.intel.com> removes the limitions of the old API. The sctp library has been
converted to use these new options at the same time. Any user
space app that directly uses the old options should convert to using
the new options.
Who: Vlad Yasevich <vladislav.yasevich@hp.com>
--------------------------- ---------------------------
...@@ -314,3 +324,23 @@ Why: This option was introduced just to allow older lm-sensors userspace ...@@ -314,3 +324,23 @@ Why: This option was introduced just to allow older lm-sensors userspace
to keep working over the upgrade to 2.6.26. At the scheduled time of to keep working over the upgrade to 2.6.26. At the scheduled time of
removal fixed lm-sensors (2.x or 3.x) should be readily available. removal fixed lm-sensors (2.x or 3.x) should be readily available.
Who: Rene Herman <rene.herman@gmail.com> Who: Rene Herman <rene.herman@gmail.com>
---------------------------
What: Code that is now under CONFIG_WIRELESS_EXT_SYSFS
(in net/core/net-sysfs.c)
When: After the only user (hal) has seen a release with the patches
for enough time, probably some time in 2010.
Why: Over 1K .text/.data size reduction, data is available in other
ways (ioctls)
Who: Johannes Berg <johannes@sipsolutions.net>
---------------------------
What: CONFIG_NF_CT_ACCT
When: 2.6.29
Why: Accounting can now be enabled/disabled without kernel recompilation.
Currently used only to set a default value for a feature that is also
controlled by a kernel/module/sysfs/sysctl parameter.
Who: Krzysztof Piotr Oledzki <ole@ans.pl>
...@@ -510,6 +510,7 @@ prototypes: ...@@ -510,6 +510,7 @@ prototypes:
void (*close)(struct vm_area_struct*); void (*close)(struct vm_area_struct*);
int (*fault)(struct vm_area_struct*, struct vm_fault *); int (*fault)(struct vm_area_struct*, struct vm_fault *);
int (*page_mkwrite)(struct vm_area_struct *, struct page *); int (*page_mkwrite)(struct vm_area_struct *, struct page *);
int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
locking rules: locking rules:
BKL mmap_sem PageLocked(page) BKL mmap_sem PageLocked(page)
...@@ -517,6 +518,7 @@ open: no yes ...@@ -517,6 +518,7 @@ open: no yes
close: no yes close: no yes
fault: no yes fault: no yes
page_mkwrite: no yes no page_mkwrite: no yes no
access: no yes
->page_mkwrite() is called when a previously read-only page is ->page_mkwrite() is called when a previously read-only page is
about to become writeable. The file system is responsible for about to become writeable. The file system is responsible for
...@@ -525,6 +527,11 @@ taking to lock out truncate, the page range should be verified to be ...@@ -525,6 +527,11 @@ taking to lock out truncate, the page range should be verified to be
within i_size. The page mapping should also be checked that it is not within i_size. The page mapping should also be checked that it is not
NULL. NULL.
->access() is called when get_user_pages() fails in
acces_process_vm(), typically used to debug a process through
/proc/pid/mem or ptrace. This function is needed only for
VM_IO | VM_PFNMAP VMAs.
================================================================================ ================================================================================
Dubious stuff Dubious stuff
......
...@@ -26,11 +26,11 @@ You can simplify mounting by just typing: ...@@ -26,11 +26,11 @@ You can simplify mounting by just typing:
this will allocate the first available loopback device (and load loop.o this will allocate the first available loopback device (and load loop.o
kernel module if necessary) automatically. If the loopback driver is not kernel module if necessary) automatically. If the loopback driver is not
loaded automatically, make sure that your kernel is compiled with kmod loaded automatically, make sure that you have compiled the module and
support (CONFIG_KMOD) enabled. Beware that umount will not that modprobe is functioning. Beware that umount will not deallocate
deallocate /dev/loopN device if /etc/mtab file on your system is a /dev/loopN device if /etc/mtab file on your system is a symbolic link to
symbolic link to /proc/mounts. You will need to do it manually using /proc/mounts. You will need to do it manually using "-d" switch of
"-d" switch of losetup(8). Read losetup(8) manpage for more info. losetup(8). Read losetup(8) manpage for more info.
To create the BFS image under UnixWare you need to find out first which To create the BFS image under UnixWare you need to find out first which
slice contains it. The command prtvtoc(1M) is your friend: slice contains it. The command prtvtoc(1M) is your friend:
......
...@@ -311,9 +311,20 @@ the subsystem must be ready for it. ...@@ -311,9 +311,20 @@ the subsystem must be ready for it.
[An Example] [An Example]
The best example of these basic concepts is the simple_children The best example of these basic concepts is the simple_children
subsystem/group and the simple_child item in configfs_example.c It subsystem/group and the simple_child item in configfs_example_explicit.c
shows a trivial object displaying and storing an attribute, and a simple and configfs_example_macros.c. It shows a trivial object displaying and
group creating and destroying these children. storing an attribute, and a simple group creating and destroying these
children.
The only difference between configfs_example_explicit.c and
configfs_example_macros.c is how the attributes of the childless item
are defined. The childless item has extended attributes, each with
their own show()/store() operation. This follows a convention commonly
used in sysfs. configfs_example_explicit.c creates these attributes
by explicitly defining the structures involved. Conversely
configfs_example_macros.c uses some convenience macros from configfs.h
to define the attributes. These macros are similar to their sysfs
counterparts.
[Hierarchy Navigation and the Subsystem Mutex] [Hierarchy Navigation and the Subsystem Mutex]
......
/*
* vim: noexpandtab ts=8 sts=0 sw=8:
*
* configfs_example.c - This file is a demonstration module containing
* a number of configfs subsystems.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
* Based on sysfs:
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
*
* configfs Copyright (C) 2005 Oracle. All rights reserved.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/configfs.h>
/*
* 01-childless
*
* This first example is a childless subsystem. It cannot create
* any config_items. It just has attributes.
*
* Note that we are enclosing the configfs_subsystem inside a container.
* This is not necessary if a subsystem has no attributes directly
* on the subsystem. See the next example, 02-simple-children, for
* such a subsystem.
*/
struct childless {
struct configfs_subsystem subsys;
int showme;
int storeme;
};
struct childless_attribute {
struct configfs_attribute attr;
ssize_t (*show)(struct childless *, char *);
ssize_t (*store)(struct childless *, const char *, size_t);
};
static inline struct childless *to_childless(struct config_item *item)
{
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
}
static ssize_t childless_showme_read(struct childless *childless,
char *page)
{
ssize_t pos;
pos = sprintf(page, "%d\n", childless->showme);
childless->showme++;
return pos;
}
static ssize_t childless_storeme_read(struct childless *childless,
char *page)
{
return sprintf(page, "%d\n", childless->storeme);
}
static ssize_t childless_storeme_write(struct childless *childless,
const char *page,
size_t count)
{
unsigned long tmp;
char *p = (char *) page;
tmp = simple_strtoul(p, &p, 10);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp > INT_MAX)
return -ERANGE;
childless->storeme = tmp;
return count;
}
static ssize_t childless_description_read(struct childless *childless,
char *page)
{
return sprintf(page,
"[01-childless]\n"
"\n"
"The childless subsystem is the simplest possible subsystem in\n"
"configfs. It does not support the creation of child config_items.\n"
"It only has a few attributes. In fact, it isn't much different\n"
"than a directory in /proc.\n");
}
static struct childless_attribute childless_attr_showme = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
.show = childless_showme_read,
};
static struct childless_attribute childless_attr_storeme = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
.show = childless_storeme_read,
.store = childless_storeme_write,
};
static struct childless_attribute childless_attr_description = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
.show = childless_description_read,
};
static struct configfs_attribute *childless_attrs[] = {
&childless_attr_showme.attr,
&childless_attr_storeme.attr,
&childless_attr_description.attr,
NULL,
};
static ssize_t childless_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
struct childless *childless = to_childless(item);
struct childless_attribute *childless_attr =
container_of(attr, struct childless_attribute, attr);
ssize_t ret = 0;
if (childless_attr->show)
ret = childless_attr->show(childless, page);
return ret;
}
static ssize_t childless_attr_store(struct config_item *item,
struct configfs_attribute *attr,
const char *page, size_t count)
{
struct childless *childless = to_childless(item);
struct childless_attribute *childless_attr =
container_of(attr, struct childless_attribute, attr);
ssize_t ret = -EINVAL;
if (childless_attr->store)
ret = childless_attr->store(childless, page, count);
return ret;
}
static struct configfs_item_operations childless_item_ops = {
.show_attribute = childless_attr_show,
.store_attribute = childless_attr_store,
};
static struct config_item_type childless_type = {
.ct_item_ops = &childless_item_ops,
.ct_attrs = childless_attrs,
.ct_owner = THIS_MODULE,
};
static struct childless childless_subsys = {
.subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "01-childless",
.ci_type = &childless_type,
},
},
},
};
/* ----------------------------------------------------------------- */
/*
* 02-simple-children
*
* This example merely has a simple one-attribute child. Note that
* there is no extra attribute structure, as the child's attribute is
* known from the get-go. Also, there is no container for the
* subsystem, as it has no attributes of its own.
*/
struct simple_child {
struct config_item item;
int storeme;
};
static inline struct simple_child *to_simple_child(struct config_item *item)
{
return item ? container_of(item, struct simple_child, item) : NULL;
}
static struct configfs_attribute simple_child_attr_storeme = {
.ca_owner = THIS_MODULE,
.ca_name = "storeme",
.ca_mode = S_IRUGO | S_IWUSR,
};
static struct configfs_attribute *simple_child_attrs[] = {
&simple_child_attr_storeme,
NULL,
};
static ssize_t simple_child_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
ssize_t count;
struct simple_child *simple_child = to_simple_child(item);
count = sprintf(page, "%d\n", simple_child->storeme);
return count;
}
static ssize_t simple_child_attr_store(struct config_item *item,
struct configfs_attribute *attr,
const char *page, size_t count)
{
struct simple_child *simple_child = to_simple_child(item);
unsigned long tmp;
char *p = (char *) page;
tmp = simple_strtoul(p, &p, 10);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp > INT_MAX)
return -ERANGE;
simple_child->storeme = tmp;
return count;
}
static void simple_child_release(struct config_item *item)
{
kfree(to_simple_child(item));
}
static struct configfs_item_operations simple_child_item_ops = {
.release = simple_child_release,
.show_attribute = simple_child_attr_show,
.store_attribute = simple_child_attr_store,
};
static struct config_item_type simple_child_type = {
.ct_item_ops = &simple_child_item_ops,
.ct_attrs = simple_child_attrs,
.ct_owner = THIS_MODULE,
};
struct simple_children {
struct config_group group;
};
static inline struct simple_children *to_simple_children(struct config_item *item)
{
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
}
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
{
struct simple_child *simple_child;
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
if (!simple_child)
return NULL;
config_item_init_type_name(&simple_child->item, name,
&simple_child_type);
simple_child->storeme = 0;
return &simple_child->item;
}
static struct configfs_attribute simple_children_attr_description = {
.ca_owner = THIS_MODULE,
.ca_name = "description",
.ca_mode = S_IRUGO,
};
static struct configfs_attribute *simple_children_attrs[] = {
&simple_children_attr_description,
NULL,
};
static ssize_t simple_children_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
return sprintf(page,
"[02-simple-children]\n"
"\n"
"This subsystem allows the creation of child config_items. These\n"
"items have only one attribute that is readable and writeable.\n");
}
static void simple_children_release(struct config_item *item)
{
kfree(to_simple_children(item));
}
static struct configfs_item_operations simple_children_item_ops = {
.release = simple_children_release,
.show_attribute = simple_children_attr_show,
};
/*
* Note that, since no extra work is required on ->drop_item(),
* no ->drop_item() is provided.
*/
static struct configfs_group_operations simple_children_group_ops = {
.make_item = simple_children_make_item,
};
static struct config_item_type simple_children_type = {
.ct_item_ops = &simple_children_item_ops,
.ct_group_ops = &simple_children_group_ops,
.ct_attrs = simple_children_attrs,
.ct_owner = THIS_MODULE,
};
static struct configfs_subsystem simple_children_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "02-simple-children",
.ci_type = &simple_children_type,
},
},
};
/* ----------------------------------------------------------------- */
/*
* 03-group-children
*
* This example reuses the simple_children group from above. However,
* the simple_children group is not the subsystem itself, it is a
* child of the subsystem. Creation of a group in the subsystem creates
* a new simple_children group. That group can then have simple_child
* children of its own.
*/
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
{
struct simple_children *simple_children;
simple_children = kzalloc(sizeof(struct simple_children),
GFP_KERNEL);
if (!simple_children)
return NULL;
config_group_init_type_name(&simple_children->group, name,
&simple_children_type);
return &simple_children->group;
}
static struct configfs_attribute group_children_attr_description = {
.ca_owner = THIS_MODULE,
.ca_name = "description",
.ca_mode = S_IRUGO,
};
static struct configfs_attribute *group_children_attrs[] = {
&group_children_attr_description,
NULL,
};
static ssize_t group_children_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
return sprintf(page,
"[03-group-children]\n"
"\n"
"This subsystem allows the creation of child config_groups. These\n"
"groups are like the subsystem simple-children.\n");
}
static struct configfs_item_operations group_children_item_ops = {
.show_attribute = group_children_attr_show,
};
/*
* Note that, since no extra work is required on ->drop_item(),
* no ->drop_item() is provided.
*/
static struct configfs_group_operations group_children_group_ops = {
.make_group = group_children_make_group,
};
static struct config_item_type group_children_type = {
.ct_item_ops = &group_children_item_ops,
.ct_group_ops = &group_children_group_ops,
.ct_attrs = group_children_attrs,
.ct_owner = THIS_MODULE,
};
static struct configfs_subsystem group_children_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "03-group-children",
.ci_type = &group_children_type,
},
},
};
/* ----------------------------------------------------------------- */
/*
* We're now done with our subsystem definitions.
* For convenience in this module, here's a list of them all. It
* allows the init function to easily register them. Most modules
* will only have one subsystem, and will only call register_subsystem
* on it directly.
*/
static struct configfs_subsystem *example_subsys[] = {
&childless_subsys.subsys,
&simple_children_subsys,
&group_children_subsys,
NULL,
};
static int __init configfs_example_init(void)
{
int ret;
int i;
struct configfs_subsystem *subsys;
for (i = 0; example_subsys[i]; i++) {
subsys = example_subsys[i];
config_group_init(&subsys->su_group);
mutex_init(&subsys->su_mutex);
ret = configfs_register_subsystem(subsys);
if (ret) {
printk(KERN_ERR "Error %d while registering subsystem %s\n",
ret,
subsys->su_group.cg_item.ci_namebuf);
goto out_unregister;
}
}
return 0;
out_unregister:
for (; i >= 0; i--) {
configfs_unregister_subsystem(example_subsys[i]);
}
return ret;
}
static void __exit configfs_example_exit(void)
{
int i;
for (i = 0; example_subsys[i]; i++) {
configfs_unregister_subsystem(example_subsys[i]);
}
}
module_init(configfs_example_init);
module_exit(configfs_example_exit);
MODULE_LICENSE("GPL");
/*
* vim: noexpandtab ts=8 sts=0 sw=8:
*
* configfs_example_explicit.c - This file is a demonstration module
* containing a number of configfs subsystems. It explicitly defines
* each structure without using the helper macros defined in
* configfs.h.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
* Based on sysfs:
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
*
* configfs Copyright (C) 2005 Oracle. All rights reserved.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/configfs.h>
/*
* 01-childless
*
* This first example is a childless subsystem. It cannot create
* any config_items. It just has attributes.
*
* Note that we are enclosing the configfs_subsystem inside a container.
* This is not necessary if a subsystem has no attributes directly
* on the subsystem. See the next example, 02-simple-children, for
* such a subsystem.
*/
struct childless {
struct configfs_subsystem subsys;
int showme;
int storeme;
};
struct childless_attribute {
struct configfs_attribute attr;
ssize_t (*show)(struct childless *, char *);
ssize_t (*store)(struct childless *, const char *, size_t);
};
static inline struct childless *to_childless(struct config_item *item)
{
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
}
static ssize_t childless_showme_read(struct childless *childless,
char *page)
{
ssize_t pos;
pos = sprintf(page, "%d\n", childless->showme);
childless->showme++;
return pos;
}
static ssize_t childless_storeme_read(struct childless *childless,
char *page)
{
return sprintf(page, "%d\n", childless->storeme);
}
static ssize_t childless_storeme_write(struct childless *childless,
const char *page,
size_t count)
{
unsigned long tmp;
char *p = (char *) page;
tmp = simple_strtoul(p, &p, 10);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp > INT_MAX)
return -ERANGE;
childless->storeme = tmp;
return count;
}
static ssize_t childless_description_read(struct childless *childless,
char *page)
{
return sprintf(page,
"[01-childless]\n"
"\n"
"The childless subsystem is the simplest possible subsystem in\n"
"configfs. It does not support the creation of child config_items.\n"
"It only has a few attributes. In fact, it isn't much different\n"
"than a directory in /proc.\n");
}
static struct childless_attribute childless_attr_showme = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
.show = childless_showme_read,
};
static struct childless_attribute childless_attr_storeme = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
.show = childless_storeme_read,
.store = childless_storeme_write,
};
static struct childless_attribute childless_attr_description = {
.attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
.show = childless_description_read,
};
static struct configfs_attribute *childless_attrs[] = {
&childless_attr_showme.attr,
&childless_attr_storeme.attr,
&childless_attr_description.attr,
NULL,
};
static ssize_t childless_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
struct childless *childless = to_childless(item);
struct childless_attribute *childless_attr =
container_of(attr, struct childless_attribute, attr);
ssize_t ret = 0;
if (childless_attr->show)
ret = childless_attr->show(childless, page);
return ret;
}
static ssize_t childless_attr_store(struct config_item *item,
struct configfs_attribute *attr,
const char *page, size_t count)
{
struct childless *childless = to_childless(item);
struct childless_attribute *childless_attr =
container_of(attr, struct childless_attribute, attr);
ssize_t ret = -EINVAL;
if (childless_attr->store)
ret = childless_attr->store(childless, page, count);
return ret;
}
static struct configfs_item_operations childless_item_ops = {
.show_attribute = childless_attr_show,
.store_attribute = childless_attr_store,
};
static struct config_item_type childless_type = {
.ct_item_ops = &childless_item_ops,
.ct_attrs = childless_attrs,
.ct_owner = THIS_MODULE,
};
static struct childless childless_subsys = {
.subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "01-childless",
.ci_type = &childless_type,
},
},
},
};
/* ----------------------------------------------------------------- */
/*
* 02-simple-children
*
* This example merely has a simple one-attribute child. Note that
* there is no extra attribute structure, as the child's attribute is
* known from the get-go. Also, there is no container for the
* subsystem, as it has no attributes of its own.
*/
struct simple_child {
struct config_item item;
int storeme;
};
static inline struct simple_child *to_simple_child(struct config_item *item)
{
return item ? container_of(item, struct simple_child, item) : NULL;
}
static struct configfs_attribute simple_child_attr_storeme = {
.ca_owner = THIS_MODULE,
.ca_name = "storeme",
.ca_mode = S_IRUGO | S_IWUSR,
};
static struct configfs_attribute *simple_child_attrs[] = {
&simple_child_attr_storeme,
NULL,
};
static ssize_t simple_child_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
ssize_t count;
struct simple_child *simple_child = to_simple_child(item);
count = sprintf(page, "%d\n", simple_child->storeme);
return count;
}
static ssize_t simple_child_attr_store(struct config_item *item,
struct configfs_attribute *attr,
const char *page, size_t count)
{
struct simple_child *simple_child = to_simple_child(item);
unsigned long tmp;
char *p = (char *) page;
tmp = simple_strtoul(p, &p, 10);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp > INT_MAX)
return -ERANGE;
simple_child->storeme = tmp;
return count;
}
static void simple_child_release(struct config_item *item)
{
kfree(to_simple_child(item));
}
static struct configfs_item_operations simple_child_item_ops = {
.release = simple_child_release,
.show_attribute = simple_child_attr_show,
.store_attribute = simple_child_attr_store,
};
static struct config_item_type simple_child_type = {
.ct_item_ops = &simple_child_item_ops,
.ct_attrs = simple_child_attrs,
.ct_owner = THIS_MODULE,
};
struct simple_children {
struct config_group group;
};
static inline struct simple_children *to_simple_children(struct config_item *item)
{
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
}
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
{
struct simple_child *simple_child;
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
if (!simple_child)
return ERR_PTR(-ENOMEM);
config_item_init_type_name(&simple_child->item, name,
&simple_child_type);
simple_child->storeme = 0;
return &simple_child->item;
}
static struct configfs_attribute simple_children_attr_description = {
.ca_owner = THIS_MODULE,
.ca_name = "description",
.ca_mode = S_IRUGO,
};
static struct configfs_attribute *simple_children_attrs[] = {
&simple_children_attr_description,
NULL,
};
static ssize_t simple_children_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
return sprintf(page,
"[02-simple-children]\n"
"\n"
"This subsystem allows the creation of child config_items. These\n"
"items have only one attribute that is readable and writeable.\n");
}
static void simple_children_release(struct config_item *item)
{
kfree(to_simple_children(item));
}
static struct configfs_item_operations simple_children_item_ops = {
.release = simple_children_release,
.show_attribute = simple_children_attr_show,
};
/*
* Note that, since no extra work is required on ->drop_item(),
* no ->drop_item() is provided.
*/
static struct configfs_group_operations simple_children_group_ops = {
.make_item = simple_children_make_item,
};
static struct config_item_type simple_children_type = {
.ct_item_ops = &simple_children_item_ops,
.ct_group_ops = &simple_children_group_ops,
.ct_attrs = simple_children_attrs,
.ct_owner = THIS_MODULE,
};
static struct configfs_subsystem simple_children_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "02-simple-children",
.ci_type = &simple_children_type,
},
},
};
/* ----------------------------------------------------------------- */
/*
* 03-group-children
*
* This example reuses the simple_children group from above. However,
* the simple_children group is not the subsystem itself, it is a
* child of the subsystem. Creation of a group in the subsystem creates
* a new simple_children group. That group can then have simple_child
* children of its own.
*/
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
{
struct simple_children *simple_children;
simple_children = kzalloc(sizeof(struct simple_children),
GFP_KERNEL);
if (!simple_children)
return ERR_PTR(-ENOMEM);
config_group_init_type_name(&simple_children->group, name,
&simple_children_type);
return &simple_children->group;
}
static struct configfs_attribute group_children_attr_description = {
.ca_owner = THIS_MODULE,
.ca_name = "description",
.ca_mode = S_IRUGO,
};
static struct configfs_attribute *group_children_attrs[] = {
&group_children_attr_description,
NULL,
};
static ssize_t group_children_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
return sprintf(page,
"[03-group-children]\n"
"\n"
"This subsystem allows the creation of child config_groups. These\n"
"groups are like the subsystem simple-children.\n");
}
static struct configfs_item_operations group_children_item_ops = {
.show_attribute = group_children_attr_show,
};
/*
* Note that, since no extra work is required on ->drop_item(),
* no ->drop_item() is provided.
*/
static struct configfs_group_operations group_children_group_ops = {
.make_group = group_children_make_group,
};
static struct config_item_type group_children_type = {
.ct_item_ops = &group_children_item_ops,
.ct_group_ops = &group_children_group_ops,
.ct_attrs = group_children_attrs,
.ct_owner = THIS_MODULE,
};
static struct configfs_subsystem group_children_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "03-group-children",
.ci_type = &group_children_type,
},
},
};
/* ----------------------------------------------------------------- */
/*
* We're now done with our subsystem definitions.
* For convenience in this module, here's a list of them all. It
* allows the init function to easily register them. Most modules
* will only have one subsystem, and will only call register_subsystem
* on it directly.
*/
static struct configfs_subsystem *example_subsys[] = {
&childless_subsys.subsys,
&simple_children_subsys,
&group_children_subsys,
NULL,
};
static int __init configfs_example_init(void)
{
int ret;
int i;
struct configfs_subsystem *subsys;
for (i = 0; example_subsys[i]; i++) {
subsys = example_subsys[i];
config_group_init(&subsys->su_group);
mutex_init(&subsys->su_mutex);
ret = configfs_register_subsystem(subsys);
if (ret) {
printk(KERN_ERR "Error %d while registering subsystem %s\n",
ret,
subsys->su_group.cg_item.ci_namebuf);
goto out_unregister;
}
}
return 0;
out_unregister:
for (; i >= 0; i--) {
configfs_unregister_subsystem(example_subsys[i]);
}
return ret;
}
static void __exit configfs_example_exit(void)
{
int i;
for (i = 0; example_subsys[i]; i++) {
configfs_unregister_subsystem(example_subsys[i]);
}
}
module_init(configfs_example_init);
module_exit(configfs_example_exit);
MODULE_LICENSE("GPL");
/*
* vim: noexpandtab ts=8 sts=0 sw=8:
*
* configfs_example_macros.c - This file is a demonstration module
* containing a number of configfs subsystems. It uses the helper
* macros defined by configfs.h
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*
* Based on sysfs:
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
*
* configfs Copyright (C) 2005 Oracle. All rights reserved.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/configfs.h>
/*
* 01-childless
*
* This first example is a childless subsystem. It cannot create
* any config_items. It just has attributes.
*
* Note that we are enclosing the configfs_subsystem inside a container.
* This is not necessary if a subsystem has no attributes directly
* on the subsystem. See the next example, 02-simple-children, for
* such a subsystem.
*/
struct childless {
struct configfs_subsystem subsys;
int showme;
int storeme;
};
static inline struct childless *to_childless(struct config_item *item)
{
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
}
CONFIGFS_ATTR_STRUCT(childless);
#define CHILDLESS_ATTR(_name, _mode, _show, _store) \
struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
#define CHILDLESS_ATTR_RO(_name, _show) \
struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show);
static ssize_t childless_showme_read(struct childless *childless,
char *page)
{
ssize_t pos;
pos = sprintf(page, "%d\n", childless->showme);
childless->showme++;
return pos;
}
static ssize_t childless_storeme_read(struct childless *childless,
char *page)
{
return sprintf(page, "%d\n", childless->storeme);
}
static ssize_t childless_storeme_write(struct childless *childless,
const char *page,
size_t count)
{
unsigned long tmp;
char *p = (char *) page;
tmp = simple_strtoul(p, &p, 10);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp > INT_MAX)
return -ERANGE;
childless->storeme = tmp;
return count;
}
static ssize_t childless_description_read(struct childless *childless,
char *page)
{
return sprintf(page,
"[01-childless]\n"
"\n"
"The childless subsystem is the simplest possible subsystem in\n"
"configfs. It does not support the creation of child config_items.\n"
"It only has a few attributes. In fact, it isn't much different\n"
"than a directory in /proc.\n");
}
CHILDLESS_ATTR_RO(showme, childless_showme_read);
CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,
childless_storeme_write);
CHILDLESS_ATTR_RO(description, childless_description_read);
static struct configfs_attribute *childless_attrs[] = {
&childless_attr_showme.attr,
&childless_attr_storeme.attr,
&childless_attr_description.attr,
NULL,
};
CONFIGFS_ATTR_OPS(childless);
static struct configfs_item_operations childless_item_ops = {
.show_attribute = childless_attr_show,
.store_attribute = childless_attr_store,
};
static struct config_item_type childless_type = {
.ct_item_ops = &childless_item_ops,
.ct_attrs = childless_attrs,
.ct_owner = THIS_MODULE,
};
static struct childless childless_subsys = {
.subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "01-childless",
.ci_type = &childless_type,
},
},
},
};
/* ----------------------------------------------------------------- */
/*
* 02-simple-children
*
* This example merely has a simple one-attribute child. Note that
* there is no extra attribute structure, as the child's attribute is
* known from the get-go. Also, there is no container for the
* subsystem, as it has no attributes of its own.
*/
struct simple_child {
struct config_item item;
int storeme;
};
static inline struct simple_child *to_simple_child(struct config_item *item)
{
return item ? container_of(item, struct simple_child, item) : NULL;
}
static struct configfs_attribute simple_child_attr_storeme = {
.ca_owner = THIS_MODULE,
.ca_name = "storeme",
.ca_mode = S_IRUGO | S_IWUSR,
};
static struct configfs_attribute *simple_child_attrs[] = {
&simple_child_attr_storeme,
NULL,
};
static ssize_t simple_child_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
ssize_t count;
struct simple_child *simple_child = to_simple_child(item);
count = sprintf(page, "%d\n", simple_child->storeme);
return count;
}
static ssize_t simple_child_attr_store(struct config_item *item,
struct configfs_attribute *attr,
const char *page, size_t count)
{
struct simple_child *simple_child = to_simple_child(item);
unsigned long tmp;
char *p = (char *) page;
tmp = simple_strtoul(p, &p, 10);
if (!p || (*p && (*p != '\n')))
return -EINVAL;
if (tmp > INT_MAX)
return -ERANGE;
simple_child->storeme = tmp;
return count;
}
static void simple_child_release(struct config_item *item)
{
kfree(to_simple_child(item));
}
static struct configfs_item_operations simple_child_item_ops = {
.release = simple_child_release,
.show_attribute = simple_child_attr_show,
.store_attribute = simple_child_attr_store,
};
static struct config_item_type simple_child_type = {
.ct_item_ops = &simple_child_item_ops,
.ct_attrs = simple_child_attrs,
.ct_owner = THIS_MODULE,
};
struct simple_children {
struct config_group group;
};
static inline struct simple_children *to_simple_children(struct config_item *item)
{
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
}
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
{
struct simple_child *simple_child;
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
if (!simple_child)
return ERR_PTR(-ENOMEM);
config_item_init_type_name(&simple_child->item, name,
&simple_child_type);
simple_child->storeme = 0;
return &simple_child->item;
}
static struct configfs_attribute simple_children_attr_description = {
.ca_owner = THIS_MODULE,
.ca_name = "description",
.ca_mode = S_IRUGO,
};
static struct configfs_attribute *simple_children_attrs[] = {
&simple_children_attr_description,
NULL,
};
static ssize_t simple_children_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
return sprintf(page,
"[02-simple-children]\n"
"\n"
"This subsystem allows the creation of child config_items. These\n"
"items have only one attribute that is readable and writeable.\n");
}
static void simple_children_release(struct config_item *item)
{
kfree(to_simple_children(item));
}
static struct configfs_item_operations simple_children_item_ops = {
.release = simple_children_release,
.show_attribute = simple_children_attr_show,
};
/*
* Note that, since no extra work is required on ->drop_item(),
* no ->drop_item() is provided.
*/
static struct configfs_group_operations simple_children_group_ops = {
.make_item = simple_children_make_item,
};
static struct config_item_type simple_children_type = {
.ct_item_ops = &simple_children_item_ops,
.ct_group_ops = &simple_children_group_ops,
.ct_attrs = simple_children_attrs,
.ct_owner = THIS_MODULE,
};
static struct configfs_subsystem simple_children_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "02-simple-children",
.ci_type = &simple_children_type,
},
},
};
/* ----------------------------------------------------------------- */
/*
* 03-group-children
*
* This example reuses the simple_children group from above. However,
* the simple_children group is not the subsystem itself, it is a
* child of the subsystem. Creation of a group in the subsystem creates
* a new simple_children group. That group can then have simple_child
* children of its own.
*/
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
{
struct simple_children *simple_children;
simple_children = kzalloc(sizeof(struct simple_children),
GFP_KERNEL);
if (!simple_children)
return ERR_PTR(-ENOMEM);
config_group_init_type_name(&simple_children->group, name,
&simple_children_type);
return &simple_children->group;
}
static struct configfs_attribute group_children_attr_description = {
.ca_owner = THIS_MODULE,
.ca_name = "description",
.ca_mode = S_IRUGO,
};
static struct configfs_attribute *group_children_attrs[] = {
&group_children_attr_description,
NULL,
};
static ssize_t group_children_attr_show(struct config_item *item,
struct configfs_attribute *attr,
char *page)
{
return sprintf(page,
"[03-group-children]\n"
"\n"
"This subsystem allows the creation of child config_groups. These\n"
"groups are like the subsystem simple-children.\n");
}
static struct configfs_item_operations group_children_item_ops = {
.show_attribute = group_children_attr_show,
};
/*
* Note that, since no extra work is required on ->drop_item(),
* no ->drop_item() is provided.
*/
static struct configfs_group_operations group_children_group_ops = {
.make_group = group_children_make_group,
};
static struct config_item_type group_children_type = {
.ct_item_ops = &group_children_item_ops,
.ct_group_ops = &group_children_group_ops,
.ct_attrs = group_children_attrs,
.ct_owner = THIS_MODULE,
};
static struct configfs_subsystem group_children_subsys = {
.su_group = {
.cg_item = {
.ci_namebuf = "03-group-children",
.ci_type = &group_children_type,
},
},
};
/* ----------------------------------------------------------------- */
/*
* We're now done with our subsystem definitions.
* For convenience in this module, here's a list of them all. It
* allows the init function to easily register them. Most modules
* will only have one subsystem, and will only call register_subsystem
* on it directly.
*/
static struct configfs_subsystem *example_subsys[] = {
&childless_subsys.subsys,
&simple_children_subsys,
&group_children_subsys,
NULL,
};
static int __init configfs_example_init(void)
{
int ret;
int i;
struct configfs_subsystem *subsys;
for (i = 0; example_subsys[i]; i++) {
subsys = example_subsys[i];
config_group_init(&subsys->su_group);
mutex_init(&subsys->su_mutex);
ret = configfs_register_subsystem(subsys);
if (ret) {
printk(KERN_ERR "Error %d while registering subsystem %s\n",
ret,
subsys->su_group.cg_item.ci_namebuf);
goto out_unregister;
}
}
return 0;
out_unregister:
for (; i >= 0; i--) {
configfs_unregister_subsystem(example_subsys[i]);
}
return ret;
}
static void __exit configfs_example_exit(void)
{
int i;
for (i = 0; example_subsys[i]; i++) {
configfs_unregister_subsystem(example_subsys[i]);
}
}
module_init(configfs_example_init);
module_exit(configfs_example_exit);
MODULE_LICENSE("GPL");
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
################################################################################ ################################################################################
Author: NetApp and Open Grid Computing Author: NetApp and Open Grid Computing
Date: April 15, 2008 Date: May 29, 2008
Table of Contents Table of Contents
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
...@@ -60,16 +60,18 @@ Installation ...@@ -60,16 +60,18 @@ Installation
The procedures described in this document have been tested with The procedures described in this document have been tested with
distributions from Red Hat's Fedora Project (http://fedora.redhat.com/). distributions from Red Hat's Fedora Project (http://fedora.redhat.com/).
- Install nfs-utils-1.1.1 or greater on the client - Install nfs-utils-1.1.2 or greater on the client
An NFS/RDMA mount point can only be obtained by using the mount.nfs An NFS/RDMA mount point can be obtained by using the mount.nfs command in
command in nfs-utils-1.1.1 or greater. To see which version of mount.nfs nfs-utils-1.1.2 or greater (nfs-utils-1.1.1 was the first nfs-utils
you are using, type: version with support for NFS/RDMA mounts, but for various reasons we
recommend using nfs-utils-1.1.2 or greater). To see which version of
mount.nfs you are using, type:
> /sbin/mount.nfs -V $ /sbin/mount.nfs -V
If the version is less than 1.1.1 or the command does not exist, If the version is less than 1.1.2 or the command does not exist,
then you will need to install the latest version of nfs-utils. you should install the latest version of nfs-utils.
Download the latest package from: Download the latest package from:
...@@ -77,22 +79,33 @@ Installation ...@@ -77,22 +79,33 @@ Installation
Uncompress the package and follow the installation instructions. Uncompress the package and follow the installation instructions.
If you will not be using GSS and NFSv4, the installation process If you will not need the idmapper and gssd executables (you do not need
can be simplified by disabling these features when running configure: these to create an NFS/RDMA enabled mount command), the installation
process can be simplified by disabling these features when running
configure:
> ./configure --disable-gss --disable-nfsv4 $ ./configure --disable-gss --disable-nfsv4
For more information on this see the package's README and INSTALL files. To build nfs-utils you will need the tcp_wrappers package installed. For
more information on this see the package's README and INSTALL files.
After building the nfs-utils package, there will be a mount.nfs binary in After building the nfs-utils package, there will be a mount.nfs binary in
the utils/mount directory. This binary can be used to initiate NFS v2, v3, the utils/mount directory. This binary can be used to initiate NFS v2, v3,
or v4 mounts. To initiate a v4 mount, the binary must be called mount.nfs4. or v4 mounts. To initiate a v4 mount, the binary must be called
The standard technique is to create a symlink called mount.nfs4 to mount.nfs. mount.nfs4. The standard technique is to create a symlink called
mount.nfs4 to mount.nfs.
NOTE: mount.nfs and therefore nfs-utils-1.1.1 or greater is only needed This mount.nfs binary should be installed at /sbin/mount.nfs as follows:
$ sudo cp utils/mount/mount.nfs /sbin/mount.nfs
In this location, mount.nfs will be invoked automatically for NFS mounts
by the system mount commmand.
NOTE: mount.nfs and therefore nfs-utils-1.1.2 or greater is only needed
on the NFS client machine. You do not need this specific version of on the NFS client machine. You do not need this specific version of
nfs-utils on the server. Furthermore, only the mount.nfs command from nfs-utils on the server. Furthermore, only the mount.nfs command from
nfs-utils-1.1.1 is needed on the client. nfs-utils-1.1.2 is needed on the client.
- Install a Linux kernel with NFS/RDMA - Install a Linux kernel with NFS/RDMA
...@@ -156,8 +169,8 @@ Check RDMA and NFS Setup ...@@ -156,8 +169,8 @@ Check RDMA and NFS Setup
this time. For example, if you are using a Mellanox Tavor/Sinai/Arbel this time. For example, if you are using a Mellanox Tavor/Sinai/Arbel
card: card:
> modprobe ib_mthca $ modprobe ib_mthca
> modprobe ib_ipoib $ modprobe ib_ipoib
If you are using InfiniBand, make sure there is a Subnet Manager (SM) If you are using InfiniBand, make sure there is a Subnet Manager (SM)
running on the network. If your IB switch has an embedded SM, you can running on the network. If your IB switch has an embedded SM, you can
...@@ -166,7 +179,7 @@ Check RDMA and NFS Setup ...@@ -166,7 +179,7 @@ Check RDMA and NFS Setup
If an SM is running on your network, you should see the following: If an SM is running on your network, you should see the following:
> cat /sys/class/infiniband/driverX/ports/1/state $ cat /sys/class/infiniband/driverX/ports/1/state
4: ACTIVE 4: ACTIVE
where driverX is mthca0, ipath5, ehca3, etc. where driverX is mthca0, ipath5, ehca3, etc.
...@@ -174,10 +187,10 @@ Check RDMA and NFS Setup ...@@ -174,10 +187,10 @@ Check RDMA and NFS Setup
To further test the InfiniBand software stack, use IPoIB (this To further test the InfiniBand software stack, use IPoIB (this
assumes you have two IB hosts named host1 and host2): assumes you have two IB hosts named host1 and host2):
host1> ifconfig ib0 a.b.c.x host1$ ifconfig ib0 a.b.c.x
host2> ifconfig ib0 a.b.c.y host2$ ifconfig ib0 a.b.c.y
host1> ping a.b.c.y host1$ ping a.b.c.y
host2> ping a.b.c.x host2$ ping a.b.c.x
For other device types, follow the appropriate procedures. For other device types, follow the appropriate procedures.
...@@ -202,11 +215,11 @@ NFS/RDMA Setup ...@@ -202,11 +215,11 @@ NFS/RDMA Setup
/vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash) /vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash)
/vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash) /vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash)
The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the The IP address(es) is(are) the client's IPoIB address for an InfiniBand
cleint's iWARP address(es) for an RNIC. HCA or the cleint's iWARP address(es) for an RNIC.
NOTE: The "insecure" option must be used because the NFS/RDMA client does not NOTE: The "insecure" option must be used because the NFS/RDMA client does
use a reserved port. not use a reserved port.
Each time a machine boots: Each time a machine boots:
...@@ -214,43 +227,45 @@ NFS/RDMA Setup ...@@ -214,43 +227,45 @@ NFS/RDMA Setup
For InfiniBand using a Mellanox adapter: For InfiniBand using a Mellanox adapter:
> modprobe ib_mthca $ modprobe ib_mthca
> modprobe ib_ipoib $ modprobe ib_ipoib
> ifconfig ib0 a.b.c.d $ ifconfig ib0 a.b.c.d
NOTE: use unique addresses for the client and server NOTE: use unique addresses for the client and server
- Start the NFS server - Start the NFS server
If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config), If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
load the RDMA transport module: kernel config), load the RDMA transport module:
> modprobe svcrdma $ modprobe svcrdma
Regardless of how the server was built (module or built-in), start the server: Regardless of how the server was built (module or built-in), start the
server:
> /etc/init.d/nfs start $ /etc/init.d/nfs start
or or
> service nfs start $ service nfs start
Instruct the server to listen on the RDMA transport: Instruct the server to listen on the RDMA transport:
> echo rdma 2050 > /proc/fs/nfsd/portlist $ echo rdma 2050 > /proc/fs/nfsd/portlist
- On the client system - On the client system
If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config), If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
load the RDMA client module: kernel config), load the RDMA client module:
> modprobe xprtrdma.ko $ modprobe xprtrdma.ko
Regardless of how the client was built (module or built-in), issue the mount.nfs command: Regardless of how the client was built (module or built-in), use this
command to mount the NFS/RDMA server:
> /path/to/your/mount.nfs <IPoIB-server-name-or-address>:/<export> /mnt -i -o rdma,port=2050 $ mount -o rdma,port=2050 <IPoIB-server-name-or-address>:/<export> /mnt
To verify that the mount is using RDMA, run "cat /proc/mounts" and check the To verify that the mount is using RDMA, run "cat /proc/mounts" and check
"proto" field for the given mount. the "proto" field for the given mount.
Congratulations! You're using NFS/RDMA! Congratulations! You're using NFS/RDMA!
Optimized MPEG Filesystem (OMFS)
Overview
========
OMFS is a filesystem created by SonicBlue for use in the ReplayTV DVR
and Rio Karma MP3 player. The filesystem is extent-based, utilizing
block sizes from 2k to 8k, with hash-based directories. This
filesystem driver may be used to read and write disks from these
devices.
Note, it is not recommended that this FS be used in place of a general
filesystem for your own streaming media device. Native Linux filesystems
will likely perform better.
More information is available at:
http://linux-karma.sf.net/
Various utilities, including mkomfs and omfsck, are included with
omfsprogs, available at:
http://bobcopeland.com/karma/
Instructions are included in its README.
Options
=======
OMFS supports the following mount-time options:
uid=n - make all files owned by specified user
gid=n - make all files owned by specified group
umask=xxx - set permission umask to xxx
fmask=xxx - set umask to xxx for files
dmask=xxx - set umask to xxx for directories
Disk format
===========
OMFS discriminates between "sysblocks" and normal data blocks. The sysblock
group consists of super block information, file metadata, directory structures,
and extents. Each sysblock has a header containing CRCs of the entire
sysblock, and may be mirrored in successive blocks on the disk. A sysblock may
have a smaller size than a data block, but since they are both addressed by the
same 64-bit block number, any remaining space in the smaller sysblock is
unused.
Sysblock header information:
struct omfs_header {
__be64 h_self; /* FS block where this is located */
__be32 h_body_size; /* size of useful data after header */
__be16 h_crc; /* crc-ccitt of body_size bytes */
char h_fill1[2];
u8 h_version; /* version, always 1 */
char h_type; /* OMFS_INODE_X */
u8 h_magic; /* OMFS_IMAGIC */
u8 h_check_xor; /* XOR of header bytes before this */
__be32 h_fill2;
};
Files and directories are both represented by omfs_inode:
struct omfs_inode {
struct omfs_header i_head; /* header */
__be64 i_parent; /* parent containing this inode */
__be64 i_sibling; /* next inode in hash bucket */
__be64 i_ctime; /* ctime, in milliseconds */
char i_fill1[35];
char i_type; /* OMFS_[DIR,FILE] */
__be32 i_fill2;
char i_fill3[64];
char i_name[OMFS_NAMELEN]; /* filename */
__be64 i_size; /* size of file, in bytes */
};
Directories in OMFS are implemented as a large hash table. Filenames are
hashed then prepended into the bucket list beginning at OMFS_DIR_START.
Lookup requires hashing the filename, then seeking across i_sibling pointers
until a match is found on i_name. Empty buckets are represented by block
pointers with all-1s (~0).
A file is an omfs_inode structure followed by an extent table beginning at
OMFS_EXTENT_START:
struct omfs_extent_entry {
__be64 e_cluster; /* start location of a set of blocks */
__be64 e_blocks; /* number of blocks after e_cluster */
};
struct omfs_extent {
__be64 e_next; /* next extent table location */
__be32 e_extent_count; /* total # extents in this table */
__be32 e_fill;
struct omfs_extent_entry e_entry; /* start of extent entries */
};
Each extent holds the block offset followed by number of blocks allocated to
the extent. The final extent in each table is a terminator with e_cluster
being ~0 and e_blocks being ones'-complement of the total number of blocks
in the table.
If this table overflows, a continuation inode is written and pointed to by
e_next. These have a header but lack the rest of the inode structure.
...@@ -296,6 +296,7 @@ Table 1-4: Kernel info in /proc ...@@ -296,6 +296,7 @@ Table 1-4: Kernel info in /proc
uptime System uptime uptime System uptime
version Kernel version version Kernel version
video bttv info of video resources (2.4) video bttv info of video resources (2.4)
vmallocinfo Show vmalloced areas
.............................................................................. ..............................................................................
You can, for example, check which interrupts are currently in use and what You can, for example, check which interrupts are currently in use and what
...@@ -557,6 +558,49 @@ VmallocTotal: total size of vmalloc memory area ...@@ -557,6 +558,49 @@ VmallocTotal: total size of vmalloc memory area
VmallocUsed: amount of vmalloc area which is used VmallocUsed: amount of vmalloc area which is used
VmallocChunk: largest contigious block of vmalloc area which is free VmallocChunk: largest contigious block of vmalloc area which is free
..............................................................................
vmallocinfo:
Provides information about vmalloced/vmaped areas. One line per area,
containing the virtual address range of the area, size in bytes,
caller information of the creator, and optional information depending
on the kind of area :
pages=nr number of pages
phys=addr if a physical address was specified
ioremap I/O mapping (ioremap() and friends)
vmalloc vmalloc() area
vmap vmap()ed pages
user VM_USERMAP area
vpages buffer for pages pointers was vmalloced (huge area)
N<node>=nr (Only on NUMA kernels)
Number of pages allocated on memory node <node>
> cat /proc/vmallocinfo
0xffffc20000000000-0xffffc20000201000 2101248 alloc_large_system_hash+0x204 ...
/0x2c0 pages=512 vmalloc N0=128 N1=128 N2=128 N3=128
0xffffc20000201000-0xffffc20000302000 1052672 alloc_large_system_hash+0x204 ...
/0x2c0 pages=256 vmalloc N0=64 N1=64 N2=64 N3=64
0xffffc20000302000-0xffffc20000304000 8192 acpi_tb_verify_table+0x21/0x4f...
phys=7fee8000 ioremap
0xffffc20000304000-0xffffc20000307000 12288 acpi_tb_verify_table+0x21/0x4f...
phys=7fee7000 ioremap
0xffffc2000031d000-0xffffc2000031f000 8192 init_vdso_vars+0x112/0x210
0xffffc2000031f000-0xffffc2000032b000 49152 cramfs_uncompress_init+0x2e ...
/0x80 pages=11 vmalloc N0=3 N1=3 N2=2 N3=3
0xffffc2000033a000-0xffffc2000033d000 12288 sys_swapon+0x640/0xac0 ...
pages=2 vmalloc N1=2
0xffffc20000347000-0xffffc2000034c000 20480 xt_alloc_table_info+0xfe ...
/0x130 [x_tables] pages=4 vmalloc N0=4
0xffffffffa0000000-0xffffffffa000f000 61440 sys_init_module+0xc27/0x1d00 ...
pages=14 vmalloc N2=14
0xffffffffa000f000-0xffffffffa0014000 20480 sys_init_module+0xc27/0x1d00 ...
pages=4 vmalloc N1=4
0xffffffffa0014000-0xffffffffa0017000 12288 sys_init_module+0xc27/0x1d00 ...
pages=2 vmalloc N1=2
0xffffffffa0017000-0xffffffffa0022000 45056 sys_init_module+0xc27/0x1d00 ...
pages=10 vmalloc N0=10
1.3 IDE devices in /proc/ide 1.3 IDE devices in /proc/ide
---------------------------- ----------------------------
...@@ -887,7 +931,7 @@ group_prealloc max_to_scan mb_groups mb_history min_to_scan order2_req ...@@ -887,7 +931,7 @@ group_prealloc max_to_scan mb_groups mb_history min_to_scan order2_req
stats stream_req stats stream_req
mb_groups: mb_groups:
This file gives the details of mutiblock allocator buddy cache of free blocks This file gives the details of multiblock allocator buddy cache of free blocks
mb_history: mb_history:
Multiblock allocation history. Multiblock allocation history.
...@@ -1430,7 +1474,7 @@ used because pages_free(1355) is smaller than watermark + protection[2] ...@@ -1430,7 +1474,7 @@ used because pages_free(1355) is smaller than watermark + protection[2]
normal page requirement. If requirement is DMA zone(index=0), protection[0] normal page requirement. If requirement is DMA zone(index=0), protection[0]
(=0) is used. (=0) is used.
zone[i]'s protection[j] is calculated by following exprssion. zone[i]'s protection[j] is calculated by following expression.
(i < j): (i < j):
zone[i]->protection[j] zone[i]->protection[j]
......
...@@ -294,6 +294,16 @@ user-defined data with a channel, and is immediately available ...@@ -294,6 +294,16 @@ user-defined data with a channel, and is immediately available
(including in create_buf_file()) via chan->private_data or (including in create_buf_file()) via chan->private_data or
buf->chan->private_data. buf->chan->private_data.
Buffer-only channels
--------------------
These channels have no files associated and can be created with
relay_open(NULL, NULL, ...). Such channels are useful in scenarios such
as when doing early tracing in the kernel, before the VFS is up. In these
cases, one may open a buffer-only channel and then call
relay_late_setup_files() when the kernel is ready to handle files,
to expose the buffered data to the userspace.
Channel 'modes' Channel 'modes'
--------------- ---------------
......
...@@ -248,6 +248,7 @@ The top level sysfs directory looks like: ...@@ -248,6 +248,7 @@ The top level sysfs directory looks like:
block/ block/
bus/ bus/
class/ class/
dev/
devices/ devices/
firmware/ firmware/
net/ net/
...@@ -274,6 +275,11 @@ fs/ contains a directory for some filesystems. Currently each ...@@ -274,6 +275,11 @@ fs/ contains a directory for some filesystems. Currently each
filesystem wanting to export attributes must create its own hierarchy filesystem wanting to export attributes must create its own hierarchy
below fs/ (see ./fuse.txt for an example). below fs/ (see ./fuse.txt for an example).
dev/ contains two directories char/ and block/. Inside these two
directories there are symlinks named <major>:<minor>. These symlinks
point to the sysfs directory for the given device. /sys/dev provides a
quick way to lookup the sysfs interface for a device from the result of
a stat(2) operation.
More information can driver-model specific features can be found in More information can driver-model specific features can be found in
Documentation/driver-model/. Documentation/driver-model/.
......
Introduction
=============
UBIFS file-system stands for UBI File System. UBI stands for "Unsorted
Block Images". UBIFS is a flash file system, which means it is designed
to work with flash devices. It is important to understand, that UBIFS
is completely different to any traditional file-system in Linux, like
Ext2, XFS, JFS, etc. UBIFS represents a separate class of file-systems
which work with MTD devices, not block devices. The other Linux
file-system of this class is JFFS2.
To make it more clear, here is a small comparison of MTD devices and
block devices.
1 MTD devices represent flash devices and they consist of eraseblocks of
rather large size, typically about 128KiB. Block devices consist of
small blocks, typically 512 bytes.
2 MTD devices support 3 main operations - read from some offset within an
eraseblock, write to some offset within an eraseblock, and erase a whole
eraseblock. Block devices support 2 main operations - read a whole
block and write a whole block.
3 The whole eraseblock has to be erased before it becomes possible to
re-write its contents. Blocks may be just re-written.
4 Eraseblocks become worn out after some number of erase cycles -
typically 100K-1G for SLC NAND and NOR flashes, and 1K-10K for MLC
NAND flashes. Blocks do not have the wear-out property.
5 Eraseblocks may become bad (only on NAND flashes) and software should
deal with this. Blocks on hard drives typically do not become bad,
because hardware has mechanisms to substitute bad blocks, at least in
modern LBA disks.
It should be quite obvious why UBIFS is very different to traditional
file-systems.
UBIFS works on top of UBI. UBI is a separate software layer which may be
found in drivers/mtd/ubi. UBI is basically a volume management and
wear-leveling layer. It provides so called UBI volumes which is a higher
level abstraction than a MTD device. The programming model of UBI devices
is very similar to MTD devices - they still consist of large eraseblocks,
they have read/write/erase operations, but UBI devices are devoid of
limitations like wear and bad blocks (items 4 and 5 in the above list).
In a sense, UBIFS is a next generation of JFFS2 file-system, but it is
very different and incompatible to JFFS2. The following are the main
differences.
* JFFS2 works on top of MTD devices, UBIFS depends on UBI and works on
top of UBI volumes.
* JFFS2 does not have on-media index and has to build it while mounting,
which requires full media scan. UBIFS maintains the FS indexing
information on the flash media and does not require full media scan,
so it mounts many times faster than JFFS2.
* JFFS2 is a write-through file-system, while UBIFS supports write-back,
which makes UBIFS much faster on writes.
Similarly to JFFS2, UBIFS supports on-the-flight compression which makes
it possible to fit quite a lot of data to the flash.
Similarly to JFFS2, UBIFS is tolerant of unclean reboots and power-cuts.
It does not need stuff like ckfs.ext2. UBIFS automatically replays its
journal and recovers from crashes, ensuring that the on-flash data
structures are consistent.
UBIFS scales logarithmically (most of the data structures it uses are
trees), so the mount time and memory consumption do not linearly depend
on the flash size, like in case of JFFS2. This is because UBIFS
maintains the FS index on the flash media. However, UBIFS depends on
UBI, which scales linearly. So overall UBI/UBIFS stack scales linearly.
Nevertheless, UBI/UBIFS scales considerably better than JFFS2.
The authors of UBIFS believe, that it is possible to develop UBI2 which
would scale logarithmically as well. UBI2 would support the same API as UBI,
but it would be binary incompatible to UBI. So UBIFS would not need to be
changed to use UBI2
Mount options
=============
(*) == default.
norm_unmount (*) commit on unmount; the journal is committed
when the file-system is unmounted so that the
next mount does not have to replay the journal
and it becomes very fast;
fast_unmount do not commit on unmount; this option makes
unmount faster, but the next mount slower
because of the need to replay the journal.
Quick usage instructions
========================
The UBI volume to mount is specified using "ubiX_Y" or "ubiX:NAME" syntax,
where "X" is UBI device number, "Y" is UBI volume number, and "NAME" is
UBI volume name.
Mount volume 0 on UBI device 0 to /mnt/ubifs:
$ mount -t ubifs ubi0_0 /mnt/ubifs
Mount "rootfs" volume of UBI device 0 to /mnt/ubifs ("rootfs" is volume
name):
$ mount -t ubifs ubi0:rootfs /mnt/ubifs
The following is an example of the kernel boot arguments to attach mtd0
to UBI and mount volume "rootfs":
ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
Module Parameters for Debugging
===============================
When UBIFS has been compiled with debugging enabled, there are 3 module
parameters that are available to control aspects of testing and debugging.
The parameters are unsigned integers where each bit controls an option.
The parameters are:
debug_msgs Selects which debug messages to display, as follows:
Message Type Flag value
General messages 1
Journal messages 2
Mount messages 4
Commit messages 8
LEB search messages 16
Budgeting messages 32
Garbage collection messages 64
Tree Node Cache (TNC) messages 128
LEB properties (lprops) messages 256
Input/output messages 512
Log messages 1024
Scan messages 2048
Recovery messages 4096
debug_chks Selects extra checks that UBIFS can do while running:
Check Flag value
General checks 1
Check Tree Node Cache (TNC) 2
Check indexing tree size 4
Check orphan area 8
Check old indexing tree 16
Check LEB properties (lprops) 32
Check leaf nodes and inodes 64
debug_tsts Selects a mode of testing, as follows:
Test mode Flag value
Force in-the-gaps method 2
Failure mode for recovery testing 4
For example, set debug_msgs to 5 to display General messages and Mount
messages.
References
==========
UBIFS documentation and FAQ/HOWTO at the MTD web site:
http://www.linux-mtd.infradead.org/doc/ubifs.html
http://www.linux-mtd.infradead.org/faq/ubifs.html
...@@ -96,6 +96,14 @@ shortname=lower|win95|winnt|mixed ...@@ -96,6 +96,14 @@ shortname=lower|win95|winnt|mixed
emulate the Windows 95 rule for create. emulate the Windows 95 rule for create.
Default setting is `lower'. Default setting is `lower'.
tz=UTC -- Interpret timestamps as UTC rather than local time.
This option disables the conversion of timestamps
between local time (as used by Windows on FAT) and UTC
(which Linux uses internally). This is particuluarly
useful when mounting devices (like digital cameras)
that are set to UTC in order to avoid the pitfalls of
local time.
<bool>: 0,1,yes,no,true,false <bool>: 0,1,yes,no,true,false
TODO TODO
......
...@@ -143,7 +143,7 @@ struct file_system_type { ...@@ -143,7 +143,7 @@ struct file_system_type {
The get_sb() method has the following arguments: The get_sb() method has the following arguments:
struct file_system_type *fs_type: decribes the filesystem, partly initialized struct file_system_type *fs_type: describes the filesystem, partly initialized
by the specific filesystem code by the specific filesystem code
int flags: mount flags int flags: mount flags
...@@ -895,9 +895,9 @@ struct dentry_operations { ...@@ -895,9 +895,9 @@ struct dentry_operations {
iput() yourself iput() yourself
d_dname: called when the pathname of a dentry should be generated. d_dname: called when the pathname of a dentry should be generated.
Usefull for some pseudo filesystems (sockfs, pipefs, ...) to delay Useful for some pseudo filesystems (sockfs, pipefs, ...) to delay
pathname generation. (Instead of doing it when dentry is created, pathname generation. (Instead of doing it when dentry is created,
its done only when the path is needed.). Real filesystems probably it's done only when the path is needed.). Real filesystems probably
dont want to use it, because their dentries are present in global dont want to use it, because their dentries are present in global
dcache hash, so their hash should be an invariant. As no lock is dcache hash, so their hash should be an invariant. As no lock is
held, d_dname() should not try to modify the dentry itself, unless held, d_dname() should not try to modify the dentry itself, unless
......
此差异已折叠。
...@@ -347,15 +347,12 @@ necessarily be nonportable. ...@@ -347,15 +347,12 @@ necessarily be nonportable.
Dynamic definition of GPIOs is not currently standard; for example, as Dynamic definition of GPIOs is not currently standard; for example, as
a side effect of configuring an add-on board with some GPIO expanders. a side effect of configuring an add-on board with some GPIO expanders.
These calls are purely for kernel space, but a userspace API could be built
on top of them.
GPIO implementor's framework (OPTIONAL) GPIO implementor's framework (OPTIONAL)
======================================= =======================================
As noted earlier, there is an optional implementation framework making it As noted earlier, there is an optional implementation framework making it
easier for platforms to support different kinds of GPIO controller using easier for platforms to support different kinds of GPIO controller using
the same programming interface. the same programming interface. This framework is called "gpiolib".
As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
will be found there. That will list all the controllers registered through will be found there. That will list all the controllers registered through
...@@ -392,11 +389,21 @@ either NULL or the label associated with that GPIO when it was requested. ...@@ -392,11 +389,21 @@ either NULL or the label associated with that GPIO when it was requested.
Platform Support Platform Support
---------------- ----------------
To support this framework, a platform's Kconfig will "select HAVE_GPIO_LIB" To support this framework, a platform's Kconfig will "select" either
ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep(). three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
They may also want to provide a custom value for ARCH_NR_GPIOS. They may also want to provide a custom value for ARCH_NR_GPIOS.
ARCH_REQUIRE_GPIOLIB means that the gpio-lib code will always get compiled
into the kernel on that architecture.
ARCH_WANT_OPTIONAL_GPIOLIB means the gpio-lib code defaults to off and the user
can enable it and build it into the kernel optionally.
If neither of these options are selected, the platform does not support
GPIOs through GPIO-lib and the code cannot be enabled by the user.
Trivial implementations of those functions can directly use framework Trivial implementations of those functions can directly use framework
code, which always dispatches through the gpio_chip: code, which always dispatches through the gpio_chip:
...@@ -439,4 +446,120 @@ becomes available. That may mean the device should not be registered until ...@@ -439,4 +446,120 @@ becomes available. That may mean the device should not be registered until
calls for that GPIO can work. One way to address such dependencies is for calls for that GPIO can work. One way to address such dependencies is for
such gpio_chip controllers to provide setup() and teardown() callbacks to such gpio_chip controllers to provide setup() and teardown() callbacks to
board specific code; those board specific callbacks would register devices board specific code; those board specific callbacks would register devices
once all the necessary resources are available. once all the necessary resources are available, and remove them later when
the GPIO controller device becomes unavailable.
Sysfs Interface for Userspace (OPTIONAL)
========================================
Platforms which use the "gpiolib" implementors framework may choose to
configure a sysfs user interface to GPIOs. This is different from the
debugfs interface, since it provides control over GPIO direction and
value instead of just showing a gpio state summary. Plus, it could be
present on production systems without debugging support.
Given approprate hardware documentation for the system, userspace could
know for example that GPIO #23 controls the write protect line used to
protect boot loader segments in flash memory. System upgrade procedures
may need to temporarily remove that protection, first importing a GPIO,
then changing its output state, then updating the code before re-enabling
the write protection. In normal use, GPIO #23 would never be touched,
and the kernel would have no need to know about it.
Again depending on appropriate hardware documentation, on some systems
userspace GPIO can be used to determine system configuration data that
standard kernels won't know about. And for some tasks, simple userspace
GPIO drivers could be all that the system really needs.
Note that standard kernel drivers exist for common "LEDs and Buttons"
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
instead of talking directly to the GPIOs; they integrate with kernel
frameworks better than your userspace code could.
Paths in Sysfs
--------------
There are three kinds of entry in /sys/class/gpio:
- Control interfaces used to get userspace control over GPIOs;
- GPIOs themselves; and
- GPIO controllers ("gpio_chip" instances).
That's in addition to standard files including the "device" symlink.
The control interfaces are write-only:
/sys/class/gpio/
"export" ... Userspace may ask the kernel to export control of
a GPIO to userspace by writing its number to this file.
Example: "echo 19 > export" will create a "gpio19" node
for GPIO #19, if that's not requested by kernel code.
"unexport" ... Reverses the effect of exporting to userspace.
Example: "echo 19 > unexport" will remove a "gpio19"
node exported using the "export" file.
GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
and have the following read/write attributes:
/sys/class/gpio/gpioN/
"direction" ... reads as either "in" or "out". This value may
normally be written. Writing as "out" defaults to
initializing the value as low. To ensure glitch free
operation, values "low" and "high" may be written to
configure the GPIO as an output with that initial value.
Note that this attribute *will not exist* if the kernel
doesn't support changing the direction of a GPIO, or
it was exported by kernel code that didn't explicitly
allow userspace to reconfigure this GPIO's direction.
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.
GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the
controller implementing GPIOs starting at #42) and have the following
read-only attributes:
/sys/class/gpio/gpiochipN/
"base" ... same as N, the first GPIO managed by this chip
"label" ... provided for diagnostics (not always unique)
"ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
Board documentation should in most cases cover what GPIOs are used for
what purposes. However, those numbers are not always stable; GPIOs on
a daughtercard might be different depending on the base board being used,
or other cards in the stack. In such cases, you may need to use the
gpiochip nodes (possibly in conjunction with schematics) to determine
the correct GPIO number to use for a given signal.
Exporting from Kernel code
--------------------------
Kernel code can explicitly manage exports of GPIOs which have already been
requested using gpio_request():
/* export the GPIO to userspace */
int gpio_export(unsigned gpio, bool direction_may_change);
/* reverse gpio_export() */
void gpio_unexport();
After a kernel driver requests a GPIO, it may only be made available in
the sysfs interface by gpio_export(). The driver can control whether the
signal direction may change. This helps drivers prevent userspace code
from accidentally clobbering important system state.
This explicit exporting can help with debugging (by making some kinds
of experiments easier), or can provide an always-there interface that's
suitable for documenting as part of a board support package.
...@@ -22,6 +22,10 @@ Module Parameters ...@@ -22,6 +22,10 @@ Module Parameters
and PWM output control functions. Using this parameter and PWM output control functions. Using this parameter
shouldn't be required since the BIOS usually takes care shouldn't be required since the BIOS usually takes care
of this. of this.
* probe_all_addr: bool Include non-standard LPC addresses 0x162e and 0x164e
when probing for ISA devices. This is required for the
following boards:
- VIA EPIA SN18000
Note that there is no need to use this parameter if the driver loads without Note that there is no need to use this parameter if the driver loads without
complaining. The driver will say so if it is necessary. complaining. The driver will say so if it is necessary.
......
...@@ -96,11 +96,6 @@ initial testing of the ADM1027 it was 1.00 degC steps. Analog Devices has ...@@ -96,11 +96,6 @@ initial testing of the ADM1027 it was 1.00 degC steps. Analog Devices has
confirmed this "bug". The ADT7463 is reported to work as described in the confirmed this "bug". The ADT7463 is reported to work as described in the
documentation. The current lm85 driver does not show the offset register. documentation. The current lm85 driver does not show the offset register.
The ADT7463 has a THERM asserted counter. This counter has a 22.76ms
resolution and a range of 5.8 seconds. The driver implements a 32-bit
accumulator of the counter value to extend the range to over a year. The
counter will stay at it's max value until read.
See the vendor datasheets for more information. There is application note See the vendor datasheets for more information. There is application note
from National (AN-1260) with some additional information about the LM85. from National (AN-1260) with some additional information about the LM85.
The Analog Devices datasheet is very detailed and describes a procedure for The Analog Devices datasheet is very detailed and describes a procedure for
...@@ -206,13 +201,15 @@ Configuration choices: ...@@ -206,13 +201,15 @@ Configuration choices:
The National LM85's have two vendor specific configuration The National LM85's have two vendor specific configuration
features. Tach. mode and Spinup Control. For more details on these, features. Tach. mode and Spinup Control. For more details on these,
see the LM85 datasheet or Application Note AN-1260. see the LM85 datasheet or Application Note AN-1260. These features
are not currently supported by the lm85 driver.
The Analog Devices ADM1027 has several vendor specific enhancements. The Analog Devices ADM1027 has several vendor specific enhancements.
The number of pulses-per-rev of the fans can be set, Tach monitoring The number of pulses-per-rev of the fans can be set, Tach monitoring
can be optimized for PWM operation, and an offset can be applied to can be optimized for PWM operation, and an offset can be applied to
the temperatures to compensate for systemic errors in the the temperatures to compensate for systemic errors in the
measurements. measurements. These features are not currently supported by the lm85
driver.
In addition to the ADM1027 features, the ADT7463 also has Tmin control In addition to the ADM1027 features, the ADT7463 also has Tmin control
and THERM asserted counts. Automatic Tmin control acts to adjust the and THERM asserted counts. Automatic Tmin control acts to adjust the
......
...@@ -49,7 +49,7 @@ $ modprobe max6875 force=0,0x50 ...@@ -49,7 +49,7 @@ $ modprobe max6875 force=0,0x50
The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
addresses. For example, for address 0x50, it also reserves 0x51. addresses. For example, for address 0x50, it also reserves 0x51.
The even-address instance is called 'max6875', the odd one is 'max6875 subclient'. The even-address instance is called 'max6875', the odd one is 'dummy'.
Programming the chip using i2c-dev Programming the chip using i2c-dev
......
...@@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead. ...@@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead.
Supported chips: Supported chips:
* Philips PCA9539 * Philips PCA9539
Prefix: 'pca9539' Prefix: 'pca9539'
Addresses scanned: 0x74 - 0x77 Addresses scanned: none
Datasheet: Datasheet:
http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
...@@ -23,6 +23,14 @@ The input sense can also be inverted. ...@@ -23,6 +23,14 @@ The input sense can also be inverted.
The 16 lines are split between two bytes. The 16 lines are split between two bytes.
Detection
---------
The PCA9539 is difficult to detect and not commonly found in PC machines,
so you have to pass the I2C bus and address of the installed PCA9539
devices explicitly to the driver at load time via the force=... parameter.
Sysfs entries Sysfs entries
------------- -------------
......
...@@ -4,13 +4,13 @@ Kernel driver pcf8574 ...@@ -4,13 +4,13 @@ Kernel driver pcf8574
Supported chips: Supported chips:
* Philips PCF8574 * Philips PCF8574
Prefix: 'pcf8574' Prefix: 'pcf8574'
Addresses scanned: I2C 0x20 - 0x27 Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html http://www.semiconductors.philips.com/pip/PCF8574P.html
* Philips PCF8574A * Philips PCF8574A
Prefix: 'pcf8574a' Prefix: 'pcf8574a'
Addresses scanned: I2C 0x38 - 0x3f Addresses scanned: none
Datasheet: Publicly available at the Philips Semiconductors website Datasheet: Publicly available at the Philips Semiconductors website
http://www.semiconductors.philips.com/pip/PCF8574P.html http://www.semiconductors.philips.com/pip/PCF8574P.html
...@@ -38,12 +38,10 @@ For more informations see the datasheet. ...@@ -38,12 +38,10 @@ For more informations see the datasheet.
Accessing PCF8574(A) via /sys interface Accessing PCF8574(A) via /sys interface
------------------------------------- -------------------------------------
! Be careful !
The PCF8574(A) is plainly impossible to detect ! Stupid chip. The PCF8574(A) is plainly impossible to detect ! Stupid chip.
So every chip with address in the interval [20..27] and [38..3f] are So, you have to pass the I2C bus and address of the installed PCF857A
detected as PCF8574(A). If you have other chips in this address and PCF8574A devices explicitly to the driver at load time via the
range, the workaround is to load this module after the one force=... parameter.
for your others chips.
On detection (i.e. insmod, modprobe et al.), directories are being On detection (i.e. insmod, modprobe et al.), directories are being
created for each detected PCF8574(A): created for each detected PCF8574(A):
......
...@@ -40,12 +40,9 @@ Detection ...@@ -40,12 +40,9 @@ Detection
--------- ---------
There is no method known to detect whether a chip on a given I2C address is There is no method known to detect whether a chip on a given I2C address is
a PCF8575 or whether it is any other I2C device. So there are two alternatives a PCF8575 or whether it is any other I2C device, so you have to pass the I2C
to let the driver find the installed PCF8575 devices: bus and address of the installed PCF8575 devices explicitly to the driver at
- Load this driver after any other I2C driver for I2C devices with addresses load time via the force=... parameter.
in the range 0x20 .. 0x27.
- Pass the I2C bus and address of the installed PCF8575 devices explicitly to
the driver at load time via the probe=... or force=... parameters.
/sys interface /sys interface
-------------- --------------
......
此差异已折叠。
...@@ -50,9 +50,9 @@ Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qe ...@@ -50,9 +50,9 @@ Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qe
/usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image /usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image
(xx is the number of virtual processors for the guest, now the maximum value is 4) (xx is the number of virtual processors for the guest, now the maximum value is 4)
5. Known possibile issue on some platforms with old Firmware. 5. Known possible issue on some platforms with old Firmware.
If meet strange host crashe issues, try to solve it through either of the following ways: In the event of strange host crash issues, try to solve it through either of the following ways:
(1): Upgrade your Firmware to the latest one. (1): Upgrade your Firmware to the latest one.
...@@ -65,8 +65,8 @@ index 0b53344..f02b0f7 100644 ...@@ -65,8 +65,8 @@ index 0b53344..f02b0f7 100644
mov ar.pfs = loc1 mov ar.pfs = loc1
mov rp = loc0 mov rp = loc0
;; ;;
- srlz.d // seralize restoration of psr.l - srlz.d // serialize restoration of psr.l
+ srlz.i // seralize restoration of psr.l + srlz.i // serialize restoration of psr.l
+ ;; + ;;
br.ret.sptk.many b0 br.ret.sptk.many b0
END(ia64_pal_call_static) END(ia64_pal_call_static)
......
Paravirt_ops on IA64
====================
21 May 2008, Isaku Yamahata <yamahata@valinux.co.jp>
Introduction
------------
The aim of this documentation is to help with maintainability and/or to
encourage people to use paravirt_ops/IA64.
paravirt_ops (pv_ops in short) is a way for virtualization support of
Linux kernel on x86. Several ways for virtualization support were
proposed, paravirt_ops is the winner.
On the other hand, now there are also several IA64 virtualization
technologies like kvm/IA64, xen/IA64 and many other academic IA64
hypervisors so that it is good to add generic virtualization
infrastructure on Linux/IA64.
What is paravirt_ops?
---------------------
It has been developed on x86 as virtualization support via API, not ABI.
It allows each hypervisor to override operations which are important for
hypervisors at API level. And it allows a single kernel binary to run on
all supported execution environments including native machine.
Essentially paravirt_ops is a set of function pointers which represent
operations corresponding to low level sensitive instructions and high
level functionalities in various area. But one significant difference
from usual function pointer table is that it allows optimization with
binary patch. It is because some of these operations are very
performance sensitive and indirect call overhead is not negligible.
With binary patch, indirect C function call can be transformed into
direct C function call or in-place execution to eliminate the overhead.
Thus, operations of paravirt_ops are classified into three categories.
- simple indirect call
These operations correspond to high level functionality so that the
overhead of indirect call isn't very important.
- indirect call which allows optimization with binary patch
Usually these operations correspond to low level instructions. They
are called frequently and performance critical. So the overhead is
very important.
- a set of macros for hand written assembly code
Hand written assembly codes (.S files) also need paravirtualization
because they include sensitive instructions or some of code paths in
them are very performance critical.
The relation to the IA64 machine vector
---------------------------------------
Linux/IA64 has the IA64 machine vector functionality which allows the
kernel to switch implementations (e.g. initialization, ipi, dma api...)
depending on executing platform.
We can replace some implementations very easily defining a new machine
vector. Thus another approach for virtualization support would be
enhancing the machine vector functionality.
But paravirt_ops approach was taken because
- virtualization support needs wider support than machine vector does.
e.g. low level instruction paravirtualization. It must be
initialized very early before platform detection.
- virtualization support needs more functionality like binary patch.
Probably the calling overhead might not be very large compared to the
emulation overhead of virtualization. However in the native case, the
overhead should be eliminated completely.
A single kernel binary should run on each environment including native,
and the overhead of paravirt_ops on native environment should be as
small as possible.
- for full virtualization technology, e.g. KVM/IA64 or
Xen/IA64 HVM domain, the result would be
(the emulated platform machine vector. probably dig) + (pv_ops).
This means that the virtualization support layer should be under
the machine vector layer.
Possibly it might be better to move some function pointers from
paravirt_ops to machine vector. In fact, Xen domU case utilizes both
pv_ops and machine vector.
IA64 paravirt_ops
-----------------
In this section, the concrete paravirt_ops will be discussed.
Because of the architecture difference between ia64 and x86, the
resulting set of functions is very different from x86 pv_ops.
- C function pointer tables
They are not very performance critical so that simple C indirect
function call is acceptable. The following structures are defined at
this moment. For details see linux/include/asm-ia64/paravirt.h
- struct pv_info
This structure describes the execution environment.
- struct pv_init_ops
This structure describes the various initialization hooks.
- struct pv_iosapic_ops
This structure describes hooks to iosapic operations.
- struct pv_irq_ops
This structure describes hooks to irq related operations
- struct pv_time_op
This structure describes hooks to steal time accounting.
- a set of indirect calls which need optimization
Currently this class of functions correspond to a subset of IA64
intrinsics. At this moment the optimization with binary patch isn't
implemented yet.
struct pv_cpu_op is defined. For details see
linux/include/asm-ia64/paravirt_privop.h
Mostly they correspond to ia64 intrinsics 1-to-1.
Caveat: Now they are defined as C indirect function pointers, but in
order to support binary patch optimization, they will be changed
using GCC extended inline assembly code.
- a set of macros for hand written assembly code (.S files)
For maintenance purpose, the taken approach for .S files is single
source code and compile multiple times with different macros definitions.
Each pv_ops instance must define those macros to compile.
The important thing here is that sensitive, but non-privileged
instructions must be paravirtualized and that some privileged
instructions also need paravirtualization for reasonable performance.
Developers who modify .S files must be aware of that. At this moment
an easy checker is implemented to detect paravirtualization breakage.
But it doesn't cover all the cases.
Sometimes this set of macros is called pv_cpu_asm_op. But there is no
corresponding structure in the source code.
Those macros mostly 1:1 correspond to a subset of privileged
instructions. See linux/include/asm-ia64/native/inst.h.
And some functions written in assembly also need to be overrided so
that each pv_ops instance have to define some macros. Again see
linux/include/asm-ia64/native/inst.h.
Those structures must be initialized very early before start_kernel.
Probably initialized in head.S using multi entry point or some other trick.
For native case implementation see linux/arch/ia64/kernel/paravirt.c.
...@@ -31,7 +31,7 @@ The driver works with ALSA drivers simultaneously. For example, the xracer ...@@ -31,7 +31,7 @@ The driver works with ALSA drivers simultaneously. For example, the xracer
uses joystick as input device and PCM device as sound output in one time. uses joystick as input device and PCM device as sound output in one time.
There are no sound or input collisions detected. The source code have There are no sound or input collisions detected. The source code have
comments about them; but I've found the joystick can be initialized comments about them; but I've found the joystick can be initialized
separately of ALSA modules. So, you canm use only one joystick driver separately of ALSA modules. So, you can use only one joystick driver
without ALSA drivers. The ALSA drivers are not needed to compile or without ALSA drivers. The ALSA drivers are not needed to compile or
run this driver. run this driver.
......
$Id: gameport-programming.txt,v 1.3 2001/04/24 13:51:37 vojtech Exp $
Programming gameport drivers Programming gameport drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
mISDN is a new modular ISDN driver, in the long term it should replace
the old I4L driver architecture for passiv ISDN cards.
It was designed to allow a broad range of applications and interfaces
but only have the basic function in kernel, the interface to the user
space is based on sockets with a own address family AF_ISDN.
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册