aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-31 16:06:50 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-03-31 16:06:50 -0800
commitf6ea76c0dc98f2a9219ee5327a2d3a00dfb7e89b (patch)
treec7c6360b40213958ee55fff48cc16c506357ce5d
parent54356933c64d5f26e15c040d6bb81e8d2d616555 (diff)
parent63b61eadc2c4fd8ef6932e3a31370927b2e4951f (diff)
downloadhistory-f6ea76c0dc98f2a9219ee5327a2d3a00dfb7e89b.tar.gz
Merge bk://kernel.bkbits.net/davem/net-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
-rw-r--r--Documentation/i2c/busses/i2c-ali153542
-rw-r--r--Documentation/i2c/busses/i2c-ali156327
-rw-r--r--Documentation/i2c/busses/i2c-ali15x3112
-rw-r--r--Documentation/i2c/busses/i2c-amd75625
-rw-r--r--Documentation/i2c/busses/i2c-amd811141
-rw-r--r--Documentation/i2c/busses/i2c-i80180
-rw-r--r--Documentation/i2c/busses/i2c-i81046
-rw-r--r--Documentation/i2c/busses/i2c-nforce241
-rw-r--r--Documentation/i2c/busses/i2c-parport (renamed from Documentation/i2c/i2c-parport)18
-rw-r--r--Documentation/i2c/busses/i2c-parport-light11
-rw-r--r--Documentation/i2c/busses/i2c-pca-isa23
-rw-r--r--Documentation/i2c/busses/i2c-piix472
-rw-r--r--Documentation/i2c/busses/i2c-prosavage23
-rw-r--r--Documentation/i2c/busses/i2c-savage426
-rw-r--r--Documentation/i2c/busses/i2c-sis559559
-rw-r--r--Documentation/i2c/busses/i2c-sis63049
-rw-r--r--Documentation/i2c/busses/i2c-sis69x73
-rw-r--r--Documentation/i2c/busses/i2c-via34
-rw-r--r--Documentation/i2c/busses/i2c-viapro47
-rw-r--r--Documentation/i2c/busses/i2c-voodoo362
-rw-r--r--Documentation/i2c/busses/scx200_acb14
-rw-r--r--arch/i386/kernel/acpi/sleep.c3
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/ia64/kernel/acpi.c2
-rw-r--r--arch/ia64/kernel/iosapic.c9
-rw-r--r--arch/ia64/kernel/ivt.S3
-rw-r--r--arch/ia64/kernel/minstate.h2
-rw-r--r--arch/ia64/kernel/setup.c9
-rw-r--r--arch/ia64/kernel/unaligned.c16
-rw-r--r--arch/ia64/pci/pci.c134
-rw-r--r--arch/ia64/sn/kernel/setup.c28
-rw-r--r--drivers/acpi/Kconfig20
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c18
-rw-r--r--drivers/acpi/acpi_memhotplug.c542
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/button.c4
-rw-r--r--drivers/acpi/container.c15
-rw-r--r--drivers/acpi/debug.c4
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c11
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c8
-rw-r--r--drivers/acpi/dispatcher/dsutils.c166
-rw-r--r--drivers/acpi/dispatcher/dswexec.c61
-rw-r--r--drivers/acpi/ec.c2
-rw-r--r--drivers/acpi/events/evxface.c4
-rw-r--r--drivers/acpi/executer/exmisc.c5
-rw-r--r--drivers/acpi/executer/exoparg2.c6
-rw-r--r--drivers/acpi/executer/exresolv.c6
-rw-r--r--drivers/acpi/executer/exstoren.c7
-rw-r--r--drivers/acpi/executer/exstorob.c27
-rw-r--r--drivers/acpi/fan.c33
-rw-r--r--drivers/acpi/ibm_acpi.c4
-rw-r--r--drivers/acpi/numa.c2
-rw-r--r--drivers/acpi/osl.c10
-rw-r--r--drivers/acpi/parser/psopcode.c2
-rw-r--r--drivers/acpi/parser/psparse.c42
-rw-r--r--drivers/acpi/parser/pswalk.c254
-rw-r--r--drivers/acpi/pci_irq.c38
-rw-r--r--drivers/acpi/pci_link.c14
-rw-r--r--drivers/acpi/pci_root.c4
-rw-r--r--drivers/acpi/power.c10
-rw-r--r--drivers/acpi/processor_core.c6
-rw-r--r--drivers/acpi/processor_thermal.c2
-rw-r--r--drivers/acpi/processor_throttling.c2
-rw-r--r--drivers/acpi/resources/rsaddr.c146
-rw-r--r--drivers/acpi/resources/rscalc.c14
-rw-r--r--drivers/acpi/resources/rsdump.c23
-rw-r--r--drivers/acpi/resources/rslist.c1
-rw-r--r--drivers/acpi/scan.c47
-rw-r--r--drivers/acpi/thermal.c2
-rw-r--r--drivers/acpi/toshiba_acpi.c2
-rw-r--r--drivers/acpi/utilities/utcopy.c19
-rw-r--r--drivers/acpi/utilities/utdelete.c18
-rw-r--r--drivers/acpi/utilities/utglobal.c10
-rw-r--r--drivers/acpi/utilities/utmisc.c44
-rw-r--r--drivers/acpi/video.c2
-rw-r--r--drivers/i2c/algos/i2c-algo-ite.c13
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c44
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c13
-rw-r--r--drivers/i2c/busses/Kconfig38
-rw-r--r--drivers/i2c/busses/i2c-elektor.c9
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c4
-rw-r--r--drivers/i2c/busses/i2c-ite.c7
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c2
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c15
-rw-r--r--drivers/i2c/busses/i2c-viapro.c17
-rw-r--r--drivers/i2c/chips/Kconfig25
-rw-r--r--drivers/i2c/chips/Makefile2
-rw-r--r--drivers/i2c/chips/adm1021.c14
-rw-r--r--drivers/i2c/chips/ds1337.c402
-rw-r--r--drivers/i2c/chips/eeprom.c3
-rw-r--r--drivers/i2c/chips/it87.c10
-rw-r--r--drivers/i2c/chips/lm85.c104
-rw-r--r--drivers/i2c/chips/lm87.c20
-rw-r--r--drivers/i2c/chips/lm90.c44
-rw-r--r--drivers/i2c/chips/lm92.c423
-rw-r--r--drivers/i2c/chips/m41t00.c1
-rw-r--r--drivers/i2c/chips/w83627hf.c5
-rw-r--r--drivers/i2c/chips/w83781d.c100
-rw-r--r--drivers/i2c/i2c-core.c10
-rw-r--r--drivers/pci/msi.c4
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c9
-rw-r--r--include/acpi/acconfig.h4
-rw-r--r--include/acpi/acdisasm.h5
-rw-r--r--include/acpi/acdispat.h10
-rw-r--r--include/acpi/acinterp.h1
-rw-r--r--include/acpi/aclocal.h4
-rw-r--r--include/acpi/acpi_bus.h1
-rw-r--r--include/acpi/acpi_drivers.h3
-rw-r--r--include/acpi/acstruct.h1
-rw-r--r--include/acpi/actbl.h4
-rw-r--r--include/acpi/actbl2.h79
-rw-r--r--include/acpi/actypes.h39
-rw-r--r--include/acpi/platform/acenv.h2
-rw-r--r--include/acpi/processor.h2
-rw-r--r--include/asm-ia64/smp.h45
-rw-r--r--include/asm-ia64/sn/addrs.h7
-rw-r--r--include/asm-ia64/sn/arch.h24
-rw-r--r--include/asm-ia64/sn/pda.h15
-rw-r--r--include/asm-ia64/sn/sn_cpuid.h5
-rw-r--r--include/asm-ia64/sn/sn_sal.h50
-rw-r--r--include/linux/acpi.h2
-rw-r--r--include/linux/i2c.h13
-rw-r--r--net/bluetooth/sco.c2
124 files changed, 3542 insertions, 906 deletions
diff --git a/Documentation/i2c/busses/i2c-ali1535 b/Documentation/i2c/busses/i2c-ali1535
new file mode 100644
index 00000000000000..0db3b4c74ad111
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ali1535
@@ -0,0 +1,42 @@
+Kernel driver i2c-ali1535
+
+Supported adapters:
+ * Acer Labs, Inc. ALI 1535 (south bridge)
+ Datasheet: Now under NDA
+ http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ Dan Eaton <dan.eaton@rocketlogix.com>,
+ Stephen Rousset<stephen.rousset@rocketlogix.com>
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1535 South Bridge.
+
+The M1535 is a South bridge for portable systems. It is very similar to the
+M15x3 South bridges also produced by Acer Labs Inc. Some of the registers
+within the part have moved and some have been redefined slightly.
+Additionally, the sequencing of the SMBus transactions has been modified to
+be more consistent with the sequencing recommended by the manufacturer and
+observed through testing. These changes are reflected in this driver and
+can be identified by comparing this driver to the i2c-ali15x3 driver. For
+an overview of these chips see http://www.acerlabs.com
+
+The SMB controller is part of the M7101 device, which is an ACPI-compliant
+Power Management Unit (PMU).
+
+The whole M7101 device has to be enabled for the SMB to work. You can't
+just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
+We make sure that the SMB is enabled. We leave the ACPI alone.
+
+
+Features
+--------
+
+This driver controls the SMB Host only. This driver does not use
+interrupts.
diff --git a/Documentation/i2c/busses/i2c-ali1563 b/Documentation/i2c/busses/i2c-ali1563
new file mode 100644
index 00000000000000..99ad4b9bcc32ec
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ali1563
@@ -0,0 +1,27 @@
+Kernel driver i2c-ali1563
+
+Supported adapters:
+ * Acer Labs, Inc. ALI 1563 (south bridge)
+ Datasheet: Now under NDA
+ http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Author: Patrick Mochel <mochel@digitalimplant.org>
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1563 South Bridge.
+
+For an overview of these chips see http://www.acerlabs.com
+
+The M1563 southbridge is deceptively similar to the M1533, with a few
+notable exceptions. One of those happens to be the fact they upgraded the
+i2c core to be SMBus 2.0 compliant, and happens to be almost identical to
+the i2c controller found in the Intel 801 south bridges.
+
+Features
+--------
+
+This driver controls the SMB Host only. This driver does not use
+interrupts.
diff --git a/Documentation/i2c/busses/i2c-ali15x3 b/Documentation/i2c/busses/i2c-ali15x3
new file mode 100644
index 00000000000000..ff28d381bebe8d
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ali15x3
@@ -0,0 +1,112 @@
+Kernel driver i2c-ali15x3
+
+Supported adapters:
+ * Acer Labs, Inc. ALI 1533 and 1543C (south bridge)
+ Datasheet: Now under NDA
+ http://www.ali.com.tw/eng/support/datasheet_request.php
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Module Parameters
+-----------------
+
+* force_addr: int
+ Initialize the base address of the i2c controller
+
+
+Notes
+-----
+
+The force_addr parameter is useful for boards that don't set the address in
+the BIOS. Does not do a PCI force; the device must still be present in
+lspci. Don't use this unless the driver complains that the base address is
+not set.
+
+Example: 'modprobe i2c-ali15x3 force_addr=0xe800'
+
+SMBus periodically hangs on ASUS P5A motherboards and can only be cleared
+by a power cycle. Cause unknown (see Issues below).
+
+
+Description
+-----------
+
+This is the driver for the SMB Host controller on Acer Labs Inc. (ALI)
+M1541 and M1543C South Bridges.
+
+The M1543C is a South bridge for desktop systems.
+The M1541 is a South bridge for portable systems.
+They are part of the following ALI chipsets:
+
+ * "Aladdin Pro 2" includes the M1621 Slot 1 North bridge with AGP and
+ 100MHz CPU Front Side bus
+ * "Aladdin V" includes the M1541 Socket 7 North bridge with AGP and 100MHz
+ CPU Front Side bus
+ Some Aladdin V motherboards:
+ Asus P5A
+ Atrend ATC-5220
+ BCM/GVC VP1541
+ Biostar M5ALA
+ Gigabyte GA-5AX (** Generally doesn't work because the BIOS doesn't
+ enable the 7101 device! **)
+ Iwill XA100 Plus
+ Micronics C200
+ Microstar (MSI) MS-5169
+
+ * "Aladdin IV" includes the M1541 Socket 7 North bridge
+ with host bus up to 83.3 MHz.
+
+For an overview of these chips see http://www.acerlabs.com. At this time the
+full data sheets on the web site are password protected, however if you
+contact the ALI office in San Jose they may give you the password.
+
+The M1533/M1543C devices appear as FOUR separate devices on the PCI bus. An
+output of lspci will show something similar to the following:
+
+ 00:02.0 USB Controller: Acer Laboratories Inc. M5237 (rev 03)
+ 00:03.0 Bridge: Acer Laboratories Inc. M7101 <= THIS IS THE ONE WE NEED
+ 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 (rev c3)
+ 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 (rev c1)
+
+** IMPORTANT **
+** If you have a M1533 or M1543C on the board and you get
+** "ali15x3: Error: Can't detect ali15x3!"
+** then run lspci.
+** If you see the 1533 and 5229 devices but NOT the 7101 device,
+** then you must enable ACPI, the PMU, SMB, or something similar
+** in the BIOS.
+** The driver won't work if it can't find the M7101 device.
+
+The SMB controller is part of the M7101 device, which is an ACPI-compliant
+Power Management Unit (PMU).
+
+The whole M7101 device has to be enabled for the SMB to work. You can't
+just enable the SMB alone. The SMB and the ACPI have separate I/O spaces.
+We make sure that the SMB is enabled. We leave the ACPI alone.
+
+Features
+--------
+
+This driver controls the SMB Host only. The SMB Slave
+controller on the M15X3 is not enabled. This driver does not use
+interrupts.
+
+
+Issues
+------
+
+This driver requests the I/O space for only the SMB
+registers. It doesn't use the ACPI region.
+
+On the ASUS P5A motherboard, there are several reports that
+the SMBus will hang and this can only be resolved by
+powering off the computer. It appears to be worse when the board
+gets hot, for example under heavy CPU load, or in the summer.
+There may be electrical problems on this board.
+On the P5A, the W83781D sensor chip is on both the ISA and
+SMBus. Therefore the SMBus hangs can generally be avoided
+by accessing the W83781D on the ISA bus only.
+
diff --git a/Documentation/i2c/busses/i2c-amd756 b/Documentation/i2c/busses/i2c-amd756
new file mode 100644
index 00000000000000..67f30874d0bfbd
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-amd756
@@ -0,0 +1,25 @@
+Kernel driver i2c-amd756
+
+Supported adapters:
+ * AMD 756
+ * AMD 766
+ * AMD 768
+ * AMD 8111
+ Datasheets: Publicly available on AMD website
+
+ * nVidia nForce
+ Datasheet: Unavailable
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver supports the AMD 756, 766, 768 and 8111 Peripheral Bus
+Controllers, and the nVidia nForce.
+
+Note that for the 8111, there are two SMBus adapters. The SMBus 1.0 adapter
+is supported by this driver, and the SMBus 2.0 adapter is supported by the
+i2c-amd8111 driver.
diff --git a/Documentation/i2c/busses/i2c-amd8111 b/Documentation/i2c/busses/i2c-amd8111
new file mode 100644
index 00000000000000..db294ee7455a44
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-amd8111
@@ -0,0 +1,41 @@
+Kernel driver i2c-adm8111
+
+Supported adapters:
+ * AMD-8111 SMBus 2.0 PCI interface
+
+Datasheets:
+ AMD datasheet not yet available, but almost everything can be found
+ in publically available ACPI 2.0 specification, which the adapter
+ follows.
+
+Author: Vojtech Pavlik <vojtech@suse.cz>
+
+Description
+-----------
+
+If you see something like this:
+
+00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02)
+ Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0
+ Flags: medium devsel, IRQ 19
+ I/O ports at d400 [size=32]
+
+in your 'lspci -v', then this driver is for your chipset.
+
+Process Call Support
+--------------------
+
+Supported.
+
+SMBus 2.0 Support
+-----------------
+
+Supported. Both PEC and block process call support is implemented. Slave
+mode or host notification are not yet implemented.
+
+Notes
+-----
+
+Note that for the 8111, there are two SMBus adapters. The SMBus 2.0 adapter
+is supported by this driver, and the SMBus 1.0 adapter is supported by the
+i2c-amd756 driver.
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
new file mode 100644
index 00000000000000..fd4b2712d570a9
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-i801
@@ -0,0 +1,80 @@
+Kernel driver i2c-i801
+
+Supported adapters:
+ * Intel 82801AA and 82801AB (ICH and ICH0 - part of the
+ '810' and '810E' chipsets)
+ * Intel 82801BA (ICH2 - part of the '815E' chipset)
+ * Intel 82801CA/CAM (ICH3)
+ * Intel 82801DB (ICH4) (HW PEC supported, 32 byte buffer not supported)
+ * Intel 82801EB/ER (ICH5) (HW PEC supported, 32 byte buffer not supported)
+ * Intel 6300ESB
+ * Intel 82801FB/FR/FW/FRW (ICH6)
+ * Intel ICH7
+ Datasheets: Publicly available at the Intel website
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark Studebaker <mdsxyz123@yahoo.com>
+
+
+Module Parameters
+-----------------
+
+* force_addr: int
+ Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS!
+
+
+Description
+-----------
+
+The ICH (properly known as the 82801AA), ICH0 (82801AB), ICH2 (82801BA),
+ICH3 (82801CA/CAM) and later devices are Intel chips that are a part of
+Intel's '810' chipset for Celeron-based PCs, '810E' chipset for
+Pentium-based PCs, '815E' chipset, and others.
+
+The ICH chips contain at least SEVEN separate PCI functions in TWO logical
+PCI devices. An output of lspci will show something similar to the
+following:
+
+ 00:1e.0 PCI bridge: Intel Corporation: Unknown device 2418 (rev 01)
+ 00:1f.0 ISA bridge: Intel Corporation: Unknown device 2410 (rev 01)
+ 00:1f.1 IDE interface: Intel Corporation: Unknown device 2411 (rev 01)
+ 00:1f.2 USB Controller: Intel Corporation: Unknown device 2412 (rev 01)
+ 00:1f.3 Unknown class [0c05]: Intel Corporation: Unknown device 2413 (rev 01)
+
+The SMBus controller is function 3 in device 1f. Class 0c05 is SMBus Serial
+Controller.
+
+If you do NOT see the 24x3 device at function 3, and you can't figure out
+any way in the BIOS to enable it,
+
+The ICH chips are quite similar to Intel's PIIX4 chip, at least in the
+SMBus controller.
+
+See the file i2c-piix4 for some additional information.
+
+
+Process Call Support
+--------------------
+
+Not supported.
+
+
+I2C Block Read Support
+----------------------
+
+Not supported at the moment.
+
+
+SMBus 2.0 Support
+-----------------
+
+The 82801DB (ICH4) and later chips support several SMBus 2.0 features.
+
+**********************
+The lm_sensors project gratefully acknowledges the support of Texas
+Instruments in the initial development of this driver.
+
+The lm_sensors project gratefully acknowledges the support of Intel in the
+development of SMBus 2.0 / ICH4 features of this driver.
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
new file mode 100644
index 00000000000000..0544eb3328879c
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-i810
@@ -0,0 +1,46 @@
+Kernel driver i2c-i810
+
+Supported adapters:
+ * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Ralph Metzler <rjkm@thp.uni-koeln.de>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Main contact: Mark Studebaker <mdsxyz123@yahoo.com>
+
+Description
+-----------
+
+WARNING: If you have an '810' or '815' motherboard, your standard I2C
+temperature sensors are most likely on the 801's I2C bus. You want the
+i2c-i801 driver for those, not this driver.
+
+Now for the i2c-i810...
+
+The GMCH chip contains two I2C interfaces.
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org .
+
+The second interface is a general-purpose I2C bus. It may be connected to a
+TV-out chip such as the BT869 or possibly to a digital flat-panel display.
+
+Features
+--------
+
+Both busses use the i2c-algo-bit driver for 'bit banging'
+and support for specific transactions is provided by i2c-algo-bit.
+
+Issues
+------
+
+If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1),
+the test may fail; if so, the i2c-i810 driver won't be inserted. However,
+we think this has been fixed.
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
new file mode 100644
index 00000000000000..e379e182e64f4f
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -0,0 +1,41 @@
+Kernel driver i2c-nforce2
+
+Supported adapters:
+ * nForce2 MCP 10de:0064
+ * nForce2 Ultra 400 MCP 10de:0084
+ * nForce3 Pro150 MCP 10de:00D4
+ * nForce3 250Gb MCP 10de:00E4
+ * nForce4 MCP 10de:0052
+
+Datasheet: not publically available, but seems to be similar to the
+ AMD-8111 SMBus 2.0 adapter.
+
+Authors:
+ Hans-Frieder Vogt <hfvogt@arcor.de>,
+ Thomas Leibold <thomas@plx.com>,
+ Patrick Dreker <patrick@dreker.de>
+
+Description
+-----------
+
+i2c-nforce2 is a driver for the SMBuses included in the nVidia nForce2 MCP.
+
+If your 'lspci -v' listing shows something like the following,
+
+00:01.1 SMBus: nVidia Corporation: Unknown device 0064 (rev a2)
+ Subsystem: Asustek Computer, Inc.: Unknown device 0c11
+ Flags: 66Mhz, fast devsel, IRQ 5
+ I/O ports at c000 [size=32]
+ Capabilities: <available only to root>
+
+then this driver should support the SMBuses of your motherboard.
+
+
+Notes
+-----
+
+The SMBus adapter in the nForce2 chipset seems to be very similar to the
+SMBus 2.0 adapter in the AMD-8111 southbridge. However, I could only get
+the driver to work with direct I/O access, which is different to the EC
+interface of the AMD-8111. Tested on Asus A7N8X. The ACPI DSDT table of the
+Asus A7N8X lists two SMBuses, both of which are supported by this driver.
diff --git a/Documentation/i2c/i2c-parport b/Documentation/i2c/busses/i2c-parport
index d359461ce9b239..9f1d0082da18b4 100644
--- a/Documentation/i2c/i2c-parport
+++ b/Documentation/i2c/busses/i2c-parport
@@ -1,8 +1,6 @@
-==================
-i2c-parport driver
-==================
+Kernel driver i2c-parport
-2004-07-06, Jean Delvare
+Author: Jean Delvare <khali@linux-fr.org>
This is a unified driver for several i2c-over-parallel-port adapters,
such as the ones made by Philips, Velleman or ELV. This driver is
@@ -126,14 +124,14 @@ adapters do, so you won't even have to change the code.
Similar (but different) drivers
-------------------------------
-This driver is NOT the same as the i2c-pport driver found in the i2c package.
-The i2c-pport driver makes use of modern parallel port features so that
-you don't need additional electronics. It has other restrictions however, and
-was not ported to Linux 2.6 (yet).
+This driver is NOT the same as the i2c-pport driver found in the i2c
+package. The i2c-pport driver makes use of modern parallel port features so
+that you don't need additional electronics. It has other restrictions
+however, and was not ported to Linux 2.6 (yet).
This driver is also NOT the same as the i2c-pcf-epp driver found in the
-lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port
-as an I2C bus directly. Instead, it uses it to control an external I2C bus
+lm_sensors package. The i2c-pcf-epp driver doesn't use the parallel port as
+an I2C bus directly. Instead, it uses it to control an external I2C bus
master. That driver was not ported to Linux 2.6 (yet) either.
diff --git a/Documentation/i2c/busses/i2c-parport-light b/Documentation/i2c/busses/i2c-parport-light
new file mode 100644
index 00000000000000..287436478520a0
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-parport-light
@@ -0,0 +1,11 @@
+Kernel driver i2c-parport-light
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+This driver is a light version of i2c-parport. It doesn't depend
+on the parport driver, and uses direct I/O access instead. This might be
+prefered on embedded systems where wasting memory for the clean but heavy
+parport handling is not an option. The drawback is a reduced portability
+and the impossibility to daisy-chain other parallel port devices.
+
+Please see i2c-parport for documentation.
diff --git a/Documentation/i2c/busses/i2c-pca-isa b/Documentation/i2c/busses/i2c-pca-isa
new file mode 100644
index 00000000000000..6fc8f4c27c3ce5
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-pca-isa
@@ -0,0 +1,23 @@
+Kernel driver i2c-pca-isa
+
+Supported adapters:
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
+
+Author: Ian Campbell <icampbell@arcom.com>, Arcom Control Systems
+
+Module Parameters
+-----------------
+
+* base int
+ I/O base address
+* irq int
+ IRQ interrupt
+* clock int
+ Clock rate as described in table 1 of PCA9564 datasheet
+
+Description
+-----------
+
+This driver supports ISA boards using the Philips PCA 9564
+Parallel bus to I2C bus controller
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
new file mode 100644
index 00000000000000..856b4b8b962ccc
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -0,0 +1,72 @@
+Kernel driver i2c-piix4
+
+Supported adapters:
+ * Intel 82371AB PIIX4 and PIIX4E
+ * Intel 82443MX (440MX)
+ Datasheet: Publicly available at the Intel website
+ * ServerWorks OSB4, CSB5 and CSB6 southbridges
+ Datasheet: Only available via NDA from ServerWorks
+ * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
+ Datasheet: Publicly available at the SMSC website http://www.smsc.com
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>
+ Philip Edelbrock <phil@netroedge.com>
+
+
+Module Parameters
+-----------------
+
+* force: int
+ Forcibly enable the PIIX4. DANGEROUS!
+* force_addr: int
+ Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS!
+* fix_hstcfg: int
+ Fix config register. Needed on some boards (Force CPCI735).
+
+
+Description
+-----------
+
+The PIIX4 (properly known as the 82371AB) is an Intel chip with a lot of
+functionality. Among other things, it implements the PCI bus. One of its
+minor functions is implementing a System Management Bus. This is a true
+SMBus - you can not access it on I2C levels. The good news is that it
+natively understands SMBus commands and you do not have to worry about
+timing problems. The bad news is that non-SMBus devices connected to it can
+confuse it mightily. Yes, this is known to happen...
+
+Do 'lspci -v' and see whether it contains an entry like this:
+
+0000:00:02.3 Bridge: Intel Corp. 82371AB/EB/MB PIIX4 ACPI (rev 02)
+ Flags: medium devsel, IRQ 9
+
+Bus and device numbers may differ, but the function number must be
+identical (like many PCI devices, the PIIX4 incorporates a number of
+different 'functions', which can be considered as separate devices). If you
+find such an entry, you have a PIIX4 SMBus controller.
+
+On some computers (most notably, some Dells), the SMBus is disabled by
+default. If you use the insmod parameter 'force=1', the kernel module will
+try to enable it. THIS IS VERY DANGEROUS! If the BIOS did not set up a
+correct address for this module, you could get in big trouble (read:
+crashes, data corruption, etc.). Try this only as a last resort (try BIOS
+updates first, for example), and backup first! An even more dangerous
+option is 'force_addr=<IOPORT>'. This will not only enable the PIIX4 like
+'force' foes, but it will also set a new base I/O port address. The SMBus
+parts of the PIIX4 needs a range of 8 of these addresses to function
+correctly. If these addresses are already reserved by some other device,
+you will get into big trouble! DON'T USE THIS IF YOU ARE NOT VERY SURE
+ABOUT WHAT YOU ARE DOING!
+
+The PIIX4E is just an new version of the PIIX4; it is supported as well.
+The PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use
+this driver on those mainboards.
+
+The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are
+identical to the PIIX4 in I2C/SMBus support.
+
+A few OSB4 southbridges are known to be misconfigured by the BIOS. In this
+case, you have you use the fix_hstcfg module parameter. Do not use it
+unless you know you have to, because in some cases it also breaks
+configuration on southbridges that don't need it.
diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage
new file mode 100644
index 00000000000000..7036879025110f
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-prosavage
@@ -0,0 +1,23 @@
+Kernel driver i2c-prosavage
+
+Supported adapters:
+
+ S3/VIA KM266/VT8375 aka ProSavage8
+ S3/VIA KM133/VT8365 aka Savage4
+
+Author: Henk Vergonet <henk@god.dyndns.org>
+
+Description
+-----------
+
+The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or
+'host').
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org . The second interface is a general-purpose I2C bus.
+
+Usefull for gaining access to the TV Encoder chips.
+
diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4
new file mode 100644
index 00000000000000..6ecceab618d397
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-savage4
@@ -0,0 +1,26 @@
+Kernel driver i2c-savage4
+
+Supported adapters:
+ * Savage4
+ * Savage2000
+
+Authors:
+ Alexander Wold <awold@bigfoot.com>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Description
+-----------
+
+The Savage4 chips contain two I2C interfaces (aka a I2C 'master'
+or 'host').
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org . The DDC bus is not yet supported because its register
+is not directly memory-mapped.
+
+The second interface is a general-purpose I2C bus. This is the only
+interface supported by the driver at the moment.
+
diff --git a/Documentation/i2c/busses/i2c-sis5595 b/Documentation/i2c/busses/i2c-sis5595
new file mode 100644
index 00000000000000..cc47db7d00a989
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-sis5595
@@ -0,0 +1,59 @@
+Kernel driver i2c-sis5595
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Supported adapters:
+ * Silicon Integrated Systems Corp. SiS5595 Southbridge
+ Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
+
+Note: all have mfr. ID 0x1039.
+
+ SUPPORTED PCI ID
+ 5595 0008
+
+ Note: these chips contain a 0008 device which is incompatible with the
+ 5595. We recognize these by the presence of the listed
+ "blacklist" PCI ID and refuse to load.
+
+ NOT SUPPORTED PCI ID BLACKLIST PCI ID
+ 540 0008 0540
+ 550 0008 0550
+ 5513 0008 5511
+ 5581 0008 5597
+ 5582 0008 5597
+ 5597 0008 5597
+ 5598 0008 5597/5598
+ 630 0008 0630
+ 645 0008 0645
+ 646 0008 0646
+ 648 0008 0648
+ 650 0008 0650
+ 651 0008 0651
+ 730 0008 0730
+ 735 0008 0735
+ 745 0008 0745
+ 746 0008 0746
+
+Module Parameters
+-----------------
+
+* force_addr=0xaddr Set the I/O base address. Useful for boards
+ that don't set the address in the BIOS. Does not do a
+ PCI force; the device must still be present in lspci.
+ Don't use this unless the driver complains that the
+ base address is not set.
+
+Description
+-----------
+
+i2c-sis5595 is a true SMBus host driver for motherboards with the SiS5595
+southbridges.
+
+WARNING: If you are trying to access the integrated sensors on the SiS5595
+chip, you want the sis5595 driver for those, not this driver. This driver
+is a BUS driver, not a CHIP driver. A BUS driver is used by other CHIP
+drivers to access chips on the bus.
+
diff --git a/Documentation/i2c/busses/i2c-sis630 b/Documentation/i2c/busses/i2c-sis630
new file mode 100644
index 00000000000000..9aca6889f748e2
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-sis630
@@ -0,0 +1,49 @@
+Kernel driver i2c-sis630
+
+Supported adapters:
+ * Silicon Integrated Systems Corp (SiS)
+ 630 chipset (Datasheet: available at http://amalysh.bei.t-online.de/docs/SIS/)
+ 730 chipset
+ * Possible other SiS chipsets ?
+
+Author: Alexander Malysh <amalysh@web.de>
+
+Module Parameters
+-----------------
+
+* force = [1|0] Forcibly enable the SIS630. DANGEROUS!
+ This can be interesting for chipsets not named
+ above to check if it works for you chipset, but DANGEROUS!
+
+* high_clock = [1|0] Forcibly set Host Master Clock to 56KHz (default,
+ what your BIOS use). DANGEROUS! This should be a bit
+ faster, but freeze some systems (i.e. my Laptop).
+
+
+Description
+-----------
+
+This SMBus only driver is known to work on motherboards with the above
+named chipsets.
+
+If you see something like this:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS] 630 Host (rev 31)
+00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+
+or like this:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS] 730 Host (rev 02)
+00:01.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+
+in your 'lspci' output , then this driver is for your chipset.
+
+Thank You
+---------
+Philip Edelbrock <phil@netroedge.com>
+- testing SiS730 support
+Mark M. Hoffman <mhoffman@lightlink.com>
+- bug fixes
+
+To anyone else which I forgot here ;), thanks!
+
diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis69x
new file mode 100644
index 00000000000000..5be48769f65bdd
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-sis69x
@@ -0,0 +1,73 @@
+Kernel driver i2c-sis96x
+
+Replaces 2.4.x i2c-sis645
+
+Supported adapters:
+ * Silicon Integrated Systems Corp (SiS)
+ Any combination of these host bridges:
+ 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
+ and these south bridges:
+ 961, 962, 963(L)
+
+Author: Mark M. Hoffman <mhoffman@lightlink.com>
+
+Description
+-----------
+
+This SMBus only driver is known to work on motherboards with the above
+named chipset combinations. The driver was developed without benefit of a
+proper datasheet from SiS. The SMBus registers are assumed compatible with
+those of the SiS630, although they are located in a completely different
+place. Thanks to Alexander Malysh <amalysh@web.de> for providing the
+SiS630 datasheet (and driver).
+
+The command "lspci" as root should produce something like these lines:
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
+00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
+
+or perhaps this...
+
+00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
+00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
+00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
+
+(kernel versions later than 2.4.18 may fill in the "Unknown"s)
+
+If you cant see it please look on quirk_sis_96x_smbus
+(drivers/pci/quirks.c) (also if southbridge detection fails)
+
+I suspect that this driver could be made to work for the following SiS
+chipsets as well: 635, and 635T. If anyone owns a board with those chips
+AND is willing to risk crashing & burning an otherwise well-behaved kernel
+in the name of progress... please contact me at <mhoffman@lightlink.com> or
+via the project's mailing list: <sensors@stimpy.netroedge.com>. Please
+send bug reports and/or success stories as well.
+
+
+TO DOs
+------
+
+* The driver does not support SMBus block reads/writes; I may add them if a
+scenario is found where they're needed.
+
+
+Thank You
+---------
+
+Mark D. Studebaker <mdsxyz123@yahoo.com>
+ - design hints and bug fixes
+Alexander Maylsh <amalysh@web.de>
+ - ditto, plus an important datasheet... almost the one I really wanted
+Hans-Günter Lütke Uphues <hg_lu@t-online.de>
+ - patch for SiS735
+Robert Zwerus <arzie@dds.nl>
+ - testing for SiS645DX
+Kianusch Sayah Karadji <kianusch@sk-tech.net>
+ - patch for SiS645DX/962
+Ken Healy
+ - patch for SiS655
+
+To anyone else who has written w/ feedback, thanks!
+
diff --git a/Documentation/i2c/busses/i2c-via b/Documentation/i2c/busses/i2c-via
new file mode 100644
index 00000000000000..55edfe1a640be0
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-via
@@ -0,0 +1,34 @@
+Kernel driver i2c-via
+
+Supported adapters:
+ * VIA Technologies, InC. VT82C586B
+ Datasheet: Publicly available at the VIA website
+
+Author: Kyösti Mälkki <kmalkki@cc.hut.fi>
+
+Description
+-----------
+
+i2c-via is an i2c bus driver for motherboards with VIA chipset.
+
+The following VIA pci chipsets are supported:
+ - MVP3, VP3, VP2/97, VPX/97
+ - others with South bridge VT82C586B
+
+Your lspci listing must show this :
+
+ Bridge: VIA Technologies, Inc. VT82C586B ACPI (rev 10)
+
+ Problems?
+
+ Q: You have VT82C586B on the motherboard, but not in the listing.
+
+ A: Go to your BIOS setup, section PCI devices or similar.
+ Turn USB support on, and try again.
+
+ Q: No error messages, but still i2c doesn't seem to work.
+
+ A: This can happen. This driver uses the pins VIA recommends in their
+ datasheets, but there are several ways the motherboard manufacturer
+ can actually wire the lines.
+
diff --git a/Documentation/i2c/busses/i2c-viapro b/Documentation/i2c/busses/i2c-viapro
new file mode 100644
index 00000000000000..702f5ac68c09d8
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-viapro
@@ -0,0 +1,47 @@
+Kernel driver i2c-viapro
+
+Supported adapters:
+ * VIA Technologies, Inc. VT82C596A/B
+ Datasheet: Sometimes available at the VIA website
+
+ * VIA Technologies, Inc. VT82C686A/B
+ Datasheet: Sometimes available at the VIA website
+
+ * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237
+ Datasheet: available on request from Via
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Module Parameters
+-----------------
+
+* force: int
+ Forcibly enable the SMBus controller. DANGEROUS!
+* force_addr: int
+ Forcibly enable the SMBus at the given address. EXTREMELY DANGEROUS!
+
+Description
+-----------
+
+i2c-viapro is a true SMBus host driver for motherboards with one of the
+supported VIA southbridges.
+
+Your lspci -n listing must show one of these :
+
+ device 1106:3050 (VT82C596 function 3)
+ device 1106:3051 (VT82C596 function 3)
+ device 1106:3057 (VT82C686 function 4)
+ device 1106:3074 (VT8233)
+ device 1106:3147 (VT8233A)
+ device 1106:8235 (VT8231)
+ devide 1106:3177 (VT8235)
+ devide 1106:3227 (VT8237)
+
+If none of these show up, you should look in the BIOS for settings like
+enable ACPI / SMBus or even USB.
+
+
diff --git a/Documentation/i2c/busses/i2c-voodoo3 b/Documentation/i2c/busses/i2c-voodoo3
new file mode 100644
index 00000000000000..62d90a454d399d
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-voodoo3
@@ -0,0 +1,62 @@
+Kernel driver i2c-voodoo3
+
+Supported adapters:
+ * 3dfx Voodoo3 based cards
+ * Voodoo Banshee based cards
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Ralph Metzler <rjkm@thp.uni-koeln.de>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+Main contact: Philip Edelbrock <phil@netroedge.com>
+
+The code is based upon Ralph's test code (he did the hard stuff ;')
+
+Description
+-----------
+
+The 3dfx Voodoo3 chip contains two I2C interfaces (aka a I2C 'master' or
+'host').
+
+The first interface is used for DDC (Data Display Channel) which is a
+serial channel through the VGA monitor connector to a DDC-compliant
+monitor. This interface is defined by the Video Electronics Standards
+Association (VESA). The standards are available for purchase at
+http://www.vesa.org .
+
+The second interface is a general-purpose I2C bus. The intent by 3dfx was
+to allow manufacturers to add extra chips to the video card such as a
+TV-out chip such as the BT869 or possibly even I2C based temperature
+sensors like the ADM1021 or LM75.
+
+Stability
+---------
+
+Seems to be stable on the test machine, but needs more testing on other
+machines. Simultaneous accesses of the DDC and I2C busses may cause errors.
+
+Supported Devices
+-----------------
+
+Specifically, this driver was written and tested on the '3dfx Voodoo3 AGP
+3000' which has a tv-out feature (s-video or composite). According to the
+docs and discussions, this code should work for any Voodoo3 based cards as
+well as Voodoo Banshee based cards. The DDC interface has been tested on a
+Voodoo Banshee card.
+
+Issues
+------
+
+Probably many, but it seems to work OK on my system. :')
+
+
+External Device Connection
+--------------------------
+
+The digital video input jumpers give availability to the I2C bus.
+Specifically, pins 13 and 25 (bottom row middle, and bottom right-end) are
+the I2C clock and I2C data lines, respectively. +5V and GND are probably
+also easily available making the addition of extra I2C/SMBus devices easy
+to implement.
diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb
new file mode 100644
index 00000000000000..08c8cd1df60c50
--- /dev/null
+++ b/Documentation/i2c/busses/scx200_acb
@@ -0,0 +1,14 @@
+Kernel driver scx200_acb
+
+Author: Christer Weinigel <wingel@nano-system.com>
+
+Module Parameters
+-----------------
+
+* base: int
+ Base addresses for the ACCESS.bus controllers
+
+Description
+-----------
+
+Enable the use of the ACCESS.bus controllers of a SCx200 processor.
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 0b7e2d381a3ebd..28bb0514bb6e1c 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -8,7 +8,7 @@
#include <linux/acpi.h>
#include <linux/bootmem.h>
#include <asm/smp.h>
-
+#include <asm/tlbflush.h>
/* address in low memory of the wakeup routine. */
unsigned long acpi_wakeup_address = 0;
@@ -27,6 +27,7 @@ static void init_low_mapping(pgd_t *pgd, int pgd_limit)
set_pgd(pgd, *(pgd+USER_PTRS_PER_PGD));
pgd_ofs++, pgd++;
}
+ flush_tlb_all();
}
/**
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index a337879e981da8..33fcb205fcb7ad 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -169,6 +169,7 @@ config NUMA
bool "NUMA support"
depends on !IA64_HP_SIM
default y if IA64_SGI_SN2
+ select ACPI_NUMA
help
Say Y to compile the kernel to support NUMA (Non-Uniform Memory
Access). This option is for configuring high-end multiprocessor
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index ca062b9628ab3c..a8e99c56a76894 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -771,7 +771,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */
-#ifdef CONFIG_NUMA
+#ifdef CONFIG_ACPI_NUMA
acpi_status __init
acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
{
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 111dad9175ba10..c15be5c38f5605 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -91,7 +91,6 @@
#undef DEBUG_INTERRUPT_ROUTING
-#undef OVERRIDE_DEBUG
#ifdef DEBUG_INTERRUPT_ROUTING
#define DBG(fmt...) printk(fmt)
@@ -499,14 +498,14 @@ get_target_cpu (unsigned int gsi, int vector)
* distribute interrupts.
*/
if (smp_int_redirect & SMP_IRQ_REDIRECTION)
- return hard_smp_processor_id();
+ return cpu_physical_id(smp_processor_id());
/*
* Some interrupts (ACPI SCI, for instance) are registered
* before the BSP is marked as online.
*/
if (!cpu_online(smp_processor_id()))
- return hard_smp_processor_id();
+ return cpu_physical_id(smp_processor_id());
#ifdef CONFIG_NUMA
{
@@ -553,7 +552,7 @@ skip_numa_setup:
return cpu_physical_id(cpu);
#else
- return hard_smp_processor_id();
+ return cpu_physical_id(smp_processor_id());
#endif
}
@@ -740,7 +739,7 @@ iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long trigger)
{
int vector;
- unsigned int dest = hard_smp_processor_id();
+ unsigned int dest = cpu_physical_id(smp_processor_id());
vector = isa_irq_to_vector(isa_irq);
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index b3ed949a4f8609..d9c05d53435bd1 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -957,6 +957,8 @@ END(ia64_syscall_setup)
* element, followed by the arguments.
*/
ENTRY(dispatch_illegal_op_fault)
+ .prologue
+ .body
SAVE_MIN_WITH_COVER
ssm psr.ic | PSR_DEFAULT_BITS
;;
@@ -969,6 +971,7 @@ ENTRY(dispatch_illegal_op_fault)
mov out0=ar.ec
;;
SAVE_REST
+ PT_REGS_UNWIND_INFO(0)
;;
br.call.sptk.many rp=ia64_illegal_op_fault
.ret0: ;;
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index a01c2cd060380b..1dbc7b2497c90d 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -26,7 +26,7 @@
(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
;; \
(pUStk) mov r18=ar.bsp; \
-(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \
+(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */
#define MINSTATE_END_SAVE_MIN_VIRT \
bsw.1; /* switch back to bank 1 (must be last in insn group) */ \
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 9891effcf4c3cb..f05650c801d2a4 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -646,6 +646,15 @@ cpu_init (void)
ia64_set_kr(IA64_KR_FPU_OWNER, 0);
/*
+ * Initialize the page-table base register to a global
+ * directory with all zeroes. This ensure that we can handle
+ * TLB-misses to user address-space even before we created the
+ * first user address-space. This may happen, e.g., due to
+ * aggressive use of lfetch.fault.
+ */
+ ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page)));
+
+ /*
* Initialize default control register to defer all speculative faults. The
* kernel MUST NOT depend on a particular setting of these bits (in other words,
* the kernel must have recovery code for all speculative accesses). Turn on
diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
index 46dad0d215a3dc..43b45b65ee5a9d 100644
--- a/arch/ia64/kernel/unaligned.c
+++ b/arch/ia64/kernel/unaligned.c
@@ -1380,6 +1380,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
* - ldX.spill
* - stX.spill
* Reason: RNATs are based on addresses
+ * - ld16
+ * - st16
+ * Reason: ld16 and st16 are supposed to occur in a single
+ * memory op
*
* synchronization:
* - cmpxchg
@@ -1401,6 +1405,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
switch (opcode) {
case LDS_OP:
case LDSA_OP:
+ if (u.insn.x)
+ /* oops, really a semaphore op (cmpxchg, etc) */
+ goto failure;
+ /* no break */
case LDS_IMM_OP:
case LDSA_IMM_OP:
case LDFS_OP:
@@ -1425,6 +1433,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
case LDCCLR_OP:
case LDCNC_OP:
case LDCCLRACQ_OP:
+ if (u.insn.x)
+ /* oops, really a semaphore op (cmpxchg, etc) */
+ goto failure;
+ /* no break */
case LD_IMM_OP:
case LDA_IMM_OP:
case LDBIAS_IMM_OP:
@@ -1437,6 +1449,10 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
case ST_OP:
case STREL_OP:
+ if (u.insn.x)
+ /* oops, really a semaphore op (cmpxchg, etc) */
+ goto failure;
+ /* no break */
case ST_IMM_OP:
case STREL_IMM_OP:
ret = emulate_store_int(ifa, u.insn, regs);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 61d8dd3c9c93a0..88641e5095b5f9 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -178,30 +178,6 @@ alloc_pci_controller (int seg)
return controller;
}
-static int __devinit
-alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end,
- unsigned long flags)
-{
- struct resource *res;
-
- res = kmalloc(sizeof(*res), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- memset(res, 0, sizeof(*res));
- res->name = name;
- res->start = start;
- res->end = end;
- res->flags = flags;
-
- if (insert_resource(root, res)) {
- kfree(res);
- return -EBUSY;
- }
-
- return 0;
-}
-
static u64 __devinit
add_io_space (struct acpi_resource_address64 *addr)
{
@@ -254,10 +230,9 @@ struct pci_root_info {
char *name;
};
-static acpi_status __devinit
-add_window (struct acpi_resource *res, void *data)
+static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
{
- struct pci_root_info *info = (struct pci_root_info *) data;
+ struct pci_root_info *info = data;
struct pci_window *window;
struct acpi_resource_address64 addr;
acpi_status status;
@@ -265,45 +240,71 @@ add_window (struct acpi_resource *res, void *data)
struct resource *root;
status = acpi_resource_to_address64(res, &addr);
- if (ACPI_SUCCESS(status)) {
- if (!addr.address_length)
- return AE_OK;
-
- if (addr.resource_type == ACPI_MEMORY_RANGE) {
- flags = IORESOURCE_MEM;
- root = &iomem_resource;
- offset = addr.address_translation_offset;
- } else if (addr.resource_type == ACPI_IO_RANGE) {
- flags = IORESOURCE_IO;
- root = &ioport_resource;
- offset = add_io_space(&addr);
- if (offset == ~0)
- return AE_OK;
- } else
+ if (!ACPI_SUCCESS(status))
+ return AE_OK;
+
+ if (!addr.address_length)
+ return AE_OK;
+
+ if (addr.resource_type == ACPI_MEMORY_RANGE) {
+ flags = IORESOURCE_MEM;
+ root = &iomem_resource;
+ offset = addr.address_translation_offset;
+ } else if (addr.resource_type == ACPI_IO_RANGE) {
+ flags = IORESOURCE_IO;
+ root = &ioport_resource;
+ offset = add_io_space(&addr);
+ if (offset == ~0)
return AE_OK;
-
- window = &info->controller->window[info->controller->windows++];
- window->resource.flags = flags;
- window->resource.start = addr.min_address_range;
- window->resource.end = addr.max_address_range;
- window->offset = offset;
-
- if (alloc_resource(info->name, root, addr.min_address_range + offset,
- addr.max_address_range + offset, flags))
- printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
- addr.min_address_range + offset, addr.max_address_range + offset,
- root->name, info->name);
+ } else
+ return AE_OK;
+
+ window = &info->controller->window[info->controller->windows++];
+ window->resource.name = info->name;
+ window->resource.flags = flags;
+ window->resource.start = addr.min_address_range + offset;
+ window->resource.end = addr.max_address_range + offset;
+ window->resource.child = NULL;
+ window->offset = offset;
+
+ if (insert_resource(root, &window->resource)) {
+ printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n",
+ window->resource.start, window->resource.end,
+ root->name, info->name);
}
return AE_OK;
}
+static void __devinit
+pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
+{
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < ctrl->windows; i++) {
+ struct resource *res = &ctrl->window[i].resource;
+ /* HP's firmware has a hack to work around a Windows bug.
+ * Ignore these tiny memory ranges */
+ if ((res->flags & IORESOURCE_MEM) &&
+ (res->end - res->start < 16))
+ continue;
+ if (j >= PCI_BUS_NUM_RESOURCES) {
+ printk("Ignoring range [%lx-%lx] (%lx)\n", res->start,
+ res->end, res->flags);
+ continue;
+ }
+ bus->resource[j++] = res;
+ }
+}
+
struct pci_bus * __devinit
-pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
+pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
{
struct pci_root_info info;
struct pci_controller *controller;
unsigned int windows = 0;
+ struct pci_bus *pbus;
char *name;
controller = alloc_pci_controller(domain);
@@ -312,8 +313,10 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
controller->acpi_handle = device->handle;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows);
- controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
+ &windows);
+ controller->window = kmalloc(sizeof(*controller->window) * windows,
+ GFP_KERNEL);
if (!controller->window)
goto out2;
@@ -324,9 +327,14 @@ pci_acpi_scan_root (struct acpi_device *device, int domain, int bus)
sprintf(name, "PCI Bus %04x:%02x", domain, bus);
info.controller = controller;
info.name = name;
- acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, &info);
+ acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
+ &info);
+
+ pbus = pci_scan_bus(bus, &pci_root_ops, controller);
+ if (pbus)
+ pcibios_setup_root_windows(pbus, controller);
- return pci_scan_bus(bus, &pci_root_ops, controller);
+ return pbus;
out3:
kfree(controller->window);
@@ -347,9 +355,9 @@ void pcibios_resource_to_bus(struct pci_dev *dev,
struct pci_window *window = &controller->window[i];
if (!(window->resource.flags & res->flags))
continue;
- if (window->resource.start > res->start - window->offset)
+ if (window->resource.start > res->start)
continue;
- if (window->resource.end < res->end - window->offset)
+ if (window->resource.end < res->end)
continue;
offset = window->offset;
break;
@@ -371,9 +379,9 @@ void pcibios_bus_to_resource(struct pci_dev *dev,
struct pci_window *window = &controller->window[i];
if (!(window->resource.flags & res->flags))
continue;
- if (window->resource.start > region->start)
+ if (window->resource.start - window->offset > region->start)
continue;
- if (window->resource.end < region->end)
+ if (window->resource.end - window->offset < region->end)
continue;
offset = window->offset;
break;
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index a852077940fe03..f0306b516afba5 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -67,15 +67,27 @@ extern void snidle(int);
extern unsigned char acpi_kbd_controller_present;
unsigned long sn_rtc_cycles_per_second;
-
EXPORT_SYMBOL(sn_rtc_cycles_per_second);
+DEFINE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
+EXPORT_PER_CPU_SYMBOL(__sn_hub_info);
+
partid_t sn_partid = -1;
EXPORT_SYMBOL(sn_partid);
char sn_system_serial_number_string[128];
EXPORT_SYMBOL(sn_system_serial_number_string);
u64 sn_partition_serial_number;
EXPORT_SYMBOL(sn_partition_serial_number);
+u8 sn_partition_id;
+EXPORT_SYMBOL(sn_partition_id);
+u8 sn_system_size;
+EXPORT_SYMBOL(sn_system_size);
+u8 sn_sharing_domain_size;
+EXPORT_SYMBOL(sn_sharing_domain_size);
+u8 sn_coherency_id;
+EXPORT_SYMBOL(sn_coherency_id);
+u8 sn_region_size;
+EXPORT_SYMBOL(sn_region_size);
short physical_node_map[MAX_PHYSNODE_ID];
@@ -232,7 +244,7 @@ static void __init sn_check_for_wars(void)
} else {
for_each_online_node(cnode) {
if (is_shub_1_1(cnodeid_to_nasid(cnode)))
- shub_1_1_found = 1;
+ sn_hub_info->shub_1_1_found = 1;
}
}
}
@@ -424,16 +436,14 @@ void __init sn_cpu_init(void)
int slice;
int cnode;
int i;
- u64 shubtype, nasid_bitmask, nasid_shift;
static int wars_have_been_checked;
memset(pda, 0, sizeof(pda));
- if (ia64_sn_get_hub_info(0, &shubtype, &nasid_bitmask, &nasid_shift))
+ if (ia64_sn_get_sn_info(0, &sn_hub_info->shub2, &sn_hub_info->nasid_bitmask, &sn_hub_info->nasid_shift,
+ &sn_system_size, &sn_sharing_domain_size, &sn_partition_id,
+ &sn_coherency_id, &sn_region_size))
BUG();
- pda->shub2 = (u8)shubtype;
- pda->nasid_bitmask = (u16)nasid_bitmask;
- pda->nasid_shift = (u8)nasid_shift;
- pda->as_shift = pda->nasid_shift - 2;
+ sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
/*
* The boot cpu makes this call again after platform initialization is
@@ -482,7 +492,7 @@ void __init sn_cpu_init(void)
sn_check_for_wars();
wars_have_been_checked = 1;
}
- pda->shub_1_1_found = shub_1_1_found;
+ sn_hub_info->shub_1_1_found = shub_1_1_found;
/*
* Set up addresses of PIO/MEM write status registers.
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 894128bffc58c3..0400a52d508557 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -331,6 +331,26 @@ config ACPI_CONTAINER
This is the ACPI generic container driver which supports
ACPI0004, PNP0A05 and PNP0A06 devices
+config ACPI_HOTPLUG_MEMORY
+ tristate "Memory Hotplug"
+ depends on ACPI
+ depends on MEMORY_HOTPLUG
+ default n
+ help
+ This driver adds supports for ACPI Memory Hotplug. This driver
+ provides support for fielding notifications on ACPI memory
+ devices (PNP0C80) which represent memory ranges that may be
+ onlined or offlined during runtime.
+
+ Enabling this driver assumes that your platform hardware
+ and firmware have support for hot-plugging physical memory. If
+ your system does not support physically adding or ripping out
+ memory DIMMs at some platfrom defined granularity (individually
+ or as a bank) at runtime, then you need not enable this driver.
+
+ If one selects "m," this driver can be loaded using the following
+ command:
+ $>modprobe acpi_memhotplug
endif # ACPI
endmenu
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 1ae0d89c2d3fbc..65c92e20566d58 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -55,3 +55,4 @@ obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_IBM) += ibm_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_BUS) += scan.o motherboard.o
+obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index e0f498c7b343c7..23ab761dd72176 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -51,8 +51,8 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME);
MODULE_LICENSE("GPL");
-int acpi_ac_add (struct acpi_device *device);
-int acpi_ac_remove (struct acpi_device *device, int type);
+static int acpi_ac_add (struct acpi_device *device);
+static int acpi_ac_remove (struct acpi_device *device, int type);
static int acpi_ac_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_ac_driver = {
@@ -108,9 +108,9 @@ acpi_ac_get_state (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_ac_dir;
+static struct proc_dir_entry *acpi_ac_dir;
-int acpi_ac_seq_show(struct seq_file *seq, void *offset)
+static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
{
struct acpi_ac *ac = (struct acpi_ac *) seq->private;
@@ -200,7 +200,7 @@ acpi_ac_remove_fs (
Driver Model
-------------------------------------------------------------------------- */
-void
+static void
acpi_ac_notify (
acpi_handle handle,
u32 event,
@@ -232,7 +232,7 @@ acpi_ac_notify (
}
-int
+static int
acpi_ac_add (
struct acpi_device *device)
{
@@ -286,7 +286,7 @@ end:
}
-int
+static int
acpi_ac_remove (
struct acpi_device *device,
int type)
@@ -315,7 +315,7 @@ acpi_ac_remove (
}
-int __init
+static int __init
acpi_ac_init (void)
{
int result = 0;
@@ -337,7 +337,7 @@ acpi_ac_init (void)
}
-void __exit
+static void __exit
acpi_ac_exit (void)
{
ACPI_FUNCTION_TRACE("acpi_ac_exit");
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
new file mode 100644
index 00000000000000..77285ffe41c5cb
--- /dev/null
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * ACPI based HotPlug driver that supports Memory Hotplug
+ * This driver fields notifications from firmare for memory add
+ * and remove operations and alerts the VM of the affected memory
+ * ranges.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/memory_hotplug.h>
+#include <acpi/acpi_drivers.h>
+
+
+#define ACPI_MEMORY_DEVICE_COMPONENT 0x08000000UL
+#define ACPI_MEMORY_DEVICE_CLASS "memory"
+#define ACPI_MEMORY_DEVICE_HID "PNP0C80"
+#define ACPI_MEMORY_DEVICE_DRIVER_NAME "Hotplug Mem Driver"
+#define ACPI_MEMORY_DEVICE_NAME "Hotplug Mem Device"
+
+#define _COMPONENT ACPI_MEMORY_DEVICE_COMPONENT
+
+ACPI_MODULE_NAME ("acpi_memory")
+MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
+MODULE_DESCRIPTION(ACPI_MEMORY_DEVICE_DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+/* ACPI _STA method values */
+#define ACPI_MEMORY_STA_PRESENT (0x00000001UL)
+#define ACPI_MEMORY_STA_ENABLED (0x00000002UL)
+#define ACPI_MEMORY_STA_FUNCTIONAL (0x00000008UL)
+
+/* Memory Device States */
+#define MEMORY_INVALID_STATE 0
+#define MEMORY_POWER_ON_STATE 1
+#define MEMORY_POWER_OFF_STATE 2
+
+static int acpi_memory_device_add (struct acpi_device *device);
+static int acpi_memory_device_remove (struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_memory_device_driver = {
+ .name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
+ .class = ACPI_MEMORY_DEVICE_CLASS,
+ .ids = ACPI_MEMORY_DEVICE_HID,
+ .ops = {
+ .add = acpi_memory_device_add,
+ .remove = acpi_memory_device_remove,
+ },
+};
+
+struct acpi_memory_device {
+ acpi_handle handle;
+ unsigned int state; /* State of the memory device */
+ unsigned short cache_attribute; /* memory cache attribute */
+ unsigned short read_write_attribute;/* memory read/write attribute */
+ u64 start_addr; /* Memory Range start physical addr */
+ u64 end_addr; /* Memory Range end physical addr */
+};
+
+
+static int
+acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_resource *resource = NULL;
+ struct acpi_resource_address64 address64;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources");
+
+ /* Get the range from the _CRS */
+ status = acpi_get_current_resources(mem_device->handle, &buffer);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-EINVAL);
+
+ resource = (struct acpi_resource *) buffer.pointer;
+ status = acpi_resource_to_address64(resource, &address64);
+ if (ACPI_SUCCESS(status)) {
+ if (address64.resource_type == ACPI_MEMORY_RANGE) {
+ /* Populate the structure */
+ mem_device->cache_attribute =
+ address64.attribute.memory.cache_attribute;
+ mem_device->read_write_attribute =
+ address64.attribute.memory.read_write_attribute;
+ mem_device->start_addr = address64.min_address_range;
+ mem_device->end_addr = address64.max_address_range;
+ }
+ }
+
+ acpi_os_free(buffer.pointer);
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_get_device(acpi_handle handle,
+ struct acpi_memory_device **mem_device)
+{
+ acpi_status status;
+ acpi_handle phandle;
+ struct acpi_device *device = NULL;
+ struct acpi_device *pdevice = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_get_device");
+
+ if (!acpi_bus_get_device(handle, &device) && device)
+ goto end;
+
+ status = acpi_get_parent(handle, &phandle);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_get_parent\n"));
+ return_VALUE(-EINVAL);
+ }
+
+ /* Get the parent device */
+ status = acpi_bus_get_device(phandle, &pdevice);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_bus_get_device\n"));
+ return_VALUE(-EINVAL);
+ }
+
+ /*
+ * Now add the notified device. This creates the acpi_device
+ * and invokes .add function
+ */
+ status = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_bus_add\n"));
+ return_VALUE(-EINVAL);
+ }
+
+end:
+ *mem_device = acpi_driver_data(device);
+ if (!(*mem_device)) {
+ printk(KERN_ERR "\n driver data not found" );
+ return_VALUE(-ENODEV);
+ }
+
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_check_device(struct acpi_memory_device *mem_device)
+{
+ unsigned long current_status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_check_device");
+
+ /* Get device present/absent information from the _STA */
+ if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->handle, "_STA",
+ NULL, &current_status)))
+ return_VALUE(-ENODEV);
+ /*
+ * Check for device status. Device should be
+ * present/enabled/functioning.
+ */
+ if (!((current_status & ACPI_MEMORY_STA_PRESENT)
+ && (current_status & ACPI_MEMORY_STA_ENABLED)
+ && (current_status & ACPI_MEMORY_STA_FUNCTIONAL)))
+ return_VALUE(-ENODEV);
+
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_enable_device(struct acpi_memory_device *mem_device)
+{
+ int result;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_enable_device");
+
+ /* Get the range from the _CRS */
+ result = acpi_memory_get_device_resources(mem_device);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "\nget_device_resources failed\n"));
+ mem_device->state = MEMORY_INVALID_STATE;
+ return result;
+ }
+
+ /*
+ * Tell the VM there is more memory here...
+ * Note: Assume that this function returns zero on success
+ */
+ result = add_memory(mem_device->start_addr,
+ (mem_device->end_addr - mem_device->start_addr) + 1,
+ mem_device->read_write_attribute);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "\nadd_memory failed\n"));
+ mem_device->state = MEMORY_INVALID_STATE;
+ return result;
+ }
+
+ return result;
+}
+
+static int
+acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+{
+ acpi_status status;
+ struct acpi_object_list arg_list;
+ union acpi_object arg;
+ unsigned long current_status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_powerdown_device");
+
+ /* Issue the _EJ0 command */
+ arg_list.count = 1;
+ arg_list.pointer = &arg;
+ arg.type = ACPI_TYPE_INTEGER;
+ arg.integer.value = 1;
+ status = acpi_evaluate_object(mem_device->handle,
+ "_EJ0", &arg_list, NULL);
+ /* Return on _EJ0 failure */
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,"_EJ0 failed.\n"));
+ return_VALUE(-ENODEV);
+ }
+
+ /* Evalute _STA to check if the device is disabled */
+ status = acpi_evaluate_integer(mem_device->handle, "_STA",
+ NULL, &current_status);
+ if (ACPI_FAILURE(status))
+ return_VALUE(-ENODEV);
+
+ /* Check for device status. Device should be disabled */
+ if (current_status & ACPI_MEMORY_STA_ENABLED)
+ return_VALUE(-EINVAL);
+
+ return_VALUE(0);
+}
+
+static int
+acpi_memory_disable_device(struct acpi_memory_device *mem_device)
+{
+ int result;
+ u64 start = mem_device->start_addr;
+ u64 len = mem_device->end_addr - start + 1;
+ unsigned long attr = mem_device->read_write_attribute;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
+
+ /*
+ * Ask the VM to offline this memory range.
+ * Note: Assume that this function returns zero on success
+ */
+ result = remove_memory(start, len, attr);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
+ return_VALUE(result);
+ }
+
+ /* Power-off and eject the device */
+ result = acpi_memory_powerdown_device(mem_device);
+ if (result) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device Power Down failed.\n"));
+ /* Set the status of the device to invalid */
+ mem_device->state = MEMORY_INVALID_STATE;
+ return result;
+ }
+
+ mem_device->state = MEMORY_POWER_OFF_STATE;
+ return result;
+}
+
+static void
+acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct acpi_memory_device *mem_device;
+ struct acpi_device *device;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_notify");
+
+ switch (event) {
+ case ACPI_NOTIFY_BUS_CHECK:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "\nReceived BUS CHECK notification for device\n"));
+ /* Fall Through */
+ case ACPI_NOTIFY_DEVICE_CHECK:
+ if (event == ACPI_NOTIFY_DEVICE_CHECK)
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "\nReceived DEVICE CHECK notification for device\n"));
+ if (acpi_memory_get_device(handle, &mem_device)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in finding driver data\n"));
+ return_VOID;
+ }
+
+ if (!acpi_memory_check_device(mem_device)) {
+ if (acpi_memory_enable_device(mem_device))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_memory_enable_device\n"));
+ }
+ break;
+ case ACPI_NOTIFY_EJECT_REQUEST:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "\nReceived EJECT REQUEST notification for device\n"));
+
+ if (acpi_bus_get_device(handle, &device)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Device doesn't exist\n"));
+ break;
+ }
+ mem_device = acpi_driver_data(device);
+ if (!mem_device) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Driver Data is NULL\n"));
+ break;
+ }
+
+ /*
+ * Currently disabling memory device from kernel mode
+ * TBD: Can also be disabled from user mode scripts
+ * TBD: Can also be disabled by Callback registration
+ * with generic sysfs driver
+ */
+ if (acpi_memory_disable_device(mem_device))
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error in acpi_memory_disable_device\n"));
+ /*
+ * TBD: Invoke acpi_bus_remove to cleanup data structures
+ */
+ break;
+ default:
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "Unsupported event [0x%x]\n", event));
+ break;
+ }
+
+ return_VOID;
+}
+
+static int
+acpi_memory_device_add(struct acpi_device *device)
+{
+ int result;
+ struct acpi_memory_device *mem_device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_add");
+
+ if (!device)
+ return_VALUE(-EINVAL);
+
+ mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
+ if (!mem_device)
+ return_VALUE(-ENOMEM);
+ memset(mem_device, 0, sizeof(struct acpi_memory_device));
+
+ mem_device->handle = device->handle;
+ sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
+ sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
+ acpi_driver_data(device) = mem_device;
+
+ /* Get the range from the _CRS */
+ result = acpi_memory_get_device_resources(mem_device);
+ if (result) {
+ kfree(mem_device);
+ return_VALUE(result);
+ }
+
+ /* Set the device state */
+ mem_device->state = MEMORY_POWER_ON_STATE;
+
+ printk(KERN_INFO "%s \n", acpi_device_name(device));
+
+ return_VALUE(result);
+}
+
+static int
+acpi_memory_device_remove (struct acpi_device *device, int type)
+{
+ struct acpi_memory_device *mem_device = NULL;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_remove");
+
+ if (!device || !acpi_driver_data(device))
+ return_VALUE(-EINVAL);
+
+ mem_device = (struct acpi_memory_device *) acpi_driver_data(device);
+ kfree(mem_device);
+
+ return_VALUE(0);
+}
+
+/*
+ * Helper function to check for memory device
+ */
+static acpi_status
+is_memory_device(acpi_handle handle)
+{
+ char *hardware_id;
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_device_info *info;
+
+ ACPI_FUNCTION_TRACE("is_memory_device");
+
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(AE_ERROR);
+
+ info = buffer.pointer;
+ if (!(info->valid & ACPI_VALID_HID)) {
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(AE_ERROR);
+ }
+
+ hardware_id = info->hardware_id.value;
+ if ((hardware_id == NULL) ||
+ (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
+ status = AE_ERROR;
+
+ acpi_os_free(buffer.pointer);
+ return_ACPI_STATUS(status);
+}
+
+static acpi_status
+acpi_memory_register_notify_handler (acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_register_notify_handler");
+
+ status = is_memory_device(handle);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(AE_OK); /* continue */
+
+ status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ acpi_memory_device_notify, NULL);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error installing notify handler\n"));
+ return_ACPI_STATUS(AE_OK); /* continue */
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+static acpi_status
+acpi_memory_deregister_notify_handler (acpi_handle handle,
+ u32 level, void *ctxt, void **retv)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_deregister_notify_handler");
+
+ status = is_memory_device(handle);
+ if (ACPI_FAILURE(status))
+ return_ACPI_STATUS(AE_OK); /* continue */
+
+ status = acpi_remove_notify_handler(handle,
+ ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify);
+ if (ACPI_FAILURE(status)) {
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+ "Error removing notify handler\n"));
+ return_ACPI_STATUS(AE_OK); /* continue */
+ }
+
+ return_ACPI_STATUS(status);
+}
+
+static int __init
+acpi_memory_device_init (void)
+{
+ int result;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_init");
+
+ result = acpi_bus_register_driver(&acpi_memory_device_driver);
+
+ if (result < 0)
+ return_VALUE(-ENODEV);
+
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_memory_register_notify_handler,
+ NULL, NULL);
+
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+ acpi_bus_unregister_driver(&acpi_memory_device_driver);
+ return_VALUE(-ENODEV);
+ }
+
+ return_VALUE(0);
+}
+
+static void __exit
+acpi_memory_device_exit (void)
+{
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE("acpi_memory_device_exit");
+
+ /*
+ * Adding this to un-install notification handlers for all the device
+ * handles.
+ */
+ status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+ ACPI_UINT32_MAX,
+ acpi_memory_deregister_notify_handler,
+ NULL, NULL);
+
+ if (ACPI_FAILURE (status))
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed\n"));
+
+ acpi_bus_unregister_driver(&acpi_memory_device_driver);
+
+ return_VOID;
+}
+
+module_init(acpi_memory_device_init);
+module_exit(acpi_memory_device_exit);
+
+
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index a10de067dbb631..c55feca9b7d5e0 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -341,7 +341,7 @@ acpi_battery_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_battery_dir;
+static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
{
int result = 0;
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 31aded126ce88c..ec4430e3053ffb 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -275,7 +275,7 @@ acpi_button_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
-void
+static void
acpi_button_notify (
acpi_handle handle,
u32 event,
@@ -302,7 +302,7 @@ acpi_button_notify (
}
-acpi_status
+static acpi_status
acpi_button_notify_fixed (
void *data)
{
diff --git a/drivers/acpi/container.c b/drivers/acpi/container.c
index 060251b5e49c83..5a0adbf8bc0454 100644
--- a/drivers/acpi/container.c
+++ b/drivers/acpi/container.c
@@ -177,13 +177,18 @@ container_notify_cb(acpi_handle handle, u32 type, void *context)
printk("Container driver received %s event\n",
(type == ACPI_NOTIFY_BUS_CHECK)?
"ACPI_NOTIFY_BUS_CHECK":"ACPI_NOTIFY_DEVICE_CHECK");
+ status = acpi_bus_get_device(handle, &device);
if (present) {
- status = acpi_bus_get_device(handle, &device);
if (ACPI_FAILURE(status) || !device) {
result = container_device_add(&device, handle);
if (!result)
- kobject_hotplug(&device->kobj, KOBJ_ONLINE);
- } else {
+ kobject_hotplug(&device->kobj,
+ KOBJ_ONLINE);
+ else
+ printk("Failed to add container\n");
+ }
+ } else {
+ if (ACPI_SUCCESS(status)) {
/* device exist and this is a remove request */
kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
}
@@ -255,7 +260,7 @@ end:
}
-int __init
+static int __init
acpi_container_init(void)
{
int result = 0;
@@ -276,7 +281,7 @@ acpi_container_init(void)
return(0);
}
-void __exit
+static void __exit
acpi_container_exit(void)
{
int action = UNINSTALL_NOTIFY_HANDLER;
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index d947e2a0a46291..2c0dac559f1636 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -35,7 +35,7 @@ struct acpi_dlevel {
};
#define ACPI_DEBUG_INIT(v) { .name = #v, .value = v }
-const struct acpi_dlayer acpi_debug_layers[] =
+static const struct acpi_dlayer acpi_debug_layers[] =
{
ACPI_DEBUG_INIT(ACPI_UTILITIES),
ACPI_DEBUG_INIT(ACPI_HARDWARE),
@@ -53,7 +53,7 @@ const struct acpi_dlayer acpi_debug_layers[] =
ACPI_DEBUG_INIT(ACPI_TOOLS),
};
-const struct acpi_dlevel acpi_debug_levels[] =
+static const struct acpi_dlevel acpi_debug_levels[] =
{
ACPI_DEBUG_INIT(ACPI_LV_ERROR),
ACPI_DEBUG_INIT(ACPI_LV_WARN),
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index fac39ba4a7b44d..9f0456cb9bb55c 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -448,7 +448,16 @@ acpi_ds_restart_control_method (
*/
walk_state->return_desc = return_desc;
}
- else {
+
+ /*
+ * The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) {
/*
* Delete the return value if it will not be used by the
* calling method
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 66fc7549c68830..5c987a0e7b75e8 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -1010,6 +1010,10 @@ acpi_ds_exec_end_control_op (
* has been bubbled up the tree
*/
if (op->common.value.arg) {
+ /* Since we have a real Return(), delete any implicit return */
+
+ acpi_ds_clear_implicit_return (walk_state);
+
/* Return statement has an immediate operand */
status = acpi_ds_create_operands (walk_state, op->common.value.arg);
@@ -1036,6 +1040,10 @@ acpi_ds_exec_end_control_op (
}
else if ((walk_state->results) &&
(walk_state->results->results.num_results > 0)) {
+ /* Since we have a real Return(), delete any implicit return */
+
+ acpi_ds_clear_implicit_return (walk_state);
+
/*
* The return value has come from a previous calculation.
*
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index df6b0018677905..462c5d83e747fe 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -54,10 +54,120 @@
ACPI_MODULE_NAME ("dsutils")
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_clear_implicit_return
+ *
+ * PARAMETERS: walk_state - Current State
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
+ * to delete "stale" return values (if enabled, the return value
+ * from every operator is saved at least momentarily, in case the
+ * parent method exits.)
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state)
+{
+ ACPI_FUNCTION_NAME ("ds_clear_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature
+ */
+ if (!acpi_gbl_enable_interpreter_slack) {
+ return;
+ }
+
+ if (walk_state->implicit_return_obj) {
+ /*
+ * Delete any "stale" implicit return. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Removing reference on stale implicit return obj %p\n",
+ walk_state->implicit_return_obj));
+
+ acpi_ut_remove_reference (walk_state->implicit_return_obj);
+ walk_state->implicit_return_obj = NULL;
+ }
+}
+
+
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
+ * FUNCTION: acpi_ds_do_implicit_return
+ *
+ * PARAMETERS: return_desc - The return value
+ * walk_state - Current State
+ * add_reference - True if a reference should be added to the
+ * return object
+ *
+ * RETURN: TRUE if implicit return enabled, FALSE otherwise
+ *
+ * DESCRIPTION: Implements the optional "implicit return". We save the result
+ * of every ASL operator and control method invocation in case the
+ * parent method exit. Before storing a new return value, we
+ * delete the previous return value.
+ *
+ ******************************************************************************/
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference)
+{
+ ACPI_FUNCTION_NAME ("ds_do_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature, and we must
+ * have a valid return object
+ */
+ if ((!acpi_gbl_enable_interpreter_slack) ||
+ (!return_desc)) {
+ return (FALSE);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Result %p will be implicitly returned; Prev=%p\n",
+ return_desc,
+ walk_state->implicit_return_obj));
+
+ /*
+ * Delete any "stale" implicit return value first. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels, so we don't clear the value if it
+ * is the same as the return_desc.
+ */
+ if (walk_state->implicit_return_obj) {
+ if (walk_state->implicit_return_obj == return_desc) {
+ return (TRUE);
+ }
+ acpi_ds_clear_implicit_return (walk_state);
+ }
+
+ /* Save the implicit return value, add a reference if requested */
+
+ walk_state->implicit_return_obj = return_desc;
+ if (add_reference) {
+ acpi_ut_add_reference (return_desc);
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ds_is_result_used
*
* PARAMETERS: Op - Current Op
@@ -76,7 +186,6 @@ acpi_ds_is_result_used (
{
const struct acpi_opcode_info *parent_info;
-
ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
@@ -88,6 +197,19 @@ acpi_ds_is_result_used (
}
/*
+ * We know that this operator is not a
+ * Return() operator (would not come here.) The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
+
+ /*
+ * Now determine if the parent will use the result
+ *
* If there is no parent, or the parent is a scope_op, we are executing
* at the method level. An executing method typically has no parent,
* since each method is parsed separately. A method invoked externally
@@ -95,29 +217,10 @@ acpi_ds_is_result_used (
*/
if ((!op->common.parent) ||
(op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
- /*
- * If this is the last statement in the method, we know it is not a
- * Return() operator (would not come here.) The following code is the
- * optional support for a so-called "implicit return". Some AML code
- * assumes that the last value of the method is "implicitly" returned
- * to the caller. Just save the last result as the return value.
- * NOTE: this is optional because the ASL language does not actually
- * support this behavior.
- */
- if ((acpi_gbl_enable_interpreter_slack) &&
- (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] will be implicitly returned\n",
- acpi_ps_get_opcode_name (op->common.aml_opcode)));
-
- /* Use the top of the result stack as the implicit return value */
-
- walk_state->return_desc = walk_state->results->results.obj_desc[0];
- return_VALUE (TRUE);
- }
-
/* No parent, the return value cannot possibly be used */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode)));
return_VALUE (FALSE);
}
@@ -262,9 +365,8 @@ acpi_ds_delete_result_if_not_used (
}
if (!acpi_ds_is_result_used (op, walk_state)) {
- /*
- * Must pop the result stack (obj_desc should be equal to result_obj)
- */
+ /* Must pop the result stack (obj_desc should be equal to result_obj) */
+
status = acpi_ds_result_pop (&obj_desc, walk_state);
if (ACPI_SUCCESS (status)) {
acpi_ut_remove_reference (result_obj);
@@ -338,9 +440,8 @@ acpi_ds_clear_operands (
ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
- /*
- * Remove a reference on each operand on the stack
- */
+ /* Remove a reference on each operand on the stack */
+
for (i = 0; i < walk_state->num_operands; i++) {
/*
* Remove a reference to all operands, including both
@@ -407,11 +508,7 @@ acpi_ds_create_operand (
return_ACPI_STATUS (status);
}
- /*
- * All prefixes have been handled, and the name is
- * in name_string
- */
-
+ /* All prefixes have been handled, and the name is in name_string */
/*
* Special handling for buffer_field declarations. This is a deferred
@@ -586,7 +683,8 @@ acpi_ds_create_operand (
*
* FUNCTION: acpi_ds_create_operands
*
- * PARAMETERS: first_arg - First argument of a parser argument tree
+ * PARAMETERS: walk_state - Current state
+ * first_arg - First argument of a parser argument tree
*
* RETURN: Status
*
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index b02322e213de9d..2071a0d2bbbb95 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -91,6 +91,7 @@ acpi_ds_get_predicate_value (
union acpi_operand_object *result_obj) {
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
+ union acpi_operand_object *local_obj_desc = NULL;
ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state);
@@ -130,12 +131,17 @@ acpi_ds_get_predicate_value (
}
/*
- * Result of predicate evaluation currently must
- * be a number
+ * Result of predicate evaluation must be an Integer
+ * object. Implicitly convert the argument if necessary.
*/
- if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER) {
+ status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad predicate (not a number) obj_desc=%p State=%p Type=%X\n",
+ "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
status = AE_AML_OPERAND_TYPE;
@@ -144,13 +150,13 @@ acpi_ds_get_predicate_value (
/* Truncate the predicate to 32-bits if necessary */
- acpi_ex_truncate_for32bit_table (obj_desc);
+ acpi_ex_truncate_for32bit_table (local_obj_desc);
/*
* Save the result of the predicate evaluation on
* the control stack
*/
- if (obj_desc->integer.value) {
+ if (local_obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
}
else {
@@ -170,12 +176,15 @@ cleanup:
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc, walk_state));
+ ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state));
/*
* Delete the predicate result object (we know that
* we don't need it anymore)
*/
+ if (local_obj_desc != obj_desc) {
+ acpi_ut_remove_reference (local_obj_desc);
+ }
acpi_ut_remove_reference (obj_desc);
walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
@@ -306,9 +315,10 @@ acpi_ds_exec_begin_op (
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
- /* most operators with arguments */
- /* Start a new result/operand state */
-
+ /*
+ * Most operators with arguments.
+ * Start a new result/operand state
+ */
status = acpi_ds_result_stack_push (walk_state);
break;
@@ -471,20 +481,41 @@ acpi_ds_exec_end_op (
/* 1 Operand, 0 external_result, 0 internal_result */
status = acpi_ds_exec_end_control_op (walk_state, op);
- if (ACPI_FAILURE (status)) {
- break;
- }
- status = acpi_ds_result_stack_pop (walk_state);
+ /* Make sure to properly pop the result stack */
+
+ if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ }
+ else if (status == AE_CTRL_PENDING) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ if (ACPI_SUCCESS (status)) {
+ status = AE_CTRL_PENDING;
+ }
+ }
break;
case AML_TYPE_METHOD_CALL:
+ /*
+ * If the method is referenced from within a package
+ * declaration, it is not a invocation of the method, just
+ * a reference to it.
+ */
+ if ((op->asl.parent) &&
+ ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) ||
+ (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op));
+ op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object;
+ acpi_ut_add_reference (op->asl.value.arg->asl.node->object);
+ return_ACPI_STATUS (AE_OK);
+ }
+
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op));
/*
- * (AML_METHODCALL) Op->Value->Arg->Node contains
+ * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
* the method Node pointer
*/
/* next_op points to the op that holds the method name */
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 8d4219388c9a8d..fdf143b405be7f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -514,7 +514,7 @@ out:
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_ec_dir;
+static struct proc_dir_entry *acpi_ec_dir;
static int
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index a48820152ccdc8..0bfec10a5f1e90 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -149,7 +149,9 @@ acpi_install_fixed_event_handler (
acpi_gbl_fixed_event_handlers[event].handler = handler;
acpi_gbl_fixed_event_handlers[event].context = context;
- status = acpi_enable_event (event, 0);
+ status = acpi_clear_event (event);
+ if (ACPI_SUCCESS(status))
+ status = acpi_enable_event (event, 0);
if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Could not enable fixed event.\n"));
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index fc54d4d0ccabea..b542dcd58c0742 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -95,6 +95,7 @@ acpi_ex_get_object_reference (
switch (obj_desc->reference.opcode) {
case AML_LOCAL_OP:
case AML_ARG_OP:
+ case AML_DEBUG_OP:
/* The referenced object is the pseudo-node for the local/arg */
@@ -103,7 +104,7 @@ acpi_ex_get_object_reference (
default:
- ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n",
+ ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n",
obj_desc->reference.opcode));
return_ACPI_STATUS (AE_AML_INTERNAL);
}
@@ -121,7 +122,7 @@ acpi_ex_get_object_reference (
default:
- ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n",
+ ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n",
ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
return_ACPI_STATUS (AE_TYPE);
}
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index 23964e70a89bf5..8be4d80ceed594 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -442,6 +442,12 @@ acpi_ex_opcode_2A_1T_1R (
return_desc->reference.object = operand[0];
}
+ /*
+ * Add a reference to the target package/buffer/string for the life
+ * of the index.
+ */
+ acpi_ut_add_reference (operand[0]);
+
/* Complete the Index reference object */
return_desc->reference.opcode = AML_INDEX_OP;
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 9cccf8299dd835..7be60491115684 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -422,6 +422,12 @@ acpi_ex_resolve_multiple (
* This could of course in turn be another reference object.
*/
obj_desc = *(obj_desc->reference.where);
+ if (!obj_desc) {
+ /* NULL package elements are allowed */
+
+ type = 0; /* Uninitialized */
+ goto exit;
+ }
break;
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index e663a48f8a1cb6..d3677feb07fd9b 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -206,7 +206,6 @@ acpi_ex_store_object_to_object (
{
union acpi_operand_object *actual_src_desc;
acpi_status status = AE_OK;
- acpi_object_type original_src_type;
ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
@@ -223,8 +222,7 @@ acpi_ex_store_object_to_object (
return_ACPI_STATUS (status);
}
- original_src_type = ACPI_GET_OBJECT_TYPE (source_desc);
- if (original_src_type != ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the current type
@@ -275,8 +273,7 @@ acpi_ex_store_object_to_object (
* Note: There is different store behavior depending on the original
* source type
*/
- status = acpi_ex_store_buffer_to_buffer (original_src_type, actual_src_desc,
- dest_desc);
+ status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
break;
case ACPI_TYPE_PACKAGE:
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index 4e2b442ee5a391..05e1ecae8d92be 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -66,7 +66,6 @@
acpi_status
acpi_ex_store_buffer_to_buffer (
- acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc)
{
@@ -77,9 +76,8 @@ acpi_ex_store_buffer_to_buffer (
ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
- /*
- * We know that source_desc is a buffer by now
- */
+ /* We know that source_desc is a buffer by now */
+
buffer = (u8 *) source_desc->buffer.pointer;
length = source_desc->buffer.length;
@@ -105,7 +103,17 @@ acpi_ex_store_buffer_to_buffer (
ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
+#ifdef ACPI_OBSOLETE_BEHAVIOR
+ /*
+ * NOTE: ACPI versions up to 3.0 specified that the buffer must be
+ * truncated if the string is smaller than the buffer. However, "other"
+ * implementations of ACPI never did this and thus became the defacto
+ * standard. ACPi 3.0_a changes this behavior such that the buffer
+ * is no longer truncated.
+ */
+
/*
+ * OBSOLETE BEHAVIOR:
* If the original source was a string, we must truncate the buffer,
* according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
* copy must not truncate the original buffer.
@@ -115,6 +123,7 @@ acpi_ex_store_buffer_to_buffer (
target_desc->buffer.length = length;
}
+#endif
}
else {
/* Truncate the source, copy only what will fit */
@@ -159,9 +168,8 @@ acpi_ex_store_string_to_string (
ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
- /*
- * We know that source_desc is a string by now.
- */
+ /* We know that source_desc is a string by now */
+
buffer = (u8 *) source_desc->string.pointer;
length = source_desc->string.length;
@@ -185,9 +193,8 @@ acpi_ex_store_string_to_string (
*/
if (target_desc->string.pointer &&
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- /*
- * Only free if not a pointer into the DSDT
- */
+ /* Only free if not a pointer into the DSDT */
+
ACPI_MEM_FREE (target_desc->string.pointer);
}
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 2c5422dfecb5af..14192ee55f8f1d 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -50,8 +50,8 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION(ACPI_FAN_DRIVER_NAME);
MODULE_LICENSE("GPL");
-int acpi_fan_add (struct acpi_device *device);
-int acpi_fan_remove (struct acpi_device *device, int type);
+static int acpi_fan_add (struct acpi_device *device);
+static int acpi_fan_remove (struct acpi_device *device, int type);
static struct acpi_driver acpi_fan_driver = {
.name = ACPI_FAN_DRIVER_NAME,
@@ -72,27 +72,24 @@ struct acpi_fan {
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_fan_dir;
+static struct proc_dir_entry *acpi_fan_dir;
static int
acpi_fan_read_state (struct seq_file *seq, void *offset)
{
- struct acpi_fan *fan = (struct acpi_fan *) seq->private;
+ struct acpi_fan *fan = seq->private;
int state = 0;
ACPI_FUNCTION_TRACE("acpi_fan_read_state");
- if (!fan)
- goto end;
-
- if (acpi_bus_get_power(fan->handle, &state))
- goto end;
-
- seq_printf(seq, "status: %s\n",
- !state?"on":"off");
-
-end:
+ if (fan) {
+ if (acpi_bus_get_power(fan->handle, &state))
+ seq_printf(seq, "status: ERROR\n");
+ else
+ seq_printf(seq, "status: %s\n",
+ !state?"on":"off");
+ }
return_VALUE(0);
}
@@ -197,7 +194,7 @@ acpi_fan_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
-int
+static int
acpi_fan_add (
struct acpi_device *device)
{
@@ -243,7 +240,7 @@ end:
}
-int
+static int
acpi_fan_remove (
struct acpi_device *device,
int type)
@@ -265,7 +262,7 @@ acpi_fan_remove (
}
-int __init
+static int __init
acpi_fan_init (void)
{
int result = 0;
@@ -287,7 +284,7 @@ acpi_fan_init (void)
}
-void __exit
+static void __exit
acpi_fan_exit (void)
{
ACPI_FUNCTION_TRACE("acpi_fan_exit");
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 94a76e520e213e..0fb731a470dce9 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -155,7 +155,7 @@ struct ibm_struct {
int experimental;
};
-struct proc_dir_entry *proc_dir = NULL;
+static struct proc_dir_entry *proc_dir = NULL;
#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -856,7 +856,7 @@ static int beep_write(struct ibm_struct *ibm, char *buf)
return 0;
}
-struct ibm_struct ibms[] = {
+static struct ibm_struct ibms[] = {
{
.name = "driver",
.init = driver_init,
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 9bfce46cd435e2..a82834b32752b0 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -170,7 +170,7 @@ acpi_table_parse_srat (
int __init
-acpi_numa_init()
+acpi_numa_init(void)
{
int result;
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 94a511315c8ba9..5a9128de62261f 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -563,7 +563,7 @@ acpi_os_write_pci_configuration (struct acpi_pci_id *pci_id, u32 reg, acpi_integ
}
/* TODO: Change code to take advantage of driver model more */
-void
+static void
acpi_os_derive_pci_id_2 (
acpi_handle rhandle, /* upper bound */
acpi_handle chandle, /* current node */
@@ -1071,7 +1071,7 @@ acpi_os_signal (
}
EXPORT_SYMBOL(acpi_os_signal);
-int __init
+static int __init
acpi_os_name_setup(char *str)
{
char *p = acpi_os_name;
@@ -1101,7 +1101,7 @@ __setup("acpi_os_name=", acpi_os_name_setup);
* empty string disables _OSI
* TBD additional string adds to _OSI
*/
-int __init
+static int __init
acpi_osi_setup(char *str)
{
if (str == NULL || *str == '\0') {
@@ -1119,7 +1119,7 @@ acpi_osi_setup(char *str)
__setup("acpi_osi=", acpi_osi_setup);
/* enable serialization to combat AE_ALREADY_EXISTS errors */
-int __init
+static int __init
acpi_serialize_setup(char *str)
{
printk(KERN_INFO PREFIX "serialize enabled\n");
@@ -1140,7 +1140,7 @@ __setup("acpi_serialize", acpi_serialize_setup);
* Run-time events on the same GPE this flag is available
* to tell Linux to keep the wake-time GPEs enabled at run-time.
*/
-int __init
+static int __init
acpi_wake_gpes_always_on_setup(char *str)
{
printk(KERN_INFO PREFIX "wake GPEs not disabled\n");
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index c1360fc23cee18..03e33fedc11a2f 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -522,7 +522,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
-/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R),
/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index fd2751f512e37d..e79edb53cb3b96 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -1187,8 +1187,8 @@ acpi_ps_parse_aml (
previous_walk_state = walk_state;
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, State=%p\n",
- walk_state->return_desc, walk_state));
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, implicit_value=%p State=%p\n",
+ walk_state->return_desc, walk_state->implicit_return_obj, walk_state));
/* Check if we have restarted a preempted walk */
@@ -1200,8 +1200,20 @@ acpi_ps_parse_aml (
* If the method return value is not used by the parent,
* The object is deleted
*/
- status = acpi_ds_restart_control_method (walk_state,
- previous_walk_state->return_desc);
+ if (!previous_walk_state->return_desc) {
+ status = acpi_ds_restart_control_method (walk_state,
+ previous_walk_state->implicit_return_obj);
+ }
+ else {
+ /*
+ * We have a valid return value, delete any implicit
+ * return value.
+ */
+ acpi_ds_clear_implicit_return (previous_walk_state);
+
+ status = acpi_ds_restart_control_method (walk_state,
+ previous_walk_state->return_desc);
+ }
if (ACPI_SUCCESS (status)) {
walk_state->walk_type |= ACPI_WALK_METHOD_RESTART;
}
@@ -1218,12 +1230,26 @@ acpi_ps_parse_aml (
* value (if any)
*/
else if (previous_walk_state->caller_return_desc) {
- *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc; /* NULL if no return value */
+ if (previous_walk_state->implicit_return_obj) {
+ *(previous_walk_state->caller_return_desc) = previous_walk_state->implicit_return_obj;
+ }
+ else {
+ /* NULL if no return value */
+
+ *(previous_walk_state->caller_return_desc) = previous_walk_state->return_desc;
+ }
}
- else if (previous_walk_state->return_desc) {
- /* Caller doesn't want it, must delete it */
+ else {
+ if (previous_walk_state->return_desc) {
+ /* Caller doesn't want it, must delete it */
- acpi_ut_remove_reference (previous_walk_state->return_desc);
+ acpi_ut_remove_reference (previous_walk_state->return_desc);
+ }
+ if (previous_walk_state->implicit_return_obj) {
+ /* Caller doesn't want it, must delete it */
+
+ acpi_ut_remove_reference (previous_walk_state->implicit_return_obj);
+ }
}
acpi_ds_delete_walk_state (previous_walk_state);
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index e04b1b73606b95..110d2ce917b643 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -44,7 +44,6 @@
#include <acpi/acpi.h>
#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME ("pswalk")
@@ -52,256 +51,65 @@
/*******************************************************************************
*
- * FUNCTION: acpi_ps_get_next_walk_op
+ * FUNCTION: acpi_ps_delete_parse_tree
*
- * PARAMETERS: walk_state - Current state of the walk
- * Op - Current Op to be walked
- * ascending_callback - Procedure called when Op is complete
+ * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: Get the next Op in a walk of the parse tree.
+ * DESCRIPTION: Delete a portion of or an entire parse tree.
*
******************************************************************************/
-acpi_status
-acpi_ps_get_next_walk_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_parse_upwards ascending_callback)
+void
+acpi_ps_delete_parse_tree (
+ union acpi_parse_object *subtree_root)
{
- union acpi_parse_object *next;
- union acpi_parse_object *parent;
- union acpi_parse_object *grand_parent;
- acpi_status status;
+ union acpi_parse_object *op = subtree_root;
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent = NULL;
- ACPI_FUNCTION_TRACE_PTR ("ps_get_next_walk_op", op);
+ ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
- /* Check for a argument only if we are descending in the tree */
+ /* Visit all nodes in the subtree */
- if (walk_state->next_op_info != ACPI_NEXT_OP_UPWARD) {
- /* Look for an argument or child of the current op */
+ while (op) {
+ /* Check if we are not ascending */
- next = acpi_ps_get_arg (op, 0);
- if (next) {
- /* Still going downward in tree (Op is not completed yet) */
+ if (op != parent) {
+ /* Look for an argument or child of the current op */
- walk_state->prev_op = op;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
+ next = acpi_ps_get_arg (op, 0);
+ if (next) {
+ /* Still going downward in tree (Op is not completed yet) */
- return_ACPI_STATUS (AE_OK);
+ op = next;
+ continue;
+ }
}
/*
- * No more children, this Op is complete. Save Next and Parent
- * in case the Op object gets deleted by the callback routine
+ * No more children, this Op is complete.
*/
- next = op->common.next;
- parent = op->common.parent;
-
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
+ next = op->common.next;
+ parent = op->common.parent;
- status = ascending_callback (walk_state);
+ acpi_ps_free_op (op);
/*
* If we are back to the starting point, the walk is complete.
*/
- if (op == walk_state->origin) {
- /* Reached the point of origin, the walk is complete */
-
- walk_state->prev_op = op;
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (status);
+ if (op == subtree_root) {
+ return_VOID;
}
-
- /*
- * Check for a sibling to the current op. A sibling means
- * we are still going "downward" in the tree.
- */
if (next) {
- /* There is a sibling, it will be next */
-
- walk_state->prev_op = op;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- /* Continue downward */
-
- return_ACPI_STATUS (status);
+ op = next;
}
-
- /*
- * Drop into the loop below because we are moving upwards in
- * the tree
- */
- }
- else {
- /*
- * We are resuming a walk, and we were (are) going upward in the tree.
- * So, we want to drop into the parent loop below.
- */
- parent = op;
- }
-
- /*
- * Look for a sibling of the current Op's parent
- * Continue moving up the tree until we find a node that has not been
- * visited, or we get back to where we started.
- */
- while (parent) {
- /* We are moving up the tree, therefore this parent Op is complete */
-
- grand_parent = parent->common.parent;
- next = parent->common.next;
-
- walk_state->op = parent;
- walk_state->op_info = acpi_ps_get_opcode_info (parent->common.aml_opcode);
- walk_state->opcode = parent->common.aml_opcode;
-
- status = ascending_callback (walk_state);
-
- /*
- * If we are back to the starting point, the walk is complete.
- */
- if (parent == walk_state->origin) {
- /* Reached the point of origin, the walk is complete */
-
- walk_state->prev_op = parent;
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (status);
- }
-
- /*
- * If there is a sibling to this parent (it is not the starting point
- * Op), then we will visit it.
- */
- if (next) {
- /* found sibling of parent */
-
- walk_state->prev_op = parent;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- return_ACPI_STATUS (status);
+ else {
+ op = parent;
}
-
- /* No siblings, no errors, just move up one more level in the tree */
-
- op = parent;
- parent = grand_parent;
- walk_state->prev_op = op;
}
-
-
- /*
- * Got all the way to the top of the tree, we must be done!
- * However, the code should have terminated in the loop above
- */
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_completed_op
- *
- * PARAMETERS: State - Walk state
- * Op - Completed op
- *
- * RETURN: AE_OK
- *
- * DESCRIPTION: Callback function for acpi_ps_get_next_walk_op(). Used during
- * acpi_ps_delete_parse tree to delete Op objects when all sub-objects
- * have been visited (and deleted.)
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ps_delete_completed_op (
- struct acpi_walk_state *walk_state)
-{
-
- acpi_ps_free_op (walk_state->op);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_parse_tree
- *
- * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete a portion of or an entire parse tree.
- *
- ******************************************************************************/
-
-void
-acpi_ps_delete_parse_tree (
- union acpi_parse_object *subtree_root)
-{
- struct acpi_walk_state *walk_state;
- struct acpi_thread_state *thread;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
-
-
- if (!subtree_root) {
- return_VOID;
- }
-
- /* Create and initialize a new walk list */
-
- thread = acpi_ut_create_thread_state ();
- if (!thread) {
- return_VOID;
- }
-
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread);
- if (!walk_state) {
- return_VOID;
- }
-
- walk_state->parse_flags = 0;
- walk_state->descending_callback = NULL;
- walk_state->ascending_callback = NULL;
-
- walk_state->origin = subtree_root;
- walk_state->next_op = subtree_root;
-
- /* Head downward in the tree */
-
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- /* Visit all nodes in the subtree */
-
- while (walk_state->next_op) {
- status = acpi_ps_get_next_walk_op (walk_state, walk_state->next_op,
- acpi_ps_delete_completed_op);
- if (ACPI_FAILURE (status)) {
- break;
- }
- }
-
- /* We are done with this walk */
-
- acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state, thread));
- acpi_ds_delete_walk_state (walk_state);
-
return_VOID;
}
-
-
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index a4750192a31995..12b0eea6340733 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -42,8 +42,8 @@
#define _COMPONENT ACPI_PCI_COMPONENT
ACPI_MODULE_NAME ("pci_irq")
-struct acpi_prt_list acpi_prt;
-DEFINE_SPINLOCK(acpi_prt_lock);
+static struct acpi_prt_list acpi_prt;
+static DEFINE_SPINLOCK(acpi_prt_lock);
/* --------------------------------------------------------------------------
PCI IRQ Routing Table (PRT) Support
@@ -281,7 +281,8 @@ acpi_pci_irq_lookup (
int device,
int pin,
int *edge_level,
- int *active_high_low)
+ int *active_high_low,
+ char **link)
{
struct acpi_prt_entry *entry = NULL;
int segment = pci_domain_nr(bus);
@@ -301,7 +302,8 @@ acpi_pci_irq_lookup (
}
if (entry->link.handle) {
- irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index, edge_level, active_high_low);
+ irq = acpi_pci_link_get_irq(entry->link.handle,
+ entry->link.index, edge_level, active_high_low, link);
if (irq < 0) {
ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n"));
return_VALUE(-1);
@@ -327,7 +329,8 @@ acpi_pci_irq_derive (
struct pci_dev *dev,
int pin,
int *edge_level,
- int *active_high_low)
+ int *active_high_low,
+ char **link)
{
struct pci_dev *bridge = dev;
int irq = -1;
@@ -360,7 +363,7 @@ acpi_pci_irq_derive (
}
irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn),
- pin, edge_level, active_high_low);
+ pin, edge_level, active_high_low, link);
}
if (irq < 0) {
@@ -389,6 +392,7 @@ acpi_pci_irq_enable (
int edge_level = ACPI_LEVEL_SENSITIVE;
int active_high_low = ACPI_ACTIVE_LOW;
extern int via_interrupt_line_quirk;
+ char *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
@@ -411,21 +415,23 @@ acpi_pci_irq_enable (
* First we check the PCI IRQ routing table (PRT) for an IRQ. PRT
* values override any BIOS-assigned IRQs set during boot.
*/
- irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, &edge_level, &active_high_low);
+ irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
+ &edge_level, &active_high_low, &link);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (irq < 0)
- irq = acpi_pci_irq_derive(dev, pin, &edge_level, &active_high_low);
+ irq = acpi_pci_irq_derive(dev, pin, &edge_level,
+ &active_high_low, &link);
/*
* No IRQ known to the ACPI subsystem - maybe the BIOS /
* driver reported one, then use it. Exit in any case.
*/
if (irq < 0) {
- printk(KERN_WARNING PREFIX "PCI interrupt %s[%c]: no GSI",
+ printk(KERN_WARNING PREFIX "PCI Interrupt %s[%c]: no GSI",
pci_name(dev), ('A' + pin));
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq >= 0 && (dev->irq <= 0xF)) {
@@ -443,9 +449,13 @@ acpi_pci_irq_enable (
dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
- printk(KERN_INFO PREFIX "PCI interrupt %s[%c] -> GSI %u "
- "(%s, %s) -> IRQ %d\n",
- pci_name(dev), 'A' + pin, irq,
+ printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
+ pci_name(dev), 'A' + pin);
+
+ if (link)
+ printk("Link [%s] -> ", link);
+
+ printk("GSI %u (%s, %s) -> IRQ %d\n", irq,
(edge_level == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(active_high_low == ACPI_ACTIVE_LOW) ? "low" : "high",
dev->irq);
@@ -482,14 +492,14 @@ acpi_pci_irq_disable (
* First we check the PCI IRQ routing table (PRT) for an IRQ.
*/
gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin,
- &edge_level, &active_high_low);
+ &edge_level, &active_high_low, NULL);
/*
* If no PRT entry was found, we'll try to derive an IRQ from the
* device's parent bridge.
*/
if (gsi < 0)
gsi = acpi_pci_irq_derive(dev, pin,
- &edge_level, &active_high_low);
+ &edge_level, &active_high_low, NULL);
if (gsi < 0)
return_VOID;
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 3191b5ff105e1a..520b28ad0740e6 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -522,9 +522,11 @@ acpi_irq_penalty_init(void)
static int acpi_irq_balance; /* 0: static, 1: balance */
-static int acpi_pci_link_allocate(struct acpi_pci_link* link) {
- int irq;
- int i;
+static int acpi_pci_link_allocate(
+ struct acpi_pci_link *link)
+{
+ int irq;
+ int i;
ACPI_FUNCTION_TRACE("acpi_pci_link_allocate");
@@ -597,8 +599,9 @@ int
acpi_pci_link_get_irq (
acpi_handle handle,
int index,
- int* edge_level,
- int* active_high_low)
+ int *edge_level,
+ int *active_high_low,
+ char **name)
{
int result = 0;
struct acpi_device *device = NULL;
@@ -634,6 +637,7 @@ acpi_pci_link_get_irq (
if (edge_level) *edge_level = link->irq.edge_level;
if (active_high_low) *active_high_low = link->irq.active_high_low;
+ if (name) *name = acpi_device_bid(link->device);
return_VALUE(link->irq.active);
}
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 2adaba68b85b7f..7e6b8e3b2ed418 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -258,7 +258,7 @@ acpi_pci_root_add (
/* TBD: Locking */
list_add_tail(&root->node, &acpi_pci_roots);
- printk(KERN_INFO PREFIX "%s [%s] (%02x:%02x)\n",
+ printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n",
acpi_device_name(device), acpi_device_bid(device),
root->id.segment, root->id.bus);
@@ -272,7 +272,7 @@ acpi_pci_root_add (
root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus);
if (!root->bus) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
- "Bus %02x:%02x not present in PCI namespace\n",
+ "Bus %04x:%02x not present in PCI namespace\n",
root->id.segment, root->id.bus));
result = -ENODEV;
goto end;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 419b371d95ad83..373a3a95bb4e1b 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -58,8 +58,8 @@ ACPI_MODULE_NAME ("acpi_power")
#define ACPI_POWER_RESOURCE_STATE_ON 0x01
#define ACPI_POWER_RESOURCE_STATE_UNKNOWN 0xFF
-int acpi_power_add (struct acpi_device *device);
-int acpi_power_remove (struct acpi_device *device, int type);
+static int acpi_power_add (struct acpi_device *device);
+static int acpi_power_remove (struct acpi_device *device, int type);
static int acpi_power_open_fs(struct inode *inode, struct file *file);
static struct acpi_driver acpi_power_driver = {
@@ -479,7 +479,7 @@ end:
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_power_dir;
+static struct proc_dir_entry *acpi_power_dir;
static int acpi_power_seq_show(struct seq_file *seq, void *offset)
{
@@ -576,7 +576,7 @@ acpi_power_remove_fs (
Driver Interface
-------------------------------------------------------------------------- */
-int
+static int
acpi_power_add (
struct acpi_device *device)
{
@@ -642,7 +642,7 @@ end:
}
-int
+static int
acpi_power_remove (
struct acpi_device *device,
int type)
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index e517a11dc9c688..f4778747e889bd 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -105,7 +105,7 @@ static struct acpi_driver acpi_processor_driver = {
#define UNINSTALL_NOTIFY_HANDLER 2
-struct file_operations acpi_processor_info_fops = {
+static struct file_operations acpi_processor_info_fops = {
.open = acpi_processor_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
@@ -121,7 +121,7 @@ struct acpi_processor_errata errata;
Errata Handling
-------------------------------------------------------------------------- */
-int
+static int
acpi_processor_errata_piix4 (
struct pci_dev *dev)
{
@@ -259,7 +259,7 @@ acpi_processor_errata (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_processor_dir = NULL;
+static struct proc_dir_entry *acpi_processor_dir = NULL;
static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset)
{
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 8711236d28b665..12bd980a12e940 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -345,7 +345,7 @@ end:
return_VALUE(0);
}
-int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
+static int acpi_processor_limit_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_limit_seq_show,
PDE(inode)->data);
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index db0b31d2b3eb3b..be9f569d39d33f 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -308,7 +308,7 @@ end:
return_VALUE(0);
}
-int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
+static int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_processor_throttling_seq_show,
PDE(inode)->data);
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c
index ec4ae9a15cb0c5..4788c079735d8a 100644
--- a/drivers/acpi/resources/rsaddr.c
+++ b/drivers/acpi/resources/rsaddr.c
@@ -110,13 +110,13 @@ acpi_rs_address16_resource (
buffer += 2;
temp8 = *buffer;
- /* Values 0-2 are valid */
+ /* Values 0-2 and 0xC0-0xFF are valid */
- if (temp8 > 2) {
+ if ((temp8 > 2) && (temp8 < 0xC0)) {
return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
}
- output_struct->data.address16.resource_type = temp8 & 0x03;
+ output_struct->data.address16.resource_type = temp8;
/*
* Get the General Flags (Byte4)
@@ -496,12 +496,13 @@ acpi_rs_address32_resource (
buffer += 2;
temp8 = *buffer;
- /* Values 0-2 are valid */
- if(temp8 > 2) {
+ /* Values 0-2 and 0xC0-0xFF are valid */
+
+ if ((temp8 > 2) && (temp8 < 0xC0)) {
return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
}
- output_struct->data.address32.resource_type = temp8 & 0x03;
+ output_struct->data.address32.resource_type = temp8;
/*
* Get the General Flags (Byte4)
@@ -850,6 +851,7 @@ acpi_rs_address64_resource (
struct acpi_resource *output_struct = (void *) *output_buffer;
u16 temp16;
u8 temp8;
+ u8 resource_type;
u8 *temp_ptr;
acpi_size struct_size;
u32 index;
@@ -860,6 +862,7 @@ acpi_rs_address64_resource (
buffer = byte_stream_buffer;
struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
+ resource_type = *buffer;
/*
* Point past the Descriptor to get the number of bytes consumed
@@ -882,13 +885,13 @@ acpi_rs_address64_resource (
buffer += 2;
temp8 = *buffer;
- /* Values 0-2 are valid */
+ /* Values 0-2 and 0xC0-0xFF are valid */
- if(temp8 > 2) {
+ if ((temp8 > 2) && (temp8 < 0xC0)) {
return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE);
}
- output_struct->data.address64.resource_type = temp8 & 0x03;
+ output_struct->data.address64.resource_type = temp8;
/*
* Get the General Flags (Byte4)
@@ -942,98 +945,113 @@ acpi_rs_address64_resource (
}
}
+ if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
+ /* Move past revision_id and Reserved byte */
+
+ buffer += 2;
+ }
+
/*
- * Get Granularity (Bytes 6-13)
+ * Get Granularity (Bytes 6-13) or (Bytes 8-15)
*/
buffer += 1;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.granularity, buffer);
/*
- * Get min_address_range (Bytes 14-21)
+ * Get min_address_range (Bytes 14-21) or (Bytes 16-23)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.min_address_range, buffer);
/*
- * Get max_address_range (Bytes 22-29)
+ * Get max_address_range (Bytes 22-29) or (Bytes 24-31)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.max_address_range, buffer);
/*
- * Get address_translation_offset (Bytes 30-37)
+ * Get address_translation_offset (Bytes 30-37) or (Bytes 32-39)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_translation_offset, buffer);
/*
- * Get address_length (Bytes 38-45)
+ * Get address_length (Bytes 38-45) or (Bytes 40-47)
*/
buffer += 8;
ACPI_MOVE_64_TO_64 (&output_struct->data.address64.address_length, buffer);
- /*
- * Resource Source Index (if present)
- */
- buffer += 8;
+ output_struct->data.address64.resource_source.index = 0x00;
+ output_struct->data.address64.resource_source.string_length = 0;
+ output_struct->data.address64.resource_source.string_ptr = NULL;
- /*
- * This will leave us pointing to the Resource Source Index
- * If it is present, then save it off and calculate the
- * pointer to where the null terminated string goes:
- * Each Interrupt takes 32-bits + the 5 bytes of the
- * stream that are default.
- *
- * Note: Some resource descriptors will have an additional null, so
- * we add 1 to the length.
- */
- if (*bytes_consumed > (46 + 1)) {
- /* Dereference the Index */
+ if (resource_type == ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE) {
+ /* Get type_specific_attribute (Bytes 48-55) */
- temp8 = *buffer;
- output_struct->data.address64.resource_source.index =
- (u32) temp8;
+ buffer += 8;
+ ACPI_MOVE_64_TO_64 (&output_struct->data.address64.type_specific_attributes, buffer);
+ }
+ else {
+ output_struct->data.address64.type_specific_attributes = 0;
- /* Point to the String */
+ /*
+ * Resource Source Index (if present)
+ */
+ buffer += 8;
- buffer += 1;
+ /*
+ * This will leave us pointing to the Resource Source Index
+ * If it is present, then save it off and calculate the
+ * pointer to where the null terminated string goes:
+ * Each Interrupt takes 32-bits + the 5 bytes of the
+ * stream that are default.
+ *
+ * Note: Some resource descriptors will have an additional null, so
+ * we add 1 to the length.
+ */
+ if (*bytes_consumed > (46 + 1)) {
+ /* Dereference the Index */
- /* Point the String pointer to the end of this structure */
+ temp8 = *buffer;
+ output_struct->data.address64.resource_source.index =
+ (u32) temp8;
- output_struct->data.address64.resource_source.string_ptr =
- (char *)((u8 *)output_struct + struct_size);
+ /* Point to the String */
- temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
+ buffer += 1;
- /* Copy the string into the buffer */
+ /* Point the String pointer to the end of this structure */
- index = 0;
- while (0x00 != *buffer) {
- *temp_ptr = *buffer;
+ output_struct->data.address64.resource_source.string_ptr =
+ (char *)((u8 *)output_struct + struct_size);
- temp_ptr += 1;
- buffer += 1;
- index += 1;
- }
+ temp_ptr = (u8 *) output_struct->data.address64.resource_source.string_ptr;
- /*
- * Add the terminating null
- */
- *temp_ptr = 0x00;
- output_struct->data.address64.resource_source.string_length = index + 1;
+ /* Copy the string into the buffer */
- /*
- * In order for the struct_size to fall on a 32-bit boundary,
- * calculate the length of the string and expand the
- * struct_size to the next 32-bit boundary.
- */
- temp8 = (u8) (index + 1);
- struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
- }
- else {
- output_struct->data.address64.resource_source.index = 0x00;
- output_struct->data.address64.resource_source.string_length = 0;
- output_struct->data.address64.resource_source.string_ptr = NULL;
+ index = 0;
+ while (0x00 != *buffer) {
+ *temp_ptr = *buffer;
+
+ temp_ptr += 1;
+ buffer += 1;
+ index += 1;
+ }
+
+ /*
+ * Add the terminating null
+ */
+ *temp_ptr = 0x00;
+ output_struct->data.address64.resource_source.string_length = index + 1;
+
+ /*
+ * In order for the struct_size to fall on a 32-bit boundary,
+ * calculate the length of the string and expand the
+ * struct_size to the next 32-bit boundary.
+ */
+ temp8 = (u8) (index + 1);
+ struct_size += ACPI_ROUND_UP_to_32_bITS (temp8);
+ }
}
/*
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 1113af74693954..8a5f0a52371d49 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -376,6 +376,20 @@ acpi_rs_get_list_length (
break;
+ case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
+ /*
+ * 64-Bit Address Resource
+ */
+ buffer = byte_stream_buffer;
+
+ ++buffer;
+ ACPI_MOVE_16_TO_16 (&temp16, buffer);
+
+ bytes_consumed = temp16 + 3;
+ structure_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_address64);
+ break;
+
+
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index a869980f7fe454..eef1b1f2c68596 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -571,7 +571,7 @@ acpi_rs_dump_address16 (
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
+ acpi_os_printf (" Type Specific: %s Translation\n",
ACPI_SPARSE_TRANSLATION ==
address16_data->attribute.io.translation_attribute ?
"Sparse" : "Dense");
@@ -584,8 +584,8 @@ acpi_rs_dump_address16 (
default:
- acpi_os_printf ("Invalid resource type. Exiting.\n");
- return;
+ acpi_os_printf ("0x%2.2X\n", address16_data->resource_type);
+ break;
}
acpi_os_printf (" Resource %s\n",
@@ -718,7 +718,7 @@ acpi_rs_dump_address32 (
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
+ acpi_os_printf (" Type Specific: %s Translation\n",
ACPI_SPARSE_TRANSLATION ==
address32_data->attribute.io.translation_attribute ?
"Sparse" : "Dense");
@@ -731,8 +731,8 @@ acpi_rs_dump_address32 (
default:
- acpi_os_printf (" Invalid Resource Type..exiting.\n");
- return;
+ acpi_os_printf (" Resource Type: 0x%2.2X\n", address32_data->resource_type);
+ break;
}
acpi_os_printf (" Resource %s\n",
@@ -865,7 +865,7 @@ acpi_rs_dump_address64 (
break;
}
- acpi_os_printf (" Type Specific: %s Translation\n",
+ acpi_os_printf (" Type Specific: %s Translation\n",
ACPI_SPARSE_TRANSLATION ==
address64_data->attribute.io.translation_attribute ?
"Sparse" : "Dense");
@@ -878,8 +878,8 @@ acpi_rs_dump_address64 (
default:
- acpi_os_printf (" Invalid Resource Type..exiting.\n");
- return;
+ acpi_os_printf (" Resource Type: 0x%2.2X\n", address64_data->resource_type);
+ break;
}
acpi_os_printf (" Resource %s\n",
@@ -913,7 +913,10 @@ acpi_rs_dump_address64 (
acpi_os_printf (" Address Length: %8.8X%8.8X\n",
ACPI_FORMAT_UINT64 (address64_data->address_length));
- if(0xFF != address64_data->resource_source.index) {
+ acpi_os_printf (" Type Specific Attributes: %8.8X%8.8X\n",
+ ACPI_FORMAT_UINT64 (address64_data->type_specific_attributes));
+
+ if (0xFF != address64_data->resource_source.index) {
acpi_os_printf (" Resource Source Index: %X\n",
address64_data->resource_source.index);
acpi_os_printf (" Resource Source: %s\n",
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 1297589d792f53..e49c1e030f99f7 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -178,6 +178,7 @@ acpi_rs_byte_stream_to_list (
case ACPI_RDESC_TYPE_QWORD_ADDRESS_SPACE:
+ case ACPI_RDESC_TYPE_EXTENDED_ADDRESS_SPACE:
/*
* 64-Bit Address Resource
*/
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f20d88d3c554bb..e7ca06626566e5 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -27,6 +27,10 @@ static LIST_HEAD(acpi_device_list);
DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
+static int
+acpi_bus_trim(struct acpi_device *start,
+ int rmdevice);
+
static void acpi_device_release(struct kobject * kobj)
{
struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
@@ -81,12 +85,37 @@ static struct kobj_type ktype_acpi_ns = {
.release = acpi_device_release,
};
+static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
+ char **envp, int num_envp, char *buffer,
+ int buffer_size)
+{
+ struct acpi_device *dev = to_acpi_device(kobj);
+ int i = 0;
+ int len = 0;
+
+ if (!dev->driver)
+ return 0;
+
+ if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
+ "PHYSDEVDRIVER=%s", dev->driver->name))
+ return -ENOMEM;
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+static struct kset_hotplug_ops namespace_hotplug_ops = {
+ .hotplug = &namespace_hotplug,
+};
+
static struct kset acpi_namespace_kset = {
.kobj = {
.name = "namespace",
},
.subsys = &acpi_subsys,
.ktype = &ktype_acpi_ns,
+ .hotplug_ops = &namespace_hotplug_ops,
};
@@ -358,7 +387,15 @@ setup_sys_fs_device_files (
struct acpi_device *dev,
acpi_device_sysfs_files *func)
{
- if (dev->flags.ejectable == 1)
+ acpi_status status;
+ acpi_handle temp = NULL;
+
+ /*
+ * If device has _EJ0, 'eject' file is created that is used to trigger
+ * hot-removal function from userland.
+ */
+ status = acpi_get_handle(dev->handle, "_EJ0", &temp);
+ if (ACPI_SUCCESS(status))
(*(func))(&dev->kobj,&acpi_device_attr_eject.attr);
}
@@ -857,7 +894,7 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device *
acpi_os_free(buffer.pointer);
}
-int acpi_device_set_context(struct acpi_device * device, int type)
+static int acpi_device_set_context(struct acpi_device * device, int type)
{
acpi_status status = AE_OK;
int result = 0;
@@ -882,7 +919,7 @@ int acpi_device_set_context(struct acpi_device * device, int type)
return result;
}
-void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
+static void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle, int type)
{
#ifdef CONFIG_ACPI_DEBUG_OUTPUT
char *type_string = NULL;
@@ -925,7 +962,7 @@ void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle,
}
-int
+static int
acpi_bus_remove (
struct acpi_device *dev,
int rmdevice)
@@ -1223,7 +1260,7 @@ int acpi_bus_scan (struct acpi_device *start)
EXPORT_SYMBOL(acpi_bus_scan);
-int
+static int
acpi_bus_trim(struct acpi_device *start,
int rmdevice)
{
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index be97f286957924..79c3a686bc4421 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -774,7 +774,7 @@ acpi_thermal_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_thermal_dir;
+static struct proc_dir_entry *acpi_thermal_dir;
static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
{
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index c0c9ea1084aa34..c84997c9f9640b 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -481,7 +481,7 @@ read_version(char* p)
#define PROC_TOSHIBA "toshiba"
-ProcItem proc_items[] =
+static ProcItem proc_items[] =
{
{ "lcd" , read_lcd , write_lcd },
{ "video" , read_video , write_video },
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 0b366d3b48667a..0fcd98bde0d105 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -659,15 +659,17 @@ acpi_ut_copy_simple_object (
/* Create an actual buffer only if length > 0 */
if (source_desc->buffer.length) {
- dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length);
+ dest_desc->buffer.pointer =
+ ACPI_MEM_ALLOCATE (source_desc->buffer.length);
if (!dest_desc->buffer.pointer) {
return (AE_NO_MEMORY);
}
/* Copy the actual buffer data */
- ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer,
- source_desc->buffer.length);
+ ACPI_MEMCPY (dest_desc->buffer.pointer,
+ source_desc->buffer.pointer,
+ source_desc->buffer.length);
}
}
break;
@@ -682,7 +684,8 @@ acpi_ut_copy_simple_object (
*/
if ((source_desc->string.pointer) &&
(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- dest_desc->string.pointer = ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
+ dest_desc->string.pointer =
+ ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
if (!dest_desc->string.pointer) {
return (AE_NO_MEMORY);
}
@@ -692,6 +695,14 @@ acpi_ut_copy_simple_object (
}
break;
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ /*
+ * We copied the reference object, so we now must add a reference
+ * to the object pointed to by the reference
+ */
+ acpi_ut_add_reference (source_desc->reference.object);
+ break;
+
default:
/* Nothing to do for other simple objects */
break;
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index e8ee13280bbf16..9a52ad52a23aea 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -46,6 +46,7 @@
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>
+#include <acpi/amlcode.h>
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ("utdelete")
@@ -562,8 +563,23 @@ acpi_ut_update_object_reference (
break;
- case ACPI_TYPE_REGION:
case ACPI_TYPE_LOCAL_REFERENCE:
+
+ /*
+ * The target of an Index (a package, string, or buffer) must track
+ * changes to the ref count of the index.
+ */
+ if (object->reference.opcode == AML_INDEX_OP) {
+ status = acpi_ut_create_update_state_and_push (
+ object->reference.object, action, &state_list);
+ if (ACPI_FAILURE (status)) {
+ goto error_exit;
+ }
+ }
+ break;
+
+
+ case ACPI_TYPE_REGION:
default:
/* No subobjects */
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index d3eb4db38f75ce..25b0f8ae1bc6fc 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -194,6 +194,8 @@ const char *acpi_gbl_highest_dstate_names[4] =
*/
const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] =
{
+ /* Operating System Vendor Strings */
+
"Linux",
"Windows 2000",
"Windows 2001",
@@ -202,7 +204,11 @@ const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STR
"Windows 2001 SP1",
"Windows 2001 SP2",
"Windows 2001 SP3",
- "Windows 2001 SP4"
+ "Windows 2001 SP4",
+
+ /* Feature Group Strings */
+
+ "Extended Address Space Descriptor"
};
@@ -355,6 +361,7 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]
/* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS},
/* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS},
/* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS},
+ /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS},
/* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE},
/* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE},
@@ -362,6 +369,7 @@ struct acpi_bit_register_info acpi_gbl_bit_register_info[ACPI_NUM_BITREG]
/* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE},
/* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE},
/* ACPI_BITREG_WAKE_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, 0, 0},
+ /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
/* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE},
/* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD},
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 4d32f6d18f648f..f6598547389b87 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -372,7 +372,7 @@ acpi_ut_strtoul64 (
u32 base,
acpi_integer *ret_integer)
{
- u32 this_digit;
+ u32 this_digit = 0;
acpi_integer return_value = 0;
acpi_integer quotient;
@@ -380,6 +380,10 @@ acpi_ut_strtoul64 (
ACPI_FUNCTION_TRACE ("ut_stroul64");
+ if ((!string) || !(*string)) {
+ goto error_exit;
+ }
+
switch (base) {
case ACPI_ANY_BASE:
case 10:
@@ -394,7 +398,7 @@ acpi_ut_strtoul64 (
/* Skip over any white space in the buffer */
while (ACPI_IS_SPACE (*string) || *string == '\t') {
- ++string;
+ string++;
}
/*
@@ -403,9 +407,9 @@ acpi_ut_strtoul64 (
*/
if (base == 0) {
if ((*string == '0') &&
- (ACPI_TOLOWER (*(++string)) == 'x')) {
+ (ACPI_TOLOWER (*(string + 1)) == 'x')) {
base = 16;
- ++string;
+ string += 2;
}
else {
base = 10;
@@ -416,10 +420,10 @@ acpi_ut_strtoul64 (
* For hexadecimal base, skip over the leading
* 0 or 0x, if they are present.
*/
- if (base == 16 &&
- *string == '0' &&
- ACPI_TOLOWER (*(++string)) == 'x') {
- string++;
+ if ((base == 16) &&
+ (*string == '0') &&
+ (ACPI_TOLOWER (*(string + 1)) == 'x')) {
+ string += 2;
}
/* Any string left? */
@@ -437,23 +441,27 @@ acpi_ut_strtoul64 (
this_digit = ((u8) *string) - '0';
}
else {
+ if (base == 10) {
+ /* Digit is out of range */
+
+ goto error_exit;
+ }
+
this_digit = (u8) ACPI_TOUPPER (*string);
- if (ACPI_IS_UPPER ((char) this_digit)) {
+ if (ACPI_IS_XDIGIT ((char) this_digit)) {
/* Convert ASCII Hex char to value */
this_digit = this_digit - 'A' + 10;
}
else {
- goto error_exit;
+ /*
+ * We allow non-hex chars, just stop now, same as end-of-string.
+ * See ACPI spec, string-to-integer conversion.
+ */
+ break;
}
}
- /* Check to see if digit is out of range */
-
- if (this_digit >= base) {
- goto error_exit;
- }
-
/* Divide the digit into the correct position */
(void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer) this_digit),
@@ -464,9 +472,11 @@ acpi_ut_strtoul64 (
return_value *= base;
return_value += this_digit;
- ++string;
+ string++;
}
+ /* All done, normal exit */
+
*ret_integer = return_value;
return_ACPI_STATUS (AE_OK);
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bd311c2076acc4..71fa1011715f36 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -683,7 +683,7 @@ acpi_video_bus_check (
FS Interface (/proc)
-------------------------------------------------------------------------- */
-struct proc_dir_entry *acpi_video_dir;
+static struct proc_dir_entry *acpi_video_dir;
/* video devices */
diff --git a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
index ffd87404b0a0eb..68e9e6832ca0c2 100644
--- a/drivers/i2c/algos/i2c-algo-ite.c
+++ b/drivers/i2c/algos/i2c-algo-ite.c
@@ -713,14 +713,11 @@ static u32 iic_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm iic_algo = {
- "ITE IIC algorithm",
- I2C_ALGO_IIC,
- iic_xfer, /* master_xfer */
- NULL, /* smbus_xfer */
- NULL, /* slave_xmit */
- NULL, /* slave_recv */
- algo_control, /* ioctl */
- iic_func, /* functionality */
+ .name = "ITE IIC algorithm",
+ .id = I2C_ALGO_IIC,
+ .master_xfer = iic_xfer,
+ .algo_control = algo_control, /* ioctl */
+ .functionality = iic_func,
};
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 66e681cb33d1ea..8d087dac32afc7 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -78,7 +78,6 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
set_pcf(adap, 1, I2C_PCF_STOP);
}
-
static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
int timeout = DEF_TIMEOUT;
@@ -109,6 +108,26 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
adap->waitforpin();
*status = get_pcf(adap, 1);
}
+ if (*status & I2C_PCF_LAB) {
+ DEB2(printk(KERN_INFO
+ "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
+ *status));
+ /* Cleanup from LAB-- reset and enable ESO.
+ * This resets the PCF8584; since we've lost the bus, no
+ * further attempts should be made by callers to clean up
+ * (no i2c_stop() etc.)
+ */
+ set_pcf(adap, 1, I2C_PCF_PIN);
+ set_pcf(adap, 1, I2C_PCF_ESO);
+ /* TODO: we should pause for a time period sufficient for any
+ * running I2C transaction to complete-- the arbitration
+ * logic won't work properly until the next START is seen.
+ */
+ DEB2(printk(KERN_INFO
+ "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
+ get_pcf(adap,1)));
+ return(-EINTR);
+ }
#endif
if (timeout <= 0)
return(-1);
@@ -188,16 +207,22 @@ static inline int try_address(struct i2c_algo_pcf_data *adap,
unsigned char addr, int retries)
{
int i, status, ret = -1;
+ int wfp;
for (i=0;i<retries;i++) {
i2c_outb(adap, addr);
i2c_start(adap);
status = get_pcf(adap, 1);
- if (wait_for_pin(adap, &status) >= 0) {
+ if ((wfp = wait_for_pin(adap, &status)) >= 0) {
if ((status & I2C_PCF_LRB) == 0) {
i2c_stop(adap);
break; /* success! */
}
}
+ if (wfp == -EINTR) {
+ /* arbitration lost */
+ udelay(adap->udelay);
+ return -EINTR;
+ }
i2c_stop(adap);
udelay(adap->udelay);
}
@@ -219,6 +244,10 @@ static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
i2c_outb(adap, buf[wrcount]);
timeout = wait_for_pin(adap, &status);
if (timeout) {
+ if (timeout == -EINTR) {
+ /* arbitration lost */
+ return -EINTR;
+ }
i2c_stop(adap);
dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
return -EREMOTEIO; /* got a better one ?? */
@@ -247,11 +276,16 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
{
int i, status;
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
+ int wfp;
/* increment number of bytes to read by one -- read dummy byte */
for (i = 0; i <= count; i++) {
- if (wait_for_pin(adap, &status)) {
+ if ((wfp = wait_for_pin(adap, &status))) {
+ if (wfp == -EINTR) {
+ /* arbitration lost */
+ return -EINTR;
+ }
i2c_stop(adap);
dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
return (-1);
@@ -366,6 +400,10 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
/* Wait for PIN (pending interrupt NOT) */
timeout = wait_for_pin(adap, &status);
if (timeout) {
+ if (timeout == -EINTR) {
+ /* arbitration lost */
+ return (-EINTR);
+ }
i2c_stop(adap);
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting "
"for PIN(1) in pcf_xfer\n");)
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index ea1a9047a3b25a..35789bb7126a3b 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -136,14 +136,11 @@ static u32 bit_func(struct i2c_adapter *adap)
/* -----exported algorithm data: ------------------------------------- */
static struct i2c_algorithm i2c_sibyte_algo = {
- "SiByte algorithm",
- I2C_ALGO_SIBYTE,
- NULL, /* master_xfer */
- smbus_xfer, /* smbus_xfer */
- NULL, /* slave_xmit */
- NULL, /* slave_recv */
- algo_control, /* ioctl */
- bit_func, /* functionality */
+ .name = "SiByte algorithm",
+ .id = I2C_ALGO_SIBYTE,
+ .smbus_xfer = smbus_xfer,
+ .algo_control = algo_control, /* ioctl */
+ .functionality = bit_func,
};
/*
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 34ff2ecad216fb..edf8051da3b4ce 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -108,7 +108,7 @@ config I2C_HYDRA
will be called i2c-hydra.
config I2C_I801
- tristate "Intel 801"
+ tristate "Intel 82801 (ICH)"
depends on I2C && PCI && EXPERIMENTAL
help
If you say yes to this option, support will be included for the Intel
@@ -119,7 +119,7 @@ config I2C_I801
82801BA
82801CA/CAM
82801DB
- 82801EB
+ 82801EB/ER (ICH5/ICH5R)
6300ESB
ICH6
ICH7
@@ -143,6 +143,23 @@ config I2C_I810
This driver can also be built as a module. If so, the module
will be called i2c-i810.
+config I2C_PIIX4
+ tristate "Intel PIIX4"
+ depends on I2C && PCI
+ help
+ If you say yes to this option, support will be included for the Intel
+ PIIX4 family of mainboard I2C interfaces. Specifically, the following
+ versions of the chipset are supported:
+ Intel PIIX4
+ Intel 440MX
+ Serverworks OSB4
+ Serverworks CSB5
+ Serverworks CSB6
+ SMSC Victory66
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-piix4.
+
config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface"
depends on IBM_OCP && I2C
@@ -285,23 +302,6 @@ config I2C_PARPORT_LIGHT
This support is also available as a module. If so, the module
will be called i2c-parport-light.
-config I2C_PIIX4
- tristate "Intel PIIX4"
- depends on I2C && PCI && EXPERIMENTAL
- help
- If you say yes to this option, support will be included for the Intel
- PIIX4 family of mainboard I2C interfaces. Specifically, the following
- versions of the chipset are supported:
- Intel PIIX4
- Intel 440MX
- Serverworks OSB4
- Serverworks CSB5
- Serverworks CSB6
- SMSC Victory66
-
- This driver can also be built as a module. If so, the module
- will be called i2c-piix4.
-
config I2C_PROSAVAGE
tristate "S3/VIA (Pro)Savage"
depends on I2C && PCI && EXPERIMENTAL
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 96fc7d72904bcd..0a7720000a0c5d 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -110,22 +110,23 @@ static int pcf_isa_getclock(void *data)
}
static void pcf_isa_waitforpin(void) {
-
+ DEFINE_WAIT(wait);
int timeout = 2;
- long flags;
+ unsigned long flags;
if (irq > 0) {
spin_lock_irqsave(&lock, flags);
if (pcf_pending == 0) {
spin_unlock_irqrestore(&lock, flags);
- if (interruptible_sleep_on_timeout(&pcf_wait,
- timeout*HZ)) {
+ prepare_to_wait(&pcf_wait, &wait, TASK_INTERRUPTIBLE);
+ if (schedule_timeout(timeout*HZ)) {
spin_lock_irqsave(&lock, flags);
if (pcf_pending == 1) {
pcf_pending = 0;
}
spin_unlock_irqrestore(&lock, flags);
}
+ finish_wait(&pcf_wait, &wait);
} else {
pcf_pending = 0;
spin_unlock_irqrestore(&lock, flags);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 17326cdd68d745..bb885215c08d6c 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -630,10 +630,6 @@ static struct i2c_algorithm iic_algo = {
.name = "IBM IIC algorithm",
.id = I2C_ALGO_OCP,
.master_xfer = iic_xfer,
- .smbus_xfer = NULL,
- .slave_send = NULL,
- .slave_recv = NULL,
- .algo_control = NULL,
.functionality = iic_func
};
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 62638115cf1198..702e3def1b81f6 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -40,6 +40,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/wait.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -107,7 +108,7 @@ static int iic_ite_getclock(void *data)
* IIC controller interrupts.
*/
static void iic_ite_waitforpin(void) {
-
+ DEFINE_WAIT(wait);
int timeout = 2;
long flags;
@@ -121,13 +122,15 @@ static void iic_ite_waitforpin(void) {
spin_lock_irqsave(&lock, flags);
if (iic_pending == 0) {
spin_unlock_irqrestore(&lock, flags);
- if (interruptible_sleep_on_timeout(&iic_wait, timeout*HZ)) {
+ prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE);
+ if (schedule_timeout(timeout*HZ)) {
spin_lock_irqsave(&lock, flags);
if (iic_pending == 1) {
iic_pending = 0;
}
spin_unlock_irqrestore(&lock, flags);
}
+ finish_wait(&iic_wait, &wait);
} else {
iic_pending = 0;
spin_unlock_irqrestore(&lock, flags);
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index db88a12439562b..5b852782d2f595 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -525,6 +525,8 @@ mv64xxx_i2c_probe(struct device *dev)
drv_data->irq = platform_get_irq(pd, 0);
drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
drv_data->adapter.algo = &mv64xxx_i2c_algo;
+ drv_data->adapter.owner = THIS_MODULE;
+ drv_data->adapter.class = I2C_CLASS_HWMON;
drv_data->adapter.timeout = pdata->timeout;
drv_data->adapter.retries = pdata->retries;
dev_set_drvdata(dev, drv_data);
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 0ac72c935e752d..fcfa51c1436b56 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1,6 +1,6 @@
/* linux/drivers/i2c/busses/i2c-s3c2410.c
*
- * Copyright (C) 2004 Simtec Electronics
+ * Copyright (C) 2004,2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410 I2C Controller
@@ -188,6 +188,9 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
} else
stat |= S3C2410_IICSTAT_MASTER_TX;
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
+ addr ^= 1;
+
// todo - check for wether ack wanted or not
s3c24xx_i2c_enable_ack(i2c);
@@ -287,7 +290,7 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
!(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
/* ack was not received... */
- dev_err(i2c->dev, "ack was not received\n" );
+ dev_dbg(i2c->dev, "ack was not received\n");
s3c24xx_i2c_stop(i2c, -EREMOTEIO);
goto out_ack;
}
@@ -555,11 +558,18 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
return -EREMOTEIO;
}
+/* declare our i2c functionality */
+static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
+}
+
/* i2c bus registration info */
static struct i2c_algorithm s3c24xx_i2c_algorithm = {
.name = "S3C2410-I2C-Algorithm",
.master_xfer = s3c24xx_i2c_xfer,
+ .functionality = s3c24xx_i2c_func,
};
static struct s3c24xx_i2c s3c24xx_i2c = {
@@ -567,6 +577,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
.adap = {
.name = "s3c2410-i2c",
+ .owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm,
.retries = 2,
.class = I2C_CLASS_HWMON,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index c872c2849a0bf2..0bb60a636e166a 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -121,12 +121,12 @@ static int vt596_transaction(void)
inb_p(SMBHSTDAT1));
/* Make sure the SMBus host is ready to start transmitting */
- if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). "
"Resetting...\n", temp);
outb_p(temp, SMBHSTSTS);
- if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
dev_dbg(&vt596_adapter.dev, "Failed! (0x%02x)\n", temp);
return -1;
@@ -168,13 +168,14 @@ static int vt596_transaction(void)
dev_dbg(&vt596_adapter.dev, "Error: no response!\n");
}
- if (inb_p(SMBHSTSTS) != 0x00)
- outb_p(inb(SMBHSTSTS), SMBHSTSTS);
-
- if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
- dev_dbg(&vt596_adapter.dev, "Failed reset at end of "
- "transaction (%02x)\n", temp);
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+ outb_p(temp, SMBHSTSTS);
+ if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
+ dev_warn(&vt596_adapter.dev, "Failed reset at end "
+ "of transaction (%02x)\n", temp);
+ }
}
+
dev_dbg(&vt596_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 824c62d3a66c5c..74d23cfce2a340 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -233,9 +233,23 @@ config SENSORS_LM90
LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
MAX6658 sensor chips.
+ The Analog Devices ADT7461 sensor chip is also supported, but only
+ if found in ADM1032 compatibility mode.
+
This driver can also be built as a module. If so, the module
will be called lm90.
+config SENSORS_LM92
+ tristate "National Semiconductor LM92 and compatibles"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for National Semiconductor LM92
+ and Maxim MAX6635 sensor chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called lm92.
+
config SENSORS_MAX1619
tristate "Maxim MAX1619 sensor chip"
depends on I2C && EXPERIMENTAL
@@ -351,6 +365,17 @@ endmenu
menu "Other I2C Chip support"
depends on I2C
+config SENSORS_DS1337
+ tristate "Dallas Semiconductor DS1337 Real Time Clock"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for Dallas Semiconductor
+ DS1337 real-time clock chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called ds1337.
+
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index a6db6f39476c20..65599161a172df 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
+obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_SENSORS_LM83) += lm83.o
obj-$(CONFIG_SENSORS_LM85) += lm85.o
obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
+obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
index 5dd7f64fdddd42..b4e3ee568265ff 100644
--- a/drivers/i2c/chips/adm1021.c
+++ b/drivers/i2c/chips/adm1021.c
@@ -28,18 +28,6 @@
#include <linux/i2c-sensor.h>
-/* Registers */
-#define ADM1021_SYSCTL_TEMP 1200
-#define ADM1021_SYSCTL_REMOTE_TEMP 1201
-#define ADM1021_SYSCTL_DIE_CODE 1202
-#define ADM1021_SYSCTL_ALARMS 1203
-
-#define ADM1021_ALARM_TEMP_HIGH 0x40
-#define ADM1021_ALARM_TEMP_LOW 0x20
-#define ADM1021_ALARM_RTEMP_HIGH 0x10
-#define ADM1021_ALARM_RTEMP_LOW 0x08
-#define ADM1021_ALARM_RTEMP_NA 0x04
-
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
0x29, 0x2a, 0x2b,
@@ -380,7 +368,7 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
- data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
+ data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c;
if (data->type == adm1021)
data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
if (data->type == adm1023) {
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
new file mode 100644
index 00000000000000..07f16c3fb084df
--- /dev/null
+++ b/drivers/i2c/chips/ds1337.c
@@ -0,0 +1,402 @@
+/*
+ * linux/drivers/i2c/chips/ds1337.c
+ *
+ * Copyright (C) 2005 James Chapman <jchapman@katalix.com>
+ *
+ * based on linux/drivers/acron/char/pcf8583.c
+ * Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver for Dallas Semiconductor DS1337 real time clock chip
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/string.h>
+#include <linux/rtc.h> /* get the user-level API */
+#include <linux/bcd.h>
+#include <linux/list.h>
+
+/* Device registers */
+#define DS1337_REG_HOUR 2
+#define DS1337_REG_DAY 3
+#define DS1337_REG_DATE 4
+#define DS1337_REG_MONTH 5
+#define DS1337_REG_CONTROL 14
+#define DS1337_REG_STATUS 15
+
+/* FIXME - how do we export these interface constants? */
+#define DS1337_GET_DATE 0
+#define DS1337_SET_DATE 1
+
+/*
+ * Functions declaration
+ */
+static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+SENSORS_INSMOD_1(ds1337);
+
+static int ds1337_attach_adapter(struct i2c_adapter *adapter);
+static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
+static void ds1337_init_client(struct i2c_client *client);
+static int ds1337_detach_client(struct i2c_client *client);
+static int ds1337_command(struct i2c_client *client, unsigned int cmd,
+ void *arg);
+
+/*
+ * Driver data (common to all clients)
+ */
+static struct i2c_driver ds1337_driver = {
+ .owner = THIS_MODULE,
+ .name = "ds1337",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = ds1337_attach_adapter,
+ .detach_client = ds1337_detach_client,
+ .command = ds1337_command,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+struct ds1337_data {
+ struct i2c_client client;
+ struct list_head list;
+ int id;
+};
+
+/*
+ * Internal variables
+ */
+static int ds1337_id;
+static LIST_HEAD(ds1337_clients);
+
+static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
+{
+ s32 tmp = i2c_smbus_read_byte_data(client, reg);
+
+ if (tmp < 0)
+ return -EIO;
+
+ *value = tmp;
+
+ return 0;
+}
+
+/*
+ * Chip access functions
+ */
+static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+ struct ds1337_data *data = i2c_get_clientdata(client);
+ int result;
+ u8 buf[7];
+ u8 val;
+ struct i2c_msg msg[2];
+ u8 offs = 0;
+
+ if (!dt) {
+ dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
+ __FUNCTION__);
+
+ return -EINVAL;
+ }
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ msg[0].buf = &offs;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = sizeof(buf);
+ msg[1].buf = &buf[0];
+
+ result = client->adapter->algo->master_xfer(client->adapter,
+ &msg[0], 2);
+
+ dev_dbg(&client->adapter->dev,
+ "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
+ __FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6]);
+
+ if (result >= 0) {
+ dt->tm_sec = BCD_TO_BIN(buf[0]);
+ dt->tm_min = BCD_TO_BIN(buf[1]);
+ val = buf[2] & 0x3f;
+ dt->tm_hour = BCD_TO_BIN(val);
+ dt->tm_wday = BCD_TO_BIN(buf[3]) - 1;
+ dt->tm_mday = BCD_TO_BIN(buf[4]);
+ val = buf[5] & 0x7f;
+ dt->tm_mon = BCD_TO_BIN(val);
+ dt->tm_year = 1900 + BCD_TO_BIN(buf[6]);
+ if (buf[5] & 0x80)
+ dt->tm_year += 100;
+
+ dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ __FUNCTION__, dt->tm_sec, dt->tm_min,
+ dt->tm_hour, dt->tm_mday,
+ dt->tm_mon, dt->tm_year, dt->tm_wday);
+ } else {
+ dev_err(&client->adapter->dev, "ds1337[%d]: error reading "
+ "data! %d\n", data->id, result);
+ result = -EIO;
+ }
+
+ return result;
+}
+
+static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+ struct ds1337_data *data = i2c_get_clientdata(client);
+ int result;
+ u8 buf[8];
+ u8 val;
+ struct i2c_msg msg[1];
+
+ if (!dt) {
+ dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
+ __FUNCTION__);
+
+ return -EINVAL;
+ }
+
+ dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ "mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
+ dt->tm_sec, dt->tm_min, dt->tm_hour,
+ dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
+
+ buf[0] = 0; /* reg offset */
+ buf[1] = BIN_TO_BCD(dt->tm_sec);
+ buf[2] = BIN_TO_BCD(dt->tm_min);
+ buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6);
+ buf[4] = BIN_TO_BCD(dt->tm_wday) + 1;
+ buf[5] = BIN_TO_BCD(dt->tm_mday);
+ buf[6] = BIN_TO_BCD(dt->tm_mon);
+ if (dt->tm_year >= 2000) {
+ val = dt->tm_year - 2000;
+ buf[6] |= (1 << 7);
+ } else {
+ val = dt->tm_year - 1900;
+ }
+ buf[7] = BIN_TO_BCD(val);
+
+ msg[0].addr = client->addr;
+ msg[0].flags = 0;
+ msg[0].len = sizeof(buf);
+ msg[0].buf = &buf[0];
+
+ result = client->adapter->algo->master_xfer(client->adapter,
+ &msg[0], 1);
+ if (result < 0) {
+ dev_err(&client->adapter->dev, "ds1337[%d]: error "
+ "writing data! %d\n", data->id, result);
+ result = -EIO;
+ } else {
+ result = 0;
+ }
+
+ return result;
+}
+
+static int ds1337_command(struct i2c_client *client, unsigned int cmd,
+ void *arg)
+{
+ dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+
+ switch (cmd) {
+ case DS1337_GET_DATE:
+ return ds1337_get_datetime(client, arg);
+
+ case DS1337_SET_DATE:
+ return ds1337_set_datetime(client, arg);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * Public API for access to specific device. Useful for low-level
+ * RTC access from kernel code.
+ */
+int ds1337_do_command(int id, int cmd, void *arg)
+{
+ struct list_head *walk;
+ struct list_head *tmp;
+ struct ds1337_data *data;
+
+ list_for_each_safe(walk, tmp, &ds1337_clients) {
+ data = list_entry(walk, struct ds1337_data, list);
+ if (data->id == id)
+ return ds1337_command(&data->client, cmd, arg);
+ }
+
+ return -ENODEV;
+}
+
+static int ds1337_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, ds1337_detect);
+}
+
+/*
+ * The following function does more than just detection. If detection
+ * succeeds, it also registers the new chip.
+ */
+static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct ds1337_data *data;
+ int err = 0;
+ const char *name = "";
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_I2C))
+ goto exit;
+
+ if (!(data = kmalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct ds1337_data));
+ INIT_LIST_HEAD(&data->list);
+
+ /* The common I2C client data is placed right before the
+ * DS1337-specific data.
+ */
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &ds1337_driver;
+ new_client->flags = 0;
+
+ /*
+ * Now we do the remaining detection. A negative kind means that
+ * the driver was loaded with no force parameter (default), so we
+ * must both detect and identify the chip. A zero kind means that
+ * the driver was loaded with the force parameter, the detection
+ * step shall be skipped. A positive kind means that the driver
+ * was loaded with the force parameter and a given kind of chip is
+ * requested, so both the detection and the identification steps
+ * are skipped.
+ *
+ * For detection, we read registers that are most likely to cause
+ * detection failure, i.e. those that have more bits with fixed
+ * or reserved values.
+ */
+
+ /* Default to an DS1337 if forced */
+ if (kind == 0)
+ kind = ds1337;
+
+ if (kind < 0) { /* detection and identification */
+ u8 data;
+
+ /* Check that status register bits 6-2 are zero */
+ if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) ||
+ (data & 0x7c))
+ goto exit_free;
+
+ /* Check for a valid day register value */
+ if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) ||
+ (data == 0) || (data & 0xf8))
+ goto exit_free;
+
+ /* Check for a valid date register value */
+ if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) ||
+ (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) ||
+ (data >= 0x32))
+ goto exit_free;
+
+ /* Check for a valid month register value */
+ if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) ||
+ (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) ||
+ ((data >= 0x13) && (data <= 0x19)))
+ goto exit_free;
+
+ /* Check that control register bits 6-5 are zero */
+ if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) ||
+ (data & 0x60))
+ goto exit_free;
+
+ kind = ds1337;
+ }
+
+ if (kind == ds1337)
+ name = "ds1337";
+
+ /* We can fill in the remaining client fields */
+ strlcpy(new_client->name, name, I2C_NAME_SIZE);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Initialize the DS1337 chip */
+ ds1337_init_client(new_client);
+
+ /* Add client to local list */
+ data->id = ds1337_id++;
+ list_add(&data->list, &ds1337_clients);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static void ds1337_init_client(struct i2c_client *client)
+{
+ s32 val;
+
+ /* Ensure that device is set in 24-hour mode */
+ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+ if ((val >= 0) && (val & (1 << 6)) == 0)
+ i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+ val | (1 << 6));
+}
+
+static int ds1337_detach_client(struct i2c_client *client)
+{
+ int err;
+ struct ds1337_data *data = i2c_get_clientdata(client);
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ list_del(&data->list);
+ kfree(data);
+ return 0;
+}
+
+static int __init ds1337_init(void)
+{
+ return i2c_add_driver(&ds1337_driver);
+}
+
+static void __exit ds1337_exit(void)
+{
+ i2c_del_driver(&ds1337_driver);
+}
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("DS1337 RTC driver");
+MODULE_LICENSE("GPL");
+
+module_init(ds1337_init);
+module_exit(ds1337_exit);
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index f126d011cfee26..cbdfa2db6f7c90 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -210,10 +210,11 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
if (i2c_smbus_read_byte_data(new_client, 0x80) == 'P'
&& i2c_smbus_read_byte(new_client) == 'C'
&& i2c_smbus_read_byte(new_client) == 'G'
- && i2c_smbus_read_byte(new_client) == '-')
+ && i2c_smbus_read_byte(new_client) == '-') {
dev_info(&new_client->dev, "Vaio EEPROM detected, "
"enabling password protection\n");
data->nature = VAIO;
+ }
}
/* create the sysfs eeprom file */
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index e62c2e390076bc..bf02ba555a8518 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -734,10 +734,9 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
goto ERROR0;
/* Probe whether there is anything available on this address. Already
- done for SMBus clients */
+ done for SMBus and Super-I/O clients */
if (kind < 0) {
- if (is_isa) {
-
+ if (is_isa && !chip_type) {
#define REALLY_SLOW_IO
/* We need the timeouts for at least some IT87-like chips. But only
if we read 'undefined' registers. */
@@ -890,9 +889,9 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (data->type == it8712) {
+ data->vrm = i2c_which_vrm();
device_create_file_vrm(new_client);
device_create_file_vid(new_client);
- data->vrm = i2c_which_vrm();
}
return 0;
@@ -1123,9 +1122,6 @@ static struct it87_data *it87_update_device(struct device *dev)
it87_read_value(client, IT87_REG_TEMP_LOW(i));
}
- /* The 8705 does not have VID capability */
- data->vid = 0x1f;
-
i = it87_read_value(client, IT87_REG_FAN_DIV);
data->fan_div[0] = i & 0x07;
data->fan_div[1] = (i >> 3) & 0x07;
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
index d17aba4e42fcd9..e08000b948b2f6 100644
--- a/drivers/i2c/chips/lm85.c
+++ b/drivers/i2c/chips/lm85.c
@@ -37,7 +37,7 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
+SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
/* The LM85 registers */
@@ -74,8 +74,10 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
#define LM85_VERSTEP_LM85B 0x62
#define LM85_VERSTEP_ADM1027 0x60
#define LM85_VERSTEP_ADT7463 0x62
+#define LM85_VERSTEP_ADT7463C 0x6A
#define LM85_VERSTEP_EMC6D100_A0 0x60
#define LM85_VERSTEP_EMC6D100_A1 0x61
+#define LM85_VERSTEP_EMC6D102 0x65
#define LM85_REG_CONFIG 0x40
@@ -112,9 +114,13 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
#define EMC6D100_REG_ALARM3 0x7d
/* IN5, IN6 and IN7 */
-#define EMC6D100_REG_IN(nr) (0x70 + ((nr)-5))
-#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2)
-#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2)
+#define EMC6D100_REG_IN(nr) (0x70 + ((nr)-5))
+#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr)-5) * 2)
+#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr)-5) * 2)
+#define EMC6D102_REG_EXTEND_ADC1 0x85
+#define EMC6D102_REG_EXTEND_ADC2 0x86
+#define EMC6D102_REG_EXTEND_ADC3 0x87
+#define EMC6D102_REG_EXTEND_ADC4 0x88
#define LM85_ALARM_IN0 0x0001
#define LM85_ALARM_IN1 0x0002
@@ -139,35 +145,36 @@ SENSORS_INSMOD_5(lm85b, lm85c, adm1027, adt7463, emc6d100);
these macros are called: arguments may be evaluated more than once.
*/
-/* IN are scaled 1.000 == 0xc0, mag = 3 */
-#define IN_TO_REG(val) (SENSORS_LIMIT((((val)*0xc0+500)/1000),0,255))
-#define INEXT_FROM_REG(val,ext) (((val)*1000 + (ext)*250 + 96)/0xc0)
-#define IN_FROM_REG(val) (INEXT_FROM_REG(val,0))
-
/* IN are scaled acording to built-in resistors */
static int lm85_scaling[] = { /* .001 Volts */
2500, 2250, 3300, 5000, 12000,
3300, 1500, 1800 /*EMC6D100*/
};
#define SCALE(val,from,to) (((val)*(to) + ((from)/2))/(from))
-#define INS_TO_REG(n,val) (SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255))
-#define INSEXT_FROM_REG(n,val,ext) (SCALE((val)*4 + (ext),192*4,lm85_scaling[n]))
-#define INS_FROM_REG(n,val) (INSEXT_FROM_REG(n,val,0))
+
+#define INS_TO_REG(n,val) \
+ SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255)
+
+#define INSEXT_FROM_REG(n,val,ext,scale) \
+ SCALE((val)*(scale) + (ext),192*(scale),lm85_scaling[n])
+
+#define INS_FROM_REG(n,val) INSEXT_FROM_REG(n,val,0,1)
/* FAN speed is measured using 90kHz clock */
#define FAN_TO_REG(val) (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
#define FAN_FROM_REG(val) ((val)==0?-1:(val)==0xffff?0:5400000/(val))
/* Temperature is reported in .001 degC increments */
-#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)+500)/1000,-127,127))
-#define TEMPEXT_FROM_REG(val,ext) ((val)*1000 + (ext)*250)
-#define TEMP_FROM_REG(val) (TEMPEXT_FROM_REG(val,0))
-#define EXTTEMP_TO_REG(val) (SENSORS_LIMIT((val)/250,-127,127))
+#define TEMP_TO_REG(val) \
+ SENSORS_LIMIT(SCALE(val,1000,1),-127,127)
+#define TEMPEXT_FROM_REG(val,ext,scale) \
+ SCALE((val)*scale + (ext),scale,1000)
+#define TEMP_FROM_REG(val) \
+ TEMPEXT_FROM_REG(val,0,1)
#define PWM_TO_REG(val) (SENSORS_LIMIT(val,0,255))
#define PWM_FROM_REG(val) (val)
-#define EXT_FROM_REG(val,sensor) (((val)>>(sensor * 2))&0x03)
/* ZONEs have the following parameters:
* Limit (low) temp, 1. degC
@@ -355,7 +362,9 @@ struct lm85_data {
u8 pwm[3]; /* Register value */
u8 spinup_ctl; /* Register encoding, combined */
u8 tach_mode; /* Register encoding, combined */
- u16 extend_adc; /* Register value */
+ u8 temp_ext[3]; /* Decoded values */
+ u8 in_ext[8]; /* Decoded values */
+ u8 adc_scale; /* ADC Extended bits scaling factor */
u8 fan_ppr; /* Register value */
u8 smooth[3]; /* Register encoding */
u8 vid; /* Register value */
@@ -536,7 +545,10 @@ show_pwm_reg(3);
static ssize_t show_in(struct device *dev, char *buf, int nr)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]) );
+ return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr,
+ data->in[nr],
+ data->in_ext[nr],
+ data->adc_scale) );
}
static ssize_t show_in_min(struct device *dev, char *buf, int nr)
{
@@ -617,7 +629,9 @@ show_in_reg(4);
static ssize_t show_temp(struct device *dev, char *buf, int nr)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]) );
+ return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr],
+ data->temp_ext[nr],
+ data->adc_scale) );
}
static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
{
@@ -1089,7 +1103,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
&& verstep == LM85_VERSTEP_ADM1027 ) {
kind = adm1027 ;
} else if( company == LM85_COMPANY_ANALOG_DEV
- && verstep == LM85_VERSTEP_ADT7463 ) {
+ && (verstep == LM85_VERSTEP_ADT7463
+ || verstep == LM85_VERSTEP_ADT7463C) ) {
kind = adt7463 ;
} else if( company == LM85_COMPANY_ANALOG_DEV
&& (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC ) {
@@ -1107,6 +1122,9 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
*/
kind = emc6d100 ;
} else if( company == LM85_COMPANY_SMSC
+ && verstep == LM85_VERSTEP_EMC6D102) {
+ kind = emc6d102 ;
+ } else if( company == LM85_COMPANY_SMSC
&& (verstep & LM85_VERSTEP_VMASK) == LM85_VERSTEP_GENERIC) {
dev_err(&adapter->dev, "lm85: Detected SMSC chip\n");
dev_err(&adapter->dev, "lm85: Unrecognized version/stepping 0x%02x"
@@ -1142,6 +1160,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
type_name = "adt7463";
} else if ( kind == emc6d100){
type_name = "emc6d100";
+ } else if ( kind == emc6d102 ) {
+ type_name = "emc6d102";
}
strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
@@ -1259,7 +1279,6 @@ int lm85_read_value(struct i2c_client *client, u8 reg)
case LM85_REG_FAN_MIN(2) :
case LM85_REG_FAN_MIN(3) :
case LM85_REG_ALARM1 : /* Read both bytes at once */
- case ADM1027_REG_EXTEND_ADC1 : /* Read two bytes at once */
res = i2c_smbus_read_byte_data(client, reg) & 0xff ;
res |= i2c_smbus_read_byte_data(client, reg+1) << 8 ;
break ;
@@ -1363,10 +1382,25 @@ static struct lm85_data *lm85_update_device(struct device *dev)
* more significant bits that are read later.
*/
if ( (data->type == adm1027) || (data->type == adt7463) ) {
- data->extend_adc =
- lm85_read_value(client, ADM1027_REG_EXTEND_ADC1);
+ int ext1 = lm85_read_value(client,
+ ADM1027_REG_EXTEND_ADC1);
+ int ext2 = lm85_read_value(client,
+ ADM1027_REG_EXTEND_ADC2);
+ int val = (ext1 << 8) + ext2;
+
+ for(i = 0; i <= 4; i++)
+ data->in_ext[i] = (val>>(i * 2))&0x03;
+
+ for(i = 0; i <= 2; i++)
+ data->temp_ext[i] = (val>>((i + 5) * 2))&0x03;
}
+ /* adc_scale is 2^(number of LSBs). There are 4 extra bits in
+ the emc6d102 and 2 in the adt7463 and adm1027. In all
+ other chips ext is always 0 and the value of scale is
+ irrelevant. So it is left in 4*/
+ data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
+
for (i = 0; i <= 4; ++i) {
data->in[i] =
lm85_read_value(client, LM85_REG_IN(i));
@@ -1403,6 +1437,28 @@ static struct lm85_data *lm85_update_device(struct device *dev)
/* More alarm bits */
data->alarms |=
lm85_read_value(client, EMC6D100_REG_ALARM3) << 16;
+ } else if (data->type == emc6d102 ) {
+ /* Have to read LSB bits after the MSB ones because
+ the reading of the MSB bits has frozen the
+ LSBs (backward from the ADM1027).
+ */
+ int ext1 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC1);
+ int ext2 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC2);
+ int ext3 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC3);
+ int ext4 = lm85_read_value(client,
+ EMC6D102_REG_EXTEND_ADC4);
+ data->in_ext[0] = ext3 & 0x0f;
+ data->in_ext[1] = ext4 & 0x0f;
+ data->in_ext[2] = (ext4 >> 4) & 0x0f;
+ data->in_ext[3] = (ext3 >> 4) & 0x0f;
+ data->in_ext[4] = (ext2 >> 4) & 0x0f;
+
+ data->temp_ext[0] = ext1 & 0x0f;
+ data->temp_ext[1] = ext2 & 0x0f;
+ data->temp_ext[2] = (ext1 >> 4) & 0x0f;
}
data->last_reading = jiffies ;
diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c
index 8b9e2de21bff74..49d92326faab5f 100644
--- a/drivers/i2c/chips/lm87.c
+++ b/drivers/i2c/chips/lm87.c
@@ -317,20 +317,20 @@ show_temp(3);
static void set_temp_low(struct device *dev, const char *buf, int nr)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm87_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
- data->temp_low[nr] = TEMP_TO_REG(val);
- lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm87_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ data->temp_low[nr] = TEMP_TO_REG(val);
+ lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]);
}
static void set_temp_high(struct device *dev, const char *buf, int nr)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct lm87_data *data = i2c_get_clientdata(client);
- long val = simple_strtol(buf, NULL, 10);
- data->temp_high[nr] = TEMP_TO_REG(val);
- lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm87_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ data->temp_high[nr] = TEMP_TO_REG(val);
+ lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]);
}
#define set_temp(offset) \
diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
index 7540b230173e8b..02e22b128b0453 100644
--- a/drivers/i2c/chips/lm90.c
+++ b/drivers/i2c/chips/lm90.c
@@ -43,6 +43,14 @@
* variants. The extra address and features of the MAX6659 are not
* supported by this driver.
*
+ * This driver also supports the ADT7461 chip from Analog Devices but
+ * only in its "compatability mode". If an ADT7461 chip is found but
+ * is configured in non-compatible mode (where its temperature
+ * register values are decoded differently) it is ignored by this
+ * driver. Complete datasheet can be obtained from Analog's website
+ * at:
+ * http://products.analog.com/products/info.asp?product=ADT7461
+ *
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
* concern all supported chipsets, unless mentioned otherwise.
@@ -77,6 +85,7 @@
* LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
* LM89-1, and LM99-1 have address 0x4d.
* MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
+ * ADT7461 always has address 0x4c.
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
@@ -86,7 +95,7 @@ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
* Insmod parameters
*/
-SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657);
+SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
/*
* The LM90 registers
@@ -148,6 +157,19 @@ SENSORS_INSMOD_5(lm90, adm1032, lm99, lm86, max6657);
#define HYST_TO_REG(val) ((val) <= 0 ? 0 : (val) >= 30500 ? 31 : \
((val) + 500) / 1000)
+/*
+ * ADT7461 is almost identical to LM90 except that attempts to write
+ * values that are outside the range 0 < temp < 127 are treated as
+ * the boundary value.
+ */
+
+#define TEMP1_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \
+ (val) >= 127000 ? 127 : \
+ ((val) + 500) / 1000)
+#define TEMP2_TO_REG_ADT7461(val) ((val) <= 0 ? 0 : \
+ (val) >= 127750 ? 0x7FC0 : \
+ ((val) + 125) / 250 * 64)
+
/*
* Functions declaration
*/
@@ -181,6 +203,7 @@ struct lm90_data {
struct semaphore update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
+ int kind;
/* registers values */
s8 temp_input1, temp_low1, temp_high1; /* local */
@@ -216,7 +239,10 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \
- data->value = TEMP1_TO_REG(val); \
+ if (data->kind == adt7461) \
+ data->value = TEMP1_TO_REG_ADT7461(val); \
+ else \
+ data->value = TEMP1_TO_REG(val); \
i2c_smbus_write_byte_data(client, reg, data->value); \
return count; \
}
@@ -227,7 +253,10 @@ static ssize_t set_##value(struct device *dev, const char *buf, \
struct i2c_client *client = to_i2c_client(dev); \
struct lm90_data *data = i2c_get_clientdata(client); \
long val = simple_strtol(buf, NULL, 10); \
- data->value = TEMP2_TO_REG(val); \
+ if (data->kind == adt7461) \
+ data->value = TEMP2_TO_REG_ADT7461(val); \
+ else \
+ data->value = TEMP2_TO_REG(val); \
i2c_smbus_write_byte_data(client, regh, data->value >> 8); \
i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \
return count; \
@@ -381,6 +410,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
&& (reg_config1 & 0x3F) == 0x00
&& reg_convrate <= 0x0A) {
kind = adm1032;
+ } else
+ if (address == 0x4c
+ && chip_id == 0x51 /* ADT7461 */
+ && (reg_config1 & 0x1F) == 0x00 /* check compat mode */
+ && reg_convrate <= 0x0A) {
+ kind = adt7461;
}
} else
if (man_id == 0x4D) { /* Maxim */
@@ -418,11 +453,14 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
name = "lm86";
} else if (kind == max6657) {
name = "max6657";
+ } else if (kind == adt7461) {
+ name = "adt7461";
}
/* We can fill in the remaining client fields */
strlcpy(new_client->name, name, I2C_NAME_SIZE);
data->valid = 0;
+ data->kind = kind;
init_MUTEX(&data->update_lock);
/* Tell the I2C layer a new client has arrived */
diff --git a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c
new file mode 100644
index 00000000000000..3c9d0ef8eca79e
--- /dev/null
+++ b/drivers/i2c/chips/lm92.c
@@ -0,0 +1,423 @@
+/*
+ * lm92 - Hardware monitoring driver
+ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+ *
+ * Based on the lm90 driver, with some ideas taken from the lm_sensors
+ * lm92 driver as well.
+ *
+ * The LM92 is a sensor chip made by National Semiconductor. It reports
+ * its own temperature with a 0.0625 deg resolution and a 0.33 deg
+ * accuracy. Complete datasheet can be obtained from National's website
+ * at:
+ * http://www.national.com/pf/LM/LM92.html
+ *
+ * This driver also supports the MAX6635 sensor chip made by Maxim.
+ * This chip is compatible with the LM92, but has a lesser accuracy
+ * (1.0 deg). Complete datasheet can be obtained from Maxim's website
+ * at:
+ * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+ *
+ * Since the LM92 was the first chipset supported by this driver, most
+ * comments will refer to this chipset, but are actually general and
+ * concern all supported chipsets, unless mentioned otherwise.
+ *
+ * Support could easily be added for the National Semiconductor LM76
+ * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible
+ * with the LM92.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+
+/* The LM92 and MAX6635 have 2 two-state pins for address selection,
+ resulting in 4 possible addresses. */
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+ I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(lm92);
+
+/* The LM92 registers */
+#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */
+#define LM92_REG_TEMP 0x00 /* 16-bit, RO */
+#define LM92_REG_TEMP_HYST 0x02 /* 16-bit, RW */
+#define LM92_REG_TEMP_CRIT 0x03 /* 16-bit, RW */
+#define LM92_REG_TEMP_LOW 0x04 /* 16-bit, RW */
+#define LM92_REG_TEMP_HIGH 0x05 /* 16-bit, RW */
+#define LM92_REG_MAN_ID 0x07 /* 16-bit, RO, LM92 only */
+
+/* The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius,
+ left-justified in 16-bit registers. No rounding is done, with such
+ a resolution it's just not worth it. Note that the MAX6635 doesn't
+ make use of the 4 lower bits for limits (i.e. effective resolution
+ for limits is 1 degree Celsius). */
+static inline int TEMP_FROM_REG(s16 reg)
+{
+ return reg / 8 * 625 / 10;
+}
+
+static inline s16 TEMP_TO_REG(int val)
+{
+ if (val <= -60000)
+ return -60000 * 10 / 625 * 8;
+ if (val >= 160000)
+ return 160000 * 10 / 625 * 8;
+ return val * 10 / 625 * 8;
+}
+
+/* Alarm flags are stored in the 3 LSB of the temperature register */
+static inline u8 ALARMS_FROM_REG(s16 reg)
+{
+ return reg & 0x0007;
+}
+
+/* Driver data (common to all clients) */
+static struct i2c_driver lm92_driver;
+
+/* Client data (each client gets its own) */
+struct lm92_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ char valid; /* zero until following fields are valid */
+ unsigned long last_updated; /* in jiffies */
+
+ /* registers values */
+ s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst;
+};
+
+
+/*
+ * Sysfs attributes and callback functions
+ */
+
+static struct lm92_data *lm92_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm92_data *data = i2c_get_clientdata(client);
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ)
+ || !data->valid) {
+ dev_dbg(&client->dev, "Updating lm92 data\n");
+ data->temp1_input = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP));
+ data->temp1_hyst = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HYST));
+ data->temp1_crit = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_CRIT));
+ data->temp1_min = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_LOW));
+ data->temp1_max = swab16(i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HIGH));
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+#define show_temp(value) \
+static ssize_t show_##value(struct device *dev, char *buf) \
+{ \
+ struct lm92_data *data = lm92_update_device(dev); \
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+}
+show_temp(temp1_input);
+show_temp(temp1_crit);
+show_temp(temp1_min);
+show_temp(temp1_max);
+
+#define set_temp(value, reg) \
+static ssize_t set_##value(struct device *dev, const char *buf, \
+ size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct lm92_data *data = i2c_get_clientdata(client); \
+ long val = simple_strtol(buf, NULL, 10); \
+ data->value = TEMP_TO_REG(val); \
+ i2c_smbus_write_word_data(client, reg, swab16(data->value)); \
+ return count; \
+}
+set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
+set_temp(temp1_min, LM92_REG_TEMP_LOW);
+set_temp(temp1_max, LM92_REG_TEMP_HIGH);
+
+static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
+ - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_max_hyst(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
+ - TEMP_FROM_REG(data->temp1_hyst));
+}
+static ssize_t show_temp1_min_hyst(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
+ + TEMP_FROM_REG(data->temp1_hyst));
+}
+
+static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
+ size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm92_data *data = i2c_get_clientdata(client);
+ data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) -
+ simple_strtol(buf, NULL, 10);
+ i2c_smbus_write_word_data(client, LM92_REG_TEMP_HYST,
+ swab16(TEMP_TO_REG(data->temp1_hyst)));
+ return count;
+}
+
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+ struct lm92_data *data = lm92_update_device(dev);
+ return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
+static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit,
+ set_temp1_crit);
+static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst,
+ set_temp1_crit_hyst);
+static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min,
+ set_temp1_min);
+static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL);
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max,
+ set_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+
+/*
+ * Detection and registration
+ */
+
+static void lm92_init_client(struct i2c_client *client)
+{
+ u8 config;
+
+ /* Start the conversions if needed */
+ config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+ if (config & 0x01)
+ i2c_smbus_write_byte_data(client, LM92_REG_CONFIG,
+ config & 0xFE);
+}
+
+/* The MAX6635 has no identification register, so we have to use tricks
+ to identify it reliably. This is somewhat slow.
+ Note that we do NOT rely on the 2 MSB of the configuration register
+ always reading 0, as suggested by the datasheet, because it was once
+ reported not to be true. */
+static int max6635_check(struct i2c_client *client)
+{
+ u16 temp_low, temp_high, temp_hyst, temp_crit;
+ u8 conf;
+ int i;
+
+ /* No manufacturer ID register, so a read from this address will
+ always return the last read value. */
+ temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW);
+ if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low)
+ return 0;
+ temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH);
+ if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high)
+ return 0;
+
+ /* Limits are stored as integer values (signed, 9-bit). */
+ if ((temp_low & 0x7f00) || (temp_high & 0x7f00))
+ return 0;
+ temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST);
+ temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT);
+ if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00))
+ return 0;
+
+ /* Registers addresses were found to cycle over 16-byte boundaries.
+ We don't test all registers with all offsets so as to save some
+ reads and time, but this should still be sufficient to dismiss
+ non-MAX6635 chips. */
+ conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG);
+ for (i=16; i<96; i*=2) {
+ if (temp_hyst != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HYST + i - 16)
+ || temp_crit != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_CRIT + i)
+ || temp_low != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_LOW + i + 16)
+ || temp_high != i2c_smbus_read_word_data(client,
+ LM92_REG_TEMP_HIGH + i + 32)
+ || conf != i2c_smbus_read_byte_data(client,
+ LM92_REG_CONFIG + i))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* The following function does more than just detection. If detection
+ succeeds, it also registers the new chip. */
+static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct lm92_data *data;
+ int err = 0;
+ char *name;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
+ | I2C_FUNC_SMBUS_WORD_DATA))
+ goto exit;
+
+ if (!(data = kmalloc(sizeof(struct lm92_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct lm92_data));
+
+ /* Fill in enough client fields so that we can read from the chip,
+ which is required for identication */
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &lm92_driver;
+ new_client->flags = 0;
+
+ /* A negative kind means that the driver was loaded with no force
+ parameter (default), so we must identify the chip. */
+ if (kind < 0) {
+ u8 config = i2c_smbus_read_byte_data(new_client,
+ LM92_REG_CONFIG);
+ u16 man_id = i2c_smbus_read_word_data(new_client,
+ LM92_REG_MAN_ID);
+
+ if ((config & 0xe0) == 0x00
+ && man_id == 0x0180) {
+ pr_info("lm92: Found National Semiconductor LM92 chip\n");
+ kind = lm92;
+ } else
+ if (max6635_check(new_client)) {
+ pr_info("lm92: Found Maxim MAX6635 chip\n");
+ kind = lm92; /* No separate prefix */
+ }
+ else
+ goto exit_free;
+ } else
+ if (kind == 0) /* Default to an LM92 if forced */
+ kind = lm92;
+
+ /* Give it the proper name */
+ if (kind == lm92) {
+ name = "lm92";
+ } else { /* Supposedly cannot happen */
+ dev_dbg(&new_client->dev, "Kind out of range?\n");
+ goto exit_free;
+ }
+
+ /* Fill in the remaining client fields */
+ strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the i2c subsystem a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ /* Initialize the chipset */
+ lm92_init_client(new_client);
+
+ /* Register sysfs hooks */
+ device_create_file(&new_client->dev, &dev_attr_temp1_input);
+ device_create_file(&new_client->dev, &dev_attr_temp1_crit);
+ device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
+ device_create_file(&new_client->dev, &dev_attr_temp1_min);
+ device_create_file(&new_client->dev, &dev_attr_temp1_min_hyst);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int lm92_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, lm92_detect);
+}
+
+static int lm92_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+
+/*
+ * Module and driver stuff
+ */
+
+static struct i2c_driver lm92_driver = {
+ .owner = THIS_MODULE,
+ .name = "lm92",
+ .id = I2C_DRIVERID_LM92,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = lm92_attach_adapter,
+ .detach_client = lm92_detach_client,
+};
+
+static int __init sensors_lm92_init(void)
+{
+ return i2c_add_driver(&lm92_driver);
+}
+
+static void __exit sensors_lm92_exit(void)
+{
+ i2c_del_driver(&lm92_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("LM92/MAX6635 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm92_init);
+module_exit(sensors_lm92_exit);
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index de270e920207a2..e771566dffa8d6 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -184,7 +184,6 @@ m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
memset(client, 0, sizeof(struct i2c_client));
strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
- client->id = m41t00_driver.id;
client->flags = I2C_DF_NOTIFY;
client->addr = addr;
client->adapter = adap;
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index 986dba3f0a7275..133e449dc14efa 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -304,7 +304,6 @@ struct w83627hf_data {
u32 beep_mask; /* Register encoding, combined */
u8 beep_enable; /* Boolean */
u8 pwm[3]; /* Register value */
- u8 pwmenable[3]; /* bool */
u16 sens[3]; /* 782D/783S only.
1 = pentium diode; 2 = 3904 diode;
3000-5000 = thermistor beta.
@@ -1317,10 +1316,6 @@ static void w83627hf_init_client(struct i2c_client *client)
break;
}
- data->pwmenable[0] = 1;
- data->pwmenable[1] = 1;
- data->pwmenable[2] = 1;
-
if(init) {
/* Enable temp2 */
tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG);
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index e893229239d072..628d769cf47516 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -46,9 +46,6 @@
#include <asm/io.h>
#include "lm75.h"
-/* RT Table support #defined so we can take it out if it gets bothersome */
-#define W83781D_RT 1
-
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
@@ -258,9 +255,6 @@ struct w83781d_data {
3000-5000 = thermistor beta.
Default = 3435.
Other Betas unimplemented */
-#ifdef W83781D_RT
- u8 rt[3][32]; /* Register value */
-#endif
u8 vrm;
};
@@ -834,66 +828,6 @@ do { \
device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
} while (0)
-#ifdef W83781D_RT
-static ssize_t
-show_rt_reg(struct device *dev, char *buf, int nr)
-{
- struct w83781d_data *data = w83781d_update_device(dev);
- int i, j = 0;
-
- for (i = 0; i < 32; i++) {
- if (i > 0)
- j += sprintf(buf, " %ld", (long) data->rt[nr - 1][i]);
- else
- j += sprintf(buf, "%ld", (long) data->rt[nr - 1][i]);
- }
- j += sprintf(buf, "\n");
-
- return j;
-}
-
-static ssize_t
-store_rt_reg(struct device *dev, const char *buf, size_t count, int nr)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct w83781d_data *data = i2c_get_clientdata(client);
- u32 val, i;
-
- for (i = 0; i < count; i++) {
- val = simple_strtoul(buf + count, NULL, 10);
-
- /* fixme: no bounds checking 0-255 */
- data->rt[nr - 1][i] = val & 0xff;
- w83781d_write_value(client, W83781D_REG_RT_IDX, i);
- w83781d_write_value(client, W83781D_REG_RT_VAL,
- data->rt[nr - 1][i]);
- }
-
- return count;
-}
-
-#define sysfs_rt(offset) \
-static ssize_t show_regs_rt_##offset (struct device *dev, char *buf) \
-{ \
- return show_rt_reg(dev, buf, offset); \
-} \
-static ssize_t store_regs_rt_##offset (struct device *dev, const char *buf, size_t count) \
-{ \
- return store_rt_reg(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(rt##offset, S_IRUGO | S_IWUSR, show_regs_rt_##offset, store_regs_rt_##offset);
-
-sysfs_rt(1);
-sysfs_rt(2);
-sysfs_rt(3);
-
-#define device_create_file_rt(client, offset) \
-do { \
-device_create_file(&client->dev, &dev_attr_rt##offset); \
-} while (0)
-
-#endif /* ifdef W83781D_RT */
-
/* This function is called when:
* w83781d_driver is inserted (when this module is loaded), for each
available adapter
@@ -1304,13 +1238,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind != w83783s && kind != w83697hf)
device_create_file_sensor(new_client, 3);
}
-#ifdef W83781D_RT
- if (kind == w83781d) {
- device_create_file_rt(new_client, 1);
- device_create_file_rt(new_client, 2);
- device_create_file_rt(new_client, 3);
- }
-#endif
return 0;
@@ -1535,33 +1462,6 @@ w83781d_init_client(struct i2c_client *client)
break;
}
}
-#ifdef W83781D_RT
-/*
- Fill up the RT Tables.
- We assume that they are 32 bytes long, in order for temp 1-3.
- Data sheet documentation is sparse.
- We also assume that it is only for the 781D although I suspect
- that the others support it as well....
-*/
-
- if (init && type == w83781d) {
- u16 k = 0;
-/*
- Auto-indexing doesn't seem to work...
- w83781d_write_value(client,W83781D_REG_RT_IDX,0);
-*/
- for (i = 0; i < 3; i++) {
- int j;
- for (j = 0; j < 32; j++) {
- w83781d_write_value(client,
- W83781D_REG_RT_IDX, k++);
- data->rt[i][j] =
- w83781d_read_value(client,
- W83781D_REG_RT_VAL);
- }
- }
- }
-#endif /* W83781D_RT */
if (init && type != as99127f) {
/* Enable temp2 */
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 56a67457341d4d..e62a91a45a291e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -587,7 +587,13 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
int ret;
if (adap->algo->master_xfer) {
- dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num);
+#ifdef DEBUG
+ for (ret = 0; ret < num; ret++) {
+ dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
+ "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
+ 'R' : 'W', msgs[ret].addr, msgs[ret].len);
+ }
+#endif
down(&adap->bus_lock);
ret = adap->algo->master_xfer(adap,msgs,num);
@@ -709,7 +715,7 @@ int i2c_probe(struct i2c_adapter *adapter,
at all */
found = 0;
- for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
+ for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
if (((adap_id == address_data->force[i]) ||
(address_data->force[i] == ANY_I2C_BUS)) &&
(addr == address_data->force[i+1])) {
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 3f70e4926cb613..5425e0f77d8608 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -67,7 +67,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag)
int pos;
u32 mask_bits;
- pos = (int)entry->mask_base;
+ pos = (long)entry->mask_base;
pci_read_config_dword(entry->dev, pos, &mask_bits);
mask_bits &= ~(1);
mask_bits |= flag;
@@ -555,7 +555,7 @@ static int msi_capability_init(struct pci_dev *dev)
dev->irq = vector;
entry->dev = dev;
if (is_mask_bit_support(control)) {
- entry->mask_base = (void __iomem *)msi_mask_bits_reg(pos,
+ entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
is_64bit_address(control));
}
/* Replace with MSI handler */
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index df102f9301e71e..c0ddb1eb8c4d68 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -219,9 +219,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
res->data.address64.min_address_range,
res->data.address64.address_length);
break;
+ case ACPI_RSTYPE_VENDOR:
+ break;
default:
- pnp_warn("PnPACPI: Alloc type : %d not handle",
- res->id);
+ pnp_warn("PnPACPI: unknown resource type %d", res->id);
return AE_ERROR;
}
@@ -508,7 +509,7 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res,
case ACPI_RSTYPE_END_DPF:
return AE_CTRL_TERMINATE;
default:
- pnp_warn("PnPACPI:Option type: %d not handle", res->id);
+ pnp_warn("PnPACPI: unknown resource type %d", res->id);
return AE_ERROR;
}
@@ -810,7 +811,7 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table,
mem ++;
break;
default: /* other type */
- pnp_warn("Invalid type");
+ pnp_warn("unknown resource type %d", resource->id);
return -EINVAL;
}
resource ++;
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 6701c11b406b3f..2b41e47b7d8094 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -64,7 +64,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20050211
+#define ACPI_CA_VERSION 0x20050309
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
@@ -198,7 +198,7 @@
/* Number of strings associated with the _OSI reserved method */
-#define ACPI_NUM_OSI_STRINGS 9
+#define ACPI_NUM_OSI_STRINGS 10
/******************************************************************************
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index 6a5da01e46fcde..26d907eae6fe3b 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -75,6 +75,11 @@ extern const char *acpi_gbl_SHRdecode[2];
extern const char *acpi_gbl_TYPdecode[4];
extern const char *acpi_gbl_BMdecode[2];
extern const char *acpi_gbl_SIZdecode[4];
+extern const char *acpi_gbl_TTPdecode[2];
+extern const char *acpi_gbl_MTPdecode[4];
+extern const char *acpi_gbl_TRSdecode[2];
+
+
extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES];
extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES];
extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES];
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index 4efbb8d7e704b7..237d63433581cf 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -374,6 +374,16 @@ acpi_ds_create_node (
/* dsutils - Parser/Interpreter interface utility routines */
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state);
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference);
+
u8
acpi_ds_is_result_used (
union acpi_parse_object *op,
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index 78395916e4cfbf..c5301f5ffaf4fd 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -617,7 +617,6 @@ acpi_ex_store_object_to_object (
acpi_status
acpi_ex_store_buffer_to_buffer (
- acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index f2b96f6be45b5b..01d3b4bc0c857a 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -774,6 +774,7 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_POWER_BUTTON_STATUS 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_STATUS 0x0200
#define ACPI_BITMASK_RT_CLOCK_STATUS 0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_STATUS 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_WAKE_STATUS 0x8000
#define ACPI_BITMASK_ALL_FIXED_STATUS (ACPI_BITMASK_TIMER_STATUS | \
@@ -789,6 +790,7 @@ struct acpi_bit_register_info
#define ACPI_BITMASK_POWER_BUTTON_ENABLE 0x0100
#define ACPI_BITMASK_SLEEP_BUTTON_ENABLE 0x0200
#define ACPI_BITMASK_RT_CLOCK_ENABLE 0x0400
+#define ACPI_BITMASK_PCIEXP_WAKE_DISABLE 0x4000 /* ACPI 3.0 */
#define ACPI_BITMASK_SCI_ENABLE 0x0001
#define ACPI_BITMASK_BUS_MASTER_RLD 0x0002
@@ -807,6 +809,7 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_POWER_BUTTON_STATUS 0x08
#define ACPI_BITPOSITION_SLEEP_BUTTON_STATUS 0x09
#define ACPI_BITPOSITION_RT_CLOCK_STATUS 0x0A
+#define ACPI_BITPOSITION_PCIEXP_WAKE_STATUS 0x0E /* ACPI 3.0 */
#define ACPI_BITPOSITION_WAKE_STATUS 0x0F
#define ACPI_BITPOSITION_TIMER_ENABLE 0x00
@@ -814,6 +817,7 @@ struct acpi_bit_register_info
#define ACPI_BITPOSITION_POWER_BUTTON_ENABLE 0x08
#define ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE 0x09
#define ACPI_BITPOSITION_RT_CLOCK_ENABLE 0x0A
+#define ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE 0x0E /* ACPI 3.0 */
#define ACPI_BITPOSITION_SCI_ENABLE 0x00
#define ACPI_BITPOSITION_BUS_MASTER_RLD 0x01
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index b4479061b8f905..c627bc408a6b11 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -328,7 +328,6 @@ int acpi_bus_receive_event (struct acpi_bus_event *event);
int acpi_bus_register_driver (struct acpi_driver *driver);
int acpi_bus_unregister_driver (struct acpi_driver *driver);
int acpi_bus_scan (struct acpi_device *start);
-int acpi_bus_trim(struct acpi_device *start, int rmdevice);
int acpi_bus_add (struct acpi_device **child, struct acpi_device *parent,
acpi_handle handle, int type);
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 0c964592a2c34b..c62e92ec43b289 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -56,7 +56,8 @@
/* ACPI PCI Interrupt Link (pci_link.c) */
int acpi_irq_penalty_init (void);
-int acpi_pci_link_get_irq (acpi_handle handle, int index, int* edge_level, int* active_high_low);
+int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level,
+ int *active_high_low, char **name);
/* ACPI PCI Interrupt Routing (pci_irq.c) */
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index 6b2284c9e8949f..c97843f6bcbc23 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -94,6 +94,7 @@ struct acpi_walk_state
union acpi_generic_state *control_state; /* List of control states (nested IFs) */
struct acpi_namespace_node *deferred_node; /* Used when executing deferred opcodes */
struct acpi_gpe_event_info *gpe_event_info; /* Info for GPE (_Lxx/_Exx methods only */
+ union acpi_operand_object *implicit_return_obj;
struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *method_call_node; /* Called method Node*/
union acpi_parse_object *method_call_op; /* method_call Op if running a method */
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index f39ed91b5bc885..7eee731112b18f 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -261,6 +261,8 @@ struct madt_local_sapic
u8 local_sapic_eid; /* SAPIC EID */
u8 reserved [3]; /* Reserved - must be zero */
LOCAL_APIC_FLAGS
+ u32 processor_uID; /* Numeric UID - ACPI 3.0 */
+ char processor_uIDstring[1]; /* String UID - ACPI 3.0 */
};
struct madt_interrupt_source
@@ -272,7 +274,7 @@ struct madt_interrupt_source
u8 processor_eid; /* Processor EID */
u8 io_sapic_vector; /* Vector value for PMI interrupts */
u32 interrupt; /* Global system interrupt */
- u32 reserved; /* Reserved - must be zero */
+ u32 flags; /* Interrupt Source Flags */
};
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index ea3ca08d88aa85..e1729c967e052a 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -108,7 +108,7 @@ struct facs_descriptor_rev2
/*
- * ACPI 2.0 Generic Address Structure (GAS)
+ * ACPI 2.0+ Generic Address Structure (GAS)
*/
struct acpi_generic_address
{
@@ -159,7 +159,7 @@ struct acpi_generic_address
u16 iapc_boot_arch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/
/*
- * ACPI 2.0 Fixed ACPI Description Table (FADT)
+ * ACPI 2.0+ Fixed ACPI Description Table (FADT)
*/
struct fadt_descriptor_rev2
{
@@ -174,17 +174,25 @@ struct fadt_descriptor_rev2
u32 sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */
u32 fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */
u32 rtcs4 : 1; /* RTC wakeup stat not possible from S4 */
- u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits*/
+ u32 tmr_val_ext : 1; /* Indicates tmr_val is 32 bits 0=24-bits */
u32 dock_cap : 1; /* Supports Docking */
- u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG*/
- u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed. */
- u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices.*/
+ u32 reset_reg_sup : 1; /* Indicates system supports system reset via the FADT RESET_REG */
+ u32 sealed_case : 1; /* Indicates system has no internal expansion capabilities and case is sealed */
+ u32 headless : 1; /* Indicates system does not have local video capabilities or local input devices */
u32 cpu_sw_sleep : 1; /* Indicates to OSPM that a processor native instruction */
- /* Must be executed after writing the SLP_TYPx register. */
- u32 reserved6 : 18; /* Reserved - must be zero */
+ /* must be executed after writing the SLP_TYPx register */
+ /* ACPI 3.0 flag bits */
+
+ u32 pci_exp_wak : 1; /* System supports PCIEXP_WAKE (STS/EN) bits */
+ u32 use_platform_clock : 1; /* OSPM should use platform-provided timer */
+ u32 S4rtc_sts_valid : 1; /* Contents of RTC_STS valid after S4 wake */
+ u32 remote_power_on_capable : 1; /* System is compatible with remote power on */
+ u32 force_apic_cluster_model : 1; /* All local APICs must use cluster model */
+ u32 force_apic_physical_destination_mode : 1; /* all local x_aPICs must use physical dest mode */
+ u32 reserved6 : 12;/* Reserved - must be zero */
struct acpi_generic_address reset_register; /* Reset register address in GAS format */
- u8 reset_value; /* Value to write to the reset_register port to reset the system. */
+ u8 reset_value; /* Value to write to the reset_register port to reset the system */
u8 reserved7[3]; /* These three bytes must be zero */
u64 xfirmware_ctrl; /* 64-bit physical address of FACS */
u64 Xdsdt; /* 64-bit physical address of DSDT */
@@ -199,7 +207,7 @@ struct fadt_descriptor_rev2
};
-/* "Downrevved" ACPI 2.0 FADT descriptor */
+/* "Down-revved" ACPI 2.0 FADT descriptor */
struct fadt_descriptor_rev2_minus
{
@@ -213,7 +221,7 @@ struct fadt_descriptor_rev2_minus
};
-/* Embedded Controller */
+/* ECDT - Embedded Controller Boot Resources Table */
struct ec_boot_resources
{
@@ -226,6 +234,55 @@ struct ec_boot_resources
};
+/* SRAT - System Resource Affinity Table */
+
+struct static_resource_alloc
+{
+ u8 type;
+ u8 length;
+ u8 proximity_domain_lo;
+ u8 apic_id;
+ u32 enabled :1;
+ u32 reserved3 :31;
+ u8 local_sapic_eid;
+ u8 proximity_domain_hi[3];
+ u32 reserved4;
+};
+
+struct memory_affinity
+{
+ u8 type;
+ u8 length;
+ u32 proximity_domain;
+ u16 reserved3;
+ u64 base_address;
+ u64 address_length;
+ u32 reserved4;
+ u32 enabled :1;
+ u32 hot_pluggable :1;
+ u32 non_volatile :1;
+ u32 reserved5 :29;
+ u64 reserved6;
+};
+
+struct system_resource_affinity
+{
+ ACPI_TABLE_HEADER_DEF
+ u32 reserved1; /* Must be value '1' */
+ u64 reserved2;
+};
+
+
+/* SLIT - System Locality Distance Information Table */
+
+struct system_locality_info
+{
+ ACPI_TABLE_HEADER_DEF
+ u64 locality_count;
+ u8 entry[1][1];
+};
+
+
#pragma pack()
#endif /* __ACTBL2_H__ */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 51cb780c241e9c..7acb550af3eb9f 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -653,24 +653,26 @@ typedef u8 acpi_adr_space_type;
#define ACPI_BITREG_SLEEP_BUTTON_STATUS 0x04
#define ACPI_BITREG_RT_CLOCK_STATUS 0x05
#define ACPI_BITREG_WAKE_STATUS 0x06
-
-#define ACPI_BITREG_TIMER_ENABLE 0x07
-#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x08
-#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x09
-#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0A
-#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0B
-#define ACPI_BITREG_WAKE_ENABLE 0x0C
-
-#define ACPI_BITREG_SCI_ENABLE 0x0D
-#define ACPI_BITREG_BUS_MASTER_RLD 0x0E
-#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x0F
-#define ACPI_BITREG_SLEEP_TYPE_A 0x10
-#define ACPI_BITREG_SLEEP_TYPE_B 0x11
-#define ACPI_BITREG_SLEEP_ENABLE 0x12
-
-#define ACPI_BITREG_ARB_DISABLE 0x13
-
-#define ACPI_BITREG_MAX 0x13
+#define ACPI_BITREG_PCIEXP_WAKE_STATUS 0x07
+
+#define ACPI_BITREG_TIMER_ENABLE 0x08
+#define ACPI_BITREG_GLOBAL_LOCK_ENABLE 0x09
+#define ACPI_BITREG_POWER_BUTTON_ENABLE 0x0A
+#define ACPI_BITREG_SLEEP_BUTTON_ENABLE 0x0B
+#define ACPI_BITREG_RT_CLOCK_ENABLE 0x0C
+#define ACPI_BITREG_WAKE_ENABLE 0x0D
+#define ACPI_BITREG_PCIEXP_WAKE_DISABLE 0x0E
+
+#define ACPI_BITREG_SCI_ENABLE 0x0F
+#define ACPI_BITREG_BUS_MASTER_RLD 0x10
+#define ACPI_BITREG_GLOBAL_LOCK_RELEASE 0x11
+#define ACPI_BITREG_SLEEP_TYPE_A 0x12
+#define ACPI_BITREG_SLEEP_TYPE_B 0x13
+#define ACPI_BITREG_SLEEP_ENABLE 0x14
+
+#define ACPI_BITREG_ARB_DISABLE 0x15
+
+#define ACPI_BITREG_MAX 0x15
#define ACPI_NUM_BITREG ACPI_BITREG_MAX + 1
@@ -1206,6 +1208,7 @@ struct acpi_resource_address64
u64 max_address_range;
u64 address_translation_offset;
u64 address_length;
+ u64 type_specific_attributes;
struct acpi_resource_source resource_source;
};
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 5a956b549b1e58..57bf9362335dc4 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -226,6 +226,7 @@
*/
#define ACPI_STRSTR(s1,s2) strstr((s1), (s2))
+#define ACPI_STRCHR(s1,c) strchr((s1), (c))
#ifdef ACPI_FUTURE_USAGE
#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s))
@@ -294,6 +295,7 @@ typedef char *va_list;
#define ACPI_STRSTR(s1,s2) acpi_ut_strstr ((s1), (s2))
+#define ACPI_STRCHR(s1,c) acpi_ut_strchr ((s1), (c))
#ifdef ACPI_FUTURE_USAGE
#define ACPI_STRUPR(s) (void) acpi_ut_strupr ((s))
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index d1c8a8b98f6a6e..2f50a5bb0c781d 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -201,7 +201,6 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) {
/* in processor_throttling.c */
int acpi_processor_get_throttling_info (struct acpi_processor *pr);
int acpi_processor_set_throttling (struct acpi_processor *pr, int state);
-int acpi_processor_throttling_open_fs(struct inode *inode, struct file *file);
ssize_t acpi_processor_write_throttling (
struct file *file,
const char __user *buffer,
@@ -217,7 +216,6 @@ int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *dev
/* in processor_thermal.c */
int acpi_processor_get_limit_info (struct acpi_processor *pr);
-int acpi_processor_limit_open_fs(struct inode *inode, struct file *file);
ssize_t acpi_processor_write_limit (
struct file *file,
const char __user *buffer,
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index d6838c9b7bb4ee..c4a227acfeb0a4 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -3,16 +3,14 @@
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 2001-2003 Hewlett-Packard Co
+ * (c) Copyright 2001-2003, 2005 Hewlett-Packard Development Company, L.P.
* David Mosberger-Tang <davidm@hpl.hp.com>
+ * Bjorn Helgaas <bjorn.helgaas@hp.com>
*/
#ifndef _ASM_IA64_SMP_H
#define _ASM_IA64_SMP_H
#include <linux/config.h>
-
-#ifdef CONFIG_SMP
-
#include <linux/init.h>
#include <linux/threads.h>
#include <linux/kernel.h>
@@ -24,6 +22,25 @@
#include <asm/processor.h>
#include <asm/ptrace.h>
+static inline unsigned int
+ia64_get_lid (void)
+{
+ union {
+ struct {
+ unsigned long reserved : 16;
+ unsigned long eid : 8;
+ unsigned long id : 8;
+ unsigned long ignored : 32;
+ } f;
+ unsigned long bits;
+ } lid;
+
+ lid.bits = ia64_getreg(_IA64_REG_CR_LID);
+ return lid.f.id << 8 | lid.f.eid;
+}
+
+#ifdef CONFIG_SMP
+
#define XTP_OFFSET 0x1e0008
#define SMP_IRQ_REDIRECTION (1 << 0)
@@ -90,22 +107,7 @@ max_xtp (void)
writeb(0x0f, ipi_base_addr + XTP_OFFSET); /* Set XTP to max */
}
-static inline unsigned int
-hard_smp_processor_id (void)
-{
- union {
- struct {
- unsigned long reserved : 16;
- unsigned long eid : 8;
- unsigned long id : 8;
- unsigned long ignored : 32;
- } f;
- unsigned long bits;
- } lid;
-
- lid.bits = ia64_getreg(_IA64_REG_CR_LID);
- return lid.f.id << 8 | lid.f.eid;
-}
+#define hard_smp_processor_id() ia64_get_lid()
/* Upping and downing of CPUs */
extern int __cpu_disable (void);
@@ -125,7 +127,8 @@ extern void unlock_ipi_calllock(void);
#else
-#define cpu_logical_id(cpuid) 0
+#define cpu_logical_id(i) 0
+#define cpu_physical_id(i) ia64_get_lid()
#endif /* CONFIG_SMP */
#endif /* _ASM_IA64_SMP_H */
diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h
index 3ce60976d474b8..c916bd22767a14 100644
--- a/include/asm-ia64/sn/addrs.h
+++ b/include/asm-ia64/sn/addrs.h
@@ -11,6 +11,7 @@
#include <asm/percpu.h>
#include <asm/sn/types.h>
+#include <asm/sn/arch.h>
#include <asm/sn/pda.h>
/*
@@ -57,9 +58,9 @@
/*
* Define basic shift & mask constants for manipulating NASIDs and AS values.
*/
-#define NASID_BITMASK (pda->nasid_bitmask)
-#define NASID_SHIFT (pda->nasid_shift)
-#define AS_SHIFT (pda->as_shift)
+#define NASID_BITMASK (sn_hub_info->nasid_bitmask)
+#define NASID_SHIFT (sn_hub_info->nasid_shift)
+#define AS_SHIFT (sn_hub_info->as_shift)
#define AS_BITMASK 0x3UL
#define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT)
diff --git a/include/asm-ia64/sn/arch.h b/include/asm-ia64/sn/arch.h
index bfc922a0ab7179..7c349f07916a1b 100644
--- a/include/asm-ia64/sn/arch.h
+++ b/include/asm-ia64/sn/arch.h
@@ -12,10 +12,34 @@
#define _ASM_IA64_SN_ARCH_H
#include <asm/types.h>
+#include <asm/percpu.h>
#include <asm/sn/types.h>
#include <asm/sn/sn_cpuid.h>
/*
+ * The following defines attributes of the HUB chip. These attributes are
+ * frequently referenced. They are kept in the per-cpu data areas of each cpu.
+ * They are kept together in a struct to minimize cache misses.
+ */
+struct sn_hub_info_s {
+ u8 shub2;
+ u8 nasid_shift;
+ u8 as_shift;
+ u8 shub_1_1_found;
+ u16 nasid_bitmask;
+};
+DECLARE_PER_CPU(struct sn_hub_info_s, __sn_hub_info);
+#define sn_hub_info (&__get_cpu_var(__sn_hub_info))
+#define is_shub2() (sn_hub_info->shub2)
+#define is_shub1() (sn_hub_info->shub2 == 0)
+
+/*
+ * Use this macro to test if shub 1.1 wars should be enabled
+ */
+#define enable_shub_wars_1_1() (sn_hub_info->shub_1_1_found)
+
+
+/*
* This is the maximum number of nodes that can be part of a kernel.
* Effectively, it's the maximum number of compact node ids (cnodeid_t).
* This is not necessarily the same as MAX_NASIDS.
diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h
index 6465e8ab2bccd3..e940d3647c8043 100644
--- a/include/asm-ia64/sn/pda.h
+++ b/include/asm-ia64/sn/pda.h
@@ -37,11 +37,6 @@ typedef struct pda_s {
* Support for SN LEDs
*/
volatile short *led_address;
- u16 nasid_bitmask;
- u8 shub2;
- u8 nasid_shift;
- u8 as_shift;
- u8 shub_1_1_found;
u8 led_state;
u8 hb_state; /* supports blinking heartbeat leds */
unsigned int hb_count;
@@ -53,8 +48,6 @@ typedef struct pda_s {
unsigned long pio_write_status_val;
volatile unsigned long *pio_shub_war_cam_addr;
- struct bteinfo_s *cpu_bte_if[BTES_PER_NODE]; /* cpu interface order */
-
unsigned long sn_soft_irr[4];
unsigned long sn_in_service_ivecs[4];
short cnodeid_to_nasid_table[MAX_NUMNODES];
@@ -84,12 +77,4 @@ DECLARE_PER_CPU(struct pda_s, pda_percpu);
#define pdacpu(cpu) (&per_cpu(pda_percpu, cpu))
-/*
- * Use this macro to test if shub 1.1 wars should be enabled
- */
-#define enable_shub_wars_1_1() (pda->shub_1_1_found)
-
-#define is_shub2() (pda->shub2)
-#define is_shub1() (pda->shub2 == 0)
-
#endif /* _ASM_IA64_SN_PDA_H */
diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
index 749f45042cdcc1..685435af170d8d 100644
--- a/include/asm-ia64/sn/sn_cpuid.h
+++ b/include/asm-ia64/sn/sn_cpuid.h
@@ -135,9 +135,10 @@ extern int nasid_slice_to_cpuid(int, int);
#define nasid_to_cnodeid(nasid) (physical_node_map[nasid])
/*
- * partition_coherence_id - cget the coherence ID of the current partition
+ * partition_coherence_id - get the coherence ID of the current partition
*/
-#define partition_coherence_id() (get_nasid() >> 9)
+extern u8 sn_coherency_id;
+#define partition_coherence_id() (sn_coherency_id)
#endif /* _ASM_IA64_SN_SN_CPUID_H */
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 4ecc05e8ad5772..88c31b53dc0974 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -18,6 +18,7 @@
#include <asm/sn/arch.h>
#include <asm/sn/geo.h>
#include <asm/sn/nodepda.h>
+#include <asm/sn/shub_mmr.h>
// SGI Specific Calls
#define SN_SAL_POD_MODE 0x02000001
@@ -34,7 +35,7 @@
#define SN_SAL_PRINT_ERROR 0x02000012
#define SN_SAL_SET_ERROR_HANDLING_FEATURES 0x0200001a // reentrant
#define SN_SAL_GET_FIT_COMPT 0x0200001b // reentrant
-#define SN_SAL_GET_HUB_INFO 0x0200001c
+#define SN_SAL_GET_SN_INFO 0x0200001c
#define SN_SAL_GET_SAPIC_INFO 0x0200001d
#define SN_SAL_CONSOLE_PUTC 0x02000021
#define SN_SAL_CONSOLE_GETC 0x02000022
@@ -935,15 +936,24 @@ ia64_sn_get_sapic_info(int sapicid, int *nasid, int *subnode, int *slice)
/*
* Returns information about the HUB/SHUB.
* In:
- * arg0 - SN_SAL_GET_HUB_INFO
+ * arg0 - SN_SAL_GET_SN_INFO
* arg1 - 0 (other values reserved for future use)
* Out:
- * v0 - shub type (0=shub1, 1=shub2)
- * v1 - masid mask (ex., 0x7ff for 11 bit nasid)
- * v2 - bit position of low nasid bit
+ * v0
+ * [7:0] - shub type (0=shub1, 1=shub2)
+ * [15:8] - Log2 max number of nodes in entire system (includes
+ * C-bricks, I-bricks, etc)
+ * [23:16] - Log2 of nodes per sharing domain
+ * [31:24] - partition ID
+ * [39:32] - coherency_id
+ * [47:40] - regionsize
+ * v1
+ * [15:0] - nasid mask (ex., 0x7ff for 11 bit nasid)
+ * [23:15] - bit position of low nasid bit
*/
static inline u64
-ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
+ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift,
+ u8 *systemsize, u8 *sharing_domain_size, u8 *partid, u8 *coher, u8 *reg)
{
struct ia64_sal_retval ret_stuff;
@@ -951,13 +961,22 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
ret_stuff.v0 = 0;
ret_stuff.v1 = 0;
ret_stuff.v2 = 0;
- SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_HUB_INFO, fc, 0, 0, 0, 0, 0, 0);
+ SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0);
/***** BEGIN HACK - temp til old proms no longer supported ********/
if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) {
- if (arg1) *arg1 = 0;
- if (arg2) *arg2 = 0x7ff;
- if (arg3) *arg3 = 38;
+ int nasid = get_sapicid() & 0xfff;;
+#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL
+#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48
+ if (shubtype) *shubtype = 0;
+ if (nasid_bitmask) *nasid_bitmask = 0x7ff;
+ if (nasid_shift) *nasid_shift = 38;
+ if (systemsize) *systemsize = 11;
+ if (sharing_domain_size) *sharing_domain_size = 9;
+ if (partid) *partid = ia64_sn_sysctl_partition_get(nasid);
+ if (coher) *coher = nasid >> 9;
+ if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >>
+ SH_SHUB_ID_NODES_PER_BIT_SHFT;
return 0;
}
/***** END HACK *******/
@@ -965,9 +984,14 @@ ia64_sn_get_hub_info(int fc, u64 *arg1, u64 *arg2, u64 *arg3)
if (ret_stuff.status < 0)
return ret_stuff.status;
- if (arg1) *arg1 = ret_stuff.v0;
- if (arg2) *arg2 = ret_stuff.v1;
- if (arg3) *arg3 = ret_stuff.v2;
+ if (shubtype) *shubtype = ret_stuff.v0 & 0xff;
+ if (systemsize) *systemsize = (ret_stuff.v0 >> 8) & 0xff;
+ if (sharing_domain_size) *sharing_domain_size = (ret_stuff.v0 >> 16) & 0xff;
+ if (partid) *partid = (ret_stuff.v0 >> 24) & 0xff;
+ if (coher) *coher = (ret_stuff.v0 >> 32) & 0xff;
+ if (reg) *reg = (ret_stuff.v0 >> 40) & 0xff;
+ if (nasid_bitmask) *nasid_bitmask = (ret_stuff.v1 & 0xffff);
+ if (nasid_shift) *nasid_shift = (ret_stuff.v1 >> 16) & 0xff;
return 0;
}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 5cbf3486926f51..aefe6d051ace16 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -455,8 +455,6 @@ struct acpi_prt_list {
struct list_head entries;
};
-extern struct acpi_prt_list acpi_prt;
-
struct pci_dev;
int acpi_pci_irq_enable (struct pci_dev *dev);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index da901fd6b59086..9f2ae600683c63 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -306,9 +306,6 @@ struct i2c_client_address_data {
#define ANY_I2C_BUS 0xffff
#define ANY_I2C_ISA_BUS 9191
-/* The length of the option lists */
-#define I2C_CLIENT_MAX_OPTS 48
-
/* ----- functions exported by i2c.o */
@@ -526,6 +523,9 @@ union i2c_smbus_data {
#define I2C_MAJOR 89 /* Device major number */
/* These defines are used for probing i2c client addresses */
+/* The length of the option lists */
+#define I2C_CLIENT_MAX_OPTS 48
+
/* Default fill of many variables */
#define I2C_CLIENT_DEFAULTS {I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
@@ -544,19 +544,12 @@ union i2c_smbus_data {
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END, \
I2C_CLIENT_END, I2C_CLIENT_END, I2C_CLIENT_END}
-/* This is ugly. We need to evaluate I2C_CLIENT_MAX_OPTS before it is
- stringified */
-#define I2C_CLIENT_MODPARM_AUX1(x) "1-" #x "h"
-#define I2C_CLIENT_MODPARM_AUX(x) I2C_CLIENT_MODPARM_AUX1(x)
-#define I2C_CLIENT_MODPARM I2C_CLIENT_MODPARM_AUX(I2C_CLIENT_MAX_OPTS)
-
/* I2C_CLIENT_MODULE_PARM creates a module parameter, and puts it in the
module header */
#define I2C_CLIENT_MODULE_PARM(var,desc) \
static unsigned short var[I2C_CLIENT_MAX_OPTS] = I2C_CLIENT_DEFAULTS; \
static unsigned int var##_num; \
- /*MODULE_PARM(var,I2C_CLIENT_MODPARM);*/ \
module_param_array(var, short, &var##_num, 0); \
MODULE_PARM_DESC(var,desc)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 9d59df1fe545be..3e750ef09e6011 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -349,7 +349,7 @@ static void sco_sock_cleanup_listen(struct sock *parent)
}
parent->sk_state = BT_CLOSED;
- sock_set_flag(sk, SOCK_ZAPPED);
+ sock_set_flag(parent, SOCK_ZAPPED);
}
/* Kill socket (only if zapped and orphan)