forked from Minki/linux
Pull pnpacpi into acpica branch
This commit is contained in:
commit
ed03f430cd
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,6 +10,7 @@
|
||||
*.a
|
||||
*.s
|
||||
*.ko
|
||||
*.so
|
||||
*.mod.c
|
||||
|
||||
#
|
||||
@ -23,6 +24,7 @@ Module.symvers
|
||||
# Generated include files
|
||||
#
|
||||
include/asm
|
||||
include/asm-*/asm-offsets.h
|
||||
include/config
|
||||
include/linux/autoconf.h
|
||||
include/linux/compile.h
|
||||
|
1
CREDITS
1
CREDITS
@ -1883,6 +1883,7 @@ N: Jaya Kumar
|
||||
E: jayalk@intworks.biz
|
||||
W: http://www.intworks.biz
|
||||
D: Arc monochrome LCD framebuffer driver, x86 reboot fixups
|
||||
D: pirq addr, CS5535 alsa audio driver
|
||||
S: Gurgaon, India
|
||||
S: Kuala Lumpur, Malaysia
|
||||
|
||||
|
@ -253,6 +253,7 @@
|
||||
!Edrivers/usb/core/urb.c
|
||||
!Edrivers/usb/core/message.c
|
||||
!Edrivers/usb/core/file.c
|
||||
!Edrivers/usb/core/driver.c
|
||||
!Edrivers/usb/core/usb.c
|
||||
!Edrivers/usb/core/hub.c
|
||||
</chapter>
|
||||
|
@ -158,7 +158,7 @@ Even if the maintainer did not respond in step #4, make sure to ALWAYS
|
||||
copy the maintainer when you change their code.
|
||||
|
||||
For small patches you may want to CC the Trivial Patch Monkey
|
||||
trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
|
||||
trivial@kernel.org managed by Adrian Bunk; which collects "trivial"
|
||||
patches. Trivial patches must qualify for one of the following rules:
|
||||
Spelling fixes in documentation
|
||||
Spelling fixes which could break grep(1).
|
||||
@ -171,7 +171,7 @@ patches. Trivial patches must qualify for one of the following rules:
|
||||
since people copy, as long as it's trivial)
|
||||
Any fix by the author/maintainer of the file. (ie. patch monkey
|
||||
in re-transmission mode)
|
||||
URL: <http://www.kernel.org/pub/linux/kernel/people/rusty/trivial/>
|
||||
URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
|
||||
|
||||
|
||||
|
||||
|
@ -16,5 +16,7 @@ empeg
|
||||
- Empeg documentation
|
||||
mem_alignment
|
||||
- alignment abort handler documentation
|
||||
memory.txt
|
||||
- description of the virtual memory layout
|
||||
nwfpe
|
||||
- NWFPE floating point emulator documentation
|
||||
|
@ -31,7 +31,7 @@ The following people helped with review comments and inputs for this
|
||||
document:
|
||||
Christoph Hellwig <hch@infradead.org>
|
||||
Arjan van de Ven <arjanv@redhat.com>
|
||||
Randy Dunlap <rddunlap@osdl.org>
|
||||
Randy Dunlap <rdunlap@xenotime.net>
|
||||
Andre Hedrick <andre@linux-ide.org>
|
||||
|
||||
The following people helped with fixes/contributions to the bio patches
|
||||
@ -263,14 +263,8 @@ A flag in the bio structure, BIO_BARRIER is used to identify a barrier i/o.
|
||||
The generic i/o scheduler would make sure that it places the barrier request and
|
||||
all other requests coming after it after all the previous requests in the
|
||||
queue. Barriers may be implemented in different ways depending on the
|
||||
driver. A SCSI driver for example could make use of ordered tags to
|
||||
preserve the necessary ordering with a lower impact on throughput. For IDE
|
||||
this might be two sync cache flush: a pre and post flush when encountering
|
||||
a barrier write.
|
||||
|
||||
There is a provision for queues to indicate what kind of barriers they
|
||||
can provide. This is as of yet unmerged, details will be added here once it
|
||||
is in the kernel.
|
||||
driver. For more details regarding I/O barriers, please read barrier.txt
|
||||
in this directory.
|
||||
|
||||
1.2.2 Request Priority/Latency
|
||||
|
||||
|
@ -27,6 +27,7 @@ Contents:
|
||||
2.2 Powersave
|
||||
2.3 Userspace
|
||||
2.4 Ondemand
|
||||
2.5 Conservative
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
|
||||
@ -110,9 +111,64 @@ directory.
|
||||
|
||||
The CPUfreq govenor "ondemand" sets the CPU depending on the
|
||||
current usage. To do this the CPU must have the capability to
|
||||
switch the frequency very fast.
|
||||
switch the frequency very quickly. There are a number of sysfs file
|
||||
accessible parameters:
|
||||
|
||||
sampling_rate: measured in uS (10^-6 seconds), this is how often you
|
||||
want the kernel to look at the CPU usage and to make decisions on
|
||||
what to do about the frequency. Typically this is set to values of
|
||||
around '10000' or more.
|
||||
|
||||
show_sampling_rate_(min|max): the minimum and maximum sampling rates
|
||||
available that you may set 'sampling_rate' to.
|
||||
|
||||
up_threshold: defines what the average CPU usaged between the samplings
|
||||
of 'sampling_rate' needs to be for the kernel to make a decision on
|
||||
whether it should increase the frequency. For example when it is set
|
||||
to its default value of '80' it means that between the checking
|
||||
intervals the CPU needs to be on average more than 80% in use to then
|
||||
decide that the CPU frequency needs to be increased.
|
||||
|
||||
sampling_down_factor: this parameter controls the rate that the CPU
|
||||
makes a decision on when to decrease the frequency. When set to its
|
||||
default value of '5' it means that at 1/5 the sampling_rate the kernel
|
||||
makes a decision to lower the frequency. Five "lower rate" decisions
|
||||
have to be made in a row before the CPU frequency is actually lower.
|
||||
If set to '1' then the frequency decreases as quickly as it increases,
|
||||
if set to '2' it decreases at half the rate of the increase.
|
||||
|
||||
ignore_nice_load: this parameter takes a value of '0' or '1', when set
|
||||
to '0' (its default) then all processes are counted towards towards the
|
||||
'cpu utilisation' value. When set to '1' then processes that are
|
||||
run with a 'nice' value will not count (and thus be ignored) in the
|
||||
overal usage calculation. This is useful if you are running a CPU
|
||||
intensive calculation on your laptop that you do not care how long it
|
||||
takes to complete as you can 'nice' it and prevent it from taking part
|
||||
in the deciding process of whether to increase your CPU frequency.
|
||||
|
||||
|
||||
2.5 Conservative
|
||||
----------------
|
||||
|
||||
The CPUfreq governor "conservative", much like the "ondemand"
|
||||
governor, sets the CPU depending on the current usage. It differs in
|
||||
behaviour in that it gracefully increases and decreases the CPU speed
|
||||
rather than jumping to max speed the moment there is any load on the
|
||||
CPU. This behaviour more suitable in a battery powered environment.
|
||||
The governor is tweaked in the same manner as the "ondemand" governor
|
||||
through sysfs with the addition of:
|
||||
|
||||
freq_step: this describes what percentage steps the cpu freq should be
|
||||
increased and decreased smoothly by. By default the cpu frequency will
|
||||
increase in 5% chunks of your maximum cpu frequency. You can change this
|
||||
value to anywhere between 0 and 100 where '0' will effectively lock your
|
||||
CPU at a speed regardless of its load whilst '100' will, in theory, make
|
||||
it behave identically to the "ondemand" governor.
|
||||
|
||||
down_threshold: same as the 'up_threshold' found for the "ondemand"
|
||||
governor but for the opposite direction. For example when set to its
|
||||
default value of '20' it means that if the CPU usage needs to be below
|
||||
20% between samples to have the frequency decreased.
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
=============================================
|
||||
|
@ -50,12 +50,12 @@ http://www.linuxtv.org/wiki/index.php/DVB_USB
|
||||
0. History & News:
|
||||
2005-06-30 - added support for WideView WT-220U (Thanks to Steve Chang)
|
||||
2005-05-30 - added basic isochronous support to the dvb-usb-framework
|
||||
added support for Conexant Hybrid reference design and Nebula DigiTV USB
|
||||
added support for Conexant Hybrid reference design and Nebula DigiTV USB
|
||||
2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
|
||||
2005-04-02 - re-enabled and improved remote control code.
|
||||
2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
|
||||
2005-03-30 - first commit of the dvb-usb-module based on the dibusb-source. First device is a new driver for the
|
||||
TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
|
||||
TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
|
||||
|
||||
(change from dvb-dibusb to dvb-usb)
|
||||
2005-03-28 - added support for the AVerMedia AverTV DVB-T USB2.0 device (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia)
|
||||
@ -64,50 +64,50 @@ http://www.linuxtv.org/wiki/index.php/DVB_USB
|
||||
2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
|
||||
2005-01-31 - distorted streaming is gone for USB1.1 devices
|
||||
2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
|
||||
- first almost working version for HanfTek UMT-010
|
||||
- found out, that Yakumo/HAMA/Typhoon are predecessors of the HanfTek UMT-010
|
||||
- first almost working version for HanfTek UMT-010
|
||||
- found out, that Yakumo/HAMA/Typhoon are predecessors of the HanfTek UMT-010
|
||||
2005-01-10 - refactoring completed, now everything is very delightful
|
||||
- tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
|
||||
Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
|
||||
- tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
|
||||
Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
|
||||
2004-12-29 - after several days of struggling around bug of no returning URBs fixed.
|
||||
2004-12-26 - refactored the dibusb-driver, splitted into separate files
|
||||
- i2c-probing enabled
|
||||
- i2c-probing enabled
|
||||
2004-12-06 - possibility for demod i2c-address probing
|
||||
- new usb IDs (Compro, Artec)
|
||||
- new usb IDs (Compro, Artec)
|
||||
2004-11-23 - merged changes from DiB3000MC_ver2.1
|
||||
- revised the debugging
|
||||
- possibility to deliver the complete TS for USB2.0
|
||||
- revised the debugging
|
||||
- possibility to deliver the complete TS for USB2.0
|
||||
2004-11-21 - first working version of the dib3000mc/p frontend driver.
|
||||
2004-11-12 - added additional remote control keys. Thanks to Uwe Hanke.
|
||||
2004-11-07 - added remote control support. Thanks to David Matthews.
|
||||
2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec)
|
||||
- merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
|
||||
- moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
|
||||
better settled there (added xfer_ops-struct)
|
||||
- created a common files for frontends (mc/p/mb)
|
||||
- merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
|
||||
- moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
|
||||
better settled there (added xfer_ops-struct)
|
||||
- created a common files for frontends (mc/p/mb)
|
||||
2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
|
||||
2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
|
||||
to Amaury Demol for reporting
|
||||
- changed usb TS transfer method (several urbs, stopping transfer
|
||||
before setting a new pid)
|
||||
to Amaury Demol for reporting
|
||||
- changed usb TS transfer method (several urbs, stopping transfer
|
||||
before setting a new pid)
|
||||
2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
|
||||
to Christian Motschke for reporting
|
||||
to Christian Motschke for reporting
|
||||
2004-09-05 - released the dibusb device and dib3000mb-frontend driver
|
||||
|
||||
(old news for vp7041.c)
|
||||
2004-07-15 - found out, by accident, that the device has a TUA6010XS for
|
||||
PLL
|
||||
PLL
|
||||
2004-07-12 - figured out, that the driver should also work with the
|
||||
CTS Portable (Chinese Television System)
|
||||
CTS Portable (Chinese Television System)
|
||||
2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
|
||||
properly with firmware extracted from 2.422
|
||||
- #if for 2.6.4 (dvb), compile issue
|
||||
- changed firmware handling, see vp7041.txt sec 1.1
|
||||
properly with firmware extracted from 2.422
|
||||
- #if for 2.6.4 (dvb), compile issue
|
||||
- changed firmware handling, see vp7041.txt sec 1.1
|
||||
2004-07-02 - some tuner modifications, v0.1, cleanups, first public
|
||||
2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
|
||||
runs fine now
|
||||
runs fine now
|
||||
2004-06-27 - able to watch and switching channels (pre-alpha)
|
||||
- no section filtering yet
|
||||
- no section filtering yet
|
||||
2004-06-06 - first TS received, but kernel oops :/
|
||||
2004-05-14 - firmware loader is working
|
||||
2004-05-11 - start writing the driver
|
||||
|
@ -174,7 +174,7 @@ Debugging
|
||||
Everything which is identical in the following table, can be put into a common
|
||||
flexcop-module.
|
||||
|
||||
PCI USB
|
||||
PCI USB
|
||||
-------------------------------------------------------------------------------
|
||||
Different:
|
||||
Register access: accessing IO memory USB control message
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
HOWTO: Get An Avermedia DVB-T working under Linux
|
||||
______________________________________________
|
||||
______________________________________________
|
||||
|
||||
Table of Contents
|
||||
Assumptions and Introduction
|
||||
|
@ -16,7 +16,7 @@ Hardware supported by the linuxtv.org DVB drivers
|
||||
shielding, and the whole metal box has its own part number.
|
||||
|
||||
|
||||
o Frontends drivers:
|
||||
o Frontends drivers:
|
||||
- dvb_dummy_fe: for testing...
|
||||
DVB-S:
|
||||
- ves1x93 : Alps BSRV2 (ves1893 demodulator) and dbox2 (ves1993)
|
||||
@ -24,7 +24,7 @@ o Frontends drivers:
|
||||
- grundig_29504-491 : Grundig 29504-491 (Philips TDA8083 demodulator), tsa5522 PLL
|
||||
- mt312 : Zarlink mt312 or Mitel vp310 demodulator, sl1935 or tsa5059 PLL
|
||||
- stv0299 : Alps BSRU6 (tsa5059 PLL), LG TDQB-S00x (tsa5059 PLL),
|
||||
LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL),
|
||||
LG TDQF-S001F (sl1935 PLL), Philips SU1278 (tua6100 PLL),
|
||||
Philips SU1278SH (tsa5059 PLL), Samsung TBMU24112IMB
|
||||
DVB-C:
|
||||
- ves1820 : various (ves1820 demodulator, sp5659c or spXXXX PLL)
|
||||
@ -35,8 +35,8 @@ o Frontends drivers:
|
||||
- grundig_29504-401 : Grundig 29504-401 (LSI L64781 demodulator), tsa5060 PLL
|
||||
- tda1004x : Philips tda10045h (td1344 or tdm1316l PLL)
|
||||
- nxt6000 : Alps TDME7 (MITEL SP5659 PLL), Alps TDED4 (TI ALP510 PLL),
|
||||
Comtech DVBT-6k07 (SP5730 PLL)
|
||||
(NxtWave Communications NXT6000 demodulator)
|
||||
Comtech DVBT-6k07 (SP5730 PLL)
|
||||
(NxtWave Communications NXT6000 demodulator)
|
||||
- sp887x : Microtune 7202D
|
||||
- dib3000mb : DiBcom 3000-MB demodulator
|
||||
DVB-S/C/T:
|
||||
|
@ -15,7 +15,7 @@ Michael Holzt <kju@debian.org>
|
||||
|
||||
Diego Picciani <d.picciani@novacomp.it>
|
||||
for CyberLogin for Linux which allows logging onto EON
|
||||
(in case you are wondering where CyberLogin is, EON changed its login
|
||||
(in case you are wondering where CyberLogin is, EON changed its login
|
||||
procedure and CyberLogin is no longer used.)
|
||||
|
||||
Martin Schaller <martin@smurf.franken.de>
|
||||
@ -57,7 +57,7 @@ Augusto Cardoso <augusto@carhil.net>
|
||||
Davor Emard <emard@softhome.net>
|
||||
for his work on the budget drivers, the demux code,
|
||||
the module unloading problems, ...
|
||||
|
||||
|
||||
Hans-Frieder Vogt <hfvogt@arcor.de>
|
||||
for his work on calculating and checking the crc's for the
|
||||
TechnoTrend/Hauppauge DEC driver firmware
|
||||
|
@ -20,7 +20,7 @@ http://linuxtv.org/downloads/
|
||||
|
||||
What's inside this directory:
|
||||
|
||||
"cards.txt"
|
||||
"cards.txt"
|
||||
contains a list of supported hardware.
|
||||
|
||||
"contributors.txt"
|
||||
@ -37,7 +37,7 @@ that require it.
|
||||
contains detailed informations about the
|
||||
TT DEC2000/DEC3000 USB DVB hardware.
|
||||
|
||||
"bt8xx.txt"
|
||||
"bt8xx.txt"
|
||||
contains detailed installation instructions for the
|
||||
various bt8xx based "budget" DVB cards
|
||||
(Nebula, Pinnacle PCTV, Twinhan DST)
|
||||
|
@ -47,17 +47,6 @@ Who: Paul E. McKenney <paulmck@us.ibm.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: IEEE1394 Audio and Music Data Transmission Protocol driver,
|
||||
Connection Management Procedures driver
|
||||
When: November 2005
|
||||
Files: drivers/ieee1394/{amdtp,cmp}*
|
||||
Why: These are incomplete, have never worked, and are better implemented
|
||||
in userland via raw1394 (see http://freebob.sourceforge.net/ for
|
||||
example.)
|
||||
Who: Jody McIntyre <scjody@steamballoon.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
|
||||
When: November 2005
|
||||
Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
|
||||
@ -82,15 +71,6 @@ Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
|
||||
When: November 2005
|
||||
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
|
||||
Why: Match the other drivers' name for the same function, duplicate names
|
||||
will be available until removal of old names.
|
||||
Who: Grant Coady <gcoady@gmail.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: remove EXPORT_SYMBOL(panic_timeout)
|
||||
When: April 2006
|
||||
Files: kernel/panic.c
|
||||
|
@ -12,14 +12,16 @@ cifs.txt
|
||||
- description of the CIFS filesystem
|
||||
coda.txt
|
||||
- description of the CODA filesystem.
|
||||
configfs/
|
||||
- directory containing configfs documentation and example code.
|
||||
cramfs.txt
|
||||
- info on the cram filesystem for small storage (ROMs etc)
|
||||
devfs/
|
||||
- directory containing devfs documentation.
|
||||
dlmfs.txt
|
||||
- info on the userspace interface to the OCFS2 DLM.
|
||||
ext2.txt
|
||||
- info, mount options and specifications for the Ext2 filesystem.
|
||||
fat_cvf.txt
|
||||
- info on the Compressed Volume Files extension to the FAT filesystem
|
||||
hpfs.txt
|
||||
- info and mount options for the OS/2 HPFS.
|
||||
isofs.txt
|
||||
@ -32,6 +34,8 @@ ntfs.txt
|
||||
- info and mount options for the NTFS filesystem (Windows NT).
|
||||
proc.txt
|
||||
- info on Linux's /proc filesystem.
|
||||
ocfs2.txt
|
||||
- info and mount options for the OCFS2 clustered filesystem.
|
||||
romfs.txt
|
||||
- Description of the ROMFS filesystem.
|
||||
smbfs.txt
|
||||
|
434
Documentation/filesystems/configfs/configfs.txt
Normal file
434
Documentation/filesystems/configfs/configfs.txt
Normal file
@ -0,0 +1,434 @@
|
||||
|
||||
configfs - Userspace-driven kernel object configuation.
|
||||
|
||||
Joel Becker <joel.becker@oracle.com>
|
||||
|
||||
Updated: 31 March 2005
|
||||
|
||||
Copyright (c) 2005 Oracle Corporation,
|
||||
Joel Becker <joel.becker@oracle.com>
|
||||
|
||||
|
||||
[What is configfs?]
|
||||
|
||||
configfs is a ram-based filesystem that provides the converse of
|
||||
sysfs's functionality. Where sysfs is a filesystem-based view of
|
||||
kernel objects, configfs is a filesystem-based manager of kernel
|
||||
objects, or config_items.
|
||||
|
||||
With sysfs, an object is created in kernel (for example, when a device
|
||||
is discovered) and it is registered with sysfs. Its attributes then
|
||||
appear in sysfs, allowing userspace to read the attributes via
|
||||
readdir(3)/read(2). It may allow some attributes to be modified via
|
||||
write(2). The important point is that the object is created and
|
||||
destroyed in kernel, the kernel controls the lifecycle of the sysfs
|
||||
representation, and sysfs is merely a window on all this.
|
||||
|
||||
A configfs config_item is created via an explicit userspace operation:
|
||||
mkdir(2). It is destroyed via rmdir(2). The attributes appear at
|
||||
mkdir(2) time, and can be read or modified via read(2) and write(2).
|
||||
As with sysfs, readdir(3) queries the list of items and/or attributes.
|
||||
symlink(2) can be used to group items together. Unlike sysfs, the
|
||||
lifetime of the representation is completely driven by userspace. The
|
||||
kernel modules backing the items must respond to this.
|
||||
|
||||
Both sysfs and configfs can and should exist together on the same
|
||||
system. One is not a replacement for the other.
|
||||
|
||||
[Using configfs]
|
||||
|
||||
configfs can be compiled as a module or into the kernel. You can access
|
||||
it by doing
|
||||
|
||||
mount -t configfs none /config
|
||||
|
||||
The configfs tree will be empty unless client modules are also loaded.
|
||||
These are modules that register their item types with configfs as
|
||||
subsystems. Once a client subsystem is loaded, it will appear as a
|
||||
subdirectory (or more than one) under /config. Like sysfs, the
|
||||
configfs tree is always there, whether mounted on /config or not.
|
||||
|
||||
An item is created via mkdir(2). The item's attributes will also
|
||||
appear at this time. readdir(3) can determine what the attributes are,
|
||||
read(2) can query their default values, and write(2) can store new
|
||||
values. Like sysfs, attributes should be ASCII text files, preferably
|
||||
with only one value per file. The same efficiency caveats from sysfs
|
||||
apply. Don't mix more than one attribute in one attribute file.
|
||||
|
||||
Like sysfs, configfs expects write(2) to store the entire buffer at
|
||||
once. When writing to configfs attributes, userspace processes should
|
||||
first read the entire file, modify the portions they wish to change, and
|
||||
then write the entire buffer back. Attribute files have a maximum size
|
||||
of one page (PAGE_SIZE, 4096 on i386).
|
||||
|
||||
When an item needs to be destroyed, remove it with rmdir(2). An
|
||||
item cannot be destroyed if any other item has a link to it (via
|
||||
symlink(2)). Links can be removed via unlink(2).
|
||||
|
||||
[Configuring FakeNBD: an Example]
|
||||
|
||||
Imagine there's a Network Block Device (NBD) driver that allows you to
|
||||
access remote block devices. Call it FakeNBD. FakeNBD uses configfs
|
||||
for its configuration. Obviously, there will be a nice program that
|
||||
sysadmins use to configure FakeNBD, but somehow that program has to tell
|
||||
the driver about it. Here's where configfs comes in.
|
||||
|
||||
When the FakeNBD driver is loaded, it registers itself with configfs.
|
||||
readdir(3) sees this just fine:
|
||||
|
||||
# ls /config
|
||||
fakenbd
|
||||
|
||||
A fakenbd connection can be created with mkdir(2). The name is
|
||||
arbitrary, but likely the tool will make some use of the name. Perhaps
|
||||
it is a uuid or a disk name:
|
||||
|
||||
# mkdir /config/fakenbd/disk1
|
||||
# ls /config/fakenbd/disk1
|
||||
target device rw
|
||||
|
||||
The target attribute contains the IP address of the server FakeNBD will
|
||||
connect to. The device attribute is the device on the server.
|
||||
Predictably, the rw attribute determines whether the connection is
|
||||
read-only or read-write.
|
||||
|
||||
# echo 10.0.0.1 > /config/fakenbd/disk1/target
|
||||
# echo /dev/sda1 > /config/fakenbd/disk1/device
|
||||
# echo 1 > /config/fakenbd/disk1/rw
|
||||
|
||||
That's it. That's all there is. Now the device is configured, via the
|
||||
shell no less.
|
||||
|
||||
[Coding With configfs]
|
||||
|
||||
Every object in configfs is a config_item. A config_item reflects an
|
||||
object in the subsystem. It has attributes that match values on that
|
||||
object. configfs handles the filesystem representation of that object
|
||||
and its attributes, allowing the subsystem to ignore all but the
|
||||
basic show/store interaction.
|
||||
|
||||
Items are created and destroyed inside a config_group. A group is a
|
||||
collection of items that share the same attributes and operations.
|
||||
Items are created by mkdir(2) and removed by rmdir(2), but configfs
|
||||
handles that. The group has a set of operations to perform these tasks
|
||||
|
||||
A subsystem is the top level of a client module. During initialization,
|
||||
the client module registers the subsystem with configfs, the subsystem
|
||||
appears as a directory at the top of the configfs filesystem. A
|
||||
subsystem is also a config_group, and can do everything a config_group
|
||||
can.
|
||||
|
||||
[struct config_item]
|
||||
|
||||
struct config_item {
|
||||
char *ci_name;
|
||||
char ci_namebuf[UOBJ_NAME_LEN];
|
||||
struct kref ci_kref;
|
||||
struct list_head ci_entry;
|
||||
struct config_item *ci_parent;
|
||||
struct config_group *ci_group;
|
||||
struct config_item_type *ci_type;
|
||||
struct dentry *ci_dentry;
|
||||
};
|
||||
|
||||
void config_item_init(struct config_item *);
|
||||
void config_item_init_type_name(struct config_item *,
|
||||
const char *name,
|
||||
struct config_item_type *type);
|
||||
struct config_item *config_item_get(struct config_item *);
|
||||
void config_item_put(struct config_item *);
|
||||
|
||||
Generally, struct config_item is embedded in a container structure, a
|
||||
structure that actually represents what the subsystem is doing. The
|
||||
config_item portion of that structure is how the object interacts with
|
||||
configfs.
|
||||
|
||||
Whether statically defined in a source file or created by a parent
|
||||
config_group, a config_item must have one of the _init() functions
|
||||
called on it. This initializes the reference count and sets up the
|
||||
appropriate fields.
|
||||
|
||||
All users of a config_item should have a reference on it via
|
||||
config_item_get(), and drop the reference when they are done via
|
||||
config_item_put().
|
||||
|
||||
By itself, a config_item cannot do much more than appear in configfs.
|
||||
Usually a subsystem wants the item to display and/or store attributes,
|
||||
among other things. For that, it needs a type.
|
||||
|
||||
[struct config_item_type]
|
||||
|
||||
struct configfs_item_operations {
|
||||
void (*release)(struct config_item *);
|
||||
ssize_t (*show_attribute)(struct config_item *,
|
||||
struct configfs_attribute *,
|
||||
char *);
|
||||
ssize_t (*store_attribute)(struct config_item *,
|
||||
struct configfs_attribute *,
|
||||
const char *, size_t);
|
||||
int (*allow_link)(struct config_item *src,
|
||||
struct config_item *target);
|
||||
int (*drop_link)(struct config_item *src,
|
||||
struct config_item *target);
|
||||
};
|
||||
|
||||
struct config_item_type {
|
||||
struct module *ct_owner;
|
||||
struct configfs_item_operations *ct_item_ops;
|
||||
struct configfs_group_operations *ct_group_ops;
|
||||
struct configfs_attribute **ct_attrs;
|
||||
};
|
||||
|
||||
The most basic function of a config_item_type is to define what
|
||||
operations can be performed on a config_item. All items that have been
|
||||
allocated dynamically will need to provide the ct_item_ops->release()
|
||||
method. This method is called when the config_item's reference count
|
||||
reaches zero. Items that wish to display an attribute need to provide
|
||||
the ct_item_ops->show_attribute() method. Similarly, storing a new
|
||||
attribute value uses the store_attribute() method.
|
||||
|
||||
[struct configfs_attribute]
|
||||
|
||||
struct configfs_attribute {
|
||||
char *ca_name;
|
||||
struct module *ca_owner;
|
||||
mode_t ca_mode;
|
||||
};
|
||||
|
||||
When a config_item wants an attribute to appear as a file in the item's
|
||||
configfs directory, it must define a configfs_attribute describing it.
|
||||
It then adds the attribute to the NULL-terminated array
|
||||
config_item_type->ct_attrs. When the item appears in configfs, the
|
||||
attribute file will appear with the configfs_attribute->ca_name
|
||||
filename. configfs_attribute->ca_mode specifies the file permissions.
|
||||
|
||||
If an attribute is readable and the config_item provides a
|
||||
ct_item_ops->show_attribute() method, that method will be called
|
||||
whenever userspace asks for a read(2) on the attribute. The converse
|
||||
will happen for write(2).
|
||||
|
||||
[struct config_group]
|
||||
|
||||
A config_item cannot live in a vaccum. The only way one can be created
|
||||
is via mkdir(2) on a config_group. This will trigger creation of a
|
||||
child item.
|
||||
|
||||
struct config_group {
|
||||
struct config_item cg_item;
|
||||
struct list_head cg_children;
|
||||
struct configfs_subsystem *cg_subsys;
|
||||
struct config_group **default_groups;
|
||||
};
|
||||
|
||||
void config_group_init(struct config_group *group);
|
||||
void config_group_init_type_name(struct config_group *group,
|
||||
const char *name,
|
||||
struct config_item_type *type);
|
||||
|
||||
|
||||
The config_group structure contains a config_item. Properly configuring
|
||||
that item means that a group can behave as an item in its own right.
|
||||
However, it can do more: it can create child items or groups. This is
|
||||
accomplished via the group operations specified on the group's
|
||||
config_item_type.
|
||||
|
||||
struct configfs_group_operations {
|
||||
struct config_item *(*make_item)(struct config_group *group,
|
||||
const char *name);
|
||||
struct config_group *(*make_group)(struct config_group *group,
|
||||
const char *name);
|
||||
int (*commit_item)(struct config_item *item);
|
||||
void (*drop_item)(struct config_group *group,
|
||||
struct config_item *item);
|
||||
};
|
||||
|
||||
A group creates child items by providing the
|
||||
ct_group_ops->make_item() method. If provided, this method is called from mkdir(2) in the group's directory. The subsystem allocates a new
|
||||
config_item (or more likely, its container structure), initializes it,
|
||||
and returns it to configfs. Configfs will then populate the filesystem
|
||||
tree to reflect the new item.
|
||||
|
||||
If the subsystem wants the child to be a group itself, the subsystem
|
||||
provides ct_group_ops->make_group(). Everything else behaves the same,
|
||||
using the group _init() functions on the group.
|
||||
|
||||
Finally, when userspace calls rmdir(2) on the item or group,
|
||||
ct_group_ops->drop_item() is called. As a config_group is also a
|
||||
config_item, it is not necessary for a seperate drop_group() method.
|
||||
The subsystem must config_item_put() the reference that was initialized
|
||||
upon item allocation. If a subsystem has no work to do, it may omit
|
||||
the ct_group_ops->drop_item() method, and configfs will call
|
||||
config_item_put() on the item on behalf of the subsystem.
|
||||
|
||||
IMPORTANT: drop_item() is void, and as such cannot fail. When rmdir(2)
|
||||
is called, configfs WILL remove the item from the filesystem tree
|
||||
(assuming that it has no children to keep it busy). The subsystem is
|
||||
responsible for responding to this. If the subsystem has references to
|
||||
the item in other threads, the memory is safe. It may take some time
|
||||
for the item to actually disappear from the subsystem's usage. But it
|
||||
is gone from configfs.
|
||||
|
||||
A config_group cannot be removed while it still has child items. This
|
||||
is implemented in the configfs rmdir(2) code. ->drop_item() will not be
|
||||
called, as the item has not been dropped. rmdir(2) will fail, as the
|
||||
directory is not empty.
|
||||
|
||||
[struct configfs_subsystem]
|
||||
|
||||
A subsystem must register itself, ususally at module_init time. This
|
||||
tells configfs to make the subsystem appear in the file tree.
|
||||
|
||||
struct configfs_subsystem {
|
||||
struct config_group su_group;
|
||||
struct semaphore su_sem;
|
||||
};
|
||||
|
||||
int configfs_register_subsystem(struct configfs_subsystem *subsys);
|
||||
void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
|
||||
|
||||
A subsystem consists of a toplevel config_group and a semaphore.
|
||||
The group is where child config_items are created. For a subsystem,
|
||||
this group is usually defined statically. Before calling
|
||||
configfs_register_subsystem(), the subsystem must have initialized the
|
||||
group via the usual group _init() functions, and it must also have
|
||||
initialized the semaphore.
|
||||
When the register call returns, the subsystem is live, and it
|
||||
will be visible via configfs. At that point, mkdir(2) can be called and
|
||||
the subsystem must be ready for it.
|
||||
|
||||
[An Example]
|
||||
|
||||
The best example of these basic concepts is the simple_children
|
||||
subsystem/group and the simple_child item in configfs_example.c It
|
||||
shows a trivial object displaying and storing an attribute, and a simple
|
||||
group creating and destroying these children.
|
||||
|
||||
[Hierarchy Navigation and the Subsystem Semaphore]
|
||||
|
||||
There is an extra bonus that configfs provides. The config_groups and
|
||||
config_items are arranged in a hierarchy due to the fact that they
|
||||
appear in a filesystem. A subsystem is NEVER to touch the filesystem
|
||||
parts, but the subsystem might be interested in this hierarchy. For
|
||||
this reason, the hierarchy is mirrored via the config_group->cg_children
|
||||
and config_item->ci_parent structure members.
|
||||
|
||||
A subsystem can navigate the cg_children list and the ci_parent pointer
|
||||
to see the tree created by the subsystem. This can race with configfs'
|
||||
management of the hierarchy, so configfs uses the subsystem semaphore to
|
||||
protect modifications. Whenever a subsystem wants to navigate the
|
||||
hierarchy, it must do so under the protection of the subsystem
|
||||
semaphore.
|
||||
|
||||
A subsystem will be prevented from acquiring the semaphore while a newly
|
||||
allocated item has not been linked into this hierarchy. Similarly, it
|
||||
will not be able to acquire the semaphore while a dropping item has not
|
||||
yet been unlinked. This means that an item's ci_parent pointer will
|
||||
never be NULL while the item is in configfs, and that an item will only
|
||||
be in its parent's cg_children list for the same duration. This allows
|
||||
a subsystem to trust ci_parent and cg_children while they hold the
|
||||
semaphore.
|
||||
|
||||
[Item Aggregation Via symlink(2)]
|
||||
|
||||
configfs provides a simple group via the group->item parent/child
|
||||
relationship. Often, however, a larger environment requires aggregation
|
||||
outside of the parent/child connection. This is implemented via
|
||||
symlink(2).
|
||||
|
||||
A config_item may provide the ct_item_ops->allow_link() and
|
||||
ct_item_ops->drop_link() methods. If the ->allow_link() method exists,
|
||||
symlink(2) may be called with the config_item as the source of the link.
|
||||
These links are only allowed between configfs config_items. Any
|
||||
symlink(2) attempt outside the configfs filesystem will be denied.
|
||||
|
||||
When symlink(2) is called, the source config_item's ->allow_link()
|
||||
method is called with itself and a target item. If the source item
|
||||
allows linking to target item, it returns 0. A source item may wish to
|
||||
reject a link if it only wants links to a certain type of object (say,
|
||||
in its own subsystem).
|
||||
|
||||
When unlink(2) is called on the symbolic link, the source item is
|
||||
notified via the ->drop_link() method. Like the ->drop_item() method,
|
||||
this is a void function and cannot return failure. The subsystem is
|
||||
responsible for responding to the change.
|
||||
|
||||
A config_item cannot be removed while it links to any other item, nor
|
||||
can it be removed while an item links to it. Dangling symlinks are not
|
||||
allowed in configfs.
|
||||
|
||||
[Automatically Created Subgroups]
|
||||
|
||||
A new config_group may want to have two types of child config_items.
|
||||
While this could be codified by magic names in ->make_item(), it is much
|
||||
more explicit to have a method whereby userspace sees this divergence.
|
||||
|
||||
Rather than have a group where some items behave differently than
|
||||
others, configfs provides a method whereby one or many subgroups are
|
||||
automatically created inside the parent at its creation. Thus,
|
||||
mkdir("parent) results in "parent", "parent/subgroup1", up through
|
||||
"parent/subgroupN". Items of type 1 can now be created in
|
||||
"parent/subgroup1", and items of type N can be created in
|
||||
"parent/subgroupN".
|
||||
|
||||
These automatic subgroups, or default groups, do not preclude other
|
||||
children of the parent group. If ct_group_ops->make_group() exists,
|
||||
other child groups can be created on the parent group directly.
|
||||
|
||||
A configfs subsystem specifies default groups by filling in the
|
||||
NULL-terminated array default_groups on the config_group structure.
|
||||
Each group in that array is populated in the configfs tree at the same
|
||||
time as the parent group. Similarly, they are removed at the same time
|
||||
as the parent. No extra notification is provided. When a ->drop_item()
|
||||
method call notifies the subsystem the parent group is going away, it
|
||||
also means every default group child associated with that parent group.
|
||||
|
||||
As a consequence of this, default_groups cannot be removed directly via
|
||||
rmdir(2). They also are not considered when rmdir(2) on the parent
|
||||
group is checking for children.
|
||||
|
||||
[Committable Items]
|
||||
|
||||
NOTE: Committable items are currently unimplemented.
|
||||
|
||||
Some config_items cannot have a valid initial state. That is, no
|
||||
default values can be specified for the item's attributes such that the
|
||||
item can do its work. Userspace must configure one or more attributes,
|
||||
after which the subsystem can start whatever entity this item
|
||||
represents.
|
||||
|
||||
Consider the FakeNBD device from above. Without a target address *and*
|
||||
a target device, the subsystem has no idea what block device to import.
|
||||
The simple example assumes that the subsystem merely waits until all the
|
||||
appropriate attributes are configured, and then connects. This will,
|
||||
indeed, work, but now every attribute store must check if the attributes
|
||||
are initialized. Every attribute store must fire off the connection if
|
||||
that condition is met.
|
||||
|
||||
Far better would be an explicit action notifying the subsystem that the
|
||||
config_item is ready to go. More importantly, an explicit action allows
|
||||
the subsystem to provide feedback as to whether the attibutes are
|
||||
initialized in a way that makes sense. configfs provides this as
|
||||
committable items.
|
||||
|
||||
configfs still uses only normal filesystem operations. An item is
|
||||
committed via rename(2). The item is moved from a directory where it
|
||||
can be modified to a directory where it cannot.
|
||||
|
||||
Any group that provides the ct_group_ops->commit_item() method has
|
||||
committable items. When this group appears in configfs, mkdir(2) will
|
||||
not work directly in the group. Instead, the group will have two
|
||||
subdirectories: "live" and "pending". The "live" directory does not
|
||||
support mkdir(2) or rmdir(2) either. It only allows rename(2). The
|
||||
"pending" directory does allow mkdir(2) and rmdir(2). An item is
|
||||
created in the "pending" directory. Its attributes can be modified at
|
||||
will. Userspace commits the item by renaming it into the "live"
|
||||
directory. At this point, the subsystem recieves the ->commit_item()
|
||||
callback. If all required attributes are filled to satisfaction, the
|
||||
method returns zero and the item is moved to the "live" directory.
|
||||
|
||||
As rmdir(2) does not work in the "live" directory, an item must be
|
||||
shutdown, or "uncommitted". Again, this is done via rename(2), this
|
||||
time from the "live" directory back to the "pending" one. The subsystem
|
||||
is notified by the ct_group_ops->uncommit_object() method.
|
||||
|
||||
|
474
Documentation/filesystems/configfs/configfs_example.c
Normal file
474
Documentation/filesystems/configfs/configfs_example.c
Normal file
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* 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,
|
||||
};
|
||||
|
||||
|
||||
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
|
||||
{
|
||||
struct simple_child *simple_child;
|
||||
|
||||
simple_child = kmalloc(sizeof(struct simple_child), GFP_KERNEL);
|
||||
if (!simple_child)
|
||||
return NULL;
|
||||
|
||||
memset(simple_child, 0, sizeof(struct simple_child));
|
||||
|
||||
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 struct configfs_item_operations simple_children_item_ops = {
|
||||
.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,
|
||||
};
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
struct simple_children {
|
||||
struct config_group group;
|
||||
};
|
||||
|
||||
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
|
||||
{
|
||||
struct simple_children *simple_children;
|
||||
|
||||
simple_children = kmalloc(sizeof(struct simple_children),
|
||||
GFP_KERNEL);
|
||||
if (!simple_children)
|
||||
return NULL;
|
||||
|
||||
memset(simple_children, 0, sizeof(struct simple_children));
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
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);
|
||||
init_MUTEX(&subsys->su_sem);
|
||||
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");
|
130
Documentation/filesystems/dlmfs.txt
Normal file
130
Documentation/filesystems/dlmfs.txt
Normal file
@ -0,0 +1,130 @@
|
||||
dlmfs
|
||||
==================
|
||||
A minimal DLM userspace interface implemented via a virtual file
|
||||
system.
|
||||
|
||||
dlmfs is built with OCFS2 as it requires most of its infrastructure.
|
||||
|
||||
Project web page: http://oss.oracle.com/projects/ocfs2
|
||||
Tools web page: http://oss.oracle.com/projects/ocfs2-tools
|
||||
OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
|
||||
|
||||
All code copyright 2005 Oracle except when otherwise noted.
|
||||
|
||||
CREDITS
|
||||
=======
|
||||
|
||||
Some code taken from ramfs which is Copyright (C) 2000 Linus Torvalds
|
||||
and Transmeta Corp.
|
||||
|
||||
Mark Fasheh <mark.fasheh@oracle.com>
|
||||
|
||||
Caveats
|
||||
=======
|
||||
- Right now it only works with the OCFS2 DLM, though support for other
|
||||
DLM implementations should not be a major issue.
|
||||
|
||||
Mount options
|
||||
=============
|
||||
None
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
If you're just interested in OCFS2, then please see ocfs2.txt. The
|
||||
rest of this document will be geared towards those who want to use
|
||||
dlmfs for easy to setup and easy to use clustered locking in
|
||||
userspace.
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
dlmfs requires that the OCFS2 cluster infrastructure be in
|
||||
place. Please download ocfs2-tools from the above url and configure a
|
||||
cluster.
|
||||
|
||||
You'll want to start heartbeating on a volume which all the nodes in
|
||||
your lockspace can access. The easiest way to do this is via
|
||||
ocfs2_hb_ctl (distributed with ocfs2-tools). Right now it requires
|
||||
that an OCFS2 file system be in place so that it can automatically
|
||||
find it's heartbeat area, though it will eventually support heartbeat
|
||||
against raw disks.
|
||||
|
||||
Please see the ocfs2_hb_ctl and mkfs.ocfs2 manual pages distributed
|
||||
with ocfs2-tools.
|
||||
|
||||
Once you're heartbeating, DLM lock 'domains' can be easily created /
|
||||
destroyed and locks within them accessed.
|
||||
|
||||
Locking
|
||||
=======
|
||||
|
||||
Users may access dlmfs via standard file system calls, or they can use
|
||||
'libo2dlm' (distributed with ocfs2-tools) which abstracts the file
|
||||
system calls and presents a more traditional locking api.
|
||||
|
||||
dlmfs handles lock caching automatically for the user, so a lock
|
||||
request for an already acquired lock will not generate another DLM
|
||||
call. Userspace programs are assumed to handle their own local
|
||||
locking.
|
||||
|
||||
Two levels of locks are supported - Shared Read, and Exlcusive.
|
||||
Also supported is a Trylock operation.
|
||||
|
||||
For information on the libo2dlm interface, please see o2dlm.h,
|
||||
distributed with ocfs2-tools.
|
||||
|
||||
Lock value blocks can be read and written to a resource via read(2)
|
||||
and write(2) against the fd obtained via your open(2) call. The
|
||||
maximum currently supported LVB length is 64 bytes (though that is an
|
||||
OCFS2 DLM limitation). Through this mechanism, users of dlmfs can share
|
||||
small amounts of data amongst their nodes.
|
||||
|
||||
mkdir(2) signals dlmfs to join a domain (which will have the same name
|
||||
as the resulting directory)
|
||||
|
||||
rmdir(2) signals dlmfs to leave the domain
|
||||
|
||||
Locks for a given domain are represented by regular inodes inside the
|
||||
domain directory. Locking against them is done via the open(2) system
|
||||
call.
|
||||
|
||||
The open(2) call will not return until your lock has been granted or
|
||||
an error has occurred, unless it has been instructed to do a trylock
|
||||
operation. If the lock succeeds, you'll get an fd.
|
||||
|
||||
open(2) with O_CREAT to ensure the resource inode is created - dlmfs does
|
||||
not automatically create inodes for existing lock resources.
|
||||
|
||||
Open Flag Lock Request Type
|
||||
--------- -----------------
|
||||
O_RDONLY Shared Read
|
||||
O_RDWR Exclusive
|
||||
|
||||
Open Flag Resulting Locking Behavior
|
||||
--------- --------------------------
|
||||
O_NONBLOCK Trylock operation
|
||||
|
||||
You must provide exactly one of O_RDONLY or O_RDWR.
|
||||
|
||||
If O_NONBLOCK is also provided and the trylock operation was valid but
|
||||
could not lock the resource then open(2) will return ETXTBUSY.
|
||||
|
||||
close(2) drops the lock associated with your fd.
|
||||
|
||||
Modes passed to mkdir(2) or open(2) are adhered to locally. Chown is
|
||||
supported locally as well. This means you can use them to restrict
|
||||
access to the resources via dlmfs on your local node only.
|
||||
|
||||
The resource LVB may be read from the fd in either Shared Read or
|
||||
Exclusive modes via the read(2) system call. It can be written via
|
||||
write(2) only when open in Exclusive mode.
|
||||
|
||||
Once written, an LVB will be visible to other nodes who obtain Read
|
||||
Only or higher level locks on the resource.
|
||||
|
||||
See Also
|
||||
========
|
||||
http://opendlm.sourceforge.net/cvsmirror/opendlm/docs/dlmbook_final.pdf
|
||||
|
||||
For more information on the VMS distributed locking API.
|
@ -57,19 +57,19 @@ oldalloc This disables the Orlov block allocator and enables the
|
||||
we'd like to get some feedback if it's the contrary for
|
||||
you.
|
||||
|
||||
user_xattr (*) Enables POSIX Extended Attributes. It's enabled by
|
||||
default, however you need to confifure its support
|
||||
(CONFIG_EXT3_FS_XATTR). This is neccesary if you want
|
||||
to use POSIX Acces Control Lists support. You can visit
|
||||
http://acl.bestbits.at to know more about POSIX Extended
|
||||
attributes.
|
||||
user_xattr Enables Extended User Attributes. Additionally, you need
|
||||
to have extended attribute support enabled in the kernel
|
||||
configuration (CONFIG_EXT3_FS_XATTR). See the attr(5)
|
||||
manual page and http://acl.bestbits.at to learn more
|
||||
about extended attributes.
|
||||
|
||||
nouser_xattr Disables POSIX Extended Attributes.
|
||||
nouser_xattr Disables Extended User Attributes.
|
||||
|
||||
acl (*) Enables POSIX Access Control Lists support. This is
|
||||
enabled by default, however you need to configure
|
||||
its support (CONFIG_EXT3_FS_POSIX_ACL). If you want
|
||||
to know more about ACLs visit http://acl.bestbits.at
|
||||
acl Enables POSIX Access Control Lists support. Additionally,
|
||||
you need to have ACL support enabled in the kernel
|
||||
configuration (CONFIG_EXT3_FS_POSIX_ACL). See the acl(5)
|
||||
manual page and http://acl.bestbits.at for more
|
||||
information.
|
||||
|
||||
noacl This option disables POSIX Access Control List support.
|
||||
|
||||
|
55
Documentation/filesystems/ocfs2.txt
Normal file
55
Documentation/filesystems/ocfs2.txt
Normal file
@ -0,0 +1,55 @@
|
||||
OCFS2 filesystem
|
||||
==================
|
||||
OCFS2 is a general purpose extent based shared disk cluster file
|
||||
system with many similarities to ext3. It supports 64 bit inode
|
||||
numbers, and has automatically extending metadata groups which may
|
||||
also make it attractive for non-clustered use.
|
||||
|
||||
You'll want to install the ocfs2-tools package in order to at least
|
||||
get "mount.ocfs2" and "ocfs2_hb_ctl".
|
||||
|
||||
Project web page: http://oss.oracle.com/projects/ocfs2
|
||||
Tools web page: http://oss.oracle.com/projects/ocfs2-tools
|
||||
OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
|
||||
|
||||
All code copyright 2005 Oracle except when otherwise noted.
|
||||
|
||||
CREDITS:
|
||||
Lots of code taken from ext3 and other projects.
|
||||
|
||||
Authors in alphabetical order:
|
||||
Joel Becker <joel.becker@oracle.com>
|
||||
Zach Brown <zach.brown@oracle.com>
|
||||
Mark Fasheh <mark.fasheh@oracle.com>
|
||||
Kurt Hackel <kurt.hackel@oracle.com>
|
||||
Sunil Mushran <sunil.mushran@oracle.com>
|
||||
Manish Singh <manish.singh@oracle.com>
|
||||
|
||||
Caveats
|
||||
=======
|
||||
Features which OCFS2 does not support yet:
|
||||
- sparse files
|
||||
- extended attributes
|
||||
- shared writeable mmap
|
||||
- loopback is supported, but data written will not
|
||||
be cluster coherent.
|
||||
- quotas
|
||||
- cluster aware flock
|
||||
- Directory change notification (F_NOTIFY)
|
||||
- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
|
||||
- POSIX ACLs
|
||||
- readpages / writepages (not user visible)
|
||||
|
||||
Mount options
|
||||
=============
|
||||
|
||||
OCFS2 supports the following mount options:
|
||||
(*) == default
|
||||
|
||||
barrier=1 This enables/disables barriers. barrier=0 disables it,
|
||||
barrier=1 enables it.
|
||||
errors=remount-ro(*) Remount the filesystem read-only on an error.
|
||||
errors=panic Panic and halt the machine if an error occurs.
|
||||
intr (*) Allow signals to interrupt cluster operations.
|
||||
nointr Do not allow signals to interrupt cluster
|
||||
operations.
|
@ -162,9 +162,8 @@ get_sb() method fills in is the "s_op" field. This is a pointer to
|
||||
a "struct super_operations" which describes the next level of the
|
||||
filesystem implementation.
|
||||
|
||||
Usually, a filesystem uses generic one of the generic get_sb()
|
||||
implementations and provides a fill_super() method instead. The
|
||||
generic methods are:
|
||||
Usually, a filesystem uses one of the generic get_sb() implementations
|
||||
and provides a fill_super() method instead. The generic methods are:
|
||||
|
||||
get_sb_bdev: mount a filesystem residing on a block device
|
||||
|
||||
|
@ -54,13 +54,16 @@ If you really want i2c accesses for these Super I/O chips,
|
||||
use the w83781d driver. However this is not the preferred method
|
||||
now that this ISA driver has been developed.
|
||||
|
||||
Technically, the w83627thf does not support a VID reading. However, it's
|
||||
possible or even likely that your mainboard maker has routed these signals
|
||||
to a specific set of general purpose IO pins (the Asus P4C800-E is one such
|
||||
board). The w83627thf driver now interprets these as VID. If the VID on
|
||||
your board doesn't work, first see doc/vid in the lm_sensors package. If
|
||||
that still doesn't help, email us at lm-sensors@lm-sensors.org.
|
||||
The w83627_HF_ uses pins 110-106 as VID0-VID4. The w83627_THF_ uses the
|
||||
same pins as GPIO[0:4]. Technically, the w83627_THF_ does not support a
|
||||
VID reading. However the two chips have the identical 128 pin package. So,
|
||||
it is possible or even likely for a w83627thf to have the VID signals routed
|
||||
to these pins despite their not being labeled for that purpose. Therefore,
|
||||
the w83627thf driver interprets these as VID. If the VID on your board
|
||||
doesn't work, first see doc/vid in the lm_sensors package[1]. If that still
|
||||
doesn't help, you may just ignore the bogus VID reading with no harm done.
|
||||
|
||||
For further information on this driver see the w83781d driver
|
||||
documentation.
|
||||
For further information on this driver see the w83781d driver documentation.
|
||||
|
||||
[1] http://www2.lm-sensors.nu/~lm78/cvs/browse.cgi/lm_sensors2/doc/vid
|
||||
|
||||
|
@ -5,7 +5,8 @@ Supported adapters:
|
||||
* nForce2 Ultra 400 MCP 10de:0084
|
||||
* nForce3 Pro150 MCP 10de:00D4
|
||||
* nForce3 250Gb MCP 10de:00E4
|
||||
* nForce4 MCP 10de:0052
|
||||
* nForce4 MCP 10de:0052
|
||||
* nForce4 MCP-04 10de:0034
|
||||
|
||||
Datasheet: not publically available, but seems to be similar to the
|
||||
AMD-8111 SMBus 2.0 adapter.
|
||||
|
@ -17,6 +17,7 @@ It currently supports the following devices:
|
||||
* Velleman K8000 adapter
|
||||
* ELV adapter
|
||||
* Analog Devices evaluation boards (ADM1025, ADM1030, ADM1031, ADM1032)
|
||||
* Barco LPT->DVI (K5800236) adapter
|
||||
|
||||
These devices use different pinout configurations, so you have to tell
|
||||
the driver what you have, using the type module parameter. There is no
|
||||
|
@ -1,10 +1,13 @@
|
||||
Revision 5, 2005-07-29
|
||||
Revision 6, 2005-11-20
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
Greg KH <greg@kroah.com>
|
||||
|
||||
This is a guide on how to convert I2C chip drivers from Linux 2.4 to
|
||||
Linux 2.6. I have been using existing drivers (lm75, lm78) as examples.
|
||||
Then I converted a driver myself (lm83) and updated this document.
|
||||
Note that this guide is strongly oriented towards hardware monitoring
|
||||
drivers. Many points are still valid for other type of drivers, but
|
||||
others may be irrelevant.
|
||||
|
||||
There are two sets of points below. The first set concerns technical
|
||||
changes. The second set concerns coding policy. Both are mandatory.
|
||||
@ -22,16 +25,20 @@ Technical changes:
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-isa.h> /* for ISA drivers */
|
||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||
#include <linux/err.h> /* for class registration */
|
||||
#include <asm/io.h> /* if you have I/O operations */
|
||||
Please respect this inclusion order. Some extra headers may be
|
||||
required for a given driver (e.g. "lm75.h").
|
||||
|
||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
|
||||
are no more handled by the i2c core.
|
||||
are no more handled by the i2c core. Address ranges are no more
|
||||
supported either, define each individual address separately.
|
||||
SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
|
||||
|
||||
* [Client data] Get rid of sysctl_id. Try using standard names for
|
||||
@ -48,23 +55,23 @@ Technical changes:
|
||||
int kind);
|
||||
static void lm75_init_client(struct i2c_client *client);
|
||||
static int lm75_detach_client(struct i2c_client *client);
|
||||
static void lm75_update_client(struct i2c_client *client);
|
||||
static struct lm75_data lm75_update_device(struct device *dev);
|
||||
|
||||
* [Sysctl] All sysctl stuff is of course gone (defines, ctl_table
|
||||
and functions). Instead, you have to define show and set functions for
|
||||
each sysfs file. Only define set for writable values. Take a look at an
|
||||
existing 2.6 driver for details (lm78 for example). Don't forget
|
||||
existing 2.6 driver for details (it87 for example). Don't forget
|
||||
to define the attributes for each file (this is that step that
|
||||
links callback functions). Use the file names specified in
|
||||
Documentation/i2c/sysfs-interface for the individual files. Also
|
||||
Documentation/hwmon/sysfs-interface for the individual files. Also
|
||||
convert the units these files read and write to the specified ones.
|
||||
If you need to add a new type of file, please discuss it on the
|
||||
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
|
||||
patch to the Documentation/i2c/sysfs-interface file.
|
||||
patch to the Documentation/hwmon/sysfs-interface file.
|
||||
|
||||
* [Attach] For I2C drivers, the attach function should make sure
|
||||
that the adapter's class has I2C_CLASS_HWMON, using the
|
||||
following construct:
|
||||
that the adapter's class has I2C_CLASS_HWMON (or whatever class is
|
||||
suitable for your driver), using the following construct:
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
ISA-only drivers of course don't need this.
|
||||
@ -72,63 +79,72 @@ Technical changes:
|
||||
|
||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||
The type_name and client_name strings are replaced by a single
|
||||
name string, which will be filled with a lowercase, short string
|
||||
(typically the driver name, e.g. "lm75").
|
||||
name string, which will be filled with a lowercase, short string.
|
||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
||||
useless. Same for isa-only drivers, as the test would always be
|
||||
true. Only hybrid drivers (which are quite rare) still need it.
|
||||
The errorN labels are reduced to the number needed. If that number
|
||||
is 2 (i2c-only drivers), it is advised that the labels are named
|
||||
exit and exit_free. For i2c+isa drivers, labels should be named
|
||||
ERROR0, ERROR1 and ERROR2. Don't forget to properly set err before
|
||||
The labels used for error paths are reduced to the number needed.
|
||||
It is advised that the labels are given descriptive names such as
|
||||
exit and exit_free. Don't forget to properly set err before
|
||||
jumping to error labels. By the way, labels should be left-aligned.
|
||||
Use kzalloc instead of kmalloc.
|
||||
Use i2c_set_clientdata to set the client data (as opposed to
|
||||
a direct access to client->data).
|
||||
Use strlcpy instead of strcpy to copy the client name.
|
||||
Use strlcpy instead of strcpy or snprintf to copy the client name.
|
||||
Replace the sysctl directory registration by calls to
|
||||
device_create_file. Move the driver initialization before any
|
||||
sysfs file creation.
|
||||
Register the client with the hwmon class (using hwmon_device_register)
|
||||
if applicable.
|
||||
Drop client->id.
|
||||
Drop any 24RF08 corruption prevention you find, as this is now done
|
||||
at the i2c-core level, and doing it twice voids it.
|
||||
Don't add I2C_CLIENT_ALLOW_USE to client->flags, it's the default now.
|
||||
|
||||
* [Init] Limits must not be set by the driver (can be done later in
|
||||
user-space). Chip should not be reset default (although a module
|
||||
parameter may be used to force is), and initialization should be
|
||||
parameter may be used to force it), and initialization should be
|
||||
limited to the strictly necessary steps.
|
||||
|
||||
* [Detach] Get rid of data, remove the call to
|
||||
i2c_deregister_entry. Do not log an error message if
|
||||
i2c_detach_client fails, as i2c-core will now do it for you.
|
||||
* [Detach] Remove the call to i2c_deregister_entry. Do not log an
|
||||
error message if i2c_detach_client fails, as i2c-core will now do
|
||||
it for you.
|
||||
Unregister from the hwmon class if applicable.
|
||||
|
||||
* [Update] Don't access client->data directly, use
|
||||
i2c_get_clientdata(client) instead.
|
||||
* [Update] The function prototype changed, it is now
|
||||
passed a device structure, which you have to convert to a client
|
||||
using to_i2c_client(dev). The update function should return a
|
||||
pointer to the client data.
|
||||
Don't access client->data directly, use i2c_get_clientdata(client)
|
||||
instead.
|
||||
Use time_after() instead of direct jiffies comparison.
|
||||
|
||||
* [Interface] Init function should not print anything. Make sure
|
||||
there is a MODULE_LICENSE() line, at the bottom of the file
|
||||
(after MODULE_AUTHOR() and MODULE_DESCRIPTION(), in this order).
|
||||
* [Interface] Make sure there is a MODULE_LICENSE() line, at the bottom
|
||||
of the file (after MODULE_AUTHOR() and MODULE_DESCRIPTION(), in this
|
||||
order).
|
||||
|
||||
* [Driver] The flags field of the i2c_driver structure is gone.
|
||||
I2C_DF_NOTIFY is now the default behavior.
|
||||
The i2c_driver structure has a driver member, which is itself a
|
||||
structure, those name member should be initialized to a driver name
|
||||
string. i2c_driver itself has no name member anymore.
|
||||
|
||||
Coding policy:
|
||||
|
||||
* [Copyright] Use (C), not (c), for copyright.
|
||||
|
||||
* [Debug/log] Get rid of #ifdef DEBUG/#endif constructs whenever you
|
||||
can. Calls to printk/pr_debug for debugging purposes are replaced
|
||||
by calls to dev_dbg. Here is an example on how to call it (taken
|
||||
from lm75_detect):
|
||||
can. Calls to printk for debugging purposes are replaced by calls to
|
||||
dev_dbg where possible, else to pr_debug. Here is an example of how
|
||||
to call it (taken from lm75_detect):
|
||||
dev_dbg(&client->dev, "Starting lm75 update\n");
|
||||
Replace other printk calls with the dev_info, dev_err or dev_warn
|
||||
function, as appropriate.
|
||||
|
||||
* [Constants] Constants defines (registers, conversions, initial
|
||||
values) should be aligned. This greatly improves readability.
|
||||
Same goes for variables declarations. Alignments are achieved by the
|
||||
means of tabs, not spaces. Remember that tabs are set to 8 in the
|
||||
Linux kernel code.
|
||||
|
||||
* [Structure definition] The name field should be standardized. All
|
||||
lowercase and as simple as the driver name itself (e.g. "lm75").
|
||||
* [Constants] Constants defines (registers, conversions) should be
|
||||
aligned. This greatly improves readability.
|
||||
Alignments are achieved by the means of tabs, not spaces. Remember
|
||||
that tabs are set to 8 in the Linux kernel code.
|
||||
|
||||
* [Layout] Avoid extra empty lines between comments and what they
|
||||
comment. Respect the coding style (see Documentation/CodingStyle),
|
||||
|
@ -25,9 +25,9 @@ routines, a client structure specific information like the actual I2C
|
||||
address.
|
||||
|
||||
static struct i2c_driver foo_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "Foo version 2.3 driver",
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.driver = {
|
||||
.name = "foo",
|
||||
},
|
||||
.attach_adapter = &foo_attach_adapter,
|
||||
.detach_client = &foo_detach_client,
|
||||
.command = &foo_command /* may be NULL */
|
||||
@ -36,10 +36,6 @@ static struct i2c_driver foo_driver = {
|
||||
The name field must match the driver name, including the case. It must not
|
||||
contain spaces, and may be up to 31 characters long.
|
||||
|
||||
Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
|
||||
means that your driver will be notified when new adapters are found.
|
||||
This is almost always what you want.
|
||||
|
||||
All other fields are for call-back functions which will be explained
|
||||
below.
|
||||
|
||||
@ -496,17 +492,13 @@ Note that some functions are marked by `__init', and some data structures
|
||||
by `__init_data'. Hose functions and structures can be removed after
|
||||
kernel booting (or module loading) is completed.
|
||||
|
||||
|
||||
Command function
|
||||
================
|
||||
|
||||
A generic ioctl-like function call back is supported. You will seldom
|
||||
need this. You may even set it to NULL.
|
||||
|
||||
/* No commands defined */
|
||||
int foo_command(struct i2c_client *client, unsigned int cmd, void *arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
need this, and its use is deprecated anyway, so newer design should not
|
||||
use it. Set it to NULL.
|
||||
|
||||
|
||||
Sending and receiving
|
||||
|
@ -18,6 +18,7 @@ In this document you will find information about:
|
||||
=== 5. Include files
|
||||
--- 5.1 How to include files from the kernel include dir
|
||||
--- 5.2 External modules using an include/ dir
|
||||
--- 5.3 External modules using several directories
|
||||
=== 6. Module installation
|
||||
--- 6.1 INSTALL_MOD_PATH
|
||||
--- 6.2 INSTALL_MOD_DIR
|
||||
@ -38,7 +39,7 @@ included in the kernel tree.
|
||||
What is covered within this file is mainly information to authors
|
||||
of modules. The author of an external modules should supply
|
||||
a makefile that hides most of the complexity so one only has to type
|
||||
'make' to buld the module. A complete example will be present in
|
||||
'make' to build the module. A complete example will be present in
|
||||
chapter ¤. Creating a kbuild file for an external module".
|
||||
|
||||
|
||||
@ -69,7 +70,7 @@ when building an external module.
|
||||
|
||||
--- 2.2 Available targets
|
||||
|
||||
$KDIR refers to path to kernel source top-level directory
|
||||
$KDIR refers to the path to the kernel source top-level directory
|
||||
|
||||
make -C $KDIR M=`pwd`
|
||||
Will build the module(s) located in current directory.
|
||||
@ -87,11 +88,11 @@ when building an external module.
|
||||
make -C $KDIR M=$PWD modules_install
|
||||
Install the external module(s).
|
||||
Installation default is in /lib/modules/<kernel-version>/extra,
|
||||
but may be prefixed with INSTALL_MOD_PATH - see separate chater.
|
||||
but may be prefixed with INSTALL_MOD_PATH - see separate chapter.
|
||||
|
||||
make -C $KDIR M=$PWD clean
|
||||
Remove all generated files for the module - the kernel
|
||||
source directory is not moddified.
|
||||
source directory is not modified.
|
||||
|
||||
make -C $KDIR M=`pwd` help
|
||||
help will list the available target when building external
|
||||
@ -99,7 +100,7 @@ when building an external module.
|
||||
|
||||
--- 2.3 Available options:
|
||||
|
||||
$KDIR refer to path to kernel src
|
||||
$KDIR refers to the path to the kernel source top-level directory
|
||||
|
||||
make -C $KDIR
|
||||
Used to specify where to find the kernel source.
|
||||
@ -206,11 +207,11 @@ following files:
|
||||
|
||||
KERNELDIR := /lib/modules/`uname -r`/build
|
||||
all::
|
||||
$(MAKE) -C $KERNELDIR M=`pwd` $@
|
||||
$(MAKE) -C $(KERNELDIR) M=`pwd` $@
|
||||
|
||||
# Module specific targets
|
||||
genbin:
|
||||
echo "X" > 8123_bini.o_shipped
|
||||
echo "X" > 8123_bin.o_shipped
|
||||
|
||||
endif
|
||||
|
||||
@ -341,13 +342,52 @@ directory and therefore needs to deal with this in their kbuild file.
|
||||
EXTRA_CFLAGS := -Iinclude
|
||||
8123-y := 8123_if.o 8123_pci.o 8123_bin.o
|
||||
|
||||
Note that in the assingment there is no space between -I and the path.
|
||||
This is a kbuild limitation and no space must be present.
|
||||
Note that in the assignment there is no space between -I and the path.
|
||||
This is a kbuild limitation: there must be no space present.
|
||||
|
||||
--- 5.3 External modules using several directories
|
||||
|
||||
If an external module does not follow the usual kernel style but
|
||||
decide to spread files over several directories then kbuild can
|
||||
support this too.
|
||||
|
||||
Consider the following example:
|
||||
|
||||
|
|
||||
+- src/complex_main.c
|
||||
| +- hal/hardwareif.c
|
||||
| +- hal/include/hardwareif.h
|
||||
+- include/complex.h
|
||||
|
||||
To build a single module named complex.ko we then need the following
|
||||
kbuild file:
|
||||
|
||||
Kbuild:
|
||||
obj-m := complex.o
|
||||
complex-y := src/complex_main.o
|
||||
complex-y += src/hal/hardwareif.o
|
||||
|
||||
EXTRA_CFLAGS := -I$(src)/include
|
||||
EXTRA_CFLAGS += -I$(src)src/hal/include
|
||||
|
||||
|
||||
kbuild knows how to handle .o files located in another directory -
|
||||
although this is NOT reccommended practice. The syntax is to specify
|
||||
the directory relative to the directory where the Kbuild file is
|
||||
located.
|
||||
|
||||
To find the .h files we have to explicitly tell kbuild where to look
|
||||
for the .h files. When kbuild executes current directory is always
|
||||
the root of the kernel tree (argument to -C) and therefore we have to
|
||||
tell kbuild how to find the .h files using absolute paths.
|
||||
$(src) will specify the absolute path to the directory where the
|
||||
Kbuild file are located when being build as an external module.
|
||||
Therefore -I$(src)/ is used to point out the directory of the Kbuild
|
||||
file and any additional path are just appended.
|
||||
|
||||
=== 6. Module installation
|
||||
|
||||
Modules which are included in the kernel is installed in the directory:
|
||||
Modules which are included in the kernel are installed in the directory:
|
||||
|
||||
/lib/modules/$(KERNELRELEASE)/kernel
|
||||
|
||||
@ -365,7 +405,7 @@ External modules are installed in the directory:
|
||||
=> Install dir: /frodo/lib/modules/$(KERNELRELEASE)/kernel
|
||||
|
||||
INSTALL_MOD_PATH may be set as an ordinary shell variable or as in the
|
||||
example above be specified on the commandline when calling make.
|
||||
example above be specified on the command line when calling make.
|
||||
INSTALL_MOD_PATH has effect both when installing modules included in
|
||||
the kernel as well as when installing external modules.
|
||||
|
||||
@ -384,7 +424,7 @@ External modules are installed in the directory:
|
||||
|
||||
=== 7. Module versioning
|
||||
|
||||
Module versioning are enabled by the CONFIG_MODVERSIONS tag.
|
||||
Module versioning is enabled by the CONFIG_MODVERSIONS tag.
|
||||
|
||||
Module versioning is used as a simple ABI consistency check. The Module
|
||||
versioning creates a CRC value of the full prototype for an exported symbol and
|
||||
|
@ -633,6 +633,14 @@ running once the system is up.
|
||||
inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
|
||||
Format: <irq>
|
||||
|
||||
combined_mode= [HW] control which driver uses IDE ports in combined
|
||||
mode: legacy IDE driver, libata, or both
|
||||
(in the libata case, libata.atapi_enabled=1 may be
|
||||
useful as well). Note that using the ide or libata
|
||||
options may affect your device naming (e.g. by
|
||||
changing hdc to sdb).
|
||||
Format: combined (default), ide, or libata
|
||||
|
||||
inttest= [IA64]
|
||||
|
||||
io7= [HW] IO7 for Marvel based alpha systems
|
||||
@ -902,6 +910,14 @@ running once the system is up.
|
||||
nfsroot= [NFS] nfs root filesystem for disk-less boxes.
|
||||
See Documentation/nfsroot.txt.
|
||||
|
||||
nfs.callback_tcpport=
|
||||
[NFS] set the TCP port on which the NFSv4 callback
|
||||
channel should listen.
|
||||
|
||||
nfs.idmap_cache_timeout=
|
||||
[NFS] set the maximum lifetime for idmapper cache
|
||||
entries.
|
||||
|
||||
nmi_watchdog= [KNL,BUGS=IA-32] Debugging features for SMP kernels
|
||||
|
||||
no387 [BUGS=IA-32] Tells the kernel to use the 387 maths
|
||||
|
@ -860,24 +860,6 @@ The structure has a number of fields, some of which are mandatory:
|
||||
It is safe to sleep in this method.
|
||||
|
||||
|
||||
(*) int (*duplicate)(struct key *key, const struct key *source);
|
||||
|
||||
If this type of key can be duplicated, then this method should be
|
||||
provided. It is called to copy the payload attached to the source into the
|
||||
new key. The data length on the new key will have been updated and the
|
||||
quota adjusted already.
|
||||
|
||||
This method will be called with the source key's semaphore read-locked to
|
||||
prevent its payload from being changed, thus RCU constraints need not be
|
||||
applied to the source key.
|
||||
|
||||
This method does not have to lock the destination key in order to attach a
|
||||
payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
|
||||
prevents anything else from gaining access to the key.
|
||||
|
||||
It is safe to sleep in this method.
|
||||
|
||||
|
||||
(*) int (*update)(struct key *key, const void *data, size_t datalen);
|
||||
|
||||
If this type of key can be updated, then this method should be provided.
|
||||
|
@ -51,6 +51,30 @@ superblock can be autodetected and run at boot time.
|
||||
The kernel parameter "raid=partitionable" (or "raid=part") means
|
||||
that all auto-detected arrays are assembled as partitionable.
|
||||
|
||||
Boot time assembly of degraded/dirty arrays
|
||||
-------------------------------------------
|
||||
|
||||
If a raid5 or raid6 array is both dirty and degraded, it could have
|
||||
undetectable data corruption. This is because the fact that it is
|
||||
'dirty' means that the parity cannot be trusted, and the fact that it
|
||||
is degraded means that some datablocks are missing and cannot reliably
|
||||
be reconstructed (due to no parity).
|
||||
|
||||
For this reason, md will normally refuse to start such an array. This
|
||||
requires the sysadmin to take action to explicitly start the array
|
||||
desipite possible corruption. This is normally done with
|
||||
mdadm --assemble --force ....
|
||||
|
||||
This option is not really available if the array has the root
|
||||
filesystem on it. In order to support this booting from such an
|
||||
array, md supports a module parameter "start_dirty_degraded" which,
|
||||
when set to 1, bypassed the checks and will allows dirty degraded
|
||||
arrays to be started.
|
||||
|
||||
So, to boot with a root filesystem of a dirty degraded raid[56], use
|
||||
|
||||
md-mod.start_dirty_degraded=1
|
||||
|
||||
|
||||
Superblock formats
|
||||
------------------
|
||||
@ -141,6 +165,70 @@ All md devices contain:
|
||||
in a fully functional array. If this is not yet known, the file
|
||||
will be empty. If an array is being resized (not currently
|
||||
possible) this will contain the larger of the old and new sizes.
|
||||
Some raid level (RAID1) allow this value to be set while the
|
||||
array is active. This will reconfigure the array. Otherwise
|
||||
it can only be set while assembling an array.
|
||||
|
||||
chunk_size
|
||||
This is the size if bytes for 'chunks' and is only relevant to
|
||||
raid levels that involve striping (1,4,5,6,10). The address space
|
||||
of the array is conceptually divided into chunks and consecutive
|
||||
chunks are striped onto neighbouring devices.
|
||||
The size should be atleast PAGE_SIZE (4k) and should be a power
|
||||
of 2. This can only be set while assembling an array
|
||||
|
||||
component_size
|
||||
For arrays with data redundancy (i.e. not raid0, linear, faulty,
|
||||
multipath), all components must be the same size - or at least
|
||||
there must a size that they all provide space for. This is a key
|
||||
part or the geometry of the array. It is measured in sectors
|
||||
and can be read from here. Writing to this value may resize
|
||||
the array if the personality supports it (raid1, raid5, raid6),
|
||||
and if the component drives are large enough.
|
||||
|
||||
metadata_version
|
||||
This indicates the format that is being used to record metadata
|
||||
about the array. It can be 0.90 (traditional format), 1.0, 1.1,
|
||||
1.2 (newer format in varying locations) or "none" indicating that
|
||||
the kernel isn't managing metadata at all.
|
||||
|
||||
level
|
||||
The raid 'level' for this array. The name will often (but not
|
||||
always) be the same as the name of the module that implements the
|
||||
level. To be auto-loaded the module must have an alias
|
||||
md-$LEVEL e.g. md-raid5
|
||||
This can be written only while the array is being assembled, not
|
||||
after it is started.
|
||||
|
||||
new_dev
|
||||
This file can be written but not read. The value written should
|
||||
be a block device number as major:minor. e.g. 8:0
|
||||
This will cause that device to be attached to the array, if it is
|
||||
available. It will then appear at md/dev-XXX (depending on the
|
||||
name of the device) and further configuration is then possible.
|
||||
|
||||
sync_speed_min
|
||||
sync_speed_max
|
||||
This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
|
||||
however they only apply to the particular array.
|
||||
If no value has been written to these, of if the word 'system'
|
||||
is written, then the system-wide value is used. If a value,
|
||||
in kibibytes-per-second is written, then it is used.
|
||||
When the files are read, they show the currently active value
|
||||
followed by "(local)" or "(system)" depending on whether it is
|
||||
a locally set or system-wide value.
|
||||
|
||||
sync_completed
|
||||
This shows the number of sectors that have been completed of
|
||||
whatever the current sync_action is, followed by the number of
|
||||
sectors in total that could need to be processed. The two
|
||||
numbers are separated by a '/' thus effectively showing one
|
||||
value, a fraction of the process that is complete.
|
||||
|
||||
sync_speed
|
||||
This shows the current actual speed, in K/sec, of the current
|
||||
sync_action. It is averaged over the last 30 seconds.
|
||||
|
||||
|
||||
As component devices are added to an md array, they appear in the 'md'
|
||||
directory as new directories named
|
||||
@ -167,6 +255,38 @@ Each directory contains:
|
||||
of being recoverred to
|
||||
This list make grow in future.
|
||||
|
||||
errors
|
||||
An approximate count of read errors that have been detected on
|
||||
this device but have not caused the device to be evicted from
|
||||
the array (either because they were corrected or because they
|
||||
happened while the array was read-only). When using version-1
|
||||
metadata, this value persists across restarts of the array.
|
||||
|
||||
This value can be written while assembling an array thus
|
||||
providing an ongoing count for arrays with metadata managed by
|
||||
userspace.
|
||||
|
||||
slot
|
||||
This gives the role that the device has in the array. It will
|
||||
either be 'none' if the device is not active in the array
|
||||
(i.e. is a spare or has failed) or an integer less than the
|
||||
'raid_disks' number for the array indicating which possition
|
||||
it currently fills. This can only be set while assembling an
|
||||
array. A device for which this is set is assumed to be working.
|
||||
|
||||
offset
|
||||
This gives the location in the device (in sectors from the
|
||||
start) where data from the array will be stored. Any part of
|
||||
the device before this offset us not touched, unless it is
|
||||
used for storing metadata (Formats 1.1 and 1.2).
|
||||
|
||||
size
|
||||
The amount of the device, after the offset, that can be used
|
||||
for storage of data. This will normally be the same as the
|
||||
component_size. This can be written while assembling an
|
||||
array. If a value less than the current component_size is
|
||||
written, component_size will be reduced to this value.
|
||||
|
||||
|
||||
An active md device will also contain and entry for each active device
|
||||
in the array. These are named
|
||||
|
72
Documentation/networking/gianfar.txt
Normal file
72
Documentation/networking/gianfar.txt
Normal file
@ -0,0 +1,72 @@
|
||||
The Gianfar Ethernet Driver
|
||||
Sysfs File description
|
||||
|
||||
Author: Andy Fleming <afleming@freescale.com>
|
||||
Updated: 2005-07-28
|
||||
|
||||
SYSFS
|
||||
|
||||
Several of the features of the gianfar driver are controlled
|
||||
through sysfs files. These are:
|
||||
|
||||
bd_stash:
|
||||
To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
|
||||
bd_stash, echo 'off' or '0' to disable
|
||||
|
||||
rx_stash_len:
|
||||
To stash the first n bytes of the packet in L2, echo the number
|
||||
of bytes to buf_stash_len. echo 0 to disable.
|
||||
|
||||
WARNING: You could really screw these up if you set them too low or high!
|
||||
fifo_threshold:
|
||||
To change the number of bytes the controller needs in the
|
||||
fifo before it starts transmission, echo the number of bytes to
|
||||
fifo_thresh. Range should be 0-511.
|
||||
|
||||
fifo_starve:
|
||||
When the FIFO has less than this many bytes during a transmit, it
|
||||
enters starve mode, and increases the priority of TX memory
|
||||
transactions. To change, echo the number of bytes to
|
||||
fifo_starve. Range should be 0-511.
|
||||
|
||||
fifo_starve_off:
|
||||
Once in starve mode, the FIFO remains there until it has this
|
||||
many bytes. To change, echo the number of bytes to
|
||||
fifo_starve_off. Range should be 0-511.
|
||||
|
||||
CHECKSUM OFFLOADING
|
||||
|
||||
The eTSEC controller (first included in parts from late 2005 like
|
||||
the 8548) has the ability to perform TCP, UDP, and IP checksums
|
||||
in hardware. The Linux kernel only offloads the TCP and UDP
|
||||
checksums (and always performs the pseudo header checksums), so
|
||||
the driver only supports checksumming for TCP/IP and UDP/IP
|
||||
packets. Use ethtool to enable or disable this feature for RX
|
||||
and TX.
|
||||
|
||||
VLAN
|
||||
|
||||
In order to use VLAN, please consult Linux documentation on
|
||||
configuring VLANs. The gianfar driver supports hardware insertion and
|
||||
extraction of VLAN headers, but not filtering. Filtering will be
|
||||
done by the kernel.
|
||||
|
||||
MULTICASTING
|
||||
|
||||
The gianfar driver supports using the group hash table on the
|
||||
TSEC (and the extended hash table on the eTSEC) for multicast
|
||||
filtering. On the eTSEC, the exact-match MAC registers are used
|
||||
before the hash tables. See Linux documentation on how to join
|
||||
multicast groups.
|
||||
|
||||
PADDING
|
||||
|
||||
The gianfar driver supports padding received frames with 2 bytes
|
||||
to align the IP header to a 16-byte boundary, when supported by
|
||||
hardware.
|
||||
|
||||
ETHTOOL
|
||||
|
||||
The gianfar driver supports the use of ethtool for many
|
||||
configuration options. You must run ethtool only on currently
|
||||
open interfaces. See ethtool documentation for details.
|
@ -46,6 +46,29 @@ ipfrag_secret_interval - INTEGER
|
||||
for the hash secret) for IP fragments.
|
||||
Default: 600
|
||||
|
||||
ipfrag_max_dist - INTEGER
|
||||
ipfrag_max_dist is a non-negative integer value which defines the
|
||||
maximum "disorder" which is allowed among fragments which share a
|
||||
common IP source address. Note that reordering of packets is
|
||||
not unusual, but if a large number of fragments arrive from a source
|
||||
IP address while a particular fragment queue remains incomplete, it
|
||||
probably indicates that one or more fragments belonging to that queue
|
||||
have been lost. When ipfrag_max_dist is positive, an additional check
|
||||
is done on fragments before they are added to a reassembly queue - if
|
||||
ipfrag_max_dist (or more) fragments have arrived from a particular IP
|
||||
address between additions to any IP fragment queue using that source
|
||||
address, it's presumed that one or more fragments in the queue are
|
||||
lost. The existing fragment queue will be dropped, and a new one
|
||||
started. An ipfrag_max_dist value of zero disables this check.
|
||||
|
||||
Using a very small value, e.g. 1 or 2, for ipfrag_max_dist can
|
||||
result in unnecessarily dropping fragment queues when normal
|
||||
reordering of packets occurs, which could lead to poor application
|
||||
performance. Using a very large value, e.g. 50000, increases the
|
||||
likelihood of incorrectly reassembling IP fragments that originate
|
||||
from different IP datagrams, which could result in data corruption.
|
||||
Default: 64
|
||||
|
||||
INET peer storage:
|
||||
|
||||
inet_peer_threshold - INTEGER
|
||||
|
@ -1,5 +1,16 @@
|
||||
This file details changes in 2.6 which affect PCMCIA card driver authors:
|
||||
|
||||
* Unify detach and REMOVAL event code, as well as attach and INSERTION
|
||||
code (as of 2.6.16)
|
||||
void (*remove) (struct pcmcia_device *dev);
|
||||
int (*probe) (struct pcmcia_device *dev);
|
||||
|
||||
* Move suspend, resume and reset out of event handler (as of 2.6.16)
|
||||
int (*suspend) (struct pcmcia_device *dev);
|
||||
int (*resume) (struct pcmcia_device *dev);
|
||||
should be initialized in struct pcmcia_driver, and handle
|
||||
(SUSPEND == RESET_PHYSICAL) and (RESUME == CARD_RESET) events
|
||||
|
||||
* event handler initialization in struct pcmcia_driver (as of 2.6.13)
|
||||
The event handler is notified of all events, and must be initialized
|
||||
as the event() callback in the driver's struct pcmcia_driver.
|
||||
|
@ -41,3 +41,14 @@ to. Writing to this file will accept one of
|
||||
It will only change to 'firmware' or 'platform' if the system supports
|
||||
it.
|
||||
|
||||
/sys/power/image_size controls the size of the image created by
|
||||
the suspend-to-disk mechanism. It can be written a string
|
||||
representing a non-negative integer that will be used as an upper
|
||||
limit of the image size, in megabytes. The suspend-to-disk mechanism will
|
||||
do its best to ensure the image size will not exceed that number. However,
|
||||
if this turns out to be impossible, it will try to suspend anyway using the
|
||||
smallest image possible. In particular, if "0" is written to this file, the
|
||||
suspend image will be as small as possible.
|
||||
|
||||
Reading from this file will display the current image size limit, which
|
||||
is set to 500 MB by default.
|
||||
|
@ -27,6 +27,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
|
||||
|
||||
echo platform > /sys/power/disk; echo disk > /sys/power/state
|
||||
|
||||
If you want to limit the suspend image size to N megabytes, do
|
||||
|
||||
echo N > /sys/power/image_size
|
||||
|
||||
before suspend (it is limited to 500 MB by default).
|
||||
|
||||
Encrypted suspend image:
|
||||
------------------------
|
||||
|
@ -115,7 +115,7 @@ Current PPC64 Linux EEH Implementation
|
||||
At this time, a generic EEH recovery mechanism has been implemented,
|
||||
so that individual device drivers do not need to be modified to support
|
||||
EEH recovery. This generic mechanism piggy-backs on the PCI hotplug
|
||||
infrastructure, and percolates events up through the hotplug/udev
|
||||
infrastructure, and percolates events up through the userspace/udev
|
||||
infrastructure. Followiing is a detailed description of how this is
|
||||
accomplished.
|
||||
|
||||
@ -172,7 +172,7 @@ A handler for the EEH notifier_block events is implemented in
|
||||
drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
|
||||
It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
|
||||
This last call causes the device driver for the card to be stopped,
|
||||
which causes hotplug events to go out to user space. This triggers
|
||||
which causes uevents to go out to user space. This triggers
|
||||
user-space scripts that might issue commands such as "ifdown eth0"
|
||||
for ethernet cards, and so on. This handler then sleeps for 5 seconds,
|
||||
hoping to give the user-space scripts enough time to complete.
|
||||
@ -258,29 +258,30 @@ rpa_php_unconfig_pci_adapter() { // in rpaphp_pci.c
|
||||
calls
|
||||
pci_destroy_dev (struct pci_dev *) {
|
||||
calls
|
||||
device_unregister (&dev->dev) { // in /drivers/base/core.c
|
||||
device_unregister (&dev->dev) { // in /drivers/base/core.c
|
||||
calls
|
||||
device_del(struct device * dev) { // in /drivers/base/core.c
|
||||
device_del(struct device * dev) { // in /drivers/base/core.c
|
||||
calls
|
||||
kobject_del() { //in /libs/kobject.c
|
||||
kobject_del() { //in /libs/kobject.c
|
||||
calls
|
||||
kobject_hotplug() { // in /libs/kobject.c
|
||||
kobject_uevent() { // in /libs/kobject.c
|
||||
calls
|
||||
kset_hotplug() { // in /lib/kobject.c
|
||||
kset_uevent() { // in /lib/kobject.c
|
||||
calls
|
||||
kset->hotplug_ops->hotplug() which is really just
|
||||
kset->uevent_ops->uevent() // which is really just
|
||||
a call to
|
||||
dev_hotplug() { // in /drivers/base/core.c
|
||||
dev_uevent() { // in /drivers/base/core.c
|
||||
calls
|
||||
dev->bus->hotplug() which is really just a call to
|
||||
pci_hotplug () { // in drivers/pci/hotplug.c
|
||||
dev->bus->uevent() which is really just a call to
|
||||
pci_uevent () { // in drivers/pci/hotplug.c
|
||||
which prints device name, etc....
|
||||
}
|
||||
}
|
||||
then kset_hotplug() calls
|
||||
call_usermodehelper () with
|
||||
argv[0]=hotplug_path[] which is "/sbin/hotplug"
|
||||
--> event to userspace,
|
||||
then kobject_uevent() sends a netlink uevent to userspace
|
||||
--> userspace uevent
|
||||
(during early boot, nobody listens to netlink events and
|
||||
kobject_uevent() executes uevent_helper[], which runs the
|
||||
event process /sbin/hotplug)
|
||||
}
|
||||
}
|
||||
kobject_del() then calls sysfs_remove_dir(), which would
|
||||
|
@ -1,3 +1,38 @@
|
||||
Release Date : Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
|
||||
|
||||
1. Sorted out PCI IDs to remove megaraid support overlaps.
|
||||
Based on the patch from Daniel, sorted out PCI IDs along with
|
||||
charactor node name change from 'megadev' to 'megadev_legacy' to avoid
|
||||
conflict.
|
||||
---
|
||||
Hopefully we'll be getting the build restriction zapped much sooner,
|
||||
but we should also be thinking about totally removing the hardware
|
||||
support overlap in the megaraid drivers.
|
||||
|
||||
This patch pencils in a date of Feb 06 for this, and performs some
|
||||
printk abuse in hope that existing legacy users might pick up on what's
|
||||
going on.
|
||||
|
||||
Signed-off-by: Daniel Drake <dsd@gentoo.org>
|
||||
---
|
||||
|
||||
2. Fixed a issue: megaraid always fails to reset handler.
|
||||
---
|
||||
I found that the megaraid driver always fails to reset the
|
||||
adapter with the following message:
|
||||
megaraid: resetting the host...
|
||||
megaraid mbox: reset sequence completed successfully
|
||||
megaraid: fast sync command timed out
|
||||
megaraid: reservation reset failed
|
||||
when the "Cluster mode" of the adapter BIOS is enabled.
|
||||
So, whenever the reset occurs, the adapter goes to
|
||||
offline and just become unavailable.
|
||||
|
||||
Jun'ichi Nomura [mailto:jnomura@mtc.biglobe.ne.jp]
|
||||
---
|
||||
|
||||
Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
|
||||
|
@ -150,7 +150,8 @@ scsi devices of which only the first 2 respond:
|
||||
LLD mid level LLD
|
||||
===-------------------=========--------------------===------
|
||||
scsi_host_alloc() -->
|
||||
scsi_add_host() --------+
|
||||
scsi_add_host() ---->
|
||||
scsi_scan_host() -------+
|
||||
|
|
||||
slave_alloc()
|
||||
slave_configure() --> scsi_adjust_queue_depth()
|
||||
@ -196,7 +197,7 @@ of the issues involved. See the section on reference counting below.
|
||||
|
||||
|
||||
The hotplug concept may be extended to SCSI devices. Currently, when an
|
||||
HBA is added, the scsi_add_host() function causes a scan for SCSI devices
|
||||
HBA is added, the scsi_scan_host() function causes a scan for SCSI devices
|
||||
attached to the HBA's SCSI transport. On newer SCSI transports the HBA
|
||||
may become aware of a new SCSI device _after_ the scan has completed.
|
||||
An LLD can use this sequence to make the mid level aware of a SCSI device:
|
||||
@ -372,7 +373,7 @@ names all start with "scsi_".
|
||||
Summary:
|
||||
scsi_activate_tcq - turn on tag command queueing
|
||||
scsi_add_device - creates new scsi device (lu) instance
|
||||
scsi_add_host - perform sysfs registration and SCSI bus scan.
|
||||
scsi_add_host - perform sysfs registration and set up transport class
|
||||
scsi_adjust_queue_depth - change the queue depth on a SCSI device
|
||||
scsi_assign_lock - replace default host_lock with given lock
|
||||
scsi_bios_ptable - return copy of block device's partition table
|
||||
@ -386,6 +387,7 @@ Summary:
|
||||
scsi_remove_device - detach and remove a SCSI device
|
||||
scsi_remove_host - detach and remove all SCSI devices owned by host
|
||||
scsi_report_bus_reset - report scsi _bus_ reset observed
|
||||
scsi_scan_host - scan SCSI bus
|
||||
scsi_track_queue_full - track successive QUEUE_FULL events
|
||||
scsi_unblock_requests - allow further commands to be queued to given host
|
||||
scsi_unregister - [calls scsi_host_put()]
|
||||
@ -425,10 +427,10 @@ void scsi_activate_tcq(struct scsi_device *sdev, int depth)
|
||||
* Might block: yes
|
||||
*
|
||||
* Notes: This call is usually performed internally during a scsi
|
||||
* bus scan when an HBA is added (i.e. scsi_add_host()). So it
|
||||
* bus scan when an HBA is added (i.e. scsi_scan_host()). So it
|
||||
* should only be called if the HBA becomes aware of a new scsi
|
||||
* device (lu) after scsi_add_host() has completed. If successful
|
||||
* this call we lead to slave_alloc() and slave_configure() callbacks
|
||||
* device (lu) after scsi_scan_host() has completed. If successful
|
||||
* this call can lead to slave_alloc() and slave_configure() callbacks
|
||||
* into the LLD.
|
||||
*
|
||||
* Defined in: drivers/scsi/scsi_scan.c
|
||||
@ -439,7 +441,7 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
|
||||
|
||||
|
||||
/**
|
||||
* scsi_add_host - perform sysfs registration and SCSI bus scan.
|
||||
* scsi_add_host - perform sysfs registration and set up transport class
|
||||
* @shost: pointer to scsi host instance
|
||||
* @dev: pointer to struct device of type scsi class
|
||||
*
|
||||
@ -448,7 +450,11 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
|
||||
* Might block: no
|
||||
*
|
||||
* Notes: Only required in "hotplug initialization model" after a
|
||||
* successful call to scsi_host_alloc().
|
||||
* successful call to scsi_host_alloc(). This function does not
|
||||
* scan the bus; this can be done by calling scsi_scan_host() or
|
||||
* in some other transport-specific way. The LLD must set up
|
||||
* the transport template before calling this function and may only
|
||||
* access the transport class data after this function has been called.
|
||||
*
|
||||
* Defined in: drivers/scsi/hosts.c
|
||||
**/
|
||||
@ -559,7 +565,7 @@ void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
|
||||
* area for the LLD's exclusive use.
|
||||
* Both associated refcounting objects have their refcount set to 1.
|
||||
* Full registration (in sysfs) and a bus scan are performed later when
|
||||
* scsi_add_host() is called.
|
||||
* scsi_add_host() and scsi_scan_host() are called.
|
||||
*
|
||||
* Defined in: drivers/scsi/hosts.c .
|
||||
**/
|
||||
@ -698,6 +704,19 @@ int scsi_remove_host(struct Scsi_Host *shost)
|
||||
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_scan_host - scan SCSI bus
|
||||
* @shost: a pointer to a scsi host instance
|
||||
*
|
||||
* Might block: yes
|
||||
*
|
||||
* Notes: Should be called after scsi_add_host()
|
||||
*
|
||||
* Defined in: drivers/scsi/scsi_scan.c
|
||||
**/
|
||||
void scsi_scan_host(struct Scsi_Host *shost)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_track_queue_full - track successive QUEUE_FULL events on given
|
||||
* device to determine if and when there is a need
|
||||
@ -1433,7 +1452,7 @@ The following people have contributed to this document:
|
||||
Christoph Hellwig <hch at infradead dot org>
|
||||
Doug Ledford <dledford at redhat dot com>
|
||||
Andries Brouwer <Andries dot Brouwer at cwi dot nl>
|
||||
Randy Dunlap <rddunlap at osdl dot org>
|
||||
Randy Dunlap <rdunlap at xenotime dot net>
|
||||
Alan Stern <stern at rowland dot harvard dot edu>
|
||||
|
||||
|
||||
|
@ -105,7 +105,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Each of top level sound card module takes the following options.
|
||||
|
||||
index - index (slot #) of sound card
|
||||
- Values: 0 through 7 or negative
|
||||
- Values: 0 through 31 or negative
|
||||
- If nonnegative, assign that index number
|
||||
- if negative, interpret as a bitmask of permissible
|
||||
indices; the first free permitted index is assigned
|
||||
@ -134,7 +134,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma2 - second DMA # for AD1816A chip (PnP setup)
|
||||
clockfreq - Clock frequency for AD1816A chip (default = 0, 33000Hz)
|
||||
|
||||
Module supports up to 8 cards, autoprobe and PnP.
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
Module snd-ad1848
|
||||
-----------------
|
||||
@ -145,9 +145,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
irq - IRQ # for AD1848 chip
|
||||
dma1 - DMA # for AD1848 chip (0,1,3)
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. It does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-ad1889
|
||||
-----------------
|
||||
|
||||
@ -156,7 +158,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
ac97_quirk - AC'97 workaround for strange hardware
|
||||
See the description of intel8x0 module for details.
|
||||
|
||||
This module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-ali5451
|
||||
------------------
|
||||
@ -184,7 +186,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
mpu_irq - IRQ # for MPU-401 (PnP setup)
|
||||
fm_port - port # for OPL3 FM (PnP setup)
|
||||
|
||||
Module supports up to 8 cards, autoprobe and PnP.
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-als4000
|
||||
------------------
|
||||
@ -194,7 +198,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
joystick_port - port # for legacy joystick support.
|
||||
0 = disabled (default), 1 = auto-detect
|
||||
|
||||
Module supports up to 8 cards, autoprobe and PnP.
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-atiixp
|
||||
-----------------
|
||||
@ -213,6 +219,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
implementation depends on the motherboard, and you'll need to
|
||||
choose the correct one via spdif_aclink module option.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-atiixp-modem
|
||||
-----------------------
|
||||
|
||||
@ -223,6 +231,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-au8810, snd-au8820, snd-au8830
|
||||
-----------------------------------------
|
||||
|
||||
@ -263,8 +273,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma1 - 1st DMA # for AZT2320 (WSS) chip (PnP setup)
|
||||
dma2 - 2nd DMA # for AZT2320 (WSS) chip (PnP setup)
|
||||
|
||||
Module supports up to 8 cards, PnP and autoprobe.
|
||||
This module supports multiple cards, PnP and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-azt3328
|
||||
------------------
|
||||
|
||||
@ -272,7 +284,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
joystick - Enable joystick (default off)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-bt87x
|
||||
----------------
|
||||
@ -282,7 +294,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
digital_rate - Override the default digital rate (Hz)
|
||||
load_all - Load the driver even if the card model isn't known
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
@ -292,7 +304,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Module for Creative Audigy LS and SB Live 24bit
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
|
||||
Module snd-cmi8330
|
||||
@ -308,7 +320,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
sbdma8 - 8bit DMA # for CMI8330 chip (SB16)
|
||||
sbdma16 - 16bit DMA # for CMI8330 chip (SB16)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-cmipci
|
||||
-----------------
|
||||
@ -321,8 +335,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
(default = 1)
|
||||
joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
|
||||
|
||||
Module supports autoprobe and multiple chips (max 8).
|
||||
This module supports autoprobe and multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-cs4231
|
||||
-----------------
|
||||
|
||||
@ -335,7 +351,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma1 - first DMA # for CS4231 chip
|
||||
dma2 - second DMA # for CS4231 chip
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
|
||||
The power-management is supported.
|
||||
@ -355,7 +371,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma2 - second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
|
||||
The power-management is supported.
|
||||
@ -376,7 +392,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma2 - second DMA # for CS4236 chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
(if ISA PnP is not used) thus main port and control port must be
|
||||
specified!!! Other ports are optional.
|
||||
|
||||
@ -389,7 +405,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
dual_codec - Secondary codec ID (0 = disable, default)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
@ -403,13 +419,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
thinkpad - Force to enable Thinkpad's CLKRUN control.
|
||||
mmap_valid - Support OSS mmap mode (default = 0).
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
Usually external amp and CLKRUN controls are detected automatically
|
||||
from PCI sub vendor/device ids. If they don't work, give the options
|
||||
above explicitly.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-cs5535audio
|
||||
----------------------
|
||||
|
||||
Module for multifunction CS5535 companion PCI device
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-dt019x
|
||||
-----------------
|
||||
|
||||
@ -423,9 +446,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
mpu_irq - IRQ # for MPU-401 (PnP setup)
|
||||
dma8 - DMA # (PnP setup)
|
||||
|
||||
Module supports up to 8 cards. This module is enabled only with
|
||||
This module supports multiple cards. This module is enabled only with
|
||||
ISA PnP support.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-dummy
|
||||
----------------
|
||||
|
||||
@ -433,6 +458,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
or input, but you may use this module for any application which
|
||||
requires a sound card (like RealPlayer).
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-emu10k1
|
||||
------------------
|
||||
|
||||
@ -450,7 +477,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
given in MB unit. Default value is 128.
|
||||
enable_ir - enable IR
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Input & Output configurations [extin/extout]
|
||||
* Creative Card wo/Digital out [0x0003/0x1f03]
|
||||
@ -466,12 +493,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
* Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff]
|
||||
* Creative Card all ins and outs [0x3fff/0x7fff]
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-emu10k1x
|
||||
-------------------
|
||||
|
||||
Module for Creative Emu10k1X (SB Live Dell OEM version)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-ens1370
|
||||
------------------
|
||||
@ -482,7 +511,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
joystick - Enable joystick (default off)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-ens1371
|
||||
------------------
|
||||
@ -495,7 +524,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
joystick_port - port # for joystick (0x200,0x208,0x210,0x218),
|
||||
0 = disable (default), 1 = auto-detect
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-es968
|
||||
----------------
|
||||
@ -506,8 +535,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
irq - IRQ # for ES968 (SB8) chip (PnP setup)
|
||||
dma1 - DMA # for ES968 (SB8) chip (PnP setup)
|
||||
|
||||
Module supports up to 8 cards, PnP and autoprobe.
|
||||
This module supports multiple cards, PnP and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-es1688
|
||||
-----------------
|
||||
|
||||
@ -519,7 +550,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
mpu_irq - IRQ # for MPU-401 port (5,7,9,10)
|
||||
dma8 - DMA # for ES-1688 chip (0,1,3)
|
||||
|
||||
Module supports up to 8 cards and autoprobe (without MPU-401 port).
|
||||
This module supports multiple cards and autoprobe (without MPU-401 port).
|
||||
|
||||
Module snd-es18xx
|
||||
-----------------
|
||||
@ -534,8 +565,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma2 - first DMA # for ES-18xx chip (0,1,3)
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards ISA PnP and autoprobe (without MPU-401 port
|
||||
if native ISA PnP routines are not used).
|
||||
This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
|
||||
port if native ISA PnP routines are not used).
|
||||
When dma2 is equal with dma1, the driver works as half-duplex.
|
||||
|
||||
The power-management is supported.
|
||||
@ -545,7 +576,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-es1968
|
||||
-----------------
|
||||
@ -561,7 +594,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
enable_mpu - enable MPU401 (0 = off, 1 = on, 2 = auto (default))
|
||||
joystick - enable joystick (default off)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
@ -577,8 +610,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
- High 16-bits are video (radio) device number + 1
|
||||
- example: 0x10002 (MediaForte 256-PCPR, device 1)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-gusclassic
|
||||
---------------------
|
||||
|
||||
@ -592,7 +627,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
voices - GF1 voices limit (14-32)
|
||||
pcm_voices - reserved PCM voices
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-gusextreme
|
||||
---------------------
|
||||
@ -611,7 +646,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
voices - GF1 voices limit (14-32)
|
||||
pcm_voices - reserved PCM voices
|
||||
|
||||
Module supports up to 8 cards and autoprobe (without MPU-401 port).
|
||||
This module supports multiple cards and autoprobe (without MPU-401 port).
|
||||
|
||||
Module snd-gusmax
|
||||
-----------------
|
||||
@ -626,7 +661,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
voices - GF1 voices limit (14-32)
|
||||
pcm_voices - reserved PCM voices
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-hda-intel
|
||||
--------------------
|
||||
@ -688,12 +723,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
(Usually SD_LPLIB register is more accurate than the
|
||||
position buffer.)
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-hdsp
|
||||
---------------
|
||||
|
||||
Module for RME Hammerfall DSP audio interface(s)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Note: The firmware data can be automatically loaded via hotplug
|
||||
when CONFIG_FW_LOADER is set. Otherwise, you need to load
|
||||
@ -751,7 +788,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
|
||||
in msec resolution, default value is 500 (0.5 sec)
|
||||
|
||||
Module supports up to 8 cards and autoprobe. Note: The consumer part
|
||||
This module supports multiple cards and autoprobe. Note: The consumer part
|
||||
is not used with all Envy24 based cards (for example in the MidiMan Delta
|
||||
serie).
|
||||
|
||||
@ -787,7 +824,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
aureon71, universe, k8x800, phase22, phase28, ms300,
|
||||
av710
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Note: The supported board is detected by reading EEPROM or PCI
|
||||
SSID (if EEPROM isn't available). You can override the
|
||||
@ -839,6 +876,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-interwave
|
||||
--------------------
|
||||
|
||||
@ -855,7 +894,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
effect - 1 = InterWave effects enable (default 0);
|
||||
requires 8 voices
|
||||
|
||||
Module supports up to 8 cards, autoprobe and ISA PnP.
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
Module snd-interwave-stb
|
||||
------------------------
|
||||
@ -875,14 +914,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
effect - 1 = InterWave effects enable (default 0);
|
||||
requires 8 voices
|
||||
|
||||
Module supports up to 8 cards, autoprobe and ISA PnP.
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
Module snd-korg1212
|
||||
-------------------
|
||||
|
||||
Module for Korg 1212 IO PCI card
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-maestro3
|
||||
-------------------
|
||||
@ -894,7 +933,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
-1 for default pin (8 for allegro, 1 for
|
||||
others)
|
||||
|
||||
Module supports autoprobe and multiple chips (max 8).
|
||||
This module supports autoprobe and multiple chips.
|
||||
|
||||
Note: the binding of amplifier is dependent on hardware.
|
||||
If there is no sound even though all channels are unmuted, try to
|
||||
@ -909,7 +948,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Module for Digigram miXart8 sound cards.
|
||||
|
||||
Module supports multiple cards.
|
||||
This module supports multiple cards.
|
||||
Note: One miXart8 board will be represented as 4 alsa cards.
|
||||
See MIXART.txt for details.
|
||||
|
||||
@ -928,7 +967,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
irq - IRQ number or -1 (disable)
|
||||
pnp - PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports multiple devices (max 8) and PnP.
|
||||
This module supports multiple devices and PnP.
|
||||
|
||||
Module snd-mtpav
|
||||
----------------
|
||||
@ -1014,7 +1053,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma2 - second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards and ISA PnP. This module does not support
|
||||
This module supports multiple cards and ISA PnP. It does not support
|
||||
autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
|
||||
|
||||
The power-management is supported.
|
||||
@ -1064,6 +1103,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
This module supports only one card, autoprobe and PnP.
|
||||
|
||||
Module snd-pcxhr
|
||||
----------------
|
||||
|
||||
Module for Digigram PCXHR boards
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-powermac (on ppc only)
|
||||
---------------------------------
|
||||
|
||||
@ -1084,20 +1130,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
For ARM architecture only.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-rme32
|
||||
----------------
|
||||
|
||||
Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32,
|
||||
Prodif96 and Prodif Gold) sound cards.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-rme96
|
||||
----------------
|
||||
|
||||
Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-rme9652
|
||||
------------------
|
||||
@ -1107,7 +1155,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
precise_ptr - Enable precise pointer (doesn't work reliably).
|
||||
(default = 0)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Note: snd-page-alloc module does the job which snd-hammerfall-mem
|
||||
module did formerly. It will allocate the buffers in advance
|
||||
@ -1124,6 +1172,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Module supports only one card.
|
||||
Module has no enable and index options.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sb8
|
||||
--------------
|
||||
|
||||
@ -1135,8 +1185,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
irq - IRQ # for SB DSP chip (5,7,9,10)
|
||||
dma8 - DMA # for SB DSP chip (1,3)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sb16 and snd-sbawe
|
||||
-----------------------------
|
||||
|
||||
@ -1155,7 +1207,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
csp - ASP/CSP chip support - 0 = disable (default), 1 = enable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards, autoprobe and ISA PnP.
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
Note: To use Vibra16X cards in 16-bit half duplex mode, you must
|
||||
disable 16bit DMA with dma16 = -1 module parameter.
|
||||
@ -1163,6 +1215,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
half duplex mode through 8-bit DMA channel by disabling their
|
||||
16-bit DMA channel.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sgalaxy
|
||||
------------------
|
||||
|
||||
@ -1173,7 +1227,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
irq - IRQ # (7,9,10,11)
|
||||
dma1 - DMA #
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sscape
|
||||
-----------------
|
||||
@ -1185,7 +1241,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
mpu_irq - MPU-401 IRQ # (PnP setup)
|
||||
dma - DMA # (PnP setup)
|
||||
|
||||
Module supports up to 8 cards. ISA PnP must be enabled.
|
||||
This module supports multiple cards. ISA PnP must be enabled.
|
||||
You need sscape_ctl tool in alsa-tools package for loading
|
||||
the microcode.
|
||||
|
||||
@ -1194,21 +1250,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Module for AMD7930 sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-sun-cs4231 (on sparc only)
|
||||
-------------------------------------
|
||||
|
||||
Module for CS4231 sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-sun-dbri (on sparc only)
|
||||
-----------------------------------
|
||||
|
||||
Module for DBRI sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-wavefront
|
||||
--------------------
|
||||
@ -1228,7 +1284,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
dma2 - DMA2 # for CS4232 PCM interface.
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards and ISA PnP.
|
||||
This module supports multiple cards and ISA PnP.
|
||||
|
||||
Module snd-sonicvibes
|
||||
---------------------
|
||||
@ -1240,7 +1296,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
- SoundCard must have onboard SRAM for this.
|
||||
mge - Mic Gain Enable - 1 = enable, 0 = disable (default)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-serial-u16550
|
||||
------------------------
|
||||
@ -1259,7 +1315,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
|
||||
3 = MS-124W M/B, 4 = Generic
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus the main port must be specified!!! Other options are optional.
|
||||
|
||||
Module snd-trident
|
||||
@ -1278,7 +1334,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
pcm_channels - max channels (voices) reserved for PCM
|
||||
wavetable_size - max wavetable size in kB (4-?kb)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
@ -1290,14 +1346,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
vid - Vendor ID for the device (optional)
|
||||
pid - Product ID for the device (optional)
|
||||
|
||||
This module supports up to 8 cards, autoprobe and hotplugging.
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
Module snd-usb-usx2y
|
||||
--------------------
|
||||
|
||||
Module for Tascam USB US-122, US-224 and US-428 devices.
|
||||
|
||||
This module supports up to 8 cards, autoprobe and hotplugging.
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
Note: you need to load the firmware via usx2yloader utility included
|
||||
in alsa-tools and alsa-firmware packages.
|
||||
@ -1356,6 +1412,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
|
||||
additionally. The mpu_port option is for VIA686 chips only.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-via82xx-modem
|
||||
------------------------
|
||||
|
||||
@ -1368,6 +1426,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-virmidi
|
||||
------------------
|
||||
|
||||
@ -1375,9 +1435,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
This module creates virtual rawmidi devices which communicate
|
||||
to the corresponding ALSA sequencer ports.
|
||||
|
||||
midi_devs - MIDI devices # (1-8, default=4)
|
||||
midi_devs - MIDI devices # (1-4, default=4)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-vx222
|
||||
----------------
|
||||
@ -1387,7 +1447,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
mic - Enable Microphone on V222 Mic (NYI)
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
When the driver is compiled as a module and the hotplug firmware
|
||||
is supported, the firmware data is loaded via hotplug automatically.
|
||||
@ -1406,6 +1466,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
size is chosen. The possible IBL values can be found in
|
||||
/proc/asound/cardX/vx-status proc file.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-vxpocket
|
||||
-------------------
|
||||
|
||||
@ -1413,7 +1475,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards. The module is compiled only when
|
||||
This module supports multiple cards. The module is compiled only when
|
||||
PCMCIA is supported on kernel.
|
||||
|
||||
With the older 2.6.x kernel, to activate the driver via the card
|
||||
@ -1434,6 +1496,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
|
||||
ALSA 1.0.10.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-ymfpci
|
||||
-----------------
|
||||
|
||||
@ -1447,7 +1511,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
1 (auto-detect)
|
||||
rear_switch - enable shared rear/line-in switch (bool)
|
||||
|
||||
Module supports autoprobe and multiple chips (max 8).
|
||||
This module supports autoprobe and multiple chips.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
@ -1458,6 +1522,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
||||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
||||
AC97 Quirk Option
|
||||
=================
|
||||
@ -1474,7 +1540,7 @@ the proper value with this option.
|
||||
|
||||
The following strings are accepted:
|
||||
- default Don't override the default setting
|
||||
- disable Disable the quirk
|
||||
- none Disable the quirk
|
||||
- hp_only Bind Master and Headphone controls as a single control
|
||||
- swap_hp Swap headphone and master controls
|
||||
- swap_surround Swap master and surround controls
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -138,6 +138,22 @@ card*/codec97#0/ac97#?-?+regs
|
||||
# echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs
|
||||
|
||||
|
||||
USB Audio Streams
|
||||
-----------------
|
||||
|
||||
card*/stream*
|
||||
Shows the assignment and the current status of each audio stream
|
||||
of the given card. This information is very useful for debugging.
|
||||
|
||||
|
||||
HD-Audio Codecs
|
||||
---------------
|
||||
|
||||
card*/codec#*
|
||||
Shows the general codec information and the attribute of each
|
||||
widget node.
|
||||
|
||||
|
||||
Sequencer Information
|
||||
---------------------
|
||||
|
||||
|
@ -63,7 +63,7 @@ The bus instance is created via snd_hda_bus_new(). You need to pass
|
||||
the card instance, the template, and the pointer to store the
|
||||
resultant bus instance.
|
||||
|
||||
int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
|
||||
int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
|
||||
struct hda_bus **busp);
|
||||
|
||||
It returns zero if successful. A negative return value means any
|
||||
@ -166,14 +166,14 @@ The ops field contains the following callback functions:
|
||||
|
||||
struct hda_pcm_ops {
|
||||
int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
unsigned int stream_tag, unsigned int format,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
};
|
||||
|
||||
All are non-NULL, so you can call them safely without NULL check.
|
||||
@ -284,7 +284,7 @@ parameter, and PCI subsystem IDs. If the matching entry is found, it
|
||||
returns the config field value.
|
||||
|
||||
snd_hda_add_new_ctls() can be used to create and add control entries.
|
||||
Pass the zero-terminated array of snd_kcontrol_new_t. The same array
|
||||
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
||||
can be passed to snd_hda_resume_ctls() for resume.
|
||||
Note that this will call control->put callback of these entries. So,
|
||||
put callback should check codec->in_resume and force to restore the
|
||||
@ -292,7 +292,7 @@ given value if it's non-zero even if the value is identical with the
|
||||
cached value.
|
||||
|
||||
Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be
|
||||
used for the entry of snd_kcontrol_new_t.
|
||||
used for the entry of struct snd_kcontrol_new.
|
||||
|
||||
The input MUX helper callbacks for such a control are provided, too:
|
||||
snd_hda_input_mux_info() and snd_hda_input_mux_put(). See
|
||||
|
@ -202,17 +202,13 @@ you must call __handle_sysrq_nolock instead.
|
||||
|
||||
* I have more questions, who can I ask?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
You may feel free to send email to myrdraal@deathsdoor.com, and I will
|
||||
respond as soon as possible.
|
||||
-Myrdraal
|
||||
|
||||
And I'll answer any questions about the registration system you got, also
|
||||
responding as soon as possible.
|
||||
-Crutcher
|
||||
|
||||
* Credits
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Written by Mydraal <myrdraal@deathsdoor.com>
|
||||
Written by Mydraal <vulpyne@vulpyne.net>
|
||||
Updated by Adam Sulmicki <adam@cfar.umd.edu>
|
||||
Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
|
||||
Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
|
||||
|
73
MAINTAINERS
73
MAINTAINERS
@ -258,6 +258,13 @@ P: Ivan Kokshaysky
|
||||
M: ink@jurassic.park.msu.ru
|
||||
S: Maintained for 2.4; PCI support for 2.6.
|
||||
|
||||
AMD GEODE PROCESSOR/CHIPSET SUPPORT
|
||||
P: Jordan Crouse
|
||||
M: info-linux@geode.amd.com
|
||||
L: info-linux@geode.amd.com
|
||||
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
|
||||
S: Supported
|
||||
|
||||
APM DRIVER
|
||||
P: Stephen Rothwell
|
||||
M: sfr@canb.auug.org.au
|
||||
@ -536,7 +543,7 @@ P: Mauro Carvalho Chehab
|
||||
M: mchehab@brturbo.com.br
|
||||
L: video4linux-list@redhat.com
|
||||
W: http://linuxtv.org
|
||||
T: quilt http://www.linuxtv.org/download/quilt/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
|
||||
S: Maintained
|
||||
|
||||
BUSLOGIC SCSI DRIVER
|
||||
@ -554,6 +561,11 @@ W: http://us1.samba.org/samba/Linux_CIFS_client.html
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
|
||||
S: Supported
|
||||
|
||||
CONFIGFS
|
||||
P: Joel Becker
|
||||
M: Joel Becker <joel.becker@oracle.com>
|
||||
S: Supported
|
||||
|
||||
CIRRUS LOGIC GENERIC FBDEV DRIVER
|
||||
P: Jeff Garzik
|
||||
M: jgarzik@pobox.com
|
||||
@ -650,6 +662,11 @@ L: linux-crypto@vger.kernel.org
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
|
||||
S: Maintained
|
||||
|
||||
CS5535 Audio ALSA driver
|
||||
P: Jaya Kumar
|
||||
M: jayakumar.alsa@gmail.com
|
||||
S: Maintained
|
||||
|
||||
CYBERPRO FB DRIVER
|
||||
P: Russell King
|
||||
M: rmk@arm.linux.org.uk
|
||||
@ -679,13 +696,6 @@ M: pc300@cyclades.com
|
||||
W: http://www.cyclades.com/
|
||||
S: Supported
|
||||
|
||||
DAC960 RAID CONTROLLER DRIVER
|
||||
P: Dave Olien
|
||||
M dmo@osdl.org
|
||||
W: http://www.osdl.org/archive/dmo/DAC960
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
DAMA SLAVE for AX.25
|
||||
P: Joerg Reuter
|
||||
M: jreuter@yaina.de
|
||||
@ -834,7 +844,7 @@ P: LinuxTV.org Project
|
||||
M: linux-dvb-maintainer@linuxtv.org
|
||||
L: linux-dvb@linuxtv.org (subscription required)
|
||||
W: http://linuxtv.org/
|
||||
T: quilt http://www.linuxtv.org/download/quilt/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
|
||||
S: Supported
|
||||
|
||||
EATA-DMA SCSI DRIVER
|
||||
@ -1225,7 +1235,7 @@ IEEE 1394 SUBSYSTEM
|
||||
P: Ben Collins
|
||||
M: bcollins@debian.org
|
||||
P: Jody McIntyre
|
||||
M: scjody@steamballoon.com
|
||||
M: scjody@modernduck.com
|
||||
L: linux1394-devel@lists.sourceforge.net
|
||||
W: http://www.linux1394.org/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
|
||||
@ -1235,14 +1245,14 @@ IEEE 1394 OHCI DRIVER
|
||||
P: Ben Collins
|
||||
M: bcollins@debian.org
|
||||
P: Jody McIntyre
|
||||
M: scjody@steamballoon.com
|
||||
M: scjody@modernduck.com
|
||||
L: linux1394-devel@lists.sourceforge.net
|
||||
W: http://www.linux1394.org/
|
||||
S: Maintained
|
||||
|
||||
IEEE 1394 PCILYNX DRIVER
|
||||
P: Jody McIntyre
|
||||
M: scjody@steamballoon.com
|
||||
M: scjody@modernduck.com
|
||||
L: linux1394-devel@lists.sourceforge.net
|
||||
W: http://www.linux1394.org/
|
||||
S: Maintained
|
||||
@ -1284,8 +1294,8 @@ T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
|
||||
S: Supported
|
||||
|
||||
INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
|
||||
P: Vojtech Pavlik
|
||||
M: vojtech@suse.cz
|
||||
P: Dmitry Torokhov
|
||||
M: dtor_core@ameritech.net
|
||||
L: linux-input@atrey.karlin.mff.cuni.cz
|
||||
L: linux-joystick@atrey.karlin.mff.cuni.cz
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
|
||||
@ -1465,7 +1475,6 @@ P: Several
|
||||
L: kernel-janitors@osdl.org
|
||||
W: http://www.kerneljanitors.org/
|
||||
W: http://sf.net/projects/kernel-janitor/
|
||||
W: http://developer.osdl.org/rddunlap/kj-patches/
|
||||
S: Maintained
|
||||
|
||||
KERNEL NFSD
|
||||
@ -1476,17 +1485,11 @@ W: http://nfs.sourceforge.net/
|
||||
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
|
||||
S: Maintained
|
||||
|
||||
KERNEL EVENT LAYER (KOBJECT_UEVENT)
|
||||
P: Robert Love
|
||||
M: rml@novell.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
KEXEC
|
||||
P: Eric Biederman
|
||||
P: Randy Dunlap
|
||||
M: ebiederm@xmission.com
|
||||
M: rddunlap@osdl.org
|
||||
M: rdunlap@xenotime.net
|
||||
W: http://www.xmission.com/~ebiederm/files/kexec/
|
||||
L: linux-kernel@vger.kernel.org
|
||||
L: fastboot@osdl.org
|
||||
@ -1900,6 +1903,15 @@ M: ajoshi@shell.unixbox.com
|
||||
L: linux-nvidia@lists.surfsouth.com
|
||||
S: Maintained
|
||||
|
||||
ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
|
||||
P: Mark Fasheh
|
||||
M: mark.fasheh@oracle.com
|
||||
P: Kurt Hackel
|
||||
M: kurt.hackel@oracle.com
|
||||
L: ocfs2-devel@oss.oracle.com
|
||||
W: http://oss.oracle.com/projects/ocfs2/
|
||||
S: Supported
|
||||
|
||||
OLYMPIC NETWORK DRIVER
|
||||
P: Peter De Shrijver
|
||||
M: p2@ace.ulyssis.student.kuleuven.ac.be
|
||||
@ -2587,7 +2599,6 @@ S: Maintained
|
||||
UDF FILESYSTEM
|
||||
P: Ben Fennema
|
||||
M: bfennema@falcon.csc.calpoly.edu
|
||||
L: linux_udf@hpesjro.fc.hp.com
|
||||
W: http://linux-udf.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
@ -2640,6 +2651,12 @@ L: linux-usb-users@lists.sourceforge.net
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
USB ISP116X DRIVER
|
||||
P: Olav Kongas
|
||||
M: ok@artecdesign.ee
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
USB KAWASAKI LSI DRIVER
|
||||
P: Oliver Neukum
|
||||
M: oliver@neukum.name
|
||||
@ -2651,7 +2668,7 @@ USB MASS STORAGE DRIVER
|
||||
P: Matthew Dharm
|
||||
M: mdharm-usb@one-eyed-alien.net
|
||||
L: linux-usb-users@lists.sourceforge.net
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
L: usb-storage@lists.one-eyed-alien.net
|
||||
S: Maintained
|
||||
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
|
||||
|
||||
@ -2896,7 +2913,13 @@ P: Mauro Carvalho Chehab
|
||||
M: mchehab@brturbo.com.br
|
||||
L: video4linux-list@redhat.com
|
||||
W: http://linuxtv.org
|
||||
T: quilt http://www.linuxtv.org/download/quilt/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git
|
||||
S: Maintained
|
||||
|
||||
VT8231 HARDWARE MONITOR DRIVER
|
||||
P: Roger Lucas
|
||||
M: roger@planbit.co.uk
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
|
||||
W1 DALLAS'S 1-WIRE BUS
|
||||
|
36
Makefile
36
Makefile
@ -1,8 +1,8 @@
|
||||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 15
|
||||
EXTRAVERSION =-rc5
|
||||
NAME=Affluent Albatross
|
||||
EXTRAVERSION =
|
||||
NAME=Sliding Snow Leopard
|
||||
|
||||
# *DOCUMENTATION*
|
||||
# To see a list of typical targets execute "make help"
|
||||
@ -286,10 +286,6 @@ export quiet Q KBUILD_VERBOSE
|
||||
cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
|
||||
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
|
||||
|
||||
# For backward compatibility
|
||||
check_gcc = $(warning check_gcc is deprecated - use cc-option) \
|
||||
$(call cc-option, $(1),$(2))
|
||||
|
||||
# cc-option-yn
|
||||
# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
|
||||
cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
|
||||
@ -408,7 +404,7 @@ outputmakefile:
|
||||
# of make so .config is not included in this case either (for *config).
|
||||
|
||||
no-dot-config-targets := clean mrproper distclean \
|
||||
cscope TAGS tags help %docs check% kernelrelease
|
||||
cscope TAGS tags help %docs check%
|
||||
|
||||
config-targets := 0
|
||||
mixed-targets := 0
|
||||
@ -481,18 +477,20 @@ ifeq ($(dot-config),1)
|
||||
|
||||
# Read in dependencies to all Kconfig* files, make sure to run
|
||||
# oldconfig if changes are detected.
|
||||
-include .config.cmd
|
||||
-include .kconfig.d
|
||||
|
||||
include .config
|
||||
|
||||
# If .config needs to be updated, it will be done via the dependency
|
||||
# that autoconf has on .config.
|
||||
# To avoid any implicit rule to kick in, define an empty command
|
||||
.config: ;
|
||||
.config .kconfig.d: ;
|
||||
|
||||
# If .config is newer than include/linux/autoconf.h, someone tinkered
|
||||
# with it and forgot to run make oldconfig
|
||||
include/linux/autoconf.h: .config
|
||||
# with it and forgot to run make oldconfig.
|
||||
# If kconfig.d is missing then we are probarly in a cleaned tree so
|
||||
# we execute the config step to be sure to catch updated Kconfig files
|
||||
include/linux/autoconf.h: .kconfig.d .config
|
||||
$(Q)mkdir -p include/linux
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
|
||||
else
|
||||
@ -1066,7 +1064,7 @@ help:
|
||||
@echo ' all - Build all targets marked with [*]'
|
||||
@echo '* vmlinux - Build the bare kernel'
|
||||
@echo '* modules - Build all modules'
|
||||
@echo ' modules_install - Install all modules'
|
||||
@echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
|
||||
@echo ' dir/ - Build all files in dir and below'
|
||||
@echo ' dir/file.[ois] - Build specified target only'
|
||||
@echo ' dir/file.ko - Build module including final link'
|
||||
@ -1240,8 +1238,11 @@ cscope: FORCE
|
||||
quiet_cmd_TAGS = MAKE $@
|
||||
define cmd_TAGS
|
||||
rm -f $@; \
|
||||
ETAGSF=`etags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
|
||||
$(all-sources) | xargs etags $$ETAGSF -a
|
||||
ETAGSF=`etags --version | grep -i exuberant >/dev/null && \
|
||||
echo "-I __initdata,__exitdata,__acquires,__releases \
|
||||
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
||||
--extra=+f --c-kinds=+px"`; \
|
||||
$(all-sources) | xargs etags $$ETAGSF -a
|
||||
endef
|
||||
|
||||
TAGS: FORCE
|
||||
@ -1251,8 +1252,11 @@ TAGS: FORCE
|
||||
quiet_cmd_tags = MAKE $@
|
||||
define cmd_tags
|
||||
rm -f $@; \
|
||||
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
|
||||
$(all-sources) | xargs ctags $$CTAGSF -a
|
||||
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && \
|
||||
echo "-I __initdata,__exitdata,__acquires,__releases \
|
||||
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
||||
--extra=+f --c-kinds=+px"`; \
|
||||
$(all-sources) | xargs ctags $$CTAGSF -a
|
||||
endef
|
||||
|
||||
tags: FORCE
|
||||
|
@ -40,6 +40,19 @@ config GENERIC_IOMAP
|
||||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_HARDIRQS
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_IRQ_PROBE
|
||||
bool
|
||||
default y
|
||||
|
||||
config AUTO_IRQ_AFFINITY
|
||||
bool
|
||||
depends on SMP
|
||||
default y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
|
||||
|
@ -175,7 +175,6 @@ EXPORT_SYMBOL(up);
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
EXPORT_SYMBOL(synchronize_irq);
|
||||
EXPORT_SYMBOL(flush_tlb_mm);
|
||||
EXPORT_SYMBOL(flush_tlb_range);
|
||||
EXPORT_SYMBOL(flush_tlb_page);
|
||||
|
@ -32,214 +32,25 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* Controller mappings for all interrupt sources:
|
||||
*/
|
||||
irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
|
||||
[0 ... NR_IRQS-1] = {
|
||||
.handler = &no_irq_type,
|
||||
.lock = SPIN_LOCK_UNLOCKED
|
||||
}
|
||||
};
|
||||
|
||||
static void register_irq_proc(unsigned int irq);
|
||||
|
||||
volatile unsigned long irq_err_count;
|
||||
|
||||
/*
|
||||
* Special irq handlers.
|
||||
*/
|
||||
|
||||
irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic no controller code
|
||||
*/
|
||||
|
||||
static void no_irq_enable_disable(unsigned int irq) { }
|
||||
static unsigned int no_irq_startup(unsigned int irq) { return 0; }
|
||||
|
||||
static void
|
||||
no_irq_ack(unsigned int irq)
|
||||
void ack_bad_irq(unsigned int irq)
|
||||
{
|
||||
irq_err_count++;
|
||||
printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq);
|
||||
}
|
||||
|
||||
struct hw_interrupt_type no_irq_type = {
|
||||
.typename = "none",
|
||||
.startup = no_irq_startup,
|
||||
.shutdown = no_irq_enable_disable,
|
||||
.enable = no_irq_enable_disable,
|
||||
.disable = no_irq_enable_disable,
|
||||
.ack = no_irq_ack,
|
||||
.end = no_irq_enable_disable,
|
||||
};
|
||||
|
||||
int
|
||||
handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
|
||||
struct irqaction *action)
|
||||
{
|
||||
int status = 1; /* Force the "do bottom halves" bit */
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if (!(action->flags & SA_INTERRUPT))
|
||||
local_irq_enable();
|
||||
else
|
||||
local_irq_disable();
|
||||
|
||||
ret = action->handler(irq, action->dev_id, regs);
|
||||
if (ret == IRQ_HANDLED)
|
||||
status |= action->flags;
|
||||
action = action->next;
|
||||
} while (action);
|
||||
if (status & SA_SAMPLE_RANDOM)
|
||||
add_interrupt_randomness(irq);
|
||||
local_irq_disable();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic enable/disable code: this just calls
|
||||
* down into the PIC-specific version for the actual
|
||||
* hardware disable after having gotten the irq
|
||||
* controller lock.
|
||||
*/
|
||||
void inline
|
||||
disable_irq_nosync(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
if (!desc->depth++) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->handler->disable(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronous version of the above, making sure the IRQ is
|
||||
* no longer running on any other IRQ..
|
||||
*/
|
||||
void
|
||||
disable_irq(unsigned int irq)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
synchronize_irq(irq);
|
||||
}
|
||||
|
||||
void
|
||||
enable_irq(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
switch (desc->depth) {
|
||||
case 1: {
|
||||
unsigned int status = desc->status & ~IRQ_DISABLED;
|
||||
desc->status = status;
|
||||
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
|
||||
desc->status = status | IRQ_REPLAY;
|
||||
hw_resend_irq(desc->handler,irq);
|
||||
}
|
||||
desc->handler->enable(irq);
|
||||
/* fall-through */
|
||||
}
|
||||
default:
|
||||
desc->depth--;
|
||||
break;
|
||||
case 0:
|
||||
printk(KERN_ERR "enable_irq() unbalanced from %p\n",
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
int
|
||||
setup_irq(unsigned int irq, struct irqaction * new)
|
||||
{
|
||||
int shared = 0;
|
||||
struct irqaction *old, **p;
|
||||
unsigned long flags;
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
|
||||
if (desc->handler == &no_irq_type)
|
||||
return -ENOSYS;
|
||||
|
||||
/*
|
||||
* Some drivers like serial.c use request_irq() heavily,
|
||||
* so we have to be careful not to interfere with a
|
||||
* running system.
|
||||
*/
|
||||
if (new->flags & SA_SAMPLE_RANDOM) {
|
||||
/*
|
||||
* This function might sleep, we want to call it first,
|
||||
* outside of the atomic block.
|
||||
* Yes, this might clear the entropy pool if the wrong
|
||||
* driver is attempted to be loaded, without actually
|
||||
* installing a new handler, but is this really a problem,
|
||||
* only the sysadmin is able to do this.
|
||||
*/
|
||||
rand_initialize_irq(irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following block of code has to be executed atomically
|
||||
*/
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
p = &desc->action;
|
||||
if ((old = *p) != NULL) {
|
||||
/* Can't share interrupts unless both agree to */
|
||||
if (!(old->flags & new->flags & SA_SHIRQ)) {
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* add new interrupt at end of irq queue */
|
||||
do {
|
||||
p = &old->next;
|
||||
old = *p;
|
||||
} while (old);
|
||||
shared = 1;
|
||||
}
|
||||
|
||||
*p = new;
|
||||
|
||||
if (!shared) {
|
||||
desc->depth = 0;
|
||||
desc->status &=
|
||||
~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS);
|
||||
desc->handler->startup(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct proc_dir_entry * root_irq_dir;
|
||||
static struct proc_dir_entry * irq_dir[NR_IRQS];
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static struct proc_dir_entry * smp_affinity_entry[NR_IRQS];
|
||||
static char irq_user_affinity[NR_IRQS];
|
||||
static cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
|
||||
|
||||
static void
|
||||
select_smp_affinity(int irq)
|
||||
int
|
||||
select_smp_affinity(unsigned int irq)
|
||||
{
|
||||
static int last_cpu;
|
||||
int cpu = last_cpu + 1;
|
||||
|
||||
if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
|
||||
return;
|
||||
if (!irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
|
||||
return 1;
|
||||
|
||||
while (!cpu_possible(cpu))
|
||||
cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
|
||||
@ -247,208 +58,10 @@ select_smp_affinity(int irq)
|
||||
|
||||
irq_affinity[irq] = cpumask_of_cpu(cpu);
|
||||
irq_desc[irq].handler->set_affinity(irq, cpumask_of_cpu(cpu));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
irq_affinity_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
|
||||
if (count - len < 2)
|
||||
return -EINVAL;
|
||||
len += sprintf(page + len, "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
irq_affinity_write_proc(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
int irq = (long) data, full_count = count, err;
|
||||
cpumask_t new_value;
|
||||
|
||||
if (!irq_desc[irq].handler->set_affinity)
|
||||
return -EIO;
|
||||
|
||||
err = cpumask_parse(buffer, count, new_value);
|
||||
|
||||
/* The special value 0 means release control of the
|
||||
affinity to kernel. */
|
||||
cpus_and(new_value, new_value, cpu_online_map);
|
||||
if (cpus_empty(new_value)) {
|
||||
irq_user_affinity[irq] = 0;
|
||||
select_smp_affinity(irq);
|
||||
}
|
||||
/* Do not allow disabling IRQs completely - it's a too easy
|
||||
way to make the system unusable accidentally :-) At least
|
||||
one online CPU still has to be targeted. */
|
||||
else {
|
||||
irq_affinity[irq] = new_value;
|
||||
irq_user_affinity[irq] = 1;
|
||||
irq_desc[irq].handler->set_affinity(irq, new_value);
|
||||
}
|
||||
|
||||
return full_count;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#define MAX_NAMELEN 10
|
||||
|
||||
static void
|
||||
register_irq_proc (unsigned int irq)
|
||||
{
|
||||
char name [MAX_NAMELEN];
|
||||
|
||||
if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
|
||||
irq_dir[irq])
|
||||
return;
|
||||
|
||||
memset(name, 0, MAX_NAMELEN);
|
||||
sprintf(name, "%d", irq);
|
||||
|
||||
/* create /proc/irq/1234 */
|
||||
irq_dir[irq] = proc_mkdir(name, root_irq_dir);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (irq_desc[irq].handler->set_affinity) {
|
||||
struct proc_dir_entry *entry;
|
||||
/* create /proc/irq/1234/smp_affinity */
|
||||
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
|
||||
|
||||
if (entry) {
|
||||
entry->nlink = 1;
|
||||
entry->data = (void *)(long)irq;
|
||||
entry->read_proc = irq_affinity_read_proc;
|
||||
entry->write_proc = irq_affinity_write_proc;
|
||||
}
|
||||
|
||||
smp_affinity_entry[irq] = entry;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_irq_proc (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* create /proc/irq */
|
||||
root_irq_dir = proc_mkdir("irq", NULL);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* create /proc/irq/prof_cpu_mask */
|
||||
create_prof_cpu_mask(root_irq_dir);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create entries for all existing IRQs.
|
||||
*/
|
||||
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
|
||||
if (irq_desc[i].handler == &no_irq_type)
|
||||
continue;
|
||||
register_irq_proc(i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags, const char * devname, void *dev_id)
|
||||
{
|
||||
int retval;
|
||||
struct irqaction * action;
|
||||
|
||||
if (irq >= ACTUAL_NR_IRQS)
|
||||
return -EINVAL;
|
||||
if (!handler)
|
||||
return -EINVAL;
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* Sanity-check: shared interrupts should REALLY pass in
|
||||
* a real dev-ID, otherwise we'll have trouble later trying
|
||||
* to figure out which interrupt is which (messes up the
|
||||
* interrupt freeing logic etc).
|
||||
*/
|
||||
if ((irqflags & SA_SHIRQ) && !dev_id) {
|
||||
printk(KERN_ERR
|
||||
"Bad boy: %s (at %p) called us without a dev_id!\n",
|
||||
devname, __builtin_return_address(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
action = (struct irqaction *)
|
||||
kmalloc(sizeof(struct irqaction), GFP_KERNEL);
|
||||
if (!action)
|
||||
return -ENOMEM;
|
||||
|
||||
action->handler = handler;
|
||||
action->flags = irqflags;
|
||||
cpus_clear(action->mask);
|
||||
action->name = devname;
|
||||
action->next = NULL;
|
||||
action->dev_id = dev_id;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
select_smp_affinity(irq);
|
||||
#endif
|
||||
|
||||
retval = setup_irq(irq, action);
|
||||
if (retval)
|
||||
kfree(action);
|
||||
return retval;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(request_irq);
|
||||
|
||||
void
|
||||
free_irq(unsigned int irq, void *dev_id)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
struct irqaction **p;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= ACTUAL_NR_IRQS) {
|
||||
printk(KERN_CRIT "Trying to free IRQ%d\n", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
p = &desc->action;
|
||||
for (;;) {
|
||||
struct irqaction * action = *p;
|
||||
if (action) {
|
||||
struct irqaction **pp = p;
|
||||
p = &action->next;
|
||||
if (action->dev_id != dev_id)
|
||||
continue;
|
||||
|
||||
/* Found - now remove it from the list of entries. */
|
||||
*pp = action->next;
|
||||
if (!desc->action) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->handler->shutdown(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Wait to make sure it's not being used on
|
||||
another CPU. */
|
||||
while (desc->status & IRQ_INPROGRESS)
|
||||
barrier();
|
||||
#endif
|
||||
kfree(action);
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(free_irq);
|
||||
|
||||
int
|
||||
show_interrupts(struct seq_file *p, void *v)
|
||||
{
|
||||
@ -531,10 +144,6 @@ handle_irq(int irq, struct pt_regs * regs)
|
||||
* 0 return value means that this irq is already being
|
||||
* handled by some other CPU. (or is disabled)
|
||||
*/
|
||||
int cpu = smp_processor_id();
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
struct irqaction * action;
|
||||
unsigned int status;
|
||||
static unsigned int illegal_count=0;
|
||||
|
||||
if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) {
|
||||
@ -546,229 +155,8 @@ handle_irq(int irq, struct pt_regs * regs)
|
||||
}
|
||||
|
||||
irq_enter();
|
||||
kstat_cpu(cpu).irqs[irq]++;
|
||||
spin_lock_irq(&desc->lock); /* mask also the higher prio events */
|
||||
desc->handler->ack(irq);
|
||||
/*
|
||||
* REPLAY is when Linux resends an IRQ that was dropped earlier.
|
||||
* WAITING is used by probe to mark irqs that are being tested.
|
||||
*/
|
||||
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
|
||||
status |= IRQ_PENDING; /* we _want_ to handle it */
|
||||
|
||||
/*
|
||||
* If the IRQ is disabled for whatever reason, we cannot
|
||||
* use the action we have.
|
||||
*/
|
||||
action = NULL;
|
||||
if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
|
||||
action = desc->action;
|
||||
status &= ~IRQ_PENDING; /* we commit to handling */
|
||||
status |= IRQ_INPROGRESS; /* we are handling it */
|
||||
}
|
||||
desc->status = status;
|
||||
|
||||
/*
|
||||
* If there is no IRQ handler or it was disabled, exit early.
|
||||
* Since we set PENDING, if another processor is handling
|
||||
* a different instance of this same irq, the other processor
|
||||
* will take care of it.
|
||||
*/
|
||||
if (!action)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Edge triggered interrupts need to remember pending events.
|
||||
* This applies to any hw interrupts that allow a second
|
||||
* instance of the same irq to arrive while we are in handle_irq
|
||||
* or in the handler. But the code here only handles the _second_
|
||||
* instance of the irq, not the third or fourth. So it is mostly
|
||||
* useful for irq hardware that does not mask cleanly in an
|
||||
* SMP environment.
|
||||
*/
|
||||
for (;;) {
|
||||
spin_unlock(&desc->lock);
|
||||
handle_IRQ_event(irq, regs, action);
|
||||
spin_lock(&desc->lock);
|
||||
|
||||
if (!(desc->status & IRQ_PENDING)
|
||||
|| (desc->status & IRQ_LEVEL))
|
||||
break;
|
||||
desc->status &= ~IRQ_PENDING;
|
||||
}
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
out:
|
||||
/*
|
||||
* The ->end() handler has to deal with interrupts which got
|
||||
* disabled while the handler was running.
|
||||
*/
|
||||
desc->handler->end(irq);
|
||||
spin_unlock(&desc->lock);
|
||||
|
||||
local_irq_disable();
|
||||
__do_IRQ(irq, regs);
|
||||
local_irq_enable();
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ autodetection code..
|
||||
*
|
||||
* This depends on the fact that any interrupt that
|
||||
* comes in on to an unassigned handler will get stuck
|
||||
* with "IRQ_WAITING" cleared and the interrupt
|
||||
* disabled.
|
||||
*/
|
||||
unsigned long
|
||||
probe_irq_on(void)
|
||||
{
|
||||
int i;
|
||||
irq_desc_t *desc;
|
||||
unsigned long delay;
|
||||
unsigned long val;
|
||||
|
||||
/* Something may have generated an irq long ago and we want to
|
||||
flush such a longstanding irq before considering it as spurious. */
|
||||
for (i = NR_IRQS-1; i >= 0; i--) {
|
||||
desc = irq_desc + i;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
if (!irq_desc[i].action)
|
||||
irq_desc[i].handler->startup(i);
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
/* Wait for longstanding interrupts to trigger. */
|
||||
for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
|
||||
/* about 20ms delay */ barrier();
|
||||
|
||||
/* enable any unassigned irqs (we must startup again here because
|
||||
if a longstanding irq happened in the previous stage, it may have
|
||||
masked itself) first, enable any unassigned irqs. */
|
||||
for (i = NR_IRQS-1; i >= 0; i--) {
|
||||
desc = irq_desc + i;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
if (!desc->action) {
|
||||
desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
|
||||
if (desc->handler->startup(i))
|
||||
desc->status |= IRQ_PENDING;
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for spurious interrupts to trigger
|
||||
*/
|
||||
for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
|
||||
/* about 100ms delay */ barrier();
|
||||
|
||||
/*
|
||||
* Now filter out any obviously spurious interrupts
|
||||
*/
|
||||
val = 0;
|
||||
for (i=0; i<NR_IRQS; i++) {
|
||||
irq_desc_t *desc = irq_desc + i;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
if (status & IRQ_AUTODETECT) {
|
||||
/* It triggered already - consider it spurious. */
|
||||
if (!(status & IRQ_WAITING)) {
|
||||
desc->status = status & ~IRQ_AUTODETECT;
|
||||
desc->handler->shutdown(i);
|
||||
} else
|
||||
if (i < 32)
|
||||
val |= 1 << i;
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(probe_irq_on);
|
||||
|
||||
/*
|
||||
* Return a mask of triggered interrupts (this
|
||||
* can handle only legacy ISA interrupts).
|
||||
*/
|
||||
unsigned int
|
||||
probe_irq_mask(unsigned long val)
|
||||
{
|
||||
int i;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 0;
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
irq_desc_t *desc = irq_desc + i;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
if (status & IRQ_AUTODETECT) {
|
||||
/* We only react to ISA interrupts */
|
||||
if (!(status & IRQ_WAITING)) {
|
||||
if (i < 16)
|
||||
mask |= 1 << i;
|
||||
}
|
||||
|
||||
desc->status = status & ~IRQ_AUTODETECT;
|
||||
desc->handler->shutdown(i);
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
return mask & val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the result of the IRQ probe.. A negative result means that
|
||||
* we have several candidates (but we return the lowest-numbered
|
||||
* one).
|
||||
*/
|
||||
|
||||
int
|
||||
probe_irq_off(unsigned long val)
|
||||
{
|
||||
int i, irq_found, nr_irqs;
|
||||
|
||||
nr_irqs = 0;
|
||||
irq_found = 0;
|
||||
for (i=0; i<NR_IRQS; i++) {
|
||||
irq_desc_t *desc = irq_desc + i;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
if (status & IRQ_AUTODETECT) {
|
||||
if (!(status & IRQ_WAITING)) {
|
||||
if (!nr_irqs)
|
||||
irq_found = i;
|
||||
nr_irqs++;
|
||||
}
|
||||
desc->status = status & ~IRQ_AUTODETECT;
|
||||
desc->handler->shutdown(i);
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
if (nr_irqs > 1)
|
||||
irq_found = -irq_found;
|
||||
return irq_found;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(probe_irq_off);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void synchronize_irq(unsigned int irq)
|
||||
{
|
||||
/* is there anything to synchronize with? */
|
||||
if (!irq_desc[irq].action)
|
||||
return;
|
||||
|
||||
while (irq_desc[irq].status & IRQ_INPROGRESS)
|
||||
barrier();
|
||||
}
|
||||
#endif
|
||||
|
@ -41,7 +41,7 @@
|
||||
#define CAT1(x,y) x##y
|
||||
#define CAT(x,y) CAT1(x,y)
|
||||
|
||||
#define DO_DEFAULT_RTC rtc_port: 0x70
|
||||
#define DO_DEFAULT_RTC .rtc_port = 0x70
|
||||
|
||||
#define DO_EV4_MMU \
|
||||
.max_asn = EV4_MAX_ASN, \
|
||||
|
@ -45,7 +45,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
||||
static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
||||
{
|
||||
struct amba_device *pcdev = to_amba_device(dev);
|
||||
|
||||
@ -58,7 +58,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define amba_hotplug NULL
|
||||
#define amba_uevent NULL
|
||||
#endif
|
||||
|
||||
static int amba_suspend(struct device *dev, pm_message_t state)
|
||||
@ -88,7 +88,7 @@ static int amba_resume(struct device *dev)
|
||||
static struct bus_type amba_bustype = {
|
||||
.name = "amba",
|
||||
.match = amba_match,
|
||||
.hotplug = amba_hotplug,
|
||||
.uevent = amba_uevent,
|
||||
.suspend = amba_suspend,
|
||||
.resume = amba_resume,
|
||||
};
|
||||
|
@ -131,7 +131,7 @@ __syscall_start:
|
||||
.long sys_wait4
|
||||
/* 115 */ .long sys_swapoff
|
||||
.long sys_sysinfo
|
||||
.long sys_ipc_wrapper
|
||||
.long sys_ipc
|
||||
.long sys_fsync
|
||||
.long sys_sigreturn_wrapper
|
||||
/* 120 */ .long sys_clone_wrapper
|
||||
@ -254,7 +254,7 @@ __syscall_start:
|
||||
.long sys_fremovexattr
|
||||
.long sys_tkill
|
||||
.long sys_sendfile64
|
||||
/* 240 */ .long sys_futex_wrapper
|
||||
/* 240 */ .long sys_futex
|
||||
.long sys_sched_setaffinity
|
||||
.long sys_sched_getaffinity
|
||||
.long sys_io_setup
|
||||
@ -284,7 +284,7 @@ __syscall_start:
|
||||
.long sys_fstatfs64
|
||||
.long sys_tgkill
|
||||
.long sys_utimes
|
||||
/* 270 */ .long sys_arm_fadvise64_64_wrapper
|
||||
/* 270 */ .long sys_arm_fadvise64_64
|
||||
.long sys_pciconfig_iobase
|
||||
.long sys_pciconfig_read
|
||||
.long sys_pciconfig_write
|
||||
@ -333,7 +333,7 @@ __syscall_start:
|
||||
.long sys_inotify_init
|
||||
.long sys_inotify_add_watch
|
||||
.long sys_inotify_rm_watch
|
||||
.long sys_mbind_wrapper
|
||||
.long sys_mbind
|
||||
/* 320 */ .long sys_get_mempolicy
|
||||
.long sys_set_mempolicy
|
||||
__syscall_end:
|
||||
|
@ -611,6 +611,47 @@ ENTRY(__switch_to)
|
||||
.globl __kuser_helper_start
|
||||
__kuser_helper_start:
|
||||
|
||||
/*
|
||||
* Reference prototype:
|
||||
*
|
||||
* void __kernel_memory_barrier(void)
|
||||
*
|
||||
* Input:
|
||||
*
|
||||
* lr = return address
|
||||
*
|
||||
* Output:
|
||||
*
|
||||
* none
|
||||
*
|
||||
* Clobbered:
|
||||
*
|
||||
* the Z flag might be lost
|
||||
*
|
||||
* Definition and user space usage example:
|
||||
*
|
||||
* typedef void (__kernel_dmb_t)(void);
|
||||
* #define __kernel_dmb (*(__kernel_dmb_t *)0xffff0fa0)
|
||||
*
|
||||
* Apply any needed memory barrier to preserve consistency with data modified
|
||||
* manually and __kuser_cmpxchg usage.
|
||||
*
|
||||
* This could be used as follows:
|
||||
*
|
||||
* #define __kernel_dmb() \
|
||||
* asm volatile ( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #95" \
|
||||
* : : : "lr","cc" )
|
||||
*/
|
||||
|
||||
__kuser_memory_barrier: @ 0xffff0fa0
|
||||
|
||||
#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_SMP)
|
||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
||||
.align 5
|
||||
|
||||
/*
|
||||
* Reference prototype:
|
||||
*
|
||||
@ -642,6 +683,8 @@ __kuser_helper_start:
|
||||
* The C flag is also set if *ptr was changed to allow for assembly
|
||||
* optimization in the calling code.
|
||||
*
|
||||
* Note: this routine already includes memory barriers as needed.
|
||||
*
|
||||
* For example, a user space atomic_add implementation could look like this:
|
||||
*
|
||||
* #define atomic_add(ptr, val) \
|
||||
@ -698,10 +741,16 @@ __kuser_cmpxchg: @ 0xffff0fc0
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
||||
#endif
|
||||
ldrex r3, [r2]
|
||||
subs r3, r3, r0
|
||||
strexeq r3, r1, [r2]
|
||||
rsbs r0, r3, #0
|
||||
#ifdef CONFIG_SMP
|
||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
||||
#endif
|
||||
|
@ -145,7 +145,7 @@ ENTRY(vector_swi)
|
||||
#endif
|
||||
enable_irq
|
||||
|
||||
str r4, [sp, #-S_OFF]! @ push fifth arg
|
||||
stmdb sp!, {r4, r5} @ push fifth and sixth args
|
||||
|
||||
get_thread_info tsk
|
||||
ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
|
||||
@ -204,7 +204,7 @@ ENTRY(sys_call_table)
|
||||
* Special system call wrappers
|
||||
*/
|
||||
@ r0 = syscall number
|
||||
@ r5 = syscall table
|
||||
@ r8 = syscall table
|
||||
.type sys_syscall, #function
|
||||
sys_syscall:
|
||||
eor scno, r0, #__NR_SYSCALL_BASE
|
||||
@ -255,22 +255,6 @@ sys_sigaltstack_wrapper:
|
||||
ldr r2, [sp, #S_OFF + S_SP]
|
||||
b do_sigaltstack
|
||||
|
||||
sys_futex_wrapper:
|
||||
str r5, [sp, #4] @ push sixth arg
|
||||
b sys_futex
|
||||
|
||||
sys_arm_fadvise64_64_wrapper:
|
||||
str r5, [sp, #4] @ push r5 to stack
|
||||
b sys_arm_fadvise64_64
|
||||
|
||||
sys_mbind_wrapper:
|
||||
str r5, [sp, #4]
|
||||
b sys_mbind
|
||||
|
||||
sys_ipc_wrapper:
|
||||
str r5, [sp, #4] @ push sixth arg
|
||||
b sys_ipc
|
||||
|
||||
/*
|
||||
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
|
||||
* offset, we return EINVAL.
|
||||
|
@ -101,6 +101,8 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
|
||||
break;
|
||||
|
||||
case R_ARM_PC24:
|
||||
case R_ARM_CALL:
|
||||
case R_ARM_JUMP24:
|
||||
offset = (*(u32 *)loc & 0x00ffffff) << 2;
|
||||
if (offset & 0x02000000)
|
||||
offset -= 0x04000000;
|
||||
|
@ -242,6 +242,15 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
|
||||
*/
|
||||
long aluop1, aluop2, ccbit;
|
||||
|
||||
if ((insn & 0x0fffffd0) == 0x012fff10) {
|
||||
/*
|
||||
* bx or blx
|
||||
*/
|
||||
alt = get_user_reg(child, insn & 15);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if ((insn & 0xf000) != 0xf000)
|
||||
break;
|
||||
|
||||
|
@ -124,17 +124,16 @@ static int max7310_detach_client(struct i2c_client *client)
|
||||
}
|
||||
|
||||
static struct i2c_driver max7310_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "akita-max7310",
|
||||
.driver = {
|
||||
.name = "akita-max7310",
|
||||
},
|
||||
.id = I2C_DRIVERID_AKITAIOEXP,
|
||||
.flags = I2C_DF_NOTIFY,
|
||||
.attach_adapter = max7310_attach_adapter,
|
||||
.detach_client = max7310_detach_client,
|
||||
};
|
||||
|
||||
static struct i2c_client max7310_template = {
|
||||
name: "akita-max7310",
|
||||
flags: I2C_CLIENT_ALLOW_USE,
|
||||
driver: &max7310_i2c_driver,
|
||||
};
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <asm/arch/pxafb.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -393,6 +394,25 @@ static struct platform_device *platform_devices[] __initdata = {
|
||||
&mst_flash_device[1],
|
||||
};
|
||||
|
||||
static int mainstone_ohci_init(struct device *dev)
|
||||
{
|
||||
/* setup Port1 GPIO pin. */
|
||||
pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
|
||||
pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
|
||||
|
||||
/* Set the Power Control Polarity Low and Power Sense
|
||||
Polarity Low to active low. */
|
||||
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
|
||||
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pxaohci_platform_data mainstone_ohci_platform_data = {
|
||||
.port_mode = PMM_PERPORT_MODE,
|
||||
.init = mainstone_ohci_init,
|
||||
};
|
||||
|
||||
static void __init mainstone_init(void)
|
||||
{
|
||||
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
|
||||
@ -424,6 +444,7 @@ static void __init mainstone_init(void)
|
||||
|
||||
pxa_set_mci_info(&mainstone_mci_platform_data);
|
||||
pxa_set_ficp_info(&mainstone_ficp_platform_data);
|
||||
pxa_set_ohci_info(&mainstone_ohci_platform_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,19 +155,20 @@ int pxa_pm_enter(suspend_state_t state)
|
||||
PSPR = 0;
|
||||
|
||||
/* restore registers */
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
|
||||
RESTORE(GAFR0_L); RESTORE(GAFR0_U);
|
||||
RESTORE(GAFR1_L); RESTORE(GAFR1_U);
|
||||
RESTORE(GAFR2_L); RESTORE(GAFR2_U);
|
||||
RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
|
||||
RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
|
||||
RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
|
||||
RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
|
||||
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
|
||||
|
||||
#ifdef CONFIG_PXA27x
|
||||
RESTORE(MDREFR);
|
||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
|
||||
RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
|
||||
RESTORE_GPLEVEL(3); RESTORE(GPDR3);
|
||||
RESTORE(GAFR3_L); RESTORE(GAFR3_U);
|
||||
RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
|
||||
RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
|
||||
RESTORE(PFER); RESTORE(PKWR);
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -194,6 +195,11 @@ static struct platform_device ohci_device = {
|
||||
.resource = pxa27x_ohci_resources,
|
||||
};
|
||||
|
||||
void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
|
||||
{
|
||||
ohci_device.dev.platform_data = info;
|
||||
}
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&ohci_device,
|
||||
};
|
||||
|
@ -46,10 +46,9 @@ typedef struct task_struct* PTASK;
|
||||
|
||||
#ifdef MODULE
|
||||
void fp_send_sig(unsigned long sig, PTASK p, int priv);
|
||||
#if LINUX_VERSION_CODE > 0x20115
|
||||
|
||||
MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
|
||||
MODULE_DESCRIPTION("NWFPE floating point emulator");
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define fp_send_sig send_sig
|
||||
|
@ -569,12 +569,6 @@ gdb_cris_strtol (const char *s, char **endptr, int base)
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
double_this(int x)
|
||||
{
|
||||
return 2 * x;
|
||||
}
|
||||
|
||||
/********************************* Register image ****************************/
|
||||
/* Copy the content of a register image into another. The size n is
|
||||
the size of the register image. Due to struct assignment generation of
|
||||
|
@ -20,3 +20,4 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
|
||||
obj-$(CONFIG_PM) += pm.o cmode.o
|
||||
obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
|
||||
obj-$(CONFIG_SYSCTL) += sysctl.o
|
||||
obj-$(CONFIG_FUTEX) += futex.o
|
||||
|
@ -1076,7 +1076,7 @@ __entry_work_notifysig:
|
||||
LEDS 0x6410
|
||||
ori.p gr4,#0,gr8
|
||||
call do_notify_resume
|
||||
bra __entry_return_direct
|
||||
bra __entry_resume_userspace
|
||||
|
||||
# perform syscall entry tracing
|
||||
__syscall_trace_entry:
|
||||
|
242
arch/frv/kernel/futex.c
Normal file
242
arch/frv/kernel/futex.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* futex.c: futex operations
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <asm/futex.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* the various futex operations; MMU fault checking is ignored under no-MMU
|
||||
* conditions
|
||||
*/
|
||||
static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" add %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" or %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" and %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" xor %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* do the futex operations
|
||||
*/
|
||||
int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
inc_preempt_count();
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
dec_preempt_count();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS; break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end futex_atomic_op_inuser() */
|
@ -35,7 +35,7 @@ struct fdpic_func_descriptor {
|
||||
unsigned long GOT;
|
||||
};
|
||||
|
||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
|
||||
static int do_signal(sigset_t *oldset);
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
@ -55,7 +55,7 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(__frame, &saveset))
|
||||
if (do_signal(&saveset))
|
||||
/* return the signal number as the return value of this function
|
||||
* - this is an utterly evil hack. syscalls should not invoke do_signal()
|
||||
* as entry.S sets regs->gr8 to the return value of the system call
|
||||
@ -91,7 +91,7 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
|
||||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(__frame, &saveset))
|
||||
if (do_signal(&saveset))
|
||||
/* return the signal number as the return value of this function
|
||||
* - this is an utterly evil hack. syscalls should not invoke do_signal()
|
||||
* as entry.S sets regs->gr8 to the return value of the system call
|
||||
@ -276,13 +276,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
||||
/* Default to using normal stack */
|
||||
sp = regs->sp;
|
||||
sp = __frame->sp;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
@ -291,18 +290,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
}
|
||||
|
||||
return (void __user *) ((sp - frame_size) & ~7UL);
|
||||
|
||||
} /* end get_sigframe() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int rsig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ka, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
@ -346,47 +346,51 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p
|
||||
}
|
||||
|
||||
/* set up registers for signal handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->lr = (unsigned long) &frame->retcode;
|
||||
regs->gr8 = sig;
|
||||
__frame->sp = (unsigned long) frame;
|
||||
__frame->lr = (unsigned long) &frame->retcode;
|
||||
__frame->gr8 = sig;
|
||||
|
||||
if (get_personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor *) ka->sa.sa_handler;
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->gr15, &funcptr->GOT);
|
||||
__get_user(__frame->pc, &funcptr->text);
|
||||
__get_user(__frame->gr15, &funcptr->GOT);
|
||||
} else {
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->gr15 = 0;
|
||||
__frame->pc = (unsigned long) ka->sa.sa_handler;
|
||||
__frame->gr15 = 0;
|
||||
}
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
/* the tracer may want to single-step inside the handler */
|
||||
if (test_thread_flag(TIF_SINGLESTEP))
|
||||
ptrace_notify(SIGTRAP);
|
||||
|
||||
#if DEBUG_SIG
|
||||
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
|
||||
sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
|
||||
sig, current->comm, current->pid, frame, __frame->pc,
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
||||
} /* end setup_frame() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int rsig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ka, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
@ -409,7 +413,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (__put_user(0, &frame->uc.uc_flags) ||
|
||||
__put_user(0, &frame->uc.uc_link) ||
|
||||
__put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
|
||||
__put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
|
||||
__put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
|
||||
__put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
|
||||
goto give_sigsegv;
|
||||
|
||||
@ -440,34 +444,38 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->lr = (unsigned long) &frame->retcode;
|
||||
regs->gr8 = sig;
|
||||
regs->gr9 = (unsigned long) &frame->info;
|
||||
__frame->sp = (unsigned long) frame;
|
||||
__frame->lr = (unsigned long) &frame->retcode;
|
||||
__frame->gr8 = sig;
|
||||
__frame->gr9 = (unsigned long) &frame->info;
|
||||
|
||||
if (get_personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor *funcptr =
|
||||
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->gr15, &funcptr->GOT);
|
||||
__get_user(__frame->pc, &funcptr->text);
|
||||
__get_user(__frame->gr15, &funcptr->GOT);
|
||||
} else {
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->gr15 = 0;
|
||||
__frame->pc = (unsigned long) ka->sa.sa_handler;
|
||||
__frame->gr15 = 0;
|
||||
}
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
/* the tracer may want to single-step inside the handler */
|
||||
if (test_thread_flag(TIF_SINGLESTEP))
|
||||
ptrace_notify(SIGTRAP);
|
||||
|
||||
#if DEBUG_SIG
|
||||
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
|
||||
sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
|
||||
sig, current->comm, current->pid, frame, __frame->pc,
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
||||
} /* end setup_rt_frame() */
|
||||
|
||||
@ -475,43 +483,51 @@ give_sigsegv:
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
if (in_syscall(regs)) {
|
||||
if (in_syscall(__frame)) {
|
||||
/* If so, check system call restarting.. */
|
||||
switch (regs->gr8) {
|
||||
switch (__frame->gr8) {
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
case -ERESTARTNOHAND:
|
||||
regs->gr8 = -EINTR;
|
||||
__frame->gr8 = -EINTR;
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
regs->gr8 = -EINTR;
|
||||
__frame->gr8 = -EINTR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
case -ERESTARTNOINTR:
|
||||
regs->gr8 = regs->orig_gr8;
|
||||
regs->pc -= 4;
|
||||
__frame->gr8 = __frame->orig_gr8;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
ret = setup_rt_frame(sig, ka, info, oldset);
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(sig, ka, oldset);
|
||||
|
||||
if (ret) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
} /* end handle_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -520,7 +536,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
static int do_signal(sigset_t *oldset)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
@ -532,7 +548,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
* kernel mode. Just return without doing anything
|
||||
* if so.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
if (!user_mode(__frame))
|
||||
return 1;
|
||||
|
||||
if (try_to_freeze())
|
||||
@ -541,30 +557,29 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
if (!oldset)
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
handle_signal(signr, &info, &ka, oldset, regs);
|
||||
return 1;
|
||||
}
|
||||
signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
|
||||
if (signr > 0)
|
||||
return handle_signal(signr, &info, &ka, oldset);
|
||||
|
||||
no_signal:
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (regs->syscallno >= 0) {
|
||||
if (__frame->syscallno >= 0) {
|
||||
/* Restart the system call - no handlers present */
|
||||
if (regs->gr8 == -ERESTARTNOHAND ||
|
||||
regs->gr8 == -ERESTARTSYS ||
|
||||
regs->gr8 == -ERESTARTNOINTR) {
|
||||
regs->gr8 = regs->orig_gr8;
|
||||
regs->pc -= 4;
|
||||
if (__frame->gr8 == -ERESTARTNOHAND ||
|
||||
__frame->gr8 == -ERESTARTSYS ||
|
||||
__frame->gr8 == -ERESTARTNOINTR) {
|
||||
__frame->gr8 = __frame->orig_gr8;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
|
||||
if (regs->gr8 == -ERESTART_RESTARTBLOCK){
|
||||
regs->gr8 = __NR_restart_syscall;
|
||||
regs->pc -= 4;
|
||||
if (__frame->gr8 == -ERESTART_RESTARTBLOCK){
|
||||
__frame->gr8 = __NR_restart_syscall;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} /* end do_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -580,6 +595,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(__frame, NULL);
|
||||
do_signal(NULL);
|
||||
|
||||
} /* end do_notify_resume() */
|
||||
|
@ -464,7 +464,6 @@ config NUMA
|
||||
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
|
||||
default n if X86_PC
|
||||
default y if (X86_NUMAQ || X86_SUMMIT)
|
||||
select SPARSEMEM_STATIC
|
||||
|
||||
# Need comments to help the hapless user trying to turn on NUMA support
|
||||
comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
|
||||
@ -493,6 +492,10 @@ config HAVE_ARCH_ALLOC_REMAP
|
||||
depends on NUMA
|
||||
default y
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC)
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
@ -503,7 +506,8 @@ config ARCH_DISCONTIGMEM_DEFAULT
|
||||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
depends on (NUMA || (X86_PC && EXPERIMENTAL))
|
||||
select SPARSEMEM_STATIC
|
||||
|
||||
config ARCH_SELECT_MEMORY_MODEL
|
||||
def_bool y
|
||||
|
@ -39,6 +39,7 @@ config M386
|
||||
- "Winchip-2" for IDT Winchip 2.
|
||||
- "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
|
||||
- "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
|
||||
- "Geode GX/LX" For AMD Geode GX and LX processors.
|
||||
- "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
|
||||
- "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
|
||||
|
||||
@ -171,6 +172,11 @@ config MGEODEGX1
|
||||
help
|
||||
Select this for a Geode GX1 (Cyrix MediaGX) chip.
|
||||
|
||||
config MGEODE_LX
|
||||
bool "Geode GX/LX"
|
||||
help
|
||||
Select this for AMD Geode GX and LX processors.
|
||||
|
||||
config MCYRIXIII
|
||||
bool "CyrixIII/VIA-C3"
|
||||
help
|
||||
@ -220,8 +226,8 @@ config X86_XADD
|
||||
config X86_L1_CACHE_SHIFT
|
||||
int
|
||||
default "7" if MPENTIUM4 || X86_GENERIC
|
||||
default "4" if X86_ELAN || M486 || M386
|
||||
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
|
||||
default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
|
||||
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
|
||||
default "6" if MK7 || MK8 || MPENTIUMM
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
@ -290,12 +296,12 @@ config X86_INTEL_USERCOPY
|
||||
|
||||
config X86_USE_PPRO_CHECKSUM
|
||||
bool
|
||||
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
|
||||
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX
|
||||
default y
|
||||
|
||||
config X86_USE_3DNOW
|
||||
bool
|
||||
depends on MCYRIXIII || MK7
|
||||
depends on MCYRIXIII || MK7 || MGEODE_LX
|
||||
default y
|
||||
|
||||
config X86_OOSTORE
|
||||
|
@ -42,6 +42,16 @@ config DEBUG_PAGEALLOC
|
||||
This results in a large slowdown, but helps to find certain types
|
||||
of memory corruptions.
|
||||
|
||||
config DEBUG_RODATA
|
||||
bool "Write protect kernel read-only data structures"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
Mark the kernel read-only data as write-protected in the pagetables,
|
||||
in order to catch accidental (and incorrect) writes to such const
|
||||
data. This option may have a slight performance impact because a
|
||||
portion of the kernel code won't be covered by a 2MB TLB anymore.
|
||||
If in doubt, say "N".
|
||||
|
||||
config 4KSTACKS
|
||||
bool "Use 4Kb for kernel stacks instead of 8Kb"
|
||||
depends on DEBUG_KERNEL
|
||||
|
@ -721,7 +721,7 @@ static int __init apic_set_verbosity(char *str)
|
||||
apic_verbosity = APIC_VERBOSE;
|
||||
else
|
||||
printk(KERN_WARNING "APIC Verbosity level %s not recognised"
|
||||
" use apic=verbose or apic=debug", str);
|
||||
" use apic=verbose or apic=debug\n", str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -302,17 +302,6 @@ extern int (*console_blank_hook)(int);
|
||||
|
||||
#include "apm.h"
|
||||
|
||||
/*
|
||||
* Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is
|
||||
* supposed to provide limit information that it recognizes. Many machines
|
||||
* do this correctly, but many others do not restrict themselves to their
|
||||
* claimed limit. When this happens, they will cause a segmentation
|
||||
* violation in the kernel at boot time. Most BIOS's, however, will
|
||||
* respect a 64k limit, so we use that. If you want to be pedantic and
|
||||
* hold your BIOS to its claims, then undefine this.
|
||||
*/
|
||||
#define APM_RELAX_SEGMENTS
|
||||
|
||||
/*
|
||||
* Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
|
||||
* This patched by Chad Miller <cmiller@surfsouth.com>, original code by
|
||||
@ -1075,22 +1064,23 @@ static int apm_engage_power_management(u_short device, int enable)
|
||||
|
||||
static int apm_console_blank(int blank)
|
||||
{
|
||||
int error;
|
||||
u_short state;
|
||||
int error, i;
|
||||
u_short state;
|
||||
static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
|
||||
|
||||
state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
|
||||
/* Blank the first display device */
|
||||
error = set_power_state(0x100, state);
|
||||
if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
|
||||
/* try to blank them all instead */
|
||||
error = set_power_state(0x1ff, state);
|
||||
if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
|
||||
/* try to blank device one instead */
|
||||
error = set_power_state(0x101, state);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev); i++) {
|
||||
error = set_power_state(dev[i], state);
|
||||
|
||||
if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
|
||||
return 1;
|
||||
|
||||
if (error == APM_NOT_ENGAGED)
|
||||
break;
|
||||
}
|
||||
if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
|
||||
return 1;
|
||||
if (error == APM_NOT_ENGAGED) {
|
||||
|
||||
if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
|
||||
static int tried;
|
||||
int eng_error;
|
||||
if (tried++ == 0) {
|
||||
@ -2233,8 +2223,8 @@ static struct dmi_system_id __initdata apm_dmi_table[] = {
|
||||
static int __init apm_init(void)
|
||||
{
|
||||
struct proc_dir_entry *apm_proc;
|
||||
struct desc_struct *gdt;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
dmi_check_system(apm_dmi_table);
|
||||
|
||||
@ -2312,45 +2302,30 @@ static int __init apm_init(void)
|
||||
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
|
||||
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
|
||||
|
||||
/*
|
||||
* Set up the long jump entry point to the APM BIOS, which is called
|
||||
* from inline assembly.
|
||||
*/
|
||||
apm_bios_entry.offset = apm_info.bios.offset;
|
||||
apm_bios_entry.segment = APM_CS;
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
struct desc_struct *gdt = get_cpu_gdt_table(i);
|
||||
set_base(gdt[APM_CS >> 3],
|
||||
__va((unsigned long)apm_info.bios.cseg << 4));
|
||||
set_base(gdt[APM_CS_16 >> 3],
|
||||
__va((unsigned long)apm_info.bios.cseg_16 << 4));
|
||||
set_base(gdt[APM_DS >> 3],
|
||||
__va((unsigned long)apm_info.bios.dseg << 4));
|
||||
#ifndef APM_RELAX_SEGMENTS
|
||||
if (apm_info.bios.version == 0x100) {
|
||||
#endif
|
||||
/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
|
||||
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
|
||||
/* For some unknown machine. */
|
||||
_set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
|
||||
/* For the DEC Hinote Ultra CT475 (and others?) */
|
||||
_set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
|
||||
#ifndef APM_RELAX_SEGMENTS
|
||||
} else {
|
||||
_set_limit((char *)&gdt[APM_CS >> 3],
|
||||
(apm_info.bios.cseg_len - 1) & 0xffff);
|
||||
_set_limit((char *)&gdt[APM_CS_16 >> 3],
|
||||
(apm_info.bios.cseg_16_len - 1) & 0xffff);
|
||||
_set_limit((char *)&gdt[APM_DS >> 3],
|
||||
(apm_info.bios.dseg_len - 1) & 0xffff);
|
||||
/* workaround for broken BIOSes */
|
||||
if (apm_info.bios.cseg_len <= apm_info.bios.offset)
|
||||
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1);
|
||||
if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
|
||||
/* for the BIOS that assumes granularity = 1 */
|
||||
gdt[APM_DS >> 3].b |= 0x800000;
|
||||
printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* The APM 1.1 BIOS is supposed to provide limit information that it
|
||||
* recognizes. Many machines do this correctly, but many others do
|
||||
* not restrict themselves to their claimed limit. When this happens,
|
||||
* they will cause a segmentation violation in the kernel at boot time.
|
||||
* Most BIOS's, however, will respect a 64k limit, so we use that.
|
||||
*
|
||||
* Note we only set APM segments on CPU zero, since we pin the APM
|
||||
* code to that CPU.
|
||||
*/
|
||||
gdt = get_cpu_gdt_table(0);
|
||||
set_base(gdt[APM_CS >> 3],
|
||||
__va((unsigned long)apm_info.bios.cseg << 4));
|
||||
set_base(gdt[APM_CS_16 >> 3],
|
||||
__va((unsigned long)apm_info.bios.cseg_16 << 4));
|
||||
set_base(gdt[APM_DS >> 3],
|
||||
__va((unsigned long)apm_info.bios.dseg << 4));
|
||||
|
||||
apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
|
||||
if (apm_proc)
|
||||
|
@ -161,8 +161,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
|
||||
set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
if (c->x86_model == 10) {
|
||||
/* AMD Geode LX is model 10 */
|
||||
/* placeholder for any needed mods */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6: /* An Athlon/Duron */
|
||||
|
||||
/* Bit 15 of Athlon specific MSR 15, needs to be 0
|
||||
|
@ -18,9 +18,6 @@
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
|
||||
|
||||
DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
|
||||
|
||||
@ -598,11 +595,6 @@ void __devinit cpu_init(void)
|
||||
load_gdt(&cpu_gdt_descr[cpu]);
|
||||
load_idt(&idt_descr);
|
||||
|
||||
/*
|
||||
* Delete NT
|
||||
*/
|
||||
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
|
||||
|
||||
/*
|
||||
* Set up and load the per-CPU TSS and LDT
|
||||
*/
|
||||
|
@ -177,9 +177,10 @@ static unsigned int nforce2_fsb_read(int bootfsb)
|
||||
*/
|
||||
static int nforce2_set_fsb(unsigned int fsb)
|
||||
{
|
||||
u32 pll, temp = 0;
|
||||
u32 temp = 0;
|
||||
unsigned int tfsb;
|
||||
int diff;
|
||||
int pll = 0;
|
||||
|
||||
if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
|
||||
printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
#define PFX "powernow-k8: "
|
||||
#define BFX PFX "BIOS error: "
|
||||
#define VERSION "version 1.50.4"
|
||||
#define VERSION "version 1.60.0"
|
||||
#include "powernow-k8.h"
|
||||
|
||||
/* serialize freq changes */
|
||||
@ -216,10 +216,10 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid)
|
||||
|
||||
do {
|
||||
wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
|
||||
if (i++ > 100) {
|
||||
printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
|
||||
return 1;
|
||||
}
|
||||
if (i++ > 100) {
|
||||
printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
|
||||
return 1;
|
||||
}
|
||||
} while (query_current_values_with_pending_wait(data));
|
||||
|
||||
if (savefid != data->currfid) {
|
||||
@ -336,7 +336,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
|
||||
/* Phase 2 - core frequency transition */
|
||||
static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
|
||||
{
|
||||
u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid;
|
||||
u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid;
|
||||
|
||||
if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
|
||||
printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n",
|
||||
@ -359,9 +359,11 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
|
||||
: vcoreqfid - vcocurrfid;
|
||||
|
||||
while (vcofiddiff > 2) {
|
||||
(data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
|
||||
|
||||
if (reqfid > data->currfid) {
|
||||
if (data->currfid > LO_FID_TABLE_TOP) {
|
||||
if (write_new_fid(data, data->currfid + 2)) {
|
||||
if (write_new_fid(data, data->currfid + fid_interval)) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
@ -371,7 +373,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (write_new_fid(data, data->currfid - 2))
|
||||
if (write_new_fid(data, data->currfid - fid_interval))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -464,7 +466,7 @@ static int check_supported_cpu(unsigned int cpu)
|
||||
set_cpus_allowed(current, cpumask_of_cpu(cpu));
|
||||
|
||||
if (smp_processor_id() != cpu) {
|
||||
printk(KERN_ERR "limiting to cpu %u failed\n", cpu);
|
||||
printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -474,7 +476,7 @@ static int check_supported_cpu(unsigned int cpu)
|
||||
eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
|
||||
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
|
||||
((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
|
||||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) {
|
||||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
|
||||
printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
|
||||
goto out;
|
||||
}
|
||||
@ -517,22 +519,24 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
|
||||
printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j);
|
||||
return -ENODEV;
|
||||
}
|
||||
if ((pst[j].fid > MAX_FID)
|
||||
|| (pst[j].fid & 1)
|
||||
|| (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
|
||||
if (pst[j].fid > MAX_FID) {
|
||||
printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) {
|
||||
/* Only first fid is allowed to be in "low" range */
|
||||
printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
|
||||
printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pst[j].fid < lastfid)
|
||||
lastfid = pst[j].fid;
|
||||
}
|
||||
if (lastfid & 1) {
|
||||
printk(KERN_ERR PFX "lastfid invalid\n");
|
||||
printk(KERN_ERR BFX "lastfid invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lastfid > LO_FID_TABLE_TOP)
|
||||
printk(KERN_INFO PFX "first fid not from lo freq table\n");
|
||||
printk(KERN_INFO BFX "first fid not from lo freq table\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -631,7 +635,7 @@ static int find_psb_table(struct powernow_k8_data *data)
|
||||
|
||||
dprintk("table vers: 0x%x\n", psb->tableversion);
|
||||
if (psb->tableversion != PSB_VERSION_1_4) {
|
||||
printk(KERN_INFO BFX "PSB table is not v1.4\n");
|
||||
printk(KERN_ERR BFX "PSB table is not v1.4\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -689,7 +693,7 @@ static int find_psb_table(struct powernow_k8_data *data)
|
||||
* BIOS and Kernel Developer's Guide, which is available on
|
||||
* www.amd.com
|
||||
*/
|
||||
printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
|
||||
printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -912,7 +916,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
||||
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
|
||||
|
||||
if (smp_processor_id() != pol->cpu) {
|
||||
printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
|
||||
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
@ -982,6 +986,9 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
cpumask_t oldmask = CPU_MASK_ALL;
|
||||
int rc, i;
|
||||
|
||||
if (!cpu_online(pol->cpu))
|
||||
return -ENODEV;
|
||||
|
||||
if (!check_supported_cpu(pol->cpu))
|
||||
return -ENODEV;
|
||||
|
||||
@ -1021,7 +1028,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
||||
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
|
||||
|
||||
if (smp_processor_id() != pol->cpu) {
|
||||
printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
|
||||
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
@ -1162,10 +1169,9 @@ static void __exit powernowk8_exit(void)
|
||||
cpufreq_unregister_driver(&cpufreq_amd64_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
|
||||
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>");
|
||||
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
late_initcall(powernowk8_init);
|
||||
module_exit(powernowk8_exit);
|
||||
|
||||
|
@ -42,7 +42,7 @@ struct powernow_k8_data {
|
||||
#define CPUID_XFAM 0x0ff00000 /* extended family */
|
||||
#define CPUID_XFAM_K8 0
|
||||
#define CPUID_XMOD 0x000f0000 /* extended model */
|
||||
#define CPUID_XMOD_REV_F 0x00040000
|
||||
#define CPUID_XMOD_REV_G 0x00060000
|
||||
#define CPUID_USE_XFAM_XMOD 0x00000f00
|
||||
#define CPUID_GET_MAX_CAPABILITIES 0x80000000
|
||||
#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
|
||||
@ -86,13 +86,14 @@ struct powernow_k8_data {
|
||||
* low fid table
|
||||
* - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry
|
||||
* in the low fid table
|
||||
* - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid
|
||||
* - the parts can only step at <= 200 MHz intervals, odd fid values are
|
||||
* supported in revision G and later revisions.
|
||||
* - lowest frequency must be >= interprocessor hypertransport link speed
|
||||
* (only applies to MP systems obviously)
|
||||
*/
|
||||
|
||||
/* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
|
||||
#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */
|
||||
#define LO_FID_TABLE_TOP 7 /* fid values marking the boundary */
|
||||
#define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */
|
||||
|
||||
#define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */
|
||||
@ -106,7 +107,7 @@ struct powernow_k8_data {
|
||||
#define MIN_FREQ 800 /* Min and max freqs, per spec */
|
||||
#define MAX_FREQ 5000
|
||||
|
||||
#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */
|
||||
#define INVALID_FID_MASK 0xffffffc0 /* not a valid fid if these bits are set */
|
||||
#define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */
|
||||
|
||||
#define VID_OFF 0x3f
|
||||
|
@ -40,6 +40,7 @@ static struct pci_dev *speedstep_chipset_dev;
|
||||
*/
|
||||
static unsigned int speedstep_processor = 0;
|
||||
|
||||
static u32 pmbase;
|
||||
|
||||
/*
|
||||
* There are only two frequency states for each processor. Values
|
||||
@ -55,6 +56,33 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-ich", msg)
|
||||
|
||||
|
||||
/**
|
||||
* speedstep_find_register - read the PMBASE address
|
||||
*
|
||||
* Returns: -ENODEV if no register could be found
|
||||
*/
|
||||
static int speedstep_find_register (void)
|
||||
{
|
||||
if (!speedstep_chipset_dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* get PMBASE */
|
||||
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
|
||||
if (!(pmbase & 0x01)) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pmbase &= 0xFFFFFFFE;
|
||||
if (!pmbase) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dprintk("pmbase is 0x%x\n", pmbase);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* speedstep_set_state - set the SpeedStep state
|
||||
* @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
|
||||
@ -63,27 +91,13 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
|
||||
*/
|
||||
static void speedstep_set_state (unsigned int state)
|
||||
{
|
||||
u32 pmbase;
|
||||
u8 pm2_blk;
|
||||
u8 value;
|
||||
unsigned long flags;
|
||||
|
||||
if (!speedstep_chipset_dev || (state > 0x1))
|
||||
if (state > 0x1)
|
||||
return;
|
||||
|
||||
/* get PMBASE */
|
||||
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
|
||||
if (!(pmbase & 0x01)) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pmbase &= 0xFFFFFFFE;
|
||||
if (!pmbase) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable IRQs */
|
||||
local_irq_save(flags);
|
||||
|
||||
@ -315,10 +329,11 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
|
||||
cpus_allowed = current->cpus_allowed;
|
||||
set_cpus_allowed(current, policy->cpus);
|
||||
|
||||
/* detect low and high frequency */
|
||||
/* detect low and high frequency and transition latency */
|
||||
result = speedstep_get_freqs(speedstep_processor,
|
||||
&speedstep_freqs[SPEEDSTEP_LOW].frequency,
|
||||
&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
|
||||
&policy->cpuinfo.transition_latency,
|
||||
&speedstep_set_state);
|
||||
set_cpus_allowed(current, cpus_allowed);
|
||||
if (result)
|
||||
@ -335,7 +350,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
/* cpuinfo and default policy values */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
|
||||
policy->cur = speed;
|
||||
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
|
||||
@ -400,6 +414,9 @@ static int __init speedstep_init(void)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (speedstep_find_register())
|
||||
return -ENODEV;
|
||||
|
||||
return cpufreq_register_driver(&speedstep_driver);
|
||||
}
|
||||
|
||||
|
@ -320,11 +320,13 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor);
|
||||
unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
unsigned int *low_speed,
|
||||
unsigned int *high_speed,
|
||||
unsigned int *transition_latency,
|
||||
void (*set_state) (unsigned int state))
|
||||
{
|
||||
unsigned int prev_speed;
|
||||
unsigned int ret = 0;
|
||||
unsigned long flags;
|
||||
struct timeval tv1, tv2;
|
||||
|
||||
if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
|
||||
return -EINVAL;
|
||||
@ -337,7 +339,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
return -EIO;
|
||||
|
||||
dprintk("previous speed is %u\n", prev_speed);
|
||||
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/* switch to low state */
|
||||
@ -350,8 +352,17 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
|
||||
dprintk("low speed is %u\n", *low_speed);
|
||||
|
||||
/* start latency measurement */
|
||||
if (transition_latency)
|
||||
do_gettimeofday(&tv1);
|
||||
|
||||
/* switch to high state */
|
||||
set_state(SPEEDSTEP_HIGH);
|
||||
|
||||
/* end latency measurement */
|
||||
if (transition_latency)
|
||||
do_gettimeofday(&tv2);
|
||||
|
||||
*high_speed = speedstep_get_processor_frequency(processor);
|
||||
if (!*high_speed) {
|
||||
ret = -EIO;
|
||||
@ -369,6 +380,25 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
if (*high_speed != prev_speed)
|
||||
set_state(SPEEDSTEP_LOW);
|
||||
|
||||
if (transition_latency) {
|
||||
*transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC +
|
||||
tv2.tv_usec - tv1.tv_usec;
|
||||
dprintk("transition latency is %u uSec\n", *transition_latency);
|
||||
|
||||
/* convert uSec to nSec and add 20% for safety reasons */
|
||||
*transition_latency *= 1200;
|
||||
|
||||
/* check if the latency measurement is too high or too low
|
||||
* and set it to a safe value (500uSec) in that case
|
||||
*/
|
||||
if (*transition_latency > 10000000 || *transition_latency < 50000) {
|
||||
printk (KERN_WARNING "speedstep: frequency transition measured seems out of "
|
||||
"range (%u nSec), falling back to a safe one of %u nSec.\n",
|
||||
*transition_latency, 500000);
|
||||
*transition_latency = 500000;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
local_irq_restore(flags);
|
||||
return (ret);
|
||||
|
@ -44,4 +44,5 @@ extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
|
||||
extern unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
unsigned int *low_speed,
|
||||
unsigned int *high_speed,
|
||||
unsigned int *transition_latency,
|
||||
void (*set_state) (unsigned int state));
|
||||
|
@ -269,6 +269,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
|
||||
result = speedstep_get_freqs(speedstep_processor,
|
||||
&speedstep_freqs[SPEEDSTEP_LOW].frequency,
|
||||
&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
|
||||
NULL,
|
||||
&speedstep_set_state);
|
||||
|
||||
if (result) {
|
||||
|
@ -342,6 +342,31 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle National Semiconductor branded processors
|
||||
*/
|
||||
static void __devinit init_nsc(struct cpuinfo_x86 *c)
|
||||
{
|
||||
/* There may be GX1 processors in the wild that are branded
|
||||
* NSC and not Cyrix.
|
||||
*
|
||||
* This function only handles the GX processor, and kicks every
|
||||
* thing else to the Cyrix init function above - that should
|
||||
* cover any processors that might have been branded differently
|
||||
* after NSC aquired Cyrix.
|
||||
*
|
||||
* If this breaks your GX1 horribly, please e-mail
|
||||
* info-linux@ldcmail.amd.com to tell us.
|
||||
*/
|
||||
|
||||
/* Handle the GX (Formally known as the GX2) */
|
||||
|
||||
if (c->x86 == 5 && c->x86_model == 5)
|
||||
display_cacheinfo(c);
|
||||
else
|
||||
init_cyrix(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
|
||||
* by the fact that they preserve the flags across the division of 5/2.
|
||||
@ -422,7 +447,7 @@ int __init cyrix_init_cpu(void)
|
||||
static struct cpu_dev nsc_cpu_dev __initdata = {
|
||||
.c_vendor = "NSC",
|
||||
.c_ident = { "Geode by NSC" },
|
||||
.c_init = init_cyrix,
|
||||
.c_init = init_nsc,
|
||||
.c_identify = generic_identify,
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
/*
|
||||
* Get CPU information for use by the procfs.
|
||||
@ -86,8 +87,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
||||
seq_printf(m, "stepping\t: unknown\n");
|
||||
|
||||
if ( cpu_has(c, X86_FEATURE_TSC) ) {
|
||||
unsigned int freq = cpufreq_quick_get(n);
|
||||
if (!freq)
|
||||
freq = cpu_khz;
|
||||
seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
|
||||
cpu_khz / 1000, (cpu_khz % 1000));
|
||||
freq / 1000, (freq % 1000));
|
||||
}
|
||||
|
||||
/* Cache size */
|
||||
|
@ -117,14 +117,13 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
|
||||
{
|
||||
char __user *tmp = buf;
|
||||
u32 data[4];
|
||||
size_t rv;
|
||||
u32 reg = *ppos;
|
||||
int cpu = iminor(file->f_dentry->d_inode);
|
||||
|
||||
if (count % 16)
|
||||
return -EINVAL; /* Invalid chunk size */
|
||||
|
||||
for (rv = 0; count; count -= 16) {
|
||||
for (; count; count -= 16) {
|
||||
do_cpuid(cpu, reg, data);
|
||||
if (copy_to_user(tmp, &data, 16))
|
||||
return -EFAULT;
|
||||
|
@ -657,6 +657,7 @@ ENTRY(spurious_interrupt_bug)
|
||||
pushl $do_spurious_interrupt_bug
|
||||
jmp error_code
|
||||
|
||||
.section .rodata,"a"
|
||||
#include "syscall_table.S"
|
||||
|
||||
syscall_table_size=(.-sys_call_table)
|
||||
|
@ -504,19 +504,24 @@ ENTRY(cpu_gdt_table)
|
||||
.quad 0x0000000000000000 /* 0x80 TSS descriptor */
|
||||
.quad 0x0000000000000000 /* 0x88 LDT descriptor */
|
||||
|
||||
/* Segments used for calling PnP BIOS */
|
||||
.quad 0x00c09a0000000000 /* 0x90 32-bit code */
|
||||
.quad 0x00809a0000000000 /* 0x98 16-bit code */
|
||||
.quad 0x0080920000000000 /* 0xa0 16-bit data */
|
||||
.quad 0x0080920000000000 /* 0xa8 16-bit data */
|
||||
.quad 0x0080920000000000 /* 0xb0 16-bit data */
|
||||
/*
|
||||
* Segments used for calling PnP BIOS have byte granularity.
|
||||
* They code segments and data segments have fixed 64k limits,
|
||||
* the transfer segment sizes are set at run time.
|
||||
*/
|
||||
.quad 0x00409a000000ffff /* 0x90 32-bit code */
|
||||
.quad 0x00009a000000ffff /* 0x98 16-bit code */
|
||||
.quad 0x000092000000ffff /* 0xa0 16-bit data */
|
||||
.quad 0x0000920000000000 /* 0xa8 16-bit data */
|
||||
.quad 0x0000920000000000 /* 0xb0 16-bit data */
|
||||
|
||||
/*
|
||||
* The APM segments have byte granularity and their bases
|
||||
* and limits are set at run time.
|
||||
* are set at run time. All have 64k limits.
|
||||
*/
|
||||
.quad 0x00409a0000000000 /* 0xb8 APM CS code */
|
||||
.quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
|
||||
.quad 0x0040920000000000 /* 0xc8 APM DS data */
|
||||
.quad 0x00409a000000ffff /* 0xb8 APM CS code */
|
||||
.quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
|
||||
.quad 0x004092000000ffff /* 0xc8 APM DS data */
|
||||
|
||||
.quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
|
||||
.quad 0x0000000000000000 /* 0xd8 - unused */
|
||||
@ -525,3 +530,5 @@ ENTRY(cpu_gdt_table)
|
||||
.quad 0x0000000000000000 /* 0xf0 - unused */
|
||||
.quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
|
||||
|
||||
/* Be sure this is zeroed to avoid false validations in Xen */
|
||||
.fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
|
||||
|
@ -3,8 +3,7 @@
|
||||
#include <asm/checksum.h>
|
||||
#include <asm/desc.h>
|
||||
|
||||
/* This is definitely a GPL-only symbol */
|
||||
EXPORT_SYMBOL_GPL(cpu_gdt_table);
|
||||
EXPORT_SYMBOL_GPL(cpu_gdt_descr);
|
||||
|
||||
EXPORT_SYMBOL(__down_failed);
|
||||
EXPORT_SYMBOL(__down_failed_interruptible);
|
||||
|
@ -1722,8 +1722,8 @@ void disable_IO_APIC(void)
|
||||
entry.dest_mode = 0; /* Physical */
|
||||
entry.delivery_mode = dest_ExtINT; /* ExtInt */
|
||||
entry.vector = 0;
|
||||
entry.dest.physical.physical_dest = 0;
|
||||
|
||||
entry.dest.physical.physical_dest =
|
||||
GET_APIC_ID(apic_read(APIC_ID));
|
||||
|
||||
/*
|
||||
* Add it to the IO-APIC irq-routing table:
|
||||
|
@ -191,7 +191,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
|
||||
*/
|
||||
save_previous_kprobe(kcb);
|
||||
set_current_kprobe(p, regs, kcb);
|
||||
p->nmissed++;
|
||||
kprobes_inc_nmissed_count(p);
|
||||
prepare_singlestep(p, regs);
|
||||
kcb->kprobe_status = KPROBE_REENTER;
|
||||
return 1;
|
||||
|
@ -38,6 +38,12 @@
|
||||
int smp_found_config;
|
||||
unsigned int __initdata maxcpus = NR_CPUS;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
#define CPU_HOTPLUG_ENABLED (1)
|
||||
#else
|
||||
#define CPU_HOTPLUG_ENABLED (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Various Linux-internal data structures created from the
|
||||
* MP-table.
|
||||
@ -219,14 +225,18 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
|
||||
cpu_set(num_processors, cpu_possible_map);
|
||||
num_processors++;
|
||||
|
||||
if ((num_processors > 8) &&
|
||||
((APIC_XAPIC(ver) &&
|
||||
(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) ||
|
||||
(boot_cpu_data.x86_vendor == X86_VENDOR_AMD)))
|
||||
def_to_bigsmp = 1;
|
||||
else
|
||||
def_to_bigsmp = 0;
|
||||
|
||||
if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
|
||||
switch (boot_cpu_data.x86_vendor) {
|
||||
case X86_VENDOR_INTEL:
|
||||
if (!APIC_XAPIC(ver)) {
|
||||
def_to_bigsmp = 0;
|
||||
break;
|
||||
}
|
||||
/* If P4 and above fall through */
|
||||
case X86_VENDOR_AMD:
|
||||
def_to_bigsmp = 1;
|
||||
}
|
||||
}
|
||||
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
|
||||
}
|
||||
|
||||
|
@ -172,7 +172,6 @@ static ssize_t msr_read(struct file *file, char __user * buf,
|
||||
{
|
||||
u32 __user *tmp = (u32 __user *) buf;
|
||||
u32 data[2];
|
||||
size_t rv;
|
||||
u32 reg = *ppos;
|
||||
int cpu = iminor(file->f_dentry->d_inode);
|
||||
int err;
|
||||
@ -180,7 +179,7 @@ static ssize_t msr_read(struct file *file, char __user * buf,
|
||||
if (count % 8)
|
||||
return -EINVAL; /* Invalid chunk size */
|
||||
|
||||
for (rv = 0; count; count -= 8) {
|
||||
for (; count; count -= 8) {
|
||||
err = do_rdmsr(cpu, reg, &data[0], &data[1]);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -308,9 +308,7 @@ void show_regs(struct pt_regs * regs)
|
||||
cr0 = read_cr0();
|
||||
cr2 = read_cr2();
|
||||
cr3 = read_cr3();
|
||||
if (current_cpu_data.x86 > 4) {
|
||||
cr4 = read_cr4();
|
||||
}
|
||||
cr4 = read_cr4_safe();
|
||||
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
|
||||
show_trace(NULL, ®s->esp);
|
||||
}
|
||||
@ -404,17 +402,7 @@ void flush_thread(void)
|
||||
|
||||
void release_thread(struct task_struct *dead_task)
|
||||
{
|
||||
if (dead_task->mm) {
|
||||
// temporary debugging check
|
||||
if (dead_task->mm->context.size) {
|
||||
printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
|
||||
dead_task->comm,
|
||||
dead_task->mm->context.ldt,
|
||||
dead_task->mm->context.size);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
BUG_ON(dead_task->mm);
|
||||
release_vm86_irqs(dead_task);
|
||||
}
|
||||
|
||||
@ -554,7 +542,9 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
|
||||
struct pt_regs ptregs;
|
||||
|
||||
ptregs = *(struct pt_regs *)
|
||||
((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs));
|
||||
((unsigned long)tsk->thread_info +
|
||||
/* see comments in copy_thread() about -8 */
|
||||
THREAD_SIZE - sizeof(ptregs) - 8);
|
||||
ptregs.xcs &= 0xffff;
|
||||
ptregs.xds &= 0xffff;
|
||||
ptregs.xes &= 0xffff;
|
||||
|
@ -32,9 +32,12 @@
|
||||
* in exit.c or in signal.c.
|
||||
*/
|
||||
|
||||
/* determines which flags the user has access to. */
|
||||
/* 1 = access 0 = no access */
|
||||
#define FLAG_MASK 0x00044dd5
|
||||
/*
|
||||
* Determines which flags the user has access to [1 = access, 0 = no access].
|
||||
* Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
|
||||
* Also masks reserved bits (31-22, 15, 5, 3, 1).
|
||||
*/
|
||||
#define FLAG_MASK 0x00054dd5
|
||||
|
||||
/* set's the trap flag. */
|
||||
#define TRAP_FLAG 0x100
|
||||
|
@ -111,12 +111,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
|
||||
},
|
||||
},
|
||||
{ /* Handle problems with rebooting on HP nc6120 */
|
||||
{ /* Handle problems with rebooting on HP laptops */
|
||||
.callback = set_bios_reboot,
|
||||
.ident = "HP Compaq nc6120",
|
||||
.ident = "HP Compaq Laptop",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
|
@ -954,6 +954,12 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
|
||||
{
|
||||
memory_present(0, start, end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the highest page frame number we have available
|
||||
@ -965,6 +971,7 @@ void __init find_max_pfn(void)
|
||||
max_pfn = 0;
|
||||
if (efi_enabled) {
|
||||
efi_memmap_walk(efi_find_max_pfn, &max_pfn);
|
||||
efi_memmap_walk(efi_memory_present_wrapper, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -979,6 +986,7 @@ void __init find_max_pfn(void)
|
||||
continue;
|
||||
if (end > max_pfn)
|
||||
max_pfn = end;
|
||||
memory_present(0, start, end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,6 +903,12 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
|
||||
unsigned long start_eip;
|
||||
unsigned short nmi_high = 0, nmi_low = 0;
|
||||
|
||||
if (!cpu_gdt_descr[cpu].address &&
|
||||
!(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
|
||||
printk("Failed to allocate GDT for CPU %d\n", cpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
++cpucount;
|
||||
|
||||
/*
|
||||
@ -1338,8 +1344,7 @@ int __cpu_disable(void)
|
||||
if (cpu == 0)
|
||||
return -EBUSY;
|
||||
|
||||
/* We enable the timer again on the exit path of the death loop */
|
||||
disable_APIC_timer();
|
||||
clear_local_APIC();
|
||||
/* Allow any queued timer interrupts to get serviced */
|
||||
local_irq_enable();
|
||||
mdelay(1);
|
||||
|
@ -1,4 +1,3 @@
|
||||
.data
|
||||
ENTRY(sys_call_table)
|
||||
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
|
||||
.long sys_exit
|
||||
|
@ -330,7 +330,9 @@ int recalibrate_cpu_khz(void)
|
||||
unsigned int cpu_khz_old = cpu_khz;
|
||||
|
||||
if (cpu_has_tsc) {
|
||||
local_irq_disable();
|
||||
init_cpu_khz();
|
||||
local_irq_enable();
|
||||
cpu_data[0].loops_per_jiffy =
|
||||
cpufreq_scale(cpu_data[0].loops_per_jiffy,
|
||||
cpu_khz_old,
|
||||
|
@ -306,14 +306,17 @@ void die(const char * str, struct pt_regs * regs, long err)
|
||||
.lock_owner_depth = 0
|
||||
};
|
||||
static int die_counter;
|
||||
unsigned long flags;
|
||||
|
||||
if (die.lock_owner != raw_smp_processor_id()) {
|
||||
console_verbose();
|
||||
spin_lock_irq(&die.lock);
|
||||
spin_lock_irqsave(&die.lock, flags);
|
||||
die.lock_owner = smp_processor_id();
|
||||
die.lock_owner_depth = 0;
|
||||
bust_spinlocks(1);
|
||||
}
|
||||
else
|
||||
local_save_flags(flags);
|
||||
|
||||
if (++die.lock_owner_depth < 3) {
|
||||
int nl = 0;
|
||||
@ -340,7 +343,7 @@ void die(const char * str, struct pt_regs * regs, long err)
|
||||
|
||||
bust_spinlocks(0);
|
||||
die.lock_owner = -1;
|
||||
spin_unlock_irq(&die.lock);
|
||||
spin_unlock_irqrestore(&die.lock, flags);
|
||||
|
||||
if (kexec_should_crash(current))
|
||||
crash_kexec(regs);
|
||||
@ -452,7 +455,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
|
||||
#endif
|
||||
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
|
||||
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
|
||||
DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
|
||||
DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
|
||||
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
|
||||
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
|
||||
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
|
||||
@ -650,13 +653,6 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
|
||||
|
||||
cpu = smp_processor_id();
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
if (!cpu_online(cpu)) {
|
||||
nmi_exit();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
++nmi_count(cpu);
|
||||
|
||||
if (!rcu_dereference(nmi_callback)(regs, cpu))
|
||||
@ -1082,9 +1078,9 @@ void __init trap_init(void)
|
||||
set_trap_gate(0,÷_error);
|
||||
set_intr_gate(1,&debug);
|
||||
set_intr_gate(2,&nmi);
|
||||
set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
|
||||
set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
|
||||
set_system_gate(4,&overflow);
|
||||
set_system_gate(5,&bounds);
|
||||
set_trap_gate(5,&bounds);
|
||||
set_trap_gate(6,&invalid_op);
|
||||
set_trap_gate(7,&device_not_available);
|
||||
set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
|
||||
@ -1102,6 +1098,28 @@ void __init trap_init(void)
|
||||
#endif
|
||||
set_trap_gate(19,&simd_coprocessor_error);
|
||||
|
||||
if (cpu_has_fxsr) {
|
||||
/*
|
||||
* Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
|
||||
* Generates a compile-time "error: zero width for bit-field" if
|
||||
* the alignment is wrong.
|
||||
*/
|
||||
struct fxsrAlignAssert {
|
||||
int _:!(offsetof(struct task_struct,
|
||||
thread.i387.fxsave) & 15);
|
||||
};
|
||||
|
||||
printk(KERN_INFO "Enabling fast FPU save and restore... ");
|
||||
set_in_cr4(X86_CR4_OSFXSR);
|
||||
printk("done.\n");
|
||||
}
|
||||
if (cpu_has_xmm) {
|
||||
printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
|
||||
"support... ");
|
||||
set_in_cr4(X86_CR4_OSXMMEXCPT);
|
||||
printk("done.\n");
|
||||
}
|
||||
|
||||
set_system_gate(SYSCALL_VECTOR,&system_call);
|
||||
|
||||
/*
|
||||
|
@ -735,6 +735,30 @@ void free_initmem(void)
|
||||
printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_RODATA
|
||||
|
||||
extern char __start_rodata, __end_rodata;
|
||||
void mark_rodata_ro(void)
|
||||
{
|
||||
unsigned long addr = (unsigned long)&__start_rodata;
|
||||
|
||||
for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE)
|
||||
change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO);
|
||||
|
||||
printk ("Write protecting the kernel read-only data: %luk\n",
|
||||
(unsigned long)(&__end_rodata - &__start_rodata) >> 10);
|
||||
|
||||
/*
|
||||
* change_page_attr() requires a global_flush_tlb() call after it.
|
||||
* We do this after the printk so that if something went wrong in the
|
||||
* change, the printk gets out at least to give a better debug hint
|
||||
* of who is the culprit.
|
||||
*/
|
||||
global_flush_tlb();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
|
@ -223,9 +223,15 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
|
||||
}
|
||||
EXPORT_SYMBOL(ioremap_nocache);
|
||||
|
||||
/**
|
||||
* iounmap - Free a IO remapping
|
||||
* @addr: virtual address from ioremap_*
|
||||
*
|
||||
* Caller must ensure there is only one unmapping for the same pointer.
|
||||
*/
|
||||
void iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
struct vm_struct *p;
|
||||
struct vm_struct *p, *o;
|
||||
|
||||
if ((void __force *)addr <= high_memory)
|
||||
return;
|
||||
@ -239,22 +245,37 @@ void iounmap(volatile void __iomem *addr)
|
||||
addr < phys_to_virt(ISA_END_ADDRESS))
|
||||
return;
|
||||
|
||||
write_lock(&vmlist_lock);
|
||||
p = __remove_vm_area((void *)(PAGE_MASK & (unsigned long __force)addr));
|
||||
if (!p) {
|
||||
printk(KERN_WARNING "iounmap: bad address %p\n", addr);
|
||||
addr = (volatile void __iomem *)(PAGE_MASK & (unsigned long __force)addr);
|
||||
|
||||
/* Use the vm area unlocked, assuming the caller
|
||||
ensures there isn't another iounmap for the same address
|
||||
in parallel. Reuse of the virtual address is prevented by
|
||||
leaving it in the global lists until we're done with it.
|
||||
cpa takes care of the direct mappings. */
|
||||
read_lock(&vmlist_lock);
|
||||
for (p = vmlist; p; p = p->next) {
|
||||
if (p->addr == addr)
|
||||
break;
|
||||
}
|
||||
read_unlock(&vmlist_lock);
|
||||
|
||||
if (!p) {
|
||||
printk("iounmap: bad address %p\n", addr);
|
||||
dump_stack();
|
||||
goto out_unlock;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset the direct mapping. Can block */
|
||||
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
|
||||
change_page_attr(virt_to_page(__va(p->phys_addr)),
|
||||
p->size >> PAGE_SHIFT,
|
||||
PAGE_KERNEL);
|
||||
global_flush_tlb();
|
||||
}
|
||||
out_unlock:
|
||||
write_unlock(&vmlist_lock);
|
||||
|
||||
/* Finally remove it */
|
||||
o = remove_vm_area((void *)addr);
|
||||
BUG_ON(p != o || o == NULL);
|
||||
kfree(p);
|
||||
}
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
static DEFINE_SPINLOCK(cpa_lock);
|
||||
static struct list_head df_list = LIST_HEAD_INIT(df_list);
|
||||
@ -36,7 +37,8 @@ pte_t *lookup_address(unsigned long address)
|
||||
return pte_offset_kernel(pmd, address);
|
||||
}
|
||||
|
||||
static struct page *split_large_page(unsigned long address, pgprot_t prot)
|
||||
static struct page *split_large_page(unsigned long address, pgprot_t prot,
|
||||
pgprot_t ref_prot)
|
||||
{
|
||||
int i;
|
||||
unsigned long addr;
|
||||
@ -54,7 +56,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot)
|
||||
pbase = (pte_t *)page_address(base);
|
||||
for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
|
||||
set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT,
|
||||
addr == address ? prot : PAGE_KERNEL));
|
||||
addr == address ? prot : ref_prot));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
@ -98,11 +100,18 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
|
||||
*/
|
||||
static inline void revert_page(struct page *kpte_page, unsigned long address)
|
||||
{
|
||||
pte_t *linear = (pte_t *)
|
||||
pgprot_t ref_prot;
|
||||
pte_t *linear;
|
||||
|
||||
ref_prot =
|
||||
((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
|
||||
? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE;
|
||||
|
||||
linear = (pte_t *)
|
||||
pmd_offset(pud_offset(pgd_offset_k(address), address), address);
|
||||
set_pmd_pte(linear, address,
|
||||
pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT,
|
||||
PAGE_KERNEL_LARGE));
|
||||
ref_prot));
|
||||
}
|
||||
|
||||
static int
|
||||
@ -123,10 +132,16 @@ __change_page_attr(struct page *page, pgprot_t prot)
|
||||
if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
|
||||
set_pte_atomic(kpte, mk_pte(page, prot));
|
||||
} else {
|
||||
struct page *split = split_large_page(address, prot);
|
||||
pgprot_t ref_prot;
|
||||
struct page *split;
|
||||
|
||||
ref_prot =
|
||||
((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
|
||||
? PAGE_KERNEL_EXEC : PAGE_KERNEL;
|
||||
split = split_large_page(address, prot, ref_prot);
|
||||
if (!split)
|
||||
return -ENOMEM;
|
||||
set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL));
|
||||
set_pmd_pte(kpte,address,mk_pte(split, ref_prot));
|
||||
kpte_page = split;
|
||||
}
|
||||
get_page(kpte_page);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user