diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-31 16:06:50 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-03-31 16:06:50 -0800 |
commit | f6ea76c0dc98f2a9219ee5327a2d3a00dfb7e89b (patch) | |
tree | c7c6360b40213958ee55fff48cc16c506357ce5d | |
parent | 54356933c64d5f26e15c040d6bb81e8d2d616555 (diff) | |
parent | 63b61eadc2c4fd8ef6932e3a31370927b2e4951f (diff) | |
download | history-f6ea76c0dc98f2a9219ee5327a2d3a00dfb7e89b.tar.gz |
Merge bk://kernel.bkbits.net/davem/net-2.6
into ppc970.osdl.org:/home/torvalds/v2.6/linux
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, ¤t_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, ¤t_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) |