提交 2fc29911 编写于 作者: T Thomas Gleixner

Merge branch 'master' of /home/tglx/work/mtd/git/linux-2.6.git/

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
#
# NOTE! Don't add files that are generated in specific
# subdirectories here. Add them in the ".gitignore" file
# in that subdirectory instead.
#
# Normal rules
#
.*
*.o
*.a
*.s
*.ko
*.mod.c
#
# Top-level generic files
#
vmlinux*
System.map
Module.symvers
#
# Generated include files
#
include/asm
include/config
include/linux/autoconf.h
include/linux/compile.h
include/linux/version.h
......@@ -18,7 +18,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
......@@ -321,7 +321,7 @@ the "copyright" line and a pointer to where the full notice is found.
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
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
......
......@@ -2211,6 +2211,15 @@ D: OV511 driver
S: (address available on request)
S: USA
N: Ian McDonald
E: iam4@cs.waikato.ac.nz
E: imcdnzl@gmail.com
W: http://wand.net.nz/~iam4
W: http://imcdnzl.blogspot.com
D: DCCP, CCID3
S: Hamilton
S: New Zealand
N: Patrick McHardy
E: kaber@trash.net
P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80
......@@ -2238,6 +2247,12 @@ S: 249 Nichols Avenue
S: Syracuse, New York 13206
S: USA
N: Kyle McMartin
E: kyle@parisc-linux.org
D: Linux/PARISC hacker
D: AD1889 sound driver
S: Ottawa, Canada
N: Dirk Melchers
E: dirk@merlin.nbg.sub.org
D: 8 bit XT hard disk driver for OMTI5520
......@@ -2246,19 +2261,12 @@ S: D-90453 Nuernberg
S: Germany
N: Arnaldo Carvalho de Melo
E: acme@conectiva.com.br
E: acme@kernel.org
E: acme@gnu.org
W: http://bazar2.conectiva.com.br/~acme
W: http://advogato.org/person/acme
E: acme@mandriva.com
E: acme@ghostprotocols.net
W: http://oops.ghostprotocols.net:81/blog/
P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01
D: wanrouter hacking
D: misc Makefile, Config.in, drivers and network stacks fixes
D: IPX & LLC network stacks maintainer
D: Cyclom 2X synchronous card driver
D: wl3501 PCMCIA wireless card driver
D: i18n for minicom, net-tools, util-linux, fetchmail, etc
S: Conectiva S.A.
D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
S: Mandriva
S: R. Tocantins, 89 - Cristo Rei
S: 80050-430 - Curitiba - Paran
S: Brazil
......@@ -2380,8 +2388,8 @@ E: tmolina@cablespeed.com
D: bug fixes, documentation, minor hackery
N: James Morris
E: jmorris@redhat.com
W: http://www.intercode.com.au/jmorris/
E: jmorris@namei.org
W: http://namei.org/
D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
D: Crypto API, general networking, miscellaneous.
S: PO Box 707
......@@ -2423,8 +2431,7 @@ S: Toronto, Ontario
S: Canada
N: Zwane Mwaikambo
E: zwane@linuxpower.ca
W: http://function.linuxpower.ca
E: zwane@arm.linux.org.uk
D: Various driver hacking
D: Lowlevel x86 kernel hacking
D: General debugging
......
......@@ -46,6 +46,8 @@ SubmittingPatches
- procedure to get a source patch included into the kernel tree.
VGA-softcursor.txt
- how to change your VGA cursor from a blinking underscore.
applying-patches.txt
- description of various trees and how to apply their patches.
arm/
- directory with info about Linux on the ARM architecture.
basic_profiling.txt
......@@ -275,7 +277,7 @@ tty.txt
unicode.txt
- info on the Unicode character/font mapping used in Linux.
uml/
- directory with infomation about User Mode Linux.
- directory with information about User Mode Linux.
usb/
- directory with info regarding the Universal Serial Bus.
video4linux/
......
......@@ -65,7 +65,7 @@ o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
o nfs-utils 1.0.5 # showmount --version
o procps 3.2.0 # ps --version
o oprofile 0.9 # oprofiled --version
o udev 058 # udevinfo -V
o udev 071 # udevinfo -V
Kernel compilation
==================
......@@ -237,6 +237,12 @@ udev
udev is a userspace application for populating /dev dynamically with
only entries for devices actually present. udev replaces devfs.
FUSE
----
Needs libfuse 2.4.0 or later. Absolute minimum is 2.3.0 but mount
options 'direct_io' and 'kernel_cache' won't work.
Networking
==========
......@@ -390,6 +396,10 @@ udev
----
o <http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html>
FUSE
----
o <http://sourceforge.net/projects/fuse>
Networking
**********
......
......@@ -236,6 +236,9 @@ ugly), but try to avoid excess. Instead, put the comments at the head
of the function, telling people what it does, and possibly WHY it does
it.
When commenting the kernel API functions, please use the kerneldoc format.
See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc
for details.
Chapter 8: You've made a mess of it
......@@ -407,7 +410,26 @@ Kernel messages do not have to be terminated with a period.
Printing numbers in parentheses (%d) adds no value and should be avoided.
Chapter 13: References
Chapter 13: Allocating memory
The kernel provides the following general purpose memory allocators:
kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API
documentation for further information about them.
The preferred form for passing a size of a struct is the following:
p = kmalloc(sizeof(*p), ...);
The alternative form where struct name is spelled out hurts readability and
introduces an opportunity for a bug when the pointer variable type is changed
but the corresponding sizeof that is passed to a memory allocator is not.
Casting the return value which is a void pointer is redundant. The conversion
from void pointer to any other pointer type is guaranteed by the C programming
language.
Chapter 14: References
The C Programming Language, Second Edition
by Brian W. Kernighan and Dennis M. Ritchie.
......
......@@ -121,7 +121,7 @@ pool's device.
dma_addr_t addr);
This puts memory back into the pool. The pool is what was passed to
the the pool allocation routine; the cpu and dma addresses are what
the pool allocation routine; the cpu and dma addresses are what
were returned when that routine allocated the memory being freed.
......
DMA with ISA and LPC devices
============================
Pierre Ossman <drzeus@drzeus.cx>
This document describes how to do DMA transfers using the old ISA DMA
controller. Even though ISA is more or less dead today the LPC bus
uses the same DMA system so it will be around for quite some time.
Part I - Headers and dependencies
---------------------------------
To do ISA style DMA you need to include two headers:
#include <linux/dma-mapping.h>
#include <asm/dma.h>
The first is the generic DMA API used to convert virtual addresses to
physical addresses (see Documentation/DMA-API.txt for details).
The second contains the routines specific to ISA DMA transfers. Since
this is not present on all platforms make sure you construct your
Kconfig to be dependent on ISA_DMA_API (not ISA) so that nobody tries
to build your driver on unsupported platforms.
Part II - Buffer allocation
---------------------------
The ISA DMA controller has some very strict requirements on which
memory it can access so extra care must be taken when allocating
buffers.
(You usually need a special buffer for DMA transfers instead of
transferring directly to and from your normal data structures.)
The DMA-able address space is the lowest 16 MB of _physical_ memory.
Also the transfer block may not cross page boundaries (which are 64
or 128 KiB depending on which channel you use).
In order to allocate a piece of memory that satisfies all these
requirements you pass the flag GFP_DMA to kmalloc.
Unfortunately the memory available for ISA DMA is scarce so unless you
allocate the memory during boot-up it's a good idea to also pass
__GFP_REPEAT and __GFP_NOWARN to make the allocater try a bit harder.
(This scarcity also means that you should allocate the buffer as
early as possible and not release it until the driver is unloaded.)
Part III - Address translation
------------------------------
To translate the virtual address to a physical use the normal DMA
API. Do _not_ use isa_virt_to_phys() even though it does the same
thing. The reason for this is that the function isa_virt_to_phys()
will require a Kconfig dependency to ISA, not just ISA_DMA_API which
is really all you need. Remember that even though the DMA controller
has its origins in ISA it is used elsewhere.
Note: x86_64 had a broken DMA API when it came to ISA but has since
been fixed. If your arch has problems then fix the DMA API instead of
reverting to the ISA functions.
Part IV - Channels
------------------
A normal ISA DMA controller has 8 channels. The lower four are for
8-bit transfers and the upper four are for 16-bit transfers.
(Actually the DMA controller is really two separate controllers where
channel 4 is used to give DMA access for the second controller (0-3).
This means that of the four 16-bits channels only three are usable.)
You allocate these in a similar fashion as all basic resources:
extern int request_dma(unsigned int dmanr, const char * device_id);
extern void free_dma(unsigned int dmanr);
The ability to use 16-bit or 8-bit transfers is _not_ up to you as a
driver author but depends on what the hardware supports. Check your
specs or test different channels.
Part V - Transfer data
----------------------
Now for the good stuff, the actual DMA transfer. :)
Before you use any ISA DMA routines you need to claim the DMA lock
using claim_dma_lock(). The reason is that some DMA operations are
not atomic so only one driver may fiddle with the registers at a
time.
The first time you use the DMA controller you should call
clear_dma_ff(). This clears an internal register in the DMA
controller that is used for the non-atomic operations. As long as you
(and everyone else) uses the locking functions then you only need to
reset this once.
Next, you tell the controller in which direction you intend to do the
transfer using set_dma_mode(). Currently you have the options
DMA_MODE_READ and DMA_MODE_WRITE.
Set the address from where the transfer should start (this needs to
be 16-bit aligned for 16-bit transfers) and how many bytes to
transfer. Note that it's _bytes_. The DMA routines will do all the
required translation to values that the DMA controller understands.
The final step is enabling the DMA channel and releasing the DMA
lock.
Once the DMA transfer is finished (or timed out) you should disable
the channel again. You should also check get_dma_residue() to make
sure that all data has been transfered.
Example:
int flags, residue;
flags = claim_dma_lock();
clear_dma_ff();
set_dma_mode(channel, DMA_MODE_WRITE);
set_dma_addr(channel, phys_addr);
set_dma_count(channel, num_bytes);
dma_enable(channel);
release_dma_lock(flags);
while (!device_done());
flags = claim_dma_lock();
dma_disable(channel);
residue = dma_get_residue(channel);
if (residue != 0)
printk(KERN_ERR "driver: Incomplete DMA transfer!"
" %d bytes left!\n", residue);
release_dma_lock(flags);
Part VI - Suspend/resume
------------------------
It is the driver's responsibility to make sure that the machine isn't
suspended while a DMA transfer is in progress. Also, all DMA settings
are lost when the system suspends so if your driver relies on the DMA
controller being in a certain state then you have to restore these
registers upon resume.
......@@ -116,7 +116,7 @@ filesystem. Almost.
You still need to actually journal your filesystem changes, this
is done by wrapping them into transactions. Additionally you
also need to wrap the modification of each of the the buffers
also need to wrap the modification of each of the buffers
with calls to the journal layer, so it knows what the modifications
you are actually making are. To do this use journal_start() which
returns a transaction handle.
......@@ -128,7 +128,7 @@ and its counterpart journal_stop(), which indicates the end of a transaction
are nestable calls, so you can reenter a transaction if necessary,
but remember you must call journal_stop() the same number of times as
journal_start() before the transaction is completed (or more accurately
leaves the the update phase). Ext3/VFS makes use of this feature to simplify
leaves the update phase). Ext3/VFS makes use of this feature to simplify
quota support.
</para>
......
......@@ -239,9 +239,9 @@ X!Ilib/string.c
<title>Network device support</title>
<sect1><title>Driver Support</title>
!Enet/core/dev.c
</sect1>
<sect1><title>8390 Based Network Cards</title>
!Edrivers/net/8390.c
!Enet/ethernet/eth.c
!Einclude/linux/etherdevice.h
!Enet/core/wireless.c
</sect1>
<sect1><title>Synchronous PPP</title>
!Edrivers/net/wan/syncppp.c
......@@ -286,7 +286,9 @@ X!Edrivers/pci/search.c
-->
!Edrivers/pci/msi.c
!Edrivers/pci/bus.c
!Edrivers/pci/hotplug.c
<!-- FIXME: Removed for now since no structured comments in source
X!Edrivers/pci/hotplug.c
-->
!Edrivers/pci/probe.c
!Edrivers/pci/rom.c
</sect1>
......
此差异已折叠。
......@@ -96,7 +96,7 @@
<chapter id="pubfunctions">
<title>Public Functions Provided</title>
!Earch/i386/kernel/mca.c
!Edrivers/mca/mca-legacy.c
</chapter>
<chapter id="dmafunctions">
......
......@@ -291,7 +291,7 @@
!Edrivers/usb/core/hcd.c
!Edrivers/usb/core/hcd-pci.c
!Edrivers/usb/core/buffer.c
!Idrivers/usb/core/buffer.c
</chapter>
<chapter>
......@@ -841,7 +841,7 @@ usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
File modification time is not updated by this request.
</para><para>
Those struct members are from some interface descriptor
applying to the the current configuration.
applying to the current configuration.
The interface number is the bInterfaceNumber value, and
the altsetting number is the bAlternateSetting value.
(This resets each endpoint in the interface.)
......
......@@ -345,8 +345,7 @@ if (!retval) {
<programlisting>
static inline void skel_delete (struct usb_skel *dev)
{
if (dev->bulk_in_buffer != NULL)
kfree (dev->bulk_in_buffer);
kfree (dev->bulk_in_buffer);
if (dev->bulk_out_buffer != NULL)
usb_buffer_free (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer,
......
......@@ -605,12 +605,13 @@ is in the ipmi_poweroff module. When the system requests a powerdown,
it will send the proper IPMI commands to do this. This is supported on
several platforms.
There is a module parameter named "poweroff_control" that may either be zero
(do a power down) or 2 (do a power cycle, power the system off, then power
it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do
the same thing on the kernel command line. The parameter is also available
via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the
system does not support power cycling, it will always to the power off.
There is a module parameter named "poweroff_powercycle" that may
either be zero (do a power down) or non-zero (do a power cycle, power
the system off, then power it on in a few seconds). Setting
ipmi_poweroff.poweroff_control=x will do the same thing on the kernel
command line. The parameter is also available via the proc filesystem
in /proc/sys/dev/ipmi/poweroff_powercycle. Note that if the system
does not support power cycling, it will always do the power off.
Note that if you have ACPI enabled, the system will prefer using ACPI to
power off.
......@@ -430,7 +430,7 @@ which may result in system hang. The software driver of specific
MSI-capable hardware is responsible for whether calling
pci_enable_msi or not. A return of zero indicates the kernel
successfully initializes the MSI/MSI-X capability structure of the
device funtion. The device function is now running on MSI/MSI-X mode.
device function. The device function is now running on MSI/MSI-X mode.
5.6 How to tell whether MSI/MSI-X is enabled on device function
......
Using RCU to Protect Dynamic NMI Handlers
Although RCU is usually used to protect read-mostly data structures,
it is possible to use RCU to provide dynamic non-maskable interrupt
handlers, as well as dynamic irq handlers. This document describes
how to do this, drawing loosely from Zwane Mwaikambo's NMI-timer
work in "arch/i386/oprofile/nmi_timer_int.c" and in
"arch/i386/kernel/traps.c".
The relevant pieces of code are listed below, each followed by a
brief explanation.
static int dummy_nmi_callback(struct pt_regs *regs, int cpu)
{
return 0;
}
The dummy_nmi_callback() function is a "dummy" NMI handler that does
nothing, but returns zero, thus saying that it did nothing, allowing
the NMI handler to take the default machine-specific action.
static nmi_callback_t nmi_callback = dummy_nmi_callback;
This nmi_callback variable is a global function pointer to the current
NMI handler.
fastcall void do_nmi(struct pt_regs * regs, long error_code)
{
int cpu;
nmi_enter();
cpu = smp_processor_id();
++nmi_count(cpu);
if (!rcu_dereference(nmi_callback)(regs, cpu))
default_do_nmi(regs);
nmi_exit();
}
The do_nmi() function processes each NMI. It first disables preemption
in the same way that a hardware irq would, then increments the per-CPU
count of NMIs. It then invokes the NMI handler stored in the nmi_callback
function pointer. If this handler returns zero, do_nmi() invokes the
default_do_nmi() function to handle a machine-specific NMI. Finally,
preemption is restored.
Strictly speaking, rcu_dereference() is not needed, since this code runs
only on i386, which does not need rcu_dereference() anyway. However,
it is a good documentation aid, particularly for anyone attempting to
do something similar on Alpha.
Quick Quiz: Why might the rcu_dereference() be necessary on Alpha,
given that the code referenced by the pointer is read-only?
Back to the discussion of NMI and RCU...
void set_nmi_callback(nmi_callback_t callback)
{
rcu_assign_pointer(nmi_callback, callback);
}
The set_nmi_callback() function registers an NMI handler. Note that any
data that is to be used by the callback must be initialized up -before-
the call to set_nmi_callback(). On architectures that do not order
writes, the rcu_assign_pointer() ensures that the NMI handler sees the
initialized values.
void unset_nmi_callback(void)
{
rcu_assign_pointer(nmi_callback, dummy_nmi_callback);
}
This function unregisters an NMI handler, restoring the original
dummy_nmi_handler(). However, there may well be an NMI handler
currently executing on some other CPU. We therefore cannot free
up any data structures used by the old NMI handler until execution
of it completes on all other CPUs.
One way to accomplish this is via synchronize_sched(), perhaps as
follows:
unset_nmi_callback();
synchronize_sched();
kfree(my_nmi_data);
This works because synchronize_sched() blocks until all CPUs complete
any preemption-disabled segments of code that they were executing.
Since NMI handlers disable preemption, synchronize_sched() is guaranteed
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.
Answer to Quick Quiz
Why might the rcu_dereference() be necessary on Alpha, given
that the code referenced by the pointer is read-only?
Answer: The caller to set_nmi_callback() might well have
initialized some data that is to be used by the
new NMI handler. In this case, the rcu_dereference()
would be needed, because otherwise a CPU that received
an NMI just after the new handler was set might see
the pointer to the new NMI handler, but the old
pre-initialized version of the handler's data.
More important, the rcu_dereference() makes it clear
to someone reading the code that the pointer is being
protected by RCU.
......@@ -2,7 +2,8 @@ Read the F-ing Papers!
This document describes RCU-related publications, and is followed by
the corresponding bibtex entries.
the corresponding bibtex entries. A number of the publications may
be found at http://www.rdrop.com/users/paulmck/RCU/.
The first thing resembling RCU was published in 1980, when Kung and Lehman
[Kung80] recommended use of a garbage collector to defer destruction
......@@ -113,6 +114,10 @@ describing how to make RCU safe for soft-realtime applications [Sarma04c],
and a paper describing SELinux performance with RCU [JamesMorris04b].
2005 has seen further adaptation of RCU to realtime use, permitting
preemption of RCU realtime critical sections [PaulMcKenney05a,
PaulMcKenney05b].
Bibtex Entries
@article{Kung80
......@@ -410,3 +415,32 @@ Oregon Health and Sciences University"
\url{http://www.livejournal.com/users/james_morris/2153.html}
[Viewed December 10, 2004]"
}
@unpublished{PaulMcKenney05a
,Author="Paul E. McKenney"
,Title="{[RFC]} {RCU} and {CONFIG\_PREEMPT\_RT} progress"
,month="May"
,year="2005"
,note="Available:
\url{http://lkml.org/lkml/2005/5/9/185}
[Viewed May 13, 2005]"
,annotation="
First publication of working lock-based deferred free patches
for the CONFIG_PREEMPT_RT environment.
"
}
@conference{PaulMcKenney05b
,Author="Paul E. McKenney and Dipankar Sarma"
,Title="Towards Hard Realtime Response from the Linux Kernel on SMP Hardware"
,Booktitle="linux.conf.au 2005"
,month="April"
,year="2005"
,address="Canberra, Australia"
,note="Available:
\url{http://www.rdrop.com/users/paulmck/RCU/realtimeRCU.2005.04.23a.pdf}
[Viewed May 13, 2005]"
,annotation="
Realtime turns into making RCU yet more realtime friendly.
"
}
......@@ -8,7 +8,7 @@ is that since there is only one CPU, it should not be necessary to
wait for anything else to get done, since there are no other CPUs for
anything else to be happening on. Although this approach will -sort- -of-
work a surprising amount of the time, it is a very bad idea in general.
This document presents two examples that demonstrate exactly how bad an
This document presents three examples that demonstrate exactly how bad an
idea this is.
......@@ -26,6 +26,9 @@ from softirq, the list scan would find itself referencing a newly freed
element B. This situation can greatly decrease the life expectancy of
your kernel.
This same problem can occur if call_rcu() is invoked from a hardware
interrupt handler.
Example 2: Function-Call Fatality
......@@ -44,8 +47,37 @@ its arguments would cause it to fail to make the fundamental guarantee
underlying RCU, namely that call_rcu() defers invoking its arguments until
all RCU read-side critical sections currently executing have completed.
Quick Quiz: why is it -not- legal to invoke synchronize_rcu() in
this case?
Quick Quiz #1: why is it -not- legal to invoke synchronize_rcu() in
this case?
Example 3: Death by Deadlock
Suppose that call_rcu() is invoked while holding a lock, and that the
callback function must acquire this same lock. In this case, if
call_rcu() were to directly invoke the callback, the result would
be self-deadlock.
In some cases, it would possible to restructure to code so that
the call_rcu() is delayed until after the lock is released. However,
there are cases where this can be quite ugly:
1. If a number of items need to be passed to call_rcu() within
the same critical section, then the code would need to create
a list of them, then traverse the list once the lock was
released.
2. In some cases, the lock will be held across some kernel API,
so that delaying the call_rcu() until the lock is released
requires that the data item be passed up via a common API.
It is far better to guarantee that callbacks are invoked
with no locks held than to have to modify such APIs to allow
arbitrary data items to be passed back up through them.
If call_rcu() directly invokes the callback, painful locking restrictions
or API changes would be required.
Quick Quiz #2: What locking restriction must RCU callbacks respect?
Summary
......@@ -53,12 +85,35 @@ Summary
Permitting call_rcu() to immediately invoke its arguments or permitting
synchronize_rcu() to immediately return breaks RCU, even on a UP system.
So do not do it! Even on a UP system, the RCU infrastructure -must-
respect grace periods.
Answer to Quick Quiz
The calling function is scanning an RCU-protected linked list, and
is therefore within an RCU read-side critical section. Therefore,
the called function has been invoked within an RCU read-side critical
section, and is not permitted to block.
respect grace periods, and -must- invoke callbacks from a known environment
in which no locks are held.
Answer to Quick Quiz #1:
Why is it -not- legal to invoke synchronize_rcu() in this case?
Because the calling function is scanning an RCU-protected linked
list, and is therefore within an RCU read-side critical section.
Therefore, the called function has been invoked within an RCU
read-side critical section, and is not permitted to block.
Answer to Quick Quiz #2:
What locking restriction must RCU callbacks respect?
Any lock that is acquired within an RCU callback must be
acquired elsewhere using an _irq variant of the spinlock
primitive. For example, if "mylock" is acquired by an
RCU callback, then a process-context acquisition of this
lock must use something like spin_lock_irqsave() to
acquire the lock.
If the process-context code were to simply use spin_lock(),
then, since RCU callbacks can be invoked from softirq context,
the callback might be called from a softirq that interrupted
the process-context critical section. This would result in
self-deadlock.
This restriction might seem gratuitous, since very few RCU
callbacks acquire locks directly. However, a great many RCU
callbacks do acquire locks -indirectly-, for example, via
the kfree() primitive.
......@@ -43,6 +43,10 @@ over a rather long period of time, but improvements are always welcome!
rcu_read_lock_bh()) in the read-side critical sections,
and are also an excellent aid to readability.
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()
or by the appropriate update-side lock.
3. Does the update code tolerate concurrent accesses?
The whole point of RCU is to permit readers to run without
......@@ -90,7 +94,11 @@ over a rather long period of time, but improvements are always welcome!
The rcu_dereference() primitive is used by the various
"_rcu()" list-traversal primitives, such as the
list_for_each_entry_rcu().
list_for_each_entry_rcu(). Note that it is perfectly
legal (if redundant) for update-side code to use
rcu_dereference() and the "_rcu()" list-traversal
primitives. This is particularly useful in code
that is common to readers and updaters.
b. If the list macros are being used, the list_add_tail_rcu()
and list_add_rcu() primitives must be used in order
......@@ -150,16 +158,9 @@ over a rather long period of time, but improvements are always welcome!
Use of the _rcu() list-traversal primitives outside of an
RCU read-side critical section causes no harm other than
a slight performance degradation on Alpha CPUs and some
confusion on the part of people trying to read the code.
Another way of thinking of this is "If you are holding the
lock that prevents the data structure from changing, why do
you also need RCU-based protection?" That said, there may
well be situations where use of the _rcu() list-traversal
primitives while the update-side lock is held results in
simpler and more maintainable code. The jury is still out
on this question.
a slight performance degradation on Alpha CPUs. It can
also be quite helpful in reducing code bloat when common
code is shared between readers and updaters.
10. Conversely, if you are in an RCU read-side critical section,
you -must- use the "_rcu()" variants of the list macros.
......
......@@ -64,6 +64,54 @@ o I hear that RCU is patented? What is with that?
Of these, one was allowed to lapse by the assignee, and the
others have been contributed to the Linux kernel under GPL.
o I hear that RCU needs work in order to support realtime kernels?
Yes, work in progress.
o Where can I find more information on RCU?
See the RTFP.txt file in this directory.
Or point your browser at http://www.rdrop.com/users/paulmck/RCU/.
o What are all these files in this directory?
NMI-RCU.txt
Describes how to use RCU to implement dynamic
NMI handlers, which can be revectored on the fly,
without rebooting.
RTFP.txt
List of RCU-related publications and web sites.
UP.txt
Discussion of RCU usage in UP kernels.
arrayRCU.txt
Describes how to use RCU to protect arrays, with
resizeable arrays whose elements reference other
data structures being of the most interest.
checklist.txt
Lists things to check for when inspecting code that
uses RCU.
listRCU.txt
Describes how to use RCU to protect linked lists.
This is the simplest and most common use of RCU
in the Linux kernel.
rcu.txt
You are reading it!
whatisRCU.txt
Overview of how the RCU implementation works. Along
the way, presents a conceptual view of RCU.
Refcounter framework for elements of lists/arrays protected by
RCU.
Refcounting on elements of lists which are protected by traditional
reader/writer spinlocks or semaphores are straight forward as in:
1. 2.
add() search_and_reference()
{ {
alloc_object read_lock(&list_lock);
... search_for_element
atomic_set(&el->rc, 1); atomic_inc(&el->rc);
write_lock(&list_lock); ...
add_element read_unlock(&list_lock);
... ...
write_unlock(&list_lock); }
}
3. 4.
release_referenced() delete()
{ {
... write_lock(&list_lock);
atomic_dec(&el->rc, relfunc) ...
... delete_element
} write_unlock(&list_lock);
...
if (atomic_dec_and_test(&el->rc))
kfree(el);
...
}
If this list/array is made lock free using rcu as in changing the
write_lock in add() and delete() to spin_lock and changing read_lock
in search_and_reference to rcu_read_lock(), the rcuref_get in
search_and_reference could potentially hold reference to an element which
has already been deleted from the list/array. rcuref_lf_get_rcu takes
care of this scenario. search_and_reference should look as;
1. 2.
add() search_and_reference()
{ {
alloc_object rcu_read_lock();
... search_for_element
atomic_set(&el->rc, 1); if (rcuref_inc_lf(&el->rc)) {
write_lock(&list_lock); rcu_read_unlock();
return FAIL;
add_element }
... ...
write_unlock(&list_lock); rcu_read_unlock();
} }
3. 4.
release_referenced() delete()
{ {
... write_lock(&list_lock);
rcuref_dec(&el->rc, relfunc) ...
... delete_element
} write_unlock(&list_lock);
...
if (rcuref_dec_and_test(&el->rc))
call_rcu(&el->head, el_free);
...
}
Sometimes, reference to the element need to be obtained in the
update (write) stream. In such cases, rcuref_inc_lf might be an overkill
since the spinlock serialising list updates are held. rcuref_inc
is to be used in such cases.
For arches which do not have cmpxchg rcuref_inc_lf
api uses a hashed spinlock implementation and the same hashed spinlock
is acquired in all rcuref_xxx primitives to preserve atomicity.
Note: Use rcuref_inc api only if you need to use rcuref_inc_lf on the
refcounter atleast at one place. Mixing rcuref_inc and atomic_xxx api
might lead to races. rcuref_inc_lf() must be used in lockfree
RCU critical sections only.
RCU Torture Test Operation
CONFIG_RCU_TORTURE_TEST
The CONFIG_RCU_TORTURE_TEST config option is available for all RCU
implementations. It creates an rcutorture kernel module that can
be loaded to run a torture test. The test periodically outputs
status messages via printk(), which can be examined via the dmesg
command (perhaps grepping for "rcutorture"). The test is started
when the module is loaded, and stops when the module is unloaded.
However, actually setting this config option to "y" results in the system
running the test immediately upon boot, and ending only when the system
is taken down. Normally, one will instead want to build the system
with CONFIG_RCU_TORTURE_TEST=m and to use modprobe and rmmod to control
the test, perhaps using a script similar to the one shown at the end of
this document. Note that you will need CONFIG_MODULE_UNLOAD in order
to be able to end the test.
MODULE PARAMETERS
This module has the following parameters:
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.
stat_interval The number of seconds between output of torture
statistics (via printk()). Regardless of the interval,
statistics are printed when the module is unloaded.
Setting the interval to zero causes the statistics to
be printed -only- when the module is unloaded, and this
is the default.
verbose Enable debug printk()s. Default is disabled.
OUTPUT
The statistics output is as follows:
rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
rcutorture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
rcutorture: Reader Pipe: 1466408 9747 0 0 0 0 0 0 0 0 0
rcutorture: Reader Batch: 1464477 11678 0 0 0 0 0 0 0 0
rcutorture: Free-Block Circulation: 1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
rcutorture: --- End of test
The command "dmesg | grep rcutorture:" will extract this information on
most systems. On more esoteric configurations, it may be necessary to
use other commands to access the output of the printk()s used by
the RCU torture test. The printk()s use KERN_ALERT, so they should
be evident. ;-)
The entries are as follows:
o "ggp": The number of counter flips (or batches) since boot.
o "rtc": The hexadecimal address of the structure currently visible
to readers.
o "ver": The number of times since boot that the rcutw writer task
has changed the structure visible to readers.
o "tfle": If non-zero, indicates that the "torture freelist"
containing structure to be placed into the "rtc" area is empty.
This condition is important, since it can fool you into thinking
that RCU is working when it is not. :-/
o "rta": Number of structures allocated from the torture freelist.
o "rtaf": Number of allocations from the torture freelist that have
failed due to the list being empty.
o "rtf": Number of frees into the torture freelist.
o "Reader Pipe": Histogram of "ages" of structures seen by readers.
If any entries past the first two are non-zero, RCU is broken.
And rcutorture prints the error flag string "!!!" to make sure
you notice. The age of a newly allocated structure is zero,
it becomes one when removed from reader visibility, and is
incremented once per grace period subsequently -- and is freed
after passing through (RCU_TORTURE_PIPE_LEN-2) grace periods.
The output displayed above was taken from a correctly working
RCU. If you want to see what it looks like when broken, break
it yourself. ;-)
o "Reader Batch": Another histogram of "ages" of structures seen
by readers, but in terms of counter flips (or batches) rather
than in terms of grace periods. The legal number of non-zero
entries is again two. The reason for this separate view is
that it is easier to get the third entry to show up in the
"Reader Batch" list than in the "Reader Pipe" list.
o "Free-Block Circulation": Shows the number of torture structures
that have reached a given point in the pipeline. The first element
should closely correspond to the number of structures allocated,
the second to the number that have been removed from reader view,
and all but the last remaining to the corresponding number of
passes through a grace period. The last entry should be zero,
as it is only incremented if a torture structure's counter
somehow gets incremented farther than it should.
USAGE
The following script may be used to torture RCU:
#!/bin/sh
modprobe rcutorture
sleep 100
rmmod rcutorture
dmesg | grep rcutorture:
The output can be manually inspected for the error flag of "!!!".
One could of course create a more elaborate script that automatically
checked for such errors.
此差异已折叠。
......@@ -301,8 +301,84 @@ now, but you can do this to mark internal company procedures or just
point out some special detail about the sign-off.
12) The canonical patch format
12) More references for submitting patches
The canonical patch subject line is:
Subject: [PATCH 001/123] subsystem: summary phrase
The canonical patch message body contains the following:
- A "from" line specifying the patch author.
- An empty line.
- The body of the explanation, which will be copied to the
permanent changelog to describe this patch.
- The "Signed-off-by:" lines, described above, which will
also go in the changelog.
- A marker line containing simply "---".
- Any additional comments not suitable for the changelog.
- The actual patch (diff output).
The Subject line format makes it very easy to sort the emails
alphabetically by subject line - pretty much any email reader will
support that - since because the sequence number is zero-padded,
the numerical and alphabetic sort is the same.
The "subsystem" in the email's Subject should identify which
area or subsystem of the kernel is being patched.
The "summary phrase" in the email's Subject should concisely
describe the patch which that email contains. The "summary
phrase" should not be a filename. Do not use the same "summary
phrase" for every patch in a whole patch series.
Bear in mind that the "summary phrase" of your email becomes
a globally-unique identifier for that patch. It propagates
all the way into the git changelog. The "summary phrase" may
later be used in developer discussions which refer to the patch.
People will want to google for the "summary phrase" to read
discussion regarding that patch.
A couple of example Subjects:
Subject: [patch 2/5] ext2: improve scalability of bitmap searching
Subject: [PATCHv2 001/207] x86: fix eflags tracking
The "from" line must be the very first line in the message body,
and has the form:
From: Original Author <author@example.com>
The "from" line specifies who will be credited as the author of the
patch in the permanent changelog. If the "from" line is missing,
then the "From:" line from the email header will be used to determine
the patch author in the changelog.
The explanation body will be committed to the permanent source
changelog, so should make sense to a competent reader who has long
since forgotten the immediate details of the discussion that might
have led to this patch.
The "---" marker line serves the essential purpose of marking for patch
handling tools where the changelog message ends.
One good use for the additional comments after the "---" marker is for
a diffstat, to show what files have changed, and the number of inserted
and deleted lines per file. A diffstat is especially useful on bigger
patches. Other comments relevant only to the moment or the maintainer,
not suitable for the permanent changelog, should also go here.
See more details on the proper patch format in the following
references.
13) More references for submitting patches
Andrew Morton, "The perfect patch" (tpp).
<http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt>
......@@ -310,6 +386,14 @@ Andrew Morton, "The perfect patch" (tpp).
Jeff Garzik, "Linux kernel patch submission format."
<http://linux.yyz.us/patch-format.html>
Greg KH, "How to piss off a kernel subsystem maintainer"
<http://www.kroah.com/log/2005/03/31/>
Kernel Documentation/CodingStyle
<http://sosdg.org/~coywolf/lxr/source/Documentation/CodingStyle>
Linus Torvald's mail on the canonical patch format:
<http://lkml.org/lkml/2005/4/7/183>
-----------------------------------
......
......@@ -33,3 +33,6 @@ The result of the execution of this aml method is
attached to /proc/acpi/hotkey/poll_method, which is dnyamically
created. Please use command "cat /proc/acpi/hotkey/polling_method"
to retrieve it.
Note: Use cmdline "acpi_generic_hotkey" to over-ride
platform-specific with generic driver.
......@@ -8,13 +8,15 @@ fi
n_partitions=${n_partitions:-16}
dir=$1
shelf=$2
nslots=16
maxslot=`echo $nslots 1 - p | dc`
MAJOR=152
set -e
minor=`echo 10 \* $shelf \* $n_partitions | bc`
minor=`echo $nslots \* $shelf \* $n_partitions | bc`
endp=`echo $n_partitions - 1 | bc`
for slot in `seq 0 9`; do
for slot in `seq 0 $maxslot`; do
for part in `seq 0 $endp`; do
name=e$shelf.$slot
test "$part" != "0" && name=${name}p$part
......
Applying Patches To The Linux Kernel
------------------------------------
(Written by Jesper Juhl, August 2005)
A frequently asked question on the Linux Kernel Mailing List is how to apply
a patch to the kernel or, more specifically, what base kernel a patch for
one of the many trees/branches should be applied to. Hopefully this document
will explain this to you.
In addition to explaining how to apply and revert patches, a brief
description of the different kernel trees (and examples of how to apply
their specific patches) is also provided.
What is a patch?
---
A patch is a small text document containing a delta of changes between two
different versions of a source tree. Patches are created with the `diff'
program.
To correctly apply a patch you need to know what base it was generated from
and what new version the patch will change the source tree into. These
should both be present in the patch file metadata or be possible to deduce
from the filename.
How do I apply or revert a patch?
---
You apply a patch with the `patch' program. The patch program reads a diff
(or patch) file and makes the changes to the source tree described in it.
Patches for the Linux kernel are generated relative to the parent directory
holding the kernel source dir.
This means that paths to files inside the patch file contain the name of the
kernel source directories it was generated against (or some other directory
names like "a/" and "b/").
Since this is unlikely to match the name of the kernel source dir on your
local machine (but is often useful info to see what version an otherwise
unlabeled patch was generated against) you should change into your kernel
source directory and then strip the first element of the path from filenames
in the patch file when applying it (the -p1 argument to `patch' does this).
To revert a previously applied patch, use the -R argument to patch.
So, if you applied a patch like this:
patch -p1 < ../patch-x.y.z
You can revert (undo) it like this:
patch -R -p1 < ../patch-x.y.z
How do I feed a patch/diff file to `patch'?
---
This (as usual with Linux and other UNIX like operating systems) can be
done in several different ways.
In all the examples below I feed the file (in uncompressed form) to patch
via stdin using the following syntax:
patch -p1 < path/to/patch-x.y.z
If you just want to be able to follow the examples below and don't want to
know of more than one way to use patch, then you can stop reading this
section here.
Patch can also get the name of the file to use via the -i argument, like
this:
patch -p1 -i path/to/patch-x.y.z
If your patch file is compressed with gzip or bzip2 and you don't want to
uncompress it before applying it, then you can feed it to patch like this
instead:
zcat path/to/patch-x.y.z.gz | patch -p1
bzcat path/to/patch-x.y.z.bz2 | patch -p1
If you wish to uncompress the patch file by hand first before applying it
(what I assume you've done in the examples below), then you simply run
gunzip or bunzip2 on the file - like this:
gunzip patch-x.y.z.gz
bunzip2 patch-x.y.z.bz2
Which will leave you with a plain text patch-x.y.z file that you can feed to
patch via stdin or the -i argument, as you prefer.
A few other nice arguments for patch are -s which causes patch to be silent
except for errors which is nice to prevent errors from scrolling out of the
screen too fast, and --dry-run which causes patch to just print a listing of
what would happen, but doesn't actually make any changes. Finally --verbose
tells patch to print more information about the work being done.
Common errors when patching
---
When patch applies a patch file it attempts to verify the sanity of the
file in different ways.
Checking that the file looks like a valid patch file, checking the code
around the bits being modified matches the context provided in the patch are
just two of the basic sanity checks patch does.
If patch encounters something that doesn't look quite right it has two
options. It can either refuse to apply the changes and abort or it can try
to find a way to make the patch apply with a few minor changes.
One example of something that's not 'quite right' that patch will attempt to
fix up is if all the context matches, the lines being changed match, but the
line numbers are different. This can happen, for example, if the patch makes
a change in the middle of the file but for some reasons a few lines have
been added or removed near the beginning of the file. In that case
everything looks good it has just moved up or down a bit, and patch will
usually adjust the line numbers and apply the patch.
Whenever patch applies a patch that it had to modify a bit to make it fit
it'll tell you about it by saying the patch applied with 'fuzz'.
You should be wary of such changes since even though patch probably got it
right it doesn't /always/ get it right, and the result will sometimes be
wrong.
When patch encounters a change that it can't fix up with fuzz it rejects it
outright and leaves a file with a .rej extension (a reject file). You can
read this file to see exactely what change couldn't be applied, so you can
go fix it up by hand if you wish.
If you don't have any third party patches applied to your kernel source, but
only patches from kernel.org and you apply the patches in the correct order,
and have made no modifications yourself to the source files, then you should
never see a fuzz or reject message from patch. If you do see such messages
anyway, then there's a high risk that either your local source tree or the
patch file is corrupted in some way. In that case you should probably try
redownloading the patch and if things are still not OK then you'd be advised
to start with a fresh tree downloaded in full from kernel.org.
Let's look a bit more at some of the messages patch can produce.
If patch stops and presents a "File to patch:" prompt, then patch could not
find a file to be patched. Most likely you forgot to specify -p1 or you are
in the wrong directory. Less often, you'll find patches that need to be
applied with -p0 instead of -p1 (reading the patch file should reveal if
this is the case - if so, then this is an error by the person who created
the patch but is not fatal).
If you get "Hunk #2 succeeded at 1887 with fuzz 2 (offset 7 lines)." or a
message similar to that, then it means that patch had to adjust the location
of the change (in this example it needed to move 7 lines from where it
expected to make the change to make it fit).
The resulting file may or may not be OK, depending on the reason the file
was different than expected.
This often happens if you try to apply a patch that was generated against a
different kernel version than the one you are trying to patch.
If you get a message like "Hunk #3 FAILED at 2387.", then it means that the
patch could not be applied correctly and the patch program was unable to
fuzz its way through. This will generate a .rej file with the change that
caused the patch to fail and also a .orig file showing you the original
content that couldn't be changed.
If you get "Reversed (or previously applied) patch detected! Assume -R? [n]"
then patch detected that the change contained in the patch seems to have
already been made.
If you actually did apply this patch previously and you just re-applied it
in error, then just say [n]o and abort this patch. If you applied this patch
previously and actually intended to revert it, but forgot to specify -R,
then you can say [y]es here to make patch revert it for you.
This can also happen if the creator of the patch reversed the source and
destination directories when creating the patch, and in that case reverting
the patch will in fact apply it.
A message similar to "patch: **** unexpected end of file in patch" or "patch
unexpectedly ends in middle of line" means that patch could make no sense of
the file you fed to it. Either your download is broken or you tried to feed
patch a compressed patch file without uncompressing it first.
As I already mentioned above, these errors should never happen if you apply
a patch from kernel.org to the correct version of an unmodified source tree.
So if you get these errors with kernel.org patches then you should probably
assume that either your patch file or your tree is broken and I'd advice you
to start over with a fresh download of a full kernel tree and the patch you
wish to apply.
Are there any alternatives to `patch'?
---
Yes there are alternatives. You can use the `interdiff' program
(http://cyberelk.net/tim/patchutils/) to generate a patch representing the
differences between two patches and then apply the result.
This will let you move from something like 2.6.12.2 to 2.6.12.3 in a single
step. The -z flag to interdiff will even let you feed it patches in gzip or
bzip2 compressed form directly without the use of zcat or bzcat or manual
decompression.
Here's how you'd go from 2.6.12.2 to 2.6.12.3 in a single step:
interdiff -z ../patch-2.6.12.2.bz2 ../patch-2.6.12.3.gz | patch -p1
Although interdiff may save you a step or two you are generally advised to
do the additional steps since interdiff can get things wrong in some cases.
Another alternative is `ketchup', which is a python script for automatic
downloading and applying of patches (http://www.selenic.com/ketchup/).
Other nice tools are diffstat which shows a summary of changes made by a
patch, lsdiff which displays a short listing of affected files in a patch
file, along with (optionally) the line numbers of the start of each patch
and grepdiff which displays a list of the files modified by a patch where
the patch contains a given regular expression.
Where can I download the patches?
---
The patches are available at http://kernel.org/
Most recent patches are linked from the front page, but they also have
specific homes.
The 2.6.x.y (-stable) and 2.6.x patches live at
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/
The -rc patches live at
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/testing/
The -git patches live at
ftp://ftp.kernel.org/pub/linux/kernel/v2.6/snapshots/
The -mm kernels live at
ftp://ftp.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/
In place of ftp.kernel.org you can use ftp.cc.kernel.org, where cc is a
country code. This way you'll be downloading from a mirror site that's most
likely geographically closer to you, resulting in faster downloads for you,
less bandwidth used globally and less load on the main kernel.org servers -
these are good things, do use mirrors when possible.
The 2.6.x kernels
---
These are the base stable releases released by Linus. The highest numbered
release is the most recent.
If regressions or other serious flaws are found then a -stable fix patch
will be released (see below) on top of this base. Once a new 2.6.x base
kernel is released, a patch is made available that is a delta between the
previous 2.6.x kernel and the new one.
To apply a patch moving from 2.6.11 to 2.6.12 you'd do the following (note
that such patches do *NOT* apply on top of 2.6.x.y kernels but on top of the
base 2.6.x kernel - if you need to move from 2.6.x.y to 2.6.x+1 you need to
first revert the 2.6.x.y patch).
Here are some examples:
# moving from 2.6.11 to 2.6.12
$ cd ~/linux-2.6.11 # change to kernel source dir
$ patch -p1 < ../patch-2.6.12 # apply the 2.6.12 patch
$ cd ..
$ mv linux-2.6.11 linux-2.6.12 # rename source dir
# moving from 2.6.11.1 to 2.6.12
$ cd ~/linux-2.6.11.1 # change to kernel source dir
$ patch -p1 -R < ../patch-2.6.11.1 # revert the 2.6.11.1 patch
# source dir is now 2.6.11
$ patch -p1 < ../patch-2.6.12 # apply new 2.6.12 patch
$ cd ..
$ mv linux-2.6.11.1 inux-2.6.12 # rename source dir
The 2.6.x.y kernels
---
Kernels with 4 digit versions are -stable kernels. They contain small(ish)
critical fixes for security problems or significant regressions discovered
in a given 2.6.x kernel.
This is the recommended branch for users who want the most recent stable
kernel and are not interested in helping test development/experimental
versions.
If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is
the current stable kernel.
These patches are not incremental, meaning that for example the 2.6.12.3
patch does not apply on top of the 2.6.12.2 kernel source, but rather on top
of the base 2.6.12 kernel source.
So, in order to apply the 2.6.12.3 patch to your existing 2.6.12.2 kernel
source you have to first back out the 2.6.12.2 patch (so you are left with a
base 2.6.12 kernel source) and then apply the new 2.6.12.3 patch.
Here's a small example:
$ cd ~/linux-2.6.12.2 # change into the kernel source dir
$ patch -p1 -R < ../patch-2.6.12.2 # revert the 2.6.12.2 patch
$ patch -p1 < ../patch-2.6.12.3 # apply the new 2.6.12.3 patch
$ cd ..
$ mv linux-2.6.12.2 linux-2.6.12.3 # rename the kernel source dir
The -rc kernels
---
These are release-candidate kernels. These are development kernels released
by Linus whenever he deems the current git (the kernel's source management
tool) tree to be in a reasonably sane state adequate for testing.
These kernels are not stable and you should expect occasional breakage if
you intend to run them. This is however the most stable of the main
development branches and is also what will eventually turn into the next
stable kernel, so it is important that it be tested by as many people as
possible.
This is a good branch to run for people who want to help out testing
development kernels but do not want to run some of the really experimental
stuff (such people should see the sections about -git and -mm kernels below).
The -rc patches are not incremental, they apply to a base 2.6.x kernel, just
like the 2.6.x.y patches described above. The kernel version before the -rcN
suffix denotes the version of the kernel that this -rc kernel will eventually
turn into.
So, 2.6.13-rc5 means that this is the fifth release candidate for the 2.6.13
kernel and the patch should be applied on top of the 2.6.12 kernel source.
Here are 3 examples of how to apply these patches:
# first an example of moving from 2.6.12 to 2.6.13-rc3
$ cd ~/linux-2.6.12 # change into the 2.6.12 source dir
$ patch -p1 < ../patch-2.6.13-rc3 # apply the 2.6.13-rc3 patch
$ cd ..
$ mv linux-2.6.12 linux-2.6.13-rc3 # rename the source dir
# now let's move from 2.6.13-rc3 to 2.6.13-rc5
$ cd ~/linux-2.6.13-rc3 # change into the 2.6.13-rc3 dir
$ patch -p1 -R < ../patch-2.6.13-rc3 # revert the 2.6.13-rc3 patch
$ patch -p1 < ../patch-2.6.13-rc5 # apply the new 2.6.13-rc5 patch
$ cd ..
$ mv linux-2.6.13-rc3 linux-2.6.13-rc5 # rename the source dir
# finally let's try and move from 2.6.12.3 to 2.6.13-rc5
$ cd ~/linux-2.6.12.3 # change to the kernel source dir
$ patch -p1 -R < ../patch-2.6.12.3 # revert the 2.6.12.3 patch
$ patch -p1 < ../patch-2.6.13-rc5 # apply new 2.6.13-rc5 patch
$ cd ..
$ mv linux-2.6.12.3 linux-2.6.13-rc5 # rename the kernel source dir
The -git kernels
---
These are daily snapshots of Linus' kernel tree (managed in a git
repository, hence the name).
These patches are usually released daily and represent the current state of
Linus' tree. They are more experimental than -rc kernels since they are
generated automatically without even a cursory glance to see if they are
sane.
-git patches are not incremental and apply either to a base 2.6.x kernel or
a base 2.6.x-rc kernel - you can see which from their name.
A patch named 2.6.12-git1 applies to the 2.6.12 kernel source and a patch
named 2.6.13-rc3-git2 applies to the source of the 2.6.13-rc3 kernel.
Here are some examples of how to apply these patches:
# moving from 2.6.12 to 2.6.12-git1
$ cd ~/linux-2.6.12 # change to the kernel source dir
$ patch -p1 < ../patch-2.6.12-git1 # apply the 2.6.12-git1 patch
$ cd ..
$ mv linux-2.6.12 linux-2.6.12-git1 # rename the kernel source dir
# moving from 2.6.12-git1 to 2.6.13-rc2-git3
$ cd ~/linux-2.6.12-git1 # change to the kernel source dir
$ patch -p1 -R < ../patch-2.6.12-git1 # revert the 2.6.12-git1 patch
# we now have a 2.6.12 kernel
$ patch -p1 < ../patch-2.6.13-rc2 # apply the 2.6.13-rc2 patch
# the kernel is now 2.6.13-rc2
$ patch -p1 < ../patch-2.6.13-rc2-git3 # apply the 2.6.13-rc2-git3 patch
# the kernel is now 2.6.13-rc2-git3
$ cd ..
$ mv linux-2.6.12-git1 linux-2.6.13-rc2-git3 # rename source dir
The -mm kernels
---
These are experimental kernels released by Andrew Morton.
The -mm tree serves as a sort of proving ground for new features and other
experimental patches.
Once a patch has proved its worth in -mm for a while Andrew pushes it on to
Linus for inclusion in mainline.
Although it's encouraged that patches flow to Linus via the -mm tree, this
is not always enforced.
Subsystem maintainers (or individuals) sometimes push their patches directly
to Linus, even though (or after) they have been merged and tested in -mm (or
sometimes even without prior testing in -mm).
You should generally strive to get your patches into mainline via -mm to
ensure maximum testing.
This branch is in constant flux and contains many experimental features, a
lot of debugging patches not appropriate for mainline etc and is the most
experimental of the branches described in this document.
These kernels are not appropriate for use on systems that are supposed to be
stable and they are more risky to run than any of the other branches (make
sure you have up-to-date backups - that goes for any experimental kernel but
even more so for -mm kernels).
These kernels in addition to all the other experimental patches they contain
usually also contain any changes in the mainline -git kernels available at
the time of release.
Testing of -mm kernels is greatly appreciated since the whole point of the
tree is to weed out regressions, crashes, data corruption bugs, build
breakage (and any other bug in general) before changes are merged into the
more stable mainline Linus tree.
But testers of -mm should be aware that breakage in this tree is more common
than in any other tree.
The -mm kernels are not released on a fixed schedule, but usually a few -mm
kernels are released in between each -rc kernel (1 to 3 is common).
The -mm kernels apply to either a base 2.6.x kernel (when no -rc kernels
have been released yet) or to a Linus -rc kernel.
Here are some examples of applying the -mm patches:
# moving from 2.6.12 to 2.6.12-mm1
$ cd ~/linux-2.6.12 # change to the 2.6.12 source dir
$ patch -p1 < ../2.6.12-mm1 # apply the 2.6.12-mm1 patch
$ cd ..
$ mv linux-2.6.12 linux-2.6.12-mm1 # rename the source appropriately
# moving from 2.6.12-mm1 to 2.6.13-rc3-mm3
$ cd ~/linux-2.6.12-mm1
$ patch -p1 -R < ../2.6.12-mm1 # revert the 2.6.12-mm1 patch
# we now have a 2.6.12 source
$ patch -p1 < ../patch-2.6.13-rc3 # apply the 2.6.13-rc3 patch
# we now have a 2.6.13-rc3 source
$ patch -p1 < ../2.6.13-rc3-mm3 # apply the 2.6.13-rc3-mm3 patch
$ cd ..
$ mv linux-2.6.12-mm1 linux-2.6.13-rc3-mm3 # rename the source dir
This concludes this list of explanations of the various kernel trees and I
hope you are now crystal clear on how to apply the various patches and help
testing the kernel.
......@@ -81,7 +81,8 @@ Adding New Machines
Any large scale modifications, or new drivers should be discussed
on the ARM kernel mailing list (linux-arm-kernel) before being
attempted.
attempted. See http://www.arm.linux.org.uk/mailinglists/ for the
mailing list information.
NAND
......@@ -120,6 +121,43 @@ Clock Management
various clock units
Platform Data
-------------
Whenever a device has platform specific data that is specified
on a per-machine basis, care should be taken to ensure the
following:
1) that default data is not left in the device to confuse the
driver if a machine does not set it at startup
2) the data should (if possible) be marked as __initdata,
to ensure that the data is thrown away if the machine is
not the one currently in use.
The best way of doing this is to make a function that
kmalloc()s an area of memory, and copies the __initdata
and then sets the relevant device's platform data. Making
the function `__init` takes care of ensuring it is discarded
with the rest of the initialisation code
static __init void s3c24xx_xxx_set_platdata(struct xxx_data *pd)
{
struct s3c2410_xxx_mach_info *npd;
npd = kmalloc(sizeof(struct s3c2410_xxx_mach_info), GFP_KERNEL);
if (npd) {
memcpy(npd, pd, sizeof(struct s3c2410_xxx_mach_info));
s3c_device_xxx.dev.platform_data = npd;
} else {
printk(KERN_ERR "no memory for xxx platform data\n");
}
}
Note, since the code is marked as __init, it should not be
exported outside arch/arm/mach-s3c2410/, or exported to
modules via EXPORT_SYMBOL() and related functions.
Port Contributors
-----------------
......@@ -149,6 +187,7 @@ Document Changes
06 Mar 2005 - BJD - Added Christer Weinigel
08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
08 Mar 2005 - BJD - Added section on adding machines
09 Sep 2005 - BJD - Added section on platform data
Document Author
---------------
......
S3C24XX USB Host support
========================
Introduction
------------
This document details the S3C2410/S3C2440 in-built OHCI USB host support.
Configuration
-------------
Enable at least the following kernel options:
menuconfig:
Device Drivers --->
USB support --->
<*> Support for Host-side USB
<*> OHCI HCD support
.config:
CONFIG_USB
CONFIG_USB_OHCI_HCD
Once these options are configured, the standard set of USB device
drivers can be configured and used.
Board Support
-------------
The driver attaches to a platform device, which will need to be
added by the board specific support file in linux/arch/arm/mach-s3c2410,
such as mach-bast.c or mach-smdk2410.c
The platform device's platform_data field is only needed if the
board implements extra power control or over-current monitoring.
The OHCI driver does not ensure the state of the S3C2410's MISCCTRL
register, so if both ports are to be used for the host, then it is
the board support file's responsibility to ensure that the second
port is configured to be connected to the OHCI core.
Platform Data
-------------
See linux/include/asm-arm/arch-s3c2410/usb-control.h for the
descriptions of the platform device data. An implementation
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
The `struct s3c2410_hcd_info` contains a pair of functions
that get called to enable over-current detection, and to
control the port power status.
The ports are numbered 0 and 1.
power_control:
Called to enable or disable the power on the port.
enable_oc:
Called to enable or disable the over-current monitoring.
This should claim or release the resources being used to
check the power condition on the port, such as an IRQ.
report_oc:
The OHCI driver fills this field in for the over-current code
to call when there is a change to the over-current state on
an port. The ports argument is a bitmask of 1 bit per port,
with bit X being 1 for an over-current on port X.
The function s3c2410_usb_report_oc() has been provided to
ensure this is called correctly.
port[x]:
This is struct describes each port, 0 or 1. The platform driver
should set the flags field of each port to S3C_HCDFLG_USED if
the port is enabled.
Document Author
---------------
Ben Dooks, (c) 2005 Simtec Electronics
......@@ -906,9 +906,20 @@ Aside:
4. The I/O scheduler
I/O schedulers are now per queue. They should be runtime switchable and modular
but aren't yet. Jens has most bits to do this, but the sysfs implementation is
missing.
I/O scheduler, a.k.a. elevator, is implemented in two layers. Generic dispatch
queue and specific I/O schedulers. Unless stated otherwise, elevator is used
to refer to both parts and I/O scheduler to specific I/O schedulers.
Block layer implements generic dispatch queue in ll_rw_blk.c and elevator.c.
The generic dispatch queue is responsible for properly ordering barrier
requests, requeueing, handling non-fs requests and all other subtleties.
Specific I/O schedulers are responsible for ordering normal filesystem
requests. They can also choose to delay certain requests to improve
throughput or whatever purpose. As the plural form indicates, there are
multiple I/O schedulers. They can be built as modules but at least one should
be built inside the kernel. Each queue can choose different one and can also
change to another one dynamically.
A block layer call to the i/o scheduler follows the convention elv_xxx(). This
calls elevator_xxx_fn in the elevator switch (drivers/block/elevator.c). Oh,
......@@ -921,44 +932,36 @@ keeping work.
The functions an elevator may implement are: (* are mandatory)
elevator_merge_fn called to query requests for merge with a bio
elevator_merge_req_fn " " " with another request
elevator_merge_req_fn called when two requests get merged. the one
which gets merged into the other one will be
never seen by I/O scheduler again. IOW, after
being merged, the request is gone.
elevator_merged_fn called when a request in the scheduler has been
involved in a merge. It is used in the deadline
scheduler for example, to reposition the request
if its sorting order has changed.
*elevator_next_req_fn returns the next scheduled request, or NULL
if there are none (or none are ready).
elevator_dispatch_fn fills the dispatch queue with ready requests.
I/O schedulers are free to postpone requests by
not filling the dispatch queue unless @force
is non-zero. Once dispatched, I/O schedulers
are not allowed to manipulate the requests -
they belong to generic dispatch queue.
*elevator_add_req_fn called to add a new request into the scheduler
elevator_add_req_fn called to add a new request into the scheduler
elevator_queue_empty_fn returns true if the merge queue is empty.
Drivers shouldn't use this, but rather check
if elv_next_request is NULL (without losing the
request if one exists!)
elevator_remove_req_fn This is called when a driver claims ownership of
the target request - it now belongs to the
driver. It must not be modified or merged.
Drivers must not lose the request! A subsequent
call of elevator_next_req_fn must return the
_next_ request.
elevator_requeue_req_fn called to add a request to the scheduler. This
is used when the request has alrnadebeen
returned by elv_next_request, but hasn't
completed. If this is not implemented then
elevator_add_req_fn is called instead.
elevator_former_req_fn
elevator_latter_req_fn These return the request before or after the
one specified in disk sort order. Used by the
block layer to find merge possibilities.
elevator_completed_req_fn called when a request is completed. This might
come about due to being merged with another or
when the device completes the request.
elevator_completed_req_fn called when a request is completed.
elevator_may_queue_fn returns true if the scheduler wants to allow the
current context to queue a new request even if
......@@ -967,13 +970,33 @@ elevator_may_queue_fn returns true if the scheduler wants to allow the
elevator_set_req_fn
elevator_put_req_fn Must be used to allocate and free any elevator
specific storate for a request.
specific storage for a request.
elevator_activate_req_fn Called when device driver first sees a request.
I/O schedulers can use this callback to
determine when actual execution of a request
starts.
elevator_deactivate_req_fn Called when device driver decides to delay
a request by requeueing it.
elevator_init_fn
elevator_exit_fn Allocate and free any elevator specific storage
for a queue.
4.2 I/O scheduler implementation
4.2 Request flows seen by I/O schedulers
All requests seens by I/O schedulers strictly follow one of the following three
flows.
set_req_fn ->
i. add_req_fn -> (merged_fn ->)* -> dispatch_fn -> activate_req_fn ->
(deactivate_req_fn -> activate_req_fn ->)* -> completed_req_fn
ii. add_req_fn -> (merged_fn ->)* -> merge_req_fn
iii. [none]
-> put_req_fn
4.3 I/O scheduler implementation
The generic i/o scheduler algorithm attempts to sort/merge/batch requests for
optimal disk scan and request servicing performance (based on generic
principles and device capabilities), optimized for:
......@@ -993,18 +1016,7 @@ request in sort order to prevent binary tree lookups.
This arrangement is not a generic block layer characteristic however, so
elevators may implement queues as they please.
ii. Last merge hint
The last merge hint is part of the generic queue layer. I/O schedulers must do
some management on it. For the most part, the most important thing is to make
sure q->last_merge is cleared (set to NULL) when the request on it is no longer
a candidate for merging (for example if it has been sent to the driver).
The last merge performed is cached as a hint for the subsequent request. If
sequential data is being submitted, the hint is used to perform merges without
any scanning. This is not sufficient when there are multiple processes doing
I/O though, so a "merge hash" is used by some schedulers.
iii. Merge hash
ii. Merge hash
AS and deadline use a hash table indexed by the last sector of a request. This
enables merging code to quickly look up "back merge" candidates, even when
multiple I/O streams are being performed at once on one disk.
......@@ -1013,29 +1025,8 @@ multiple I/O streams are being performed at once on one disk.
are far less common than "back merges" due to the nature of most I/O patterns.
Front merges are handled by the binary trees in AS and deadline schedulers.
iv. Handling barrier cases
A request with flags REQ_HARDBARRIER or REQ_SOFTBARRIER must not be ordered
around. That is, they must be processed after all older requests, and before
any newer ones. This includes merges!
In AS and deadline schedulers, barriers have the effect of flushing the reorder
queue. The performance cost of this will vary from nothing to a lot depending
on i/o patterns and device characteristics. Obviously they won't improve
performance, so their use should be kept to a minimum.
v. Handling insertion position directives
A request may be inserted with a position directive. The directives are one of
ELEVATOR_INSERT_BACK, ELEVATOR_INSERT_FRONT, ELEVATOR_INSERT_SORT.
ELEVATOR_INSERT_SORT is a general directive for non-barrier requests.
ELEVATOR_INSERT_BACK is used to insert a barrier to the back of the queue.
ELEVATOR_INSERT_FRONT is used to insert a barrier to the front of the queue, and
overrides the ordering requested by any previous barriers. In practice this is
harmless and required, because it is used for SCSI requeueing. This does not
require flushing the reorder queue, so does not impose a performance penalty.
vi. Plugging the queue to batch requests in anticipation of opportunities for
merge/sort optimizations
iii. Plugging the queue to batch requests in anticipation of opportunities for
merge/sort optimizations
This is just the same as in 2.4 so far, though per-device unplugging
support is anticipated for 2.5. Also with a priority-based i/o scheduler,
......@@ -1069,7 +1060,7 @@ Aside:
blk_kick_queue() to unplug a specific queue (right away ?)
or optionally, all queues, is in the plan.
4.3 I/O contexts
4.4 I/O contexts
I/O contexts provide a dynamically allocated per process data area. They may
be used in I/O schedulers, and in the block layer (could be used for IO statis,
priorities for example). See *io_context in drivers/block/ll_rw_blk.c, and
......
......@@ -49,9 +49,6 @@ changes occur:
page table operations such as what happens during
fork, and exec.
Platform developers note that generic code will always
invoke this interface without mm->page_table_lock held.
3) void flush_tlb_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
......@@ -72,9 +69,6 @@ changes occur:
call flush_tlb_page (see below) for each entry which may be
modified.
Platform developers note that generic code will always
invoke this interface with mm->page_table_lock held.
4) void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
This time we need to remove the PAGE_SIZE sized translation
......@@ -93,9 +87,6 @@ changes occur:
This is used primarily during fault processing.
Platform developers note that generic code will always
invoke this interface with mm->page_table_lock held.
5) void flush_tlb_pgtables(struct mm_struct *mm,
unsigned long start, unsigned long end)
......
......@@ -17,7 +17,9 @@ This driver is known to work with the following cards:
* SA P600
* SA P800
* SA E400
* SA E300
* SA P400i
* SA E200
* SA E200i
If nodes are not already created in the /dev/cciss directory, run as root:
......
......@@ -68,7 +68,8 @@ it a better device citizen. Further thanks to Joel Katz
Porfiri Claudio <C.Porfiri@nisms.tei.ericsson.se> for patches
to make the driver work with the older CDU-510/515 series, and
Heiko Eissfeldt <heiko@colossus.escape.de> for pointing out that
the verify_area() checks were ignoring the results of said checks.
the verify_area() checks were ignoring the results of said checks
(note: verify_area() has since been replaced by access_ok()).
(Acknowledgments from Ron Jeppesen in the 0.3 release:)
Thanks to Corey Minyard who wrote the original CDU-31A driver on which
......
/*
* cn_test.c
*
* 2004-2005 Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru>
* All rights reserved.
*
* 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 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/timer.h>
#include "connector.h"
static struct cb_id cn_test_id = { 0x123, 0x456 };
static char cn_test_name[] = "cn_test";
static struct sock *nls;
static struct timer_list cn_test_timer;
void cn_test_callback(void *data)
{
struct cn_msg *msg = (struct cn_msg *)data;
printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
__func__, jiffies, msg->id.idx, msg->id.val,
msg->seq, msg->ack, msg->len, (char *)msg->data);
}
static int cn_test_want_notify(void)
{
struct cn_ctl_msg *ctl;
struct cn_notify_req *req;
struct cn_msg *msg = NULL;
int size, size0;
struct sk_buff *skb;
struct nlmsghdr *nlh;
u32 group = 1;
size0 = sizeof(*msg) + sizeof(*ctl) + 3 * sizeof(*req);
size = NLMSG_SPACE(size0);
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",
size);
return -ENOMEM;
}
nlh = NLMSG_PUT(skb, 0, 0x123, NLMSG_DONE, size - sizeof(*nlh));
msg = (struct cn_msg *)NLMSG_DATA(nlh);
memset(msg, 0, size0);
msg->id.idx = -1;
msg->id.val = -1;
msg->seq = 0x123;
msg->ack = 0x345;
msg->len = size0 - sizeof(*msg);
ctl = (struct cn_ctl_msg *)(msg + 1);
ctl->idx_notify_num = 1;
ctl->val_notify_num = 2;
ctl->group = group;
ctl->len = msg->len - sizeof(*ctl);
req = (struct cn_notify_req *)(ctl + 1);
/*
* Idx.
*/
req->first = cn_test_id.idx;
req->range = 10;
/*
* Val 0.
*/
req++;
req->first = cn_test_id.val;
req->range = 10;
/*
* Val 1.
*/
req++;
req->first = cn_test_id.val + 20;
req->range = 10;
NETLINK_CB(skb).dst_groups = ctl->group;
//netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC);
netlink_unicast(nls, skb, 0, 0);
printk(KERN_INFO "Request was sent. Group=0x%x.\n", ctl->group);
return 0;
nlmsg_failure:
printk(KERN_ERR "Failed to send %u.%u\n", msg->seq, msg->ack);
kfree_skb(skb);
return -EINVAL;
}
static u32 cn_test_timer_counter;
static void cn_test_timer_func(unsigned long __data)
{
struct cn_msg *m;
char data[32];
m = kmalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
if (m) {
memset(m, 0, sizeof(*m) + sizeof(data));
memcpy(&m->id, &cn_test_id, sizeof(m->id));
m->seq = cn_test_timer_counter;
m->len = sizeof(data);
m->len =
scnprintf(data, sizeof(data), "counter = %u",
cn_test_timer_counter) + 1;
memcpy(m + 1, data, m->len);
cn_netlink_send(m, 0, gfp_any());
kfree(m);
}
cn_test_timer_counter++;
mod_timer(&cn_test_timer, jiffies + HZ);
}
static int cn_test_init(void)
{
int err;
err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
if (err)
goto err_out;
cn_test_id.val++;
err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
if (err) {
cn_del_callback(&cn_test_id);
goto err_out;
}
init_timer(&cn_test_timer);
cn_test_timer.function = cn_test_timer_func;
cn_test_timer.expires = jiffies + HZ;
cn_test_timer.data = 0;
add_timer(&cn_test_timer);
return 0;
err_out:
if (nls && nls->sk_socket)
sock_release(nls->sk_socket);
return err;
}
static void cn_test_fini(void)
{
del_timer_sync(&cn_test_timer);
cn_del_callback(&cn_test_id);
cn_test_id.val--;
cn_del_callback(&cn_test_id);
if (nls && nls->sk_socket)
sock_release(nls->sk_socket);
}
module_init(cn_test_init);
module_exit(cn_test_fini);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Connector's test module");
/*****************************************/
Kernel Connector.
/*****************************************/
Kernel connector - new netlink based userspace <-> kernel space easy
to use communication module.
Connector driver adds possibility to connect various agents using
netlink based network. One must register callback and
identifier. When driver receives special netlink message with
appropriate identifier, appropriate callback will be called.
From the userspace point of view it's quite straightforward:
socket();
bind();
send();
recv();
But if kernelspace want to use full power of such connections, driver
writer must create special sockets, must know about struct sk_buff
handling... Connector allows any kernelspace agents to use netlink
based networking for inter-process communication in a significantly
easier way:
int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
void cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask);
struct cb_id
{
__u32 idx;
__u32 val;
};
idx and val are unique identifiers which must be registered in
connector.h for in-kernel usage. void (*callback) (void *) - is a
callback function which will be called when message with above idx.val
will be received by connector core. Argument for that function must
be dereferenced to struct cn_msg *.
struct cn_msg
{
struct cb_id id;
__u32 seq;
__u32 ack;
__u32 len; /* Length of the following data */
__u8 data[0];
};
/*****************************************/
Connector interfaces.
/*****************************************/
int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
Registers new callback with connector core.
struct cb_id *id - unique connector's user identifier.
It must be registered in connector.h for legal in-kernel users.
char *name - connector's callback symbolic name.
void (*callback) (void *) - connector's callback.
Argument must be dereferenced to struct cn_msg *.
void cn_del_callback(struct cb_id *id);
Unregisters new callback with connector core.
struct cb_id *id - unique connector's user identifier.
void cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask);
Sends message to the specified groups. It can be safely called from
any context, but may silently fail under strong memory pressure.
struct cn_msg * - message header(with attached data).
u32 __group - destination group.
If __group is zero, then appropriate group will
be searched through all registered connector users,
and message will be delivered to the group which was
created for user with the same ID as in msg.
If __group is not zero, then message will be delivered
to the specified group.
int gfp_mask - GFP mask.
Note: When registering new callback user, connector core assigns
netlink group to the user which is equal to it's id.idx.
/*****************************************/
Protocol description.
/*****************************************/
Current offers transport layer with fixed header. Recommended
protocol which uses such header is following:
msg->seq and msg->ack are used to determine message genealogy. When
someone sends message it puts there locally unique sequence and random
acknowledge numbers. Sequence number may be copied into
nlmsghdr->nlmsg_seq too.
Sequence number is incremented with each message to be sent.
If we expect reply to our message, then sequence number in received
message MUST be the same as in original message, and acknowledge
number MUST be the same + 1.
If we receive message and it's sequence number is not equal to one we
are expecting, then it is new message. If we receive message and it's
sequence number is the same as one we are expecting, but it's
acknowledge is not equal acknowledge number in original message + 1,
then it is new message.
Obviously, protocol header contains above id.
connector allows event notification in the following form: kernel
driver or userspace process can ask connector to notify it when
selected id's will be turned on or off(registered or unregistered it's
callback). It is done by sending special command to connector
driver(it also registers itself with id={-1, -1}).
As example of usage Documentation/connector now contains cn_test.c -
testing module which uses connector to request notification and to
send messages.
/*****************************************/
Reliability.
/*****************************************/
Netlink itself is not reliable protocol, that means that messages can
be lost due to memory pressure or process' receiving queue overflowed,
so caller is warned must be prepared. That is why struct cn_msg [main
connector's message header] contains u32 seq and u32 ack fields.
/*****************************************/
Userspace usage.
/*****************************************/
2.6.14 has a new netlink socket implementation, which by default does not
allow to send data to netlink groups other than 1.
So, if to use netlink socket (for example using connector)
with different group number userspace application must subscribe to
that group. It can be achieved by following pseudocode:
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
l_local.nl_family = AF_NETLINK;
l_local.nl_groups = 12345;
l_local.nl_pid = 0;
if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
perror("bind");
close(s);
return -1;
}
{
int on = l_local.nl_groups;
setsockopt(s, 270, 1, &on, sizeof(on));
}
Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket
option. To drop multicast subscription one should call above socket option
with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
2.6.14 netlink code only allows to select a group which is less or equal to
the maximum group number, which is used at netlink_kernel_create() time.
In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use
group number 12345, you must increment CN_NETLINK_USERS to that number.
Additional 0xf numbers are allocated to be used by non-in-kernel users.
Due to this limitation, group 0xffffffff does not work now, so one can
not use add/remove connector's group notifications, but as far as I know,
only cn_test.c test module used it.
Some work in netlink area is still being done, so things can be changed in
2.6.15 timeframe, if it will happen, documentation will be updated for that
kernel.
......@@ -36,7 +36,7 @@ cpufreq stats provides following statistics (explained in detail below).
All the statistics will be from the time the stats driver has been inserted
to the time when a read of a particular statistic is done. Obviously, stats
driver will not have any information about the the frequcny transitions before
driver will not have any information about the frequency transitions before
the stats driver insertion.
--------------------------------------------------------------------------------
......
......@@ -60,6 +60,18 @@ all of the cpus in the system. This removes any overhead due to
load balancing code trying to pull tasks outside of the cpu exclusive
cpuset only to be prevented by the tasks' cpus_allowed mask.
A cpuset that is mem_exclusive restricts kernel allocations for
page, buffer and other data commonly shared by the kernel across
multiple users. All cpusets, whether mem_exclusive or not, restrict
allocations of memory for user space. This enables configuring a
system so that several independent jobs can share common kernel
data, such as file system pages, while isolating each jobs user
allocation in its own cpuset. To do this, construct a large
mem_exclusive cpuset to hold all the jobs, and construct child,
non-mem_exclusive cpusets for each individual job. Only a small
amount of typical kernel memory, such as requests from interrupt
handlers, is allowed to be taken outside even a mem_exclusive cpuset.
User level code may create and destroy cpusets by name in the cpuset
virtual file system, manage the attributes and permissions of these
cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
......@@ -82,7 +94,7 @@ the available CPU and Memory resources amongst the requesting tasks.
But larger systems, which benefit more from careful processor and
memory placement to reduce memory access times and contention,
and which typically represent a larger investment for the customer,
can benefit from explictly placing jobs on properly sized subsets of
can benefit from explicitly placing jobs on properly sized subsets of
the system.
This can be especially valuable on:
......@@ -265,7 +277,7 @@ rewritten to the 'tasks' file of its cpuset. This is done to avoid
impacting the scheduler code in the kernel with a check for changes
in a tasks processor placement.
There is an exception to the above. If hotplug funtionality is used
There is an exception to the above. If hotplug functionality is used
to remove all the CPUs that are currently assigned to a cpuset,
then the kernel will automatically update the cpus_allowed of all
tasks attached to CPUs in that cpuset to allow all CPUs. When memory
......
......@@ -223,6 +223,7 @@ CAST5 algorithm contributors:
TEA/XTEA algorithm contributors:
Aaron Grothe
Michael Ringe
Khazad algorithm contributors:
Aaron Grothe
......
Below is the orginal README file from the descore.shar package.
Below is the original README file from the descore.shar package.
------------------------------------------------------------------------------
des - fast & portable DES encryption & decryption.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -55,6 +55,7 @@ aic7*seq.h*
aicasm
aicdb.h*
asm
asm-offsets.*
asm_offsets.*
autoconf.h*
bbootsect
......
......@@ -350,7 +350,7 @@ When a driver is registered, the bus's list of devices is iterated
over. bus->match() is called for each device that is not already
claimed by a driver.
When a device is successfully bound to a device, device->driver is
When a device is successfully bound to a driver, device->driver is
set, the device is added to a per-driver list of devices, and a
symlink is created in the driver's sysfs directory that points to the
device's physical directory:
......
此差异已折叠。
......@@ -23,7 +23,6 @@ This application requires the following to function properly as of now.
eg: $ szap -c channels.conf -r "TMC" -x
(b) a channels.conf containing a valid PMT PID
eg: TMC:11996:h:0:27500:278:512:650:321
here 278 is a valid PMT PID. the rest of the values are the
......@@ -31,13 +30,7 @@ This application requires the following to function properly as of now.
(c) after running a szap, you have to run ca_zap, for the
descrambler to function,
eg: $ ca_zap patched_channels.conf "TMC"
The patched means a patch to apply to scan, such that scan can
generate a channels.conf_with pmt, which has this PMT PID info
(NOTE: szap cannot use this channels.conf with the PMT_PID)
eg: $ ca_zap channels.conf "TMC"
(d) Hopeflly Enjoy your favourite subscribed channel as you do with
a FTA card.
......
......@@ -7,7 +7,7 @@ To protect itself the kernel has to verify this address.
In older versions of Linux this was done with the
int verify_area(int type, const void * addr, unsigned long size)
function.
function (which has since been replaced by access_ok()).
This function verified that the memory area starting at address
addr and of size size was accessible for the operation specified
......
Bugs
====
I currently don't know of any bug. Please do send reports to:
- linux-fbdev-devel@lists.sourceforge.net
- Knut_Petersen@t-online.de.
Untested features
=================
All LCD stuff is untested. If it worked in tridentfb, it should work in
cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -272,3 +272,6 @@ beep_mask Bitmask for beep.
eeprom Raw EEPROM data in binary form.
Read only.
pec Enable or disable PEC (SMBus only)
Read/Write
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册