Merge commit 'v2.6.27-rc7' into x86/pebs
This commit is contained in:
commit
ebdd90a8cb
8561 changed files with 308130 additions and 160992 deletions
2
.mailmap
2
.mailmap
|
@ -96,4 +96,6 @@ Tejun Heo <htejun@gmail.com>
|
||||||
Thomas Graf <tgraf@suug.ch>
|
Thomas Graf <tgraf@suug.ch>
|
||||||
Tony Luck <tony.luck@intel.com>
|
Tony Luck <tony.luck@intel.com>
|
||||||
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
|
Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
|
||||||
|
Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
|
||||||
|
Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
|
||||||
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
|
Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
|
||||||
|
|
|
@ -89,8 +89,6 @@ cciss.txt
|
||||||
- info, major/minor #'s for Compaq's SMART Array Controllers.
|
- info, major/minor #'s for Compaq's SMART Array Controllers.
|
||||||
cdrom/
|
cdrom/
|
||||||
- directory with information on the CD-ROM drivers that Linux has.
|
- directory with information on the CD-ROM drivers that Linux has.
|
||||||
cli-sti-removal.txt
|
|
||||||
- cli()/sti() removal guide.
|
|
||||||
computone.txt
|
computone.txt
|
||||||
- info on Computone Intelliport II/Plus Multiport Serial Driver.
|
- info on Computone Intelliport II/Plus Multiport Serial Driver.
|
||||||
connector/
|
connector/
|
||||||
|
@ -361,8 +359,6 @@ telephony/
|
||||||
- directory with info on telephony (e.g. voice over IP) support.
|
- directory with info on telephony (e.g. voice over IP) support.
|
||||||
time_interpolators.txt
|
time_interpolators.txt
|
||||||
- info on time interpolators.
|
- info on time interpolators.
|
||||||
tipar.txt
|
|
||||||
- information about Parallel link cable for Texas Instruments handhelds.
|
|
||||||
tty.txt
|
tty.txt
|
||||||
- guide to the locking policies of the tty layer.
|
- guide to the locking policies of the tty layer.
|
||||||
uml/
|
uml/
|
||||||
|
|
315
Documentation/ABI/testing/sysfs-class-regulator
Normal file
315
Documentation/ABI/testing/sysfs-class-regulator
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
What: /sys/class/regulator/.../state
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
state. This holds the regulator output state.
|
||||||
|
|
||||||
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
'enabled'
|
||||||
|
'disabled'
|
||||||
|
'unknown'
|
||||||
|
|
||||||
|
'enabled' means the regulator output is ON and is supplying
|
||||||
|
power to the system.
|
||||||
|
|
||||||
|
'disabled' means the regulator output is OFF and is not
|
||||||
|
supplying power to the system..
|
||||||
|
|
||||||
|
'unknown' means software cannot determine the state.
|
||||||
|
|
||||||
|
NOTE: this field can be used in conjunction with microvolts
|
||||||
|
and microamps to determine regulator output levels.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../type
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
type. This holds the regulator type.
|
||||||
|
|
||||||
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
'voltage'
|
||||||
|
'current'
|
||||||
|
'unknown'
|
||||||
|
|
||||||
|
'voltage' means the regulator output voltage can be controlled
|
||||||
|
by software.
|
||||||
|
|
||||||
|
'current' means the regulator output current limit can be
|
||||||
|
controlled by software.
|
||||||
|
|
||||||
|
'unknown' means software cannot control either voltage or
|
||||||
|
current limit.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../microvolts
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
microvolts. This holds the regulator output voltage setting
|
||||||
|
measured in microvolts (i.e. E-6 Volts).
|
||||||
|
|
||||||
|
NOTE: This value should not be used to determine the regulator
|
||||||
|
output voltage level as this value is the same regardless of
|
||||||
|
whether the regulator is enabled or disabled.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../microamps
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
microamps. This holds the regulator output current limit
|
||||||
|
setting measured in microamps (i.e. E-6 Amps).
|
||||||
|
|
||||||
|
NOTE: This value should not be used to determine the regulator
|
||||||
|
output current level as this value is the same regardless of
|
||||||
|
whether the regulator is enabled or disabled.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../opmode
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
opmode. This holds the regulator operating mode setting.
|
||||||
|
|
||||||
|
The opmode value can be one of the following strings:
|
||||||
|
|
||||||
|
'fast'
|
||||||
|
'normal'
|
||||||
|
'idle'
|
||||||
|
'standby'
|
||||||
|
'unknown'
|
||||||
|
|
||||||
|
The modes are described in include/linux/regulator/regulator.h
|
||||||
|
|
||||||
|
NOTE: This value should not be used to determine the regulator
|
||||||
|
output operating mode as this value is the same regardless of
|
||||||
|
whether the regulator is enabled or disabled.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../min_microvolts
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
min_microvolts. This holds the minimum safe working regulator
|
||||||
|
output voltage setting for this domain measured in microvolts.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'constraint not defined' if
|
||||||
|
the power domain has no min microvolts constraint defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../max_microvolts
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
max_microvolts. This holds the maximum safe working regulator
|
||||||
|
output voltage setting for this domain measured in microvolts.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'constraint not defined' if
|
||||||
|
the power domain has no max microvolts constraint defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../min_microamps
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
min_microamps. This holds the minimum safe working regulator
|
||||||
|
output current limit setting for this domain measured in
|
||||||
|
microamps.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'constraint not defined' if
|
||||||
|
the power domain has no min microamps constraint defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../max_microamps
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
max_microamps. This holds the maximum safe working regulator
|
||||||
|
output current limit setting for this domain measured in
|
||||||
|
microamps.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'constraint not defined' if
|
||||||
|
the power domain has no max microamps constraint defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../num_users
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
num_users. This holds the number of consumer devices that
|
||||||
|
have called regulator_enable() on this regulator.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../requested_microamps
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
requested_microamps. This holds the total requested load
|
||||||
|
current in microamps for this regulator from all its consumer
|
||||||
|
devices.
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../parent
|
||||||
|
Date: April 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Some regulator directories will contain a link called parent.
|
||||||
|
This points to the parent or supply regulator if one exists.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_mem_microvolts
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_mem_microvolts. This holds the regulator output
|
||||||
|
voltage setting for this domain measured in microvolts when
|
||||||
|
the system is suspended to memory.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'not defined' if
|
||||||
|
the power domain has no suspend to memory voltage defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_disk_microvolts
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_disk_microvolts. This holds the regulator output
|
||||||
|
voltage setting for this domain measured in microvolts when
|
||||||
|
the system is suspended to disk.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'not defined' if
|
||||||
|
the power domain has no suspend to disk voltage defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_standby_microvolts
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_standby_microvolts. This holds the regulator output
|
||||||
|
voltage setting for this domain measured in microvolts when
|
||||||
|
the system is suspended to standby.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'not defined' if
|
||||||
|
the power domain has no suspend to standby voltage defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_mem_mode
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_mem_mode. This holds the regulator operating mode
|
||||||
|
setting for this domain when the system is suspended to
|
||||||
|
memory.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'not defined' if
|
||||||
|
the power domain has no suspend to memory mode defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_disk_mode
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_disk_mode. This holds the regulator operating mode
|
||||||
|
setting for this domain when the system is suspended to disk.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'not defined' if
|
||||||
|
the power domain has no suspend to disk mode defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_standby_mode
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_standby_mode. This holds the regulator operating mode
|
||||||
|
setting for this domain when the system is suspended to
|
||||||
|
standby.
|
||||||
|
|
||||||
|
NOTE: this will return the string 'not defined' if
|
||||||
|
the power domain has no suspend to standby mode defined by
|
||||||
|
platform code.
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_mem_state
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_mem_state. This holds the regulator operating state
|
||||||
|
when suspended to memory.
|
||||||
|
|
||||||
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
'enabled'
|
||||||
|
'disabled'
|
||||||
|
'not defined'
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_disk_state
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_disk_state. This holds the regulator operating state
|
||||||
|
when suspended to disk.
|
||||||
|
|
||||||
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
'enabled'
|
||||||
|
'disabled'
|
||||||
|
'not defined'
|
||||||
|
|
||||||
|
What: /sys/class/regulator/.../suspend_standby_state
|
||||||
|
Date: May 2008
|
||||||
|
KernelVersion: 2.6.26
|
||||||
|
Contact: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
Description:
|
||||||
|
Each regulator directory will contain a field called
|
||||||
|
suspend_standby_state. This holds the regulator operating
|
||||||
|
state when suspended to standby.
|
||||||
|
|
||||||
|
This will be one of the following strings:
|
||||||
|
|
||||||
|
'enabled'
|
||||||
|
'disabled'
|
||||||
|
'not defined'
|
27
Documentation/ABI/testing/sysfs-firmware-sgi_uv
Normal file
27
Documentation/ABI/testing/sysfs-firmware-sgi_uv
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
What: /sys/firmware/sgi_uv/
|
||||||
|
Date: August 2008
|
||||||
|
Contact: Russ Anderson <rja@sgi.com>
|
||||||
|
Description:
|
||||||
|
The /sys/firmware/sgi_uv directory contains information
|
||||||
|
about the SGI UV platform.
|
||||||
|
|
||||||
|
Under that directory are a number of files:
|
||||||
|
|
||||||
|
partition_id
|
||||||
|
coherence_id
|
||||||
|
|
||||||
|
The partition_id entry contains the partition id.
|
||||||
|
SGI UV systems can be partitioned into multiple physical
|
||||||
|
machines, which each partition running a unique copy
|
||||||
|
of the operating system. Each partition will have a unique
|
||||||
|
partition id. To display the partition id, use the command:
|
||||||
|
|
||||||
|
cat /sys/firmware/sgi_uv/partition_id
|
||||||
|
|
||||||
|
The coherence_id entry contains the coherence id.
|
||||||
|
A partitioned SGI UV system can have one or more coherence
|
||||||
|
domain. The coherence id indicates which coherence domain
|
||||||
|
this partition is in. To display the coherence id, use the
|
||||||
|
command:
|
||||||
|
|
||||||
|
cat /sys/firmware/sgi_uv/coherence_id
|
26
Documentation/ABI/testing/sysfs-gpio
Normal file
26
Documentation/ABI/testing/sysfs-gpio
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
What: /sys/class/gpio/
|
||||||
|
Date: July 2008
|
||||||
|
KernelVersion: 2.6.27
|
||||||
|
Contact: David Brownell <dbrownell@users.sourceforge.net>
|
||||||
|
Description:
|
||||||
|
|
||||||
|
As a Kconfig option, individual GPIO signals may be accessed from
|
||||||
|
userspace. GPIOs are only made available to userspace by an explicit
|
||||||
|
"export" operation. If a given GPIO is not claimed for use by
|
||||||
|
kernel code, it may be exported by userspace (and unexported later).
|
||||||
|
Kernel code may export it for complete or partial access.
|
||||||
|
|
||||||
|
GPIOs are identified as they are inside the kernel, using integers in
|
||||||
|
the range 0..INT_MAX. See Documentation/gpio.txt for more information.
|
||||||
|
|
||||||
|
/sys/class/gpio
|
||||||
|
/export ... asks the kernel to export a GPIO to userspace
|
||||||
|
/unexport ... to return a GPIO to the kernel
|
||||||
|
/gpioN ... for each exported GPIO #N
|
||||||
|
/value ... always readable, writes fail for input GPIOs
|
||||||
|
/direction ... r/w as: in, out (default low); write: high, low
|
||||||
|
/gpiochipN ... for each gpiochip; #N is its first GPIO
|
||||||
|
/base ... (r/o) same as N
|
||||||
|
/label ... (r/o) descriptive, not necessarily unique
|
||||||
|
/ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)
|
||||||
|
|
|
@ -474,25 +474,29 @@ make a good program).
|
||||||
So, you can either get rid of GNU emacs, or change it to use saner
|
So, you can either get rid of GNU emacs, or change it to use saner
|
||||||
values. To do the latter, you can stick the following in your .emacs file:
|
values. To do the latter, you can stick the following in your .emacs file:
|
||||||
|
|
||||||
(defun linux-c-mode ()
|
(defun c-lineup-arglist-tabs-only (ignored)
|
||||||
"C mode with adjusted defaults for use with the Linux kernel."
|
"Line up argument lists by tabs, not spaces"
|
||||||
(interactive)
|
(let* ((anchor (c-langelem-pos c-syntactic-element))
|
||||||
(c-mode)
|
(column (c-langelem-2nd-pos c-syntactic-element))
|
||||||
(c-set-style "K&R")
|
(offset (- (1+ column) anchor))
|
||||||
(setq tab-width 8)
|
(steps (floor offset c-basic-offset)))
|
||||||
|
(* (max steps 1)
|
||||||
|
c-basic-offset)))
|
||||||
|
|
||||||
|
(add-hook 'c-mode-hook
|
||||||
|
(lambda ()
|
||||||
|
(let ((filename (buffer-file-name)))
|
||||||
|
;; Enable kernel mode for the appropriate files
|
||||||
|
(when (and filename
|
||||||
|
(string-match "~/src/linux-trees" filename))
|
||||||
(setq indent-tabs-mode t)
|
(setq indent-tabs-mode t)
|
||||||
(setq c-basic-offset 8))
|
(c-set-style "linux")
|
||||||
|
(c-set-offset 'arglist-cont-nonempty
|
||||||
|
'(c-lineup-gcc-asm-reg
|
||||||
|
c-lineup-arglist-tabs-only))))))
|
||||||
|
|
||||||
This will define the M-x linux-c-mode command. When hacking on a
|
This will make emacs go better with the kernel coding style for C
|
||||||
module, if you put the string -*- linux-c -*- somewhere on the first
|
files below ~/src/linux-trees.
|
||||||
two lines, this mode will be automatically invoked. Also, you may want
|
|
||||||
to add
|
|
||||||
|
|
||||||
(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode)
|
|
||||||
auto-mode-alist))
|
|
||||||
|
|
||||||
to your .emacs file if you want to have linux-c-mode switched on
|
|
||||||
automagically when you edit source files under /usr/src/linux.
|
|
||||||
|
|
||||||
But even if you fail in getting emacs to do sane formatting, not
|
But even if you fail in getting emacs to do sane formatting, not
|
||||||
everything is lost: use "indent".
|
everything is lost: use "indent".
|
||||||
|
|
|
@ -298,10 +298,10 @@ recommended that you never use these unless you really know what the
|
||||||
cache width is.
|
cache width is.
|
||||||
|
|
||||||
int
|
int
|
||||||
dma_mapping_error(dma_addr_t dma_addr)
|
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||||
|
|
||||||
int
|
int
|
||||||
pci_dma_mapping_error(dma_addr_t dma_addr)
|
pci_dma_mapping_error(struct pci_dev *hwdev, dma_addr_t dma_addr)
|
||||||
|
|
||||||
In some circumstances dma_map_single and dma_map_page will fail to create
|
In some circumstances dma_map_single and dma_map_page will fail to create
|
||||||
a mapping. A driver can check for these errors by testing the returned
|
a mapping. A driver can check for these errors by testing the returned
|
||||||
|
|
|
@ -12,7 +12,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
|
||||||
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
|
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
|
||||||
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
|
||||||
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
|
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
|
||||||
mac80211.xml debugobjects.xml
|
mac80211.xml debugobjects.xml sh.xml
|
||||||
|
|
||||||
###
|
###
|
||||||
# The build process is as follows (targets):
|
# The build process is as follows (targets):
|
||||||
|
@ -102,6 +102,13 @@ C-procfs-example = procfs_example.xml
|
||||||
C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
|
C-procfs-example2 = $(addprefix $(obj)/,$(C-procfs-example))
|
||||||
$(obj)/procfs-guide.xml: $(C-procfs-example2)
|
$(obj)/procfs-guide.xml: $(C-procfs-example2)
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
##oops, this is a kernel module::hostprogs-y := procfs_example
|
||||||
|
obj-m += procfs_example.o
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
notfoundtemplate = echo "*** You have to install docbook-utils or xmlto ***"; \
|
notfoundtemplate = echo "*** You have to install docbook-utils or xmlto ***"; \
|
||||||
exit 1
|
exit 1
|
||||||
db2xtemplate = db2TYPE -o $(dir $@) $<
|
db2xtemplate = db2TYPE -o $(dir $@) $<
|
||||||
|
|
|
@ -98,6 +98,24 @@
|
||||||
"Kernel debugging" select "KGDB: kernel debugging with remote gdb".
|
"Kernel debugging" select "KGDB: kernel debugging with remote gdb".
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
It is advised, but not required that you turn on the
|
||||||
|
CONFIG_FRAME_POINTER kernel option. This option inserts code to
|
||||||
|
into the compiled executable which saves the frame information in
|
||||||
|
registers or on the stack at different points which will allow a
|
||||||
|
debugger such as gdb to more accurately construct stack back traces
|
||||||
|
while debugging the kernel.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
If the architecture that you are using supports the kernel option
|
||||||
|
CONFIG_DEBUG_RODATA, you should consider turning it off. This
|
||||||
|
option will prevent the use of software breakpoints because it
|
||||||
|
marks certain regions of the kernel's memory space as read-only.
|
||||||
|
If kgdb supports it for the architecture you are using, you can
|
||||||
|
use hardware breakpoints if you desire to run with the
|
||||||
|
CONFIG_DEBUG_RODATA option turned on, else you need to turn off
|
||||||
|
this option.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
Next you should choose one of more I/O drivers to interconnect debugging
|
Next you should choose one of more I/O drivers to interconnect debugging
|
||||||
host and debugged target. Early boot debugging requires a KGDB
|
host and debugged target. Early boot debugging requires a KGDB
|
||||||
I/O driver that supports early debugging and the driver must be
|
I/O driver that supports early debugging and the driver must be
|
||||||
|
|
|
@ -29,12 +29,12 @@
|
||||||
|
|
||||||
<revhistory>
|
<revhistory>
|
||||||
<revision>
|
<revision>
|
||||||
<revnumber>1.0 </revnumber>
|
<revnumber>1.0</revnumber>
|
||||||
<date>May 30, 2001</date>
|
<date>May 30, 2001</date>
|
||||||
<revremark>Initial revision posted to linux-kernel</revremark>
|
<revremark>Initial revision posted to linux-kernel</revremark>
|
||||||
</revision>
|
</revision>
|
||||||
<revision>
|
<revision>
|
||||||
<revnumber>1.1 </revnumber>
|
<revnumber>1.1</revnumber>
|
||||||
<date>June 3, 2001</date>
|
<date>June 3, 2001</date>
|
||||||
<revremark>Revised after comments from linux-kernel</revremark>
|
<revremark>Revised after comments from linux-kernel</revremark>
|
||||||
</revision>
|
</revision>
|
||||||
|
|
|
@ -189,8 +189,6 @@ static int __init init_procfs_example(void)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
no_symlink:
|
no_symlink:
|
||||||
remove_proc_entry("tty", example_dir);
|
|
||||||
no_tty:
|
|
||||||
remove_proc_entry("bar", example_dir);
|
remove_proc_entry("bar", example_dir);
|
||||||
no_bar:
|
no_bar:
|
||||||
remove_proc_entry("foo", example_dir);
|
remove_proc_entry("foo", example_dir);
|
||||||
|
@ -206,7 +204,6 @@ out:
|
||||||
static void __exit cleanup_procfs_example(void)
|
static void __exit cleanup_procfs_example(void)
|
||||||
{
|
{
|
||||||
remove_proc_entry("jiffies_too", example_dir);
|
remove_proc_entry("jiffies_too", example_dir);
|
||||||
remove_proc_entry("tty", example_dir);
|
|
||||||
remove_proc_entry("bar", example_dir);
|
remove_proc_entry("bar", example_dir);
|
||||||
remove_proc_entry("foo", example_dir);
|
remove_proc_entry("foo", example_dir);
|
||||||
remove_proc_entry("jiffies", example_dir);
|
remove_proc_entry("jiffies", example_dir);
|
||||||
|
@ -222,3 +219,4 @@ module_exit(cleanup_procfs_example);
|
||||||
|
|
||||||
MODULE_AUTHOR("Erik Mouw");
|
MODULE_AUTHOR("Erik Mouw");
|
||||||
MODULE_DESCRIPTION("procfs examples");
|
MODULE_DESCRIPTION("procfs examples");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
the hardware structures represented here, please consult the Principles
|
the hardware structures represented here, please consult the Principles
|
||||||
of Operation.
|
of Operation.
|
||||||
</para>
|
</para>
|
||||||
!Iinclude/asm-s390/cio.h
|
!Iarch/s390/include/asm/cio.h
|
||||||
</sect1>
|
</sect1>
|
||||||
<sect1 id="ccwdev">
|
<sect1 id="ccwdev">
|
||||||
<title>ccw devices</title>
|
<title>ccw devices</title>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
ccw device structure. Device drivers must not bypass those functions
|
ccw device structure. Device drivers must not bypass those functions
|
||||||
or strange side effects may happen.
|
or strange side effects may happen.
|
||||||
</para>
|
</para>
|
||||||
!Iinclude/asm-s390/ccwdev.h
|
!Iarch/s390/include/asm/ccwdev.h
|
||||||
!Edrivers/s390/cio/device.c
|
!Edrivers/s390/cio/device.c
|
||||||
!Edrivers/s390/cio/device_ops.c
|
!Edrivers/s390/cio/device_ops.c
|
||||||
</sect1>
|
</sect1>
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
measurement data which is made available by the channel subsystem
|
measurement data which is made available by the channel subsystem
|
||||||
for each channel attached device.
|
for each channel attached device.
|
||||||
</para>
|
</para>
|
||||||
!Iinclude/asm-s390/cmb.h
|
!Iarch/s390/include/asm/cmb.h
|
||||||
!Edrivers/s390/cio/cmf.c
|
!Edrivers/s390/cio/cmf.c
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@ -142,7 +142,7 @@
|
||||||
</para>
|
</para>
|
||||||
<sect1 id="ccwgroupdevices">
|
<sect1 id="ccwgroupdevices">
|
||||||
<title>ccw group devices</title>
|
<title>ccw group devices</title>
|
||||||
!Iinclude/asm-s390/ccwgroup.h
|
!Iarch/s390/include/asm/ccwgroup.h
|
||||||
!Edrivers/s390/cio/ccwgroup.c
|
!Edrivers/s390/cio/ccwgroup.c
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
105
Documentation/DocBook/sh.tmpl
Normal file
105
Documentation/DocBook/sh.tmpl
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
|
||||||
|
|
||||||
|
<book id="sh-drivers">
|
||||||
|
<bookinfo>
|
||||||
|
<title>SuperH Interfaces Guide</title>
|
||||||
|
|
||||||
|
<authorgroup>
|
||||||
|
<author>
|
||||||
|
<firstname>Paul</firstname>
|
||||||
|
<surname>Mundt</surname>
|
||||||
|
<affiliation>
|
||||||
|
<address>
|
||||||
|
<email>lethal@linux-sh.org</email>
|
||||||
|
</address>
|
||||||
|
</affiliation>
|
||||||
|
</author>
|
||||||
|
</authorgroup>
|
||||||
|
|
||||||
|
<copyright>
|
||||||
|
<year>2008</year>
|
||||||
|
<holder>Paul Mundt</holder>
|
||||||
|
</copyright>
|
||||||
|
<copyright>
|
||||||
|
<year>2008</year>
|
||||||
|
<holder>Renesas Technology Corp.</holder>
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<legalnotice>
|
||||||
|
<para>
|
||||||
|
This documentation is free software; you can redistribute
|
||||||
|
it and/or modify it under the terms of the GNU General Public
|
||||||
|
License version 2 as published by the Free Software Foundation.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
This program is distributed in the hope that it will be
|
||||||
|
useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
You should have received a copy of the GNU General Public
|
||||||
|
License along with this program; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||||
|
MA 02111-1307 USA
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For more details see the file COPYING in the source
|
||||||
|
distribution of Linux.
|
||||||
|
</para>
|
||||||
|
</legalnotice>
|
||||||
|
</bookinfo>
|
||||||
|
|
||||||
|
<toc></toc>
|
||||||
|
|
||||||
|
<chapter id="mm">
|
||||||
|
<title>Memory Management</title>
|
||||||
|
<sect1 id="sh4">
|
||||||
|
<title>SH-4</title>
|
||||||
|
<sect2 id="sq">
|
||||||
|
<title>Store Queue API</title>
|
||||||
|
!Earch/sh/kernel/cpu/sh4/sq.c
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="sh5">
|
||||||
|
<title>SH-5</title>
|
||||||
|
<sect2 id="tlb">
|
||||||
|
<title>TLB Interfaces</title>
|
||||||
|
!Iarch/sh/mm/tlb-sh5.c
|
||||||
|
!Iarch/sh/include/asm/tlb_64.h
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="clk">
|
||||||
|
<title>Clock Framework Extensions</title>
|
||||||
|
!Iarch/sh/include/asm/clock.h
|
||||||
|
</chapter>
|
||||||
|
<chapter id="mach">
|
||||||
|
<title>Machine Specific Interfaces</title>
|
||||||
|
<sect1 id="dreamcast">
|
||||||
|
<title>mach-dreamcast</title>
|
||||||
|
!Iarch/sh/boards/mach-dreamcast/rtc.c
|
||||||
|
</sect1>
|
||||||
|
<sect1 id="x3proto">
|
||||||
|
<title>mach-x3proto</title>
|
||||||
|
!Earch/sh/boards/mach-x3proto/ilsel.c
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
<chapter id="busses">
|
||||||
|
<title>Busses</title>
|
||||||
|
<sect1 id="superhyway">
|
||||||
|
<title>SuperHyway</title>
|
||||||
|
!Edrivers/sh/superhyway/superhyway.c
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="maple">
|
||||||
|
<title>Maple</title>
|
||||||
|
!Edrivers/sh/maple/maple.c
|
||||||
|
</sect1>
|
||||||
|
</chapter>
|
||||||
|
</book>
|
|
@ -1648,7 +1648,7 @@ static struct video_buffer capture_fb;
|
||||||
|
|
||||||
<chapter id="pubfunctions">
|
<chapter id="pubfunctions">
|
||||||
<title>Public Functions Provided</title>
|
<title>Public Functions Provided</title>
|
||||||
!Edrivers/media/video/videodev.c
|
!Edrivers/media/video/v4l2-dev.c
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
</book>
|
</book>
|
||||||
|
|
|
@ -69,12 +69,6 @@
|
||||||
device to be used as both a tty interface and as a synchronous
|
device to be used as both a tty interface and as a synchronous
|
||||||
controller is a project for Linux post the 2.4 release
|
controller is a project for Linux post the 2.4 release
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
The support code handles most common card configurations and
|
|
||||||
supports running both Cisco HDLC and Synchronous PPP. With extra
|
|
||||||
glue the frame relay and X.25 protocols can also be used with this
|
|
||||||
driver.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="Driver_Modes">
|
<chapter id="Driver_Modes">
|
||||||
|
@ -179,35 +173,27 @@
|
||||||
<para>
|
<para>
|
||||||
If you wish to use the network interface facilities of the driver,
|
If you wish to use the network interface facilities of the driver,
|
||||||
then you need to attach a network device to each channel that is
|
then you need to attach a network device to each channel that is
|
||||||
present and in use. In addition to use the SyncPPP and Cisco HDLC
|
present and in use. In addition to use the generic HDLC
|
||||||
you need to follow some additional plumbing rules. They may seem
|
you need to follow some additional plumbing rules. They may seem
|
||||||
complex but a look at the example hostess_sv11 driver should
|
complex but a look at the example hostess_sv11 driver should
|
||||||
reassure you.
|
reassure you.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The network device used for each channel should be pointed to by
|
The network device used for each channel should be pointed to by
|
||||||
the netdevice field of each channel. The dev-> priv field of the
|
the netdevice field of each channel. The hdlc-> priv field of the
|
||||||
network device points to your private data - you will need to be
|
network device points to your private data - you will need to be
|
||||||
able to find your ppp device from this. In addition to use the
|
able to find your private data from this.
|
||||||
sync ppp layer the private data must start with a void * pointer
|
|
||||||
to the syncppp structures.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The way most drivers approach this particular problem is to
|
The way most drivers approach this particular problem is to
|
||||||
create a structure holding the Z8530 device definition and
|
create a structure holding the Z8530 device definition and
|
||||||
put that and the syncppp pointer into the private field of
|
put that into the private field of the network device. The
|
||||||
the network device. The network device fields of the channels
|
network device fields of the channels then point back to the
|
||||||
then point back to the network devices. The ppp_device can also
|
network devices.
|
||||||
be put in the private structure conveniently.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If you wish to use the synchronous ppp then you need to attach
|
If you wish to use the generic HDLC then you need to register
|
||||||
the syncppp layer to the network device. You should do this before
|
the HDLC device.
|
||||||
you register the network device. The
|
|
||||||
<function>sppp_attach</function> requires that the first void *
|
|
||||||
pointer in your private data is pointing to an empty struct
|
|
||||||
ppp_device. The function fills in the initial data for the
|
|
||||||
ppp/hdlc layer.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Before you register your network device you will also need to
|
Before you register your network device you will also need to
|
||||||
|
@ -314,7 +300,7 @@
|
||||||
buffer in sk_buff format and queues it for transmission. The
|
buffer in sk_buff format and queues it for transmission. The
|
||||||
caller must provide the entire packet with the exception of the
|
caller must provide the entire packet with the exception of the
|
||||||
bitstuffing and CRC. This is normally done by the caller via
|
bitstuffing and CRC. This is normally done by the caller via
|
||||||
the syncppp interface layer. It returns 0 if the buffer has been
|
the generic HDLC interface layer. It returns 0 if the buffer has been
|
||||||
queued and non zero values for queue full. If the function accepts
|
queued and non zero values for queue full. If the function accepts
|
||||||
the buffer it becomes property of the Z8530 layer and the caller
|
the buffer it becomes property of the Z8530 layer and the caller
|
||||||
should not free it.
|
should not free it.
|
||||||
|
|
|
@ -48,7 +48,7 @@ IOVA generation is pretty generic. We used the same technique as vmalloc()
|
||||||
but these are not global address spaces, but separate for each domain.
|
but these are not global address spaces, but separate for each domain.
|
||||||
Different DMA engines may support different number of domains.
|
Different DMA engines may support different number of domains.
|
||||||
|
|
||||||
We also allocate gaurd pages with each mapping, so we can attempt to catch
|
We also allocate guard pages with each mapping, so we can attempt to catch
|
||||||
any overflow that might happen.
|
any overflow that might happen.
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,4 +112,4 @@ TBD
|
||||||
|
|
||||||
- For compatibility testing, could use unity map domain for all devices, just
|
- For compatibility testing, could use unity map domain for all devices, just
|
||||||
provide a 1-1 for all useful memory under a single domain for all devices.
|
provide a 1-1 for all useful memory under a single domain for all devices.
|
||||||
- API for paravirt ops for abstracting functionlity for VMM folks.
|
- API for paravirt ops for abstracting functionality for VMM folks.
|
||||||
|
|
3
Documentation/Makefile
Normal file
3
Documentation/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
|
||||||
|
filesystems/configfs/ ia64/ networking/ \
|
||||||
|
pcmcia/ spi/ video4linux/ vm/ watchdog/src/
|
|
@ -528,7 +528,33 @@ See more details on the proper patch format in the following
|
||||||
references.
|
references.
|
||||||
|
|
||||||
|
|
||||||
|
16) Sending "git pull" requests (from Linus emails)
|
||||||
|
|
||||||
|
Please write the git repo address and branch name alone on the same line
|
||||||
|
so that I can't even by mistake pull from the wrong branch, and so
|
||||||
|
that a triple-click just selects the whole thing.
|
||||||
|
|
||||||
|
So the proper format is something along the lines of:
|
||||||
|
|
||||||
|
"Please pull from
|
||||||
|
|
||||||
|
git://jdelvare.pck.nerim.net/jdelvare-2.6 i2c-for-linus
|
||||||
|
|
||||||
|
to get these changes:"
|
||||||
|
|
||||||
|
so that I don't have to hunt-and-peck for the address and inevitably
|
||||||
|
get it wrong (actually, I've only gotten it wrong a few times, and
|
||||||
|
checking against the diffstat tells me when I get it wrong, but I'm
|
||||||
|
just a lot more comfortable when I don't have to "look for" the right
|
||||||
|
thing to pull, and double-check that I have the right branch-name).
|
||||||
|
|
||||||
|
|
||||||
|
Please use "git diff -M --stat --summary" to generate the diffstat:
|
||||||
|
the -M enables rename detection, and the summary enables a summary of
|
||||||
|
new/deleted or renamed files.
|
||||||
|
|
||||||
|
With rename detection, the statistics are rather different [...]
|
||||||
|
because git will notice that a fair number of the changes are renames.
|
||||||
|
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
SECTION 2 - HINTS, TIPS, AND TRICKS
|
SECTION 2 - HINTS, TIPS, AND TRICKS
|
||||||
|
|
10
Documentation/accounting/Makefile
Normal file
10
Documentation/accounting/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||||
|
obj- := dummy.o
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
hostprogs-y := getdelays
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
|
HOSTCFLAGS_getdelays.o += -I$(objtree)/usr/include
|
|
@ -11,6 +11,7 @@ the delays experienced by a task while
|
||||||
a) waiting for a CPU (while being runnable)
|
a) waiting for a CPU (while being runnable)
|
||||||
b) completion of synchronous block I/O initiated by the task
|
b) completion of synchronous block I/O initiated by the task
|
||||||
c) swapping in pages
|
c) swapping in pages
|
||||||
|
d) memory reclaim
|
||||||
|
|
||||||
and makes these statistics available to userspace through
|
and makes these statistics available to userspace through
|
||||||
the taskstats interface.
|
the taskstats interface.
|
||||||
|
@ -41,7 +42,7 @@ this structure. See
|
||||||
include/linux/taskstats.h
|
include/linux/taskstats.h
|
||||||
for a description of the fields pertaining to delay accounting.
|
for a description of the fields pertaining to delay accounting.
|
||||||
It will generally be in the form of counters returning the cumulative
|
It will generally be in the form of counters returning the cumulative
|
||||||
delay seen for cpu, sync block I/O, swapin etc.
|
delay seen for cpu, sync block I/O, swapin, memory reclaim etc.
|
||||||
|
|
||||||
Taking the difference of two successive readings of a given
|
Taking the difference of two successive readings of a given
|
||||||
counter (say cpu_delay_total) for a task will give the delay
|
counter (say cpu_delay_total) for a task will give the delay
|
||||||
|
@ -94,7 +95,9 @@ CPU count real total virtual total delay total
|
||||||
7876 92005750 100000000 24001500
|
7876 92005750 100000000 24001500
|
||||||
IO count delay total
|
IO count delay total
|
||||||
0 0
|
0 0
|
||||||
MEM count delay total
|
SWAP count delay total
|
||||||
|
0 0
|
||||||
|
RECLAIM count delay total
|
||||||
0 0
|
0 0
|
||||||
|
|
||||||
Get delays seen in executing a given simple command
|
Get delays seen in executing a given simple command
|
||||||
|
@ -108,5 +111,7 @@ CPU count real total virtual total delay total
|
||||||
6 4000250 4000000 0
|
6 4000250 4000000 0
|
||||||
IO count delay total
|
IO count delay total
|
||||||
0 0
|
0 0
|
||||||
MEM count delay total
|
SWAP count delay total
|
||||||
|
0 0
|
||||||
|
RECLAIM count delay total
|
||||||
0 0
|
0 0
|
||||||
|
|
|
@ -196,14 +196,24 @@ void print_delayacct(struct taskstats *t)
|
||||||
" %15llu%15llu%15llu%15llu\n"
|
" %15llu%15llu%15llu%15llu\n"
|
||||||
"IO %15s%15s\n"
|
"IO %15s%15s\n"
|
||||||
" %15llu%15llu\n"
|
" %15llu%15llu\n"
|
||||||
"MEM %15s%15s\n"
|
"SWAP %15s%15s\n"
|
||||||
|
" %15llu%15llu\n"
|
||||||
|
"RECLAIM %12s%15s\n"
|
||||||
" %15llu%15llu\n",
|
" %15llu%15llu\n",
|
||||||
"count", "real total", "virtual total", "delay total",
|
"count", "real total", "virtual total", "delay total",
|
||||||
t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total,
|
(unsigned long long)t->cpu_count,
|
||||||
t->cpu_delay_total,
|
(unsigned long long)t->cpu_run_real_total,
|
||||||
|
(unsigned long long)t->cpu_run_virtual_total,
|
||||||
|
(unsigned long long)t->cpu_delay_total,
|
||||||
"count", "delay total",
|
"count", "delay total",
|
||||||
t->blkio_count, t->blkio_delay_total,
|
(unsigned long long)t->blkio_count,
|
||||||
"count", "delay total", t->swapin_count, t->swapin_delay_total);
|
(unsigned long long)t->blkio_delay_total,
|
||||||
|
"count", "delay total",
|
||||||
|
(unsigned long long)t->swapin_count,
|
||||||
|
(unsigned long long)t->swapin_delay_total,
|
||||||
|
"count", "delay total",
|
||||||
|
(unsigned long long)t->freepages_count,
|
||||||
|
(unsigned long long)t->freepages_delay_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_context_switch_counts(struct taskstats *t)
|
void task_context_switch_counts(struct taskstats *t)
|
||||||
|
@ -211,14 +221,17 @@ void task_context_switch_counts(struct taskstats *t)
|
||||||
printf("\n\nTask %15s%15s\n"
|
printf("\n\nTask %15s%15s\n"
|
||||||
" %15llu%15llu\n",
|
" %15llu%15llu\n",
|
||||||
"voluntary", "nonvoluntary",
|
"voluntary", "nonvoluntary",
|
||||||
t->nvcsw, t->nivcsw);
|
(unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_cgroupstats(struct cgroupstats *c)
|
void print_cgroupstats(struct cgroupstats *c)
|
||||||
{
|
{
|
||||||
printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
|
printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
|
||||||
"uninterruptible %llu\n", c->nr_sleeping, c->nr_io_wait,
|
"uninterruptible %llu\n", (unsigned long long)c->nr_sleeping,
|
||||||
c->nr_running, c->nr_stopped, c->nr_uninterruptible);
|
(unsigned long long)c->nr_io_wait,
|
||||||
|
(unsigned long long)c->nr_running,
|
||||||
|
(unsigned long long)c->nr_stopped,
|
||||||
|
(unsigned long long)c->nr_uninterruptible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ This document contains an explanation of the struct taskstats fields.
|
||||||
There are three different groups of fields in the struct taskstats:
|
There are three different groups of fields in the struct taskstats:
|
||||||
|
|
||||||
1) Common and basic accounting fields
|
1) Common and basic accounting fields
|
||||||
If CONFIG_TASKSTATS is set, the taskstats inteface is enabled and
|
If CONFIG_TASKSTATS is set, the taskstats interface is enabled and
|
||||||
the common fields and basic accounting fields are collected for
|
the common fields and basic accounting fields are collected for
|
||||||
delivery at do_exit() of a task.
|
delivery at do_exit() of a task.
|
||||||
2) Delay accounting fields
|
2) Delay accounting fields
|
||||||
|
@ -26,6 +26,8 @@ There are three different groups of fields in the struct taskstats:
|
||||||
|
|
||||||
5) Time accounting for SMT machines
|
5) Time accounting for SMT machines
|
||||||
|
|
||||||
|
6) Extended delay accounting fields for memory reclaim
|
||||||
|
|
||||||
Future extension should add fields to the end of the taskstats struct, and
|
Future extension should add fields to the end of the taskstats struct, and
|
||||||
should not change the relative position of each field within the struct.
|
should not change the relative position of each field within the struct.
|
||||||
|
|
||||||
|
@ -170,4 +172,9 @@ struct taskstats {
|
||||||
__u64 ac_utimescaled; /* utime scaled on frequency etc */
|
__u64 ac_utimescaled; /* utime scaled on frequency etc */
|
||||||
__u64 ac_stimescaled; /* stime scaled on frequency etc */
|
__u64 ac_stimescaled; /* stime scaled on frequency etc */
|
||||||
__u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
|
__u64 cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
|
||||||
|
|
||||||
|
6) Extended delay accounting fields for memory reclaim
|
||||||
|
/* Delay waiting for memory reclaim */
|
||||||
|
__u64 freepages_count;
|
||||||
|
__u64 freepages_delay_total;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ Linux currently supports the following features on the IXP4xx chips:
|
||||||
- Flash access (MTD/JFFS)
|
- Flash access (MTD/JFFS)
|
||||||
- I2C through GPIO on IXP42x
|
- I2C through GPIO on IXP42x
|
||||||
- GPIO for input/output/interrupts
|
- GPIO for input/output/interrupts
|
||||||
See include/asm-arm/arch-ixp4xx/platform.h for access functions.
|
See arch/arm/mach-ixp4xx/include/mach/platform.h for access functions.
|
||||||
- Timers (watchdog, OS)
|
- Timers (watchdog, OS)
|
||||||
|
|
||||||
The following components of the chips are not supported by Linux and
|
The following components of the chips are not supported by Linux and
|
||||||
|
|
|
@ -138,14 +138,8 @@ So, what's changed?
|
||||||
|
|
||||||
Set active the IRQ edge(s)/level. This replaces the
|
Set active the IRQ edge(s)/level. This replaces the
|
||||||
SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
|
SA1111 INTPOL manipulation, and the set_GPIO_IRQ_edge()
|
||||||
function. Type should be one of the following:
|
function. Type should be one of IRQ_TYPE_xxx defined in
|
||||||
|
<linux/irq.h>
|
||||||
#define IRQT_NOEDGE (0)
|
|
||||||
#define IRQT_RISING (__IRQT_RISEDGE)
|
|
||||||
#define IRQT_FALLING (__IRQT_FALEDGE)
|
|
||||||
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
|
|
||||||
#define IRQT_LOW (__IRQT_LOWLVL)
|
|
||||||
#define IRQT_HIGH (__IRQT_HIGHLVL)
|
|
||||||
|
|
||||||
3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
|
3. set_GPIO_IRQ_edge() is obsolete, and should be replaced by set_irq_type.
|
||||||
|
|
||||||
|
@ -164,7 +158,7 @@ So, what's changed?
|
||||||
be re-checked for pending events. (see the Neponset IRQ handler for
|
be re-checked for pending events. (see the Neponset IRQ handler for
|
||||||
details).
|
details).
|
||||||
|
|
||||||
7. fixup_irq() is gone, as is include/asm-arm/arch-*/irq.h
|
7. fixup_irq() is gone, as is arch/arm/mach-*/include/mach/irq.h
|
||||||
|
|
||||||
Please note that this will not solve all problems - some of them are
|
Please note that this will not solve all problems - some of them are
|
||||||
hardware based. Mixing level-based and edge-based IRQs on the same
|
hardware based. Mixing level-based and edge-based IRQs on the same
|
||||||
|
|
|
@ -79,7 +79,7 @@ Machine/Platform support
|
||||||
To this end, we now have arch/arm/mach-$(MACHINE) directories which are
|
To this end, we now have arch/arm/mach-$(MACHINE) directories which are
|
||||||
designed to house the non-driver files for a particular machine (eg, PCI,
|
designed to house the non-driver files for a particular machine (eg, PCI,
|
||||||
memory management, architecture definitions etc). For all future
|
memory management, architecture definitions etc). For all future
|
||||||
machines, there should be a corresponding include/asm-arm/arch-$(MACHINE)
|
machines, there should be a corresponding arch/arm/mach-$(MACHINE)/include/mach
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ Kernel entry (head.S)
|
||||||
class typically based around one or more system on a chip devices, and
|
class typically based around one or more system on a chip devices, and
|
||||||
acts as a natural container around the actual implementations. These
|
acts as a natural container around the actual implementations. These
|
||||||
classes are given directories - arch/arm/mach-<class> and
|
classes are given directories - arch/arm/mach-<class> and
|
||||||
include/asm-arm/arch-<class> - which contain the source files to
|
arch/arm/mach-<class> - which contain the source files to/include/mach
|
||||||
support the machine class. This directories also contain any machine
|
support the machine class. This directories also contain any machine
|
||||||
specific supporting code.
|
specific supporting code.
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,31 @@ Introduction
|
||||||
data-sheet/users manual to find out the complete list.
|
data-sheet/users manual to find out the complete list.
|
||||||
|
|
||||||
|
|
||||||
|
GPIOLIB
|
||||||
|
-------
|
||||||
|
|
||||||
|
With the event of the GPIOLIB in drivers/gpio, support for some
|
||||||
|
of the GPIO functions such as reading and writing a pin will
|
||||||
|
be removed in favour of this common access method.
|
||||||
|
|
||||||
|
Once all the extant drivers have been converted, the functions
|
||||||
|
listed below will be removed (they may be marked as __deprecated
|
||||||
|
in the near future).
|
||||||
|
|
||||||
|
- s3c2410_gpio_getpin
|
||||||
|
- s3c2410_gpio_setpin
|
||||||
|
|
||||||
|
|
||||||
Headers
|
Headers
|
||||||
-------
|
-------
|
||||||
|
|
||||||
See include/asm-arm/arch-s3c2410/regs-gpio.h for the list
|
See arch/arm/mach-s3c2410/include/mach/regs-gpio.h for the list
|
||||||
of GPIO pins, and the configuration values for them. This
|
of GPIO pins, and the configuration values for them. This
|
||||||
is included by using #include <asm/arch/regs-gpio.h>
|
is included by using #include <mach/regs-gpio.h>
|
||||||
|
|
||||||
The GPIO management functions are defined in the hardware
|
The GPIO management functions are defined in the hardware
|
||||||
header include/asm-arm/arch-s3c2410/hardware.h which can be
|
header arch/arm/mach-s3c2410/include/mach/hardware.h which can be
|
||||||
included by #include <asm/arch/hardware.h>
|
included by #include <mach/hardware.h>
|
||||||
|
|
||||||
A useful amount of documentation can be found in the hardware
|
A useful amount of documentation can be found in the hardware
|
||||||
header on how the GPIO functions (and others) work.
|
header on how the GPIO functions (and others) work.
|
||||||
|
|
|
@ -8,9 +8,10 @@ Introduction
|
||||||
|
|
||||||
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
|
The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
|
||||||
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
|
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
|
||||||
S3C2412, S3C2413, S3C2440 and S3C2442 devices are supported.
|
S3C2412, S3C2413, S3C2440, S3C2442 and S3C2443 devices are supported.
|
||||||
|
|
||||||
|
Support for the S3C2400 and S3C24A0 series are in progress.
|
||||||
|
|
||||||
Support for the S3C2400 series is in progress.
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
@ -36,7 +37,23 @@ Layout
|
||||||
in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
|
in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440
|
||||||
|
|
||||||
Register, kernel and platform data definitions are held in the
|
Register, kernel and platform data definitions are held in the
|
||||||
include/asm-arm/arch-s3c2410 directory.
|
arch/arm/mach-s3c2410 directory./include/mach
|
||||||
|
|
||||||
|
arch/arm/plat-s3c24xx:
|
||||||
|
|
||||||
|
Files in here are either common to all the s3c24xx family,
|
||||||
|
or are common to only some of them with names to indicate this
|
||||||
|
status. The files that are not common to all are generally named
|
||||||
|
with the initial cpu they support in the series to ensure a short
|
||||||
|
name without any possibility of confusion with newer devices.
|
||||||
|
|
||||||
|
As an example, initially s3c244x would cover s3c2440 and s3c2442, but
|
||||||
|
with the s3c2443 which does not share many of the same drivers in
|
||||||
|
this directory, the name becomes invalid. We stick to s3c2440-<x>
|
||||||
|
to indicate a driver that is s3c2440 and s3c2442 compatible.
|
||||||
|
|
||||||
|
This does mean that to find the status of any given SoC, a number
|
||||||
|
of directories may need to be searched.
|
||||||
|
|
||||||
|
|
||||||
Machines
|
Machines
|
||||||
|
@ -159,6 +176,17 @@ NAND
|
||||||
For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
|
For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt
|
||||||
|
|
||||||
|
|
||||||
|
SD/MMC
|
||||||
|
------
|
||||||
|
|
||||||
|
The SD/MMC hardware pre S3C2443 is supported in the current
|
||||||
|
kernel, the driver is drivers/mmc/host/s3cmci.c and supports
|
||||||
|
1 and 4 bit SD or MMC cards.
|
||||||
|
|
||||||
|
The SDIO behaviour of this driver has not been fully tested. There is no
|
||||||
|
current support for hardware SDIO interrupts.
|
||||||
|
|
||||||
|
|
||||||
Serial
|
Serial
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -178,6 +206,9 @@ GPIO
|
||||||
The core contains support for manipulating the GPIO, see the
|
The core contains support for manipulating the GPIO, see the
|
||||||
documentation in GPIO.txt in the same directory as this file.
|
documentation in GPIO.txt in the same directory as this file.
|
||||||
|
|
||||||
|
Newer kernels carry GPIOLIB, and support is being moved towards
|
||||||
|
this with some of the older support in line to be removed.
|
||||||
|
|
||||||
|
|
||||||
Clock Management
|
Clock Management
|
||||||
----------------
|
----------------
|
||||||
|
|
|
@ -49,7 +49,7 @@ Board Support
|
||||||
Platform Data
|
Platform Data
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
See linux/include/asm-arm/arch-s3c2410/usb-control.h for the
|
See arch/arm/mach-s3c2410/include/mach/usb-control.h for the
|
||||||
descriptions of the platform device data. An implementation
|
descriptions of the platform device data. An implementation
|
||||||
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
|
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
|
||||||
|
|
||||||
|
|
10
Documentation/auxdisplay/Makefile
Normal file
10
Documentation/auxdisplay/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||||
|
obj- := dummy.o
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
hostprogs-y := cfag12864b-example
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
|
HOSTCFLAGS_cfag12864b-example.o += -I$(objtree)/usr/include
|
67
Documentation/bt8xxgpio.txt
Normal file
67
Documentation/bt8xxgpio.txt
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
===============================================================
|
||||||
|
== BT8XXGPIO driver ==
|
||||||
|
== ==
|
||||||
|
== A driver for a selfmade cheap BT8xx based PCI GPIO-card ==
|
||||||
|
== ==
|
||||||
|
== For advanced documentation, see ==
|
||||||
|
== http://www.bu3sch.de/btgpio.php ==
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
|
||||||
|
A generic digital 24-port PCI GPIO card can be built out of an ordinary
|
||||||
|
Brooktree bt848, bt849, bt878 or bt879 based analog TV tuner card. The
|
||||||
|
Brooktree chip is used in old analog Hauppauge WinTV PCI cards. You can easily
|
||||||
|
find them used for low prices on the net.
|
||||||
|
|
||||||
|
The bt8xx chip does have 24 digital GPIO ports.
|
||||||
|
These ports are accessible via 24 pins on the SMD chip package.
|
||||||
|
|
||||||
|
|
||||||
|
==============================================
|
||||||
|
== How to physically access the GPIO pins ==
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
The are several ways to access these pins. One might unsolder the whole chip
|
||||||
|
and put it on a custom PCI board, or one might only unsolder each individual
|
||||||
|
GPIO pin and solder that to some tiny wire. As the chip package really is tiny
|
||||||
|
there are some advanced soldering skills needed in any case.
|
||||||
|
|
||||||
|
The physical pinouts are drawn in the following ASCII art.
|
||||||
|
The GPIO pins are marked with G00-G23
|
||||||
|
|
||||||
|
G G G G G G G G G G G G G G G G G G
|
||||||
|
0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
|
||||||
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
--| ^ ^ |--
|
||||||
|
--| pin 86 pin 67 |--
|
||||||
|
--| |--
|
||||||
|
--| pin 61 > |-- G18
|
||||||
|
--| |-- G19
|
||||||
|
--| |-- G20
|
||||||
|
--| |-- G21
|
||||||
|
--| |-- G22
|
||||||
|
--| pin 56 > |-- G23
|
||||||
|
--| |--
|
||||||
|
--| Brooktree 878/879 |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| |--
|
||||||
|
--| O |--
|
||||||
|
--| |--
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
||||||
|
^
|
||||||
|
This is pin 1
|
||||||
|
|
|
@ -112,27 +112,18 @@ Hot plug support for SCSI tape drives
|
||||||
|
|
||||||
Hot plugging of SCSI tape drives is supported, with some caveats.
|
Hot plugging of SCSI tape drives is supported, with some caveats.
|
||||||
The cciss driver must be informed that changes to the SCSI bus
|
The cciss driver must be informed that changes to the SCSI bus
|
||||||
have been made, in addition to and prior to informing the SCSI
|
have been made. This may be done via the /proc filesystem.
|
||||||
mid layer. This may be done via the /proc filesystem. For example:
|
For example:
|
||||||
|
|
||||||
echo "rescan" > /proc/scsi/cciss0/1
|
echo "rescan" > /proc/scsi/cciss0/1
|
||||||
|
|
||||||
This causes the adapter to query the adapter about changes to the
|
This causes the driver to query the adapter about changes to the
|
||||||
physical SCSI buses and/or fibre channel arbitrated loop and the
|
physical SCSI buses and/or fibre channel arbitrated loop and the
|
||||||
driver to make note of any new or removed sequential access devices
|
driver to make note of any new or removed sequential access devices
|
||||||
or medium changers. The driver will output messages indicating what
|
or medium changers. The driver will output messages indicating what
|
||||||
devices have been added or removed and the controller, bus, target and
|
devices have been added or removed and the controller, bus, target and
|
||||||
lun used to address the device. Once this is done, the SCSI mid layer
|
lun used to address the device. It then notifies the SCSI mid layer
|
||||||
can be informed of changes to the virtual SCSI bus which the driver
|
of these changes.
|
||||||
presents to it in the usual way. For example:
|
|
||||||
|
|
||||||
echo scsi add-single-device 3 2 1 0 > /proc/scsi/scsi
|
|
||||||
|
|
||||||
to add a device on controller 3, bus 2, target 1, lun 0. Note that
|
|
||||||
the driver makes an effort to preserve the devices positions
|
|
||||||
in the virtual SCSI bus, so if you are only moving tape drives
|
|
||||||
around on the same adapter and not adding or removing tape drives
|
|
||||||
from the adapter, informing the SCSI mid layer may not be necessary.
|
|
||||||
|
|
||||||
Note that the naming convention of the /proc filesystem entries
|
Note that the naming convention of the /proc filesystem entries
|
||||||
contains a number in addition to the driver name. (E.g. "cciss0"
|
contains a number in addition to the driver name. (E.g. "cciss0"
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
|
|
||||||
#### cli()/sti() removal guide, started by Ingo Molnar <mingo@redhat.com>
|
|
||||||
|
|
||||||
|
|
||||||
as of 2.5.28, five popular macros have been removed on SMP, and
|
|
||||||
are being phased out on UP:
|
|
||||||
|
|
||||||
cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags)
|
|
||||||
|
|
||||||
until now it was possible to protect driver code against interrupt
|
|
||||||
handlers via a cli(), but from now on other, more lightweight methods
|
|
||||||
have to be used for synchronization, such as spinlocks or semaphores.
|
|
||||||
|
|
||||||
for example, driver code that used to do something like:
|
|
||||||
|
|
||||||
struct driver_data;
|
|
||||||
|
|
||||||
irq_handler (...)
|
|
||||||
{
|
|
||||||
....
|
|
||||||
driver_data.finish = 1;
|
|
||||||
driver_data.new_work = 0;
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
ioctl_func (...)
|
|
||||||
{
|
|
||||||
...
|
|
||||||
cli();
|
|
||||||
...
|
|
||||||
driver_data.finish = 0;
|
|
||||||
driver_data.new_work = 2;
|
|
||||||
...
|
|
||||||
sti();
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
was SMP-correct because the cli() function ensured that no
|
|
||||||
interrupt handler (amongst them the above irq_handler()) function
|
|
||||||
would execute while the cli()-ed section is executing.
|
|
||||||
|
|
||||||
but from now on a more direct method of locking has to be used:
|
|
||||||
|
|
||||||
DEFINE_SPINLOCK(driver_lock);
|
|
||||||
struct driver_data;
|
|
||||||
|
|
||||||
irq_handler (...)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
....
|
|
||||||
spin_lock_irqsave(&driver_lock, flags);
|
|
||||||
....
|
|
||||||
driver_data.finish = 1;
|
|
||||||
driver_data.new_work = 0;
|
|
||||||
....
|
|
||||||
spin_unlock_irqrestore(&driver_lock, flags);
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
ioctl_func (...)
|
|
||||||
{
|
|
||||||
...
|
|
||||||
spin_lock_irq(&driver_lock);
|
|
||||||
...
|
|
||||||
driver_data.finish = 0;
|
|
||||||
driver_data.new_work = 2;
|
|
||||||
...
|
|
||||||
spin_unlock_irq(&driver_lock);
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
the above code has a number of advantages:
|
|
||||||
|
|
||||||
- the locking relation is easier to understand - actual lock usage
|
|
||||||
pinpoints the critical sections. cli() usage is too opaque.
|
|
||||||
Easier to understand means it's easier to debug.
|
|
||||||
|
|
||||||
- it's faster, because spinlocks are faster to acquire than the
|
|
||||||
potentially heavily-used IRQ lock. Furthermore, your driver does
|
|
||||||
not have to wait eg. for a big heavy SCSI interrupt to finish,
|
|
||||||
because the driver_lock spinlock is only used by your driver.
|
|
||||||
cli() on the other hand was used by many drivers, and extended
|
|
||||||
the critical section to the whole IRQ handler function - creating
|
|
||||||
serious lock contention.
|
|
||||||
|
|
||||||
|
|
||||||
to make the transition easier, we've still kept the cli(), sti(),
|
|
||||||
save_flags(), save_flags_cli() and restore_flags() macros defined
|
|
||||||
on UP systems - but their usage will be phased out until 2.6 is
|
|
||||||
released.
|
|
||||||
|
|
||||||
drivers that want to disable local interrupts (interrupts on the
|
|
||||||
current CPU), can use the following five macros:
|
|
||||||
|
|
||||||
local_irq_disable(), local_irq_enable(), local_save_flags(flags),
|
|
||||||
local_irq_save(flags), local_irq_restore(flags)
|
|
||||||
|
|
||||||
but beware, their meaning and semantics are much simpler, far from
|
|
||||||
that of the old cli(), sti(), save_flags(flags) and restore_flags(flags)
|
|
||||||
SMP meaning:
|
|
||||||
|
|
||||||
local_irq_disable() => turn local IRQs off
|
|
||||||
|
|
||||||
local_irq_enable() => turn local IRQs on
|
|
||||||
|
|
||||||
local_save_flags(flags) => save the current IRQ state into flags. The
|
|
||||||
state can be on or off. (on some
|
|
||||||
architectures there's even more bits in it.)
|
|
||||||
|
|
||||||
local_irq_save(flags) => save the current IRQ state into flags and
|
|
||||||
disable interrupts.
|
|
||||||
|
|
||||||
local_irq_restore(flags) => restore the IRQ state from flags.
|
|
||||||
|
|
||||||
(local_irq_save can save both irqs on and irqs off state, and
|
|
||||||
local_irq_restore can restore into both irqs on and irqs off state.)
|
|
||||||
|
|
||||||
another related change is that synchronize_irq() now takes a parameter:
|
|
||||||
synchronize_irq(irq). This change too has the purpose of making SMP
|
|
||||||
synchronization more lightweight - this way you can wait for your own
|
|
||||||
interrupt handler to finish, no need to wait for other IRQ sources.
|
|
||||||
|
|
||||||
|
|
||||||
why were these changes done? The main reason was the architectural burden
|
|
||||||
of maintaining the cli()/sti() interface - it became a real problem. The
|
|
||||||
new interrupt system is much more streamlined, easier to understand, debug,
|
|
||||||
and it's also a bit faster - the same happened to it that will happen to
|
|
||||||
cli()/sti() using drivers once they convert to spinlocks :-)
|
|
||||||
|
|
11
Documentation/connector/Makefile
Normal file
11
Documentation/connector/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
ifneq ($(CONFIG_CONNECTOR),)
|
||||||
|
obj-m += cn_test.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
hostprogs-y := ucon
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
|
HOSTCFLAGS_ucon.o += -I$(objtree)/usr/include
|
|
@ -242,8 +242,7 @@ rmdir() if there are no tasks.
|
||||||
1. Add support for accounting huge pages (as a separate controller)
|
1. Add support for accounting huge pages (as a separate controller)
|
||||||
2. Make per-cgroup scanner reclaim not-shared pages first
|
2. Make per-cgroup scanner reclaim not-shared pages first
|
||||||
3. Teach controller to account for shared-pages
|
3. Teach controller to account for shared-pages
|
||||||
4. Start reclamation when the limit is lowered
|
4. Start reclamation in the background when the limit is
|
||||||
5. Start reclamation in the background when the limit is
|
|
||||||
not yet hit but the usage is getting closer
|
not yet hit but the usage is getting closer
|
||||||
|
|
||||||
Summary
|
Summary
|
||||||
|
|
|
@ -122,7 +122,7 @@ around '10000' or more.
|
||||||
show_sampling_rate_(min|max): the minimum and maximum sampling rates
|
show_sampling_rate_(min|max): the minimum and maximum sampling rates
|
||||||
available that you may set 'sampling_rate' to.
|
available that you may set 'sampling_rate' to.
|
||||||
|
|
||||||
up_threshold: defines what the average CPU usaged between the samplings
|
up_threshold: defines what the average CPU usage between the samplings
|
||||||
of 'sampling_rate' needs to be for the kernel to make a decision on
|
of 'sampling_rate' needs to be for the kernel to make a decision on
|
||||||
whether it should increase the frequency. For example when it is set
|
whether it should increase the frequency. For example when it is set
|
||||||
to its default value of '80' it means that between the checking
|
to its default value of '80' it means that between the checking
|
||||||
|
|
|
@ -59,15 +59,10 @@ apicid values in those tables for disabled apics. In the event BIOS doesn't
|
||||||
mark such hot-pluggable cpus as disabled entries, one could use this
|
mark such hot-pluggable cpus as disabled entries, one could use this
|
||||||
parameter "additional_cpus=x" to represent those cpus in the cpu_possible_map.
|
parameter "additional_cpus=x" to represent those cpus in the cpu_possible_map.
|
||||||
|
|
||||||
s390 uses the number of cpus it detects at IPL time to also the number of bits
|
|
||||||
in cpu_possible_map. If it is desired to add additional cpus at a later time
|
|
||||||
the number should be specified using this option or the possible_cpus option.
|
|
||||||
|
|
||||||
possible_cpus=n [s390 only] use this to set hotpluggable cpus.
|
possible_cpus=n [s390 only] use this to set hotpluggable cpus.
|
||||||
This option sets possible_cpus bits in
|
This option sets possible_cpus bits in
|
||||||
cpu_possible_map. Thus keeping the numbers of bits set
|
cpu_possible_map. Thus keeping the numbers of bits set
|
||||||
constant even if the machine gets rebooted.
|
constant even if the machine gets rebooted.
|
||||||
This option overrides additional_cpus.
|
|
||||||
|
|
||||||
CPU maps and such
|
CPU maps and such
|
||||||
-----------------
|
-----------------
|
||||||
|
|
|
@ -635,14 +635,16 @@ prior 'mems' setting, will not be moved.
|
||||||
|
|
||||||
There is an exception to the above. If hotplug functionality 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,
|
to remove all the CPUs that are currently assigned to a cpuset,
|
||||||
then the kernel will automatically update the cpus_allowed of all
|
then all the tasks in that cpuset will be moved to the nearest ancestor
|
||||||
tasks attached to CPUs in that cpuset to allow all CPUs. When memory
|
with non-empty cpus. But the moving of some (or all) tasks might fail if
|
||||||
hotplug functionality for removing Memory Nodes is available, a
|
cpuset is bound with another cgroup subsystem which has some restrictions
|
||||||
similar exception is expected to apply there as well. In general,
|
on task attaching. In this failing case, those tasks will stay
|
||||||
the kernel prefers to violate cpuset placement, over starving a task
|
in the original cpuset, and the kernel will automatically update
|
||||||
that has had all its allowed CPUs or Memory Nodes taken offline. User
|
their cpus_allowed to allow all online CPUs. When memory hotplug
|
||||||
code should reconfigure cpusets to only refer to online CPUs and Memory
|
functionality for removing Memory Nodes is available, a similar exception
|
||||||
Nodes when using hotplug to add or remove such resources.
|
is expected to apply there as well. In general, the kernel prefers to
|
||||||
|
violate cpuset placement, over starving a task that has had all
|
||||||
|
its allowed CPUs or Memory Nodes taken offline.
|
||||||
|
|
||||||
There is a second exception to the above. GFP_ATOMIC requests are
|
There is a second exception to the above. GFP_ATOMIC requests are
|
||||||
kernel internal allocations that must be satisfied, immediately.
|
kernel internal allocations that must be satisfied, immediately.
|
||||||
|
|
|
@ -2560,9 +2560,6 @@ Your cooperation is appreciated.
|
||||||
96 = /dev/usb/hiddev0 1st USB HID device
|
96 = /dev/usb/hiddev0 1st USB HID device
|
||||||
...
|
...
|
||||||
111 = /dev/usb/hiddev15 16th USB HID device
|
111 = /dev/usb/hiddev15 16th USB HID device
|
||||||
112 = /dev/usb/auer0 1st auerswald ISDN device
|
|
||||||
...
|
|
||||||
127 = /dev/usb/auer15 16th auerswald ISDN device
|
|
||||||
128 = /dev/usb/brlvgr0 First Braille Voyager device
|
128 = /dev/usb/brlvgr0 First Braille Voyager device
|
||||||
...
|
...
|
||||||
131 = /dev/usb/brlvgr3 Fourth Braille Voyager device
|
131 = /dev/usb/brlvgr3 Fourth Braille Voyager device
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*.css
|
*.css
|
||||||
*.dvi
|
*.dvi
|
||||||
*.eps
|
*.eps
|
||||||
|
*.fw.gen.S
|
||||||
|
*.fw
|
||||||
*.gif
|
*.gif
|
||||||
*.grep
|
*.grep
|
||||||
*.grp
|
*.grp
|
||||||
|
|
|
@ -222,74 +222,9 @@ both csrow2 and csrow3 are populated, this indicates a dual ranked
|
||||||
set of DIMMs for channels 0 and 1.
|
set of DIMMs for channels 0 and 1.
|
||||||
|
|
||||||
|
|
||||||
Within each of the 'mc','mcX' and 'csrowX' directories are several
|
Within each of the 'mcX' and 'csrowX' directories are several
|
||||||
EDAC control and attribute files.
|
EDAC control and attribute files.
|
||||||
|
|
||||||
|
|
||||||
============================================================================
|
|
||||||
DIRECTORY 'mc'
|
|
||||||
|
|
||||||
In directory 'mc' are EDAC system overall control and attribute files:
|
|
||||||
|
|
||||||
|
|
||||||
Panic on UE control file:
|
|
||||||
|
|
||||||
'edac_mc_panic_on_ue'
|
|
||||||
|
|
||||||
An uncorrectable error will cause a machine panic. This is usually
|
|
||||||
desirable. It is a bad idea to continue when an uncorrectable error
|
|
||||||
occurs - it is indeterminate what was uncorrected and the operating
|
|
||||||
system context might be so mangled that continuing will lead to further
|
|
||||||
corruption. If the kernel has MCE configured, then EDAC will never
|
|
||||||
notice the UE.
|
|
||||||
|
|
||||||
LOAD TIME: module/kernel parameter: panic_on_ue=[0|1]
|
|
||||||
|
|
||||||
RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_panic_on_ue
|
|
||||||
|
|
||||||
|
|
||||||
Log UE control file:
|
|
||||||
|
|
||||||
'edac_mc_log_ue'
|
|
||||||
|
|
||||||
Generate kernel messages describing uncorrectable errors. These errors
|
|
||||||
are reported through the system message log system. UE statistics
|
|
||||||
will be accumulated even when UE logging is disabled.
|
|
||||||
|
|
||||||
LOAD TIME: module/kernel parameter: log_ue=[0|1]
|
|
||||||
|
|
||||||
RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ue
|
|
||||||
|
|
||||||
|
|
||||||
Log CE control file:
|
|
||||||
|
|
||||||
'edac_mc_log_ce'
|
|
||||||
|
|
||||||
Generate kernel messages describing correctable errors. These
|
|
||||||
errors are reported through the system message log system.
|
|
||||||
CE statistics will be accumulated even when CE logging is disabled.
|
|
||||||
|
|
||||||
LOAD TIME: module/kernel parameter: log_ce=[0|1]
|
|
||||||
|
|
||||||
RUN TIME: echo "1" >/sys/devices/system/edac/mc/edac_mc_log_ce
|
|
||||||
|
|
||||||
|
|
||||||
Polling period control file:
|
|
||||||
|
|
||||||
'edac_mc_poll_msec'
|
|
||||||
|
|
||||||
The time period, in milliseconds, for polling for error information.
|
|
||||||
Too small a value wastes resources. Too large a value might delay
|
|
||||||
necessary handling of errors and might loose valuable information for
|
|
||||||
locating the error. 1000 milliseconds (once each second) is the current
|
|
||||||
default. Systems which require all the bandwidth they can get, may
|
|
||||||
increase this.
|
|
||||||
|
|
||||||
LOAD TIME: module/kernel parameter: poll_msec=[0|1]
|
|
||||||
|
|
||||||
RUN TIME: echo "1000" >/sys/devices/system/edac/mc/edac_mc_poll_msec
|
|
||||||
|
|
||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
'mcX' DIRECTORIES
|
'mcX' DIRECTORIES
|
||||||
|
|
||||||
|
@ -392,7 +327,7 @@ Sdram memory scrubbing rate:
|
||||||
'sdram_scrub_rate'
|
'sdram_scrub_rate'
|
||||||
|
|
||||||
Read/Write attribute file that controls memory scrubbing. The scrubbing
|
Read/Write attribute file that controls memory scrubbing. The scrubbing
|
||||||
rate is set by writing a minimum bandwith in bytes/sec to the attribute
|
rate is set by writing a minimum bandwidth in bytes/sec to the attribute
|
||||||
file. The rate will be translated to an internal value that gives at
|
file. The rate will be translated to an internal value that gives at
|
||||||
least the specified rate.
|
least the specified rate.
|
||||||
|
|
||||||
|
@ -537,7 +472,6 @@ Channel 1 DIMM Label control file:
|
||||||
motherboard specific and determination of this information
|
motherboard specific and determination of this information
|
||||||
must occur in userland at this time.
|
must occur in userland at this time.
|
||||||
|
|
||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
SYSTEM LOGGING
|
SYSTEM LOGGING
|
||||||
|
|
||||||
|
@ -570,7 +504,6 @@ error type, a notice of "no info" and then an optional,
|
||||||
driver-specific error message.
|
driver-specific error message.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
============================================================================
|
============================================================================
|
||||||
PCI Bus Parity Detection
|
PCI Bus Parity Detection
|
||||||
|
|
||||||
|
@ -604,6 +537,74 @@ Enable/Disable PCI Parity checking control file:
|
||||||
echo "0" >/sys/devices/system/edac/pci/check_pci_parity
|
echo "0" >/sys/devices/system/edac/pci/check_pci_parity
|
||||||
|
|
||||||
|
|
||||||
|
Parity Count:
|
||||||
|
|
||||||
|
'pci_parity_count'
|
||||||
|
|
||||||
|
This attribute file will display the number of parity errors that
|
||||||
|
have been detected.
|
||||||
|
|
||||||
|
|
||||||
|
============================================================================
|
||||||
|
MODULE PARAMETERS
|
||||||
|
|
||||||
|
Panic on UE control file:
|
||||||
|
|
||||||
|
'edac_mc_panic_on_ue'
|
||||||
|
|
||||||
|
An uncorrectable error will cause a machine panic. This is usually
|
||||||
|
desirable. It is a bad idea to continue when an uncorrectable error
|
||||||
|
occurs - it is indeterminate what was uncorrected and the operating
|
||||||
|
system context might be so mangled that continuing will lead to further
|
||||||
|
corruption. If the kernel has MCE configured, then EDAC will never
|
||||||
|
notice the UE.
|
||||||
|
|
||||||
|
LOAD TIME: module/kernel parameter: edac_mc_panic_on_ue=[0|1]
|
||||||
|
|
||||||
|
RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_panic_on_ue
|
||||||
|
|
||||||
|
|
||||||
|
Log UE control file:
|
||||||
|
|
||||||
|
'edac_mc_log_ue'
|
||||||
|
|
||||||
|
Generate kernel messages describing uncorrectable errors. These errors
|
||||||
|
are reported through the system message log system. UE statistics
|
||||||
|
will be accumulated even when UE logging is disabled.
|
||||||
|
|
||||||
|
LOAD TIME: module/kernel parameter: edac_mc_log_ue=[0|1]
|
||||||
|
|
||||||
|
RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ue
|
||||||
|
|
||||||
|
|
||||||
|
Log CE control file:
|
||||||
|
|
||||||
|
'edac_mc_log_ce'
|
||||||
|
|
||||||
|
Generate kernel messages describing correctable errors. These
|
||||||
|
errors are reported through the system message log system.
|
||||||
|
CE statistics will be accumulated even when CE logging is disabled.
|
||||||
|
|
||||||
|
LOAD TIME: module/kernel parameter: edac_mc_log_ce=[0|1]
|
||||||
|
|
||||||
|
RUN TIME: echo "1" > /sys/module/edac_core/parameters/edac_mc_log_ce
|
||||||
|
|
||||||
|
|
||||||
|
Polling period control file:
|
||||||
|
|
||||||
|
'edac_mc_poll_msec'
|
||||||
|
|
||||||
|
The time period, in milliseconds, for polling for error information.
|
||||||
|
Too small a value wastes resources. Too large a value might delay
|
||||||
|
necessary handling of errors and might loose valuable information for
|
||||||
|
locating the error. 1000 milliseconds (once each second) is the current
|
||||||
|
default. Systems which require all the bandwidth they can get, may
|
||||||
|
increase this.
|
||||||
|
|
||||||
|
LOAD TIME: module/kernel parameter: edac_mc_poll_msec=[0|1]
|
||||||
|
|
||||||
|
RUN TIME: echo "1000" > /sys/module/edac_core/parameters/edac_mc_poll_msec
|
||||||
|
|
||||||
|
|
||||||
Panic on PCI PARITY Error:
|
Panic on PCI PARITY Error:
|
||||||
|
|
||||||
|
@ -614,21 +615,13 @@ Panic on PCI PARITY Error:
|
||||||
error has been detected.
|
error has been detected.
|
||||||
|
|
||||||
|
|
||||||
module/kernel parameter: panic_on_pci_parity=[0|1]
|
module/kernel parameter: edac_panic_on_pci_pe=[0|1]
|
||||||
|
|
||||||
Enable:
|
Enable:
|
||||||
echo "1" >/sys/devices/system/edac/pci/panic_on_pci_parity
|
echo "1" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
|
||||||
|
|
||||||
Disable:
|
Disable:
|
||||||
echo "0" >/sys/devices/system/edac/pci/panic_on_pci_parity
|
echo "0" > /sys/module/edac_core/parameters/edac_panic_on_pci_pe
|
||||||
|
|
||||||
|
|
||||||
Parity Count:
|
|
||||||
|
|
||||||
'pci_parity_count'
|
|
||||||
|
|
||||||
This attribute file will display the number of parity errors that
|
|
||||||
have been detected.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,15 +19,6 @@ Who: Pavel Machek <pavel@suse.cz>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: old NCR53C9x driver
|
|
||||||
When: October 2007
|
|
||||||
Why: Replaced by the much better esp_scsi driver. Actual low-level
|
|
||||||
driver can be ported over almost trivially.
|
|
||||||
Who: David Miller <davem@davemloft.net>
|
|
||||||
Christoph Hellwig <hch@lst.de>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
||||||
When: December 2008
|
When: December 2008
|
||||||
Files: include/linux/video_decoder.h include/linux/videodev.h
|
Files: include/linux/video_decoder.h include/linux/videodev.h
|
||||||
|
@ -47,6 +38,30 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: old tuner-3036 i2c driver
|
||||||
|
When: 2.6.28
|
||||||
|
Why: This driver is for VERY old i2c-over-parallel port teletext receiver
|
||||||
|
boxes. Rather then spending effort on converting this driver to V4L2,
|
||||||
|
and since it is extremely unlikely that anyone still uses one of these
|
||||||
|
devices, it was decided to drop it.
|
||||||
|
Who: Hans Verkuil <hverkuil@xs4all.nl>
|
||||||
|
Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: V4L2 dpc7146 driver
|
||||||
|
When: 2.6.28
|
||||||
|
Why: Old driver for the dpc7146 demonstration board that is no longer
|
||||||
|
relevant. The last time this was tested on actual hardware was
|
||||||
|
probably around 2002. Since this is a driver for a demonstration
|
||||||
|
board the decision was made to remove it rather than spending a
|
||||||
|
lot of effort continually updating this driver to stay in sync
|
||||||
|
with the latest internal V4L2 or I2C API.
|
||||||
|
Who: Hans Verkuil <hverkuil@xs4all.nl>
|
||||||
|
Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
|
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
|
||||||
When: November 2005
|
When: November 2005
|
||||||
Files: drivers/pcmcia/: pcmcia_ioctl.c
|
Files: drivers/pcmcia/: pcmcia_ioctl.c
|
||||||
|
@ -138,24 +153,6 @@ Who: Kay Sievers <kay.sievers@suse.de>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: find_task_by_pid
|
|
||||||
When: 2.6.26
|
|
||||||
Why: With pid namespaces, calling this funciton will return the
|
|
||||||
wrong task when called from inside a namespace.
|
|
||||||
|
|
||||||
The best way to save a task pid and find a task by this
|
|
||||||
pid later, is to find this task's struct pid pointer (or get
|
|
||||||
it directly from the task) and call pid_task() later.
|
|
||||||
|
|
||||||
If someone really needs to get a task by its pid_t, then
|
|
||||||
he most likely needs the find_task_by_vpid() to get the
|
|
||||||
task from the same namespace as the current task is in, but
|
|
||||||
this may be not so in general.
|
|
||||||
|
|
||||||
Who: Pavel Emelyanov <xemul@openvz.org>
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: ACPI procfs interface
|
What: ACPI procfs interface
|
||||||
When: July 2008
|
When: July 2008
|
||||||
Why: ACPI sysfs conversion should be finished by January 2008.
|
Why: ACPI sysfs conversion should be finished by January 2008.
|
||||||
|
@ -199,19 +196,6 @@ Who: Tejun Heo <htejun@gmail.com>
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: The arch/ppc and include/asm-ppc directories
|
|
||||||
When: Jun 2008
|
|
||||||
Why: The arch/powerpc tree is the merged architecture for ppc32 and ppc64
|
|
||||||
platforms. Currently there are efforts underway to port the remaining
|
|
||||||
arch/ppc platforms to the merged tree. New submissions to the arch/ppc
|
|
||||||
tree have been frozen with the 2.6.22 kernel release and that tree will
|
|
||||||
remain in bug-fix only mode until its scheduled removal. Platforms
|
|
||||||
that are not ported by June 2008 will be removed due to the lack of an
|
|
||||||
interested maintainer.
|
|
||||||
Who: linuxppc-dev@ozlabs.org
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
What: i386/x86_64 bzImage symlinks
|
What: i386/x86_64 bzImage symlinks
|
||||||
When: April 2010
|
When: April 2010
|
||||||
|
|
||||||
|
@ -338,3 +322,11 @@ Why: Accounting can now be enabled/disabled without kernel recompilation.
|
||||||
controlled by a kernel/module/sysfs/sysctl parameter.
|
controlled by a kernel/module/sysfs/sysctl parameter.
|
||||||
Who: Krzysztof Piotr Oledzki <ole@ans.pl>
|
Who: Krzysztof Piotr Oledzki <ole@ans.pl>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
What: ide-scsi (BLK_DEV_IDESCSI)
|
||||||
|
When: 2.6.29
|
||||||
|
Why: The 2.6 kernel supports direct writing to ide CD drives, which
|
||||||
|
eliminates the need for ide-scsi. The new method is more
|
||||||
|
efficient in every way.
|
||||||
|
Who: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
|
||||||
|
|
|
@ -144,8 +144,8 @@ prototypes:
|
||||||
void (*kill_sb) (struct super_block *);
|
void (*kill_sb) (struct super_block *);
|
||||||
locking rules:
|
locking rules:
|
||||||
may block BKL
|
may block BKL
|
||||||
get_sb yes yes
|
get_sb yes no
|
||||||
kill_sb yes yes
|
kill_sb yes no
|
||||||
|
|
||||||
->get_sb() returns error or 0 with locked superblock attached to the vfsmount
|
->get_sb() returns error or 0 with locked superblock attached to the vfsmount
|
||||||
(exclusive on ->s_umount).
|
(exclusive on ->s_umount).
|
||||||
|
@ -409,12 +409,12 @@ ioctl: yes (see below)
|
||||||
unlocked_ioctl: no (see below)
|
unlocked_ioctl: no (see below)
|
||||||
compat_ioctl: no
|
compat_ioctl: no
|
||||||
mmap: no
|
mmap: no
|
||||||
open: maybe (see below)
|
open: no
|
||||||
flush: no
|
flush: no
|
||||||
release: no
|
release: no
|
||||||
fsync: no (see below)
|
fsync: no (see below)
|
||||||
aio_fsync: no
|
aio_fsync: no
|
||||||
fasync: yes (see below)
|
fasync: no
|
||||||
lock: yes
|
lock: yes
|
||||||
readv: no
|
readv: no
|
||||||
writev: no
|
writev: no
|
||||||
|
@ -431,13 +431,6 @@ For many filesystems, it is probably safe to acquire the inode
|
||||||
semaphore. Note some filesystems (i.e. remote ones) provide no
|
semaphore. Note some filesystems (i.e. remote ones) provide no
|
||||||
protection for i_size so you will need to use the BKL.
|
protection for i_size so you will need to use the BKL.
|
||||||
|
|
||||||
->open() locking is in-transit: big lock partially moved into the methods.
|
|
||||||
The only exception is ->open() in the instances of file_operations that never
|
|
||||||
end up in ->i_fop/->proc_fops, i.e. ones that belong to character devices
|
|
||||||
(chrdev_open() takes lock before replacing ->f_op and calling the secondary
|
|
||||||
method. As soon as we fix the handling of module reference counters all
|
|
||||||
instances of ->open() will be called without the BKL.
|
|
||||||
|
|
||||||
Note: ext2_release() was *the* source of contention on fs-intensive
|
Note: ext2_release() was *the* source of contention on fs-intensive
|
||||||
loads and dropping BKL on ->release() helps to get rid of that (we still
|
loads and dropping BKL on ->release() helps to get rid of that (we still
|
||||||
grab BKL for cases when we close a file that had been opened r/w, but that
|
grab BKL for cases when we close a file that had been opened r/w, but that
|
||||||
|
|
3
Documentation/filesystems/configfs/Makefile
Normal file
3
Documentation/filesystems/configfs/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
ifneq ($(CONFIG_CONFIGFS_FS),)
|
||||||
|
obj-m += configfs_example_explicit.o configfs_example_macros.o
|
||||||
|
endif
|
|
@ -311,9 +311,20 @@ the subsystem must be ready for it.
|
||||||
[An Example]
|
[An Example]
|
||||||
|
|
||||||
The best example of these basic concepts is the simple_children
|
The best example of these basic concepts is the simple_children
|
||||||
subsystem/group and the simple_child item in configfs_example.c It
|
subsystem/group and the simple_child item in configfs_example_explicit.c
|
||||||
shows a trivial object displaying and storing an attribute, and a simple
|
and configfs_example_macros.c. It shows a trivial object displaying and
|
||||||
group creating and destroying these children.
|
storing an attribute, and a simple group creating and destroying these
|
||||||
|
children.
|
||||||
|
|
||||||
|
The only difference between configfs_example_explicit.c and
|
||||||
|
configfs_example_macros.c is how the attributes of the childless item
|
||||||
|
are defined. The childless item has extended attributes, each with
|
||||||
|
their own show()/store() operation. This follows a convention commonly
|
||||||
|
used in sysfs. configfs_example_explicit.c creates these attributes
|
||||||
|
by explicitly defining the structures involved. Conversely
|
||||||
|
configfs_example_macros.c uses some convenience macros from configfs.h
|
||||||
|
to define the attributes. These macros are similar to their sysfs
|
||||||
|
counterparts.
|
||||||
|
|
||||||
[Hierarchy Navigation and the Subsystem Mutex]
|
[Hierarchy Navigation and the Subsystem Mutex]
|
||||||
|
|
||||||
|
|
|
@ -1,485 +0,0 @@
|
||||||
/*
|
|
||||||
* vim: noexpandtab ts=8 sts=0 sw=8:
|
|
||||||
*
|
|
||||||
* configfs_example.c - This file is a demonstration module containing
|
|
||||||
* a number of configfs subsystems.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public
|
|
||||||
* License along with this program; if not, write to the
|
|
||||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
* Boston, MA 021110-1307, USA.
|
|
||||||
*
|
|
||||||
* Based on sysfs:
|
|
||||||
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
|
|
||||||
*
|
|
||||||
* configfs Copyright (C) 2005 Oracle. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
|
|
||||||
#include <linux/configfs.h>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 01-childless
|
|
||||||
*
|
|
||||||
* This first example is a childless subsystem. It cannot create
|
|
||||||
* any config_items. It just has attributes.
|
|
||||||
*
|
|
||||||
* Note that we are enclosing the configfs_subsystem inside a container.
|
|
||||||
* This is not necessary if a subsystem has no attributes directly
|
|
||||||
* on the subsystem. See the next example, 02-simple-children, for
|
|
||||||
* such a subsystem.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct childless {
|
|
||||||
struct configfs_subsystem subsys;
|
|
||||||
int showme;
|
|
||||||
int storeme;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct childless_attribute {
|
|
||||||
struct configfs_attribute attr;
|
|
||||||
ssize_t (*show)(struct childless *, char *);
|
|
||||||
ssize_t (*store)(struct childless *, const char *, size_t);
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline struct childless *to_childless(struct config_item *item)
|
|
||||||
{
|
|
||||||
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t childless_showme_read(struct childless *childless,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
ssize_t pos;
|
|
||||||
|
|
||||||
pos = sprintf(page, "%d\n", childless->showme);
|
|
||||||
childless->showme++;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t childless_storeme_read(struct childless *childless,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
return sprintf(page, "%d\n", childless->storeme);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t childless_storeme_write(struct childless *childless,
|
|
||||||
const char *page,
|
|
||||||
size_t count)
|
|
||||||
{
|
|
||||||
unsigned long tmp;
|
|
||||||
char *p = (char *) page;
|
|
||||||
|
|
||||||
tmp = simple_strtoul(p, &p, 10);
|
|
||||||
if (!p || (*p && (*p != '\n')))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (tmp > INT_MAX)
|
|
||||||
return -ERANGE;
|
|
||||||
|
|
||||||
childless->storeme = tmp;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t childless_description_read(struct childless *childless,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
return sprintf(page,
|
|
||||||
"[01-childless]\n"
|
|
||||||
"\n"
|
|
||||||
"The childless subsystem is the simplest possible subsystem in\n"
|
|
||||||
"configfs. It does not support the creation of child config_items.\n"
|
|
||||||
"It only has a few attributes. In fact, it isn't much different\n"
|
|
||||||
"than a directory in /proc.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct childless_attribute childless_attr_showme = {
|
|
||||||
.attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
|
|
||||||
.show = childless_showme_read,
|
|
||||||
};
|
|
||||||
static struct childless_attribute childless_attr_storeme = {
|
|
||||||
.attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
|
|
||||||
.show = childless_storeme_read,
|
|
||||||
.store = childless_storeme_write,
|
|
||||||
};
|
|
||||||
static struct childless_attribute childless_attr_description = {
|
|
||||||
.attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
|
|
||||||
.show = childless_description_read,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct configfs_attribute *childless_attrs[] = {
|
|
||||||
&childless_attr_showme.attr,
|
|
||||||
&childless_attr_storeme.attr,
|
|
||||||
&childless_attr_description.attr,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t childless_attr_show(struct config_item *item,
|
|
||||||
struct configfs_attribute *attr,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
struct childless *childless = to_childless(item);
|
|
||||||
struct childless_attribute *childless_attr =
|
|
||||||
container_of(attr, struct childless_attribute, attr);
|
|
||||||
ssize_t ret = 0;
|
|
||||||
|
|
||||||
if (childless_attr->show)
|
|
||||||
ret = childless_attr->show(childless, page);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t childless_attr_store(struct config_item *item,
|
|
||||||
struct configfs_attribute *attr,
|
|
||||||
const char *page, size_t count)
|
|
||||||
{
|
|
||||||
struct childless *childless = to_childless(item);
|
|
||||||
struct childless_attribute *childless_attr =
|
|
||||||
container_of(attr, struct childless_attribute, attr);
|
|
||||||
ssize_t ret = -EINVAL;
|
|
||||||
|
|
||||||
if (childless_attr->store)
|
|
||||||
ret = childless_attr->store(childless, page, count);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_item_operations childless_item_ops = {
|
|
||||||
.show_attribute = childless_attr_show,
|
|
||||||
.store_attribute = childless_attr_store,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct config_item_type childless_type = {
|
|
||||||
.ct_item_ops = &childless_item_ops,
|
|
||||||
.ct_attrs = childless_attrs,
|
|
||||||
.ct_owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct childless childless_subsys = {
|
|
||||||
.subsys = {
|
|
||||||
.su_group = {
|
|
||||||
.cg_item = {
|
|
||||||
.ci_namebuf = "01-childless",
|
|
||||||
.ci_type = &childless_type,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 02-simple-children
|
|
||||||
*
|
|
||||||
* This example merely has a simple one-attribute child. Note that
|
|
||||||
* there is no extra attribute structure, as the child's attribute is
|
|
||||||
* known from the get-go. Also, there is no container for the
|
|
||||||
* subsystem, as it has no attributes of its own.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct simple_child {
|
|
||||||
struct config_item item;
|
|
||||||
int storeme;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline struct simple_child *to_simple_child(struct config_item *item)
|
|
||||||
{
|
|
||||||
return item ? container_of(item, struct simple_child, item) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_attribute simple_child_attr_storeme = {
|
|
||||||
.ca_owner = THIS_MODULE,
|
|
||||||
.ca_name = "storeme",
|
|
||||||
.ca_mode = S_IRUGO | S_IWUSR,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct configfs_attribute *simple_child_attrs[] = {
|
|
||||||
&simple_child_attr_storeme,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t simple_child_attr_show(struct config_item *item,
|
|
||||||
struct configfs_attribute *attr,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
ssize_t count;
|
|
||||||
struct simple_child *simple_child = to_simple_child(item);
|
|
||||||
|
|
||||||
count = sprintf(page, "%d\n", simple_child->storeme);
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t simple_child_attr_store(struct config_item *item,
|
|
||||||
struct configfs_attribute *attr,
|
|
||||||
const char *page, size_t count)
|
|
||||||
{
|
|
||||||
struct simple_child *simple_child = to_simple_child(item);
|
|
||||||
unsigned long tmp;
|
|
||||||
char *p = (char *) page;
|
|
||||||
|
|
||||||
tmp = simple_strtoul(p, &p, 10);
|
|
||||||
if (!p || (*p && (*p != '\n')))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (tmp > INT_MAX)
|
|
||||||
return -ERANGE;
|
|
||||||
|
|
||||||
simple_child->storeme = tmp;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void simple_child_release(struct config_item *item)
|
|
||||||
{
|
|
||||||
kfree(to_simple_child(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_item_operations simple_child_item_ops = {
|
|
||||||
.release = simple_child_release,
|
|
||||||
.show_attribute = simple_child_attr_show,
|
|
||||||
.store_attribute = simple_child_attr_store,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct config_item_type simple_child_type = {
|
|
||||||
.ct_item_ops = &simple_child_item_ops,
|
|
||||||
.ct_attrs = simple_child_attrs,
|
|
||||||
.ct_owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct simple_children {
|
|
||||||
struct config_group group;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline struct simple_children *to_simple_children(struct config_item *item)
|
|
||||||
{
|
|
||||||
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
|
|
||||||
{
|
|
||||||
struct simple_child *simple_child;
|
|
||||||
|
|
||||||
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
|
|
||||||
if (!simple_child)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
|
|
||||||
config_item_init_type_name(&simple_child->item, name,
|
|
||||||
&simple_child_type);
|
|
||||||
|
|
||||||
simple_child->storeme = 0;
|
|
||||||
|
|
||||||
return &simple_child->item;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_attribute simple_children_attr_description = {
|
|
||||||
.ca_owner = THIS_MODULE,
|
|
||||||
.ca_name = "description",
|
|
||||||
.ca_mode = S_IRUGO,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct configfs_attribute *simple_children_attrs[] = {
|
|
||||||
&simple_children_attr_description,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t simple_children_attr_show(struct config_item *item,
|
|
||||||
struct configfs_attribute *attr,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
return sprintf(page,
|
|
||||||
"[02-simple-children]\n"
|
|
||||||
"\n"
|
|
||||||
"This subsystem allows the creation of child config_items. These\n"
|
|
||||||
"items have only one attribute that is readable and writeable.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void simple_children_release(struct config_item *item)
|
|
||||||
{
|
|
||||||
kfree(to_simple_children(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_item_operations simple_children_item_ops = {
|
|
||||||
.release = simple_children_release,
|
|
||||||
.show_attribute = simple_children_attr_show,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that, since no extra work is required on ->drop_item(),
|
|
||||||
* no ->drop_item() is provided.
|
|
||||||
*/
|
|
||||||
static struct configfs_group_operations simple_children_group_ops = {
|
|
||||||
.make_item = simple_children_make_item,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct config_item_type simple_children_type = {
|
|
||||||
.ct_item_ops = &simple_children_item_ops,
|
|
||||||
.ct_group_ops = &simple_children_group_ops,
|
|
||||||
.ct_attrs = simple_children_attrs,
|
|
||||||
.ct_owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct configfs_subsystem simple_children_subsys = {
|
|
||||||
.su_group = {
|
|
||||||
.cg_item = {
|
|
||||||
.ci_namebuf = "02-simple-children",
|
|
||||||
.ci_type = &simple_children_type,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 03-group-children
|
|
||||||
*
|
|
||||||
* This example reuses the simple_children group from above. However,
|
|
||||||
* the simple_children group is not the subsystem itself, it is a
|
|
||||||
* child of the subsystem. Creation of a group in the subsystem creates
|
|
||||||
* a new simple_children group. That group can then have simple_child
|
|
||||||
* children of its own.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
|
|
||||||
{
|
|
||||||
struct simple_children *simple_children;
|
|
||||||
|
|
||||||
simple_children = kzalloc(sizeof(struct simple_children),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!simple_children)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
|
|
||||||
config_group_init_type_name(&simple_children->group, name,
|
|
||||||
&simple_children_type);
|
|
||||||
|
|
||||||
return &simple_children->group;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_attribute group_children_attr_description = {
|
|
||||||
.ca_owner = THIS_MODULE,
|
|
||||||
.ca_name = "description",
|
|
||||||
.ca_mode = S_IRUGO,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct configfs_attribute *group_children_attrs[] = {
|
|
||||||
&group_children_attr_description,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t group_children_attr_show(struct config_item *item,
|
|
||||||
struct configfs_attribute *attr,
|
|
||||||
char *page)
|
|
||||||
{
|
|
||||||
return sprintf(page,
|
|
||||||
"[03-group-children]\n"
|
|
||||||
"\n"
|
|
||||||
"This subsystem allows the creation of child config_groups. These\n"
|
|
||||||
"groups are like the subsystem simple-children.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct configfs_item_operations group_children_item_ops = {
|
|
||||||
.show_attribute = group_children_attr_show,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that, since no extra work is required on ->drop_item(),
|
|
||||||
* no ->drop_item() is provided.
|
|
||||||
*/
|
|
||||||
static struct configfs_group_operations group_children_group_ops = {
|
|
||||||
.make_group = group_children_make_group,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct config_item_type group_children_type = {
|
|
||||||
.ct_item_ops = &group_children_item_ops,
|
|
||||||
.ct_group_ops = &group_children_group_ops,
|
|
||||||
.ct_attrs = group_children_attrs,
|
|
||||||
.ct_owner = THIS_MODULE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct configfs_subsystem group_children_subsys = {
|
|
||||||
.su_group = {
|
|
||||||
.cg_item = {
|
|
||||||
.ci_namebuf = "03-group-children",
|
|
||||||
.ci_type = &group_children_type,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We're now done with our subsystem definitions.
|
|
||||||
* For convenience in this module, here's a list of them all. It
|
|
||||||
* allows the init function to easily register them. Most modules
|
|
||||||
* will only have one subsystem, and will only call register_subsystem
|
|
||||||
* on it directly.
|
|
||||||
*/
|
|
||||||
static struct configfs_subsystem *example_subsys[] = {
|
|
||||||
&childless_subsys.subsys,
|
|
||||||
&simple_children_subsys,
|
|
||||||
&group_children_subsys,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init configfs_example_init(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
int i;
|
|
||||||
struct configfs_subsystem *subsys;
|
|
||||||
|
|
||||||
for (i = 0; example_subsys[i]; i++) {
|
|
||||||
subsys = example_subsys[i];
|
|
||||||
|
|
||||||
config_group_init(&subsys->su_group);
|
|
||||||
mutex_init(&subsys->su_mutex);
|
|
||||||
ret = configfs_register_subsystem(subsys);
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "Error %d while registering subsystem %s\n",
|
|
||||||
ret,
|
|
||||||
subsys->su_group.cg_item.ci_namebuf);
|
|
||||||
goto out_unregister;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_unregister:
|
|
||||||
for (; i >= 0; i--) {
|
|
||||||
configfs_unregister_subsystem(example_subsys[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit configfs_example_exit(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; example_subsys[i]; i++) {
|
|
||||||
configfs_unregister_subsystem(example_subsys[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(configfs_example_init);
|
|
||||||
module_exit(configfs_example_exit);
|
|
||||||
MODULE_LICENSE("GPL");
|
|
485
Documentation/filesystems/configfs/configfs_example_explicit.c
Normal file
485
Documentation/filesystems/configfs/configfs_example_explicit.c
Normal file
|
@ -0,0 +1,485 @@
|
||||||
|
/*
|
||||||
|
* vim: noexpandtab ts=8 sts=0 sw=8:
|
||||||
|
*
|
||||||
|
* configfs_example_explicit.c - This file is a demonstration module
|
||||||
|
* containing a number of configfs subsystems. It explicitly defines
|
||||||
|
* each structure without using the helper macros defined in
|
||||||
|
* configfs.h.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public
|
||||||
|
* License along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 021110-1307, USA.
|
||||||
|
*
|
||||||
|
* Based on sysfs:
|
||||||
|
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
|
||||||
|
*
|
||||||
|
* configfs Copyright (C) 2005 Oracle. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <linux/configfs.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 01-childless
|
||||||
|
*
|
||||||
|
* This first example is a childless subsystem. It cannot create
|
||||||
|
* any config_items. It just has attributes.
|
||||||
|
*
|
||||||
|
* Note that we are enclosing the configfs_subsystem inside a container.
|
||||||
|
* This is not necessary if a subsystem has no attributes directly
|
||||||
|
* on the subsystem. See the next example, 02-simple-children, for
|
||||||
|
* such a subsystem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct childless {
|
||||||
|
struct configfs_subsystem subsys;
|
||||||
|
int showme;
|
||||||
|
int storeme;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct childless_attribute {
|
||||||
|
struct configfs_attribute attr;
|
||||||
|
ssize_t (*show)(struct childless *, char *);
|
||||||
|
ssize_t (*store)(struct childless *, const char *, size_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct childless *to_childless(struct config_item *item)
|
||||||
|
{
|
||||||
|
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_showme_read(struct childless *childless,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
ssize_t pos;
|
||||||
|
|
||||||
|
pos = sprintf(page, "%d\n", childless->showme);
|
||||||
|
childless->showme++;
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_storeme_read(struct childless *childless,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page, "%d\n", childless->storeme);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_storeme_write(struct childless *childless,
|
||||||
|
const char *page,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
unsigned long tmp;
|
||||||
|
char *p = (char *) page;
|
||||||
|
|
||||||
|
tmp = simple_strtoul(p, &p, 10);
|
||||||
|
if (!p || (*p && (*p != '\n')))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (tmp > INT_MAX)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
childless->storeme = tmp;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_description_read(struct childless *childless,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page,
|
||||||
|
"[01-childless]\n"
|
||||||
|
"\n"
|
||||||
|
"The childless subsystem is the simplest possible subsystem in\n"
|
||||||
|
"configfs. It does not support the creation of child config_items.\n"
|
||||||
|
"It only has a few attributes. In fact, it isn't much different\n"
|
||||||
|
"than a directory in /proc.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct childless_attribute childless_attr_showme = {
|
||||||
|
.attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
|
||||||
|
.show = childless_showme_read,
|
||||||
|
};
|
||||||
|
static struct childless_attribute childless_attr_storeme = {
|
||||||
|
.attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
|
||||||
|
.show = childless_storeme_read,
|
||||||
|
.store = childless_storeme_write,
|
||||||
|
};
|
||||||
|
static struct childless_attribute childless_attr_description = {
|
||||||
|
.attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
|
||||||
|
.show = childless_description_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *childless_attrs[] = {
|
||||||
|
&childless_attr_showme.attr,
|
||||||
|
&childless_attr_storeme.attr,
|
||||||
|
&childless_attr_description.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t childless_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
struct childless *childless = to_childless(item);
|
||||||
|
struct childless_attribute *childless_attr =
|
||||||
|
container_of(attr, struct childless_attribute, attr);
|
||||||
|
ssize_t ret = 0;
|
||||||
|
|
||||||
|
if (childless_attr->show)
|
||||||
|
ret = childless_attr->show(childless, page);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_attr_store(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
const char *page, size_t count)
|
||||||
|
{
|
||||||
|
struct childless *childless = to_childless(item);
|
||||||
|
struct childless_attribute *childless_attr =
|
||||||
|
container_of(attr, struct childless_attribute, attr);
|
||||||
|
ssize_t ret = -EINVAL;
|
||||||
|
|
||||||
|
if (childless_attr->store)
|
||||||
|
ret = childless_attr->store(childless, page, count);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations childless_item_ops = {
|
||||||
|
.show_attribute = childless_attr_show,
|
||||||
|
.store_attribute = childless_attr_store,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type childless_type = {
|
||||||
|
.ct_item_ops = &childless_item_ops,
|
||||||
|
.ct_attrs = childless_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct childless childless_subsys = {
|
||||||
|
.subsys = {
|
||||||
|
.su_group = {
|
||||||
|
.cg_item = {
|
||||||
|
.ci_namebuf = "01-childless",
|
||||||
|
.ci_type = &childless_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 02-simple-children
|
||||||
|
*
|
||||||
|
* This example merely has a simple one-attribute child. Note that
|
||||||
|
* there is no extra attribute structure, as the child's attribute is
|
||||||
|
* known from the get-go. Also, there is no container for the
|
||||||
|
* subsystem, as it has no attributes of its own.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct simple_child {
|
||||||
|
struct config_item item;
|
||||||
|
int storeme;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct simple_child *to_simple_child(struct config_item *item)
|
||||||
|
{
|
||||||
|
return item ? container_of(item, struct simple_child, item) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_attribute simple_child_attr_storeme = {
|
||||||
|
.ca_owner = THIS_MODULE,
|
||||||
|
.ca_name = "storeme",
|
||||||
|
.ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *simple_child_attrs[] = {
|
||||||
|
&simple_child_attr_storeme,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t simple_child_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
ssize_t count;
|
||||||
|
struct simple_child *simple_child = to_simple_child(item);
|
||||||
|
|
||||||
|
count = sprintf(page, "%d\n", simple_child->storeme);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t simple_child_attr_store(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
const char *page, size_t count)
|
||||||
|
{
|
||||||
|
struct simple_child *simple_child = to_simple_child(item);
|
||||||
|
unsigned long tmp;
|
||||||
|
char *p = (char *) page;
|
||||||
|
|
||||||
|
tmp = simple_strtoul(p, &p, 10);
|
||||||
|
if (!p || (*p && (*p != '\n')))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (tmp > INT_MAX)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
simple_child->storeme = tmp;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_child_release(struct config_item *item)
|
||||||
|
{
|
||||||
|
kfree(to_simple_child(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations simple_child_item_ops = {
|
||||||
|
.release = simple_child_release,
|
||||||
|
.show_attribute = simple_child_attr_show,
|
||||||
|
.store_attribute = simple_child_attr_store,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type simple_child_type = {
|
||||||
|
.ct_item_ops = &simple_child_item_ops,
|
||||||
|
.ct_attrs = simple_child_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct simple_children {
|
||||||
|
struct config_group group;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct simple_children *to_simple_children(struct config_item *item)
|
||||||
|
{
|
||||||
|
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
|
||||||
|
{
|
||||||
|
struct simple_child *simple_child;
|
||||||
|
|
||||||
|
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
|
||||||
|
if (!simple_child)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
config_item_init_type_name(&simple_child->item, name,
|
||||||
|
&simple_child_type);
|
||||||
|
|
||||||
|
simple_child->storeme = 0;
|
||||||
|
|
||||||
|
return &simple_child->item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_attribute simple_children_attr_description = {
|
||||||
|
.ca_owner = THIS_MODULE,
|
||||||
|
.ca_name = "description",
|
||||||
|
.ca_mode = S_IRUGO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *simple_children_attrs[] = {
|
||||||
|
&simple_children_attr_description,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t simple_children_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page,
|
||||||
|
"[02-simple-children]\n"
|
||||||
|
"\n"
|
||||||
|
"This subsystem allows the creation of child config_items. These\n"
|
||||||
|
"items have only one attribute that is readable and writeable.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_children_release(struct config_item *item)
|
||||||
|
{
|
||||||
|
kfree(to_simple_children(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations simple_children_item_ops = {
|
||||||
|
.release = simple_children_release,
|
||||||
|
.show_attribute = simple_children_attr_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that, since no extra work is required on ->drop_item(),
|
||||||
|
* no ->drop_item() is provided.
|
||||||
|
*/
|
||||||
|
static struct configfs_group_operations simple_children_group_ops = {
|
||||||
|
.make_item = simple_children_make_item,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type simple_children_type = {
|
||||||
|
.ct_item_ops = &simple_children_item_ops,
|
||||||
|
.ct_group_ops = &simple_children_group_ops,
|
||||||
|
.ct_attrs = simple_children_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_subsystem simple_children_subsys = {
|
||||||
|
.su_group = {
|
||||||
|
.cg_item = {
|
||||||
|
.ci_namebuf = "02-simple-children",
|
||||||
|
.ci_type = &simple_children_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 03-group-children
|
||||||
|
*
|
||||||
|
* This example reuses the simple_children group from above. However,
|
||||||
|
* the simple_children group is not the subsystem itself, it is a
|
||||||
|
* child of the subsystem. Creation of a group in the subsystem creates
|
||||||
|
* a new simple_children group. That group can then have simple_child
|
||||||
|
* children of its own.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
|
||||||
|
{
|
||||||
|
struct simple_children *simple_children;
|
||||||
|
|
||||||
|
simple_children = kzalloc(sizeof(struct simple_children),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!simple_children)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
config_group_init_type_name(&simple_children->group, name,
|
||||||
|
&simple_children_type);
|
||||||
|
|
||||||
|
return &simple_children->group;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_attribute group_children_attr_description = {
|
||||||
|
.ca_owner = THIS_MODULE,
|
||||||
|
.ca_name = "description",
|
||||||
|
.ca_mode = S_IRUGO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *group_children_attrs[] = {
|
||||||
|
&group_children_attr_description,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t group_children_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page,
|
||||||
|
"[03-group-children]\n"
|
||||||
|
"\n"
|
||||||
|
"This subsystem allows the creation of child config_groups. These\n"
|
||||||
|
"groups are like the subsystem simple-children.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations group_children_item_ops = {
|
||||||
|
.show_attribute = group_children_attr_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that, since no extra work is required on ->drop_item(),
|
||||||
|
* no ->drop_item() is provided.
|
||||||
|
*/
|
||||||
|
static struct configfs_group_operations group_children_group_ops = {
|
||||||
|
.make_group = group_children_make_group,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type group_children_type = {
|
||||||
|
.ct_item_ops = &group_children_item_ops,
|
||||||
|
.ct_group_ops = &group_children_group_ops,
|
||||||
|
.ct_attrs = group_children_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_subsystem group_children_subsys = {
|
||||||
|
.su_group = {
|
||||||
|
.cg_item = {
|
||||||
|
.ci_namebuf = "03-group-children",
|
||||||
|
.ci_type = &group_children_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're now done with our subsystem definitions.
|
||||||
|
* For convenience in this module, here's a list of them all. It
|
||||||
|
* allows the init function to easily register them. Most modules
|
||||||
|
* will only have one subsystem, and will only call register_subsystem
|
||||||
|
* on it directly.
|
||||||
|
*/
|
||||||
|
static struct configfs_subsystem *example_subsys[] = {
|
||||||
|
&childless_subsys.subsys,
|
||||||
|
&simple_children_subsys,
|
||||||
|
&group_children_subsys,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init configfs_example_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
struct configfs_subsystem *subsys;
|
||||||
|
|
||||||
|
for (i = 0; example_subsys[i]; i++) {
|
||||||
|
subsys = example_subsys[i];
|
||||||
|
|
||||||
|
config_group_init(&subsys->su_group);
|
||||||
|
mutex_init(&subsys->su_mutex);
|
||||||
|
ret = configfs_register_subsystem(subsys);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_ERR "Error %d while registering subsystem %s\n",
|
||||||
|
ret,
|
||||||
|
subsys->su_group.cg_item.ci_namebuf);
|
||||||
|
goto out_unregister;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_unregister:
|
||||||
|
for (; i >= 0; i--) {
|
||||||
|
configfs_unregister_subsystem(example_subsys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit configfs_example_exit(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; example_subsys[i]; i++) {
|
||||||
|
configfs_unregister_subsystem(example_subsys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(configfs_example_init);
|
||||||
|
module_exit(configfs_example_exit);
|
||||||
|
MODULE_LICENSE("GPL");
|
448
Documentation/filesystems/configfs/configfs_example_macros.c
Normal file
448
Documentation/filesystems/configfs/configfs_example_macros.c
Normal file
|
@ -0,0 +1,448 @@
|
||||||
|
/*
|
||||||
|
* vim: noexpandtab ts=8 sts=0 sw=8:
|
||||||
|
*
|
||||||
|
* configfs_example_macros.c - This file is a demonstration module
|
||||||
|
* containing a number of configfs subsystems. It uses the helper
|
||||||
|
* macros defined by configfs.h
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public
|
||||||
|
* License along with this program; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 021110-1307, USA.
|
||||||
|
*
|
||||||
|
* Based on sysfs:
|
||||||
|
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
|
||||||
|
*
|
||||||
|
* configfs Copyright (C) 2005 Oracle. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <linux/configfs.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 01-childless
|
||||||
|
*
|
||||||
|
* This first example is a childless subsystem. It cannot create
|
||||||
|
* any config_items. It just has attributes.
|
||||||
|
*
|
||||||
|
* Note that we are enclosing the configfs_subsystem inside a container.
|
||||||
|
* This is not necessary if a subsystem has no attributes directly
|
||||||
|
* on the subsystem. See the next example, 02-simple-children, for
|
||||||
|
* such a subsystem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct childless {
|
||||||
|
struct configfs_subsystem subsys;
|
||||||
|
int showme;
|
||||||
|
int storeme;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct childless *to_childless(struct config_item *item)
|
||||||
|
{
|
||||||
|
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIGFS_ATTR_STRUCT(childless);
|
||||||
|
#define CHILDLESS_ATTR(_name, _mode, _show, _store) \
|
||||||
|
struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
|
||||||
|
#define CHILDLESS_ATTR_RO(_name, _show) \
|
||||||
|
struct childless_attribute childless_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show);
|
||||||
|
|
||||||
|
static ssize_t childless_showme_read(struct childless *childless,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
ssize_t pos;
|
||||||
|
|
||||||
|
pos = sprintf(page, "%d\n", childless->showme);
|
||||||
|
childless->showme++;
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_storeme_read(struct childless *childless,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page, "%d\n", childless->storeme);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_storeme_write(struct childless *childless,
|
||||||
|
const char *page,
|
||||||
|
size_t count)
|
||||||
|
{
|
||||||
|
unsigned long tmp;
|
||||||
|
char *p = (char *) page;
|
||||||
|
|
||||||
|
tmp = simple_strtoul(p, &p, 10);
|
||||||
|
if (!p || (*p && (*p != '\n')))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (tmp > INT_MAX)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
childless->storeme = tmp;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t childless_description_read(struct childless *childless,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page,
|
||||||
|
"[01-childless]\n"
|
||||||
|
"\n"
|
||||||
|
"The childless subsystem is the simplest possible subsystem in\n"
|
||||||
|
"configfs. It does not support the creation of child config_items.\n"
|
||||||
|
"It only has a few attributes. In fact, it isn't much different\n"
|
||||||
|
"than a directory in /proc.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
CHILDLESS_ATTR_RO(showme, childless_showme_read);
|
||||||
|
CHILDLESS_ATTR(storeme, S_IRUGO | S_IWUSR, childless_storeme_read,
|
||||||
|
childless_storeme_write);
|
||||||
|
CHILDLESS_ATTR_RO(description, childless_description_read);
|
||||||
|
|
||||||
|
static struct configfs_attribute *childless_attrs[] = {
|
||||||
|
&childless_attr_showme.attr,
|
||||||
|
&childless_attr_storeme.attr,
|
||||||
|
&childless_attr_description.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
CONFIGFS_ATTR_OPS(childless);
|
||||||
|
static struct configfs_item_operations childless_item_ops = {
|
||||||
|
.show_attribute = childless_attr_show,
|
||||||
|
.store_attribute = childless_attr_store,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type childless_type = {
|
||||||
|
.ct_item_ops = &childless_item_ops,
|
||||||
|
.ct_attrs = childless_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct childless childless_subsys = {
|
||||||
|
.subsys = {
|
||||||
|
.su_group = {
|
||||||
|
.cg_item = {
|
||||||
|
.ci_namebuf = "01-childless",
|
||||||
|
.ci_type = &childless_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 02-simple-children
|
||||||
|
*
|
||||||
|
* This example merely has a simple one-attribute child. Note that
|
||||||
|
* there is no extra attribute structure, as the child's attribute is
|
||||||
|
* known from the get-go. Also, there is no container for the
|
||||||
|
* subsystem, as it has no attributes of its own.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct simple_child {
|
||||||
|
struct config_item item;
|
||||||
|
int storeme;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct simple_child *to_simple_child(struct config_item *item)
|
||||||
|
{
|
||||||
|
return item ? container_of(item, struct simple_child, item) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_attribute simple_child_attr_storeme = {
|
||||||
|
.ca_owner = THIS_MODULE,
|
||||||
|
.ca_name = "storeme",
|
||||||
|
.ca_mode = S_IRUGO | S_IWUSR,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *simple_child_attrs[] = {
|
||||||
|
&simple_child_attr_storeme,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t simple_child_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
ssize_t count;
|
||||||
|
struct simple_child *simple_child = to_simple_child(item);
|
||||||
|
|
||||||
|
count = sprintf(page, "%d\n", simple_child->storeme);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t simple_child_attr_store(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
const char *page, size_t count)
|
||||||
|
{
|
||||||
|
struct simple_child *simple_child = to_simple_child(item);
|
||||||
|
unsigned long tmp;
|
||||||
|
char *p = (char *) page;
|
||||||
|
|
||||||
|
tmp = simple_strtoul(p, &p, 10);
|
||||||
|
if (!p || (*p && (*p != '\n')))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (tmp > INT_MAX)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
simple_child->storeme = tmp;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_child_release(struct config_item *item)
|
||||||
|
{
|
||||||
|
kfree(to_simple_child(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations simple_child_item_ops = {
|
||||||
|
.release = simple_child_release,
|
||||||
|
.show_attribute = simple_child_attr_show,
|
||||||
|
.store_attribute = simple_child_attr_store,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type simple_child_type = {
|
||||||
|
.ct_item_ops = &simple_child_item_ops,
|
||||||
|
.ct_attrs = simple_child_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct simple_children {
|
||||||
|
struct config_group group;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct simple_children *to_simple_children(struct config_item *item)
|
||||||
|
{
|
||||||
|
return item ? container_of(to_config_group(item), struct simple_children, group) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
|
||||||
|
{
|
||||||
|
struct simple_child *simple_child;
|
||||||
|
|
||||||
|
simple_child = kzalloc(sizeof(struct simple_child), GFP_KERNEL);
|
||||||
|
if (!simple_child)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
config_item_init_type_name(&simple_child->item, name,
|
||||||
|
&simple_child_type);
|
||||||
|
|
||||||
|
simple_child->storeme = 0;
|
||||||
|
|
||||||
|
return &simple_child->item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_attribute simple_children_attr_description = {
|
||||||
|
.ca_owner = THIS_MODULE,
|
||||||
|
.ca_name = "description",
|
||||||
|
.ca_mode = S_IRUGO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *simple_children_attrs[] = {
|
||||||
|
&simple_children_attr_description,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t simple_children_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page,
|
||||||
|
"[02-simple-children]\n"
|
||||||
|
"\n"
|
||||||
|
"This subsystem allows the creation of child config_items. These\n"
|
||||||
|
"items have only one attribute that is readable and writeable.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simple_children_release(struct config_item *item)
|
||||||
|
{
|
||||||
|
kfree(to_simple_children(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations simple_children_item_ops = {
|
||||||
|
.release = simple_children_release,
|
||||||
|
.show_attribute = simple_children_attr_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that, since no extra work is required on ->drop_item(),
|
||||||
|
* no ->drop_item() is provided.
|
||||||
|
*/
|
||||||
|
static struct configfs_group_operations simple_children_group_ops = {
|
||||||
|
.make_item = simple_children_make_item,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type simple_children_type = {
|
||||||
|
.ct_item_ops = &simple_children_item_ops,
|
||||||
|
.ct_group_ops = &simple_children_group_ops,
|
||||||
|
.ct_attrs = simple_children_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_subsystem simple_children_subsys = {
|
||||||
|
.su_group = {
|
||||||
|
.cg_item = {
|
||||||
|
.ci_namebuf = "02-simple-children",
|
||||||
|
.ci_type = &simple_children_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 03-group-children
|
||||||
|
*
|
||||||
|
* This example reuses the simple_children group from above. However,
|
||||||
|
* the simple_children group is not the subsystem itself, it is a
|
||||||
|
* child of the subsystem. Creation of a group in the subsystem creates
|
||||||
|
* a new simple_children group. That group can then have simple_child
|
||||||
|
* children of its own.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
|
||||||
|
{
|
||||||
|
struct simple_children *simple_children;
|
||||||
|
|
||||||
|
simple_children = kzalloc(sizeof(struct simple_children),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!simple_children)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
config_group_init_type_name(&simple_children->group, name,
|
||||||
|
&simple_children_type);
|
||||||
|
|
||||||
|
return &simple_children->group;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_attribute group_children_attr_description = {
|
||||||
|
.ca_owner = THIS_MODULE,
|
||||||
|
.ca_name = "description",
|
||||||
|
.ca_mode = S_IRUGO,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_attribute *group_children_attrs[] = {
|
||||||
|
&group_children_attr_description,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t group_children_attr_show(struct config_item *item,
|
||||||
|
struct configfs_attribute *attr,
|
||||||
|
char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page,
|
||||||
|
"[03-group-children]\n"
|
||||||
|
"\n"
|
||||||
|
"This subsystem allows the creation of child config_groups. These\n"
|
||||||
|
"groups are like the subsystem simple-children.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct configfs_item_operations group_children_item_ops = {
|
||||||
|
.show_attribute = group_children_attr_show,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that, since no extra work is required on ->drop_item(),
|
||||||
|
* no ->drop_item() is provided.
|
||||||
|
*/
|
||||||
|
static struct configfs_group_operations group_children_group_ops = {
|
||||||
|
.make_group = group_children_make_group,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct config_item_type group_children_type = {
|
||||||
|
.ct_item_ops = &group_children_item_ops,
|
||||||
|
.ct_group_ops = &group_children_group_ops,
|
||||||
|
.ct_attrs = group_children_attrs,
|
||||||
|
.ct_owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct configfs_subsystem group_children_subsys = {
|
||||||
|
.su_group = {
|
||||||
|
.cg_item = {
|
||||||
|
.ci_namebuf = "03-group-children",
|
||||||
|
.ci_type = &group_children_type,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're now done with our subsystem definitions.
|
||||||
|
* For convenience in this module, here's a list of them all. It
|
||||||
|
* allows the init function to easily register them. Most modules
|
||||||
|
* will only have one subsystem, and will only call register_subsystem
|
||||||
|
* on it directly.
|
||||||
|
*/
|
||||||
|
static struct configfs_subsystem *example_subsys[] = {
|
||||||
|
&childless_subsys.subsys,
|
||||||
|
&simple_children_subsys,
|
||||||
|
&group_children_subsys,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init configfs_example_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
struct configfs_subsystem *subsys;
|
||||||
|
|
||||||
|
for (i = 0; example_subsys[i]; i++) {
|
||||||
|
subsys = example_subsys[i];
|
||||||
|
|
||||||
|
config_group_init(&subsys->su_group);
|
||||||
|
mutex_init(&subsys->su_mutex);
|
||||||
|
ret = configfs_register_subsystem(subsys);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_ERR "Error %d while registering subsystem %s\n",
|
||||||
|
ret,
|
||||||
|
subsys->su_group.cg_item.ci_namebuf);
|
||||||
|
goto out_unregister;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_unregister:
|
||||||
|
for (; i >= 0; i--) {
|
||||||
|
configfs_unregister_subsystem(example_subsys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit configfs_example_exit(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; example_subsys[i]; i++) {
|
||||||
|
configfs_unregister_subsystem(example_subsys[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(configfs_example_init);
|
||||||
|
module_exit(configfs_example_exit);
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -26,6 +26,12 @@ Mailing list: linux-ext4@vger.kernel.org
|
||||||
|
|
||||||
git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
|
git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git
|
||||||
|
|
||||||
|
- Note that it is highly important to install the mke2fs.conf file
|
||||||
|
that comes with the e2fsprogs 1.41.x sources in /etc/mke2fs.conf. If
|
||||||
|
you have edited the /etc/mke2fs.conf file installed on your system,
|
||||||
|
you will need to merge your changes with the version from e2fsprogs
|
||||||
|
1.41.x.
|
||||||
|
|
||||||
- Create a new filesystem using the ext4dev filesystem type:
|
- Create a new filesystem using the ext4dev filesystem type:
|
||||||
|
|
||||||
# mke2fs -t ext4dev /dev/hda1
|
# mke2fs -t ext4dev /dev/hda1
|
||||||
|
|
|
@ -40,7 +40,7 @@ Web site
|
||||||
========
|
========
|
||||||
|
|
||||||
There is plenty of additional information on the linux-ntfs web site
|
There is plenty of additional information on the linux-ntfs web site
|
||||||
at http://linux-ntfs.sourceforge.net/
|
at http://www.linux-ntfs.org/
|
||||||
|
|
||||||
The web site has a lot of additional information, such as a comprehensive
|
The web site has a lot of additional information, such as a comprehensive
|
||||||
FAQ, documentation on the NTFS on-disk format, information on the Linux-NTFS
|
FAQ, documentation on the NTFS on-disk format, information on the Linux-NTFS
|
||||||
|
@ -272,7 +272,7 @@ And you would know that /dev/hda2 has a size of 37768814 - 4209030 + 1 =
|
||||||
For Win2k and later dynamic disks, you can for example use the ldminfo utility
|
For Win2k and later dynamic disks, you can for example use the ldminfo utility
|
||||||
which is part of the Linux LDM tools (the latest version at the time of
|
which is part of the Linux LDM tools (the latest version at the time of
|
||||||
writing is linux-ldm-0.0.8.tar.bz2). You can download it from:
|
writing is linux-ldm-0.0.8.tar.bz2). You can download it from:
|
||||||
http://linux-ntfs.sourceforge.net/downloads.html
|
http://www.linux-ntfs.org/
|
||||||
Simply extract the downloaded archive (tar xvjf linux-ldm-0.0.8.tar.bz2), go
|
Simply extract the downloaded archive (tar xvjf linux-ldm-0.0.8.tar.bz2), go
|
||||||
into it (cd linux-ldm-0.0.8) and change to the test directory (cd test). You
|
into it (cd linux-ldm-0.0.8) and change to the test directory (cd test). You
|
||||||
will find the precompiled (i386) ldminfo utility there. NOTE: You will not be
|
will find the precompiled (i386) ldminfo utility there. NOTE: You will not be
|
||||||
|
|
106
Documentation/filesystems/omfs.txt
Normal file
106
Documentation/filesystems/omfs.txt
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
Optimized MPEG Filesystem (OMFS)
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
OMFS is a filesystem created by SonicBlue for use in the ReplayTV DVR
|
||||||
|
and Rio Karma MP3 player. The filesystem is extent-based, utilizing
|
||||||
|
block sizes from 2k to 8k, with hash-based directories. This
|
||||||
|
filesystem driver may be used to read and write disks from these
|
||||||
|
devices.
|
||||||
|
|
||||||
|
Note, it is not recommended that this FS be used in place of a general
|
||||||
|
filesystem for your own streaming media device. Native Linux filesystems
|
||||||
|
will likely perform better.
|
||||||
|
|
||||||
|
More information is available at:
|
||||||
|
|
||||||
|
http://linux-karma.sf.net/
|
||||||
|
|
||||||
|
Various utilities, including mkomfs and omfsck, are included with
|
||||||
|
omfsprogs, available at:
|
||||||
|
|
||||||
|
http://bobcopeland.com/karma/
|
||||||
|
|
||||||
|
Instructions are included in its README.
|
||||||
|
|
||||||
|
Options
|
||||||
|
=======
|
||||||
|
|
||||||
|
OMFS supports the following mount-time options:
|
||||||
|
|
||||||
|
uid=n - make all files owned by specified user
|
||||||
|
gid=n - make all files owned by specified group
|
||||||
|
umask=xxx - set permission umask to xxx
|
||||||
|
fmask=xxx - set umask to xxx for files
|
||||||
|
dmask=xxx - set umask to xxx for directories
|
||||||
|
|
||||||
|
Disk format
|
||||||
|
===========
|
||||||
|
|
||||||
|
OMFS discriminates between "sysblocks" and normal data blocks. The sysblock
|
||||||
|
group consists of super block information, file metadata, directory structures,
|
||||||
|
and extents. Each sysblock has a header containing CRCs of the entire
|
||||||
|
sysblock, and may be mirrored in successive blocks on the disk. A sysblock may
|
||||||
|
have a smaller size than a data block, but since they are both addressed by the
|
||||||
|
same 64-bit block number, any remaining space in the smaller sysblock is
|
||||||
|
unused.
|
||||||
|
|
||||||
|
Sysblock header information:
|
||||||
|
|
||||||
|
struct omfs_header {
|
||||||
|
__be64 h_self; /* FS block where this is located */
|
||||||
|
__be32 h_body_size; /* size of useful data after header */
|
||||||
|
__be16 h_crc; /* crc-ccitt of body_size bytes */
|
||||||
|
char h_fill1[2];
|
||||||
|
u8 h_version; /* version, always 1 */
|
||||||
|
char h_type; /* OMFS_INODE_X */
|
||||||
|
u8 h_magic; /* OMFS_IMAGIC */
|
||||||
|
u8 h_check_xor; /* XOR of header bytes before this */
|
||||||
|
__be32 h_fill2;
|
||||||
|
};
|
||||||
|
|
||||||
|
Files and directories are both represented by omfs_inode:
|
||||||
|
|
||||||
|
struct omfs_inode {
|
||||||
|
struct omfs_header i_head; /* header */
|
||||||
|
__be64 i_parent; /* parent containing this inode */
|
||||||
|
__be64 i_sibling; /* next inode in hash bucket */
|
||||||
|
__be64 i_ctime; /* ctime, in milliseconds */
|
||||||
|
char i_fill1[35];
|
||||||
|
char i_type; /* OMFS_[DIR,FILE] */
|
||||||
|
__be32 i_fill2;
|
||||||
|
char i_fill3[64];
|
||||||
|
char i_name[OMFS_NAMELEN]; /* filename */
|
||||||
|
__be64 i_size; /* size of file, in bytes */
|
||||||
|
};
|
||||||
|
|
||||||
|
Directories in OMFS are implemented as a large hash table. Filenames are
|
||||||
|
hashed then prepended into the bucket list beginning at OMFS_DIR_START.
|
||||||
|
Lookup requires hashing the filename, then seeking across i_sibling pointers
|
||||||
|
until a match is found on i_name. Empty buckets are represented by block
|
||||||
|
pointers with all-1s (~0).
|
||||||
|
|
||||||
|
A file is an omfs_inode structure followed by an extent table beginning at
|
||||||
|
OMFS_EXTENT_START:
|
||||||
|
|
||||||
|
struct omfs_extent_entry {
|
||||||
|
__be64 e_cluster; /* start location of a set of blocks */
|
||||||
|
__be64 e_blocks; /* number of blocks after e_cluster */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct omfs_extent {
|
||||||
|
__be64 e_next; /* next extent table location */
|
||||||
|
__be32 e_extent_count; /* total # extents in this table */
|
||||||
|
__be32 e_fill;
|
||||||
|
struct omfs_extent_entry e_entry; /* start of extent entries */
|
||||||
|
};
|
||||||
|
|
||||||
|
Each extent holds the block offset followed by number of blocks allocated to
|
||||||
|
the extent. The final extent in each table is a terminator with e_cluster
|
||||||
|
being ~0 and e_blocks being ones'-complement of the total number of blocks
|
||||||
|
in the table.
|
||||||
|
|
||||||
|
If this table overflows, a continuation inode is written and pointed to by
|
||||||
|
e_next. These have a header but lack the rest of the inode structure.
|
||||||
|
|
|
@ -931,7 +931,7 @@ group_prealloc max_to_scan mb_groups mb_history min_to_scan order2_req
|
||||||
stats stream_req
|
stats stream_req
|
||||||
|
|
||||||
mb_groups:
|
mb_groups:
|
||||||
This file gives the details of mutiblock allocator buddy cache of free blocks
|
This file gives the details of multiblock allocator buddy cache of free blocks
|
||||||
|
|
||||||
mb_history:
|
mb_history:
|
||||||
Multiblock allocation history.
|
Multiblock allocation history.
|
||||||
|
@ -1339,6 +1339,25 @@ Enables/Disables the protection of the per-process proc entries "maps" and
|
||||||
"smaps". When enabled, the contents of these files are visible only to
|
"smaps". When enabled, the contents of these files are visible only to
|
||||||
readers that are allowed to ptrace() the given process.
|
readers that are allowed to ptrace() the given process.
|
||||||
|
|
||||||
|
msgmni
|
||||||
|
------
|
||||||
|
|
||||||
|
Maximum number of message queue ids on the system.
|
||||||
|
This value scales to the amount of lowmem. It is automatically recomputed
|
||||||
|
upon memory add/remove or ipc namespace creation/removal.
|
||||||
|
When a value is written into this file, msgmni's value becomes fixed, i.e. it
|
||||||
|
is not recomputed anymore when one of the above events occurs.
|
||||||
|
Use auto_msgmni to change this behavior.
|
||||||
|
|
||||||
|
auto_msgmni
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Enables/Disables automatic recomputing of msgmni upon memory add/remove or
|
||||||
|
upon ipc namespace creation/removal (see the msgmni description above).
|
||||||
|
Echoing "1" into this file enables msgmni automatic recomputing.
|
||||||
|
Echoing "0" turns it off.
|
||||||
|
auto_msgmni default value is 1.
|
||||||
|
|
||||||
|
|
||||||
2.4 /proc/sys/vm - The virtual memory subsystem
|
2.4 /proc/sys/vm - The virtual memory subsystem
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
@ -1474,7 +1493,7 @@ used because pages_free(1355) is smaller than watermark + protection[2]
|
||||||
normal page requirement. If requirement is DMA zone(index=0), protection[0]
|
normal page requirement. If requirement is DMA zone(index=0), protection[0]
|
||||||
(=0) is used.
|
(=0) is used.
|
||||||
|
|
||||||
zone[i]'s protection[j] is calculated by following exprssion.
|
zone[i]'s protection[j] is calculated by following expression.
|
||||||
|
|
||||||
(i < j):
|
(i < j):
|
||||||
zone[i]->protection[j]
|
zone[i]->protection[j]
|
||||||
|
@ -2394,6 +2413,8 @@ The following 4 memory types are supported:
|
||||||
- (bit 1) anonymous shared memory
|
- (bit 1) anonymous shared memory
|
||||||
- (bit 2) file-backed private memory
|
- (bit 2) file-backed private memory
|
||||||
- (bit 3) file-backed shared memory
|
- (bit 3) file-backed shared memory
|
||||||
|
- (bit 4) ELF header pages in file-backed private memory areas (it is
|
||||||
|
effective only if the bit 2 is cleared)
|
||||||
|
|
||||||
Note that MMIO pages such as frame buffer are never dumped and vDSO pages
|
Note that MMIO pages such as frame buffer are never dumped and vDSO pages
|
||||||
are always dumped regardless of the bitmask status.
|
are always dumped regardless of the bitmask status.
|
||||||
|
|
|
@ -3,14 +3,14 @@ Quota subsystem
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Quota subsystem allows system administrator to set limits on used space and
|
Quota subsystem allows system administrator to set limits on used space and
|
||||||
number of used inodes (inode is a filesystem structure which is associated
|
number of used inodes (inode is a filesystem structure which is associated with
|
||||||
with each file or directory) for users and/or groups. For both used space and
|
each file or directory) for users and/or groups. For both used space and number
|
||||||
number of used inodes there are actually two limits. The first one is called
|
of used inodes there are actually two limits. The first one is called softlimit
|
||||||
softlimit and the second one hardlimit. An user can never exceed a hardlimit
|
and the second one hardlimit. An user can never exceed a hardlimit for any
|
||||||
for any resource. User is allowed to exceed softlimit but only for limited
|
resource (unless he has CAP_SYS_RESOURCE capability). User is allowed to exceed
|
||||||
period of time. This period is called "grace period" or "grace time". When
|
softlimit but only for limited period of time. This period is called "grace
|
||||||
grace time is over, user is not able to allocate more space/inodes until he
|
period" or "grace time". When grace time is over, user is not able to allocate
|
||||||
frees enough of them to get below softlimit.
|
more space/inodes until he frees enough of them to get below softlimit.
|
||||||
|
|
||||||
Quota limits (and amount of grace time) are set independently for each
|
Quota limits (and amount of grace time) are set independently for each
|
||||||
filesystem.
|
filesystem.
|
||||||
|
@ -53,6 +53,12 @@ in parentheses):
|
||||||
QUOTA_NL_BSOFTLONGWARN - space (block) softlimit is exceeded
|
QUOTA_NL_BSOFTLONGWARN - space (block) softlimit is exceeded
|
||||||
longer than given grace period.
|
longer than given grace period.
|
||||||
QUOTA_NL_BSOFTWARN - space (block) softlimit
|
QUOTA_NL_BSOFTWARN - space (block) softlimit
|
||||||
|
- four warnings are also defined for the event when user stops
|
||||||
|
exceeding some limit:
|
||||||
|
QUOTA_NL_IHARDBELOW - inode hardlimit
|
||||||
|
QUOTA_NL_ISOFTBELOW - inode softlimit
|
||||||
|
QUOTA_NL_BHARDBELOW - space (block) hardlimit
|
||||||
|
QUOTA_NL_BSOFTBELOW - space (block) softlimit
|
||||||
QUOTA_NL_A_DEV_MAJOR (u32)
|
QUOTA_NL_A_DEV_MAJOR (u32)
|
||||||
- major number of a device with the affected filesystem
|
- major number of a device with the affected filesystem
|
||||||
QUOTA_NL_A_DEV_MINOR (u32)
|
QUOTA_NL_A_DEV_MINOR (u32)
|
||||||
|
|
|
@ -294,6 +294,16 @@ user-defined data with a channel, and is immediately available
|
||||||
(including in create_buf_file()) via chan->private_data or
|
(including in create_buf_file()) via chan->private_data or
|
||||||
buf->chan->private_data.
|
buf->chan->private_data.
|
||||||
|
|
||||||
|
Buffer-only channels
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
These channels have no files associated and can be created with
|
||||||
|
relay_open(NULL, NULL, ...). Such channels are useful in scenarios such
|
||||||
|
as when doing early tracing in the kernel, before the VFS is up. In these
|
||||||
|
cases, one may open a buffer-only channel and then call
|
||||||
|
relay_late_setup_files() when the kernel is ready to handle files,
|
||||||
|
to expose the buffered data to the userspace.
|
||||||
|
|
||||||
Channel 'modes'
|
Channel 'modes'
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ Similarly to JFFS2, UBIFS supports on-the-flight compression which makes
|
||||||
it possible to fit quite a lot of data to the flash.
|
it possible to fit quite a lot of data to the flash.
|
||||||
|
|
||||||
Similarly to JFFS2, UBIFS is tolerant of unclean reboots and power-cuts.
|
Similarly to JFFS2, UBIFS is tolerant of unclean reboots and power-cuts.
|
||||||
It does not need stuff like ckfs.ext2. UBIFS automatically replays its
|
It does not need stuff like fsck.ext2. UBIFS automatically replays its
|
||||||
journal and recovers from crashes, ensuring that the on-flash data
|
journal and recovers from crashes, ensuring that the on-flash data
|
||||||
structures are consistent.
|
structures are consistent.
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,14 @@ shortname=lower|win95|winnt|mixed
|
||||||
emulate the Windows 95 rule for create.
|
emulate the Windows 95 rule for create.
|
||||||
Default setting is `lower'.
|
Default setting is `lower'.
|
||||||
|
|
||||||
|
tz=UTC -- Interpret timestamps as UTC rather than local time.
|
||||||
|
This option disables the conversion of timestamps
|
||||||
|
between local time (as used by Windows on FAT) and UTC
|
||||||
|
(which Linux uses internally). This is particuluarly
|
||||||
|
useful when mounting devices (like digital cameras)
|
||||||
|
that are set to UTC in order to avoid the pitfalls of
|
||||||
|
local time.
|
||||||
|
|
||||||
<bool>: 0,1,yes,no,true,false
|
<bool>: 0,1,yes,no,true,false
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
|
@ -143,7 +143,7 @@ struct file_system_type {
|
||||||
|
|
||||||
The get_sb() method has the following arguments:
|
The get_sb() method has the following arguments:
|
||||||
|
|
||||||
struct file_system_type *fs_type: decribes the filesystem, partly initialized
|
struct file_system_type *fs_type: describes the filesystem, partly initialized
|
||||||
by the specific filesystem code
|
by the specific filesystem code
|
||||||
|
|
||||||
int flags: mount flags
|
int flags: mount flags
|
||||||
|
@ -895,9 +895,9 @@ struct dentry_operations {
|
||||||
iput() yourself
|
iput() yourself
|
||||||
|
|
||||||
d_dname: called when the pathname of a dentry should be generated.
|
d_dname: called when the pathname of a dentry should be generated.
|
||||||
Usefull for some pseudo filesystems (sockfs, pipefs, ...) to delay
|
Useful for some pseudo filesystems (sockfs, pipefs, ...) to delay
|
||||||
pathname generation. (Instead of doing it when dentry is created,
|
pathname generation. (Instead of doing it when dentry is created,
|
||||||
its done only when the path is needed.). Real filesystems probably
|
it's done only when the path is needed.). Real filesystems probably
|
||||||
dont want to use it, because their dentries are present in global
|
dont want to use it, because their dentries are present in global
|
||||||
dcache hash, so their hash should be an invariant. As no lock is
|
dcache hash, so their hash should be an invariant. As no lock is
|
||||||
held, d_dname() should not try to modify the dentry itself, unless
|
held, d_dname() should not try to modify the dentry itself, unless
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
Copyright 2008 Red Hat Inc.
|
Copyright 2008 Red Hat Inc.
|
||||||
Author: Steven Rostedt <srostedt@redhat.com>
|
Author: Steven Rostedt <srostedt@redhat.com>
|
||||||
License: The GNU Free Documentation License, Version 1.2
|
License: The GNU Free Documentation License, Version 1.2
|
||||||
|
(dual licensed under the GPL v2)
|
||||||
Reviewers: Elias Oltmanns, Randy Dunlap, Andrew Morton,
|
Reviewers: Elias Oltmanns, Randy Dunlap, Andrew Morton,
|
||||||
John Kacur, and David Teigland.
|
John Kacur, and David Teigland.
|
||||||
|
|
||||||
|
|
|
@ -347,15 +347,12 @@ necessarily be nonportable.
|
||||||
Dynamic definition of GPIOs is not currently standard; for example, as
|
Dynamic definition of GPIOs is not currently standard; for example, as
|
||||||
a side effect of configuring an add-on board with some GPIO expanders.
|
a side effect of configuring an add-on board with some GPIO expanders.
|
||||||
|
|
||||||
These calls are purely for kernel space, but a userspace API could be built
|
|
||||||
on top of them.
|
|
||||||
|
|
||||||
|
|
||||||
GPIO implementor's framework (OPTIONAL)
|
GPIO implementor's framework (OPTIONAL)
|
||||||
=======================================
|
=======================================
|
||||||
As noted earlier, there is an optional implementation framework making it
|
As noted earlier, there is an optional implementation framework making it
|
||||||
easier for platforms to support different kinds of GPIO controller using
|
easier for platforms to support different kinds of GPIO controller using
|
||||||
the same programming interface.
|
the same programming interface. This framework is called "gpiolib".
|
||||||
|
|
||||||
As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
|
As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
|
||||||
will be found there. That will list all the controllers registered through
|
will be found there. That will list all the controllers registered through
|
||||||
|
@ -392,11 +389,21 @@ either NULL or the label associated with that GPIO when it was requested.
|
||||||
|
|
||||||
Platform Support
|
Platform Support
|
||||||
----------------
|
----------------
|
||||||
To support this framework, a platform's Kconfig will "select HAVE_GPIO_LIB"
|
To support this framework, a platform's Kconfig will "select" either
|
||||||
|
ARCH_REQUIRE_GPIOLIB or ARCH_WANT_OPTIONAL_GPIOLIB
|
||||||
and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
|
and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
|
||||||
three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
|
three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
|
||||||
They may also want to provide a custom value for ARCH_NR_GPIOS.
|
They may also want to provide a custom value for ARCH_NR_GPIOS.
|
||||||
|
|
||||||
|
ARCH_REQUIRE_GPIOLIB means that the gpio-lib code will always get compiled
|
||||||
|
into the kernel on that architecture.
|
||||||
|
|
||||||
|
ARCH_WANT_OPTIONAL_GPIOLIB means the gpio-lib code defaults to off and the user
|
||||||
|
can enable it and build it into the kernel optionally.
|
||||||
|
|
||||||
|
If neither of these options are selected, the platform does not support
|
||||||
|
GPIOs through GPIO-lib and the code cannot be enabled by the user.
|
||||||
|
|
||||||
Trivial implementations of those functions can directly use framework
|
Trivial implementations of those functions can directly use framework
|
||||||
code, which always dispatches through the gpio_chip:
|
code, which always dispatches through the gpio_chip:
|
||||||
|
|
||||||
|
@ -439,4 +446,120 @@ becomes available. That may mean the device should not be registered until
|
||||||
calls for that GPIO can work. One way to address such dependencies is for
|
calls for that GPIO can work. One way to address such dependencies is for
|
||||||
such gpio_chip controllers to provide setup() and teardown() callbacks to
|
such gpio_chip controllers to provide setup() and teardown() callbacks to
|
||||||
board specific code; those board specific callbacks would register devices
|
board specific code; those board specific callbacks would register devices
|
||||||
once all the necessary resources are available.
|
once all the necessary resources are available, and remove them later when
|
||||||
|
the GPIO controller device becomes unavailable.
|
||||||
|
|
||||||
|
|
||||||
|
Sysfs Interface for Userspace (OPTIONAL)
|
||||||
|
========================================
|
||||||
|
Platforms which use the "gpiolib" implementors framework may choose to
|
||||||
|
configure a sysfs user interface to GPIOs. This is different from the
|
||||||
|
debugfs interface, since it provides control over GPIO direction and
|
||||||
|
value instead of just showing a gpio state summary. Plus, it could be
|
||||||
|
present on production systems without debugging support.
|
||||||
|
|
||||||
|
Given approprate hardware documentation for the system, userspace could
|
||||||
|
know for example that GPIO #23 controls the write protect line used to
|
||||||
|
protect boot loader segments in flash memory. System upgrade procedures
|
||||||
|
may need to temporarily remove that protection, first importing a GPIO,
|
||||||
|
then changing its output state, then updating the code before re-enabling
|
||||||
|
the write protection. In normal use, GPIO #23 would never be touched,
|
||||||
|
and the kernel would have no need to know about it.
|
||||||
|
|
||||||
|
Again depending on appropriate hardware documentation, on some systems
|
||||||
|
userspace GPIO can be used to determine system configuration data that
|
||||||
|
standard kernels won't know about. And for some tasks, simple userspace
|
||||||
|
GPIO drivers could be all that the system really needs.
|
||||||
|
|
||||||
|
Note that standard kernel drivers exist for common "LEDs and Buttons"
|
||||||
|
GPIO tasks: "leds-gpio" and "gpio_keys", respectively. Use those
|
||||||
|
instead of talking directly to the GPIOs; they integrate with kernel
|
||||||
|
frameworks better than your userspace code could.
|
||||||
|
|
||||||
|
|
||||||
|
Paths in Sysfs
|
||||||
|
--------------
|
||||||
|
There are three kinds of entry in /sys/class/gpio:
|
||||||
|
|
||||||
|
- Control interfaces used to get userspace control over GPIOs;
|
||||||
|
|
||||||
|
- GPIOs themselves; and
|
||||||
|
|
||||||
|
- GPIO controllers ("gpio_chip" instances).
|
||||||
|
|
||||||
|
That's in addition to standard files including the "device" symlink.
|
||||||
|
|
||||||
|
The control interfaces are write-only:
|
||||||
|
|
||||||
|
/sys/class/gpio/
|
||||||
|
|
||||||
|
"export" ... Userspace may ask the kernel to export control of
|
||||||
|
a GPIO to userspace by writing its number to this file.
|
||||||
|
|
||||||
|
Example: "echo 19 > export" will create a "gpio19" node
|
||||||
|
for GPIO #19, if that's not requested by kernel code.
|
||||||
|
|
||||||
|
"unexport" ... Reverses the effect of exporting to userspace.
|
||||||
|
|
||||||
|
Example: "echo 19 > unexport" will remove a "gpio19"
|
||||||
|
node exported using the "export" file.
|
||||||
|
|
||||||
|
GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
|
||||||
|
and have the following read/write attributes:
|
||||||
|
|
||||||
|
/sys/class/gpio/gpioN/
|
||||||
|
|
||||||
|
"direction" ... reads as either "in" or "out". This value may
|
||||||
|
normally be written. Writing as "out" defaults to
|
||||||
|
initializing the value as low. To ensure glitch free
|
||||||
|
operation, values "low" and "high" may be written to
|
||||||
|
configure the GPIO as an output with that initial value.
|
||||||
|
|
||||||
|
Note that this attribute *will not exist* if the kernel
|
||||||
|
doesn't support changing the direction of a GPIO, or
|
||||||
|
it was exported by kernel code that didn't explicitly
|
||||||
|
allow userspace to reconfigure this GPIO's direction.
|
||||||
|
|
||||||
|
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
|
||||||
|
is configured as an output, this value may be written;
|
||||||
|
any nonzero value is treated as high.
|
||||||
|
|
||||||
|
GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the
|
||||||
|
controller implementing GPIOs starting at #42) and have the following
|
||||||
|
read-only attributes:
|
||||||
|
|
||||||
|
/sys/class/gpio/gpiochipN/
|
||||||
|
|
||||||
|
"base" ... same as N, the first GPIO managed by this chip
|
||||||
|
|
||||||
|
"label" ... provided for diagnostics (not always unique)
|
||||||
|
|
||||||
|
"ngpio" ... how many GPIOs this manges (N to N + ngpio - 1)
|
||||||
|
|
||||||
|
Board documentation should in most cases cover what GPIOs are used for
|
||||||
|
what purposes. However, those numbers are not always stable; GPIOs on
|
||||||
|
a daughtercard might be different depending on the base board being used,
|
||||||
|
or other cards in the stack. In such cases, you may need to use the
|
||||||
|
gpiochip nodes (possibly in conjunction with schematics) to determine
|
||||||
|
the correct GPIO number to use for a given signal.
|
||||||
|
|
||||||
|
|
||||||
|
Exporting from Kernel code
|
||||||
|
--------------------------
|
||||||
|
Kernel code can explicitly manage exports of GPIOs which have already been
|
||||||
|
requested using gpio_request():
|
||||||
|
|
||||||
|
/* export the GPIO to userspace */
|
||||||
|
int gpio_export(unsigned gpio, bool direction_may_change);
|
||||||
|
|
||||||
|
/* reverse gpio_export() */
|
||||||
|
void gpio_unexport();
|
||||||
|
|
||||||
|
After a kernel driver requests a GPIO, it may only be made available in
|
||||||
|
the sysfs interface by gpio_export(). The driver can control whether the
|
||||||
|
signal direction may change. This helps drivers prevent userspace code
|
||||||
|
from accidentally clobbering important system state.
|
||||||
|
|
||||||
|
This explicit exporting can help with debugging (by making some kinds
|
||||||
|
of experiments easier), or can provide an always-there interface that's
|
||||||
|
suitable for documenting as part of a board support package.
|
||||||
|
|
|
@ -10,6 +10,10 @@ Supported chips:
|
||||||
Prefix: 'sch311x'
|
Prefix: 'sch311x'
|
||||||
Addresses scanned: none, address read from Super-I/O config space
|
Addresses scanned: none, address read from Super-I/O config space
|
||||||
Datasheet: http://www.nuhorizons.com/FeaturedProducts/Volume1/SMSC/311x.pdf
|
Datasheet: http://www.nuhorizons.com/FeaturedProducts/Volume1/SMSC/311x.pdf
|
||||||
|
* SMSC SCH5027
|
||||||
|
Prefix: 'sch5027'
|
||||||
|
Addresses scanned: I2C 0x2c, 0x2d, 0x2e
|
||||||
|
Datasheet: Provided by SMSC upon request and under NDA
|
||||||
|
|
||||||
Authors:
|
Authors:
|
||||||
Juerg Haefliger <juergh@gmail.com>
|
Juerg Haefliger <juergh@gmail.com>
|
||||||
|
@ -22,34 +26,36 @@ Module Parameters
|
||||||
and PWM output control functions. Using this parameter
|
and PWM output control functions. Using this parameter
|
||||||
shouldn't be required since the BIOS usually takes care
|
shouldn't be required since the BIOS usually takes care
|
||||||
of this.
|
of this.
|
||||||
|
* probe_all_addr: bool Include non-standard LPC addresses 0x162e and 0x164e
|
||||||
Note that there is no need to use this parameter if the driver loads without
|
when probing for ISA devices. This is required for the
|
||||||
complaining. The driver will say so if it is necessary.
|
following boards:
|
||||||
|
- VIA EPIA SN18000
|
||||||
|
|
||||||
|
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
This driver implements support for the hardware monitoring capabilities of the
|
This driver implements support for the hardware monitoring capabilities of the
|
||||||
SMSC DME1737 and Asus A8000 (which are the same) and SMSC SCH311x Super-I/O
|
SMSC DME1737 and Asus A8000 (which are the same), SMSC SCH5027, and SMSC
|
||||||
chips. These chips feature monitoring of 3 temp sensors temp[1-3] (2 remote
|
SCH311x Super-I/O chips. These chips feature monitoring of 3 temp sensors
|
||||||
diodes and 1 internal), 7 voltages in[0-6] (6 external and 1 internal) and up
|
temp[1-3] (2 remote diodes and 1 internal), 7 voltages in[0-6] (6 external and
|
||||||
to 6 fan speeds fan[1-6]. Additionally, the chips implement up to 5 PWM
|
1 internal) and up to 6 fan speeds fan[1-6]. Additionally, the chips implement
|
||||||
outputs pwm[1-3,5-6] for controlling fan speeds both manually and
|
up to 5 PWM outputs pwm[1-3,5-6] for controlling fan speeds both manually and
|
||||||
automatically.
|
automatically.
|
||||||
|
|
||||||
For the DME1737 and A8000, fan[1-2] and pwm[1-2] are always present. Fan[3-6]
|
For the DME1737, A8000 and SCH5027, fan[1-2] and pwm[1-2] are always present.
|
||||||
and pwm[3,5-6] are optional features and their availability depends on the
|
Fan[3-6] and pwm[3,5-6] are optional features and their availability depends on
|
||||||
configuration of the chip. The driver will detect which features are present
|
the configuration of the chip. The driver will detect which features are
|
||||||
during initialization and create the sysfs attributes accordingly.
|
present during initialization and create the sysfs attributes accordingly.
|
||||||
|
|
||||||
For the SCH311x, fan[1-3] and pwm[1-3] are always present and fan[4-6] and
|
For the SCH311x, fan[1-3] and pwm[1-3] are always present and fan[4-6] and
|
||||||
pwm[5-6] don't exist.
|
pwm[5-6] don't exist.
|
||||||
|
|
||||||
The hardware monitoring features of the DME1737 and A8000 are only accessible
|
The hardware monitoring features of the DME1737, A8000, and SCH5027 are only
|
||||||
via SMBus, while the SCH311x only provides access via the ISA bus. The driver
|
accessible via SMBus, while the SCH311x only provides access via the ISA bus.
|
||||||
will therefore register itself as an I2C client driver if it detects a DME1737
|
The driver will therefore register itself as an I2C client driver if it detects
|
||||||
or A8000 and as a platform driver if it detects a SCH311x chip.
|
a DME1737, A8000, or SCH5027 and as a platform driver if it detects a SCH311x
|
||||||
|
chip.
|
||||||
|
|
||||||
|
|
||||||
Voltage Monitoring
|
Voltage Monitoring
|
||||||
|
@ -60,6 +66,7 @@ scaling resistors. The values returned by the driver therefore reflect true
|
||||||
millivolts and don't need scaling. The voltage inputs are mapped as follows
|
millivolts and don't need scaling. The voltage inputs are mapped as follows
|
||||||
(the last column indicates the input ranges):
|
(the last column indicates the input ranges):
|
||||||
|
|
||||||
|
DME1737, A8000:
|
||||||
in0: +5VTR (+5V standby) 0V - 6.64V
|
in0: +5VTR (+5V standby) 0V - 6.64V
|
||||||
in1: Vccp (processor core) 0V - 3V
|
in1: Vccp (processor core) 0V - 3V
|
||||||
in2: VCC (internal +3.3V) 0V - 4.38V
|
in2: VCC (internal +3.3V) 0V - 4.38V
|
||||||
|
@ -68,6 +75,24 @@ millivolts and don't need scaling. The voltage inputs are mapped as follows
|
||||||
in5: VTR (+3.3V standby) 0V - 4.38V
|
in5: VTR (+3.3V standby) 0V - 4.38V
|
||||||
in6: Vbat (+3.0V) 0V - 4.38V
|
in6: Vbat (+3.0V) 0V - 4.38V
|
||||||
|
|
||||||
|
SCH311x:
|
||||||
|
in0: +2.5V 0V - 6.64V
|
||||||
|
in1: Vccp (processor core) 0V - 2V
|
||||||
|
in2: VCC (internal +3.3V) 0V - 4.38V
|
||||||
|
in3: +5V 0V - 6.64V
|
||||||
|
in4: +12V 0V - 16V
|
||||||
|
in5: VTR (+3.3V standby) 0V - 4.38V
|
||||||
|
in6: Vbat (+3.0V) 0V - 4.38V
|
||||||
|
|
||||||
|
SCH5027:
|
||||||
|
in0: +5VTR (+5V standby) 0V - 6.64V
|
||||||
|
in1: Vccp (processor core) 0V - 3V
|
||||||
|
in2: VCC (internal +3.3V) 0V - 4.38V
|
||||||
|
in3: V2_IN 0V - 1.5V
|
||||||
|
in4: V1_IN 0V - 1.5V
|
||||||
|
in5: VTR (+3.3V standby) 0V - 4.38V
|
||||||
|
in6: Vbat (+3.0V) 0V - 4.38V
|
||||||
|
|
||||||
Each voltage input has associated min and max limits which trigger an alarm
|
Each voltage input has associated min and max limits which trigger an alarm
|
||||||
when crossed.
|
when crossed.
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
Kernel driver ibmaem
|
Kernel driver ibmaem
|
||||||
======================
|
======================
|
||||||
|
|
||||||
|
This driver talks to the IBM Systems Director Active Energy Manager, known
|
||||||
|
henceforth as AEM.
|
||||||
|
|
||||||
Supported systems:
|
Supported systems:
|
||||||
* Any recent IBM System X server with Active Energy Manager support.
|
* Any recent IBM System X server with AEM support.
|
||||||
This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2,
|
This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2,
|
||||||
x3950 M2, and certain HS2x/LS2x/QS2x blades. The IPMI host interface
|
x3950 M2, and certain HS2x/LS2x/QS2x blades. The IPMI host interface
|
||||||
driver ("ipmi-si") needs to be loaded for this driver to do anything.
|
driver ("ipmi-si") needs to be loaded for this driver to do anything.
|
||||||
|
@ -14,24 +17,22 @@ Author: Darrick J. Wong
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
This driver implements sensor reading support for the energy and power
|
This driver implements sensor reading support for the energy and power meters
|
||||||
meters available on various IBM System X hardware through the BMC. All
|
available on various IBM System X hardware through the BMC. All sensor banks
|
||||||
sensor banks will be exported as platform devices; this driver can talk
|
will be exported as platform devices; this driver can talk to both v1 and v2
|
||||||
to both v1 and v2 interfaces. This driver is completely separate from the
|
interfaces. This driver is completely separate from the older ibmpex driver.
|
||||||
older ibmpex driver.
|
|
||||||
|
|
||||||
The v1 AEM interface has a simple set of features to monitor energy use.
|
The v1 AEM interface has a simple set of features to monitor energy use. There
|
||||||
There is a register that displays an estimate of raw energy consumption
|
is a register that displays an estimate of raw energy consumption since the
|
||||||
since the last BMC reset, and a power sensor that returns average power
|
last BMC reset, and a power sensor that returns average power use over a
|
||||||
use over a configurable interval.
|
configurable interval.
|
||||||
|
|
||||||
The v2 AEM interface is a bit more sophisticated, being able to present
|
The v2 AEM interface is a bit more sophisticated, being able to present a wider
|
||||||
a wider range of energy and power use registers, the power cap as
|
range of energy and power use registers, the power cap as set by the AEM
|
||||||
set by the AEM software, and temperature sensors.
|
software, and temperature sensors.
|
||||||
|
|
||||||
Special Features
|
Special Features
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The "power_cap" value displays the current system power cap, as set by
|
The "power_cap" value displays the current system power cap, as set by the AEM
|
||||||
the Active Energy Manager software. Setting the power cap from the host
|
software. Setting the power cap from the host is not currently supported.
|
||||||
is not currently supported.
|
|
||||||
|
|
|
@ -6,12 +6,14 @@ Supported chips:
|
||||||
Prefix: 'it87'
|
Prefix: 'it87'
|
||||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||||
Datasheet: Publicly available at the ITE website
|
Datasheet: Publicly available at the ITE website
|
||||||
http://www.ite.com.tw/
|
http://www.ite.com.tw/product_info/file/pc/IT8705F_V.0.4.1.pdf
|
||||||
* IT8712F
|
* IT8712F
|
||||||
Prefix: 'it8712'
|
Prefix: 'it8712'
|
||||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||||
Datasheet: Publicly available at the ITE website
|
Datasheet: Publicly available at the ITE website
|
||||||
http://www.ite.com.tw/
|
http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.1.pdf
|
||||||
|
http://www.ite.com.tw/product_info/file/pc/Errata%20V0.1%20for%20IT8712F%20V0.9.1.pdf
|
||||||
|
http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.3.pdf
|
||||||
* IT8716F/IT8726F
|
* IT8716F/IT8726F
|
||||||
Prefix: 'it8716'
|
Prefix: 'it8716'
|
||||||
Addresses scanned: from Super I/O config space (8 I/O ports)
|
Addresses scanned: from Super I/O config space (8 I/O ports)
|
||||||
|
@ -90,14 +92,13 @@ upper VID bits share their pins with voltage inputs (in5 and in6) so you
|
||||||
can't have both on a given board.
|
can't have both on a given board.
|
||||||
|
|
||||||
The IT8716F, IT8718F and later IT8712F revisions have support for
|
The IT8716F, IT8718F and later IT8712F revisions have support for
|
||||||
2 additional fans. They are supported by the driver for the IT8716F and
|
2 additional fans. The additional fans are supported by the driver.
|
||||||
IT8718F but not for the IT8712F
|
|
||||||
|
|
||||||
The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
|
The IT8716F and IT8718F, and late IT8712F and IT8705F also have optional
|
||||||
16-bit tachometer counters for fans 1 to 3. This is better (no more fan
|
16-bit tachometer counters for fans 1 to 3. This is better (no more fan
|
||||||
clock divider mess) but not compatible with the older chips and
|
clock divider mess) but not compatible with the older chips and
|
||||||
revisions. For now, the driver only uses the 16-bit mode on the
|
revisions. The 16-bit tachometer mode is enabled by the driver when one
|
||||||
IT8716F and IT8718F.
|
of the above chips is detected.
|
||||||
|
|
||||||
The IT8726F is just bit enhanced IT8716F with additional hardware
|
The IT8726F is just bit enhanced IT8716F with additional hardware
|
||||||
for AMD power sequencing. Therefore the chip will appear as IT8716F
|
for AMD power sequencing. Therefore the chip will appear as IT8716F
|
||||||
|
|
|
@ -96,11 +96,6 @@ initial testing of the ADM1027 it was 1.00 degC steps. Analog Devices has
|
||||||
confirmed this "bug". The ADT7463 is reported to work as described in the
|
confirmed this "bug". The ADT7463 is reported to work as described in the
|
||||||
documentation. The current lm85 driver does not show the offset register.
|
documentation. The current lm85 driver does not show the offset register.
|
||||||
|
|
||||||
The ADT7463 has a THERM asserted counter. This counter has a 22.76ms
|
|
||||||
resolution and a range of 5.8 seconds. The driver implements a 32-bit
|
|
||||||
accumulator of the counter value to extend the range to over a year. The
|
|
||||||
counter will stay at it's max value until read.
|
|
||||||
|
|
||||||
See the vendor datasheets for more information. There is application note
|
See the vendor datasheets for more information. There is application note
|
||||||
from National (AN-1260) with some additional information about the LM85.
|
from National (AN-1260) with some additional information about the LM85.
|
||||||
The Analog Devices datasheet is very detailed and describes a procedure for
|
The Analog Devices datasheet is very detailed and describes a procedure for
|
||||||
|
@ -206,13 +201,15 @@ Configuration choices:
|
||||||
|
|
||||||
The National LM85's have two vendor specific configuration
|
The National LM85's have two vendor specific configuration
|
||||||
features. Tach. mode and Spinup Control. For more details on these,
|
features. Tach. mode and Spinup Control. For more details on these,
|
||||||
see the LM85 datasheet or Application Note AN-1260.
|
see the LM85 datasheet or Application Note AN-1260. These features
|
||||||
|
are not currently supported by the lm85 driver.
|
||||||
|
|
||||||
The Analog Devices ADM1027 has several vendor specific enhancements.
|
The Analog Devices ADM1027 has several vendor specific enhancements.
|
||||||
The number of pulses-per-rev of the fans can be set, Tach monitoring
|
The number of pulses-per-rev of the fans can be set, Tach monitoring
|
||||||
can be optimized for PWM operation, and an offset can be applied to
|
can be optimized for PWM operation, and an offset can be applied to
|
||||||
the temperatures to compensate for systemic errors in the
|
the temperatures to compensate for systemic errors in the
|
||||||
measurements.
|
measurements. These features are not currently supported by the lm85
|
||||||
|
driver.
|
||||||
|
|
||||||
In addition to the ADM1027 features, the ADT7463 also has Tmin control
|
In addition to the ADM1027 features, the ADT7463 also has Tmin control
|
||||||
and THERM asserted counts. Automatic Tmin control acts to adjust the
|
and THERM asserted counts. Automatic Tmin control acts to adjust the
|
||||||
|
|
|
@ -40,10 +40,6 @@ Module Parameters
|
||||||
(default is 1)
|
(default is 1)
|
||||||
Use 'init=0' to bypass initializing the chip.
|
Use 'init=0' to bypass initializing the chip.
|
||||||
Try this if your computer crashes when you load the module.
|
Try this if your computer crashes when you load the module.
|
||||||
* reset: int
|
|
||||||
(default is 0)
|
|
||||||
The driver used to reset the chip on load, but does no more. Use
|
|
||||||
'reset=1' to restore the old behavior. Report if you need to do this.
|
|
||||||
|
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -22,6 +22,7 @@ Credits:
|
||||||
|
|
||||||
Additional contributors:
|
Additional contributors:
|
||||||
Sven Anders <anders@anduras.de>
|
Sven Anders <anders@anduras.de>
|
||||||
|
Marc Hulsman <m.hulsman@tudelft.nl>
|
||||||
|
|
||||||
Module Parameters
|
Module Parameters
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -67,9 +68,8 @@ on until the temperature falls below the Hysteresis value.
|
||||||
|
|
||||||
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
||||||
triggered if the rotation speed has dropped below a programmable limit. Fan
|
triggered if the rotation speed has dropped below a programmable limit. Fan
|
||||||
readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3
|
readings can be divided by a programmable divider (1, 2, 4, 8, 16,
|
||||||
and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more
|
32, 64 or 128 for all fans) to give the readings more range or accuracy.
|
||||||
range or accuracy.
|
|
||||||
|
|
||||||
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||||
|
|
281
Documentation/i2c/upgrading-clients
Normal file
281
Documentation/i2c/upgrading-clients
Normal file
|
@ -0,0 +1,281 @@
|
||||||
|
Upgrading I2C Drivers to the new 2.6 Driver Model
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
Ben Dooks <ben-linux@fluff.org>
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
This guide outlines how to alter existing Linux 2.6 client drivers from
|
||||||
|
the old to the new new binding methods.
|
||||||
|
|
||||||
|
|
||||||
|
Example old-style driver
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
|
||||||
|
struct example_state {
|
||||||
|
struct i2c_client client;
|
||||||
|
....
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver;
|
||||||
|
|
||||||
|
static unsigned short ignore[] = { I2C_CLIENT_END };
|
||||||
|
static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
|
||||||
|
|
||||||
|
I2C_CLIENT_INSMOD;
|
||||||
|
|
||||||
|
static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
||||||
|
{
|
||||||
|
struct example_state *state;
|
||||||
|
struct device *dev = &adap->dev; /* to use for dev_ reports */
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
dev_err(dev, "failed to create our state\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
example->client.addr = addr;
|
||||||
|
example->client.flags = 0;
|
||||||
|
example->client.adapter = adap;
|
||||||
|
|
||||||
|
i2c_set_clientdata(&state->i2c_client, state);
|
||||||
|
strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
|
||||||
|
|
||||||
|
ret = i2c_attach_client(&state->i2c_client);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "failed to attach client\n");
|
||||||
|
kfree(state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &state->i2c_client.dev;
|
||||||
|
|
||||||
|
/* rest of the initialisation goes here. */
|
||||||
|
|
||||||
|
dev_info(dev, "example client created\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit example_detach(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct example_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
i2c_detach_client(client);
|
||||||
|
kfree(state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int example_attach_adapter(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
return i2c_probe(adap, &addr_data, example_attach);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "example",
|
||||||
|
},
|
||||||
|
.attach_adapter = example_attach_adapter,
|
||||||
|
.detach_client = __devexit_p(example_detach),
|
||||||
|
.suspend = example_suspend,
|
||||||
|
.resume = example_resume,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Updating the client
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The new style binding model will check against a list of supported
|
||||||
|
devices and their associated address supplied by the code registering
|
||||||
|
the busses. This means that the driver .attach_adapter and
|
||||||
|
.detach_adapter methods can be removed, along with the addr_data,
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
- static struct i2c_driver example_driver;
|
||||||
|
|
||||||
|
- static unsigned short ignore[] = { I2C_CLIENT_END };
|
||||||
|
- static unsigned short normal_addr[] = { OUR_ADDR, I2C_CLIENT_END };
|
||||||
|
|
||||||
|
- I2C_CLIENT_INSMOD;
|
||||||
|
|
||||||
|
- static int example_attach_adapter(struct i2c_adapter *adap)
|
||||||
|
- {
|
||||||
|
- return i2c_probe(adap, &addr_data, example_attach);
|
||||||
|
- }
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
- .attach_adapter = example_attach_adapter,
|
||||||
|
- .detach_client = __devexit_p(example_detach),
|
||||||
|
}
|
||||||
|
|
||||||
|
Add the probe and remove methods to the i2c_driver, as so:
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
+ .probe = example_probe,
|
||||||
|
+ .remove = __devexit_p(example_remove),
|
||||||
|
}
|
||||||
|
|
||||||
|
Change the example_attach method to accept the new parameters
|
||||||
|
which include the i2c_client that it will be working with:
|
||||||
|
|
||||||
|
- static int example_attach(struct i2c_adapter *adap, int addr, int kind)
|
||||||
|
+ static int example_probe(struct i2c_client *client,
|
||||||
|
+ const struct i2c_device_id *id)
|
||||||
|
|
||||||
|
Change the name of example_attach to example_probe to align it with the
|
||||||
|
i2c_driver entry names. The rest of the probe routine will now need to be
|
||||||
|
changed as the i2c_client has already been setup for use.
|
||||||
|
|
||||||
|
The necessary client fields have already been setup before
|
||||||
|
the probe function is called, so the following client setup
|
||||||
|
can be removed:
|
||||||
|
|
||||||
|
- example->client.addr = addr;
|
||||||
|
- example->client.flags = 0;
|
||||||
|
- example->client.adapter = adap;
|
||||||
|
-
|
||||||
|
- strlcpy(client->i2c_client.name, "example", I2C_NAME_SIZE);
|
||||||
|
|
||||||
|
The i2c_set_clientdata is now:
|
||||||
|
|
||||||
|
- i2c_set_clientdata(&state->client, state);
|
||||||
|
+ i2c_set_clientdata(client, state);
|
||||||
|
|
||||||
|
The call to i2c_attach_client is no longer needed, if the probe
|
||||||
|
routine exits successfully, then the driver will be automatically
|
||||||
|
attached by the core. Change the probe routine as so:
|
||||||
|
|
||||||
|
- ret = i2c_attach_client(&state->i2c_client);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- dev_err(dev, "failed to attach client\n");
|
||||||
|
- kfree(state);
|
||||||
|
- return ret;
|
||||||
|
- }
|
||||||
|
|
||||||
|
|
||||||
|
Remove the storage of 'struct i2c_client' from the 'struct example_state'
|
||||||
|
as we are provided with the i2c_client in our example_probe. Instead we
|
||||||
|
store a pointer to it for when it is needed.
|
||||||
|
|
||||||
|
struct example_state {
|
||||||
|
- struct i2c_client client;
|
||||||
|
+ struct i2c_client *client;
|
||||||
|
|
||||||
|
the new i2c client as so:
|
||||||
|
|
||||||
|
- struct device *dev = &adap->dev; /* to use for dev_ reports */
|
||||||
|
+ struct device *dev = &i2c_client->dev; /* to use for dev_ reports */
|
||||||
|
|
||||||
|
And remove the change after our client is attached, as the driver no
|
||||||
|
longer needs to register a new client structure with the core:
|
||||||
|
|
||||||
|
- dev = &state->i2c_client.dev;
|
||||||
|
|
||||||
|
In the probe routine, ensure that the new state has the client stored
|
||||||
|
in it:
|
||||||
|
|
||||||
|
static int example_probe(struct i2c_client *i2c_client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct example_state *state;
|
||||||
|
struct device *dev = &i2c_client->dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
dev_err(dev, "failed to create our state\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ state->client = i2c_client;
|
||||||
|
|
||||||
|
Update the detach method, by changing the name to _remove and
|
||||||
|
to delete the i2c_detach_client call. It is possible that you
|
||||||
|
can also remove the ret variable as it is not not needed for
|
||||||
|
any of the core functions.
|
||||||
|
|
||||||
|
- static int __devexit example_detach(struct i2c_client *client)
|
||||||
|
+ static int __devexit example_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct example_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
- i2c_detach_client(client);
|
||||||
|
|
||||||
|
And finally ensure that we have the correct ID table for the i2c-core
|
||||||
|
and other utilities:
|
||||||
|
|
||||||
|
+ struct i2c_device_id example_idtable[] = {
|
||||||
|
+ { "example", 0 },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+MODULE_DEVICE_TABLE(i2c, example_idtable);
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "example",
|
||||||
|
},
|
||||||
|
+ .id_table = example_ids,
|
||||||
|
|
||||||
|
|
||||||
|
Our driver should now look like this:
|
||||||
|
|
||||||
|
struct example_state {
|
||||||
|
struct i2c_client *client;
|
||||||
|
....
|
||||||
|
};
|
||||||
|
|
||||||
|
static int example_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct example_state *state;
|
||||||
|
struct device *dev = &client->dev;
|
||||||
|
|
||||||
|
state = kzalloc(sizeof(struct example_state), GFP_KERNEL);
|
||||||
|
if (state == NULL) {
|
||||||
|
dev_err(dev, "failed to create our state\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->client = client;
|
||||||
|
i2c_set_clientdata(client, state);
|
||||||
|
|
||||||
|
/* rest of the initialisation goes here. */
|
||||||
|
|
||||||
|
dev_info(dev, "example client created\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devexit example_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct example_state *state = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
kfree(state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_device_id example_idtable[] = {
|
||||||
|
{ "example", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(i2c, example_idtable);
|
||||||
|
|
||||||
|
static struct i2c_driver example_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "example",
|
||||||
|
},
|
||||||
|
.id_table = example_idtable,
|
||||||
|
.probe = example_probe,
|
||||||
|
.remove = __devexit_p(example_remove),
|
||||||
|
.suspend = example_suspend,
|
||||||
|
.resume = example_resume,
|
||||||
|
};
|
8
Documentation/ia64/Makefile
Normal file
8
Documentation/ia64/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||||
|
obj- := dummy.o
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
hostprogs-y := aliasing-test
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
|
@ -50,9 +50,9 @@ Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qe
|
||||||
/usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image
|
/usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image
|
||||||
(xx is the number of virtual processors for the guest, now the maximum value is 4)
|
(xx is the number of virtual processors for the guest, now the maximum value is 4)
|
||||||
|
|
||||||
5. Known possibile issue on some platforms with old Firmware.
|
5. Known possible issue on some platforms with old Firmware.
|
||||||
|
|
||||||
If meet strange host crashe issues, try to solve it through either of the following ways:
|
In the event of strange host crash issues, try to solve it through either of the following ways:
|
||||||
|
|
||||||
(1): Upgrade your Firmware to the latest one.
|
(1): Upgrade your Firmware to the latest one.
|
||||||
|
|
||||||
|
@ -65,8 +65,8 @@ index 0b53344..f02b0f7 100644
|
||||||
mov ar.pfs = loc1
|
mov ar.pfs = loc1
|
||||||
mov rp = loc0
|
mov rp = loc0
|
||||||
;;
|
;;
|
||||||
- srlz.d // seralize restoration of psr.l
|
- srlz.d // serialize restoration of psr.l
|
||||||
+ srlz.i // seralize restoration of psr.l
|
+ srlz.i // serialize restoration of psr.l
|
||||||
+ ;;
|
+ ;;
|
||||||
br.ret.sptk.many b0
|
br.ret.sptk.many b0
|
||||||
END(ia64_pal_call_static)
|
END(ia64_pal_call_static)
|
||||||
|
|
|
@ -31,7 +31,7 @@ The driver works with ALSA drivers simultaneously. For example, the xracer
|
||||||
uses joystick as input device and PCM device as sound output in one time.
|
uses joystick as input device and PCM device as sound output in one time.
|
||||||
There are no sound or input collisions detected. The source code have
|
There are no sound or input collisions detected. The source code have
|
||||||
comments about them; but I've found the joystick can be initialized
|
comments about them; but I've found the joystick can be initialized
|
||||||
separately of ALSA modules. So, you canm use only one joystick driver
|
separately of ALSA modules. So, you can use only one joystick driver
|
||||||
without ALSA drivers. The ALSA drivers are not needed to compile or
|
without ALSA drivers. The ALSA drivers are not needed to compile or
|
||||||
run this driver.
|
run this driver.
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,6 @@ Code Seq# Include File Comments
|
||||||
'T' all linux/soundcard.h conflict!
|
'T' all linux/soundcard.h conflict!
|
||||||
'T' all asm-i386/ioctls.h conflict!
|
'T' all asm-i386/ioctls.h conflict!
|
||||||
'U' 00-EF linux/drivers/usb/usb.h
|
'U' 00-EF linux/drivers/usb/usb.h
|
||||||
'U' F0-FF drivers/usb/auerswald.c
|
|
||||||
'V' all linux/vt.h
|
'V' all linux/vt.h
|
||||||
'W' 00-1F linux/watchdog.h conflict!
|
'W' 00-1F linux/watchdog.h conflict!
|
||||||
'W' 00-1F linux/wanrouter.h conflict!
|
'W' 00-1F linux/wanrouter.h conflict!
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
To decode a hex IOCTL code:
|
To decode a hex IOCTL code:
|
||||||
|
|
||||||
Most architecures use this generic format, but check
|
Most architectures use this generic format, but check
|
||||||
include/ARCH/ioctl.h for specifics, e.g. powerpc
|
include/ARCH/ioctl.h for specifics, e.g. powerpc
|
||||||
uses 3 bits to encode read/write and 13 bits for size.
|
uses 3 bits to encode read/write and 13 bits for size.
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ uses 3 bits to encode read/write and 13 bits for size.
|
||||||
7-0 function #
|
7-0 function #
|
||||||
|
|
||||||
|
|
||||||
So for example 0x82187201 is a read with arg length of 0x218,
|
So for example 0x82187201 is a read with arg length of 0x218,
|
||||||
character 'r' function 1. Grepping the source reveals this is:
|
character 'r' function 1. Grepping the source reveals this is:
|
||||||
|
|
||||||
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
|
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
|
||||||
|
|
|
@ -143,7 +143,7 @@ disk and partition statistics are consistent again. Since we still don't
|
||||||
keep record of the partition-relative address, an operation is attributed to
|
keep record of the partition-relative address, an operation is attributed to
|
||||||
the partition which contains the first sector of the request after the
|
the partition which contains the first sector of the request after the
|
||||||
eventual merges. As requests can be merged across partition, this could lead
|
eventual merges. As requests can be merged across partition, this could lead
|
||||||
to some (probably insignificant) innacuracy.
|
to some (probably insignificant) inaccuracy.
|
||||||
|
|
||||||
Additional notes
|
Additional notes
|
||||||
----------------
|
----------------
|
||||||
|
|
6
Documentation/isdn/README.mISDN
Normal file
6
Documentation/isdn/README.mISDN
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
mISDN is a new modular ISDN driver, in the long term it should replace
|
||||||
|
the old I4L driver architecture for passiv ISDN cards.
|
||||||
|
It was designed to allow a broad range of applications and interfaces
|
||||||
|
but only have the basic function in kernel, the interface to the user
|
||||||
|
space is based on sockets with a own address family AF_ISDN.
|
||||||
|
|
|
@ -11,14 +11,14 @@ for non English (read: Japanese) speakers and is not intended as a
|
||||||
fork. So if you have any comments or updates for this file, please try
|
fork. So if you have any comments or updates for this file, please try
|
||||||
to update the original English file first.
|
to update the original English file first.
|
||||||
|
|
||||||
Last Updated: 2007/11/16
|
Last Updated: 2008/08/21
|
||||||
==================================
|
==================================
|
||||||
これは、
|
これは、
|
||||||
linux-2.6.24/Documentation/HOWTO
|
linux-2.6.27/Documentation/HOWTO
|
||||||
の和訳です。
|
の和訳です。
|
||||||
|
|
||||||
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
|
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
|
||||||
翻訳日: 2007/11/10
|
翻訳日: 2008/8/5
|
||||||
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
|
翻訳者: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
|
||||||
校正者: 松倉さん <nbh--mats at nifty dot com>
|
校正者: 松倉さん <nbh--mats at nifty dot com>
|
||||||
小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
|
小林 雅典さん (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
|
||||||
|
@ -287,13 +287,15 @@ Linux カーネルの開発プロセスは現在幾つかの異なるメイン
|
||||||
に安定した状態にあると判断したときにリリースされます。目標は毎週新
|
に安定した状態にあると判断したときにリリースされます。目標は毎週新
|
||||||
しい -rc カーネルをリリースすることです。
|
しい -rc カーネルをリリースすることです。
|
||||||
|
|
||||||
- 以下の URL で各 -rc リリースに存在する既知の後戻り問題のリスト
|
|
||||||
が追跡されます-
|
|
||||||
http://kernelnewbies.org/known_regressions
|
|
||||||
|
|
||||||
- このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
|
- このプロセスはカーネルが 「準備ができた」と考えられるまで継続しま
|
||||||
す。このプロセスはだいたい 6週間継続します。
|
す。このプロセスはだいたい 6週間継続します。
|
||||||
|
|
||||||
|
- 各リリースでの既知の後戻り問題(regression: このリリースの中で新規
|
||||||
|
に作り込まれた問題を指す) はその都度 Linux-kernel メーリングリスト
|
||||||
|
に投稿されます。ゴールとしては、カーネルが 「準備ができた」と宣言
|
||||||
|
する前にこのリストの長さをゼロに減らすことですが、現実には、数個の
|
||||||
|
後戻り問題がリリース時にたびたび残ってしまいます。
|
||||||
|
|
||||||
Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ
|
Andrew Morton が Linux-kernel メーリングリストにカーネルリリースについ
|
||||||
て書いたことをここで言っておくことは価値があります-
|
て書いたことをここで言っておくことは価値があります-
|
||||||
「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現
|
「カーネルがいつリリースされるかは誰も知りません。なぜなら、これは現
|
||||||
|
@ -303,18 +305,20 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー
|
||||||
2.6.x.y -stable カーネルツリー
|
2.6.x.y -stable カーネルツリー
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
バージョンに4つ目の数字がついたカーネルは -stable カーネルです。これに
|
バージョン番号が4つの数字に分かれているカーネルは -stable カーネルです。
|
||||||
は、2.6.x カーネルで見つかったセキュリティ問題や重大な後戻りに対する比
|
これには、2.6.x カーネルで見つかったセキュリティ問題や重大な後戻りに対
|
||||||
較的小さい重要な修正が含まれます。
|
する比較的小さい重要な修正が含まれます。
|
||||||
|
|
||||||
これは、開発/実験的バージョンのテストに協力することに興味が無く、
|
これは、開発/実験的バージョンのテストに協力することに興味が無く、
|
||||||
最新の安定したカーネルを使いたいユーザに推奨するブランチです。
|
最新の安定したカーネルを使いたいユーザに推奨するブランチです。
|
||||||
|
|
||||||
もし、2.6.x.y カーネルが存在しない場合には、番号が一番大きい 2.6.x
|
もし、2.6.x.y カーネルが存在しない場合には、番号が一番大きい 2.6.x が
|
||||||
が最新の安定版カーネルです。
|
最新の安定版カーネルです。
|
||||||
|
|
||||||
2.6.x.y は "stable" チーム <stable@kernel.org> でメンテされており、だ
|
2.6.x.y は "stable" チーム <stable@kernel.org> でメンテされており、必
|
||||||
いたい隔週でリリースされています。
|
要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ
|
||||||
|
た問題がなければもう少し長くなることもあります。セキュリティ関連の問題
|
||||||
|
の場合はこれに対してだいたいの場合、すぐにリリースがされます。
|
||||||
|
|
||||||
カーネルツリーに入っている、Documentation/stable_kernel_rules.txt ファ
|
カーネルツリーに入っている、Documentation/stable_kernel_rules.txt ファ
|
||||||
イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ
|
イルにはどのような種類の変更が -stable ツリーに受け入れ可能か、またリ
|
||||||
|
@ -341,7 +345,9 @@ linux-kernel メーリングリストで収集された多数のパッチと同
|
||||||
メインラインへ入れるように Linus にプッシュします。
|
メインラインへ入れるように Linus にプッシュします。
|
||||||
|
|
||||||
メインカーネルツリーに含めるために Linus に送る前に、すべての新しいパッ
|
メインカーネルツリーに含めるために Linus に送る前に、すべての新しいパッ
|
||||||
チが -mm ツリーでテストされることが強く推奨されます。
|
チが -mm ツリーでテストされることが強く推奨されています。マージウィン
|
||||||
|
ドウが開く前に -mm ツリーに現れなかったパッチはメインラインにマージさ
|
||||||
|
れることは困難になります。
|
||||||
|
|
||||||
これらのカーネルは安定して動作すべきシステムとして使うのには適切ではあ
|
これらのカーネルは安定して動作すべきシステムとして使うのには適切ではあ
|
||||||
りませんし、カーネルブランチの中でももっとも動作にリスクが高いものです。
|
りませんし、カーネルブランチの中でももっとも動作にリスクが高いものです。
|
||||||
|
@ -395,13 +401,15 @@ linux-kernel メーリングリストで収集された多数のパッチと同
|
||||||
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
|
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
|
git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
|
||||||
|
|
||||||
- SCSI, James Bottomley <James.Bottomley@SteelEye.com>
|
- SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
|
||||||
git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
|
git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
|
||||||
|
|
||||||
|
- x86, Ingo Molnar <mingo@elte.hu>
|
||||||
|
git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
|
||||||
|
|
||||||
quilt ツリー-
|
quilt ツリー-
|
||||||
- USB, PCI ドライバコアと I2C, Greg Kroah-Hartman <gregkh@suse.de>
|
- USB, ドライバコアと I2C, Greg Kroah-Hartman <gregkh@suse.de>
|
||||||
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
|
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
|
||||||
- x86-64 と i386 の仲間 Andi Kleen <ak@suse.de>
|
|
||||||
|
|
||||||
その他のカーネルツリーは http://git.kernel.org/ と MAINTAINERS ファ
|
その他のカーネルツリーは http://git.kernel.org/ と MAINTAINERS ファ
|
||||||
イルに一覧表があります。
|
イルに一覧表があります。
|
||||||
|
@ -412,13 +420,32 @@ linux-kernel メーリングリストで収集された多数のパッチと同
|
||||||
bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
|
bugzilla.kernel.org は Linux カーネル開発者がカーネルのバグを追跡する
|
||||||
場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。
|
場所です。ユーザは見つけたバグの全てをこのツールで報告すべきです。
|
||||||
どう kernel bugzilla を使うかの詳細は、以下を参照してください-
|
どう kernel bugzilla を使うかの詳細は、以下を参照してください-
|
||||||
http://test.kernel.org/bugzilla/faq.html
|
http://bugzilla.kernel.org/page.cgi?id=faq.html
|
||||||
|
|
||||||
メインカーネルソースディレクトリにあるファイル REPORTING-BUGS はカーネ
|
メインカーネルソースディレクトリにあるファイル REPORTING-BUGS はカーネ
|
||||||
ルバグらしいものについてどうレポートするかの良いテンプレートであり、問
|
ルバグらしいものについてどうレポートするかの良いテンプレートであり、問
|
||||||
題の追跡を助けるためにカーネル開発者にとってどんな情報が必要なのかの詳
|
題の追跡を助けるためにカーネル開発者にとってどんな情報が必要なのかの詳
|
||||||
細が書かれています。
|
細が書かれています。
|
||||||
|
|
||||||
|
バグレポートの管理
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
あなたのハッキングのスキルを訓練する最高の方法のひとつに、他人がレポー
|
||||||
|
トしたバグを修正することがあります。あなたがカーネルをより安定化させる
|
||||||
|
こに寄与するということだけでなく、あなたは 現実の問題を修正することを
|
||||||
|
学び、自分のスキルも強化でき、また他の開発者があなたの存在に気がつき
|
||||||
|
ます。バグを修正することは、多くの開発者の中から自分が功績をあげる最善
|
||||||
|
の道です、なぜなら多くの人は他人のバグの修正に時間を浪費することを好ま
|
||||||
|
ないからです。
|
||||||
|
|
||||||
|
すでにレポートされたバグのために仕事をするためには、
|
||||||
|
http://bugzilla.kernel.org に行ってください。もし今後のバグレポートに
|
||||||
|
ついてアドバイスを受けたいのであれば、bugme-new メーリングリスト(新し
|
||||||
|
いバグレポートだけがここにメールされる) または bugme-janitor メーリン
|
||||||
|
グリスト(bugzilla の変更毎にここにメールされる)を購読できます。
|
||||||
|
|
||||||
|
http://lists.linux-foundation.org/mailman/listinfo/bugme-new
|
||||||
|
http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
|
||||||
|
|
||||||
メーリングリスト
|
メーリングリスト
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
111
Documentation/ja_JP/SubmitChecklist
Normal file
111
Documentation/ja_JP/SubmitChecklist
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
NOTE:
|
||||||
|
This is a version of Documentation/SubmitChecklist into Japanese.
|
||||||
|
This document is maintained by Takenori Nagano <t-nagano@ah.jp.nec.com>
|
||||||
|
and the JF Project team <http://www.linux.or.jp/JF/>.
|
||||||
|
If you find any difference between this document and the original file
|
||||||
|
or a problem with the translation,
|
||||||
|
please contact the maintainer of this file or JF project.
|
||||||
|
|
||||||
|
Please also note that the purpose of this file is to be easier to read
|
||||||
|
for non English (read: Japanese) speakers and is not intended as a
|
||||||
|
fork. So if you have any comments or updates of this file, please try
|
||||||
|
to update the original English file first.
|
||||||
|
|
||||||
|
Last Updated: 2008/07/14
|
||||||
|
==================================
|
||||||
|
これは、
|
||||||
|
linux-2.6.26/Documentation/SubmitChecklist の和訳です。
|
||||||
|
|
||||||
|
翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
|
||||||
|
翻訳日: 2008/07/14
|
||||||
|
翻訳者: Takenori Nagano <t-nagano at ah dot jp dot nec dot com>
|
||||||
|
校正者: Masanori Kobayashi さん <zap03216 at nifty dot ne dot jp>
|
||||||
|
==================================
|
||||||
|
|
||||||
|
|
||||||
|
Linux カーネルパッチ投稿者向けチェックリスト
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
本書では、パッチをより素早く取り込んでもらいたい開発者が実践すべき基本的な事柄
|
||||||
|
をいくつか紹介します。ここにある全ての事柄は、Documentation/SubmittingPatches
|
||||||
|
などのLinuxカーネルパッチ投稿に際しての心得を補足するものです。
|
||||||
|
|
||||||
|
1: 妥当なCONFIGオプションや変更されたCONFIGオプション、つまり =y, =m, =n
|
||||||
|
全てで正しくビルドできることを確認してください。その際、gcc及びリンカが
|
||||||
|
warningやerrorを出していないことも確認してください。
|
||||||
|
|
||||||
|
2: allnoconfig, allmodconfig オプションを用いて正しくビルドできることを
|
||||||
|
確認してください。
|
||||||
|
|
||||||
|
3: 手許のクロスコンパイルツールやOSDLのPLMのようなものを用いて、複数の
|
||||||
|
アーキテクチャにおいても正しくビルドできることを確認してください。
|
||||||
|
|
||||||
|
4: 64bit長の'unsigned long'を使用しているppc64は、クロスコンパイルでの
|
||||||
|
チェックに適当なアーキテクチャです。
|
||||||
|
|
||||||
|
5: カーネルコーディングスタイルに準拠しているかどうか確認してください(!)
|
||||||
|
|
||||||
|
6: CONFIGオプションの追加・変更をした場合には、CONFIGメニューが壊れていない
|
||||||
|
ことを確認してください。
|
||||||
|
|
||||||
|
7: 新しくKconfigのオプションを追加する際には、必ずそのhelpも記述してください。
|
||||||
|
|
||||||
|
8: 適切なKconfigの依存関係を考えながら慎重にチェックしてください。
|
||||||
|
ただし、この作業はマシンを使ったテストできちんと行うのがとても困難です。
|
||||||
|
うまくやるには、自分の頭で考えることです。
|
||||||
|
|
||||||
|
9: sparseを利用してちゃんとしたコードチェックをしてください。
|
||||||
|
|
||||||
|
10: 'make checkstack' と 'make namespacecheck' を利用し、問題が発見されたら
|
||||||
|
修正してください。'make checkstack' は明示的に問題を示しませんが、どれか
|
||||||
|
1つの関数が512バイトより大きいスタックを使っていれば、修正すべき候補と
|
||||||
|
なります。
|
||||||
|
|
||||||
|
11: グローバルなkernel API を説明する kernel-doc をソースの中に含めてください。
|
||||||
|
( staticな関数においては必須ではありませんが、含めてもらっても結構です )
|
||||||
|
そして、'make htmldocs' もしくは 'make mandocs' を利用して追記した
|
||||||
|
ドキュメントのチェックを行い、問題が見つかった場合には修正を行ってください。
|
||||||
|
|
||||||
|
12: CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, CONFIG_DEBUG_SLAB,
|
||||||
|
CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, CONFIG_DEBUG_SPINLOCK,
|
||||||
|
CONFIG_DEBUG_SPINLOCK_SLEEP これら全てを同時に有効にして動作確認を
|
||||||
|
行ってください。
|
||||||
|
|
||||||
|
13: CONFIG_SMP, CONFIG_PREEMPT を有効にした場合と無効にした場合の両方で
|
||||||
|
ビルドした上、動作確認を行ってください。
|
||||||
|
|
||||||
|
14: もしパッチがディスクのI/O性能などに影響を与えるようであれば、
|
||||||
|
'CONFIG_LBD'オプションを有効にした場合と無効にした場合の両方で
|
||||||
|
テストを実施してみてください。
|
||||||
|
|
||||||
|
15: lockdepの機能を全て有効にした上で、全てのコードパスを評価してください。
|
||||||
|
|
||||||
|
16: /proc に新しいエントリを追加した場合には、Documentation/ 配下に
|
||||||
|
必ずドキュメントを追加してください。
|
||||||
|
|
||||||
|
17: 新しいブートパラメータを追加した場合には、
|
||||||
|
必ずDocumentation/kernel-parameters.txt に説明を追加してください。
|
||||||
|
|
||||||
|
18: 新しくmoduleにパラメータを追加した場合には、MODULE_PARM_DESC()を
|
||||||
|
利用して必ずその説明を記述してください。
|
||||||
|
|
||||||
|
19: 新しいuserspaceインタフェースを作成した場合には、Documentation/ABI/ に
|
||||||
|
Documentation/ABI/README を参考にして必ずドキュメントを追加してください。
|
||||||
|
|
||||||
|
20: 'make headers_check'を実行して全く問題がないことを確認してください。
|
||||||
|
|
||||||
|
21: 少なくともslabアロケーションとpageアロケーションに失敗した場合の
|
||||||
|
挙動について、fault-injectionを利用して確認してください。
|
||||||
|
Documentation/fault-injection/ を参照してください。
|
||||||
|
|
||||||
|
追加したコードがかなりの量であったならば、サブシステム特有の
|
||||||
|
fault-injectionを追加したほうが良いかもしれません。
|
||||||
|
|
||||||
|
22: 新たに追加したコードは、`gcc -W'でコンパイルしてください。
|
||||||
|
このオプションは大量の不要なメッセージを出力しますが、
|
||||||
|
"warning: comparison between signed and unsigned" のようなメッセージは、
|
||||||
|
バグを見つけるのに役に立ちます。
|
||||||
|
|
||||||
|
23: 投稿したパッチが -mm パッチセットにマージされた後、全ての既存のパッチや
|
||||||
|
VM, VFS およびその他のサブシステムに関する様々な変更と、現時点でも共存
|
||||||
|
できることを確認するテストを行ってください。
|
|
@ -65,26 +65,26 @@ Install kexec-tools
|
||||||
|
|
||||||
2) Download the kexec-tools user-space package from the following URL:
|
2) Download the kexec-tools user-space package from the following URL:
|
||||||
|
|
||||||
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools-testing.tar.gz
|
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/kexec-tools.tar.gz
|
||||||
|
|
||||||
This is a symlink to the latest version, which at the time of writing is
|
This is a symlink to the latest version.
|
||||||
20061214, the only release of kexec-tools-testing so far. As other versions
|
|
||||||
are released, the older ones will remain available at
|
|
||||||
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/
|
|
||||||
|
|
||||||
Note: Latest kexec-tools-testing git tree is available at
|
The latest kexec-tools git tree is available at:
|
||||||
|
|
||||||
git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools-testing.git
|
git://git.kernel.org/pub/scm/linux/kernel/git/horms/kexec-tools.git
|
||||||
or
|
or
|
||||||
http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools-testing.git;a=summary
|
http://www.kernel.org/git/?p=linux/kernel/git/horms/kexec-tools.git
|
||||||
|
|
||||||
|
More information about kexec-tools can be found at
|
||||||
|
http://www.kernel.org/pub/linux/kernel/people/horms/kexec-tools/README.html
|
||||||
|
|
||||||
3) Unpack the tarball with the tar command, as follows:
|
3) Unpack the tarball with the tar command, as follows:
|
||||||
|
|
||||||
tar xvpzf kexec-tools-testing.tar.gz
|
tar xvpzf kexec-tools.tar.gz
|
||||||
|
|
||||||
4) Change to the kexec-tools directory, as follows:
|
4) Change to the kexec-tools directory, as follows:
|
||||||
|
|
||||||
cd kexec-tools-testing-VERSION
|
cd kexec-tools-VERSION
|
||||||
|
|
||||||
5) Configure the package, as follows:
|
5) Configure the package, as follows:
|
||||||
|
|
||||||
|
|
|
@ -365,6 +365,8 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
no delay (0).
|
no delay (0).
|
||||||
Format: integer
|
Format: integer
|
||||||
|
|
||||||
|
bootmem_debug [KNL] Enable bootmem allocator debug messages.
|
||||||
|
|
||||||
bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards)
|
bttv.card= [HW,V4L] bttv (bt848 + bt878 based grabber cards)
|
||||||
bttv.radio= Most important insmod options are available as
|
bttv.radio= Most important insmod options are available as
|
||||||
kernel args too.
|
kernel args too.
|
||||||
|
@ -1072,6 +1074,9 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
|
|
||||||
* [no]ncq: Turn on or off NCQ.
|
* [no]ncq: Turn on or off NCQ.
|
||||||
|
|
||||||
|
* nohrst, nosrst, norst: suppress hard, soft
|
||||||
|
and both resets.
|
||||||
|
|
||||||
If there are multiple matching configurations changing
|
If there are multiple matching configurations changing
|
||||||
the same attribute, the last one is used.
|
the same attribute, the last one is used.
|
||||||
|
|
||||||
|
@ -2159,13 +2164,6 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
<deci-seconds>: poll all this frequency
|
<deci-seconds>: poll all this frequency
|
||||||
0: no polling (default)
|
0: no polling (default)
|
||||||
|
|
||||||
tipar.timeout= [HW,PPT]
|
|
||||||
Set communications timeout in tenths of a second
|
|
||||||
(default 15).
|
|
||||||
|
|
||||||
tipar.delay= [HW,PPT]
|
|
||||||
Set inter-bit delay in microseconds (default 10).
|
|
||||||
|
|
||||||
tmscsim= [HW,SCSI]
|
tmscsim= [HW,SCSI]
|
||||||
See comment before function dc390_setup() in
|
See comment before function dc390_setup() in
|
||||||
drivers/scsi/tmscsim.c.
|
drivers/scsi/tmscsim.c.
|
||||||
|
|
|
@ -864,7 +864,7 @@ payload contents" for more information.
|
||||||
request_key_with_auxdata() respectively.
|
request_key_with_auxdata() respectively.
|
||||||
|
|
||||||
These two functions return with the key potentially still under
|
These two functions return with the key potentially still under
|
||||||
construction. To wait for contruction completion, the following should be
|
construction. To wait for construction completion, the following should be
|
||||||
called:
|
called:
|
||||||
|
|
||||||
int wait_for_key_construction(struct key *key, bool intr);
|
int wait_for_key_construction(struct key *key, bool intr);
|
||||||
|
|
|
@ -44,7 +44,7 @@ detailed description):
|
||||||
- LCD brightness control
|
- LCD brightness control
|
||||||
- Volume control
|
- Volume control
|
||||||
- Fan control and monitoring: fan speed, fan enable/disable
|
- Fan control and monitoring: fan speed, fan enable/disable
|
||||||
- Experimental: WAN enable and disable
|
- WAN enable and disable
|
||||||
|
|
||||||
A compatibility table by model and feature is maintained on the web
|
A compatibility table by model and feature is maintained on the web
|
||||||
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
|
site, http://ibm-acpi.sf.net/. I appreciate any success or failure
|
||||||
|
@ -1375,18 +1375,13 @@ with EINVAL, try to set pwm1_enable to 1 and pwm1 to at least 128 (255
|
||||||
would be the safest choice, though).
|
would be the safest choice, though).
|
||||||
|
|
||||||
|
|
||||||
EXPERIMENTAL: WAN
|
WAN
|
||||||
-----------------
|
---
|
||||||
|
|
||||||
procfs: /proc/acpi/ibm/wan
|
procfs: /proc/acpi/ibm/wan
|
||||||
sysfs device attribute: wwan_enable (deprecated)
|
sysfs device attribute: wwan_enable (deprecated)
|
||||||
sysfs rfkill class: switch "tpacpi_wwan_sw"
|
sysfs rfkill class: switch "tpacpi_wwan_sw"
|
||||||
|
|
||||||
This feature is marked EXPERIMENTAL because the implementation
|
|
||||||
directly accesses hardware registers and may not work as expected. USE
|
|
||||||
WITH CAUTION! To use this feature, you need to supply the
|
|
||||||
experimental=1 parameter when loading the module.
|
|
||||||
|
|
||||||
This feature shows the presence and current state of a W-WAN (Sierra
|
This feature shows the presence and current state of a W-WAN (Sierra
|
||||||
Wireless EV-DO) device.
|
Wireless EV-DO) device.
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ Hardware accelerated blink of LEDs
|
||||||
|
|
||||||
Some LEDs can be programmed to blink without any CPU interaction. To
|
Some LEDs can be programmed to blink without any CPU interaction. To
|
||||||
support this feature, a LED driver can optionally implement the
|
support this feature, a LED driver can optionally implement the
|
||||||
blink_set() function (see <linux/leds.h>). If implemeted, triggers can
|
blink_set() function (see <linux/leds.h>). If implemented, triggers can
|
||||||
attempt to use it before falling back to software timers. The blink_set()
|
attempt to use it before falling back to software timers. The blink_set()
|
||||||
function should return 0 if the blink setting is supported, or -EINVAL
|
function should return 0 if the blink setting is supported, or -EINVAL
|
||||||
otherwise, which means that LED blinking will be handled by software.
|
otherwise, which means that LED blinking will be handled by software.
|
||||||
|
|
|
@ -36,11 +36,13 @@
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <signal.h>
|
||||||
#include "linux/lguest_launcher.h"
|
#include "linux/lguest_launcher.h"
|
||||||
#include "linux/virtio_config.h"
|
#include "linux/virtio_config.h"
|
||||||
#include "linux/virtio_net.h"
|
#include "linux/virtio_net.h"
|
||||||
#include "linux/virtio_blk.h"
|
#include "linux/virtio_blk.h"
|
||||||
#include "linux/virtio_console.h"
|
#include "linux/virtio_console.h"
|
||||||
|
#include "linux/virtio_rng.h"
|
||||||
#include "linux/virtio_ring.h"
|
#include "linux/virtio_ring.h"
|
||||||
#include "asm-x86/bootparam.h"
|
#include "asm-x86/bootparam.h"
|
||||||
/*L:110 We can ignore the 39 include files we need for this program, but I do
|
/*L:110 We can ignore the 39 include files we need for this program, but I do
|
||||||
|
@ -64,8 +66,8 @@ typedef uint8_t u8;
|
||||||
#endif
|
#endif
|
||||||
/* We can have up to 256 pages for devices. */
|
/* We can have up to 256 pages for devices. */
|
||||||
#define DEVICE_PAGES 256
|
#define DEVICE_PAGES 256
|
||||||
/* This will occupy 2 pages: it must be a power of 2. */
|
/* This will occupy 3 pages: it must be a power of 2. */
|
||||||
#define VIRTQUEUE_NUM 128
|
#define VIRTQUEUE_NUM 256
|
||||||
|
|
||||||
/*L:120 verbose is both a global flag and a macro. The C preprocessor allows
|
/*L:120 verbose is both a global flag and a macro. The C preprocessor allows
|
||||||
* this, and although I wouldn't recommend it, it works quite nicely here. */
|
* this, and although I wouldn't recommend it, it works quite nicely here. */
|
||||||
|
@ -74,12 +76,19 @@ static bool verbose;
|
||||||
do { if (verbose) printf(args); } while(0)
|
do { if (verbose) printf(args); } while(0)
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
||||||
/* The pipe to send commands to the waker process */
|
/* File descriptors for the Waker. */
|
||||||
static int waker_fd;
|
struct {
|
||||||
|
int pipe[2];
|
||||||
|
int lguest_fd;
|
||||||
|
} waker_fds;
|
||||||
|
|
||||||
/* The pointer to the start of guest memory. */
|
/* The pointer to the start of guest memory. */
|
||||||
static void *guest_base;
|
static void *guest_base;
|
||||||
/* The maximum guest physical address allowed, and maximum possible. */
|
/* The maximum guest physical address allowed, and maximum possible. */
|
||||||
static unsigned long guest_limit, guest_max;
|
static unsigned long guest_limit, guest_max;
|
||||||
|
/* The pipe for signal hander to write to. */
|
||||||
|
static int timeoutpipe[2];
|
||||||
|
static unsigned int timeout_usec = 500;
|
||||||
|
|
||||||
/* a per-cpu variable indicating whose vcpu is currently running */
|
/* a per-cpu variable indicating whose vcpu is currently running */
|
||||||
static unsigned int __thread cpu_id;
|
static unsigned int __thread cpu_id;
|
||||||
|
@ -155,11 +164,14 @@ struct virtqueue
|
||||||
/* Last available index we saw. */
|
/* Last available index we saw. */
|
||||||
u16 last_avail_idx;
|
u16 last_avail_idx;
|
||||||
|
|
||||||
/* The routine to call when the Guest pings us. */
|
/* The routine to call when the Guest pings us, or timeout. */
|
||||||
void (*handle_output)(int fd, struct virtqueue *me);
|
void (*handle_output)(int fd, struct virtqueue *me, bool timeout);
|
||||||
|
|
||||||
/* Outstanding buffers */
|
/* Outstanding buffers */
|
||||||
unsigned int inflight;
|
unsigned int inflight;
|
||||||
|
|
||||||
|
/* Is this blocked awaiting a timer? */
|
||||||
|
bool blocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Remember the arguments to the program so we can "reboot" */
|
/* Remember the arguments to the program so we can "reboot" */
|
||||||
|
@ -190,6 +202,9 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
|
||||||
return iov->iov_base;
|
return iov->iov_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wrapper for the last available index. Makes it easier to change. */
|
||||||
|
#define lg_last_avail(vq) ((vq)->last_avail_idx)
|
||||||
|
|
||||||
/* The virtio configuration space is defined to be little-endian. x86 is
|
/* The virtio configuration space is defined to be little-endian. x86 is
|
||||||
* little-endian too, but it's nice to be explicit so we have these helpers. */
|
* little-endian too, but it's nice to be explicit so we have these helpers. */
|
||||||
#define cpu_to_le16(v16) (v16)
|
#define cpu_to_le16(v16) (v16)
|
||||||
|
@ -199,6 +214,33 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
|
||||||
#define le32_to_cpu(v32) (v32)
|
#define le32_to_cpu(v32) (v32)
|
||||||
#define le64_to_cpu(v64) (v64)
|
#define le64_to_cpu(v64) (v64)
|
||||||
|
|
||||||
|
/* Is this iovec empty? */
|
||||||
|
static bool iov_empty(const struct iovec iov[], unsigned int num_iov)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_iov; i++)
|
||||||
|
if (iov[i].iov_len)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take len bytes from the front of this iovec. */
|
||||||
|
static void iov_consume(struct iovec iov[], unsigned num_iov, unsigned len)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_iov; i++) {
|
||||||
|
unsigned int used;
|
||||||
|
|
||||||
|
used = iov[i].iov_len < len ? iov[i].iov_len : len;
|
||||||
|
iov[i].iov_base += used;
|
||||||
|
iov[i].iov_len -= used;
|
||||||
|
len -= used;
|
||||||
|
}
|
||||||
|
assert(len == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* The device virtqueue descriptors are followed by feature bitmasks. */
|
/* The device virtqueue descriptors are followed by feature bitmasks. */
|
||||||
static u8 *get_feature_bits(struct device *dev)
|
static u8 *get_feature_bits(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -254,6 +296,7 @@ static void *map_zeroed_pages(unsigned int num)
|
||||||
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
|
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||||
if (addr == MAP_FAILED)
|
if (addr == MAP_FAILED)
|
||||||
err(1, "Mmaping %u pages of /dev/zero", num);
|
err(1, "Mmaping %u pages of /dev/zero", num);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
@ -540,69 +583,64 @@ static void add_device_fd(int fd)
|
||||||
* watch, but handing a file descriptor mask through to the kernel is fairly
|
* watch, but handing a file descriptor mask through to the kernel is fairly
|
||||||
* icky.
|
* icky.
|
||||||
*
|
*
|
||||||
* Instead, we fork off a process which watches the file descriptors and writes
|
* Instead, we clone off a thread which watches the file descriptors and writes
|
||||||
* the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
|
* the LHREQ_BREAK command to the /dev/lguest file descriptor to tell the Host
|
||||||
* stop running the Guest. This causes the Launcher to return from the
|
* stop running the Guest. This causes the Launcher to return from the
|
||||||
* /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
|
* /dev/lguest read with -EAGAIN, where it will write to /dev/lguest to reset
|
||||||
* the LHREQ_BREAK and wake us up again.
|
* the LHREQ_BREAK and wake us up again.
|
||||||
*
|
*
|
||||||
* This, of course, is merely a different *kind* of icky.
|
* This, of course, is merely a different *kind* of icky.
|
||||||
|
*
|
||||||
|
* Given my well-known antipathy to threads, I'd prefer to use processes. But
|
||||||
|
* it's easier to share Guest memory with threads, and trivial to share the
|
||||||
|
* devices.infds as the Launcher changes it.
|
||||||
*/
|
*/
|
||||||
static void wake_parent(int pipefd, int lguest_fd)
|
static int waker(void *unused)
|
||||||
{
|
{
|
||||||
/* Add the pipe from the Launcher to the fdset in the device_list, so
|
/* Close the write end of the pipe: only the Launcher has it open. */
|
||||||
* we watch it, too. */
|
close(waker_fds.pipe[1]);
|
||||||
add_device_fd(pipefd);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd_set rfds = devices.infds;
|
fd_set rfds = devices.infds;
|
||||||
unsigned long args[] = { LHREQ_BREAK, 1 };
|
unsigned long args[] = { LHREQ_BREAK, 1 };
|
||||||
|
unsigned int maxfd = devices.max_infd;
|
||||||
|
|
||||||
|
/* We also listen to the pipe from the Launcher. */
|
||||||
|
FD_SET(waker_fds.pipe[0], &rfds);
|
||||||
|
if (waker_fds.pipe[0] > maxfd)
|
||||||
|
maxfd = waker_fds.pipe[0];
|
||||||
|
|
||||||
/* Wait until input is ready from one of the devices. */
|
/* Wait until input is ready from one of the devices. */
|
||||||
select(devices.max_infd+1, &rfds, NULL, NULL, NULL);
|
select(maxfd+1, &rfds, NULL, NULL, NULL);
|
||||||
/* Is it a message from the Launcher? */
|
|
||||||
if (FD_ISSET(pipefd, &rfds)) {
|
/* Message from Launcher? */
|
||||||
int fd;
|
if (FD_ISSET(waker_fds.pipe[0], &rfds)) {
|
||||||
/* If read() returns 0, it means the Launcher has
|
char c;
|
||||||
* exited. We silently follow. */
|
/* If this fails, then assume Launcher has exited.
|
||||||
if (read(pipefd, &fd, sizeof(fd)) == 0)
|
* Don't do anything on exit: we're just a thread! */
|
||||||
exit(0);
|
if (read(waker_fds.pipe[0], &c, 1) != 1)
|
||||||
/* Otherwise it's telling us to change what file
|
_exit(0);
|
||||||
* descriptors we're to listen to. Positive means
|
continue;
|
||||||
* listen to a new one, negative means stop
|
|
||||||
* listening. */
|
|
||||||
if (fd >= 0)
|
|
||||||
FD_SET(fd, &devices.infds);
|
|
||||||
else
|
|
||||||
FD_CLR(-fd - 1, &devices.infds);
|
|
||||||
} else /* Send LHREQ_BREAK command. */
|
|
||||||
pwrite(lguest_fd, args, sizeof(args), cpu_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Send LHREQ_BREAK command to snap the Launcher out of it. */
|
||||||
|
pwrite(waker_fds.lguest_fd, args, sizeof(args), cpu_id);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This routine just sets up a pipe to the Waker process. */
|
/* This routine just sets up a pipe to the Waker process. */
|
||||||
static int setup_waker(int lguest_fd)
|
static void setup_waker(int lguest_fd)
|
||||||
{
|
{
|
||||||
int pipefd[2], child;
|
/* This pipe is closed when Launcher dies, telling Waker. */
|
||||||
|
if (pipe(waker_fds.pipe) != 0)
|
||||||
|
err(1, "Creating pipe for Waker");
|
||||||
|
|
||||||
/* We create a pipe to talk to the Waker, and also so it knows when the
|
/* Waker also needs to know the lguest fd */
|
||||||
* Launcher dies (and closes pipe). */
|
waker_fds.lguest_fd = lguest_fd;
|
||||||
pipe(pipefd);
|
|
||||||
child = fork();
|
|
||||||
if (child == -1)
|
|
||||||
err(1, "forking");
|
|
||||||
|
|
||||||
if (child == 0) {
|
if (clone(waker, malloc(4096) + 4096, CLONE_VM | SIGCHLD, NULL) == -1)
|
||||||
/* We are the Waker: close the "writing" end of our copy of the
|
err(1, "Creating Waker");
|
||||||
* pipe and start waiting for input. */
|
|
||||||
close(pipefd[1]);
|
|
||||||
wake_parent(pipefd[0], lguest_fd);
|
|
||||||
}
|
|
||||||
/* Close the reading end of our copy of the pipe. */
|
|
||||||
close(pipefd[0]);
|
|
||||||
|
|
||||||
/* Here is the fd used to talk to the waker. */
|
|
||||||
return pipefd[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -661,19 +699,22 @@ static unsigned get_vq_desc(struct virtqueue *vq,
|
||||||
unsigned int *out_num, unsigned int *in_num)
|
unsigned int *out_num, unsigned int *in_num)
|
||||||
{
|
{
|
||||||
unsigned int i, head;
|
unsigned int i, head;
|
||||||
|
u16 last_avail;
|
||||||
|
|
||||||
/* Check it isn't doing very strange things with descriptor numbers. */
|
/* Check it isn't doing very strange things with descriptor numbers. */
|
||||||
if ((u16)(vq->vring.avail->idx - vq->last_avail_idx) > vq->vring.num)
|
last_avail = lg_last_avail(vq);
|
||||||
|
if ((u16)(vq->vring.avail->idx - last_avail) > vq->vring.num)
|
||||||
errx(1, "Guest moved used index from %u to %u",
|
errx(1, "Guest moved used index from %u to %u",
|
||||||
vq->last_avail_idx, vq->vring.avail->idx);
|
last_avail, vq->vring.avail->idx);
|
||||||
|
|
||||||
/* If there's nothing new since last we looked, return invalid. */
|
/* If there's nothing new since last we looked, return invalid. */
|
||||||
if (vq->vring.avail->idx == vq->last_avail_idx)
|
if (vq->vring.avail->idx == last_avail)
|
||||||
return vq->vring.num;
|
return vq->vring.num;
|
||||||
|
|
||||||
/* Grab the next descriptor number they're advertising, and increment
|
/* Grab the next descriptor number they're advertising, and increment
|
||||||
* the index we've seen. */
|
* the index we've seen. */
|
||||||
head = vq->vring.avail->ring[vq->last_avail_idx++ % vq->vring.num];
|
head = vq->vring.avail->ring[last_avail % vq->vring.num];
|
||||||
|
lg_last_avail(vq)++;
|
||||||
|
|
||||||
/* If their number is silly, that's a fatal mistake. */
|
/* If their number is silly, that's a fatal mistake. */
|
||||||
if (head >= vq->vring.num)
|
if (head >= vq->vring.num)
|
||||||
|
@ -821,8 +862,8 @@ static bool handle_console_input(int fd, struct device *dev)
|
||||||
unsigned long args[] = { LHREQ_BREAK, 0 };
|
unsigned long args[] = { LHREQ_BREAK, 0 };
|
||||||
/* Close the fd so Waker will know it has to
|
/* Close the fd so Waker will know it has to
|
||||||
* exit. */
|
* exit. */
|
||||||
close(waker_fd);
|
close(waker_fds.pipe[1]);
|
||||||
/* Just in case waker is blocked in BREAK, send
|
/* Just in case Waker is blocked in BREAK, send
|
||||||
* unbreak now. */
|
* unbreak now. */
|
||||||
write(fd, args, sizeof(args));
|
write(fd, args, sizeof(args));
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -839,7 +880,7 @@ static bool handle_console_input(int fd, struct device *dev)
|
||||||
|
|
||||||
/* Handling output for console is simple: we just get all the output buffers
|
/* Handling output for console is simple: we just get all the output buffers
|
||||||
* and write them to stdout. */
|
* and write them to stdout. */
|
||||||
static void handle_console_output(int fd, struct virtqueue *vq)
|
static void handle_console_output(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
unsigned int head, out, in;
|
unsigned int head, out, in;
|
||||||
int len;
|
int len;
|
||||||
|
@ -854,6 +895,24 @@ static void handle_console_output(int fd, struct virtqueue *vq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is called when we no longer want to hear about Guest changes to a
|
||||||
|
* virtqueue. This is more efficient in high-traffic cases, but it means we
|
||||||
|
* have to set a timer to check if any more changes have occurred. */
|
||||||
|
static void block_vq(struct virtqueue *vq)
|
||||||
|
{
|
||||||
|
struct itimerval itm;
|
||||||
|
|
||||||
|
vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
|
vq->blocked = true;
|
||||||
|
|
||||||
|
itm.it_interval.tv_sec = 0;
|
||||||
|
itm.it_interval.tv_usec = 0;
|
||||||
|
itm.it_value.tv_sec = 0;
|
||||||
|
itm.it_value.tv_usec = timeout_usec;
|
||||||
|
|
||||||
|
setitimer(ITIMER_REAL, &itm, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Network
|
* The Network
|
||||||
*
|
*
|
||||||
|
@ -861,22 +920,39 @@ static void handle_console_output(int fd, struct virtqueue *vq)
|
||||||
* and write them (ignoring the first element) to this device's file descriptor
|
* and write them (ignoring the first element) to this device's file descriptor
|
||||||
* (/dev/net/tun).
|
* (/dev/net/tun).
|
||||||
*/
|
*/
|
||||||
static void handle_net_output(int fd, struct virtqueue *vq)
|
static void handle_net_output(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
unsigned int head, out, in;
|
unsigned int head, out, in, num = 0;
|
||||||
int len;
|
int len;
|
||||||
struct iovec iov[vq->vring.num];
|
struct iovec iov[vq->vring.num];
|
||||||
|
static int last_timeout_num;
|
||||||
|
|
||||||
/* Keep getting output buffers from the Guest until we run out. */
|
/* Keep getting output buffers from the Guest until we run out. */
|
||||||
while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
|
while ((head = get_vq_desc(vq, iov, &out, &in)) != vq->vring.num) {
|
||||||
if (in)
|
if (in)
|
||||||
errx(1, "Input buffers in output queue?");
|
errx(1, "Input buffers in output queue?");
|
||||||
/* Check header, but otherwise ignore it (we told the Guest we
|
len = writev(vq->dev->fd, iov, out);
|
||||||
* supported no features, so it shouldn't have anything
|
if (len < 0)
|
||||||
* interesting). */
|
err(1, "Writing network packet to tun");
|
||||||
(void)convert(&iov[0], struct virtio_net_hdr);
|
|
||||||
len = writev(vq->dev->fd, iov+1, out-1);
|
|
||||||
add_used_and_trigger(fd, vq, head, len);
|
add_used_and_trigger(fd, vq, head, len);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Block further kicks and set up a timer if we saw anything. */
|
||||||
|
if (!timeout && num)
|
||||||
|
block_vq(vq);
|
||||||
|
|
||||||
|
/* We never quite know how long should we wait before we check the
|
||||||
|
* queue again for more packets. We start at 500 microseconds, and if
|
||||||
|
* we get fewer packets than last time, we assume we made the timeout
|
||||||
|
* too small and increase it by 10 microseconds. Otherwise, we drop it
|
||||||
|
* by one microsecond every time. It seems to work well enough. */
|
||||||
|
if (timeout) {
|
||||||
|
if (num < last_timeout_num)
|
||||||
|
timeout_usec += 10;
|
||||||
|
else if (timeout_usec > 1)
|
||||||
|
timeout_usec--;
|
||||||
|
last_timeout_num = num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,7 +963,6 @@ static bool handle_tun_input(int fd, struct device *dev)
|
||||||
unsigned int head, in_num, out_num;
|
unsigned int head, in_num, out_num;
|
||||||
int len;
|
int len;
|
||||||
struct iovec iov[dev->vq->vring.num];
|
struct iovec iov[dev->vq->vring.num];
|
||||||
struct virtio_net_hdr *hdr;
|
|
||||||
|
|
||||||
/* First we need a network buffer from the Guests's recv virtqueue. */
|
/* First we need a network buffer from the Guests's recv virtqueue. */
|
||||||
head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
|
head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
|
||||||
|
@ -896,25 +971,23 @@ static bool handle_tun_input(int fd, struct device *dev)
|
||||||
* early, the Guest won't be ready yet. Wait until the device
|
* early, the Guest won't be ready yet. Wait until the device
|
||||||
* status says it's ready. */
|
* status says it's ready. */
|
||||||
/* FIXME: Actually want DRIVER_ACTIVE here. */
|
/* FIXME: Actually want DRIVER_ACTIVE here. */
|
||||||
if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK)
|
|
||||||
warn("network: no dma buffer!");
|
/* Now tell it we want to know if new things appear. */
|
||||||
|
dev->vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
|
||||||
|
wmb();
|
||||||
|
|
||||||
/* We'll turn this back on if input buffers are registered. */
|
/* We'll turn this back on if input buffers are registered. */
|
||||||
return false;
|
return false;
|
||||||
} else if (out_num)
|
} else if (out_num)
|
||||||
errx(1, "Output buffers in network recv queue?");
|
errx(1, "Output buffers in network recv queue?");
|
||||||
|
|
||||||
/* First element is the header: we set it to 0 (no features). */
|
|
||||||
hdr = convert(&iov[0], struct virtio_net_hdr);
|
|
||||||
hdr->flags = 0;
|
|
||||||
hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
|
|
||||||
|
|
||||||
/* Read the packet from the device directly into the Guest's buffer. */
|
/* Read the packet from the device directly into the Guest's buffer. */
|
||||||
len = readv(dev->fd, iov+1, in_num-1);
|
len = readv(dev->fd, iov, in_num);
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
err(1, "reading network");
|
err(1, "reading network");
|
||||||
|
|
||||||
/* Tell the Guest about the new packet. */
|
/* Tell the Guest about the new packet. */
|
||||||
add_used_and_trigger(fd, dev->vq, head, sizeof(*hdr) + len);
|
add_used_and_trigger(fd, dev->vq, head, len);
|
||||||
|
|
||||||
verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
|
verbose("tun input packet len %i [%02x %02x] (%s)\n", len,
|
||||||
((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
|
((u8 *)iov[1].iov_base)[0], ((u8 *)iov[1].iov_base)[1],
|
||||||
|
@ -927,11 +1000,18 @@ static bool handle_tun_input(int fd, struct device *dev)
|
||||||
/*L:215 This is the callback attached to the network and console input
|
/*L:215 This is the callback attached to the network and console input
|
||||||
* virtqueues: it ensures we try again, in case we stopped console or net
|
* virtqueues: it ensures we try again, in case we stopped console or net
|
||||||
* delivery because Guest didn't have any buffers. */
|
* delivery because Guest didn't have any buffers. */
|
||||||
static void enable_fd(int fd, struct virtqueue *vq)
|
static void enable_fd(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
add_device_fd(vq->dev->fd);
|
add_device_fd(vq->dev->fd);
|
||||||
/* Tell waker to listen to it again */
|
/* Snap the Waker out of its select loop. */
|
||||||
write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
|
write(waker_fds.pipe[1], "", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_enable_fd(int fd, struct virtqueue *vq, bool timeout)
|
||||||
|
{
|
||||||
|
/* We don't need to know again when Guest refills receive buffer. */
|
||||||
|
vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
|
||||||
|
enable_fd(fd, vq, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the Guest tells us they updated the status field, we handle it. */
|
/* When the Guest tells us they updated the status field, we handle it. */
|
||||||
|
@ -951,7 +1031,7 @@ static void update_device_status(struct device *dev)
|
||||||
for (vq = dev->vq; vq; vq = vq->next) {
|
for (vq = dev->vq; vq; vq = vq->next) {
|
||||||
memset(vq->vring.desc, 0,
|
memset(vq->vring.desc, 0,
|
||||||
vring_size(vq->config.num, getpagesize()));
|
vring_size(vq->config.num, getpagesize()));
|
||||||
vq->last_avail_idx = 0;
|
lg_last_avail(vq) = 0;
|
||||||
}
|
}
|
||||||
} else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
|
} else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) {
|
||||||
warnx("Device %s configuration FAILED", dev->name);
|
warnx("Device %s configuration FAILED", dev->name);
|
||||||
|
@ -960,10 +1040,10 @@ static void update_device_status(struct device *dev)
|
||||||
|
|
||||||
verbose("Device %s OK: offered", dev->name);
|
verbose("Device %s OK: offered", dev->name);
|
||||||
for (i = 0; i < dev->desc->feature_len; i++)
|
for (i = 0; i < dev->desc->feature_len; i++)
|
||||||
verbose(" %08x", get_feature_bits(dev)[i]);
|
verbose(" %02x", get_feature_bits(dev)[i]);
|
||||||
verbose(", accepted");
|
verbose(", accepted");
|
||||||
for (i = 0; i < dev->desc->feature_len; i++)
|
for (i = 0; i < dev->desc->feature_len; i++)
|
||||||
verbose(" %08x", get_feature_bits(dev)
|
verbose(" %02x", get_feature_bits(dev)
|
||||||
[dev->desc->feature_len+i]);
|
[dev->desc->feature_len+i]);
|
||||||
|
|
||||||
if (dev->ready)
|
if (dev->ready)
|
||||||
|
@ -1000,7 +1080,7 @@ static void handle_output(int fd, unsigned long addr)
|
||||||
if (strcmp(vq->dev->name, "console") != 0)
|
if (strcmp(vq->dev->name, "console") != 0)
|
||||||
verbose("Output to %s\n", vq->dev->name);
|
verbose("Output to %s\n", vq->dev->name);
|
||||||
if (vq->handle_output)
|
if (vq->handle_output)
|
||||||
vq->handle_output(fd, vq);
|
vq->handle_output(fd, vq, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1014,6 +1094,29 @@ static void handle_output(int fd, unsigned long addr)
|
||||||
strnlen(from_guest_phys(addr), guest_limit - addr));
|
strnlen(from_guest_phys(addr), guest_limit - addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_timeout(int fd)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
struct device *i;
|
||||||
|
struct virtqueue *vq;
|
||||||
|
|
||||||
|
/* Clear the pipe */
|
||||||
|
read(timeoutpipe[0], buf, sizeof(buf));
|
||||||
|
|
||||||
|
/* Check each device and virtqueue: flush blocked ones. */
|
||||||
|
for (i = devices.dev; i; i = i->next) {
|
||||||
|
for (vq = i->vq; vq; vq = vq->next) {
|
||||||
|
if (!vq->blocked)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
|
||||||
|
vq->blocked = false;
|
||||||
|
if (vq->handle_output)
|
||||||
|
vq->handle_output(fd, vq, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* This is called when the Waker wakes us up: check for incoming file
|
/* This is called when the Waker wakes us up: check for incoming file
|
||||||
* descriptors. */
|
* descriptors. */
|
||||||
static void handle_input(int fd)
|
static void handle_input(int fd)
|
||||||
|
@ -1024,16 +1127,20 @@ static void handle_input(int fd)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct device *i;
|
struct device *i;
|
||||||
fd_set fds = devices.infds;
|
fd_set fds = devices.infds;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
num = select(devices.max_infd+1, &fds, NULL, NULL, &poll);
|
||||||
|
/* Could get interrupted */
|
||||||
|
if (num < 0)
|
||||||
|
continue;
|
||||||
/* If nothing is ready, we're done. */
|
/* If nothing is ready, we're done. */
|
||||||
if (select(devices.max_infd+1, &fds, NULL, NULL, &poll) == 0)
|
if (num == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Otherwise, call the device(s) which have readable file
|
/* Otherwise, call the device(s) which have readable file
|
||||||
* descriptors and a method of handling them. */
|
* descriptors and a method of handling them. */
|
||||||
for (i = devices.dev; i; i = i->next) {
|
for (i = devices.dev; i; i = i->next) {
|
||||||
if (i->handle_input && FD_ISSET(i->fd, &fds)) {
|
if (i->handle_input && FD_ISSET(i->fd, &fds)) {
|
||||||
int dev_fd;
|
|
||||||
if (i->handle_input(fd, i))
|
if (i->handle_input(fd, i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1043,13 +1150,12 @@ static void handle_input(int fd)
|
||||||
* buffers to deliver into. Console also uses
|
* buffers to deliver into. Console also uses
|
||||||
* it when it discovers that stdin is closed. */
|
* it when it discovers that stdin is closed. */
|
||||||
FD_CLR(i->fd, &devices.infds);
|
FD_CLR(i->fd, &devices.infds);
|
||||||
/* Tell waker to ignore it too, by sending a
|
|
||||||
* negative fd number (-1, since 0 is a valid
|
|
||||||
* FD number). */
|
|
||||||
dev_fd = -i->fd - 1;
|
|
||||||
write(waker_fd, &dev_fd, sizeof(dev_fd));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Is this the timeout fd? */
|
||||||
|
if (FD_ISSET(timeoutpipe[0], &fds))
|
||||||
|
handle_timeout(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,7 +1204,7 @@ static struct lguest_device_desc *new_dev_desc(u16 type)
|
||||||
/* Each device descriptor is followed by the description of its virtqueues. We
|
/* Each device descriptor is followed by the description of its virtqueues. We
|
||||||
* specify how many descriptors the virtqueue is to have. */
|
* specify how many descriptors the virtqueue is to have. */
|
||||||
static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
||||||
void (*handle_output)(int fd, struct virtqueue *me))
|
void (*handle_output)(int, struct virtqueue *, bool))
|
||||||
{
|
{
|
||||||
unsigned int pages;
|
unsigned int pages;
|
||||||
struct virtqueue **i, *vq = malloc(sizeof(*vq));
|
struct virtqueue **i, *vq = malloc(sizeof(*vq));
|
||||||
|
@ -1114,6 +1220,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
|
||||||
vq->last_avail_idx = 0;
|
vq->last_avail_idx = 0;
|
||||||
vq->dev = dev;
|
vq->dev = dev;
|
||||||
vq->inflight = 0;
|
vq->inflight = 0;
|
||||||
|
vq->blocked = false;
|
||||||
|
|
||||||
/* Initialize the configuration. */
|
/* Initialize the configuration. */
|
||||||
vq->config.num = num_descs;
|
vq->config.num = num_descs;
|
||||||
|
@ -1246,6 +1353,24 @@ static void setup_console(void)
|
||||||
}
|
}
|
||||||
/*:*/
|
/*:*/
|
||||||
|
|
||||||
|
static void timeout_alarm(int sig)
|
||||||
|
{
|
||||||
|
write(timeoutpipe[1], "", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_timeout(void)
|
||||||
|
{
|
||||||
|
if (pipe(timeoutpipe) != 0)
|
||||||
|
err(1, "Creating timeout pipe");
|
||||||
|
|
||||||
|
if (fcntl(timeoutpipe[1], F_SETFL,
|
||||||
|
fcntl(timeoutpipe[1], F_GETFL) | O_NONBLOCK) != 0)
|
||||||
|
err(1, "Making timeout pipe nonblocking");
|
||||||
|
|
||||||
|
add_device_fd(timeoutpipe[0]);
|
||||||
|
signal(SIGALRM, timeout_alarm);
|
||||||
|
}
|
||||||
|
|
||||||
/*M:010 Inter-guest networking is an interesting area. Simplest is to have a
|
/*M:010 Inter-guest networking is an interesting area. Simplest is to have a
|
||||||
* --sharenet=<name> option which opens or creates a named pipe. This can be
|
* --sharenet=<name> option which opens or creates a named pipe. This can be
|
||||||
* used to send packets to another guest in a 1:1 manner.
|
* used to send packets to another guest in a 1:1 manner.
|
||||||
|
@ -1264,10 +1389,25 @@ static void setup_console(void)
|
||||||
|
|
||||||
static u32 str2ip(const char *ipaddr)
|
static u32 str2ip(const char *ipaddr)
|
||||||
{
|
{
|
||||||
unsigned int byte[4];
|
unsigned int b[4];
|
||||||
|
|
||||||
sscanf(ipaddr, "%u.%u.%u.%u", &byte[0], &byte[1], &byte[2], &byte[3]);
|
if (sscanf(ipaddr, "%u.%u.%u.%u", &b[0], &b[1], &b[2], &b[3]) != 4)
|
||||||
return (byte[0] << 24) | (byte[1] << 16) | (byte[2] << 8) | byte[3];
|
errx(1, "Failed to parse IP address '%s'", ipaddr);
|
||||||
|
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void str2mac(const char *macaddr, unsigned char mac[6])
|
||||||
|
{
|
||||||
|
unsigned int m[6];
|
||||||
|
if (sscanf(macaddr, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
&m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) != 6)
|
||||||
|
errx(1, "Failed to parse mac address '%s'", macaddr);
|
||||||
|
mac[0] = m[0];
|
||||||
|
mac[1] = m[1];
|
||||||
|
mac[2] = m[2];
|
||||||
|
mac[3] = m[3];
|
||||||
|
mac[4] = m[4];
|
||||||
|
mac[5] = m[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This code is "adapted" from libbridge: it attaches the Host end of the
|
/* This code is "adapted" from libbridge: it attaches the Host end of the
|
||||||
|
@ -1288,6 +1428,7 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
|
||||||
errx(1, "interface %s does not exist!", if_name);
|
errx(1, "interface %s does not exist!", if_name);
|
||||||
|
|
||||||
strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
|
strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
|
||||||
|
ifr.ifr_name[IFNAMSIZ-1] = '\0';
|
||||||
ifr.ifr_ifindex = ifidx;
|
ifr.ifr_ifindex = ifidx;
|
||||||
if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
|
if (ioctl(fd, SIOCBRADDIF, &ifr) < 0)
|
||||||
err(1, "can't add %s to bridge %s", if_name, br_name);
|
err(1, "can't add %s to bridge %s", if_name, br_name);
|
||||||
|
@ -1296,64 +1437,75 @@ static void add_to_bridge(int fd, const char *if_name, const char *br_name)
|
||||||
/* This sets up the Host end of the network device with an IP address, brings
|
/* This sets up the Host end of the network device with an IP address, brings
|
||||||
* it up so packets will flow, the copies the MAC address into the hwaddr
|
* it up so packets will flow, the copies the MAC address into the hwaddr
|
||||||
* pointer. */
|
* pointer. */
|
||||||
static void configure_device(int fd, const char *devname, u32 ipaddr,
|
static void configure_device(int fd, const char *tapif, u32 ipaddr)
|
||||||
unsigned char hwaddr[6])
|
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
|
||||||
|
|
||||||
/* Don't read these incantations. Just cut & paste them like I did! */
|
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
strcpy(ifr.ifr_name, devname);
|
strcpy(ifr.ifr_name, tapif);
|
||||||
|
|
||||||
|
/* Don't read these incantations. Just cut & paste them like I did! */
|
||||||
sin->sin_family = AF_INET;
|
sin->sin_family = AF_INET;
|
||||||
sin->sin_addr.s_addr = htonl(ipaddr);
|
sin->sin_addr.s_addr = htonl(ipaddr);
|
||||||
if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
|
if (ioctl(fd, SIOCSIFADDR, &ifr) != 0)
|
||||||
err(1, "Setting %s interface address", devname);
|
err(1, "Setting %s interface address", tapif);
|
||||||
ifr.ifr_flags = IFF_UP;
|
ifr.ifr_flags = IFF_UP;
|
||||||
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
|
if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0)
|
||||||
err(1, "Bringing interface %s up", devname);
|
err(1, "Bringing interface %s up", tapif);
|
||||||
|
|
||||||
/* SIOC stands for Socket I/O Control. G means Get (vs S for Set
|
|
||||||
* above). IF means Interface, and HWADDR is hardware address.
|
|
||||||
* Simple! */
|
|
||||||
if (ioctl(fd, SIOCGIFHWADDR, &ifr) != 0)
|
|
||||||
err(1, "getting hw address for %s", devname);
|
|
||||||
memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, 6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*L:195 Our network is a Host<->Guest network. This can either use bridging or
|
static int get_tun_device(char tapif[IFNAMSIZ])
|
||||||
* routing, but the principle is the same: it uses the "tun" device to inject
|
|
||||||
* packets into the Host as if they came in from a normal network card. We
|
|
||||||
* just shunt packets between the Guest and the tun device. */
|
|
||||||
static void setup_tun_net(const char *arg)
|
|
||||||
{
|
{
|
||||||
struct device *dev;
|
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int netfd, ipfd;
|
int netfd;
|
||||||
u32 ip;
|
|
||||||
const char *br_name = NULL;
|
/* Start with this zeroed. Messy but sure. */
|
||||||
struct virtio_net_config conf;
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
|
|
||||||
/* We open the /dev/net/tun device and tell it we want a tap device. A
|
/* We open the /dev/net/tun device and tell it we want a tap device. A
|
||||||
* tap device is like a tun device, only somehow different. To tell
|
* tap device is like a tun device, only somehow different. To tell
|
||||||
* the truth, I completely blundered my way through this code, but it
|
* the truth, I completely blundered my way through this code, but it
|
||||||
* works now! */
|
* works now! */
|
||||||
netfd = open_or_die("/dev/net/tun", O_RDWR);
|
netfd = open_or_die("/dev/net/tun", O_RDWR);
|
||||||
memset(&ifr, 0, sizeof(ifr));
|
ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
|
||||||
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
|
|
||||||
strcpy(ifr.ifr_name, "tap%d");
|
strcpy(ifr.ifr_name, "tap%d");
|
||||||
if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
|
if (ioctl(netfd, TUNSETIFF, &ifr) != 0)
|
||||||
err(1, "configuring /dev/net/tun");
|
err(1, "configuring /dev/net/tun");
|
||||||
|
|
||||||
|
if (ioctl(netfd, TUNSETOFFLOAD,
|
||||||
|
TUN_F_CSUM|TUN_F_TSO4|TUN_F_TSO6|TUN_F_TSO_ECN) != 0)
|
||||||
|
err(1, "Could not set features for tun device");
|
||||||
|
|
||||||
/* We don't need checksums calculated for packets coming in this
|
/* We don't need checksums calculated for packets coming in this
|
||||||
* device: trust us! */
|
* device: trust us! */
|
||||||
ioctl(netfd, TUNSETNOCSUM, 1);
|
ioctl(netfd, TUNSETNOCSUM, 1);
|
||||||
|
|
||||||
|
memcpy(tapif, ifr.ifr_name, IFNAMSIZ);
|
||||||
|
return netfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*L:195 Our network is a Host<->Guest network. This can either use bridging or
|
||||||
|
* routing, but the principle is the same: it uses the "tun" device to inject
|
||||||
|
* packets into the Host as if they came in from a normal network card. We
|
||||||
|
* just shunt packets between the Guest and the tun device. */
|
||||||
|
static void setup_tun_net(char *arg)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
int netfd, ipfd;
|
||||||
|
u32 ip = INADDR_ANY;
|
||||||
|
bool bridging = false;
|
||||||
|
char tapif[IFNAMSIZ], *p;
|
||||||
|
struct virtio_net_config conf;
|
||||||
|
|
||||||
|
netfd = get_tun_device(tapif);
|
||||||
|
|
||||||
/* First we create a new network device. */
|
/* First we create a new network device. */
|
||||||
dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
|
dev = new_device("net", VIRTIO_ID_NET, netfd, handle_tun_input);
|
||||||
|
|
||||||
/* Network devices need a receive and a send queue, just like
|
/* Network devices need a receive and a send queue, just like
|
||||||
* console. */
|
* console. */
|
||||||
add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
|
add_virtqueue(dev, VIRTQUEUE_NUM, net_enable_fd);
|
||||||
add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
|
add_virtqueue(dev, VIRTQUEUE_NUM, handle_net_output);
|
||||||
|
|
||||||
/* We need a socket to perform the magic network ioctls to bring up the
|
/* We need a socket to perform the magic network ioctls to bring up the
|
||||||
|
@ -1364,28 +1516,50 @@ static void setup_tun_net(const char *arg)
|
||||||
|
|
||||||
/* If the command line was --tunnet=bridge:<name> do bridging. */
|
/* If the command line was --tunnet=bridge:<name> do bridging. */
|
||||||
if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
|
if (!strncmp(BRIDGE_PFX, arg, strlen(BRIDGE_PFX))) {
|
||||||
ip = INADDR_ANY;
|
arg += strlen(BRIDGE_PFX);
|
||||||
br_name = arg + strlen(BRIDGE_PFX);
|
bridging = true;
|
||||||
add_to_bridge(ipfd, ifr.ifr_name, br_name);
|
}
|
||||||
} else /* It is an IP address to set up the device with */
|
|
||||||
|
/* A mac address may follow the bridge name or IP address */
|
||||||
|
p = strchr(arg, ':');
|
||||||
|
if (p) {
|
||||||
|
str2mac(p+1, conf.mac);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_MAC);
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* arg is now either an IP address or a bridge name */
|
||||||
|
if (bridging)
|
||||||
|
add_to_bridge(ipfd, tapif, arg);
|
||||||
|
else
|
||||||
ip = str2ip(arg);
|
ip = str2ip(arg);
|
||||||
|
|
||||||
/* Set up the tun device, and get the mac address for the interface. */
|
/* Set up the tun device. */
|
||||||
configure_device(ipfd, ifr.ifr_name, ip, conf.mac);
|
configure_device(ipfd, tapif, ip);
|
||||||
|
|
||||||
/* Tell Guest what MAC address to use. */
|
|
||||||
add_feature(dev, VIRTIO_NET_F_MAC);
|
|
||||||
add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
|
add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
|
||||||
|
/* Expect Guest to handle everything except UFO */
|
||||||
|
add_feature(dev, VIRTIO_NET_F_CSUM);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_CSUM);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_TSO4);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_TSO6);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_GUEST_ECN);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_HOST_TSO4);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_HOST_TSO6);
|
||||||
|
add_feature(dev, VIRTIO_NET_F_HOST_ECN);
|
||||||
set_config(dev, sizeof(conf), &conf);
|
set_config(dev, sizeof(conf), &conf);
|
||||||
|
|
||||||
/* We don't need the socket any more; setup is done. */
|
/* We don't need the socket any more; setup is done. */
|
||||||
close(ipfd);
|
close(ipfd);
|
||||||
|
|
||||||
verbose("device %u: tun net %u.%u.%u.%u\n",
|
devices.device_num++;
|
||||||
devices.device_num++,
|
|
||||||
(u8)(ip>>24),(u8)(ip>>16),(u8)(ip>>8),(u8)ip);
|
if (bridging)
|
||||||
if (br_name)
|
verbose("device %u: tun %s attached to bridge: %s\n",
|
||||||
verbose("attached to bridge: %s\n", br_name);
|
devices.device_num, tapif, arg);
|
||||||
|
else
|
||||||
|
verbose("device %u: tun %s: %s\n",
|
||||||
|
devices.device_num, tapif, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Our block (disk) device should be really simple: the Guest asks for a block
|
/* Our block (disk) device should be really simple: the Guest asks for a block
|
||||||
|
@ -1550,7 +1724,7 @@ static bool handle_io_finish(int fd, struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When the Guest submits some I/O, we just need to wake the I/O thread. */
|
/* When the Guest submits some I/O, we just need to wake the I/O thread. */
|
||||||
static void handle_virtblk_output(int fd, struct virtqueue *vq)
|
static void handle_virtblk_output(int fd, struct virtqueue *vq, bool timeout)
|
||||||
{
|
{
|
||||||
struct vblk_info *vblk = vq->dev->priv;
|
struct vblk_info *vblk = vq->dev->priv;
|
||||||
char c = 0;
|
char c = 0;
|
||||||
|
@ -1621,6 +1795,64 @@ static void setup_block_file(const char *filename)
|
||||||
verbose("device %u: virtblock %llu sectors\n",
|
verbose("device %u: virtblock %llu sectors\n",
|
||||||
devices.device_num, le64_to_cpu(conf.capacity));
|
devices.device_num, le64_to_cpu(conf.capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Our random number generator device reads from /dev/random into the Guest's
|
||||||
|
* input buffers. The usual case is that the Guest doesn't want random numbers
|
||||||
|
* and so has no buffers although /dev/random is still readable, whereas
|
||||||
|
* console is the reverse.
|
||||||
|
*
|
||||||
|
* The same logic applies, however. */
|
||||||
|
static bool handle_rng_input(int fd, struct device *dev)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
unsigned int head, in_num, out_num, totlen = 0;
|
||||||
|
struct iovec iov[dev->vq->vring.num];
|
||||||
|
|
||||||
|
/* First we need a buffer from the Guests's virtqueue. */
|
||||||
|
head = get_vq_desc(dev->vq, iov, &out_num, &in_num);
|
||||||
|
|
||||||
|
/* If they're not ready for input, stop listening to this file
|
||||||
|
* descriptor. We'll start again once they add an input buffer. */
|
||||||
|
if (head == dev->vq->vring.num)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (out_num)
|
||||||
|
errx(1, "Output buffers in rng?");
|
||||||
|
|
||||||
|
/* This is why we convert to iovecs: the readv() call uses them, and so
|
||||||
|
* it reads straight into the Guest's buffer. We loop to make sure we
|
||||||
|
* fill it. */
|
||||||
|
while (!iov_empty(iov, in_num)) {
|
||||||
|
len = readv(dev->fd, iov, in_num);
|
||||||
|
if (len <= 0)
|
||||||
|
err(1, "Read from /dev/random gave %i", len);
|
||||||
|
iov_consume(iov, in_num, len);
|
||||||
|
totlen += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell the Guest about the new input. */
|
||||||
|
add_used_and_trigger(fd, dev->vq, head, totlen);
|
||||||
|
|
||||||
|
/* Everything went OK! */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And this creates a "hardware" random number device for the Guest. */
|
||||||
|
static void setup_rng(void)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open_or_die("/dev/random", O_RDONLY);
|
||||||
|
|
||||||
|
/* The device responds to return from I/O thread. */
|
||||||
|
dev = new_device("rng", VIRTIO_ID_RNG, fd, handle_rng_input);
|
||||||
|
|
||||||
|
/* The device has one virtqueue, where the Guest places inbufs. */
|
||||||
|
add_virtqueue(dev, VIRTQUEUE_NUM, enable_fd);
|
||||||
|
|
||||||
|
verbose("device %u: rng\n", devices.device_num++);
|
||||||
|
}
|
||||||
/* That's the end of device setup. */
|
/* That's the end of device setup. */
|
||||||
|
|
||||||
/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
|
/*L:230 Reboot is pretty easy: clean up and exec() the Launcher afresh. */
|
||||||
|
@ -1628,11 +1860,12 @@ static void __attribute__((noreturn)) restart_guest(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Closing pipes causes the Waker thread and io_threads to die, and
|
/* Since we don't track all open fds, we simply close everything beyond
|
||||||
* closing /dev/lguest cleans up the Guest. Since we don't track all
|
* stderr. */
|
||||||
* open fds, we simply close everything beyond stderr. */
|
|
||||||
for (i = 3; i < FD_SETSIZE; i++)
|
for (i = 3; i < FD_SETSIZE; i++)
|
||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
|
/* The exec automatically gets rid of the I/O and Waker threads. */
|
||||||
execv(main_args[0], main_args);
|
execv(main_args[0], main_args);
|
||||||
err(1, "Could not exec %s", main_args[0]);
|
err(1, "Could not exec %s", main_args[0]);
|
||||||
}
|
}
|
||||||
|
@ -1663,7 +1896,7 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
|
||||||
/* ERESTART means that we need to reboot the guest */
|
/* ERESTART means that we need to reboot the guest */
|
||||||
} else if (errno == ERESTART) {
|
} else if (errno == ERESTART) {
|
||||||
restart_guest();
|
restart_guest();
|
||||||
/* EAGAIN means the Waker wanted us to look at some input.
|
/* EAGAIN means a signal (timeout).
|
||||||
* Anything else means a bug or incompatible change. */
|
* Anything else means a bug or incompatible change. */
|
||||||
} else if (errno != EAGAIN)
|
} else if (errno != EAGAIN)
|
||||||
err(1, "Running guest failed");
|
err(1, "Running guest failed");
|
||||||
|
@ -1691,13 +1924,14 @@ static struct option opts[] = {
|
||||||
{ "verbose", 0, NULL, 'v' },
|
{ "verbose", 0, NULL, 'v' },
|
||||||
{ "tunnet", 1, NULL, 't' },
|
{ "tunnet", 1, NULL, 't' },
|
||||||
{ "block", 1, NULL, 'b' },
|
{ "block", 1, NULL, 'b' },
|
||||||
|
{ "rng", 0, NULL, 'r' },
|
||||||
{ "initrd", 1, NULL, 'i' },
|
{ "initrd", 1, NULL, 'i' },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
errx(1, "Usage: lguest [--verbose] "
|
errx(1, "Usage: lguest [--verbose] "
|
||||||
"[--tunnet=(<ipaddr>|bridge:<bridgename>)\n"
|
"[--tunnet=(<ipaddr>:<macaddr>|bridge:<bridgename>:<macaddr>)\n"
|
||||||
"|--block=<filename>|--initrd=<filename>]...\n"
|
"|--block=<filename>|--initrd=<filename>]...\n"
|
||||||
"<mem-in-mb> vmlinux [args...]");
|
"<mem-in-mb> vmlinux [args...]");
|
||||||
}
|
}
|
||||||
|
@ -1765,6 +1999,9 @@ int main(int argc, char *argv[])
|
||||||
case 'b':
|
case 'b':
|
||||||
setup_block_file(optarg);
|
setup_block_file(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
setup_rng();
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
initrd_name = optarg;
|
initrd_name = optarg;
|
||||||
break;
|
break;
|
||||||
|
@ -1783,6 +2020,9 @@ int main(int argc, char *argv[])
|
||||||
/* We always have a console device */
|
/* We always have a console device */
|
||||||
setup_console();
|
setup_console();
|
||||||
|
|
||||||
|
/* We can timeout waiting for Guest network transmit. */
|
||||||
|
setup_timeout();
|
||||||
|
|
||||||
/* Now we load the kernel */
|
/* Now we load the kernel */
|
||||||
start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
|
start = load_kernel(open_or_die(argv[optind+1], O_RDONLY));
|
||||||
|
|
||||||
|
@ -1826,10 +2066,10 @@ int main(int argc, char *argv[])
|
||||||
* /dev/lguest file descriptor. */
|
* /dev/lguest file descriptor. */
|
||||||
lguest_fd = tell_kernel(pgdir, start);
|
lguest_fd = tell_kernel(pgdir, start);
|
||||||
|
|
||||||
/* We fork off a child process, which wakes the Launcher whenever one
|
/* We clone off a thread, which wakes the Launcher whenever one of the
|
||||||
* of the input file descriptors needs attention. We call this the
|
* input file descriptors needs attention. We call this the Waker, and
|
||||||
* Waker, and we'll cover it in a moment. */
|
* we'll cover it in a moment. */
|
||||||
waker_fd = setup_waker(lguest_fd);
|
setup_waker(lguest_fd);
|
||||||
|
|
||||||
/* Finally, run the Guest. This doesn't return. */
|
/* Finally, run the Guest. This doesn't return. */
|
||||||
run_guest(lguest_fd);
|
run_guest(lguest_fd);
|
||||||
|
|
|
@ -36,7 +36,7 @@ It can be done by slightly modifying the standard atomic operations : only
|
||||||
their UP variant must be kept. It typically means removing LOCK prefix (on
|
their UP variant must be kept. It typically means removing LOCK prefix (on
|
||||||
i386 and x86_64) and any SMP sychronization barrier. If the architecture does
|
i386 and x86_64) and any SMP sychronization barrier. If the architecture does
|
||||||
not have a different behavior between SMP and UP, including asm-generic/local.h
|
not have a different behavior between SMP and UP, including asm-generic/local.h
|
||||||
in your archtecture's local.h is sufficient.
|
in your architecture's local.h is sufficient.
|
||||||
|
|
||||||
The local_t type is defined as an opaque signed long by embedding an
|
The local_t type is defined as an opaque signed long by embedding an
|
||||||
atomic_long_t inside a structure. This is made so a cast from this type to a
|
atomic_long_t inside a structure. This is made so a cast from this type to a
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
=============================================================================
|
=============================================================================
|
||||||
|
MOXA Smartio/Industio Family Device Driver Installation Guide
|
||||||
|
for Linux Kernel 2.4.x, 2.6.x
|
||||||
|
Copyright (C) 2008, Moxa Inc.
|
||||||
|
=============================================================================
|
||||||
|
Date: 01/21/2008
|
||||||
|
|
||||||
MOXA Smartio Family Device Driver Ver 1.1 Installation Guide
|
|
||||||
for Linux Kernel 2.2.x and 2.0.3x
|
|
||||||
Copyright (C) 1999, Moxa Technologies Co, Ltd.
|
|
||||||
=============================================================================
|
|
||||||
Content
|
Content
|
||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
2. System Requirement
|
2. System Requirement
|
||||||
3. Installation
|
3. Installation
|
||||||
|
3.1 Hardware installation
|
||||||
|
3.2 Driver files
|
||||||
|
3.3 Device naming convention
|
||||||
|
3.4 Module driver configuration
|
||||||
|
3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x.
|
||||||
|
3.6 Custom configuration
|
||||||
|
3.7 Verify driver installation
|
||||||
4. Utilities
|
4. Utilities
|
||||||
5. Setserial
|
5. Setserial
|
||||||
6. Troubleshooting
|
6. Troubleshooting
|
||||||
|
@ -16,27 +24,48 @@ Content
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
1. Introduction
|
1. Introduction
|
||||||
|
|
||||||
The Smartio family Linux driver, Ver. 1.1, supports following multiport
|
The Smartio/Industio/UPCI family Linux driver supports following multiport
|
||||||
boards.
|
boards.
|
||||||
|
|
||||||
-C104P/H/HS, C104H/PCI, C104HS/PCI, CI-104J 4 port multiport board.
|
- 2 ports multiport board
|
||||||
-C168P/H/HS, C168H/PCI 8 port multiport board.
|
CP-102U, CP-102UL, CP-102UF
|
||||||
|
CP-132U-I, CP-132UL,
|
||||||
|
CP-132, CP-132I, CP132S, CP-132IS,
|
||||||
|
CI-132, CI-132I, CI-132IS,
|
||||||
|
(C102H, C102HI, C102HIS, C102P, CP-102, CP-102S)
|
||||||
|
|
||||||
This driver has been modified a little and cleaned up from the Moxa
|
- 4 ports multiport board
|
||||||
contributed driver code and merged into Linux 2.2.14pre. In particular
|
CP-104EL,
|
||||||
official major/minor numbers have been assigned which are different to
|
CP-104UL, CP-104JU,
|
||||||
those the original Moxa supplied driver used.
|
CP-134U, CP-134U-I,
|
||||||
|
C104H/PCI, C104HS/PCI,
|
||||||
|
CP-114, CP-114I, CP-114S, CP-114IS, CP-114UL,
|
||||||
|
C104H, C104HS,
|
||||||
|
CI-104J, CI-104JS,
|
||||||
|
CI-134, CI-134I, CI-134IS,
|
||||||
|
(C114HI, CT-114I, C104P)
|
||||||
|
POS-104UL,
|
||||||
|
CB-114,
|
||||||
|
CB-134I
|
||||||
|
|
||||||
|
- 8 ports multiport board
|
||||||
|
CP-118EL, CP-168EL,
|
||||||
|
CP-118U, CP-168U,
|
||||||
|
C168H/PCI,
|
||||||
|
C168H, C168HS,
|
||||||
|
(C168P),
|
||||||
|
CB-108
|
||||||
|
|
||||||
This driver and installation procedure have been developed upon Linux Kernel
|
This driver and installation procedure have been developed upon Linux Kernel
|
||||||
2.2.5 and backward compatible to 2.0.3x. This driver supports Intel x86 and
|
2.4.x and 2.6.x. This driver supports Intel x86 hardware platform. In order
|
||||||
Alpha hardware platform. In order to maintain compatibility, this version
|
to maintain compatibility, this version has also been properly tested with
|
||||||
has also been properly tested with RedHat, OpenLinux, TurboLinux and
|
RedHat, Mandrake, Fedora and S.u.S.E Linux. However, if compatibility problem
|
||||||
S.u.S.E Linux. However, if compatibility problem occurs, please contact
|
occurs, please contact Moxa at support@moxa.com.tw.
|
||||||
Moxa at support@moxa.com.tw.
|
|
||||||
|
|
||||||
In addition to device driver, useful utilities are also provided in this
|
In addition to device driver, useful utilities are also provided in this
|
||||||
version. They are
|
version. They are
|
||||||
- msdiag Diagnostic program for detecting installed Moxa Smartio boards.
|
- msdiag Diagnostic program for displaying installed Moxa
|
||||||
|
Smartio/Industio boards.
|
||||||
- msmon Monitor program to observe data count and line status signals.
|
- msmon Monitor program to observe data count and line status signals.
|
||||||
- msterm A simple terminal program which is useful in testing serial
|
- msterm A simple terminal program which is useful in testing serial
|
||||||
ports.
|
ports.
|
||||||
|
@ -47,8 +76,7 @@ Content
|
||||||
GNU General Public License in this version. Please refer to GNU General
|
GNU General Public License in this version. Please refer to GNU General
|
||||||
Public License announcement in each source code file for more detail.
|
Public License announcement in each source code file for more detail.
|
||||||
|
|
||||||
In Moxa's ftp sites, you may always find latest driver at
|
In Moxa's Web sites, you may always find latest driver at http://web.moxa.com.
|
||||||
ftp://ftp.moxa.com or ftp://ftp.moxa.com.tw.
|
|
||||||
|
|
||||||
This version of driver can be installed as Loadable Module (Module driver)
|
This version of driver can be installed as Loadable Module (Module driver)
|
||||||
or built-in into kernel (Static driver). You may refer to following
|
or built-in into kernel (Static driver). You may refer to following
|
||||||
|
@ -61,8 +89,8 @@ Content
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
2. System Requirement
|
2. System Requirement
|
||||||
- Hardware platform: Intel x86 or Alpha machine
|
- Hardware platform: Intel x86 machine
|
||||||
- Kernel version: 2.0.3x or 2.2.x
|
- Kernel version: 2.4.x or 2.6.x
|
||||||
- gcc version 2.72 or later
|
- gcc version 2.72 or later
|
||||||
- Maximum 4 boards can be installed in combination
|
- Maximum 4 boards can be installed in combination
|
||||||
|
|
||||||
|
@ -70,9 +98,18 @@ Content
|
||||||
3. Installation
|
3. Installation
|
||||||
|
|
||||||
3.1 Hardware installation
|
3.1 Hardware installation
|
||||||
|
3.2 Driver files
|
||||||
|
3.3 Device naming convention
|
||||||
|
3.4 Module driver configuration
|
||||||
|
3.5 Static driver configuration for Linux kernel 2.4.x, 2.6.x.
|
||||||
|
3.6 Custom configuration
|
||||||
|
3.7 Verify driver installation
|
||||||
|
|
||||||
There are two types of buses, ISA and PCI, for Smartio family multiport
|
|
||||||
board.
|
3.1 Hardware installation
|
||||||
|
|
||||||
|
There are two types of buses, ISA and PCI, for Smartio/Industio
|
||||||
|
family multiport board.
|
||||||
|
|
||||||
ISA board
|
ISA board
|
||||||
---------
|
---------
|
||||||
|
@ -81,47 +118,57 @@ Content
|
||||||
installation procedure in User's Manual before proceed any further.
|
installation procedure in User's Manual before proceed any further.
|
||||||
Please make sure the JP1 is open after the ISA board is set properly.
|
Please make sure the JP1 is open after the ISA board is set properly.
|
||||||
|
|
||||||
PCI board
|
PCI/UPCI board
|
||||||
---------
|
--------------
|
||||||
You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict
|
You may need to adjust IRQ usage in BIOS to avoid from IRQ conflict
|
||||||
with other ISA devices. Please refer to hardware installation
|
with other ISA devices. Please refer to hardware installation
|
||||||
procedure in User's Manual in advance.
|
procedure in User's Manual in advance.
|
||||||
|
|
||||||
IRQ Sharing
|
PCI IRQ Sharing
|
||||||
-----------
|
-----------
|
||||||
Each port within the same multiport board shares the same IRQ. Up to
|
Each port within the same multiport board shares the same IRQ. Up to
|
||||||
4 Moxa Smartio Family multiport boards can be installed together on
|
4 Moxa Smartio/Industio PCI Family multiport boards can be installed
|
||||||
one system and they can share the same IRQ.
|
together on one system and they can share the same IRQ.
|
||||||
|
|
||||||
3.2 Driver files and device naming convention
|
|
||||||
|
3.2 Driver files
|
||||||
|
|
||||||
The driver file may be obtained from ftp, CD-ROM or floppy disk. The
|
The driver file may be obtained from ftp, CD-ROM or floppy disk. The
|
||||||
first step, anyway, is to copy driver file "mxser.tgz" into specified
|
first step, anyway, is to copy driver file "mxser.tgz" into specified
|
||||||
directory. e.g. /moxa. The execute commands as below.
|
directory. e.g. /moxa. The execute commands as below.
|
||||||
|
|
||||||
|
# cd /
|
||||||
|
# mkdir moxa
|
||||||
# cd /moxa
|
# cd /moxa
|
||||||
# tar xvf /dev/fd0
|
# tar xvf /dev/fd0
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
|
# cd /
|
||||||
|
# mkdir moxa
|
||||||
# cd /moxa
|
# cd /moxa
|
||||||
# cp /mnt/cdrom/<driver directory>/mxser.tgz .
|
# cp /mnt/cdrom/<driver directory>/mxser.tgz .
|
||||||
# tar xvfz mxser.tgz
|
# tar xvfz mxser.tgz
|
||||||
|
|
||||||
|
|
||||||
|
3.3 Device naming convention
|
||||||
|
|
||||||
You may find all the driver and utilities files in /moxa/mxser.
|
You may find all the driver and utilities files in /moxa/mxser.
|
||||||
Following installation procedure depends on the model you'd like to
|
Following installation procedure depends on the model you'd like to
|
||||||
run the driver. If you prefer module driver, please refer to 3.3.
|
run the driver. If you prefer module driver, please refer to 3.4.
|
||||||
If static driver is required, please refer to 3.4.
|
If static driver is required, please refer to 3.5.
|
||||||
|
|
||||||
Dialin and callout port
|
Dialin and callout port
|
||||||
-----------------------
|
-----------------------
|
||||||
This driver remains traditional serial device properties. There're
|
This driver remains traditional serial device properties. There are
|
||||||
two special file name for each serial port. One is dial-in port
|
two special file name for each serial port. One is dial-in port
|
||||||
which is named "ttyMxx". For callout port, the naming convention
|
which is named "ttyMxx". For callout port, the naming convention
|
||||||
is "cumxx".
|
is "cumxx".
|
||||||
|
|
||||||
Device naming when more than 2 boards installed
|
Device naming when more than 2 boards installed
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
Naming convention for each Smartio multiport board is pre-defined
|
Naming convention for each Smartio/Industio multiport board is
|
||||||
as below.
|
pre-defined as below.
|
||||||
|
|
||||||
Board Num. Dial-in Port Callout port
|
Board Num. Dial-in Port Callout port
|
||||||
1st board ttyM0 - ttyM7 cum0 - cum7
|
1st board ttyM0 - ttyM7 cum0 - cum7
|
||||||
|
@ -129,6 +176,12 @@ Content
|
||||||
3rd board ttyM16 - ttyM23 cum16 - cum23
|
3rd board ttyM16 - ttyM23 cum16 - cum23
|
||||||
4th board ttyM24 - ttym31 cum24 - cum31
|
4th board ttyM24 - ttym31 cum24 - cum31
|
||||||
|
|
||||||
|
|
||||||
|
!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
Under Kernel 2.6 the cum Device is Obsolete. So use ttyM*
|
||||||
|
device instead.
|
||||||
|
!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
Board sequence
|
Board sequence
|
||||||
--------------
|
--------------
|
||||||
This driver will activate ISA boards according to the parameter set
|
This driver will activate ISA boards according to the parameter set
|
||||||
|
@ -138,69 +191,131 @@ Content
|
||||||
For PCI boards, their sequence will be after ISA boards and C168H/PCI
|
For PCI boards, their sequence will be after ISA boards and C168H/PCI
|
||||||
has higher priority than C104H/PCI boards.
|
has higher priority than C104H/PCI boards.
|
||||||
|
|
||||||
3.3 Module driver configuration
|
3.4 Module driver configuration
|
||||||
Module driver is easiest way to install. If you prefer static driver
|
Module driver is easiest way to install. If you prefer static driver
|
||||||
installation, please skip this paragraph.
|
installation, please skip this paragraph.
|
||||||
1. Find "Makefile" in /moxa/mxser, then run
|
|
||||||
|
|
||||||
# make install
|
|
||||||
|
|
||||||
The driver files "mxser.o" and utilities will be properly compiled
|
------------- Prepare to use the MOXA driver--------------------
|
||||||
and copied to system directories respectively.Then run
|
3.4.1 Create tty device with correct major number
|
||||||
|
Before using MOXA driver, your system must have the tty devices
|
||||||
|
which are created with driver's major number. We offer one shell
|
||||||
|
script "msmknod" to simplify the procedure.
|
||||||
|
This step is only needed to be executed once. But you still
|
||||||
|
need to do this procedure when:
|
||||||
|
a. You change the driver's major number. Please refer the "3.7"
|
||||||
|
section.
|
||||||
|
b. Your total installed MOXA boards number is changed. Maybe you
|
||||||
|
add/delete one MOXA board.
|
||||||
|
c. You want to change the tty name. This needs to modify the
|
||||||
|
shell script "msmknod"
|
||||||
|
|
||||||
# insmod mxser
|
The procedure is:
|
||||||
|
|
||||||
to activate the modular driver. You may run "lsmod" to check
|
|
||||||
if "mxser.o" is activated.
|
|
||||||
|
|
||||||
2. Create special files by executing "msmknod".
|
|
||||||
# cd /moxa/mxser/driver
|
# cd /moxa/mxser/driver
|
||||||
# ./msmknod
|
# ./msmknod
|
||||||
|
|
||||||
Default major numbers for dial-in device and callout device are
|
This shell script will require the major number for dial-in
|
||||||
174, 175. Msmknod will delete any special files occupying the same
|
device and callout device to create tty device. You also need
|
||||||
device naming.
|
to specify the total installed MOXA board number. Default major
|
||||||
|
numbers for dial-in device and callout device are 30, 35. If
|
||||||
|
you need to change to other number, please refer section "3.7"
|
||||||
|
for more detailed procedure.
|
||||||
|
Msmknod will delete any special files occupying the same device
|
||||||
|
naming.
|
||||||
|
|
||||||
3. Up to now, you may manually execute "insmod mxser" to activate
|
3.4.2 Build the MOXA driver and utilities
|
||||||
this driver and run "rmmod mxser" to remove it. However, it's
|
Before using the MOXA driver and utilities, you need compile the
|
||||||
better to have a boot time configuration to eliminate manual
|
all the source code. This step is only need to be executed once.
|
||||||
operation.
|
But you still re-compile the source code if you modify the source
|
||||||
Boot time configuration can be achieved by rc file. Run following
|
code. For example, if you change the driver's major number (see
|
||||||
command for setting rc files.
|
"3.7" section), then you need to do this step again.
|
||||||
|
|
||||||
|
Find "Makefile" in /moxa/mxser, then run
|
||||||
|
|
||||||
|
# make clean; make install
|
||||||
|
|
||||||
|
!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
|
||||||
|
For Red Hat 9, Red Hat Enterprise Linux AS3/ES3/WS3 & Fedora Core1:
|
||||||
|
# make clean; make installsp1
|
||||||
|
|
||||||
|
For Red Hat Enterprise Linux AS4/ES4/WS4:
|
||||||
|
# make clean; make installsp2
|
||||||
|
!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
The driver files "mxser.o" and utilities will be properly compiled
|
||||||
|
and copied to system directories respectively.
|
||||||
|
|
||||||
|
------------- Load MOXA driver--------------------
|
||||||
|
3.4.3 Load the MOXA driver
|
||||||
|
|
||||||
|
# modprobe mxser <argument>
|
||||||
|
|
||||||
|
will activate the module driver. You may run "lsmod" to check
|
||||||
|
if "mxser" is activated. If the MOXA board is ISA board, the
|
||||||
|
<argument> is needed. Please refer to section "3.4.5" for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
|
||||||
|
------------- Load MOXA driver on boot --------------------
|
||||||
|
3.4.4 For the above description, you may manually execute
|
||||||
|
"modprobe mxser" to activate this driver and run
|
||||||
|
"rmmod mxser" to remove it.
|
||||||
|
However, it's better to have a boot time configuration to
|
||||||
|
eliminate manual operation. Boot time configuration can be
|
||||||
|
achieved by rc file. We offer one "rc.mxser" file to simplify
|
||||||
|
the procedure under "moxa/mxser/driver".
|
||||||
|
|
||||||
|
But if you use ISA board, please modify the "modprobe ..." command
|
||||||
|
to add the argument (see "3.4.5" section). After modifying the
|
||||||
|
rc.mxser, please try to execute "/moxa/mxser/driver/rc.mxser"
|
||||||
|
manually to make sure the modification is ok. If any error
|
||||||
|
encountered, please try to modify again. If the modification is
|
||||||
|
completed, follow the below step.
|
||||||
|
|
||||||
|
Run following command for setting rc files.
|
||||||
|
|
||||||
# cd /moxa/mxser/driver
|
# cd /moxa/mxser/driver
|
||||||
# cp ./rc.mxser /etc/rc.d
|
# cp ./rc.mxser /etc/rc.d
|
||||||
# cd /etc/rc.d
|
# cd /etc/rc.d
|
||||||
|
|
||||||
You may have to modify part of the content in rc.mxser to specify
|
Check "rc.serial" is existed or not. If "rc.serial" doesn't exist,
|
||||||
parameters for ISA board. Please refer to rc.mxser for more detail.
|
create it by vi, run "chmod 755 rc.serial" to change the permission.
|
||||||
Find "rc.serial". If "rc.serial" doesn't exist, create it by vi.
|
Add "/etc/rc.d/rc.mxser" in last line,
|
||||||
Add "rc.mxser" in last line. Next, open rc.local by vi
|
|
||||||
and append following content.
|
|
||||||
|
|
||||||
if [ -f /etc/rc.d/rc.serial ]; then
|
Reboot and check if moxa.o activated by "lsmod" command.
|
||||||
sh /etc/rc.d/rc.serial
|
|
||||||
fi
|
|
||||||
|
|
||||||
4. Reboot and check if mxser.o activated by "lsmod" command.
|
3.4.5. If you'd like to drive Smartio/Industio ISA boards in the system,
|
||||||
5. If you'd like to drive Smartio ISA boards in the system, you'll
|
you'll have to add parameter to specify CAP address of given
|
||||||
have to add parameter to specify CAP address of given board while
|
board while activating "mxser.o". The format for parameters are
|
||||||
activating "mxser.o". The format for parameters are as follows.
|
as follows.
|
||||||
|
|
||||||
insmod mxser ioaddr=0x???,0x???,0x???,0x???
|
modprobe mxser ioaddr=0x???,0x???,0x???,0x???
|
||||||
| | | |
|
| | | |
|
||||||
| | | +- 4th ISA board
|
| | | +- 4th ISA board
|
||||||
| | +------ 3rd ISA board
|
| | +------ 3rd ISA board
|
||||||
| +------------ 2nd ISA board
|
| +------------ 2nd ISA board
|
||||||
+------------------- 1st ISA board
|
+------------------- 1st ISA board
|
||||||
|
|
||||||
3.4 Static driver configuration
|
3.5 Static driver configuration for Linux kernel 2.4.x and 2.6.x
|
||||||
|
|
||||||
1. Create link
|
Note: To use static driver, you must install the linux kernel
|
||||||
|
source package.
|
||||||
|
|
||||||
|
3.5.1 Backup the built-in driver in the kernel.
|
||||||
|
# cd /usr/src/linux/drivers/char
|
||||||
|
# mv mxser.c mxser.c.old
|
||||||
|
|
||||||
|
For Red Hat 7.x user, you need to create link:
|
||||||
|
# cd /usr/src
|
||||||
|
# ln -s linux-2.4 linux
|
||||||
|
|
||||||
|
3.5.2 Create link
|
||||||
# cd /usr/src/linux/drivers/char
|
# cd /usr/src/linux/drivers/char
|
||||||
# ln -s /moxa/mxser/driver/mxser.c mxser.c
|
# ln -s /moxa/mxser/driver/mxser.c mxser.c
|
||||||
|
|
||||||
2. Add CAP address list for ISA boards
|
3.5.3 Add CAP address list for ISA boards. For PCI boards user,
|
||||||
|
please skip this step.
|
||||||
|
|
||||||
In module mode, the CAP address for ISA board is given by
|
In module mode, the CAP address for ISA board is given by
|
||||||
parameter. In static driver configuration, you'll have to
|
parameter. In static driver configuration, you'll have to
|
||||||
assign it within driver's source code. If you will not
|
assign it within driver's source code. If you will not
|
||||||
|
@ -222,73 +337,55 @@ Content
|
||||||
static int mxserBoardCAP[]
|
static int mxserBoardCAP[]
|
||||||
= {0x280, 0x180, 0x00, 0x00};
|
= {0x280, 0x180, 0x00, 0x00};
|
||||||
|
|
||||||
3. Modify tty_io.c
|
3.5.4 Setup kernel configuration
|
||||||
# cd /usr/src/linux/drivers/char/
|
|
||||||
# vi tty_io.c
|
|
||||||
Find pty_init(), insert "mxser_init()" as
|
|
||||||
|
|
||||||
pty_init();
|
Configure the kernel:
|
||||||
mxser_init();
|
|
||||||
|
|
||||||
4. Modify tty.h
|
# cd /usr/src/linux
|
||||||
# cd /usr/src/linux/include/linux
|
# make menuconfig
|
||||||
# vi tty.h
|
|
||||||
Find extern int tty_init(void), insert "mxser_init()" as
|
|
||||||
|
|
||||||
extern int tty_init(void);
|
You will go into a menu-driven system. Please select [Character
|
||||||
extern int mxser_init(void);
|
devices][Non-standard serial port support], enable the [Moxa
|
||||||
|
SmartIO support] driver with "[*]" for built-in (not "[M]"), then
|
||||||
|
select [Exit] to exit this program.
|
||||||
|
|
||||||
5. Modify Makefile
|
3.5.5 Rebuild kernel
|
||||||
# cd /usr/src/linux/drivers/char
|
The following are for Linux kernel rebuilding, for your
|
||||||
# vi Makefile
|
reference only.
|
||||||
Find L_OBJS := tty_io.o ...... random.o, add
|
|
||||||
"mxser.o" at last of this line as
|
|
||||||
L_OBJS := tty_io.o ....... mxser.o
|
|
||||||
|
|
||||||
6. Rebuild kernel
|
|
||||||
The following are for Linux kernel rebuilding,for your reference only.
|
|
||||||
For appropriate details, please refer to the Linux document.
|
For appropriate details, please refer to the Linux document.
|
||||||
|
|
||||||
If 'lilo' utility is installed, please use 'make zlilo' to rebuild
|
|
||||||
kernel. If 'lilo' is not installed, please follow the following steps.
|
|
||||||
|
|
||||||
a. cd /usr/src/linux
|
a. cd /usr/src/linux
|
||||||
b. make clean /* take a few minutes */
|
b. make clean /* take a few minutes */
|
||||||
c. make bzImage /* take probably 10-20 minutes */
|
c. make dep /* take a few minutes */
|
||||||
d. Backup original boot kernel. /* optional step */
|
d. make bzImage /* take probably 10-20 minutes */
|
||||||
e. cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz
|
e. make install /* copy boot image to correct position */
|
||||||
f. Please make sure the boot kernel (vmlinuz) is in the
|
f. Please make sure the boot kernel (vmlinuz) is in the
|
||||||
correct position. If you use 'lilo' utility, you should
|
correct position.
|
||||||
check /etc/lilo.conf 'image' item specified the path
|
g. If you use 'lilo' utility, you should check /etc/lilo.conf
|
||||||
which is the 'vmlinuz' path, or you will load wrong
|
'image' item specified the path which is the 'vmlinuz' path,
|
||||||
(or old) boot kernel image (vmlinuz).
|
or you will load wrong (or old) boot kernel image (vmlinuz).
|
||||||
g. chmod 400 /vmlinuz
|
After checking /etc/lilo.conf, please run "lilo".
|
||||||
h. lilo
|
|
||||||
i. rdev -R /vmlinuz 1
|
|
||||||
j. sync
|
|
||||||
|
|
||||||
Note that if the result of "make zImage" is ERROR, then you have to
|
Note that if the result of "make bzImage" is ERROR, then you have to
|
||||||
go back to Linux configuration Setup. Type "make config" in directory
|
go back to Linux configuration Setup. Type "make menuconfig" in
|
||||||
/usr/src/linux or "setup".
|
directory /usr/src/linux.
|
||||||
|
|
||||||
Since system include file, /usr/src/linux/include/linux/interrupt.h,
|
|
||||||
is modified each time the MOXA driver is installed, kernel rebuilding
|
|
||||||
is inevitable. And it takes about 10 to 20 minutes depends on the
|
|
||||||
machine.
|
|
||||||
|
|
||||||
7. Make utility
|
3.5.6 Make tty device and special file
|
||||||
# cd /moxa/mxser/utility
|
|
||||||
# make install
|
|
||||||
|
|
||||||
8. Make special file
|
|
||||||
# cd /moxa/mxser/driver
|
# cd /moxa/mxser/driver
|
||||||
# ./msmknod
|
# ./msmknod
|
||||||
|
|
||||||
9. Reboot
|
3.5.7 Make utility
|
||||||
|
# cd /moxa/mxser/utility
|
||||||
|
# make clean; make install
|
||||||
|
|
||||||
3.5 Custom configuration
|
3.5.8 Reboot
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3.6 Custom configuration
|
||||||
Although this driver already provides you default configuration, you
|
Although this driver already provides you default configuration, you
|
||||||
still can change the device name and major number.The instruction to
|
still can change the device name and major number. The instruction to
|
||||||
change these parameters are shown as below.
|
change these parameters are shown as below.
|
||||||
|
|
||||||
Change Device name
|
Change Device name
|
||||||
|
@ -306,33 +403,37 @@ Content
|
||||||
2 free major numbers for this driver. There are 3 steps to change
|
2 free major numbers for this driver. There are 3 steps to change
|
||||||
major numbers.
|
major numbers.
|
||||||
|
|
||||||
1. Find free major numbers
|
3.6.1 Find free major numbers
|
||||||
In /proc/devices, you may find all the major numbers occupied
|
In /proc/devices, you may find all the major numbers occupied
|
||||||
in the system. Please select 2 major numbers that are available.
|
in the system. Please select 2 major numbers that are available.
|
||||||
e.g. 40, 45.
|
e.g. 40, 45.
|
||||||
2. Create special files
|
3.6.2 Create special files
|
||||||
Run /moxa/mxser/driver/msmknod to create special files with
|
Run /moxa/mxser/driver/msmknod to create special files with
|
||||||
specified major numbers.
|
specified major numbers.
|
||||||
3. Modify driver with new major number
|
3.6.3 Modify driver with new major number
|
||||||
Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
|
Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
|
||||||
contains "MXSERMAJOR". Change the content as below.
|
contains "MXSERMAJOR". Change the content as below.
|
||||||
#define MXSERMAJOR 40
|
#define MXSERMAJOR 40
|
||||||
#define MXSERCUMAJOR 45
|
#define MXSERCUMAJOR 45
|
||||||
4. Run # make install in /moxa/mxser/driver.
|
3.6.4 Run "make clean; make install" in /moxa/mxser/driver.
|
||||||
|
|
||||||
3.6 Verify driver installation
|
3.7 Verify driver installation
|
||||||
You may refer to /var/log/messages to check the latest status
|
You may refer to /var/log/messages to check the latest status
|
||||||
log reported by this driver whenever it's activated.
|
log reported by this driver whenever it's activated.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
4. Utilities
|
4. Utilities
|
||||||
There are 3 utilities contained in this driver. They are msdiag, msmon and
|
There are 3 utilities contained in this driver. They are msdiag, msmon and
|
||||||
msterm. These 3 utilities are released in form of source code. They should
|
msterm. These 3 utilities are released in form of source code. They should
|
||||||
be compiled into executable file and copied into /usr/bin.
|
be compiled into executable file and copied into /usr/bin.
|
||||||
|
|
||||||
|
Before using these utilities, please load driver (refer 3.4 & 3.5) and
|
||||||
|
make sure you had run the "msmknod" utility.
|
||||||
|
|
||||||
msdiag - Diagnostic
|
msdiag - Diagnostic
|
||||||
--------------------
|
--------------------
|
||||||
This utility provides the function to detect what Moxa Smartio multiport
|
This utility provides the function to display what Moxa Smartio/Industio
|
||||||
board exists in the system.
|
board found by driver in the system.
|
||||||
|
|
||||||
msmon - Port Monitoring
|
msmon - Port Monitoring
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -353,6 +454,7 @@ Content
|
||||||
application, for example, sending AT command to a modem connected to the
|
application, for example, sending AT command to a modem connected to the
|
||||||
port or used as a terminal for login purpose. Note that this is only a
|
port or used as a terminal for login purpose. Note that this is only a
|
||||||
dumb terminal emulation without handling full screen operation.
|
dumb terminal emulation without handling full screen operation.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
5. Setserial
|
5. Setserial
|
||||||
|
|
||||||
|
@ -366,7 +468,13 @@ Content
|
||||||
being closed, before the receiver is disable.
|
being closed, before the receiver is disable.
|
||||||
spd_hi Use 57.6kb when the application requests 38.4kb.
|
spd_hi Use 57.6kb when the application requests 38.4kb.
|
||||||
spd_vhi Use 115.2kb when the application requests 38.4kb.
|
spd_vhi Use 115.2kb when the application requests 38.4kb.
|
||||||
|
spd_shi Use 230.4kb when the application requests 38.4kb.
|
||||||
|
spd_warp Use 460.8kb when the application requests 38.4kb.
|
||||||
spd_normal Use 38.4kb when the application requests 38.4kb.
|
spd_normal Use 38.4kb when the application requests 38.4kb.
|
||||||
|
spd_cust Use the custom divisor to set the speed when the
|
||||||
|
application requests 38.4kb.
|
||||||
|
divisor This option set the custom divison.
|
||||||
|
baud_base This option set the base baud rate.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
6. Troubleshooting
|
6. Troubleshooting
|
||||||
|
@ -375,8 +483,9 @@ Content
|
||||||
possible. If all the possible solutions fail, please contact our technical
|
possible. If all the possible solutions fail, please contact our technical
|
||||||
support team to get more help.
|
support team to get more help.
|
||||||
|
|
||||||
Error msg: More than 4 Moxa Smartio family boards found. Fifth board and
|
|
||||||
after are ignored.
|
Error msg: More than 4 Moxa Smartio/Industio family boards found. Fifth board
|
||||||
|
and after are ignored.
|
||||||
Solution:
|
Solution:
|
||||||
To avoid this problem, please unplug fifth and after board, because Moxa
|
To avoid this problem, please unplug fifth and after board, because Moxa
|
||||||
driver supports up to 4 boards.
|
driver supports up to 4 boards.
|
||||||
|
@ -384,7 +493,7 @@ Content
|
||||||
Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
|
Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
|
||||||
Solution:
|
Solution:
|
||||||
Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
|
Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
|
||||||
which device causes the situation,please check /proc/interrupts to find
|
which device causes the situation, please check /proc/interrupts to find
|
||||||
free IRQ and simply change another free IRQ for Moxa board.
|
free IRQ and simply change another free IRQ for Moxa board.
|
||||||
|
|
||||||
Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid.
|
Error msg: Board #: C1xx Series(CAP=xxx) interrupt number invalid.
|
||||||
|
@ -397,15 +506,18 @@ Content
|
||||||
Moxa ISA board needs an interrupt vector.Please refer to user's manual
|
Moxa ISA board needs an interrupt vector.Please refer to user's manual
|
||||||
"Hardware Installation" chapter to set interrupt vector.
|
"Hardware Installation" chapter to set interrupt vector.
|
||||||
|
|
||||||
Error msg: Couldn't install MOXA Smartio family driver!
|
Error msg: Couldn't install MOXA Smartio/Industio family driver!
|
||||||
Solution:
|
Solution:
|
||||||
Load Moxa driver fail, the major number may conflict with other devices.
|
Load Moxa driver fail, the major number may conflict with other devices.
|
||||||
Please refer to previous section 3.5 to change a free major number for
|
Please refer to previous section 3.7 to change a free major number for
|
||||||
Moxa driver.
|
Moxa driver.
|
||||||
|
|
||||||
Error msg: Couldn't install MOXA Smartio family callout driver!
|
Error msg: Couldn't install MOXA Smartio/Industio family callout driver!
|
||||||
Solution:
|
Solution:
|
||||||
Load Moxa callout driver fail, the callout device major number may
|
Load Moxa callout driver fail, the callout device major number may
|
||||||
conflict with other devices. Please refer to previous section 3.5 to
|
conflict with other devices. Please refer to previous section 3.7 to
|
||||||
change a free callout device major number for Moxa driver.
|
change a free callout device major number for Moxa driver.
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
8
Documentation/networking/Makefile
Normal file
8
Documentation/networking/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||||
|
obj- := dummy.o
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
hostprogs-y := ifenslave
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
|
@ -631,7 +631,7 @@ xmit_hash_policy
|
||||||
in environments where a layer3 gateway device is
|
in environments where a layer3 gateway device is
|
||||||
required to reach most destinations.
|
required to reach most destinations.
|
||||||
|
|
||||||
This algorithm is 802.3ad complient.
|
This algorithm is 802.3ad compliant.
|
||||||
|
|
||||||
layer3+4
|
layer3+4
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ solution for a couple of reasons:
|
||||||
|
|
||||||
The Linux network devices (by default) just can handle the
|
The Linux network devices (by default) just can handle the
|
||||||
transmission and reception of media dependent frames. Due to the
|
transmission and reception of media dependent frames. Due to the
|
||||||
arbritration on the CAN bus the transmission of a low prio CAN-ID
|
arbitration on the CAN bus the transmission of a low prio CAN-ID
|
||||||
may be delayed by the reception of a high prio CAN frame. To
|
may be delayed by the reception of a high prio CAN frame. To
|
||||||
reflect the correct* traffic on the node the loopback of the sent
|
reflect the correct* traffic on the node the loopback of the sent
|
||||||
data has to be performed right after a successful transmission. If
|
data has to be performed right after a successful transmission. If
|
||||||
|
@ -481,7 +481,7 @@ solution for a couple of reasons:
|
||||||
- stats_timer: To calculate the Socket CAN core statistics
|
- stats_timer: To calculate the Socket CAN core statistics
|
||||||
(e.g. current/maximum frames per second) this 1 second timer is
|
(e.g. current/maximum frames per second) this 1 second timer is
|
||||||
invoked at can.ko module start time by default. This timer can be
|
invoked at can.ko module start time by default. This timer can be
|
||||||
disabled by using stattimer=0 on the module comandline.
|
disabled by using stattimer=0 on the module commandline.
|
||||||
|
|
||||||
- debug: (removed since SocketCAN SVN r546)
|
- debug: (removed since SocketCAN SVN r546)
|
||||||
|
|
||||||
|
|
|
@ -1081,7 +1081,7 @@ static int set_if_addr(char *master_ifname, char *slave_ifname)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipaddr = ifr.ifr_addr.sa_data;
|
ipaddr = (unsigned char *)ifr.ifr_addr.sa_data;
|
||||||
v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n",
|
v_print("Interface '%s': set IP %s to %d.%d.%d.%d\n",
|
||||||
slave_ifname, ifra[i].desc,
|
slave_ifname, ifra[i].desc,
|
||||||
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
|
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
|
||||||
|
|
|
@ -326,7 +326,7 @@ just one call to mmap is needed:
|
||||||
mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
If tp_frame_size is a divisor of tp_block_size frames will be
|
If tp_frame_size is a divisor of tp_block_size frames will be
|
||||||
contiguosly spaced by tp_frame_size bytes. If not, each
|
contiguously spaced by tp_frame_size bytes. If not, each
|
||||||
tp_block_size/tp_frame_size frames there will be a gap between
|
tp_block_size/tp_frame_size frames there will be a gap between
|
||||||
the frames. This is because a frame cannot be spawn across two
|
the frames. This is because a frame cannot be spawn across two
|
||||||
blocks.
|
blocks.
|
||||||
|
|
|
@ -4,26 +4,27 @@ The "enviromental" rules for authors of any new tc actions are:
|
||||||
1) If you stealeth or borroweth any packet thou shalt be branching
|
1) If you stealeth or borroweth any packet thou shalt be branching
|
||||||
from the righteous path and thou shalt cloneth.
|
from the righteous path and thou shalt cloneth.
|
||||||
|
|
||||||
For example if your action queues a packet to be processed later
|
For example if your action queues a packet to be processed later,
|
||||||
or intentionaly branches by redirecting a packet then you need to
|
or intentionally branches by redirecting a packet, then you need to
|
||||||
clone the packet.
|
clone the packet.
|
||||||
|
|
||||||
There are certain fields in the skb tc_verd that need to be reset so we
|
There are certain fields in the skb tc_verd that need to be reset so we
|
||||||
avoid loops etc. A few are generic enough so much so that skb_act_clone()
|
avoid loops, etc. A few are generic enough that skb_act_clone()
|
||||||
resets them for you. So invoke skb_act_clone() rather than skb_clone()
|
resets them for you, so invoke skb_act_clone() rather than skb_clone().
|
||||||
|
|
||||||
2) If you munge any packet thou shalt call pskb_expand_head in the case
|
2) If you munge any packet thou shalt call pskb_expand_head in the case
|
||||||
someone else is referencing the skb. After that you "own" the skb.
|
someone else is referencing the skb. After that you "own" the skb.
|
||||||
You must also tell us if it is ok to munge the packet (TC_OK2MUNGE),
|
You must also tell us if it is ok to munge the packet (TC_OK2MUNGE),
|
||||||
this way any action downstream can stomp on the packet.
|
this way any action downstream can stomp on the packet.
|
||||||
|
|
||||||
3) dropping packets you dont own is a nono. You simply return
|
3) Dropping packets you don't own is a no-no. You simply return
|
||||||
TC_ACT_SHOT to the caller and they will drop it.
|
TC_ACT_SHOT to the caller and they will drop it.
|
||||||
|
|
||||||
The "enviromental" rules for callers of actions (qdiscs etc) are:
|
The "enviromental" rules for callers of actions (qdiscs etc) are:
|
||||||
|
|
||||||
*) thou art responsible for freeing anything returned as being
|
*) Thou art responsible for freeing anything returned as being
|
||||||
TC_ACT_SHOT/STOLEN/QUEUED. If none of TC_ACT_SHOT/STOLEN/QUEUED is
|
TC_ACT_SHOT/STOLEN/QUEUED. If none of TC_ACT_SHOT/STOLEN/QUEUED is
|
||||||
returned then all is great and you dont need to do anything.
|
returned, then all is great and you don't need to do anything.
|
||||||
|
|
||||||
Post on netdev if something is unclear.
|
Post on netdev if something is unclear.
|
||||||
|
|
||||||
|
|
10
Documentation/pcmcia/Makefile
Normal file
10
Documentation/pcmcia/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||||
|
obj- := dummy.o
|
||||||
|
|
||||||
|
# List of programs to build
|
||||||
|
hostprogs-y := crc32hash
|
||||||
|
|
||||||
|
# Tell kbuild to always build the programs
|
||||||
|
always := $(hostprogs-y)
|
||||||
|
|
||||||
|
HOSTCFLAGS_crc32hash.o += -I$(objtree)/usr/include
|
|
@ -26,7 +26,7 @@ int main(int argc, char **argv) {
|
||||||
printf("no string passed as argument\n");
|
printf("no string passed as argument\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
result = crc32(argv[1], strlen(argv[1]));
|
result = crc32((unsigned char const *)argv[1], strlen(argv[1]));
|
||||||
printf("0x%x\n", result);
|
printf("0x%x\n", result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
PM quality of Service interface.
|
PM Quality Of Service Interface.
|
||||||
|
|
||||||
This interface provides a kernel and user mode interface for registering
|
This interface provides a kernel and user mode interface for registering
|
||||||
performance expectations by drivers, subsystems and user space applications on
|
performance expectations by drivers, subsystems and user space applications on
|
||||||
|
@ -7,6 +7,11 @@ one of the parameters.
|
||||||
Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
|
Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
|
||||||
initial set of pm_qos parameters.
|
initial set of pm_qos parameters.
|
||||||
|
|
||||||
|
Each parameters have defined units:
|
||||||
|
* latency: usec
|
||||||
|
* timeout: usec
|
||||||
|
* throughput: kbs (kilo bit / sec)
|
||||||
|
|
||||||
The infrastructure exposes multiple misc device nodes one per implemented
|
The infrastructure exposes multiple misc device nodes one per implemented
|
||||||
parameter. The set of parameters implement is defined by pm_qos_power_init()
|
parameter. The set of parameters implement is defined by pm_qos_power_init()
|
||||||
and pm_qos_params.h. This is done because having the available parameters
|
and pm_qos_params.h. This is done because having the available parameters
|
||||||
|
|
|
@ -101,6 +101,10 @@ of charge when battery became full/empty". It also could mean "value of
|
||||||
charge when battery considered full/empty at given conditions (temperature,
|
charge when battery considered full/empty at given conditions (temperature,
|
||||||
age)". I.e. these attributes represents real thresholds, not design values.
|
age)". I.e. these attributes represents real thresholds, not design values.
|
||||||
|
|
||||||
|
CHARGE_COUNTER - the current charge counter (in µAh). This could easily
|
||||||
|
be negative; there is no empty or full value. It is only useful for
|
||||||
|
relative, time-based measurements.
|
||||||
|
|
||||||
ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
|
ENERGY_FULL, ENERGY_EMPTY - same as above but for energy.
|
||||||
|
|
||||||
CAPACITY - capacity in percents.
|
CAPACITY - capacity in percents.
|
||||||
|
|
182
Documentation/power/regulator/consumer.txt
Normal file
182
Documentation/power/regulator/consumer.txt
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
Regulator Consumer Driver Interface
|
||||||
|
===================================
|
||||||
|
|
||||||
|
This text describes the regulator interface for consumer device drivers.
|
||||||
|
Please see overview.txt for a description of the terms used in this text.
|
||||||
|
|
||||||
|
|
||||||
|
1. Consumer Regulator Access (static & dynamic drivers)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
A consumer driver can get access to it's supply regulator by calling :-
|
||||||
|
|
||||||
|
regulator = regulator_get(dev, "Vcc");
|
||||||
|
|
||||||
|
The consumer passes in it's struct device pointer and power supply ID. The core
|
||||||
|
then finds the correct regulator by consulting a machine specific lookup table.
|
||||||
|
If the lookup is successful then this call will return a pointer to the struct
|
||||||
|
regulator that supplies this consumer.
|
||||||
|
|
||||||
|
To release the regulator the consumer driver should call :-
|
||||||
|
|
||||||
|
regulator_put(regulator);
|
||||||
|
|
||||||
|
Consumers can be supplied by more than one regulator e.g. codec consumer with
|
||||||
|
analog and digital supplies :-
|
||||||
|
|
||||||
|
digital = regulator_get(dev, "Vcc"); /* digital core */
|
||||||
|
analog = regulator_get(dev, "Avdd"); /* analog */
|
||||||
|
|
||||||
|
The regulator access functions regulator_get() and regulator_put() will
|
||||||
|
usually be called in your device drivers probe() and remove() respectively.
|
||||||
|
|
||||||
|
|
||||||
|
2. Regulator Output Enable & Disable (static & dynamic drivers)
|
||||||
|
====================================================================
|
||||||
|
|
||||||
|
A consumer can enable it's power supply by calling:-
|
||||||
|
|
||||||
|
int regulator_enable(regulator);
|
||||||
|
|
||||||
|
NOTE: The supply may already be enabled before regulator_enabled() is called.
|
||||||
|
This may happen if the consumer shares the regulator or the regulator has been
|
||||||
|
previously enabled by bootloader or kernel board initialization code.
|
||||||
|
|
||||||
|
A consumer can determine if a regulator is enabled by calling :-
|
||||||
|
|
||||||
|
int regulator_is_enabled(regulator);
|
||||||
|
|
||||||
|
This will return > zero when the regulator is enabled.
|
||||||
|
|
||||||
|
|
||||||
|
A consumer can disable it's supply when no longer needed by calling :-
|
||||||
|
|
||||||
|
int regulator_disable(regulator);
|
||||||
|
|
||||||
|
NOTE: This may not disable the supply if it's shared with other consumers. The
|
||||||
|
regulator will only be disabled when the enabled reference count is zero.
|
||||||
|
|
||||||
|
Finally, a regulator can be forcefully disabled in the case of an emergency :-
|
||||||
|
|
||||||
|
int regulator_force_disable(regulator);
|
||||||
|
|
||||||
|
NOTE: this will immediately and forcefully shutdown the regulator output. All
|
||||||
|
consumers will be powered off.
|
||||||
|
|
||||||
|
|
||||||
|
3. Regulator Voltage Control & Status (dynamic drivers)
|
||||||
|
======================================================
|
||||||
|
|
||||||
|
Some consumer drivers need to be able to dynamically change their supply
|
||||||
|
voltage to match system operating points. e.g. CPUfreq drivers can scale
|
||||||
|
voltage along with frequency to save power, SD drivers may need to select the
|
||||||
|
correct card voltage, etc.
|
||||||
|
|
||||||
|
Consumers can control their supply voltage by calling :-
|
||||||
|
|
||||||
|
int regulator_set_voltage(regulator, min_uV, max_uV);
|
||||||
|
|
||||||
|
Where min_uV and max_uV are the minimum and maximum acceptable voltages in
|
||||||
|
microvolts.
|
||||||
|
|
||||||
|
NOTE: this can be called when the regulator is enabled or disabled. If called
|
||||||
|
when enabled, then the voltage changes instantly, otherwise the voltage
|
||||||
|
configuration changes and the voltage is physically set when the regulator is
|
||||||
|
next enabled.
|
||||||
|
|
||||||
|
The regulators configured voltage output can be found by calling :-
|
||||||
|
|
||||||
|
int regulator_get_voltage(regulator);
|
||||||
|
|
||||||
|
NOTE: get_voltage() will return the configured output voltage whether the
|
||||||
|
regulator is enabled or disabled and should NOT be used to determine regulator
|
||||||
|
output state. However this can be used in conjunction with is_enabled() to
|
||||||
|
determine the regulator physical output voltage.
|
||||||
|
|
||||||
|
|
||||||
|
4. Regulator Current Limit Control & Status (dynamic drivers)
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
Some consumer drivers need to be able to dynamically change their supply
|
||||||
|
current limit to match system operating points. e.g. LCD backlight driver can
|
||||||
|
change the current limit to vary the backlight brightness, USB drivers may want
|
||||||
|
to set the limit to 500mA when supplying power.
|
||||||
|
|
||||||
|
Consumers can control their supply current limit by calling :-
|
||||||
|
|
||||||
|
int regulator_set_current_limit(regulator, min_uV, max_uV);
|
||||||
|
|
||||||
|
Where min_uA and max_uA are the minimum and maximum acceptable current limit in
|
||||||
|
microamps.
|
||||||
|
|
||||||
|
NOTE: this can be called when the regulator is enabled or disabled. If called
|
||||||
|
when enabled, then the current limit changes instantly, otherwise the current
|
||||||
|
limit configuration changes and the current limit is physically set when the
|
||||||
|
regulator is next enabled.
|
||||||
|
|
||||||
|
A regulators current limit can be found by calling :-
|
||||||
|
|
||||||
|
int regulator_get_current_limit(regulator);
|
||||||
|
|
||||||
|
NOTE: get_current_limit() will return the current limit whether the regulator
|
||||||
|
is enabled or disabled and should not be used to determine regulator current
|
||||||
|
load.
|
||||||
|
|
||||||
|
|
||||||
|
5. Regulator Operating Mode Control & Status (dynamic drivers)
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
Some consumers can further save system power by changing the operating mode of
|
||||||
|
their supply regulator to be more efficient when the consumers operating state
|
||||||
|
changes. e.g. consumer driver is idle and subsequently draws less current
|
||||||
|
|
||||||
|
Regulator operating mode can be changed indirectly or directly.
|
||||||
|
|
||||||
|
Indirect operating mode control.
|
||||||
|
--------------------------------
|
||||||
|
Consumer drivers can request a change in their supply regulator operating mode
|
||||||
|
by calling :-
|
||||||
|
|
||||||
|
int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
|
||||||
|
|
||||||
|
This will cause the core to recalculate the total load on the regulator (based
|
||||||
|
on all it's consumers) and change operating mode (if necessary and permitted)
|
||||||
|
to best match the current operating load.
|
||||||
|
|
||||||
|
The load_uA value can be determined from the consumers datasheet. e.g.most
|
||||||
|
datasheets have tables showing the max current consumed in certain situations.
|
||||||
|
|
||||||
|
Most consumers will use indirect operating mode control since they have no
|
||||||
|
knowledge of the regulator or whether the regulator is shared with other
|
||||||
|
consumers.
|
||||||
|
|
||||||
|
Direct operating mode control.
|
||||||
|
------------------------------
|
||||||
|
Bespoke or tightly coupled drivers may want to directly control regulator
|
||||||
|
operating mode depending on their operating point. This can be achieved by
|
||||||
|
calling :-
|
||||||
|
|
||||||
|
int regulator_set_mode(struct regulator *regulator, unsigned int mode);
|
||||||
|
unsigned int regulator_get_mode(struct regulator *regulator);
|
||||||
|
|
||||||
|
Direct mode will only be used by consumers that *know* about the regulator and
|
||||||
|
are not sharing the regulator with other consumers.
|
||||||
|
|
||||||
|
|
||||||
|
6. Regulator Events
|
||||||
|
===================
|
||||||
|
Regulators can notify consumers of external events. Events could be received by
|
||||||
|
consumers under regulator stress or failure conditions.
|
||||||
|
|
||||||
|
Consumers can register interest in regulator events by calling :-
|
||||||
|
|
||||||
|
int regulator_register_notifier(struct regulator *regulator,
|
||||||
|
struct notifier_block *nb);
|
||||||
|
|
||||||
|
Consumers can uregister interest by calling :-
|
||||||
|
|
||||||
|
int regulator_unregister_notifier(struct regulator *regulator,
|
||||||
|
struct notifier_block *nb);
|
||||||
|
|
||||||
|
Regulators use the kernel notifier framework to send event to thier interested
|
||||||
|
consumers.
|
101
Documentation/power/regulator/machine.txt
Normal file
101
Documentation/power/regulator/machine.txt
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
Regulator Machine Driver Interface
|
||||||
|
===================================
|
||||||
|
|
||||||
|
The regulator machine driver interface is intended for board/machine specific
|
||||||
|
initialisation code to configure the regulator subsystem. Typical things that
|
||||||
|
machine drivers would do are :-
|
||||||
|
|
||||||
|
1. Regulator -> Device mapping.
|
||||||
|
2. Regulator supply configuration.
|
||||||
|
3. Power Domain constraint setting.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1. Regulator -> device mapping
|
||||||
|
==============================
|
||||||
|
Consider the following machine :-
|
||||||
|
|
||||||
|
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
|
||||||
|
|
|
||||||
|
+-> [Consumer B @ 3.3V]
|
||||||
|
|
||||||
|
The drivers for consumers A & B must be mapped to the correct regulator in
|
||||||
|
order to control their power supply. This mapping can be achieved in machine
|
||||||
|
initialisation code by calling :-
|
||||||
|
|
||||||
|
int regulator_set_device_supply(const char *regulator, struct device *dev,
|
||||||
|
const char *supply);
|
||||||
|
|
||||||
|
and is shown with the following code :-
|
||||||
|
|
||||||
|
regulator_set_device_supply("Regulator-1", devB, "Vcc");
|
||||||
|
regulator_set_device_supply("Regulator-2", devA, "Vcc");
|
||||||
|
|
||||||
|
This maps Regulator-1 to the 'Vcc' supply for Consumer B and maps Regulator-2
|
||||||
|
to the 'Vcc' supply for Consumer A.
|
||||||
|
|
||||||
|
|
||||||
|
2. Regulator supply configuration.
|
||||||
|
==================================
|
||||||
|
Consider the following machine (again) :-
|
||||||
|
|
||||||
|
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
|
||||||
|
|
|
||||||
|
+-> [Consumer B @ 3.3V]
|
||||||
|
|
||||||
|
Regulator-1 supplies power to Regulator-2. This relationship must be registered
|
||||||
|
with the core so that Regulator-1 is also enabled when Consumer A enables it's
|
||||||
|
supply (Regulator-2).
|
||||||
|
|
||||||
|
This relationship can be register with the core via :-
|
||||||
|
|
||||||
|
int regulator_set_supply(const char *regulator, const char *regulator_supply);
|
||||||
|
|
||||||
|
In this example we would use the following code :-
|
||||||
|
|
||||||
|
regulator_set_supply("Regulator-2", "Regulator-1");
|
||||||
|
|
||||||
|
Relationships can be queried by calling :-
|
||||||
|
|
||||||
|
const char *regulator_get_supply(const char *regulator);
|
||||||
|
|
||||||
|
|
||||||
|
3. Power Domain constraint setting.
|
||||||
|
===================================
|
||||||
|
Each power domain within a system has physical constraints on voltage and
|
||||||
|
current. This must be defined in software so that the power domain is always
|
||||||
|
operated within specifications.
|
||||||
|
|
||||||
|
Consider the following machine (again) :-
|
||||||
|
|
||||||
|
Regulator-1 -+-> Regulator-2 --> [Consumer A @ 1.8 - 2.0V]
|
||||||
|
|
|
||||||
|
+-> [Consumer B @ 3.3V]
|
||||||
|
|
||||||
|
This gives us two regulators and two power domains:
|
||||||
|
|
||||||
|
Domain 1: Regulator-2, Consumer B.
|
||||||
|
Domain 2: Consumer A.
|
||||||
|
|
||||||
|
Constraints can be registered by calling :-
|
||||||
|
|
||||||
|
int regulator_set_platform_constraints(const char *regulator,
|
||||||
|
struct regulation_constraints *constraints);
|
||||||
|
|
||||||
|
The example is defined as follows :-
|
||||||
|
|
||||||
|
struct regulation_constraints domain_1 = {
|
||||||
|
.min_uV = 3300000,
|
||||||
|
.max_uV = 3300000,
|
||||||
|
.valid_modes_mask = REGULATOR_MODE_NORMAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regulation_constraints domain_2 = {
|
||||||
|
.min_uV = 1800000,
|
||||||
|
.max_uV = 2000000,
|
||||||
|
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
|
||||||
|
.valid_modes_mask = REGULATOR_MODE_NORMAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
regulator_set_platform_constraints("Regulator-1", &domain_1);
|
||||||
|
regulator_set_platform_constraints("Regulator-2", &domain_2);
|
171
Documentation/power/regulator/overview.txt
Normal file
171
Documentation/power/regulator/overview.txt
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
Linux voltage and current regulator framework
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
About
|
||||||
|
=====
|
||||||
|
|
||||||
|
This framework is designed to provide a standard kernel interface to control
|
||||||
|
voltage and current regulators.
|
||||||
|
|
||||||
|
The intention is to allow systems to dynamically control regulator power output
|
||||||
|
in order to save power and prolong battery life. This applies to both voltage
|
||||||
|
regulators (where voltage output is controllable) and current sinks (where
|
||||||
|
current limit is controllable).
|
||||||
|
|
||||||
|
(C) 2008 Wolfson Microelectronics PLC.
|
||||||
|
Author: Liam Girdwood <lg@opensource.wolfsonmicro.com>
|
||||||
|
|
||||||
|
|
||||||
|
Nomenclature
|
||||||
|
============
|
||||||
|
|
||||||
|
Some terms used in this document:-
|
||||||
|
|
||||||
|
o Regulator - Electronic device that supplies power to other devices.
|
||||||
|
Most regulators can enable and disable their output whilst
|
||||||
|
some can control their output voltage and or current.
|
||||||
|
|
||||||
|
Input Voltage -> Regulator -> Output Voltage
|
||||||
|
|
||||||
|
|
||||||
|
o PMIC - Power Management IC. An IC that contains numerous regulators
|
||||||
|
and often contains other susbsystems.
|
||||||
|
|
||||||
|
|
||||||
|
o Consumer - Electronic device that is supplied power by a regulator.
|
||||||
|
Consumers can be classified into two types:-
|
||||||
|
|
||||||
|
Static: consumer does not change it's supply voltage or
|
||||||
|
current limit. It only needs to enable or disable it's
|
||||||
|
power supply. It's supply voltage is set by the hardware,
|
||||||
|
bootloader, firmware or kernel board initialisation code.
|
||||||
|
|
||||||
|
Dynamic: consumer needs to change it's supply voltage or
|
||||||
|
current limit to meet operation demands.
|
||||||
|
|
||||||
|
|
||||||
|
o Power Domain - Electronic circuit that is supplied it's input power by the
|
||||||
|
output power of a regulator, switch or by another power
|
||||||
|
domain.
|
||||||
|
|
||||||
|
The supply regulator may be behind a switch(s). i.e.
|
||||||
|
|
||||||
|
Regulator -+-> Switch-1 -+-> Switch-2 --> [Consumer A]
|
||||||
|
| |
|
||||||
|
| +-> [Consumer B], [Consumer C]
|
||||||
|
|
|
||||||
|
+-> [Consumer D], [Consumer E]
|
||||||
|
|
||||||
|
That is one regulator and three power domains:
|
||||||
|
|
||||||
|
Domain 1: Switch-1, Consumers D & E.
|
||||||
|
Domain 2: Switch-2, Consumers B & C.
|
||||||
|
Domain 3: Consumer A.
|
||||||
|
|
||||||
|
and this represents a "supplies" relationship:
|
||||||
|
|
||||||
|
Domain-1 --> Domain-2 --> Domain-3.
|
||||||
|
|
||||||
|
A power domain may have regulators that are supplied power
|
||||||
|
by other regulators. i.e.
|
||||||
|
|
||||||
|
Regulator-1 -+-> Regulator-2 -+-> [Consumer A]
|
||||||
|
|
|
||||||
|
+-> [Consumer B]
|
||||||
|
|
||||||
|
This gives us two regulators and two power domains:
|
||||||
|
|
||||||
|
Domain 1: Regulator-2, Consumer B.
|
||||||
|
Domain 2: Consumer A.
|
||||||
|
|
||||||
|
and a "supplies" relationship:
|
||||||
|
|
||||||
|
Domain-1 --> Domain-2
|
||||||
|
|
||||||
|
|
||||||
|
o Constraints - Constraints are used to define power levels for performance
|
||||||
|
and hardware protection. Constraints exist at three levels:
|
||||||
|
|
||||||
|
Regulator Level: This is defined by the regulator hardware
|
||||||
|
operating parameters and is specified in the regulator
|
||||||
|
datasheet. i.e.
|
||||||
|
|
||||||
|
- voltage output is in the range 800mV -> 3500mV.
|
||||||
|
- regulator current output limit is 20mA @ 5V but is
|
||||||
|
10mA @ 10V.
|
||||||
|
|
||||||
|
Power Domain Level: This is defined in software by kernel
|
||||||
|
level board initialisation code. It is used to constrain a
|
||||||
|
power domain to a particular power range. i.e.
|
||||||
|
|
||||||
|
- Domain-1 voltage is 3300mV
|
||||||
|
- Domain-2 voltage is 1400mV -> 1600mV
|
||||||
|
- Domain-3 current limit is 0mA -> 20mA.
|
||||||
|
|
||||||
|
Consumer Level: This is defined by consumer drivers
|
||||||
|
dynamically setting voltage or current limit levels.
|
||||||
|
|
||||||
|
e.g. a consumer backlight driver asks for a current increase
|
||||||
|
from 5mA to 10mA to increase LCD illumination. This passes
|
||||||
|
to through the levels as follows :-
|
||||||
|
|
||||||
|
Consumer: need to increase LCD brightness. Lookup and
|
||||||
|
request next current mA value in brightness table (the
|
||||||
|
consumer driver could be used on several different
|
||||||
|
personalities based upon the same reference device).
|
||||||
|
|
||||||
|
Power Domain: is the new current limit within the domain
|
||||||
|
operating limits for this domain and system state (e.g.
|
||||||
|
battery power, USB power)
|
||||||
|
|
||||||
|
Regulator Domains: is the new current limit within the
|
||||||
|
regulator operating parameters for input/ouput voltage.
|
||||||
|
|
||||||
|
If the regulator request passes all the constraint tests
|
||||||
|
then the new regulator value is applied.
|
||||||
|
|
||||||
|
|
||||||
|
Design
|
||||||
|
======
|
||||||
|
|
||||||
|
The framework is designed and targeted at SoC based devices but may also be
|
||||||
|
relevant to non SoC devices and is split into the following four interfaces:-
|
||||||
|
|
||||||
|
|
||||||
|
1. Consumer driver interface.
|
||||||
|
|
||||||
|
This uses a similar API to the kernel clock interface in that consumer
|
||||||
|
drivers can get and put a regulator (like they can with clocks atm) and
|
||||||
|
get/set voltage, current limit, mode, enable and disable. This should
|
||||||
|
allow consumers complete control over their supply voltage and current
|
||||||
|
limit. This also compiles out if not in use so drivers can be reused in
|
||||||
|
systems with no regulator based power control.
|
||||||
|
|
||||||
|
See Documentation/power/regulator/consumer.txt
|
||||||
|
|
||||||
|
2. Regulator driver interface.
|
||||||
|
|
||||||
|
This allows regulator drivers to register their regulators and provide
|
||||||
|
operations to the core. It also has a notifier call chain for propagating
|
||||||
|
regulator events to clients.
|
||||||
|
|
||||||
|
See Documentation/power/regulator/regulator.txt
|
||||||
|
|
||||||
|
3. Machine interface.
|
||||||
|
|
||||||
|
This interface is for machine specific code and allows the creation of
|
||||||
|
voltage/current domains (with constraints) for each regulator. It can
|
||||||
|
provide regulator constraints that will prevent device damage through
|
||||||
|
overvoltage or over current caused by buggy client drivers. It also
|
||||||
|
allows the creation of a regulator tree whereby some regulators are
|
||||||
|
supplied by others (similar to a clock tree).
|
||||||
|
|
||||||
|
See Documentation/power/regulator/machine.txt
|
||||||
|
|
||||||
|
4. Userspace ABI.
|
||||||
|
|
||||||
|
The framework also exports a lot of useful voltage/current/opmode data to
|
||||||
|
userspace via sysfs. This could be used to help monitor device power
|
||||||
|
consumption and status.
|
||||||
|
|
||||||
|
See Documentation/ABI/testing/regulator-sysfs.txt
|
30
Documentation/power/regulator/regulator.txt
Normal file
30
Documentation/power/regulator/regulator.txt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
Regulator Driver Interface
|
||||||
|
==========================
|
||||||
|
|
||||||
|
The regulator driver interface is relatively simple and designed to allow
|
||||||
|
regulator drivers to register their services with the core framework.
|
||||||
|
|
||||||
|
|
||||||
|
Registration
|
||||||
|
============
|
||||||
|
|
||||||
|
Drivers can register a regulator by calling :-
|
||||||
|
|
||||||
|
struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
|
||||||
|
void *reg_data);
|
||||||
|
|
||||||
|
This will register the regulators capabilities and operations the regulator
|
||||||
|
core. The core does not touch reg_data (private to regulator driver).
|
||||||
|
|
||||||
|
Regulators can be unregistered by calling :-
|
||||||
|
|
||||||
|
void regulator_unregister(struct regulator_dev *rdev);
|
||||||
|
|
||||||
|
|
||||||
|
Regulator Events
|
||||||
|
================
|
||||||
|
Regulators can send events (e.g. over temp, under voltage, etc) to consumer
|
||||||
|
drivers by calling :-
|
||||||
|
|
||||||
|
int regulator_notifier_call_chain(struct regulator_dev *rdev,
|
||||||
|
unsigned long event, void *data);
|
|
@ -20,8 +20,6 @@ mpc52xx-device-tree-bindings.txt
|
||||||
- MPC5200 Device Tree Bindings
|
- MPC5200 Device Tree Bindings
|
||||||
ppc_htab.txt
|
ppc_htab.txt
|
||||||
- info about the Linux/PPC /proc/ppc_htab entry
|
- info about the Linux/PPC /proc/ppc_htab entry
|
||||||
SBC8260_memory_mapping.txt
|
|
||||||
- EST SBC8260 board info
|
|
||||||
smp.txt
|
smp.txt
|
||||||
- use and state info about Linux/PPC on MP machines
|
- use and state info about Linux/PPC on MP machines
|
||||||
sound.txt
|
sound.txt
|
||||||
|
|
|
@ -1,197 +0,0 @@
|
||||||
Please mail me (Jon Diekema, diekema_jon@si.com or diekema@cideas.com)
|
|
||||||
if you have questions, comments or corrections.
|
|
||||||
|
|
||||||
* EST SBC8260 Linux memory mapping rules
|
|
||||||
|
|
||||||
http://www.estc.com/
|
|
||||||
http://www.estc.com/products/boards/SBC8260-8240_ds.html
|
|
||||||
|
|
||||||
Initial conditions:
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Tasks that need to be perform by the boot ROM before control is
|
|
||||||
transferred to zImage (compressed Linux kernel):
|
|
||||||
|
|
||||||
- Define the IMMR to 0xf0000000
|
|
||||||
|
|
||||||
- Initialize the memory controller so that RAM is available at
|
|
||||||
physical address 0x00000000. On the SBC8260 is this 16M (64M)
|
|
||||||
SDRAM.
|
|
||||||
|
|
||||||
- The boot ROM should only clear the RAM that it is using.
|
|
||||||
|
|
||||||
The reason for doing this is to enhances the chances of a
|
|
||||||
successful post mortem on a Linux panic. One of the first
|
|
||||||
items to examine is the 16k (LOG_BUF_LEN) circular console
|
|
||||||
buffer called log_buf which is defined in kernel/printk.c.
|
|
||||||
|
|
||||||
- To enhance boot ROM performance, the I-cache can be enabled.
|
|
||||||
|
|
||||||
Date: Mon, 22 May 2000 14:21:10 -0700
|
|
||||||
From: Neil Russell <caret@c-side.com>
|
|
||||||
|
|
||||||
LiMon (LInux MONitor) runs with and starts Linux with MMU
|
|
||||||
off, I-cache enabled, D-cache disabled. The I-cache doesn't
|
|
||||||
need hints from the MMU to work correctly as the D-cache
|
|
||||||
does. No D-cache means no special code to handle devices in
|
|
||||||
the presence of cache (no snooping, etc). The use of the
|
|
||||||
I-cache means that the monitor can run acceptably fast
|
|
||||||
directly from ROM, rather than having to copy it to RAM.
|
|
||||||
|
|
||||||
- Build the board information structure (see
|
|
||||||
include/asm-ppc/est8260.h for its definition)
|
|
||||||
|
|
||||||
- The compressed Linux kernel (zImage) contains a bootstrap loader
|
|
||||||
that is position independent; you can load it into any RAM,
|
|
||||||
ROM or FLASH memory address >= 0x00500000 (above 5 MB), or
|
|
||||||
at its link address of 0x00400000 (4 MB).
|
|
||||||
|
|
||||||
Note: If zImage is loaded at its link address of 0x00400000 (4 MB),
|
|
||||||
then zImage will skip the step of moving itself to
|
|
||||||
its link address.
|
|
||||||
|
|
||||||
- Load R3 with the address of the board information structure
|
|
||||||
|
|
||||||
- Transfer control to zImage
|
|
||||||
|
|
||||||
- The Linux console port is SMC1, and the baud rate is controlled
|
|
||||||
from the bi_baudrate field of the board information structure.
|
|
||||||
On thing to keep in mind when picking the baud rate, is that
|
|
||||||
there is no flow control on the SMC ports. I would stick
|
|
||||||
with something safe and standard like 19200.
|
|
||||||
|
|
||||||
On the EST SBC8260, the SMC1 port is on the COM1 connector of
|
|
||||||
the board.
|
|
||||||
|
|
||||||
|
|
||||||
EST SBC8260 defaults:
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Chip
|
|
||||||
Memory Sel Bus Use
|
|
||||||
--------------------- --- --- ----------------------------------
|
|
||||||
0x00000000-0x03FFFFFF CS2 60x (16M or 64M)/64M SDRAM
|
|
||||||
0x04000000-0x04FFFFFF CS4 local 4M/16M SDRAM (soldered to the board)
|
|
||||||
0x21000000-0x21000000 CS7 60x 1B/64K Flash present detect (from the flash SIMM)
|
|
||||||
0x21000001-0x21000001 CS7 60x 1B/64K Switches (read) and LEDs (write)
|
|
||||||
0x22000000-0x2200FFFF CS5 60x 8K/64K EEPROM
|
|
||||||
0xFC000000-0xFCFFFFFF CS6 60x 2M/16M flash (8 bits wide, soldered to the board)
|
|
||||||
0xFE000000-0xFFFFFFFF CS0 60x 4M/16M flash (SIMM)
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
------
|
|
||||||
|
|
||||||
- The chip selects can map 32K blocks and up (powers of 2)
|
|
||||||
|
|
||||||
- The SDRAM machine can handled up to 128Mbytes per chip select
|
|
||||||
|
|
||||||
- Linux uses the 60x bus memory (the SDRAM DIMM) for the
|
|
||||||
communications buffers.
|
|
||||||
|
|
||||||
- BATs can map 128K-256Mbytes each. There are four data BATs and
|
|
||||||
four instruction BATs. Generally the data and instruction BATs
|
|
||||||
are mapped the same.
|
|
||||||
|
|
||||||
- The IMMR must be set above the kernel virtual memory addresses,
|
|
||||||
which start at 0xC0000000. Otherwise, the kernel may crash as
|
|
||||||
soon as you start any threads or processes due to VM collisions
|
|
||||||
in the kernel or user process space.
|
|
||||||
|
|
||||||
|
|
||||||
Details from Dan Malek <dan_malek@mvista.com> on 10/29/1999:
|
|
||||||
|
|
||||||
The user application virtual space consumes the first 2 Gbytes
|
|
||||||
(0x00000000 to 0x7FFFFFFF). The kernel virtual text starts at
|
|
||||||
0xC0000000, with data following. There is a "protection hole"
|
|
||||||
between the end of kernel data and the start of the kernel
|
|
||||||
dynamically allocated space, but this space is still within
|
|
||||||
0xCxxxxxxx.
|
|
||||||
|
|
||||||
Obviously the kernel can't map any physical addresses 1:1 in
|
|
||||||
these ranges.
|
|
||||||
|
|
||||||
|
|
||||||
Details from Dan Malek <dan_malek@mvista.com> on 5/19/2000:
|
|
||||||
|
|
||||||
During the early kernel initialization, the kernel virtual
|
|
||||||
memory allocator is not operational. Prior to this KVM
|
|
||||||
initialization, we choose to map virtual to physical addresses
|
|
||||||
1:1. That is, the kernel virtual address exactly matches the
|
|
||||||
physical address on the bus. These mappings are typically done
|
|
||||||
in arch/ppc/kernel/head.S, or arch/ppc/mm/init.c. Only
|
|
||||||
absolutely necessary mappings should be done at this time, for
|
|
||||||
example board control registers or a serial uart. Normal device
|
|
||||||
driver initialization should map resources later when necessary.
|
|
||||||
|
|
||||||
Although platform dependent, and certainly the case for embedded
|
|
||||||
8xx, traditionally memory is mapped at physical address zero,
|
|
||||||
and I/O devices above physical address 0x80000000. The lowest
|
|
||||||
and highest (above 0xf0000000) I/O addresses are traditionally
|
|
||||||
used for devices or registers we need to map during kernel
|
|
||||||
initialization and prior to KVM operation. For this reason,
|
|
||||||
and since it followed prior PowerPC platform examples, I chose
|
|
||||||
to map the embedded 8xx kernel to the 0xc0000000 virtual address.
|
|
||||||
This way, we can enable the MMU to map the kernel for proper
|
|
||||||
operation, and still map a few windows before the KVM is operational.
|
|
||||||
|
|
||||||
On some systems, you could possibly run the kernel at the
|
|
||||||
0x80000000 or any other virtual address. It just depends upon
|
|
||||||
mapping that must be done prior to KVM operational. You can never
|
|
||||||
map devices or kernel spaces that overlap with the user virtual
|
|
||||||
space. This is why default IMMR mapping used by most BDM tools
|
|
||||||
won't work. They put the IMMR at something like 0x10000000 or
|
|
||||||
0x02000000 for example. You simply can't map these addresses early
|
|
||||||
in the kernel, and continue proper system operation.
|
|
||||||
|
|
||||||
The embedded 8xx/82xx kernel is mature enough that all you should
|
|
||||||
need to do is map the IMMR someplace at or above 0xf0000000 and it
|
|
||||||
should boot far enough to get serial console messages and KGDB
|
|
||||||
connected on any platform. There are lots of other subtle memory
|
|
||||||
management design features that you simply don't need to worry
|
|
||||||
about. If you are changing functions related to MMU initialization,
|
|
||||||
you are likely breaking things that are known to work and are
|
|
||||||
heading down a path of disaster and frustration. Your changes
|
|
||||||
should be to make the flexibility of the processor fit Linux,
|
|
||||||
not force arbitrary and non-workable memory mappings into Linux.
|
|
||||||
|
|
||||||
- You don't want to change KERNELLOAD or KERNELBASE, otherwise the
|
|
||||||
virtual memory and MMU code will get confused.
|
|
||||||
|
|
||||||
arch/ppc/Makefile:KERNELLOAD = 0xc0000000
|
|
||||||
|
|
||||||
include/asm-ppc/page.h:#define PAGE_OFFSET 0xc0000000
|
|
||||||
include/asm-ppc/page.h:#define KERNELBASE PAGE_OFFSET
|
|
||||||
|
|
||||||
- RAM is at physical address 0x00000000, and gets mapped to
|
|
||||||
virtual address 0xC0000000 for the kernel.
|
|
||||||
|
|
||||||
|
|
||||||
Physical addresses used by the Linux kernel:
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
0x00000000-0x3FFFFFFF 1GB reserved for RAM
|
|
||||||
0xF0000000-0xF001FFFF 128K IMMR 64K used for dual port memory,
|
|
||||||
64K for 8260 registers
|
|
||||||
|
|
||||||
|
|
||||||
Logical addresses used by the Linux kernel:
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
0xF0000000-0xFFFFFFFF 256M BAT0 (IMMR: dual port RAM, registers)
|
|
||||||
0xE0000000-0xEFFFFFFF 256M BAT1 (I/O space for custom boards)
|
|
||||||
0xC0000000-0xCFFFFFFF 256M BAT2 (RAM)
|
|
||||||
0xD0000000-0xDFFFFFFF 256M BAT3 (if RAM > 256MByte)
|
|
||||||
|
|
||||||
|
|
||||||
EST SBC8260 Linux mapping:
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
DBAT0, IBAT0, cache inhibited:
|
|
||||||
|
|
||||||
Chip
|
|
||||||
Memory Sel Use
|
|
||||||
--------------------- --- ---------------------------------
|
|
||||||
0xF0000000-0xF001FFFF n/a IMMR: dual port RAM, registers
|
|
||||||
|
|
||||||
DBAT1, IBAT1, cache inhibited:
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ Table of Contents
|
||||||
p) Freescale Synchronous Serial Interface
|
p) Freescale Synchronous Serial Interface
|
||||||
q) USB EHCI controllers
|
q) USB EHCI controllers
|
||||||
r) MDIO on GPIOs
|
r) MDIO on GPIOs
|
||||||
|
s) SPI busses
|
||||||
|
|
||||||
VII - Marvell Discovery mv64[345]6x System Controller chips
|
VII - Marvell Discovery mv64[345]6x System Controller chips
|
||||||
1) The /system-controller node
|
1) The /system-controller node
|
||||||
|
@ -277,7 +278,7 @@ it with special cases.
|
||||||
a 64-bit platform.
|
a 64-bit platform.
|
||||||
|
|
||||||
d) request and get assigned a platform number (see PLATFORM_*
|
d) request and get assigned a platform number (see PLATFORM_*
|
||||||
constants in include/asm-powerpc/processor.h
|
constants in arch/powerpc/include/asm/processor.h
|
||||||
|
|
||||||
32-bit embedded kernels:
|
32-bit embedded kernels:
|
||||||
|
|
||||||
|
@ -339,7 +340,7 @@ the block to RAM before passing it to the kernel.
|
||||||
---------
|
---------
|
||||||
|
|
||||||
The kernel is entered with r3 pointing to an area of memory that is
|
The kernel is entered with r3 pointing to an area of memory that is
|
||||||
roughly described in include/asm-powerpc/prom.h by the structure
|
roughly described in arch/powerpc/include/asm/prom.h by the structure
|
||||||
boot_param_header:
|
boot_param_header:
|
||||||
|
|
||||||
struct boot_param_header {
|
struct boot_param_header {
|
||||||
|
@ -707,7 +708,7 @@ device or bus to be described by the device tree.
|
||||||
In general, the format of an address for a device is defined by the
|
In general, the format of an address for a device is defined by the
|
||||||
parent bus type, based on the #address-cells and #size-cells
|
parent bus type, based on the #address-cells and #size-cells
|
||||||
properties. Note that the parent's parent definitions of #address-cells
|
properties. Note that the parent's parent definitions of #address-cells
|
||||||
and #size-cells are not inhereted so every node with children must specify
|
and #size-cells are not inherited so every node with children must specify
|
||||||
them. The kernel requires the root node to have those properties defining
|
them. The kernel requires the root node to have those properties defining
|
||||||
addresses format for devices directly mapped on the processor bus.
|
addresses format for devices directly mapped on the processor bus.
|
||||||
|
|
||||||
|
@ -1776,7 +1777,7 @@ platforms are moved over to use the flattened-device-tree model.
|
||||||
|
|
||||||
Xilinx uartlite devices are simple fixed speed serial ports.
|
Xilinx uartlite devices are simple fixed speed serial ports.
|
||||||
|
|
||||||
Requred properties:
|
Required properties:
|
||||||
- current-speed : Baud rate of uartlite
|
- current-speed : Baud rate of uartlite
|
||||||
|
|
||||||
v) Xilinx hwicap
|
v) Xilinx hwicap
|
||||||
|
@ -1798,7 +1799,7 @@ platforms are moved over to use the flattened-device-tree model.
|
||||||
Xilinx UART 16550 devices are very similar to the NS16550 but with
|
Xilinx UART 16550 devices are very similar to the NS16550 but with
|
||||||
different register spacing and an offset from the base address.
|
different register spacing and an offset from the base address.
|
||||||
|
|
||||||
Requred properties:
|
Required properties:
|
||||||
- clock-frequency : Frequency of the clock input
|
- clock-frequency : Frequency of the clock input
|
||||||
- reg-offset : A value of 3 is required
|
- reg-offset : A value of 3 is required
|
||||||
- reg-shift : A value of 2 is required
|
- reg-shift : A value of 2 is required
|
||||||
|
@ -1883,6 +1884,62 @@ platforms are moved over to use the flattened-device-tree model.
|
||||||
&qe_pio_c 6>;
|
&qe_pio_c 6>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
s) SPI (Serial Peripheral Interface) busses
|
||||||
|
|
||||||
|
SPI busses can be described with a node for the SPI master device
|
||||||
|
and a set of child nodes for each SPI slave on the bus. For this
|
||||||
|
discussion, it is assumed that the system's SPI controller is in
|
||||||
|
SPI master mode. This binding does not describe SPI controllers
|
||||||
|
in slave mode.
|
||||||
|
|
||||||
|
The SPI master node requires the following properties:
|
||||||
|
- #address-cells - number of cells required to define a chip select
|
||||||
|
address on the SPI bus.
|
||||||
|
- #size-cells - should be zero.
|
||||||
|
- compatible - name of SPI bus controller following generic names
|
||||||
|
recommended practice.
|
||||||
|
No other properties are required in the SPI bus node. It is assumed
|
||||||
|
that a driver for an SPI bus device will understand that it is an SPI bus.
|
||||||
|
However, the binding does not attempt to define the specific method for
|
||||||
|
assigning chip select numbers. Since SPI chip select configuration is
|
||||||
|
flexible and non-standardized, it is left out of this binding with the
|
||||||
|
assumption that board specific platform code will be used to manage
|
||||||
|
chip selects. Individual drivers can define additional properties to
|
||||||
|
support describing the chip select layout.
|
||||||
|
|
||||||
|
SPI slave nodes must be children of the SPI master node and can
|
||||||
|
contain the following properties.
|
||||||
|
- reg - (required) chip select address of device.
|
||||||
|
- compatible - (required) name of SPI device following generic names
|
||||||
|
recommended practice
|
||||||
|
- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz
|
||||||
|
- spi-cpol - (optional) Empty property indicating device requires
|
||||||
|
inverse clock polarity (CPOL) mode
|
||||||
|
- spi-cpha - (optional) Empty property indicating device requires
|
||||||
|
shifted clock phase (CPHA) mode
|
||||||
|
|
||||||
|
SPI example for an MPC5200 SPI bus:
|
||||||
|
spi@f00 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi";
|
||||||
|
reg = <0xf00 0x20>;
|
||||||
|
interrupts = <2 13 0 2 14 0>;
|
||||||
|
interrupt-parent = <&mpc5200_pic>;
|
||||||
|
|
||||||
|
ethernet-switch@0 {
|
||||||
|
compatible = "micrel,ks8995m";
|
||||||
|
spi-max-frequency = <1000000>;
|
||||||
|
reg = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
codec@1 {
|
||||||
|
compatible = "ti,tlv320aic26";
|
||||||
|
spi-max-frequency = <100000>;
|
||||||
|
reg = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
VII - Marvell Discovery mv64[345]6x System Controller chips
|
VII - Marvell Discovery mv64[345]6x System Controller chips
|
||||||
===========================================================
|
===========================================================
|
||||||
|
|
||||||
|
@ -1896,7 +1953,7 @@ prefixed with the string "marvell,", for Marvell Technology Group Ltd.
|
||||||
1) The /system-controller node
|
1) The /system-controller node
|
||||||
|
|
||||||
This node is used to represent the system-controller and must be
|
This node is used to represent the system-controller and must be
|
||||||
present when the system uses a system contller chip. The top-level
|
present when the system uses a system controller chip. The top-level
|
||||||
system-controller node contains information that is global to all
|
system-controller node contains information that is global to all
|
||||||
devices within the system controller chip. The node name begins
|
devices within the system controller chip. The node name begins
|
||||||
with "system-controller" followed by the unit address, which is
|
with "system-controller" followed by the unit address, which is
|
||||||
|
|
|
@ -7,6 +7,15 @@ Currently defined compatibles:
|
||||||
- fsl,cpm2-scc-uart
|
- fsl,cpm2-scc-uart
|
||||||
- fsl,qe-uart
|
- fsl,qe-uart
|
||||||
|
|
||||||
|
Modem control lines connected to GPIO controllers are listed in the gpios
|
||||||
|
property as described in booting-without-of.txt, section IX.1 in the following
|
||||||
|
order:
|
||||||
|
|
||||||
|
CTS, RTS, DCD, DSR, DTR, and RI.
|
||||||
|
|
||||||
|
The gpios property is optional and can be left out when control lines are
|
||||||
|
not used.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
serial@11a00 {
|
serial@11a00 {
|
||||||
|
@ -18,4 +27,6 @@ Example:
|
||||||
interrupt-parent = <&PIC>;
|
interrupt-parent = <&PIC>;
|
||||||
fsl,cpm-brg = <1>;
|
fsl,cpm-brg = <1>;
|
||||||
fsl,cpm-command = <00800000>;
|
fsl,cpm-command = <00800000>;
|
||||||
|
gpios = <&gpio_c 15 0
|
||||||
|
&gpio_d 29 0>;
|
||||||
};
|
};
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue