mirror of https://gitee.com/openkylin/linux.git
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
This commit is contained in:
commit
c08319a9d5
|
@ -223,6 +223,7 @@ CAST5 algorithm contributors:
|
|||
|
||||
TEA/XTEA algorithm contributors:
|
||||
Aaron Grothe
|
||||
Michael Ringe
|
||||
|
||||
Khazad algorithm contributors:
|
||||
Aaron Grothe
|
||||
|
|
|
@ -102,16 +102,6 @@ Who: Jody McIntyre <scjody@steamballoon.com>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: register_serial/unregister_serial
|
||||
When: September 2005
|
||||
Why: This interface does not allow serial ports to be registered against
|
||||
a struct device, and as such does not allow correct power management
|
||||
of such ports. 8250-based ports should use serial8250_register_port
|
||||
and serial8250_unregister_port, or platform devices instead.
|
||||
Who: Russell King <rmk@arm.linux.org.uk>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
|
||||
When: November 2005
|
||||
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
|
||||
|
|
|
@ -133,6 +133,7 @@ Table 1-1: Process specific entries in /proc
|
|||
statm Process memory status information
|
||||
status Process status in human readable form
|
||||
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
|
||||
smaps Extension based on maps, presenting the rss size for each mapped file
|
||||
..............................................................................
|
||||
|
||||
For example, to get the status information of a process, all you have to do is
|
||||
|
|
|
@ -90,7 +90,7 @@ void device_remove_file(struct device *, struct device_attribute *);
|
|||
|
||||
It also defines this helper for defining device attributes:
|
||||
|
||||
#define DEVICE_ATTR(_name,_mode,_show,_store) \
|
||||
#define DEVICE_ATTR(_name, _mode, _show, _store) \
|
||||
struct device_attribute dev_attr_##_name = { \
|
||||
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
||||
.show = _show, \
|
||||
|
@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
|
|||
|
||||
For example, declaring
|
||||
|
||||
static DEVICE_ATTR(foo,0644,show_foo,store_foo);
|
||||
static DEVICE_ATTR(foo, S_IWUSR | S_IRUGO, show_foo, store_foo);
|
||||
|
||||
is equivalent to doing:
|
||||
|
||||
static struct device_attribute dev_attr_foo = {
|
||||
.attr = {
|
||||
.name = "foo",
|
||||
.mode = 0644,
|
||||
.mode = S_IWUSR | S_IRUGO,
|
||||
},
|
||||
.show = show_foo,
|
||||
.store = store_foo,
|
||||
|
@ -121,8 +121,8 @@ set of sysfs operations for forwarding read and write calls to the
|
|||
show and store methods of the attribute owners.
|
||||
|
||||
struct sysfs_ops {
|
||||
ssize_t (*show)(struct kobject *, struct attribute *,char *);
|
||||
ssize_t (*store)(struct kobject *,struct attribute *,const char *);
|
||||
ssize_t (*show)(struct kobject *, struct attribute *, char *);
|
||||
ssize_t (*store)(struct kobject *, struct attribute *, const char *);
|
||||
};
|
||||
|
||||
[ Subsystems should have already defined a struct kobj_type as a
|
||||
|
@ -137,7 +137,7 @@ calls the associated methods.
|
|||
|
||||
To illustrate:
|
||||
|
||||
#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
|
||||
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
|
||||
#define to_dev(d) container_of(d, struct device, kobj)
|
||||
|
||||
static ssize_t
|
||||
|
@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
|||
ssize_t ret = 0;
|
||||
|
||||
if (dev_attr->show)
|
||||
ret = dev_attr->show(dev,buf);
|
||||
ret = dev_attr->show(dev, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -216,16 +216,16 @@ A very simple (and naive) implementation of a device attribute is:
|
|||
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf,"%s\n",dev->name);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
|
||||
}
|
||||
|
||||
static ssize_t store_name(struct device * dev, const char * buf)
|
||||
{
|
||||
sscanf(buf,"%20s",dev->name);
|
||||
return strlen(buf);
|
||||
sscanf(buf, "%20s", dev->name);
|
||||
return strnlen(buf, PAGE_SIZE);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name,S_IRUGO,show_name,store_name);
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_name, store_name);
|
||||
|
||||
|
||||
(Note that the real implementation doesn't allow userspace to set the
|
||||
|
@ -290,7 +290,7 @@ struct device_attribute {
|
|||
|
||||
Declaring:
|
||||
|
||||
DEVICE_ATTR(_name,_str,_mode,_show,_store);
|
||||
DEVICE_ATTR(_name, _str, _mode, _show, _store);
|
||||
|
||||
Creation/Removal:
|
||||
|
||||
|
@ -310,7 +310,7 @@ struct bus_attribute {
|
|||
|
||||
Declaring:
|
||||
|
||||
BUS_ATTR(_name,_mode,_show,_store)
|
||||
BUS_ATTR(_name, _mode, _show, _store)
|
||||
|
||||
Creation/Removal:
|
||||
|
||||
|
@ -331,7 +331,7 @@ struct driver_attribute {
|
|||
|
||||
Declaring:
|
||||
|
||||
DRIVER_ATTR(_name,_mode,_show,_store)
|
||||
DRIVER_ATTR(_name, _mode, _show, _store)
|
||||
|
||||
Creation/Removal:
|
||||
|
||||
|
|
|
@ -2,16 +2,11 @@ Kernel driver lm78
|
|||
==================
|
||||
|
||||
Supported chips:
|
||||
* National Semiconductor LM78
|
||||
* National Semiconductor LM78 / LM78-J
|
||||
Prefix: 'lm78'
|
||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||
Datasheet: Publicly available at the National Semiconductor website
|
||||
http://www.national.com/
|
||||
* National Semiconductor LM78-J
|
||||
Prefix: 'lm78-j'
|
||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||
Datasheet: Publicly available at the National Semiconductor website
|
||||
http://www.national.com/
|
||||
* National Semiconductor LM79
|
||||
Prefix: 'lm79'
|
||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||
|
|
|
@ -0,0 +1,174 @@
|
|||
Kernel driver w83792d
|
||||
=====================
|
||||
|
||||
Supported chips:
|
||||
* Winbond W83792D
|
||||
Prefix: 'w83792d'
|
||||
Addresses scanned: I2C 0x2c - 0x2f
|
||||
Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035
|
||||
|
||||
Author: Chunhao Huang
|
||||
Contact: DZShen <DZShen@Winbond.com.tw>
|
||||
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
* init int
|
||||
(default 1)
|
||||
Use 'init=0' to bypass initializing the chip.
|
||||
Try this if your computer crashes when you load the module.
|
||||
|
||||
* force_subclients=bus,caddr,saddr,saddr
|
||||
This is used to force the i2c addresses for subclients of
|
||||
a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
|
||||
to force the subclients of chip 0x2f on bus 0 to i2c addresses
|
||||
0x4a and 0x4b.
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This driver implements support for the Winbond W83792AD/D.
|
||||
|
||||
Detection of the chip can sometimes be foiled because it can be in an
|
||||
internal state that allows no clean access (Bank with ID register is not
|
||||
currently selected). If you know the address of the chip, use a 'force'
|
||||
parameter; this will put it into a more well-behaved state first.
|
||||
|
||||
The driver implements three temperature sensors, seven fan rotation speed
|
||||
sensors, nine voltage sensors, and two automatic fan regulation
|
||||
strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II.
|
||||
Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run
|
||||
synchronized with selected fan (fan1-fan3). This functionality and manual PWM
|
||||
control for fan4-fan7 is not yet implemented.
|
||||
|
||||
Temperatures are measured in degrees Celsius and measurement resolution is 1
|
||||
degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
|
||||
the temperature gets higher than the Overtemperature Shutdown value; it stays
|
||||
on until the temperature falls below the Hysteresis value.
|
||||
|
||||
Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
|
||||
triggered if the rotation speed has dropped below a programmable limit. Fan
|
||||
readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
|
||||
128) to give the readings more range or accuracy.
|
||||
|
||||
Voltage sensors (also known as IN sensors) report their values in millivolts.
|
||||
An alarm is triggered if the voltage has crossed a programmable minimum
|
||||
or maximum limit.
|
||||
|
||||
Alarms are provided as output from "realtime status register". Following bits
|
||||
are defined:
|
||||
|
||||
bit - alarm on:
|
||||
0 - in0
|
||||
1 - in1
|
||||
2 - temp1
|
||||
3 - temp2
|
||||
4 - temp3
|
||||
5 - fan1
|
||||
6 - fan2
|
||||
7 - fan3
|
||||
8 - in2
|
||||
9 - in3
|
||||
10 - in4
|
||||
11 - in5
|
||||
12 - in6
|
||||
13 - VID change
|
||||
14 - chassis
|
||||
15 - fan7
|
||||
16 - tart1
|
||||
17 - tart2
|
||||
18 - tart3
|
||||
19 - in7
|
||||
20 - in8
|
||||
21 - fan4
|
||||
22 - fan5
|
||||
23 - fan6
|
||||
|
||||
Tart will be asserted while target temperature cannot be achieved after 3 minutes
|
||||
of full speed rotation of corresponding fan.
|
||||
|
||||
In addition to the alarms described above, there is a CHAS alarm on the chips
|
||||
which triggers if your computer case is open (This one is latched, contrary
|
||||
to realtime alarms).
|
||||
|
||||
The chips only update values each 3 seconds; reading them more often will
|
||||
do no harm, but will return 'old' values.
|
||||
|
||||
|
||||
W83792D PROBLEMS
|
||||
----------------
|
||||
Known problems:
|
||||
- This driver is only for Winbond W83792D C version device, there
|
||||
are also some motherboards with B version W83792D device. The
|
||||
calculation method to in6-in7(measured value, limits) is a little
|
||||
different between C and B version. C or B version can be identified
|
||||
by CR[0x49h].
|
||||
- The function of vid and vrm has not been finished, because I'm NOT
|
||||
very familiar with them. Adding support is welcome.
|
||||
- The function of chassis open detection needs more tests.
|
||||
- If you have ASUS server board and chip was not found: Then you will
|
||||
need to upgrade to latest (or beta) BIOS. If it does not help please
|
||||
contact us.
|
||||
|
||||
Fan control
|
||||
-----------
|
||||
|
||||
Manual mode
|
||||
-----------
|
||||
|
||||
Works as expected. You just need to specify desired PWM/DC value (fan speed)
|
||||
in appropriate pwm# file.
|
||||
|
||||
Thermal cruise
|
||||
--------------
|
||||
|
||||
In this mode, W83792D provides the Smart Fan system to automatically control
|
||||
fan speed to keep the temperatures of CPU and the system within specific
|
||||
range. At first a wanted temperature and interval must be set. This is done
|
||||
via thermal_cruise# file. The tolerance# file serves to create T +- tolerance
|
||||
interval. The fan speed will be lowered as long as the current temperature
|
||||
remains below the thermal_cruise# +- tolerance# value. Once the temperature
|
||||
exceeds the high limit (T+tolerance), the fan will be turned on with a
|
||||
specific speed set by pwm# and automatically controlled its PWM duty cycle
|
||||
with the temperature varying. Three conditions may occur:
|
||||
|
||||
(1) If the temperature still exceeds the high limit, PWM duty
|
||||
cycle will increase slowly.
|
||||
|
||||
(2) If the temperature goes below the high limit, but still above the low
|
||||
limit (T-tolerance), the fan speed will be fixed at the current speed because
|
||||
the temperature is in the target range.
|
||||
|
||||
(3) If the temperature goes below the low limit, PWM duty cycle will decrease
|
||||
slowly to 0 or a preset stop value until the temperature exceeds the low
|
||||
limit. (The preset stop value handling is not yet implemented in driver)
|
||||
|
||||
Smart Fan II
|
||||
------------
|
||||
|
||||
W83792D also provides a special mode for fan. Four temperature points are
|
||||
available. When related temperature sensors detects the temperature in preset
|
||||
temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run
|
||||
on programmed value from sf2_level@_fan#. You need to set four temperatures
|
||||
for each fan.
|
||||
|
||||
|
||||
/sys files
|
||||
----------
|
||||
|
||||
pwm[1-3] - this file stores PWM duty cycle or DC value (fan speed) in range:
|
||||
0 (stop) to 255 (full)
|
||||
pwm[1-3]_enable - this file controls mode of fan/temperature control:
|
||||
* 0 Disabled
|
||||
* 1 Manual mode
|
||||
* 2 Smart Fan II
|
||||
* 3 Thermal Cruise
|
||||
pwm[1-3]_mode - Select PWM of DC mode
|
||||
* 0 DC
|
||||
* 1 PWM
|
||||
thermal_cruise[1-3] - Selects the desired temperature for cruise (degC)
|
||||
tolerance[1-3] - Value in degrees of Celsius (degC) for +- T
|
||||
sf2_point[1-4]_fan[1-3] - four temperature points for each fan for Smart Fan II
|
||||
sf2_level[1-3]_fan[1-3] - three PWM/DC levels for each fan for Smart Fan II
|
|
@ -4,22 +4,13 @@ Kernel driver max6875
|
|||
Supported chips:
|
||||
* Maxim MAX6874, MAX6875
|
||||
Prefix: 'max6875'
|
||||
Addresses scanned: 0x50, 0x52
|
||||
Addresses scanned: None (see below)
|
||||
Datasheet:
|
||||
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
|
||||
|
||||
Author: Ben Gardner <bgardner@wabtec.com>
|
||||
|
||||
|
||||
Module Parameters
|
||||
-----------------
|
||||
|
||||
* allow_write int
|
||||
Set to non-zero to enable write permission:
|
||||
*0: Read only
|
||||
1: Read and write
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
|
@ -33,34 +24,85 @@ registers.
|
|||
|
||||
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
|
||||
and outputs:
|
||||
|
||||
vin gpi vout
|
||||
MAX6874 6 4 8
|
||||
MAX6875 4 3 5
|
||||
|
||||
MAX6874 chips can have four different addresses (as opposed to only two for
|
||||
the MAX6875). The additional addresses (0x54 and 0x56) are not probed by
|
||||
this driver by default, but the probe module parameter can be used if
|
||||
needed.
|
||||
|
||||
See the datasheet for details on how to program the EEPROM.
|
||||
See the datasheet for more information.
|
||||
|
||||
|
||||
Sysfs entries
|
||||
-------------
|
||||
|
||||
eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
|
||||
allow_write was set and register 0x43 is 0.
|
||||
|
||||
eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
|
||||
loaded into register space until a power cycle or device reset.
|
||||
|
||||
reg_config - 70 bytes of register space. Any changes take affect immediately.
|
||||
eeprom - 512 bytes of user-defined EEPROM space.
|
||||
|
||||
|
||||
General Remarks
|
||||
---------------
|
||||
|
||||
A typical application will require that the EEPROMs be programmed once and
|
||||
never altered afterwards.
|
||||
Valid addresses for the MAX6875 are 0x50 and 0x52.
|
||||
Valid addresses for the MAX6874 are 0x50, 0x52, 0x54 and 0x56.
|
||||
The driver does not probe any address, so you must force the address.
|
||||
|
||||
Example:
|
||||
$ modprobe max6875 force=0,0x50
|
||||
|
||||
The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
|
||||
addresses. For example, for address 0x50, it also reserves 0x51.
|
||||
The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
|
||||
|
||||
|
||||
Programming the chip using i2c-dev
|
||||
----------------------------------
|
||||
|
||||
Use the i2c-dev interface to access and program the chips.
|
||||
Reads and writes are performed differently depending on the address range.
|
||||
|
||||
The configuration registers are at addresses 0x00 - 0x45.
|
||||
Use i2c_smbus_write_byte_data() to write a register and
|
||||
i2c_smbus_read_byte_data() to read a register.
|
||||
The command is the register number.
|
||||
|
||||
Examples:
|
||||
To write a 1 to register 0x45:
|
||||
i2c_smbus_write_byte_data(fd, 0x45, 1);
|
||||
|
||||
To read register 0x45:
|
||||
value = i2c_smbus_read_byte_data(fd, 0x45);
|
||||
|
||||
|
||||
The configuration EEPROM is at addresses 0x8000 - 0x8045.
|
||||
The user EEPROM is at addresses 0x8100 - 0x82ff.
|
||||
|
||||
Use i2c_smbus_write_word_data() to write a byte to EEPROM.
|
||||
|
||||
The command is the upper byte of the address: 0x80, 0x81, or 0x82.
|
||||
The data word is the lower part of the address or'd with data << 8.
|
||||
cmd = address >> 8;
|
||||
val = (address & 0xff) | (data << 8);
|
||||
|
||||
Example:
|
||||
To write 0x5a to address 0x8003:
|
||||
i2c_smbus_write_word_data(fd, 0x80, 0x5a03);
|
||||
|
||||
|
||||
Reading data from the EEPROM is a little more complicated.
|
||||
Use i2c_smbus_write_byte_data() to set the read address and then
|
||||
i2c_smbus_read_byte() or i2c_smbus_read_i2c_block_data() to read the data.
|
||||
|
||||
Example:
|
||||
To read data starting at offset 0x8100, first set the address:
|
||||
i2c_smbus_write_byte_data(fd, 0x81, 0x00);
|
||||
|
||||
And then read the data
|
||||
value = i2c_smbus_read_byte(fd);
|
||||
|
||||
or
|
||||
|
||||
count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
|
||||
|
||||
The block read should read 16 bytes.
|
||||
0x84 is the block read command.
|
||||
|
||||
See the datasheet for more details.
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ CHECKING THROUGH /DEV
|
|||
If you try to access an adapter from a userspace program, you will have
|
||||
to use the /dev interface. You will still have to check whether the
|
||||
functionality you need is supported, of course. This is done using
|
||||
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
|
||||
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
|
||||
program, is below:
|
||||
|
||||
int file;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Revision 4, 2004-03-30
|
||||
Revision 5, 2005-07-29
|
||||
Jean Delvare <khali@linux-fr.org>
|
||||
Greg KH <greg@kroah.com>
|
||||
|
||||
|
@ -17,20 +17,22 @@ yours for best results.
|
|||
|
||||
Technical changes:
|
||||
|
||||
* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
|
||||
<linux/i2c-sensor.h>. Includes typically look like that:
|
||||
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||
Includes typically look like that:
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-sensor.h>
|
||||
#include <linux/i2c-vid.h> /* if you need VRM support */
|
||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||
#include <asm/io.h> /* if you have I/O operations */
|
||||
Please respect this inclusion order. Some extra headers may be
|
||||
required for a given driver (e.g. "lm75.h").
|
||||
|
||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
|
||||
becomes I2C_CLIENT_ISA_END.
|
||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
|
||||
are no more handled by the i2c core.
|
||||
SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
|
||||
|
||||
* [Client data] Get rid of sysctl_id. Try using standard names for
|
||||
register values (for example, temp_os becomes temp_max). You're
|
||||
|
@ -66,13 +68,15 @@ Technical changes:
|
|||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
ISA-only drivers of course don't need this.
|
||||
Call i2c_probe() instead of i2c_detect().
|
||||
|
||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||
The type_name and client_name strings are replaced by a single
|
||||
name string, which will be filled with a lowercase, short string
|
||||
(typically the driver name, e.g. "lm75").
|
||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
||||
useless.
|
||||
useless. Same for isa-only drivers, as the test would always be
|
||||
true. Only hybrid drivers (which are quite rare) still need it.
|
||||
The errorN labels are reduced to the number needed. If that number
|
||||
is 2 (i2c-only drivers), it is advised that the labels are named
|
||||
exit and exit_free. For i2c+isa drivers, labels should be named
|
||||
|
@ -86,6 +90,8 @@ Technical changes:
|
|||
device_create_file. Move the driver initialization before any
|
||||
sysfs file creation.
|
||||
Drop client->id.
|
||||
Drop any 24RF08 corruption prevention you find, as this is now done
|
||||
at the i2c-core level, and doing it twice voids it.
|
||||
|
||||
* [Init] Limits must not be set by the driver (can be done later in
|
||||
user-space). Chip should not be reset default (although a module
|
||||
|
@ -93,7 +99,8 @@ Technical changes:
|
|||
limited to the strictly necessary steps.
|
||||
|
||||
* [Detach] Get rid of data, remove the call to
|
||||
i2c_deregister_entry.
|
||||
i2c_deregister_entry. Do not log an error message if
|
||||
i2c_detach_client fails, as i2c-core will now do it for you.
|
||||
|
||||
* [Update] Don't access client->data directly, use
|
||||
i2c_get_clientdata(client) instead.
|
||||
|
|
|
@ -148,15 +148,15 @@ are defined in i2c.h to help you support them, as well as a generic
|
|||
detection algorithm.
|
||||
|
||||
You do not have to use this parameter interface; but don't try to use
|
||||
function i2c_probe() (or i2c_detect()) if you don't.
|
||||
function i2c_probe() if you don't.
|
||||
|
||||
NOTE: If you want to write a `sensors' driver, the interface is slightly
|
||||
different! See below.
|
||||
|
||||
|
||||
|
||||
Probing classes (i2c)
|
||||
---------------------
|
||||
Probing classes
|
||||
---------------
|
||||
|
||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||
terminated by I2C_CLIENT_END.
|
||||
|
@ -171,12 +171,18 @@ The following lists are used internally:
|
|||
ignore: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the I2C address. These addresses are never probed.
|
||||
This parameter overrules 'normal' and 'probe', but not the 'force' lists.
|
||||
This parameter overrules the 'normal_i2c' list only.
|
||||
force: insmod parameter.
|
||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
||||
the second is the I2C address. A device is blindly assumed to be on
|
||||
the given address, no probing is done.
|
||||
|
||||
Additionally, kind-specific force lists may optionally be defined if
|
||||
the driver supports several chip kinds. They are grouped in a
|
||||
NULL-terminated list of pointers named forces, those first element if the
|
||||
generic force list mentioned above. Each additional list correspond to an
|
||||
insmod parameter of the form force_<kind>.
|
||||
|
||||
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||
parameter. The complete declaration could look like this:
|
||||
|
||||
|
@ -186,66 +192,17 @@ parameter. The complete declaration could look like this:
|
|||
|
||||
/* Magic definition of all other variables and things */
|
||||
I2C_CLIENT_INSMOD;
|
||||
/* Or, if your driver supports, say, 2 kind of devices: */
|
||||
I2C_CLIENT_INSMOD_2(foo, bar);
|
||||
|
||||
If you use the multi-kind form, an enum will be defined for you:
|
||||
enum chips { any_chip, foo, bar, ... }
|
||||
You can then (and certainly should) use it in the driver code.
|
||||
|
||||
Note that you *have* to call the defined variable `normal_i2c',
|
||||
without any prefix!
|
||||
|
||||
|
||||
Probing classes (sensors)
|
||||
-------------------------
|
||||
|
||||
If you write a `sensors' driver, you use a slightly different interface.
|
||||
As well as I2C addresses, we have to cope with ISA addresses. Also, we
|
||||
use a enum of chip types. Don't forget to include `sensors.h'.
|
||||
|
||||
The following lists are used internally. They are all lists of integers.
|
||||
|
||||
normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
|
||||
A list of I2C addresses which should normally be examined.
|
||||
normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
|
||||
A list of ISA addresses which should normally be examined.
|
||||
probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
|
||||
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
|
||||
the ISA bus, -1 for any I2C bus), the second is the address. These
|
||||
addresses are also probed, as if they were in the 'normal' list.
|
||||
ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
|
||||
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
|
||||
the ISA bus, -1 for any I2C bus), the second is the I2C address. These
|
||||
addresses are never probed. This parameter overrules 'normal' and
|
||||
'probe', but not the 'force' lists.
|
||||
|
||||
Also used is a list of pointers to sensors_force_data structures:
|
||||
force_data: insmod parameters. A list, ending with an element of which
|
||||
the force field is NULL.
|
||||
Each element contains the type of chip and a list of pairs.
|
||||
The first value is a bus number (SENSORS_ISA_BUS for the ISA bus,
|
||||
-1 for any I2C bus), the second is the address.
|
||||
These are automatically translated to insmod variables of the form
|
||||
force_foo.
|
||||
|
||||
So we have a generic insmod variabled `force', and chip-specific variables
|
||||
`force_CHIPNAME'.
|
||||
|
||||
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||
and `normal_isa' parameters, and define what chip names are used.
|
||||
The complete declaration could look like this:
|
||||
/* Scan i2c addresses 0x37, and 0x48 to 0x4f */
|
||||
static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
|
||||
0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
|
||||
/* Scan ISA address 0x290 */
|
||||
static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
|
||||
|
||||
/* Define chips foo and bar, as well as all module parameters and things */
|
||||
SENSORS_INSMOD_2(foo,bar);
|
||||
|
||||
If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
|
||||
you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
|
||||
bother with chip types, you can use SENSORS_INSMOD_0.
|
||||
|
||||
A enum is automatically defined as follows:
|
||||
enum chips { any_chip, chip1, chip2, ... }
|
||||
|
||||
|
||||
Attaching to an adapter
|
||||
-----------------------
|
||||
|
||||
|
@ -264,17 +221,10 @@ detected at a specific address, another callback is called.
|
|||
return i2c_probe(adapter,&addr_data,&foo_detect_client);
|
||||
}
|
||||
|
||||
For `sensors' drivers, use the i2c_detect function instead:
|
||||
|
||||
int foo_attach_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
return i2c_detect(adapter,&addr_data,&foo_detect_client);
|
||||
}
|
||||
|
||||
Remember, structure `addr_data' is defined by the macros explained above,
|
||||
so you do not have to define it yourself.
|
||||
|
||||
The i2c_probe or i2c_detect function will call the foo_detect_client
|
||||
The i2c_probe function will call the foo_detect_client
|
||||
function only for those i2c addresses that actually have a device on
|
||||
them (unless a `force' parameter was used). In addition, addresses that
|
||||
are already in use (by some other registered client) are skipped.
|
||||
|
@ -283,19 +233,18 @@ are already in use (by some other registered client) are skipped.
|
|||
The detect client function
|
||||
--------------------------
|
||||
|
||||
The detect client function is called by i2c_probe or i2c_detect.
|
||||
The `kind' parameter contains 0 if this call is due to a `force'
|
||||
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
|
||||
this call is due to the generic `force' parameter, and the chip type
|
||||
number if it is due to a specific `force' parameter).
|
||||
The detect client function is called by i2c_probe. The `kind' parameter
|
||||
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
||||
number for a forced detection with a chip type forced.
|
||||
|
||||
Below, some things are only needed if this is a `sensors' driver. Those
|
||||
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
||||
markers.
|
||||
|
||||
This function should only return an error (any value != 0) if there is
|
||||
some reason why no more detection should be done anymore. If the
|
||||
detection just fails for this address, return 0.
|
||||
Returning an error different from -ENODEV in a detect function will cause
|
||||
the detection to stop: other addresses and adapters won't be scanned.
|
||||
This should only be done on fatal or internal errors, such as a memory
|
||||
shortage or i2c_attach_client failing.
|
||||
|
||||
For now, you can ignore the `flags' parameter. It is there for future use.
|
||||
|
||||
|
@ -320,11 +269,10 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
|||
const char *type_name = "";
|
||||
int is_isa = i2c_is_isa_adapter(adapter);
|
||||
|
||||
if (is_isa) {
|
||||
/* Do this only if the chip can additionally be found on the ISA bus
|
||||
(hybrid chip). */
|
||||
|
||||
/* If this client can't be on the ISA bus at all, we can stop now
|
||||
(call `goto ERROR0'). But for kicks, we will assume it is all
|
||||
right. */
|
||||
if (is_isa) {
|
||||
|
||||
/* Discard immediately if this ISA range is already used */
|
||||
if (check_region(address,FOO_EXTENT))
|
||||
|
@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
|
|||
/* SENSORS ONLY END */
|
||||
|
||||
/* Try to detach the client from i2c space */
|
||||
if ((err = i2c_detach_client(client))) {
|
||||
printk("foo.o: Client deregistration failed, client not detached.\n");
|
||||
if ((err = i2c_detach_client(client)))
|
||||
return err;
|
||||
}
|
||||
|
||||
/* SENSORS ONLY START */
|
||||
/* HYBRID SENSORS CHIP ONLY START */
|
||||
if i2c_is_isa_client(client)
|
||||
release_region(client->addr,LM78_EXTENT);
|
||||
/* SENSORS ONLY END */
|
||||
/* HYBRID SENSORS CHIP ONLY END */
|
||||
|
||||
kfree(client); /* Frees client data too, if allocated at the same time */
|
||||
return 0;
|
||||
|
|
|
@ -872,7 +872,13 @@ When kbuild executes the following steps are followed (roughly):
|
|||
Assignments to $(targets) are without $(obj)/ prefix.
|
||||
if_changed may be used in conjunction with custom commands as
|
||||
defined in 6.7 "Custom kbuild commands".
|
||||
|
||||
Note: It is a typical mistake to forget the FORCE prerequisite.
|
||||
Another common pitfall is that whitespace is sometimes
|
||||
significant; for instance, the below will fail (note the extra space
|
||||
after the comma):
|
||||
target: source(s) FORCE
|
||||
#WRONG!# $(call if_changed, ld/objcopy/gzip)
|
||||
|
||||
ld
|
||||
Link target. Often LDFLAGS_$@ is used to set specific options to ld.
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
|
||||
===========================
|
||||
Intel(R) PRO/Wireless 2100 Network Connection Driver for Linux
|
||||
README.ipw2100
|
||||
|
||||
March 14, 2005
|
||||
|
||||
===========================
|
||||
Index
|
||||
---------------------------
|
||||
0. Introduction
|
||||
1. Release 1.1.0 Current Features
|
||||
2. Command Line Parameters
|
||||
3. Sysfs Helper Files
|
||||
4. Radio Kill Switch
|
||||
5. Dynamic Firmware
|
||||
6. Power Management
|
||||
7. Support
|
||||
8. License
|
||||
|
||||
|
||||
===========================
|
||||
0. Introduction
|
||||
------------ ----- ----- ---- --- -- -
|
||||
|
||||
This document provides a brief overview of the features supported by the
|
||||
IPW2100 driver project. The main project website, where the latest
|
||||
development version of the driver can be found, is:
|
||||
|
||||
http://ipw2100.sourceforge.net
|
||||
|
||||
There you can find the not only the latest releases, but also information about
|
||||
potential fixes and patches, as well as links to the development mailing list
|
||||
for the driver project.
|
||||
|
||||
|
||||
===========================
|
||||
1. Release 1.1.0 Current Supported Features
|
||||
---------------------------
|
||||
- Managed (BSS) and Ad-Hoc (IBSS)
|
||||
- WEP (shared key and open)
|
||||
- Wireless Tools support
|
||||
- 802.1x (tested with XSupplicant 1.0.1)
|
||||
|
||||
Enabled (but not supported) features:
|
||||
- Monitor/RFMon mode
|
||||
- WPA/WPA2
|
||||
|
||||
The distinction between officially supported and enabled is a reflection
|
||||
on the amount of validation and interoperability testing that has been
|
||||
performed on a given feature.
|
||||
|
||||
|
||||
===========================
|
||||
2. Command Line Parameters
|
||||
---------------------------
|
||||
|
||||
If the driver is built as a module, the following optional parameters are used
|
||||
by entering them on the command line with the modprobe command using this
|
||||
syntax:
|
||||
|
||||
modprobe ipw2100 [<option>=<VAL1><,VAL2>...]
|
||||
|
||||
For example, to disable the radio on driver loading, enter:
|
||||
|
||||
modprobe ipw2100 disable=1
|
||||
|
||||
The ipw2100 driver supports the following module parameters:
|
||||
|
||||
Name Value Example:
|
||||
debug 0x0-0xffffffff debug=1024
|
||||
mode 0,1,2 mode=1 /* AdHoc */
|
||||
channel int channel=3 /* Only valid in AdHoc or Monitor */
|
||||
associate boolean associate=0 /* Do NOT auto associate */
|
||||
disable boolean disable=1 /* Do not power the HW */
|
||||
|
||||
|
||||
===========================
|
||||
3. Sysfs Helper Files
|
||||
---------------------------
|
||||
|
||||
There are several ways to control the behavior of the driver. Many of the
|
||||
general capabilities are exposed through the Wireless Tools (iwconfig). There
|
||||
are a few capabilities that are exposed through entries in the Linux Sysfs.
|
||||
|
||||
|
||||
----- Driver Level ------
|
||||
For the driver level files, look in /sys/bus/pci/drivers/ipw2100/
|
||||
|
||||
debug_level
|
||||
|
||||
This controls the same global as the 'debug' module parameter. For
|
||||
information on the various debugging levels available, run the 'dvals'
|
||||
script found in the driver source directory.
|
||||
|
||||
NOTE: 'debug_level' is only enabled if CONFIG_IPW2100_DEBUG is turn
|
||||
on.
|
||||
|
||||
----- Device Level ------
|
||||
For the device level files look in
|
||||
|
||||
/sys/bus/pci/drivers/ipw2100/{PCI-ID}/
|
||||
|
||||
For example:
|
||||
/sys/bus/pci/drivers/ipw2100/0000:02:01.0
|
||||
|
||||
For the device level files, see /sys/bus/pci/drivers/ipw2100:
|
||||
|
||||
rf_kill
|
||||
read -
|
||||
0 = RF kill not enabled (radio on)
|
||||
1 = SW based RF kill active (radio off)
|
||||
2 = HW based RF kill active (radio off)
|
||||
3 = Both HW and SW RF kill active (radio off)
|
||||
write -
|
||||
0 = If SW based RF kill active, turn the radio back on
|
||||
1 = If radio is on, activate SW based RF kill
|
||||
|
||||
NOTE: If you enable the SW based RF kill and then toggle the HW
|
||||
based RF kill from ON -> OFF -> ON, the radio will NOT come back on
|
||||
|
||||
|
||||
===========================
|
||||
4. Radio Kill Switch
|
||||
---------------------------
|
||||
Most laptops provide the ability for the user to physically disable the radio.
|
||||
Some vendors have implemented this as a physical switch that requires no
|
||||
software to turn the radio off and on. On other laptops, however, the switch
|
||||
is controlled through a button being pressed and a software driver then making
|
||||
calls to turn the radio off and on. This is referred to as a "software based
|
||||
RF kill switch"
|
||||
|
||||
See the Sysfs helper file 'rf_kill' for determining the state of the RF switch
|
||||
on your system.
|
||||
|
||||
|
||||
===========================
|
||||
5. Dynamic Firmware
|
||||
---------------------------
|
||||
As the firmware is licensed under a restricted use license, it can not be
|
||||
included within the kernel sources. To enable the IPW2100 you will need a
|
||||
firmware image to load into the wireless NIC's processors.
|
||||
|
||||
You can obtain these images from <http://ipw2100.sf.net/firmware.php>.
|
||||
|
||||
See INSTALL for instructions on installing the firmware.
|
||||
|
||||
|
||||
===========================
|
||||
6. Power Management
|
||||
---------------------------
|
||||
The IPW2100 supports the configuration of the Power Save Protocol
|
||||
through a private wireless extension interface. The IPW2100 supports
|
||||
the following different modes:
|
||||
|
||||
off No power management. Radio is always on.
|
||||
on Automatic power management
|
||||
1-5 Different levels of power management. The higher the
|
||||
number the greater the power savings, but with an impact to
|
||||
packet latencies.
|
||||
|
||||
Power management works by powering down the radio after a certain
|
||||
interval of time has passed where no packets are passed through the
|
||||
radio. Once powered down, the radio remains in that state for a given
|
||||
period of time. For higher power savings, the interval between last
|
||||
packet processed to sleep is shorter and the sleep period is longer.
|
||||
|
||||
When the radio is asleep, the access point sending data to the station
|
||||
must buffer packets at the AP until the station wakes up and requests
|
||||
any buffered packets. If you have an AP that does not correctly support
|
||||
the PSP protocol you may experience packet loss or very poor performance
|
||||
while power management is enabled. If this is the case, you will need
|
||||
to try and find a firmware update for your AP, or disable power
|
||||
management (via `iwconfig eth1 power off`)
|
||||
|
||||
To configure the power level on the IPW2100 you use a combination of
|
||||
iwconfig and iwpriv. iwconfig is used to turn power management on, off,
|
||||
and set it to auto.
|
||||
|
||||
iwconfig eth1 power off Disables radio power down
|
||||
iwconfig eth1 power on Enables radio power management to
|
||||
last set level (defaults to AUTO)
|
||||
iwpriv eth1 set_power 0 Sets power level to AUTO and enables
|
||||
power management if not previously
|
||||
enabled.
|
||||
iwpriv eth1 set_power 1-5 Set the power level as specified,
|
||||
enabling power management if not
|
||||
previously enabled.
|
||||
|
||||
You can view the current power level setting via:
|
||||
|
||||
iwpriv eth1 get_power
|
||||
|
||||
It will return the current period or timeout that is configured as a string
|
||||
in the form of xxxx/yyyy (z) where xxxx is the timeout interval (amount of
|
||||
time after packet processing), yyyy is the period to sleep (amount of time to
|
||||
wait before powering the radio and querying the access point for buffered
|
||||
packets), and z is the 'power level'. If power management is turned off the
|
||||
xxxx/yyyy will be replaced with 'off' -- the level reported will be the active
|
||||
level if `iwconfig eth1 power on` is invoked.
|
||||
|
||||
|
||||
===========================
|
||||
7. Support
|
||||
---------------------------
|
||||
|
||||
For general development information and support,
|
||||
go to:
|
||||
|
||||
http://ipw2100.sf.net/
|
||||
|
||||
The ipw2100 1.1.0 driver and firmware can be downloaded from:
|
||||
|
||||
http://support.intel.com
|
||||
|
||||
For installation support on the ipw2100 1.1.0 driver on Linux kernels
|
||||
2.6.8 or greater, email support is available from:
|
||||
|
||||
http://supportmail.intel.com
|
||||
|
||||
===========================
|
||||
8. License
|
||||
---------------------------
|
||||
|
||||
Copyright(c) 2003 - 2005 Intel Corporation. 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 (version 2) as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in the
|
||||
file called LICENSE.
|
||||
|
||||
License Contact Information:
|
||||
James P. Ketrenos <ipw2100-admin@linux.intel.com>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
|
||||
Intel(R) PRO/Wireless 2915ABG Driver for Linux in support of:
|
||||
|
||||
Intel(R) PRO/Wireless 2200BG Network Connection
|
||||
Intel(R) PRO/Wireless 2915ABG Network Connection
|
||||
|
||||
Note: The Intel(R) PRO/Wireless 2915ABG Driver for Linux and Intel(R)
|
||||
PRO/Wireless 2200BG Driver for Linux is a unified driver that works on
|
||||
both hardware adapters listed above. In this document the Intel(R)
|
||||
PRO/Wireless 2915ABG Driver for Linux will be used to reference the
|
||||
unified driver.
|
||||
|
||||
Copyright (C) 2004-2005, Intel Corporation
|
||||
|
||||
README.ipw2200
|
||||
|
||||
Version: 1.0.0
|
||||
Date : January 31, 2005
|
||||
|
||||
|
||||
Index
|
||||
-----------------------------------------------
|
||||
1. Introduction
|
||||
1.1. Overview of features
|
||||
1.2. Module parameters
|
||||
1.3. Wireless Extension Private Methods
|
||||
1.4. Sysfs Helper Files
|
||||
2. About the Version Numbers
|
||||
3. Support
|
||||
4. License
|
||||
|
||||
|
||||
1. Introduction
|
||||
-----------------------------------------------
|
||||
The following sections attempt to provide a brief introduction to using
|
||||
the Intel(R) PRO/Wireless 2915ABG Driver for Linux.
|
||||
|
||||
This document is not meant to be a comprehensive manual on
|
||||
understanding or using wireless technologies, but should be sufficient
|
||||
to get you moving without wires on Linux.
|
||||
|
||||
For information on building and installing the driver, see the INSTALL
|
||||
file.
|
||||
|
||||
|
||||
1.1. Overview of Features
|
||||
-----------------------------------------------
|
||||
The current release (1.0.0) supports the following features:
|
||||
|
||||
+ BSS mode (Infrastructure, Managed)
|
||||
+ IBSS mode (Ad-Hoc)
|
||||
+ WEP (OPEN and SHARED KEY mode)
|
||||
+ 802.1x EAP via wpa_supplicant and xsupplicant
|
||||
+ Wireless Extension support
|
||||
+ Full B and G rate support (2200 and 2915)
|
||||
+ Full A rate support (2915 only)
|
||||
+ Transmit power control
|
||||
+ S state support (ACPI suspend/resume)
|
||||
+ long/short preamble support
|
||||
|
||||
|
||||
|
||||
1.2. Command Line Parameters
|
||||
-----------------------------------------------
|
||||
|
||||
Like many modules used in the Linux kernel, the Intel(R) PRO/Wireless
|
||||
2915ABG Driver for Linux allows certain configuration options to be
|
||||
provided as module parameters. The most common way to specify a module
|
||||
parameter is via the command line.
|
||||
|
||||
The general form is:
|
||||
|
||||
% modprobe ipw2200 parameter=value
|
||||
|
||||
Where the supported parameter are:
|
||||
|
||||
associate
|
||||
Set to 0 to disable the auto scan-and-associate functionality of the
|
||||
driver. If disabled, the driver will not attempt to scan
|
||||
for and associate to a network until it has been configured with
|
||||
one or more properties for the target network, for example configuring
|
||||
the network SSID. Default is 1 (auto-associate)
|
||||
|
||||
Example: % modprobe ipw2200 associate=0
|
||||
|
||||
auto_create
|
||||
Set to 0 to disable the auto creation of an Ad-Hoc network
|
||||
matching the channel and network name parameters provided.
|
||||
Default is 1.
|
||||
|
||||
channel
|
||||
channel number for association. The normal method for setting
|
||||
the channel would be to use the standard wireless tools
|
||||
(i.e. `iwconfig eth1 channel 10`), but it is useful sometimes
|
||||
to set this while debugging. Channel 0 means 'ANY'
|
||||
|
||||
debug
|
||||
If using a debug build, this is used to control the amount of debug
|
||||
info is logged. See the 'dval' and 'load' script for more info on
|
||||
how to use this (the dval and load scripts are provided as part
|
||||
of the ipw2200 development snapshot releases available from the
|
||||
SourceForge project at http://ipw2200.sf.net)
|
||||
|
||||
mode
|
||||
Can be used to set the default mode of the adapter.
|
||||
0 = Managed, 1 = Ad-Hoc
|
||||
|
||||
|
||||
1.3. Wireless Extension Private Methods
|
||||
-----------------------------------------------
|
||||
|
||||
As an interface designed to handle generic hardware, there are certain
|
||||
capabilities not exposed through the normal Wireless Tool interface. As
|
||||
such, a provision is provided for a driver to declare custom, or
|
||||
private, methods. The Intel(R) PRO/Wireless 2915ABG Driver for Linux
|
||||
defines several of these to configure various settings.
|
||||
|
||||
The general form of using the private wireless methods is:
|
||||
|
||||
% iwpriv $IFNAME method parameters
|
||||
|
||||
Where $IFNAME is the interface name the device is registered with
|
||||
(typically eth1, customized via one of the various network interface
|
||||
name managers, such as ifrename)
|
||||
|
||||
The supported private methods are:
|
||||
|
||||
get_mode
|
||||
Can be used to report out which IEEE mode the driver is
|
||||
configured to support. Example:
|
||||
|
||||
% iwpriv eth1 get_mode
|
||||
eth1 get_mode:802.11bg (6)
|
||||
|
||||
set_mode
|
||||
Can be used to configure which IEEE mode the driver will
|
||||
support.
|
||||
|
||||
Usage:
|
||||
% iwpriv eth1 set_mode {mode}
|
||||
Where {mode} is a number in the range 1-7:
|
||||
1 802.11a (2915 only)
|
||||
2 802.11b
|
||||
3 802.11ab (2915 only)
|
||||
4 802.11g
|
||||
5 802.11ag (2915 only)
|
||||
6 802.11bg
|
||||
7 802.11abg (2915 only)
|
||||
|
||||
get_preamble
|
||||
Can be used to report configuration of preamble length.
|
||||
|
||||
set_preamble
|
||||
Can be used to set the configuration of preamble length:
|
||||
|
||||
Usage:
|
||||
% iwpriv eth1 set_preamble {mode}
|
||||
Where {mode} is one of:
|
||||
1 Long preamble only
|
||||
0 Auto (long or short based on connection)
|
||||
|
||||
|
||||
1.4. Sysfs Helper Files:
|
||||
-----------------------------------------------
|
||||
|
||||
The Linux kernel provides a pseudo file system that can be used to
|
||||
access various components of the operating system. The Intel(R)
|
||||
PRO/Wireless 2915ABG Driver for Linux exposes several configuration
|
||||
parameters through this mechanism.
|
||||
|
||||
An entry in the sysfs can support reading and/or writing. You can
|
||||
typically query the contents of a sysfs entry through the use of cat,
|
||||
and can set the contents via echo. For example:
|
||||
|
||||
% cat /sys/bus/pci/drivers/ipw2200/debug_level
|
||||
|
||||
Will report the current debug level of the driver's logging subsystem
|
||||
(only available if CONFIG_IPW_DEBUG was configured when the driver was
|
||||
built).
|
||||
|
||||
You can set the debug level via:
|
||||
|
||||
% echo $VALUE > /sys/bus/pci/drivers/ipw2200/debug_level
|
||||
|
||||
Where $VALUE would be a number in the case of this sysfs entry. The
|
||||
input to sysfs files does not have to be a number. For example, the
|
||||
firmware loader used by hotplug utilizes sysfs entries for transferring
|
||||
the firmware image from user space into the driver.
|
||||
|
||||
The Intel(R) PRO/Wireless 2915ABG Driver for Linux exposes sysfs entries
|
||||
at two levels -- driver level, which apply to all instances of the
|
||||
driver (in the event that there are more than one device installed) and
|
||||
device level, which applies only to the single specific instance.
|
||||
|
||||
|
||||
1.4.1 Driver Level Sysfs Helper Files
|
||||
-----------------------------------------------
|
||||
|
||||
For the driver level files, look in /sys/bus/pci/drivers/ipw2200/
|
||||
|
||||
debug_level
|
||||
|
||||
This controls the same global as the 'debug' module parameter
|
||||
|
||||
|
||||
1.4.2 Device Level Sysfs Helper Files
|
||||
-----------------------------------------------
|
||||
|
||||
For the device level files, look in
|
||||
|
||||
/sys/bus/pci/drivers/ipw2200/{PCI-ID}/
|
||||
|
||||
For example:
|
||||
/sys/bus/pci/drivers/ipw2200/0000:02:01.0
|
||||
|
||||
For the device level files, see /sys/bus/pci/[drivers/ipw2200:
|
||||
|
||||
rf_kill
|
||||
read -
|
||||
0 = RF kill not enabled (radio on)
|
||||
1 = SW based RF kill active (radio off)
|
||||
2 = HW based RF kill active (radio off)
|
||||
3 = Both HW and SW RF kill active (radio off)
|
||||
write -
|
||||
0 = If SW based RF kill active, turn the radio back on
|
||||
1 = If radio is on, activate SW based RF kill
|
||||
|
||||
NOTE: If you enable the SW based RF kill and then toggle the HW
|
||||
based RF kill from ON -> OFF -> ON, the radio will NOT come back on
|
||||
|
||||
ucode
|
||||
read-only access to the ucode version number
|
||||
|
||||
|
||||
2. About the Version Numbers
|
||||
-----------------------------------------------
|
||||
|
||||
Due to the nature of open source development projects, there are
|
||||
frequently changes being incorporated that have not gone through
|
||||
a complete validation process. These changes are incorporated into
|
||||
development snapshot releases.
|
||||
|
||||
Releases are numbered with a three level scheme:
|
||||
|
||||
major.minor.development
|
||||
|
||||
Any version where the 'development' portion is 0 (for example
|
||||
1.0.0, 1.1.0, etc.) indicates a stable version that will be made
|
||||
available for kernel inclusion.
|
||||
|
||||
Any version where the 'development' portion is not a 0 (for
|
||||
example 1.0.1, 1.1.5, etc.) indicates a development version that is
|
||||
being made available for testing and cutting edge users. The stability
|
||||
and functionality of the development releases are not know. We make
|
||||
efforts to try and keep all snapshots reasonably stable, but due to the
|
||||
frequency of their release, and the desire to get those releases
|
||||
available as quickly as possible, unknown anomalies should be expected.
|
||||
|
||||
The major version number will be incremented when significant changes
|
||||
are made to the driver. Currently, there are no major changes planned.
|
||||
|
||||
|
||||
3. Support
|
||||
-----------------------------------------------
|
||||
|
||||
For installation support of the 1.0.0 version, you can contact
|
||||
http://supportmail.intel.com, or you can use the open source project
|
||||
support.
|
||||
|
||||
For general information and support, go to:
|
||||
|
||||
http://ipw2200.sf.net/
|
||||
|
||||
|
||||
4. License
|
||||
-----------------------------------------------
|
||||
|
||||
Copyright(c) 2003 - 2005 Intel Corporation. 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 version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
The full GNU General Public License is included in this distribution in the
|
||||
file called LICENSE.
|
||||
|
||||
Contact Information:
|
||||
James P. Ketrenos <ipw2100-admin@linux.intel.com>
|
||||
Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
Author: Andreas Steinmetz <ast@domdv.de>
|
||||
|
||||
|
||||
How to use dm-crypt and swsusp together:
|
||||
========================================
|
||||
|
||||
Some prerequisites:
|
||||
You know how dm-crypt works. If not, visit the following web page:
|
||||
http://www.saout.de/misc/dm-crypt/
|
||||
You have read Documentation/power/swsusp.txt and understand it.
|
||||
You did read Documentation/initrd.txt and know how an initrd works.
|
||||
You know how to create or how to modify an initrd.
|
||||
|
||||
Now your system is properly set up, your disk is encrypted except for
|
||||
the swap device(s) and the boot partition which may contain a mini
|
||||
system for crypto setup and/or rescue purposes. You may even have
|
||||
an initrd that does your current crypto setup already.
|
||||
|
||||
At this point you want to encrypt your swap, too. Still you want to
|
||||
be able to suspend using swsusp. This, however, means that you
|
||||
have to be able to either enter a passphrase or that you read
|
||||
the key(s) from an external device like a pcmcia flash disk
|
||||
or an usb stick prior to resume. So you need an initrd, that sets
|
||||
up dm-crypt and then asks swsusp to resume from the encrypted
|
||||
swap device.
|
||||
|
||||
The most important thing is that you set up dm-crypt in such
|
||||
a way that the swap device you suspend to/resume from has
|
||||
always the same major/minor within the initrd as well as
|
||||
within your running system. The easiest way to achieve this is
|
||||
to always set up this swap device first with dmsetup, so that
|
||||
it will always look like the following:
|
||||
|
||||
brw------- 1 root root 254, 0 Jul 28 13:37 /dev/mapper/swap0
|
||||
|
||||
Now set up your kernel to use /dev/mapper/swap0 as the default
|
||||
resume partition, so your kernel .config contains:
|
||||
|
||||
CONFIG_PM_STD_PARTITION="/dev/mapper/swap0"
|
||||
|
||||
Prepare your boot loader to use the initrd you will create or
|
||||
modify. For lilo the simplest setup looks like the following
|
||||
lines:
|
||||
|
||||
image=/boot/vmlinuz
|
||||
initrd=/boot/initrd.gz
|
||||
label=linux
|
||||
append="root=/dev/ram0 init=/linuxrc rw"
|
||||
|
||||
Finally you need to create or modify your initrd. Lets assume
|
||||
you create an initrd that reads the required dm-crypt setup
|
||||
from a pcmcia flash disk card. The card is formatted with an ext2
|
||||
fs which resides on /dev/hde1 when the card is inserted. The
|
||||
card contains at least the encrypted swap setup in a file
|
||||
named "swapkey". /etc/fstab of your initrd contains something
|
||||
like the following:
|
||||
|
||||
/dev/hda1 /mnt ext3 ro 0 0
|
||||
none /proc proc defaults,noatime,nodiratime 0 0
|
||||
none /sys sysfs defaults,noatime,nodiratime 0 0
|
||||
|
||||
/dev/hda1 contains an unencrypted mini system that sets up all
|
||||
of your crypto devices, again by reading the setup from the
|
||||
pcmcia flash disk. What follows now is a /linuxrc for your
|
||||
initrd that allows you to resume from encrypted swap and that
|
||||
continues boot with your mini system on /dev/hda1 if resume
|
||||
does not happen:
|
||||
|
||||
#!/bin/sh
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
mount /proc
|
||||
mount /sys
|
||||
mapped=0
|
||||
noresume=`grep -c noresume /proc/cmdline`
|
||||
if [ "$*" != "" ]
|
||||
then
|
||||
noresume=1
|
||||
fi
|
||||
dmesg -n 1
|
||||
/sbin/cardmgr -q
|
||||
for i in 1 2 3 4 5 6 7 8 9 0
|
||||
do
|
||||
if [ -f /proc/ide/hde/media ]
|
||||
then
|
||||
usleep 500000
|
||||
mount -t ext2 -o ro /dev/hde1 /mnt
|
||||
if [ -f /mnt/swapkey ]
|
||||
then
|
||||
dmsetup create swap0 /mnt/swapkey > /dev/null 2>&1 && mapped=1
|
||||
fi
|
||||
umount /mnt
|
||||
break
|
||||
fi
|
||||
usleep 500000
|
||||
done
|
||||
killproc /sbin/cardmgr
|
||||
dmesg -n 6
|
||||
if [ $mapped = 1 ]
|
||||
then
|
||||
if [ $noresume != 0 ]
|
||||
then
|
||||
mkswap /dev/mapper/swap0 > /dev/null 2>&1
|
||||
fi
|
||||
echo 254:0 > /sys/power/resume
|
||||
dmsetup remove swap0
|
||||
fi
|
||||
umount /sys
|
||||
mount /mnt
|
||||
umount /proc
|
||||
cd /mnt
|
||||
pivot_root . mnt
|
||||
mount /proc
|
||||
umount -l /mnt
|
||||
umount /proc
|
||||
exec chroot . /sbin/init $* < dev/console > dev/console 2>&1
|
||||
|
||||
Please don't mind the weird loop above, busybox's msh doesn't know
|
||||
the let statement. Now, what is happening in the script?
|
||||
First we have to decide if we want to try to resume, or not.
|
||||
We will not resume if booting with "noresume" or any parameters
|
||||
for init like "single" or "emergency" as boot parameters.
|
||||
|
||||
Then we need to set up dmcrypt with the setup data from the
|
||||
pcmcia flash disk. If this succeeds we need to reset the swap
|
||||
device if we don't want to resume. The line "echo 254:0 > /sys/power/resume"
|
||||
then attempts to resume from the first device mapper device.
|
||||
Note that it is important to set the device in /sys/power/resume,
|
||||
regardless if resuming or not, otherwise later suspend will fail.
|
||||
If resume starts, script execution terminates here.
|
||||
|
||||
Otherwise we just remove the encrypted swap device and leave it to the
|
||||
mini system on /dev/hda1 to set the whole crypto up (it is up to
|
||||
you to modify this to your taste).
|
||||
|
||||
What then follows is the well known process to change the root
|
||||
file system and continue booting from there. I prefer to unmount
|
||||
the initrd prior to continue booting but it is up to you to modify
|
||||
this.
|
|
@ -311,3 +311,10 @@ As a rule of thumb use encrypted swap to protect your data while your
|
|||
system is shut down or suspended. Additionally use the encrypted
|
||||
suspend image to prevent sensitive data from being stolen after
|
||||
resume.
|
||||
|
||||
Q: Why we cannot suspend to a swap file?
|
||||
|
||||
A: Because accessing swap file needs the filesystem mounted, and
|
||||
filesystem might do something wrong (like replaying the journal)
|
||||
during mount. [Probably could be solved by modifying every filesystem
|
||||
to support some kind of "really read-only!" option. Patches welcome.]
|
||||
|
|
|
@ -46,6 +46,12 @@ There are a few types of systems where video works after S3 resume:
|
|||
POSTing bios works. Ole Rohne has patch to do just that at
|
||||
http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
|
||||
|
||||
(8) on some systems, you can use the video_post utility mentioned here:
|
||||
http://bugzilla.kernel.org/show_bug.cgi?id=3670. Do echo 3 > /sys/power/state
|
||||
&& /usr/sbin/video_post - which will initialize the display in console mode.
|
||||
If you are in X, you can switch to a virtual terminal and back to X using
|
||||
CTRL+ALT+F1 - CTRL+ALT+F7 to get the display working in graphical mode again.
|
||||
|
||||
Now, if you pass acpi_sleep=something, and it does not work with your
|
||||
bios, you'll get a hard crash during resume. Be careful. Also it is
|
||||
safest to do your experiments with plain old VGA console. The vesafb
|
||||
|
@ -64,7 +70,8 @@ Model hack (or "how to do it")
|
|||
------------------------------------------------------------------------------
|
||||
Acer Aspire 1406LC ole's late BIOS init (7), turn off DRI
|
||||
Acer TM 242FX vbetool (6)
|
||||
Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6)
|
||||
Acer TM C110 video_post (8)
|
||||
Acer TM C300 vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8)
|
||||
Acer TM 4052LCi s3_bios (2)
|
||||
Acer TM 636Lci s3_bios vga=normal (2)
|
||||
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
|
||||
|
|
|
@ -111,24 +111,17 @@ hardware.
|
|||
Interrupts: locally disabled.
|
||||
This call must not sleep
|
||||
|
||||
stop_tx(port,tty_stop)
|
||||
stop_tx(port)
|
||||
Stop transmitting characters. This might be due to the CTS
|
||||
line becoming inactive or the tty layer indicating we want
|
||||
to stop transmission.
|
||||
|
||||
tty_stop: 1 if this call is due to the TTY layer issuing a
|
||||
TTY stop to the driver (equiv to rs_stop).
|
||||
to stop transmission due to an XOFF character.
|
||||
|
||||
Locking: port->lock taken.
|
||||
Interrupts: locally disabled.
|
||||
This call must not sleep
|
||||
|
||||
start_tx(port,tty_start)
|
||||
start transmitting characters. (incidentally, nonempty will
|
||||
always be nonzero, and shouldn't be used - it will be dropped).
|
||||
|
||||
tty_start: 1 if this call was due to the TTY layer issuing
|
||||
a TTY start to the driver (equiv to rs_start)
|
||||
start_tx(port)
|
||||
start transmitting characters.
|
||||
|
||||
Locking: port->lock taken.
|
||||
Interrupts: locally disabled.
|
||||
|
|
|
@ -83,19 +83,18 @@ single address space optimization, so that the zap_page_range (from
|
|||
vmtruncate) does not lose sending ipi's to cloned threads that might
|
||||
be spawned underneath it and go to user mode to drag in pte's into tlbs.
|
||||
|
||||
swap_list_lock/swap_device_lock
|
||||
-------------------------------
|
||||
swap_lock
|
||||
--------------
|
||||
The swap devices are chained in priority order from the "swap_list" header.
|
||||
The "swap_list" is used for the round-robin swaphandle allocation strategy.
|
||||
The #free swaphandles is maintained in "nr_swap_pages". These two together
|
||||
are protected by the swap_list_lock.
|
||||
are protected by the swap_lock.
|
||||
|
||||
The swap_device_lock, which is per swap device, protects the reference
|
||||
counts on the corresponding swaphandles, maintained in the "swap_map"
|
||||
array, and the "highest_bit" and "lowest_bit" fields.
|
||||
The swap_lock also protects all the device reference counts on the
|
||||
corresponding swaphandles, maintained in the "swap_map" array, and the
|
||||
"highest_bit" and "lowest_bit" fields.
|
||||
|
||||
Both of these are spinlocks, and are never acquired from intr level. The
|
||||
locking hierarchy is swap_list_lock -> swap_device_lock.
|
||||
The swap_lock is a spinlock, and is never acquired from intr level.
|
||||
|
||||
To prevent races between swap space deletion or async readahead swapins
|
||||
deciding whether a swap handle is being used, ie worthy of being read in
|
||||
|
|
|
@ -228,6 +228,26 @@ advantechwdt.c -- Advantech Single Board Computer
|
|||
The GETSTATUS call returns if the device is open or not.
|
||||
[FIXME -- silliness again?]
|
||||
|
||||
booke_wdt.c -- PowerPC BookE Watchdog Timer
|
||||
|
||||
Timeout default varies according to frequency, supports
|
||||
SETTIMEOUT
|
||||
|
||||
Watchdog can not be turned off, CONFIG_WATCHDOG_NOWAYOUT
|
||||
does not make sense
|
||||
|
||||
GETSUPPORT returns the watchdog_info struct, and
|
||||
GETSTATUS returns the supported options. GETBOOTSTATUS
|
||||
returns a 1 if the last reset was caused by the
|
||||
watchdog and a 0 otherwise. This watchdog can not be
|
||||
disabled once it has been started. The wdt_period kernel
|
||||
parameter selects which bit of the time base changing
|
||||
from 0->1 will trigger the watchdog exception. Changing
|
||||
the timeout from the ioctl calls will change the
|
||||
wdt_period as defined above. Finally if you would like to
|
||||
replace the default Watchdog Handler you can implement the
|
||||
WatchdogHandler() function in your own code.
|
||||
|
||||
eurotechwdt.c -- Eurotech CPU-1220/1410
|
||||
|
||||
The timeout can be set using the SETTIMEOUT ioctl and defaults
|
||||
|
|
21
MAINTAINERS
21
MAINTAINERS
|
@ -933,6 +933,13 @@ M: khc@pm.waw.pl
|
|||
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
|
||||
S: Maintained
|
||||
|
||||
HARDWARE MONITORING
|
||||
P: Jean Delvare
|
||||
M: khali@linux-fr.org
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.nu/
|
||||
S: Maintained
|
||||
|
||||
HARMONY SOUND DRIVER
|
||||
P: Kyle McMartin
|
||||
M: kyle@parisc-linux.org
|
||||
|
@ -991,6 +998,13 @@ M: mike.miller@hp.com
|
|||
L: iss_storagedev@hp.com
|
||||
S: Supported
|
||||
|
||||
HOST AP DRIVER
|
||||
P: Jouni Malinen
|
||||
M: jkmaline@cc.hut.fi
|
||||
L: hostap@shmoo.com
|
||||
W: http://hostap.epitest.fi/
|
||||
S: Maintained
|
||||
|
||||
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
|
||||
P: Jaroslav Kysela
|
||||
M: perex@suse.cz
|
||||
|
@ -1007,7 +1021,7 @@ P: William Irwin
|
|||
M: wli@holomorphy.com
|
||||
S: Maintained
|
||||
|
||||
I2C AND SENSORS DRIVERS
|
||||
I2C SUBSYSTEM
|
||||
P: Greg Kroah-Hartman
|
||||
M: greg@kroah.com
|
||||
P: Jean Delvare
|
||||
|
@ -2643,11 +2657,6 @@ S: Maintained
|
|||
UCLINUX (AND M68KNOMMU)
|
||||
P: Greg Ungerer
|
||||
M: gerg@uclinux.org
|
||||
M: gerg@snapgear.com
|
||||
P: David McCullough
|
||||
M: davidm@snapgear.com
|
||||
P: D. Jeff Dionne (created first uClinux port)
|
||||
M: jeff@uclinux.org
|
||||
W: http://www.uclinux.org/
|
||||
L: uclinux-dev@uclinux.org (subscribers-only)
|
||||
S: Maintained
|
||||
|
|
164
Makefile
164
Makefile
|
@ -109,10 +109,9 @@ $(if $(KBUILD_OUTPUT),, \
|
|||
.PHONY: $(MAKECMDGOALS)
|
||||
|
||||
$(filter-out _all,$(MAKECMDGOALS)) _all:
|
||||
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
||||
KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
|
||||
KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)" \
|
||||
-f $(CURDIR)/Makefile $@
|
||||
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
||||
KBUILD_SRC=$(CURDIR) \
|
||||
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
|
||||
|
||||
# Leave processing to above invocation of make
|
||||
skip-makefile := 1
|
||||
|
@ -233,7 +232,7 @@ ifeq ($(MAKECMDGOALS),)
|
|||
KBUILD_MODULES := 1
|
||||
endif
|
||||
|
||||
export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
|
||||
export KBUILD_MODULES KBUILD_BUILTIN
|
||||
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
|
||||
|
||||
# Beautify output
|
||||
|
@ -309,6 +308,9 @@ cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
|
|||
# Look for make include files relative to root of kernel src
|
||||
MAKEFLAGS += --include-dir=$(srctree)
|
||||
|
||||
# We need some generic definitions
|
||||
include $(srctree)/scripts/Kbuild.include
|
||||
|
||||
# For maximum performance (+ possibly random breakage, uncomment
|
||||
# the following)
|
||||
|
||||
|
@ -348,7 +350,7 @@ LINUXINCLUDE := -Iinclude \
|
|||
|
||||
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||
|
||||
CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \
|
||||
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||
-fno-strict-aliasing -fno-common \
|
||||
-ffreestanding
|
||||
AFLAGS := -D__ASSEMBLY__
|
||||
|
@ -367,15 +369,10 @@ export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
|||
# even be read-only.
|
||||
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
|
||||
|
||||
# The temporary file to save gcc -MD generated dependencies must not
|
||||
# contain a comma
|
||||
comma := ,
|
||||
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
|
||||
|
||||
# Files to ignore in find ... statements
|
||||
|
||||
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc \) -prune -o
|
||||
RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc
|
||||
RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg \) -prune -o
|
||||
RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
|
||||
|
||||
# ===========================================================================
|
||||
# Rules shared between *config targets and build targets
|
||||
|
@ -551,6 +548,26 @@ export KBUILD_IMAGE ?= vmlinux
|
|||
# images. Default is /boot, but you can set it to other values
|
||||
export INSTALL_PATH ?= /boot
|
||||
|
||||
# If CONFIG_LOCALVERSION_AUTO is set, we automatically perform some tests
|
||||
# and try to determine if the current source tree is a release tree, of any sort,
|
||||
# or if is a pure development tree.
|
||||
#
|
||||
# A 'release tree' is any tree with a git TAG associated
|
||||
# with it. The primary goal of this is to make it safe for a native
|
||||
# git/CVS/SVN user to build a release tree (i.e, 2.6.9) and also to
|
||||
# continue developing against the current Linus tree, without having the Linus
|
||||
# tree overwrite the 2.6.9 tree when installed.
|
||||
#
|
||||
# Currently, only git is supported.
|
||||
# Other SCMs can edit scripts/setlocalversion and add the appropriate
|
||||
# checks as needed.
|
||||
|
||||
|
||||
ifdef CONFIG_LOCALVERSION_AUTO
|
||||
localversion-auto := $(shell $(PERL) $(srctree)/scripts/setlocalversion $(srctree))
|
||||
LOCALVERSION := $(LOCALVERSION)$(localversion-auto)
|
||||
endif
|
||||
|
||||
#
|
||||
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
|
||||
# relocations required by build roots. This is not defined in the
|
||||
|
@ -691,8 +708,10 @@ endef
|
|||
|
||||
# Update vmlinux version before link
|
||||
# Use + in front of this rule to silent warning about make -j1
|
||||
# First command is ':' to allow us to use + in front of this rule
|
||||
cmd_ksym_ld = $(cmd_vmlinux__)
|
||||
define rule_ksym_ld
|
||||
:
|
||||
+$(call cmd,vmlinux_version)
|
||||
$(call cmd,vmlinux__)
|
||||
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
|
||||
|
@ -722,6 +741,16 @@ quiet_cmd_kallsyms = KSYM $@
|
|||
# Needs to visit scripts/ before $(KALLSYMS) can be used.
|
||||
$(KALLSYMS): scripts ;
|
||||
|
||||
# Generate some data for debugging strange kallsyms problems
|
||||
debug_kallsyms: .tmp_map$(last_kallsyms)
|
||||
|
||||
.tmp_map%: .tmp_vmlinux% FORCE
|
||||
($(OBJDUMP) -h $< | $(AWK) '/^ +[0-9]/{print $$4 " 0 " $$2}'; $(NM) $<) | sort > $@
|
||||
|
||||
.tmp_map3: .tmp_map2
|
||||
|
||||
.tmp_map2: .tmp_map1
|
||||
|
||||
endif # ifdef CONFIG_KALLSYMS
|
||||
|
||||
# vmlinux image - including updated kernel symbols
|
||||
|
@ -757,7 +786,7 @@ $(vmlinux-dirs): prepare-all scripts
|
|||
prepare2:
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
@echo ' Using $(srctree) as source for kernel'
|
||||
$(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \
|
||||
$(Q)if [ -f $(srctree)/.config ]; then \
|
||||
echo " $(srctree) is not clean, please run 'make mrproper'";\
|
||||
echo " in the '$(srctree)' directory.";\
|
||||
/bin/false; \
|
||||
|
@ -769,7 +798,8 @@ endif
|
|||
# prepare1 creates a makefile if using a separate output directory
|
||||
prepare1: prepare2 outputmakefile
|
||||
|
||||
prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
|
||||
prepare0: prepare1 include/linux/version.h include/asm \
|
||||
include/config/MARKER
|
||||
ifneq ($(KBUILD_MODULES),)
|
||||
$(Q)rm -rf $(MODVERDIR)
|
||||
$(Q)mkdir -p $(MODVERDIR)
|
||||
|
@ -875,7 +905,7 @@ modules_install: _modinst_ _modinst_post
|
|||
|
||||
.PHONY: _modinst_
|
||||
_modinst_:
|
||||
@if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \
|
||||
@if [ -z "`$(DEPMOD) -V 2>/dev/null | grep module-init-tools`" ]; then \
|
||||
echo "Warning: you may need to install module-init-tools"; \
|
||||
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
|
||||
sleep 1; \
|
||||
|
@ -1159,37 +1189,49 @@ else
|
|||
__srctree = $(srctree)/
|
||||
endif
|
||||
|
||||
ALLSOURCE_ARCHS := $(ARCH)
|
||||
|
||||
define all-sources
|
||||
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
||||
\( -name include -o -name arch \) -prune -o \
|
||||
-name '*.[chS]' -print; \
|
||||
find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
done ; \
|
||||
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
||||
\( -name config -o -name 'asm-*' \) -prune \
|
||||
-o -name '*.[chS]' -print; \
|
||||
find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print; \
|
||||
done ; \
|
||||
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
||||
-name '*.[chS]' -print )
|
||||
endef
|
||||
|
||||
quiet_cmd_cscope-file = FILELST cscope.files
|
||||
cmd_cscope-file = $(all-sources) > cscope.files
|
||||
cmd_cscope-file = (echo \-k; echo \-q; $(all-sources)) > cscope.files
|
||||
|
||||
quiet_cmd_cscope = MAKE cscope.out
|
||||
cmd_cscope = cscope -k -b -q
|
||||
cmd_cscope = cscope -b
|
||||
|
||||
cscope: FORCE
|
||||
$(call cmd,cscope-file)
|
||||
$(call cmd,cscope)
|
||||
|
||||
quiet_cmd_TAGS = MAKE $@
|
||||
cmd_TAGS = $(all-sources) | etags -
|
||||
define cmd_TAGS
|
||||
rm -f $@; \
|
||||
ETAGSF=`etags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
|
||||
$(all-sources) | xargs etags $$ETAGSF -a
|
||||
endef
|
||||
|
||||
TAGS: FORCE
|
||||
$(call cmd,TAGS)
|
||||
|
||||
# Exuberant ctags works better with -I
|
||||
|
||||
quiet_cmd_tags = MAKE $@
|
||||
define cmd_tags
|
||||
|
@ -1198,9 +1240,6 @@ define cmd_tags
|
|||
$(all-sources) | xargs ctags $$CTAGSF -a
|
||||
endef
|
||||
|
||||
TAGS: FORCE
|
||||
$(call cmd,TAGS)
|
||||
|
||||
tags: FORCE
|
||||
$(call cmd,tags)
|
||||
|
||||
|
@ -1268,82 +1307,11 @@ ifneq ($(cmd_files),)
|
|||
include $(cmd_files)
|
||||
endif
|
||||
|
||||
# Execute command and generate cmd file
|
||||
if_changed = $(if $(strip $? \
|
||||
$(filter-out $(cmd_$(1)),$(cmd_$@))\
|
||||
$(filter-out $(cmd_$@),$(cmd_$(1)))),\
|
||||
@set -e; \
|
||||
$(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
|
||||
$(cmd_$(1)); \
|
||||
echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
|
||||
|
||||
|
||||
# execute the command and also postprocess generated .d dependencies
|
||||
# file
|
||||
if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
|
||||
$(filter-out $(cmd_$(1)),$(cmd_$@))\
|
||||
$(filter-out $(cmd_$@),$(cmd_$(1)))),\
|
||||
$(Q)set -e; \
|
||||
$(if $($(quiet)cmd_$(1)),echo ' $(subst ','\'',$($(quiet)cmd_$(1)))';) \
|
||||
$(cmd_$(1)); \
|
||||
scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
|
||||
rm -f $(depfile); \
|
||||
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
|
||||
|
||||
# Usage: $(call if_changed_rule,foo)
|
||||
# will check if $(cmd_foo) changed, or any of the prequisites changed,
|
||||
# and if so will execute $(rule_foo)
|
||||
|
||||
if_changed_rule = $(if $(strip $? \
|
||||
$(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
|
||||
$(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
|
||||
$(Q)$(rule_$(1)))
|
||||
|
||||
# If quiet is set, only print short version of command
|
||||
|
||||
cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
|
||||
|
||||
# filechk is used to check if the content of a generated file is updated.
|
||||
# Sample usage:
|
||||
# define filechk_sample
|
||||
# echo $KERNELRELEASE
|
||||
# endef
|
||||
# version.h : Makefile
|
||||
# $(call filechk,sample)
|
||||
# The rule defined shall write to stdout the content of the new file.
|
||||
# The existing file will be compared with the new one.
|
||||
# - If no file exist it is created
|
||||
# - If the content differ the new file is used
|
||||
# - If they are equal no change, and no timestamp update
|
||||
|
||||
define filechk
|
||||
@set -e; \
|
||||
echo ' CHK $@'; \
|
||||
mkdir -p $(dir $@); \
|
||||
$(filechk_$(1)) < $< > $@.tmp; \
|
||||
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
|
||||
rm -f $@.tmp; \
|
||||
else \
|
||||
echo ' UPD $@'; \
|
||||
mv -f $@.tmp $@; \
|
||||
fi
|
||||
endef
|
||||
|
||||
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=dir
|
||||
# Usage:
|
||||
# $(Q)$(MAKE) $(build)=dir
|
||||
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
|
||||
|
||||
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
|
||||
# Usage:
|
||||
# $(Q)$(MAKE) $(clean)=dir
|
||||
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
|
||||
|
||||
# $(call descend,<dir>,<target>)
|
||||
# Recursively call a sub-make in <dir> with target <target>
|
||||
# Usage is deprecated, because make does not see this as an invocation of make.
|
||||
descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
|
||||
|
||||
endif # skip-makefile
|
||||
|
||||
FORCE:
|
||||
|
|
|
@ -365,8 +365,8 @@ config NO_IDLE_HZ
|
|||
|
||||
Please note that dynamic tick may affect the accuracy of
|
||||
timekeeping on some platforms depending on the implementation.
|
||||
Currently at least OMAP platform is known to have accurate
|
||||
timekeeping with dynamic tick.
|
||||
Currently at least OMAP, PXA2xx and SA11x0 platforms are known
|
||||
to have accurate timekeeping with dynamic tick.
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
bool
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
|
|
|
@ -177,7 +177,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc,
|
|||
d = irq_desc + irq;
|
||||
for (i = 0; i <= 3; i++, d++, irq++) {
|
||||
if (req & (0x0100 << i)) {
|
||||
d->handle(irq, d, regs);
|
||||
desc_handle_irq(irq, d, regs);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ static void locomo_key_handler(unsigned int irq, struct irqdesc *desc,
|
|||
|
||||
if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
|
||||
d = irq_desc + LOCOMO_IRQ_KEY_START;
|
||||
d->handle(LOCOMO_IRQ_KEY_START, d, regs);
|
||||
desc_handle_irq(LOCOMO_IRQ_KEY_START, d, regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,7 +273,7 @@ static void locomo_gpio_handler(unsigned int irq, struct irqdesc *desc,
|
|||
d = irq_desc + LOCOMO_IRQ_GPIO_START;
|
||||
for (i = 0; i <= 15; i++, irq++, d++) {
|
||||
if (req & (0x0001 << i)) {
|
||||
d->handle(irq, d, regs);
|
||||
desc_handle_irq(irq, d, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ static void locomo_lt_handler(unsigned int irq, struct irqdesc *desc,
|
|||
|
||||
if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
|
||||
d = irq_desc + LOCOMO_IRQ_LT_START;
|
||||
d->handle(LOCOMO_IRQ_LT_START, d, regs);
|
||||
desc_handle_irq(LOCOMO_IRQ_LT_START, d, regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,7 +379,7 @@ static void locomo_spi_handler(unsigned int irq, struct irqdesc *desc,
|
|||
|
||||
for (i = 0; i <= 3; i++, irq++, d++) {
|
||||
if (req & (0x0001 << i)) {
|
||||
d->handle(irq, d, regs);
|
||||
desc_handle_irq(irq, d, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -651,15 +651,15 @@ __locomo_probe(struct device *me, struct resource *mem, int irq)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int locomo_remove_child(struct device *dev, void *data)
|
||||
{
|
||||
device_unregister(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __locomo_remove(struct locomo *lchip)
|
||||
{
|
||||
struct list_head *l, *n;
|
||||
|
||||
list_for_each_safe(l, n, &lchip->dev->children) {
|
||||
struct device *d = list_to_dev(l);
|
||||
|
||||
device_unregister(d);
|
||||
}
|
||||
device_for_each_child(lchip->dev, NULL, locomo_remove_child);
|
||||
|
||||
if (lchip->irq != NO_IRQ) {
|
||||
set_irq_chained_handler(lchip->irq, NULL);
|
||||
|
|
|
@ -268,8 +268,8 @@ static struct irqchip sa1111_low_chip = {
|
|||
.mask = sa1111_mask_lowirq,
|
||||
.unmask = sa1111_unmask_lowirq,
|
||||
.retrigger = sa1111_retrigger_lowirq,
|
||||
.type = sa1111_type_lowirq,
|
||||
.wake = sa1111_wake_lowirq,
|
||||
.set_type = sa1111_type_lowirq,
|
||||
.set_wake = sa1111_wake_lowirq,
|
||||
};
|
||||
|
||||
static void sa1111_mask_highirq(unsigned int irq)
|
||||
|
@ -364,8 +364,8 @@ static struct irqchip sa1111_high_chip = {
|
|||
.mask = sa1111_mask_highirq,
|
||||
.unmask = sa1111_unmask_highirq,
|
||||
.retrigger = sa1111_retrigger_highirq,
|
||||
.type = sa1111_type_highirq,
|
||||
.wake = sa1111_wake_highirq,
|
||||
.set_type = sa1111_type_highirq,
|
||||
.set_wake = sa1111_wake_highirq,
|
||||
};
|
||||
|
||||
static void sa1111_setup_irq(struct sa1111 *sachip)
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
|
||||
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
|
||||
|
||||
/* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c
|
||||
There is no easy way to link multiple scoop devices into one
|
||||
single entity for the pxa2xx_pcmcia device */
|
||||
int scoop_num;
|
||||
struct scoop_pcmcia_dev *scoop_devs;
|
||||
|
||||
struct scoop_dev {
|
||||
void *base;
|
||||
spinlock_t scoop_lock;
|
||||
|
|
|
@ -284,7 +284,7 @@ __syscall_start:
|
|||
.long sys_fstatfs64
|
||||
.long sys_tgkill
|
||||
.long sys_utimes
|
||||
/* 270 */ .long sys_fadvise64_64
|
||||
/* 270 */ .long sys_arm_fadvise64_64_wrapper
|
||||
.long sys_pciconfig_iobase
|
||||
.long sys_pciconfig_read
|
||||
.long sys_pciconfig_write
|
||||
|
|
|
@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
|||
|
||||
if (pending) {
|
||||
struct irqdesc *d = irq_desc + ec->irq;
|
||||
d->handle(ec->irq, d, regs);
|
||||
desc_handle_irq(ec->irq, d, regs);
|
||||
called ++;
|
||||
}
|
||||
}
|
||||
|
@ -632,7 +632,7 @@ ecard_irqexp_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
|
|||
* Serial cards should go in 0/1, ethernet/scsi in 2/3
|
||||
* otherwise you will lose serial data at high speeds!
|
||||
*/
|
||||
d->handle(ec->irq, d, regs);
|
||||
desc_handle_irq(ec->irq, d, regs);
|
||||
} else {
|
||||
printk(KERN_WARNING "card%d: interrupt from unclaimed "
|
||||
"card???\n", slot);
|
||||
|
|
|
@ -265,6 +265,10 @@ sys_futex_wrapper:
|
|||
str r5, [sp, #4] @ push sixth arg
|
||||
b sys_futex
|
||||
|
||||
sys_arm_fadvise64_64_wrapper:
|
||||
str r5, [sp, #4] @ push r5 to stack
|
||||
b sys_arm_fadvise64_64
|
||||
|
||||
/*
|
||||
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
|
||||
* offset, we return EINVAL.
|
||||
|
|
|
@ -207,8 +207,8 @@ void enable_irq_wake(unsigned int irq)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||
if (desc->chip->wake)
|
||||
desc->chip->wake(irq, 1);
|
||||
if (desc->chip->set_wake)
|
||||
desc->chip->set_wake(irq, 1);
|
||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(enable_irq_wake);
|
||||
|
@ -219,8 +219,8 @@ void disable_irq_wake(unsigned int irq)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||
if (desc->chip->wake)
|
||||
desc->chip->wake(irq, 0);
|
||||
if (desc->chip->set_wake)
|
||||
desc->chip->set_wake(irq, 0);
|
||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(disable_irq_wake);
|
||||
|
@ -517,7 +517,7 @@ static void do_pending_irqs(struct pt_regs *regs)
|
|||
list_for_each_safe(l, n, &head) {
|
||||
desc = list_entry(l, struct irqdesc, pend);
|
||||
list_del_init(&desc->pend);
|
||||
desc->handle(desc - irq_desc, desc, regs);
|
||||
desc_handle_irq(desc - irq_desc, desc, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -545,7 +545,7 @@ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
|
|||
|
||||
irq_enter();
|
||||
spin_lock(&irq_controller_lock);
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
|
||||
/*
|
||||
* Now re-run any pending interrupts.
|
||||
|
@ -624,9 +624,9 @@ int set_irq_type(unsigned int irq, unsigned int type)
|
|||
}
|
||||
|
||||
desc = irq_desc + irq;
|
||||
if (desc->chip->type) {
|
||||
if (desc->chip->set_type) {
|
||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||
ret = desc->chip->type(irq, type);
|
||||
ret = desc->chip->set_type(irq, type);
|
||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||
}
|
||||
|
||||
|
@ -846,8 +846,8 @@ unsigned long probe_irq_on(void)
|
|||
|
||||
irq_desc[i].probing = 1;
|
||||
irq_desc[i].triggered = 0;
|
||||
if (irq_desc[i].chip->type)
|
||||
irq_desc[i].chip->type(i, IRQT_PROBE);
|
||||
if (irq_desc[i].chip->set_type)
|
||||
irq_desc[i].chip->set_type(i, IRQT_PROBE);
|
||||
irq_desc[i].chip->unmask(i);
|
||||
irqs += 1;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
* We need to tell the secondary core where to find
|
||||
* its stack and the page tables.
|
||||
*/
|
||||
secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
|
||||
secondary_data.stack = (void *)idle->thread_info + THREAD_START_SP;
|
||||
secondary_data.pgdir = virt_to_phys(pgd);
|
||||
wmb();
|
||||
|
||||
|
|
|
@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(execve);
|
||||
|
||||
/*
|
||||
* Since loff_t is a 64 bit type we avoid a lot of ABI hastle
|
||||
* with a different argument ordering.
|
||||
*/
|
||||
asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
|
||||
loff_t offset, loff_t len)
|
||||
{
|
||||
return sys_fadvise64_64(fd, offset, len, advice);
|
||||
}
|
||||
|
|
|
@ -433,10 +433,12 @@ void timer_dyn_reprogram(void)
|
|||
{
|
||||
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
|
||||
|
||||
write_seqlock(&xtime_lock);
|
||||
if (dyn_tick->state & DYN_TICK_ENABLED)
|
||||
dyn_tick->reprogram(next_timer_interrupt() - jiffies);
|
||||
write_sequnlock(&xtime_lock);
|
||||
if (dyn_tick) {
|
||||
write_seqlock(&xtime_lock);
|
||||
if (dyn_tick->state & DYN_TICK_ENABLED)
|
||||
dyn_tick->reprogram(next_timer_interrupt() - jiffies);
|
||||
write_sequnlock(&xtime_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
|
||||
|
|
|
@ -95,7 +95,7 @@ isa_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
desc = irq_desc + isa_irq;
|
||||
desc->handle(isa_irq, desc, regs);
|
||||
desc_handle_irq(isa_irq, desc, regs);
|
||||
}
|
||||
|
||||
static struct irqaction irq_cascade = { .handler = no_action, .name = "cascade", };
|
||||
|
|
|
@ -108,7 +108,7 @@ h720x_gpio_handler(unsigned int mask, unsigned int irq,
|
|||
while (mask) {
|
||||
if (mask & 1) {
|
||||
IRQDBG("handling irq %d\n", irq);
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
}
|
||||
irq++;
|
||||
desc++;
|
||||
|
|
|
@ -126,7 +126,7 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
|
|||
desc = irq_desc + irq;
|
||||
while (mask) {
|
||||
if (mask & 1)
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
irq++;
|
||||
desc++;
|
||||
mask >>= 1;
|
||||
|
|
|
@ -152,7 +152,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq,
|
|||
while (mask) {
|
||||
if (mask & 1) {
|
||||
DEBUG_IRQ("handling irq %d\n", irq);
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
}
|
||||
irq++;
|
||||
desc++;
|
||||
|
@ -214,7 +214,7 @@ static struct irqchip imx_gpio_chip = {
|
|||
.ack = imx_gpio_ack_irq,
|
||||
.mask = imx_gpio_mask_irq,
|
||||
.unmask = imx_gpio_unmask_irq,
|
||||
.type = imx_gpio_irq_type,
|
||||
.set_type = imx_gpio_irq_type,
|
||||
};
|
||||
|
||||
void __init
|
||||
|
|
|
@ -170,7 +170,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
|||
irq += IRQ_SIC_START;
|
||||
|
||||
desc = irq_desc + irq;
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
} while (status);
|
||||
}
|
||||
|
||||
|
|
|
@ -317,7 +317,7 @@ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, str
|
|||
for (i = 0; i <= 7; i++) {
|
||||
if (status & (1<<i)) {
|
||||
desc = irq_desc + i + IRQ_IXP2000_GPIO0;
|
||||
desc->handle(i + IRQ_IXP2000_GPIO0, desc, regs);
|
||||
desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -380,10 +380,10 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
|
|||
}
|
||||
|
||||
static struct irqchip ixp2000_GPIO_irq_chip = {
|
||||
.type = ixp2000_GPIO_irq_type,
|
||||
.ack = ixp2000_GPIO_irq_mask_ack,
|
||||
.mask = ixp2000_GPIO_irq_mask,
|
||||
.unmask = ixp2000_GPIO_irq_unmask
|
||||
.ack = ixp2000_GPIO_irq_mask_ack,
|
||||
.mask = ixp2000_GPIO_irq_mask,
|
||||
.unmask = ixp2000_GPIO_irq_unmask
|
||||
.set_type = ixp2000_GPIO_irq_type,
|
||||
};
|
||||
|
||||
static void ixp2000_pci_irq_mask(unsigned int irq)
|
||||
|
|
|
@ -133,7 +133,7 @@ static void ixdp2x00_irq_handler(unsigned int irq, struct irqdesc *desc, struct
|
|||
struct irqdesc *cpld_desc;
|
||||
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
||||
cpld_desc = irq_desc + cpld_irq;
|
||||
cpld_desc->handle(cpld_irq, cpld_desc, regs);
|
||||
desc_handle_irq(cpld_irq, cpld_desc, regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ static void ixdp2x01_irq_handler(unsigned int irq, struct irqdesc *desc, struct
|
|||
struct irqdesc *cpld_desc;
|
||||
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
||||
cpld_desc = irq_desc + cpld_irq;
|
||||
cpld_desc->handle(cpld_irq, cpld_desc, regs);
|
||||
desc_handle_irq(cpld_irq, cpld_desc, regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,90 +38,6 @@
|
|||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
enum ixp4xx_irq_type {
|
||||
IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
|
||||
};
|
||||
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
|
||||
|
||||
/*************************************************************************
|
||||
* GPIO acces functions
|
||||
*************************************************************************/
|
||||
|
||||
/*
|
||||
* Configure GPIO line for input, interrupt, or output operation
|
||||
*
|
||||
* TODO: Enable/disable the irq_desc based on interrupt or output mode.
|
||||
* TODO: Should these be named ixp4xx_gpio_?
|
||||
*/
|
||||
void gpio_line_config(u8 line, u32 style)
|
||||
{
|
||||
static const int gpio2irq[] = {
|
||||
6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
|
||||
};
|
||||
u32 enable;
|
||||
volatile u32 *int_reg;
|
||||
u32 int_style;
|
||||
enum ixp4xx_irq_type irq_type;
|
||||
|
||||
enable = *IXP4XX_GPIO_GPOER;
|
||||
|
||||
if (style & IXP4XX_GPIO_OUT) {
|
||||
enable &= ~((1) << line);
|
||||
} else if (style & IXP4XX_GPIO_IN) {
|
||||
enable |= ((1) << line);
|
||||
|
||||
switch (style & IXP4XX_GPIO_INTSTYLE_MASK)
|
||||
{
|
||||
case (IXP4XX_GPIO_ACTIVE_HIGH):
|
||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
|
||||
irq_type = IXP4XX_IRQ_LEVEL;
|
||||
break;
|
||||
case (IXP4XX_GPIO_ACTIVE_LOW):
|
||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
|
||||
irq_type = IXP4XX_IRQ_LEVEL;
|
||||
break;
|
||||
case (IXP4XX_GPIO_RISING_EDGE):
|
||||
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
|
||||
irq_type = IXP4XX_IRQ_EDGE;
|
||||
break;
|
||||
case (IXP4XX_GPIO_FALLING_EDGE):
|
||||
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
|
||||
irq_type = IXP4XX_IRQ_EDGE;
|
||||
break;
|
||||
case (IXP4XX_GPIO_TRANSITIONAL):
|
||||
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
|
||||
irq_type = IXP4XX_IRQ_EDGE;
|
||||
break;
|
||||
default:
|
||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
|
||||
irq_type = IXP4XX_IRQ_LEVEL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (style & IXP4XX_GPIO_INTSTYLE_MASK)
|
||||
ixp4xx_config_irq(gpio2irq[line], irq_type);
|
||||
|
||||
if (line >= 8) { /* pins 8-15 */
|
||||
line -= 8;
|
||||
int_reg = IXP4XX_GPIO_GPIT2R;
|
||||
}
|
||||
else { /* pins 0-7 */
|
||||
int_reg = IXP4XX_GPIO_GPIT1R;
|
||||
}
|
||||
|
||||
/* Clear the style for the appropriate pin */
|
||||
*int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
|
||||
(line * IXP4XX_GPIO_STYLE_SIZE));
|
||||
|
||||
/* Set the new style */
|
||||
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
|
||||
}
|
||||
|
||||
*IXP4XX_GPIO_GPOER = enable;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(gpio_line_config);
|
||||
|
||||
/*************************************************************************
|
||||
* IXP4xx chipset I/O mapping
|
||||
*************************************************************************/
|
||||
|
@ -165,6 +81,69 @@ void __init ixp4xx_map_io(void)
|
|||
* (be it PCI or something else) configures that GPIO line
|
||||
* as an IRQ.
|
||||
**************************************************************************/
|
||||
enum ixp4xx_irq_type {
|
||||
IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE
|
||||
};
|
||||
|
||||
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type);
|
||||
|
||||
/*
|
||||
* IRQ -> GPIO mapping table
|
||||
*/
|
||||
static int irq2gpio[32] = {
|
||||
-1, -1, -1, -1, -1, -1, 0, 1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, -1, -1,
|
||||
};
|
||||
|
||||
static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type)
|
||||
{
|
||||
int line = irq2gpio[irq];
|
||||
u32 int_style;
|
||||
enum ixp4xx_irq_type irq_type;
|
||||
volatile u32 *int_reg;
|
||||
|
||||
/*
|
||||
* Only for GPIO IRQs
|
||||
*/
|
||||
if (line < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (type & IRQT_BOTHEDGE) {
|
||||
int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
|
||||
irq_type = IXP4XX_IRQ_EDGE;
|
||||
} else if (type & IRQT_RISING) {
|
||||
int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
|
||||
irq_type = IXP4XX_IRQ_EDGE;
|
||||
} else if (type & IRQT_FALLING) {
|
||||
int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
|
||||
irq_type = IXP4XX_IRQ_EDGE;
|
||||
} else if (type & IRQT_HIGH) {
|
||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
|
||||
irq_type = IXP4XX_IRQ_LEVEL;
|
||||
} else if (type & IRQT_LOW) {
|
||||
int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
|
||||
irq_type = IXP4XX_IRQ_LEVEL;
|
||||
}
|
||||
|
||||
ixp4xx_config_irq(irq, irq_type);
|
||||
|
||||
if (line >= 8) { /* pins 8-15 */
|
||||
line -= 8;
|
||||
int_reg = IXP4XX_GPIO_GPIT2R;
|
||||
} else { /* pins 0-7 */
|
||||
int_reg = IXP4XX_GPIO_GPIT1R;
|
||||
}
|
||||
|
||||
/* Clear the style for the appropriate pin */
|
||||
*int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR <<
|
||||
(line * IXP4XX_GPIO_STYLE_SIZE));
|
||||
|
||||
/* Set the new style */
|
||||
*int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
|
||||
}
|
||||
|
||||
static void ixp4xx_irq_mask(unsigned int irq)
|
||||
{
|
||||
if (cpu_is_ixp46x() && irq >= 32)
|
||||
|
@ -183,12 +162,6 @@ static void ixp4xx_irq_unmask(unsigned int irq)
|
|||
|
||||
static void ixp4xx_irq_ack(unsigned int irq)
|
||||
{
|
||||
static int irq2gpio[32] = {
|
||||
-1, -1, -1, -1, -1, -1, 0, 1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, 2, 3, 4, 5, 6,
|
||||
7, 8, 9, 10, 11, 12, -1, -1,
|
||||
};
|
||||
int line = (irq < 32) ? irq2gpio[irq] : -1;
|
||||
|
||||
if (line >= 0)
|
||||
|
@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = {
|
|||
.ack = ixp4xx_irq_mask,
|
||||
.mask = ixp4xx_irq_mask,
|
||||
.unmask = ixp4xx_irq_level_unmask,
|
||||
.type = ixp4xx_set_irq_type
|
||||
};
|
||||
|
||||
static struct irqchip ixp4xx_irq_edge_chip = {
|
||||
.ack = ixp4xx_irq_ack,
|
||||
.mask = ixp4xx_irq_mask,
|
||||
.unmask = ixp4xx_irq_unmask,
|
||||
.type = ixp4xx_set_irq_type
|
||||
};
|
||||
|
||||
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type)
|
||||
|
|
|
@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
|
|||
|
||||
void __init coyote_pci_preinit(void)
|
||||
{
|
||||
gpio_line_config(COYOTE_PCI_SLOT0_PIN,
|
||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
|
||||
gpio_line_config(COYOTE_PCI_SLOT1_PIN,
|
||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
|
||||
set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
|
||||
|
||||
gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
|
||||
gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
void __init coyote_map_io(void)
|
||||
{
|
||||
ixp4xx_map_io();
|
||||
}
|
||||
|
||||
static struct flash_platform_data coyote_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
.width = 2,
|
||||
|
@ -107,7 +102,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = coyote_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
@ -125,7 +120,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = coyote_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
|
|
@ -35,26 +35,20 @@ extern void ixp4xx_pci_preinit(void);
|
|||
extern int ixp4xx_setup(int nr, struct pci_sys_data *sys);
|
||||
extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
|
||||
|
||||
/*
|
||||
* The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
|
||||
* Slot 0 isn't actually populated with a card connector but
|
||||
* we initialize it anyway in case a future version has the
|
||||
* slot populated or someone with good soldering skills has
|
||||
* some free time.
|
||||
*/
|
||||
|
||||
|
||||
static void gtwx5715_init_gpio(u8 pin, u32 style)
|
||||
{
|
||||
gpio_line_config(pin, style | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
|
||||
if (style & IXP4XX_GPIO_IN) gpio_line_isr_clear(pin);
|
||||
}
|
||||
|
||||
/*
|
||||
* The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h
|
||||
* Slot 0 isn't actually populated with a card connector but
|
||||
* we initialize it anyway in case a future version has the
|
||||
* slot populated or someone with good soldering skills has
|
||||
* some free time.
|
||||
*/
|
||||
void __init gtwx5715_pci_preinit(void)
|
||||
{
|
||||
gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN);
|
||||
gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN);
|
||||
set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
|
||||
set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW);
|
||||
set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW);
|
||||
set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW);
|
||||
|
||||
ixp4xx_pci_preinit();
|
||||
}
|
||||
|
|
|
@ -101,12 +101,6 @@ static struct platform_device gtwx5715_uart_device = {
|
|||
.resource = gtwx5715_uart_resources,
|
||||
};
|
||||
|
||||
|
||||
void __init gtwx5715_map_io(void)
|
||||
{
|
||||
ixp4xx_map_io();
|
||||
}
|
||||
|
||||
static struct flash_platform_data gtwx5715_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
.width = 2,
|
||||
|
@ -144,7 +138,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_UART2_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = gtwx5715_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
|
|
@ -27,14 +27,10 @@
|
|||
|
||||
void __init ixdp425_pci_preinit(void)
|
||||
{
|
||||
gpio_line_config(IXDP425_PCI_INTA_PIN,
|
||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
gpio_line_config(IXDP425_PCI_INTB_PIN,
|
||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
gpio_line_config(IXDP425_PCI_INTC_PIN,
|
||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
gpio_line_config(IXDP425_PCI_INTD_PIN,
|
||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
|
||||
set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
|
||||
set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
|
||||
set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW);
|
||||
|
||||
gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
|
||||
gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
void __init ixdp425_map_io(void)
|
||||
{
|
||||
ixp4xx_map_io();
|
||||
}
|
||||
|
||||
static struct flash_platform_data ixdp425_flash_data = {
|
||||
.map_name = "cfi_probe",
|
||||
.width = 2,
|
||||
|
@ -133,7 +128,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = ixdp425_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
@ -145,7 +140,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = ixdp425_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
@ -157,7 +152,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = ixdp425_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
@ -176,7 +171,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
|
|||
.phys_ram = PHYS_OFFSET,
|
||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||
.map_io = ixdp425_map_io,
|
||||
.map_io = ixp4xx_map_io,
|
||||
.init_irq = ixp4xx_init_irq,
|
||||
.timer = &ixp4xx_timer,
|
||||
.boot_params = 0x0100,
|
||||
|
|
|
@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys);
|
|||
|
||||
void __init ixdpg425_pci_preinit(void)
|
||||
{
|
||||
gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
||||
set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
|
||||
set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
|
||||
|
||||
gpio_line_isr_clear(6);
|
||||
gpio_line_isr_clear(7);
|
||||
|
|
|
@ -13,4 +13,4 @@ extern struct sys_timer lh7a40x_timer;
|
|||
extern void lh7a400_init_irq (void);
|
||||
extern void lh7a404_init_irq (void);
|
||||
|
||||
#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
|
||||
#define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
|
||||
|
|
|
@ -102,7 +102,7 @@ void innovator_fpga_IRQ_demux(unsigned int irq, struct irqdesc *desc,
|
|||
fpga_irq++, stat >>= 1) {
|
||||
if (stat & 1) {
|
||||
d = irq_desc + fpga_irq;
|
||||
d->handle(fpga_irq, d, regs);
|
||||
desc_handle_irq(fpga_irq, d, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,15 @@ static struct scoop_config corgi_scoop_setup = {
|
|||
.io_out = CORGI_SCOOP_IO_OUT,
|
||||
};
|
||||
|
||||
static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = {
|
||||
{
|
||||
.dev = &corgiscoop_device.dev,
|
||||
.irq = CORGI_IRQ_GPIO_CF_IRQ,
|
||||
.cd_irq = CORGI_IRQ_GPIO_CF_CD,
|
||||
.cd_irq_str = "PCMCIA0 CD",
|
||||
},
|
||||
};
|
||||
|
||||
struct platform_device corgiscoop_device = {
|
||||
.name = "sharp-scoop",
|
||||
.id = -1,
|
||||
|
@ -241,6 +250,9 @@ static void __init corgi_init(void)
|
|||
pxa_set_udc_info(&udc_info);
|
||||
pxa_set_mci_info(&corgi_mci_platform_data);
|
||||
|
||||
scoop_num = 1;
|
||||
scoop_devs = &corgi_pcmcia_scoop[0];
|
||||
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ static struct irqchip pxa_low_gpio_chip = {
|
|||
.ack = pxa_ack_low_gpio,
|
||||
.mask = pxa_mask_low_irq,
|
||||
.unmask = pxa_unmask_low_irq,
|
||||
.type = pxa_gpio_irq_type,
|
||||
.set_type = pxa_gpio_irq_type,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -157,7 +157,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
|||
mask >>= 2;
|
||||
do {
|
||||
if (mask & 1)
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
irq++;
|
||||
desc++;
|
||||
mask >>= 1;
|
||||
|
@ -172,7 +172,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
|||
desc = irq_desc + irq;
|
||||
do {
|
||||
if (mask & 1)
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
irq++;
|
||||
desc++;
|
||||
mask >>= 1;
|
||||
|
@ -187,7 +187,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
|||
desc = irq_desc + irq;
|
||||
do {
|
||||
if (mask & 1)
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
irq++;
|
||||
desc++;
|
||||
mask >>= 1;
|
||||
|
@ -203,7 +203,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
|||
desc = irq_desc + irq;
|
||||
do {
|
||||
if (mask & 1)
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
irq++;
|
||||
desc++;
|
||||
mask >>= 1;
|
||||
|
@ -241,7 +241,7 @@ static struct irqchip pxa_muxed_gpio_chip = {
|
|||
.ack = pxa_ack_muxed_gpio,
|
||||
.mask = pxa_mask_muxed_gpio,
|
||||
.unmask = pxa_unmask_muxed_gpio,
|
||||
.type = pxa_gpio_irq_type,
|
||||
.set_type = pxa_gpio_irq_type,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc,
|
|||
if (likely(pending)) {
|
||||
irq = LUBBOCK_IRQ(0) + __ffs(pending);
|
||||
desc = irq_desc + irq;
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
}
|
||||
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
|
||||
} while (pending);
|
||||
|
|
|
@ -72,7 +72,7 @@ static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
|
|||
if (likely(pending)) {
|
||||
irq = MAINSTONE_IRQ(0) + __ffs(pending);
|
||||
desc = irq_desc + irq;
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
}
|
||||
pending = MST_INTSETCLR & mainstone_irq_enabled;
|
||||
} while (pending);
|
||||
|
|
|
@ -62,6 +62,15 @@ struct platform_device poodle_scoop_device = {
|
|||
.resource = poodle_scoop_resources,
|
||||
};
|
||||
|
||||
static struct scoop_pcmcia_dev poodle_pcmcia_scoop[] = {
|
||||
{
|
||||
.dev = &poodle_scoop_device.dev,
|
||||
.irq = POODLE_IRQ_GPIO_CF_IRQ,
|
||||
.cd_irq = POODLE_IRQ_GPIO_CF_CD,
|
||||
.cd_irq_str = "PCMCIA0 CD",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* LoCoMo device */
|
||||
static struct resource locomo_resources[] = {
|
||||
|
@ -147,6 +156,9 @@ static void __init poodle_init(void)
|
|||
|
||||
set_pxa_fb_info(&poodle_fb_info);
|
||||
|
||||
scoop_num = 1;
|
||||
scoop_devs = &poodle_pcmcia_scoop[0];
|
||||
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
if (ret) {
|
||||
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
|
||||
|
|
|
@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void)
|
|||
return usec;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
static unsigned long initial_match;
|
||||
static int match_posponed;
|
||||
#endif
|
||||
|
||||
static irqreturn_t
|
||||
pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
|
@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
if (match_posponed) {
|
||||
match_posponed = 0;
|
||||
OSMR0 = initial_match;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Loop until we get ahead of the free running timer.
|
||||
* This ensures an exact clock tick count and time accuracy.
|
||||
* IRQs are disabled inside the loop to ensure coherence between
|
||||
* lost_ticks (updated in do_timer()) and the match reg value, so we
|
||||
* can use do_gettimeofday() from interrupt handlers.
|
||||
* Since IRQs are disabled at this point, coherence between
|
||||
* lost_ticks(updated in do_timer()) and the match reg value is
|
||||
* ensured, hence we can use do_gettimeofday() from interrupt
|
||||
* handlers.
|
||||
*
|
||||
* HACK ALERT: it seems that the PXA timer regs aren't updated right
|
||||
* away in all cases when a write occurs. We therefore compare with
|
||||
|
@ -126,6 +139,42 @@ static void __init pxa_timer_init(void)
|
|||
OSCR = 0; /* initialize free-running timer, force first match */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
static int pxa_dyn_tick_enable_disable(void)
|
||||
{
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pxa_dyn_tick_reprogram(unsigned long ticks)
|
||||
{
|
||||
if (ticks > 1) {
|
||||
initial_match = OSMR0;
|
||||
OSMR0 = initial_match + ticks * LATCH;
|
||||
match_posponed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
if (match_posponed) {
|
||||
match_posponed = 0;
|
||||
OSMR0 = initial_match;
|
||||
if ( (signed long)(initial_match - OSCR) <= 8 )
|
||||
return pxa_timer_interrupt(irq, dev_id, regs);
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static struct dyn_tick_timer pxa_dyn_tick = {
|
||||
.enable = pxa_dyn_tick_enable_disable,
|
||||
.disable = pxa_dyn_tick_enable_disable,
|
||||
.reprogram = pxa_dyn_tick_reprogram,
|
||||
.handler = pxa_dyn_tick_handler,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static unsigned long osmr[4], oier;
|
||||
|
||||
|
@ -161,4 +210,7 @@ struct sys_timer pxa_timer = {
|
|||
.suspend = pxa_timer_suspend,
|
||||
.resume = pxa_timer_resume,
|
||||
.offset = pxa_gettimeoffset,
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
.dyn_tick = &pxa_dyn_tick,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -124,7 +124,7 @@ bast_irq_pc104_demux(unsigned int irq,
|
|||
irqno = bast_pc104_irqs[i];
|
||||
desc = irq_desc + irqno;
|
||||
|
||||
desc->handle(irqno, desc, regs);
|
||||
desc_handle_irq(irqno, desc, regs);
|
||||
}
|
||||
|
||||
stat >>= 1;
|
||||
|
|
|
@ -388,6 +388,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
|||
unsigned long hclk,
|
||||
unsigned long pclk)
|
||||
{
|
||||
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
|
||||
struct clk *clkp = init_clocks;
|
||||
int ptr;
|
||||
int ret;
|
||||
|
@ -446,5 +447,13 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
|||
}
|
||||
}
|
||||
|
||||
/* show the clock-slow value */
|
||||
|
||||
printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
|
||||
print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
|
||||
(clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
|
||||
(clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
|
||||
(clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -184,14 +184,14 @@ struct irqchip s3c_irq_level_chip = {
|
|||
.ack = s3c_irq_maskack,
|
||||
.mask = s3c_irq_mask,
|
||||
.unmask = s3c_irq_unmask,
|
||||
.wake = s3c_irq_wake
|
||||
.set_wake = s3c_irq_wake
|
||||
};
|
||||
|
||||
static struct irqchip s3c_irq_chip = {
|
||||
.ack = s3c_irq_ack,
|
||||
.mask = s3c_irq_mask,
|
||||
.unmask = s3c_irq_unmask,
|
||||
.wake = s3c_irq_wake
|
||||
.set_wake = s3c_irq_wake
|
||||
};
|
||||
|
||||
/* S3C2410_EINTMASK
|
||||
|
@ -350,16 +350,16 @@ static struct irqchip s3c_irqext_chip = {
|
|||
.mask = s3c_irqext_mask,
|
||||
.unmask = s3c_irqext_unmask,
|
||||
.ack = s3c_irqext_ack,
|
||||
.type = s3c_irqext_type,
|
||||
.wake = s3c_irqext_wake
|
||||
.set_type = s3c_irqext_type,
|
||||
.set_wake = s3c_irqext_wake
|
||||
};
|
||||
|
||||
static struct irqchip s3c_irq_eint0t4 = {
|
||||
.ack = s3c_irq_ack,
|
||||
.mask = s3c_irq_mask,
|
||||
.unmask = s3c_irq_unmask,
|
||||
.wake = s3c_irq_wake,
|
||||
.type = s3c_irqext_type,
|
||||
.set_wake = s3c_irq_wake,
|
||||
.set_type = s3c_irqext_type,
|
||||
};
|
||||
|
||||
/* mask values for the parent registers for each of the interrupt types */
|
||||
|
@ -496,11 +496,11 @@ static void s3c_irq_demux_adc(unsigned int irq,
|
|||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_TC;
|
||||
mydesc->handle( IRQ_TC, mydesc, regs);
|
||||
desc_handle_irq(IRQ_TC, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_ADC;
|
||||
mydesc->handle(IRQ_ADC, mydesc, regs);
|
||||
desc_handle_irq(IRQ_ADC, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -529,17 +529,17 @@ static void s3c_irq_demux_uart(unsigned int start,
|
|||
desc = irq_desc + start;
|
||||
|
||||
if (subsrc & 1)
|
||||
desc->handle(start, desc, regs);
|
||||
desc_handle_irq(start, desc, regs);
|
||||
|
||||
desc++;
|
||||
|
||||
if (subsrc & 2)
|
||||
desc->handle(start+1, desc, regs);
|
||||
desc_handle_irq(start+1, desc, regs);
|
||||
|
||||
desc++;
|
||||
|
||||
if (subsrc & 4)
|
||||
desc->handle(start+2, desc, regs);
|
||||
desc_handle_irq(start+2, desc, regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,34 +110,24 @@ void __init n30_init_irq(void)
|
|||
s3c24xx_init_irq();
|
||||
}
|
||||
|
||||
|
||||
static int n30_usbstart_thread(void *unused)
|
||||
{
|
||||
/* Turn off suspend on both USB ports, and switch the
|
||||
* selectable USB port to USB device mode. */
|
||||
writel(readl(S3C2410_MISCCR) & ~0x00003008, S3C2410_MISCCR);
|
||||
|
||||
/* Turn off the D+ pull up for 3 seconds so that the USB host
|
||||
* at the other end will do a rescan of the USB bus. */
|
||||
s3c2410_gpio_setpin(S3C2410_GPB3, 0);
|
||||
|
||||
msleep_interruptible(3*HZ);
|
||||
|
||||
s3c2410_gpio_setpin(S3C2410_GPB3, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* GPB3 is the line that controls the pull-up for the USB D+ line */
|
||||
|
||||
void __init n30_init(void)
|
||||
{
|
||||
s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
|
||||
|
||||
kthread_run(n30_usbstart_thread, NULL, "n30_usbstart");
|
||||
/* Turn off suspend on both USB ports, and switch the
|
||||
* selectable USB port to USB device mode. */
|
||||
|
||||
s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
|
||||
S3C2410_MISCCR_USBSUSPND0 |
|
||||
S3C2410_MISCCR_USBSUSPND1, 0x0);
|
||||
}
|
||||
|
||||
MACHINE_START(N30, "Acer-N30")
|
||||
/* Maintainer: Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org> */
|
||||
/* Maintainer: Christer Weinigel <christer@weinigel.se>,
|
||||
Ben Dooks <ben-linux@fluff.org>
|
||||
*/
|
||||
.phys_ram = S3C2410_SDRAM_PA,
|
||||
.phys_io = S3C2410_PA_UART,
|
||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
||||
|
|
|
@ -585,14 +585,16 @@ static int s3c2410_pm_enter(suspend_state_t state)
|
|||
|
||||
s3c2410_pm_check_store();
|
||||
|
||||
// need to make some form of time-delta
|
||||
|
||||
/* send the cpu to sleep... */
|
||||
|
||||
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
|
||||
|
||||
s3c2410_cpu_suspend(regs_save);
|
||||
|
||||
/* restore the cpu state */
|
||||
|
||||
cpu_init();
|
||||
|
||||
/* unset the return-from-sleep flag, to ensure reset */
|
||||
|
||||
tmp = __raw_readl(S3C2410_GSTATUS2);
|
||||
|
|
|
@ -68,6 +68,7 @@ static struct clk s3c2440_clk_ac97 = {
|
|||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||
{
|
||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||
struct clk *clk_h;
|
||||
struct clk *clk_p;
|
||||
struct clk *clk_xtal;
|
||||
|
@ -80,8 +81,9 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
|
|||
|
||||
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
|
||||
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
||||
print_mhz(s3c2440_clk_upll.rate));
|
||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n",
|
||||
print_mhz(s3c2440_clk_upll.rate),
|
||||
(camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
|
||||
|
||||
clk_p = clk_get(NULL, "pclk");
|
||||
clk_h = clk_get(NULL, "hclk");
|
||||
|
|
|
@ -64,11 +64,11 @@ static void s3c_irq_demux_wdtac97(unsigned int irq,
|
|||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
desc_handle_irq(IRQ_S3C2440_WDT, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
desc_handle_irq(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -122,11 +122,11 @@ static void s3c_irq_demux_cam(unsigned int irq,
|
|||
if (subsrc != 0) {
|
||||
if (subsrc & 1) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
||||
desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
|
||||
}
|
||||
if (subsrc & 2) {
|
||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
||||
mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
|
||||
desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,8 +98,8 @@ static struct irqchip sa1100_low_gpio_chip = {
|
|||
.ack = sa1100_low_gpio_ack,
|
||||
.mask = sa1100_low_gpio_mask,
|
||||
.unmask = sa1100_low_gpio_unmask,
|
||||
.type = sa1100_gpio_type,
|
||||
.wake = sa1100_low_gpio_wake,
|
||||
.set_type = sa1100_gpio_type,
|
||||
.set_wake = sa1100_low_gpio_wake,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -126,7 +126,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
|
|||
mask >>= 11;
|
||||
do {
|
||||
if (mask & 1)
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
mask >>= 1;
|
||||
irq++;
|
||||
desc++;
|
||||
|
@ -181,8 +181,8 @@ static struct irqchip sa1100_high_gpio_chip = {
|
|||
.ack = sa1100_high_gpio_ack,
|
||||
.mask = sa1100_high_gpio_mask,
|
||||
.unmask = sa1100_high_gpio_unmask,
|
||||
.type = sa1100_gpio_type,
|
||||
.wake = sa1100_high_gpio_wake,
|
||||
.set_type = sa1100_gpio_type,
|
||||
.set_wake = sa1100_high_gpio_wake,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -61,12 +61,12 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
|
|||
|
||||
if (irr & IRR_ETHERNET) {
|
||||
d = irq_desc + IRQ_NEPONSET_SMC9196;
|
||||
d->handle(IRQ_NEPONSET_SMC9196, d, regs);
|
||||
desc_handle_irq(IRQ_NEPONSET_SMC9196, d, regs);
|
||||
}
|
||||
|
||||
if (irr & IRR_USAR) {
|
||||
d = irq_desc + IRQ_NEPONSET_USAR;
|
||||
d->handle(IRQ_NEPONSET_USAR, d, regs);
|
||||
desc_handle_irq(IRQ_NEPONSET_USAR, d, regs);
|
||||
}
|
||||
|
||||
desc->chip->unmask(irq);
|
||||
|
@ -74,7 +74,7 @@ neponset_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *reg
|
|||
|
||||
if (irr & IRR_SA1111) {
|
||||
d = irq_desc + IRQ_NEPONSET_SA1111;
|
||||
d->handle(IRQ_NEPONSET_SA1111, d, regs);
|
||||
desc_handle_irq(IRQ_NEPONSET_SA1111, d, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void)
|
|||
return usec;
|
||||
}
|
||||
|
||||
/*
|
||||
* We will be entered with IRQs enabled.
|
||||
*
|
||||
* Loop until we get ahead of the free running timer.
|
||||
* This ensures an exact clock tick count and time accuracy.
|
||||
* IRQs are disabled inside the loop to ensure coherence between
|
||||
* lost_ticks (updated in do_timer()) and the match reg value, so we
|
||||
* can use do_gettimeofday() from interrupt handlers.
|
||||
*/
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
static unsigned long initial_match;
|
||||
static int match_posponed;
|
||||
#endif
|
||||
|
||||
static irqreturn_t
|
||||
sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
|
@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
|
||||
write_seqlock(&xtime_lock);
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
if (match_posponed) {
|
||||
match_posponed = 0;
|
||||
OSMR0 = initial_match;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Loop until we get ahead of the free running timer.
|
||||
* This ensures an exact clock tick count and time accuracy.
|
||||
* Since IRQs are disabled at this point, coherence between
|
||||
* lost_ticks(updated in do_timer()) and the match reg value is
|
||||
* ensured, hence we can use do_gettimeofday() from interrupt
|
||||
* handlers.
|
||||
*/
|
||||
do {
|
||||
timer_tick(regs);
|
||||
OSSR = OSSR_M0; /* Clear match on timer 0 */
|
||||
|
@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void)
|
|||
OSCR = 0; /* initialize free-running timer, force first match */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
static int sa1100_dyn_tick_enable_disable(void)
|
||||
{
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sa1100_dyn_tick_reprogram(unsigned long ticks)
|
||||
{
|
||||
if (ticks > 1) {
|
||||
initial_match = OSMR0;
|
||||
OSMR0 = initial_match + ticks * LATCH;
|
||||
match_posponed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t
|
||||
sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
if (match_posponed) {
|
||||
match_posponed = 0;
|
||||
OSMR0 = initial_match;
|
||||
if ((signed long)(initial_match - OSCR) <= 0)
|
||||
return sa1100_timer_interrupt(irq, dev_id, regs);
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static struct dyn_tick_timer sa1100_dyn_tick = {
|
||||
.enable = sa1100_dyn_tick_enable_disable,
|
||||
.disable = sa1100_dyn_tick_enable_disable,
|
||||
.reprogram = sa1100_dyn_tick_reprogram,
|
||||
.handler = sa1100_dyn_tick_handler,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
unsigned long osmr[4], oier;
|
||||
|
||||
|
@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = {
|
|||
.suspend = sa1100_timer_suspend,
|
||||
.resume = sa1100_timer_resume,
|
||||
.offset = sa1100_gettimeoffset,
|
||||
#ifdef CONFIG_NO_IDLE_HZ
|
||||
.dyn_tick = &sa1100_dyn_tick,
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -108,7 +108,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
|||
irq += IRQ_SIC_START;
|
||||
|
||||
desc = irq_desc + irq;
|
||||
desc->handle(irq, desc, regs);
|
||||
desc_handle_irq(irq, desc, regs);
|
||||
} while (status);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
|
||||
|
||||
#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */
|
||||
#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */
|
||||
#define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
|
||||
|
||||
#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
|
||||
|
@ -68,6 +68,7 @@ static unsigned long ai_sys;
|
|||
static unsigned long ai_skipped;
|
||||
static unsigned long ai_half;
|
||||
static unsigned long ai_word;
|
||||
static unsigned long ai_dword;
|
||||
static unsigned long ai_multi;
|
||||
static int ai_usermode;
|
||||
|
||||
|
@ -93,6 +94,8 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof,
|
|||
p += sprintf(p, "Skipped:\t%lu\n", ai_skipped);
|
||||
p += sprintf(p, "Half:\t\t%lu\n", ai_half);
|
||||
p += sprintf(p, "Word:\t\t%lu\n", ai_word);
|
||||
if (cpu_architecture() >= CPU_ARCH_ARMv5TE)
|
||||
p += sprintf(p, "DWord:\t\t%lu\n", ai_dword);
|
||||
p += sprintf(p, "Multi:\t\t%lu\n", ai_multi);
|
||||
p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
|
||||
usermode_action[ai_usermode]);
|
||||
|
@ -283,12 +286,6 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
|
|||
{
|
||||
unsigned int rd = RD_BITS(instr);
|
||||
|
||||
if ((instr & 0x01f00ff0) == 0x01000090)
|
||||
goto swp;
|
||||
|
||||
if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
|
||||
goto bad;
|
||||
|
||||
ai_half += 1;
|
||||
|
||||
if (user_mode(regs))
|
||||
|
@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
|
|||
|
||||
return TYPE_LDST;
|
||||
|
||||
swp:
|
||||
printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
|
||||
bad:
|
||||
return TYPE_ERROR;
|
||||
fault:
|
||||
return TYPE_FAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
do_alignment_ldrdstrd(unsigned long addr, unsigned long instr,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned int rd = RD_BITS(instr);
|
||||
|
||||
ai_dword += 1;
|
||||
|
||||
if (user_mode(regs))
|
||||
goto user;
|
||||
|
||||
if ((instr & 0xf0) == 0xd0) {
|
||||
unsigned long val;
|
||||
get32_unaligned_check(val, addr);
|
||||
regs->uregs[rd] = val;
|
||||
get32_unaligned_check(val, addr+4);
|
||||
regs->uregs[rd+1] = val;
|
||||
} else {
|
||||
put32_unaligned_check(regs->uregs[rd], addr);
|
||||
put32_unaligned_check(regs->uregs[rd+1], addr+4);
|
||||
}
|
||||
|
||||
return TYPE_LDST;
|
||||
|
||||
user:
|
||||
if ((instr & 0xf0) == 0xd0) {
|
||||
unsigned long val;
|
||||
get32t_unaligned_check(val, addr);
|
||||
regs->uregs[rd] = val;
|
||||
get32t_unaligned_check(val, addr+4);
|
||||
regs->uregs[rd+1] = val;
|
||||
} else {
|
||||
put32t_unaligned_check(regs->uregs[rd], addr);
|
||||
put32t_unaligned_check(regs->uregs[rd+1], addr+4);
|
||||
}
|
||||
|
||||
return TYPE_LDST;
|
||||
|
||||
fault:
|
||||
return TYPE_FAULT;
|
||||
|
@ -617,12 +651,20 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
regs->ARM_pc += thumb_mode(regs) ? 2 : 4;
|
||||
|
||||
switch (CODING_BITS(instr)) {
|
||||
case 0x00000000: /* ldrh or strh */
|
||||
if (LDSTH_I_BIT(instr))
|
||||
case 0x00000000: /* 3.13.4 load/store instruction extensions */
|
||||
if (LDSTHD_I_BIT(instr))
|
||||
offset.un = (instr & 0xf00) >> 4 | (instr & 15);
|
||||
else
|
||||
offset.un = regs->uregs[RM_BITS(instr)];
|
||||
handler = do_alignment_ldrhstrh;
|
||||
|
||||
if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */
|
||||
(instr & 0x001000f0) == 0x001000f0) /* LDRSH */
|
||||
handler = do_alignment_ldrhstrh;
|
||||
else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */
|
||||
(instr & 0x001000f0) == 0x000000f0) /* STRD */
|
||||
handler = do_alignment_ldrdstrd;
|
||||
else
|
||||
goto bad;
|
||||
break;
|
||||
|
||||
case 0x04000000: /* ldr or str immediate */
|
||||
|
|
|
@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 16; i += 1) {
|
||||
alloc_init_section(virt, phys & SUPERSECTION_MASK,
|
||||
prot | PMD_SECT_SUPER);
|
||||
alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
|
||||
|
||||
virt += (PGDIR_SIZE / 2);
|
||||
phys += (PGDIR_SIZE / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
|
|||
pte_t *ptep;
|
||||
|
||||
if (pmd_none(*pmdp)) {
|
||||
unsigned long pmdval;
|
||||
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
|
||||
sizeof(pte_t));
|
||||
|
||||
pmdval = __pa(ptep) | prot_l1;
|
||||
pmdp[0] = __pmd(pmdval);
|
||||
pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
|
||||
flush_pmd_entry(pmdp);
|
||||
__pmd_populate(pmdp, __pa(ptep) | prot_l1);
|
||||
}
|
||||
ptep = pte_offset_kernel(pmdp, virt);
|
||||
|
||||
|
@ -459,7 +453,7 @@ static void __init build_mem_type_table(void)
|
|||
|
||||
for (i = 0; i < 16; i++) {
|
||||
unsigned long v = pgprot_val(protection_map[i]);
|
||||
v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
|
||||
v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
|
||||
protection_map[i] = __pgprot(v);
|
||||
}
|
||||
|
||||
|
@ -583,23 +577,23 @@ static void __init create_mapping(struct map_desc *md)
|
|||
*/
|
||||
void setup_mm_for_reboot(char mode)
|
||||
{
|
||||
unsigned long pmdval;
|
||||
unsigned long base_pmdval;
|
||||
pgd_t *pgd;
|
||||
pmd_t *pmd;
|
||||
int i;
|
||||
int cpu_arch = cpu_architecture();
|
||||
|
||||
if (current->mm && current->mm->pgd)
|
||||
pgd = current->mm->pgd;
|
||||
else
|
||||
pgd = init_mm.pgd;
|
||||
|
||||
for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) {
|
||||
pmdval = (i << PGDIR_SHIFT) |
|
||||
PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
|
||||
PMD_TYPE_SECT;
|
||||
if (cpu_arch <= CPU_ARCH_ARMv5TEJ)
|
||||
pmdval |= PMD_BIT4;
|
||||
base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
|
||||
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
|
||||
base_pmdval |= PMD_BIT4;
|
||||
|
||||
for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
|
||||
unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
|
||||
pmd_t *pmd;
|
||||
|
||||
pmd = pmd_off(pgd, i << PGDIR_SHIFT);
|
||||
pmd[0] = __pmd(pmdval);
|
||||
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
|
||||
|
|
|
@ -38,8 +38,8 @@ ENTRY(cpu_arm7_data_abort)
|
|||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||
ldr r8, [r0] @ read arm instruction
|
||||
tst r8, #1 << 20 @ L = 1 -> write?
|
||||
orreq r1, r1, #1 << 8 @ yes.
|
||||
tst r8, #1 << 20 @ L = 0 -> write?
|
||||
orreq r1, r1, #1 << 11 @ yes.
|
||||
and r7, r8, #15 << 24
|
||||
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
|
||||
nop
|
||||
|
@ -71,8 +71,8 @@ ENTRY(cpu_arm6_data_abort)
|
|||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||
ldr r8, [r2] @ read arm instruction
|
||||
tst r8, #1 << 20 @ L = 1 -> write?
|
||||
orreq r1, r1, #1 << 8 @ yes.
|
||||
tst r8, #1 << 20 @ L = 0 -> write?
|
||||
orreq r1, r1, #1 << 11 @ yes.
|
||||
and r7, r8, #14 << 24
|
||||
teq r7, #8 << 24 @ was it ldm/stm
|
||||
movne pc, lr
|
||||
|
|
|
@ -590,7 +590,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
|
|||
if (!(isr & 1))
|
||||
continue;
|
||||
d = irq_desc + gpio_irq;
|
||||
d->handle(gpio_irq, d, regs);
|
||||
desc_handle_irq(gpio_irq, d, regs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,13 @@ config PROFILING
|
|||
bool "Kernel profiling support"
|
||||
|
||||
config SYSTEM_PROFILER
|
||||
bool "System profiling support"
|
||||
bool "System profiling support"
|
||||
|
||||
source "lib/Kconfig.debug"
|
||||
|
||||
config ETRAX_KGDB
|
||||
bool "Use kernel GDB debugger"
|
||||
depends on DEBUG_KERNEL
|
||||
---help---
|
||||
The CRIS version of gdb can be used to remotely debug a running
|
||||
Linux kernel via the serial debug port. Provided you have gdb-cris
|
||||
|
@ -22,25 +25,11 @@ config ETRAX_KGDB
|
|||
this option is turned on!
|
||||
|
||||
|
||||
config DEBUG_INFO
|
||||
bool "Compile the kernel with debug info"
|
||||
help
|
||||
If you say Y here the resulting kernel image will include
|
||||
debugging info resulting in a larger kernel image.
|
||||
Say Y here only if you plan to use gdb to debug the kernel.
|
||||
If you don't debug the kernel, you can say N.
|
||||
|
||||
config FRAME_POINTER
|
||||
bool "Compile the kernel with frame pointers"
|
||||
help
|
||||
If you say Y here the resulting kernel image will be slightly larger
|
||||
and slower, but it will give very useful debugging information.
|
||||
If you don't debug the kernel, you can say N, but we may not be able
|
||||
to solve problems without frame pointers.
|
||||
|
||||
config DEBUG_NMI_OOPS
|
||||
bool "NMI causes oops printout"
|
||||
help
|
||||
If the system locks up without any debug information you can say Y
|
||||
here to make it possible to dump an OOPS with an external NMI.
|
||||
bool "NMI causes oops printout"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
If the system locks up without any debug information you can say Y
|
||||
here to make it possible to dump an OOPS with an external NMI.
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -71,7 +71,6 @@ EXPORT_SYMBOL(memset);
|
|||
EXPORT_SYMBOL(memcmp);
|
||||
EXPORT_SYMBOL(memscan);
|
||||
EXPORT_SYMBOL(memmove);
|
||||
EXPORT_SYMBOL(strtok);
|
||||
|
||||
EXPORT_SYMBOL(get_wchan);
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@ config X86
|
|||
486, 586, Pentiums, and various instruction-set-compatible chips by
|
||||
AMD, Cyrix, and others.
|
||||
|
||||
config SEMAPHORE_SLEEPERS
|
||||
bool
|
||||
default y
|
||||
|
||||
config MMU
|
||||
bool
|
||||
default y
|
||||
|
@ -754,6 +758,7 @@ config NUMA
|
|||
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
|
||||
default n if X86_PC
|
||||
default y if (X86_NUMAQ || X86_SUMMIT)
|
||||
select SPARSEMEM_STATIC
|
||||
|
||||
# Need comments to help the hapless user trying to turn on NUMA support
|
||||
comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
|
||||
|
|
|
@ -7,7 +7,7 @@ extra-y := head.o init_task.o vmlinux.lds
|
|||
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
|
||||
ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
|
||||
pci-dma.o i386_ksyms.o i387.o dmi_scan.o bootflag.o \
|
||||
doublefault.o quirks.o
|
||||
doublefault.o quirks.o i8237.o
|
||||
|
||||
obj-y += cpu/
|
||||
obj-y += timers/
|
||||
|
|
|
@ -833,6 +833,9 @@ acpi_process_madt(void)
|
|||
if (!error) {
|
||||
acpi_lapic = 1;
|
||||
|
||||
#ifdef CONFIG_X86_GENERICARCH
|
||||
generic_bigsmp_probe();
|
||||
#endif
|
||||
/*
|
||||
* Parse MADT IO-APIC entries
|
||||
*/
|
||||
|
|
|
@ -613,8 +613,8 @@ void __devinit cpu_init(void)
|
|||
memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
|
||||
GDT_ENTRY_TLS_ENTRIES * 8);
|
||||
|
||||
__asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
|
||||
__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
|
||||
load_gdt(&cpu_gdt_descr[cpu]);
|
||||
load_idt(&idt_descr);
|
||||
|
||||
/*
|
||||
* Delete NT
|
||||
|
@ -642,12 +642,12 @@ void __devinit cpu_init(void)
|
|||
asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
|
||||
|
||||
/* Clear all 6 debug registers: */
|
||||
|
||||
#define CD(register) set_debugreg(0, register)
|
||||
|
||||
CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
|
||||
|
||||
#undef CD
|
||||
set_debugreg(0, 0);
|
||||
set_debugreg(0, 1);
|
||||
set_debugreg(0, 2);
|
||||
set_debugreg(0, 3);
|
||||
set_debugreg(0, 6);
|
||||
set_debugreg(0, 7);
|
||||
|
||||
/*
|
||||
* Force FPU initialization:
|
||||
|
|
|
@ -64,8 +64,6 @@ static int dont_scale_voltage;
|
|||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
|
||||
|
||||
|
||||
#define __hlt() __asm__ __volatile__("hlt": : :"memory")
|
||||
|
||||
/* Clock ratios multiplied by 10 */
|
||||
static int clock_ratio[32];
|
||||
static int eblcr_table[32];
|
||||
|
@ -168,11 +166,9 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
|||
outb(0xFE,0x21); /* TMR0 only */
|
||||
outb(0xFF,0x80); /* delay */
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
__hlt();
|
||||
safe_halt();
|
||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||
__hlt();
|
||||
halt();
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
|
@ -251,9 +247,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
|||
bcr2.bits.CLOCKMUL = clock_ratio_index;
|
||||
local_irq_disable();
|
||||
wrmsrl (MSR_VIA_BCR2, bcr2.val);
|
||||
local_irq_enable();
|
||||
|
||||
__hlt();
|
||||
safe_halt();
|
||||
|
||||
/* Disable software clock multiplier */
|
||||
rdmsrl (MSR_VIA_BCR2, bcr2.val);
|
||||
|
|
|
@ -132,11 +132,7 @@ static void __init set_cx86_memwb(void)
|
|||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
|
||||
/* set 'Not Write-through' */
|
||||
cr0 = 0x20000000;
|
||||
__asm__("movl %%cr0,%%eax\n\t"
|
||||
"orl %0,%%eax\n\t"
|
||||
"movl %%eax,%%cr0\n"
|
||||
: : "r" (cr0)
|
||||
:"ax");
|
||||
write_cr0(read_cr0() | cr0);
|
||||
/* CCR2 bit 2: lock NW bit and set WT1 */
|
||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
|
||||
}
|
||||
|
|
|
@ -82,16 +82,13 @@ static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
|
|||
*/
|
||||
static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
|
||||
{
|
||||
unsigned int eax;
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
if (c->cpuid_level < 4)
|
||||
return 1;
|
||||
|
||||
__asm__("cpuid"
|
||||
: "=a" (eax)
|
||||
: "0" (4), "c" (0)
|
||||
: "bx", "dx");
|
||||
|
||||
/* Intel has a non-standard dependency on %ecx for this CPUID level. */
|
||||
cpuid_count(4, 0, &eax, &ebx, &ecx, &edx);
|
||||
if (eax & 0x1f)
|
||||
return ((eax >> 26) + 1);
|
||||
else
|
||||
|
|
|
@ -305,6 +305,9 @@ static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
|
|||
{
|
||||
struct _cpuid4_info *this_leaf;
|
||||
unsigned long num_threads_sharing;
|
||||
#ifdef CONFIG_X86_HT
|
||||
struct cpuinfo_x86 *c = cpu_data + cpu;
|
||||
#endif
|
||||
|
||||
this_leaf = CPUID4_INFO_IDX(cpu, index);
|
||||
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
|
||||
|
@ -314,10 +317,12 @@ static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
|
|||
#ifdef CONFIG_X86_HT
|
||||
else if (num_threads_sharing == smp_num_siblings)
|
||||
this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
|
||||
#endif
|
||||
else if (num_threads_sharing == (c->x86_num_cores * smp_num_siblings))
|
||||
this_leaf->shared_cpu_map = cpu_core_map[cpu];
|
||||
else
|
||||
printk(KERN_INFO "Number of CPUs sharing cache didn't match "
|
||||
printk(KERN_DEBUG "Number of CPUs sharing cache didn't match "
|
||||
"any known set of CPUs\n");
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
|
||||
|
|
|
@ -561,7 +561,7 @@ struct mtrr_value {
|
|||
|
||||
static struct mtrr_value * mtrr_state;
|
||||
|
||||
static int mtrr_save(struct sys_device * sysdev, u32 state)
|
||||
static int mtrr_save(struct sys_device * sysdev, pm_message_t state)
|
||||
{
|
||||
int i;
|
||||
int size = num_var_ranges * sizeof(struct mtrr_value);
|
||||
|
|
|
@ -153,7 +153,7 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
|
|||
disable_local_APIC();
|
||||
atomic_dec(&waiting_for_crash_ipi);
|
||||
/* Assume hlt works */
|
||||
__asm__("hlt");
|
||||
halt();
|
||||
for(;;);
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -20,7 +20,7 @@ static void doublefault_fn(void)
|
|||
struct Xgt_desc_struct gdt_desc = {0, 0};
|
||||
unsigned long gdt, tss;
|
||||
|
||||
__asm__ __volatile__("sgdt %0": "=m" (gdt_desc): :"memory");
|
||||
store_gdt(&gdt_desc);
|
||||
gdt = gdt_desc.address;
|
||||
|
||||
printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
|
||||
|
|
|
@ -79,7 +79,7 @@ static void efi_call_phys_prelog(void)
|
|||
* directory. If I have PSE, I just need to duplicate one entry in
|
||||
* page directory.
|
||||
*/
|
||||
__asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
|
||||
cr4 = read_cr4();
|
||||
|
||||
if (cr4 & X86_CR4_PSE) {
|
||||
efi_bak_pg_dir_pointer[0].pgd =
|
||||
|
@ -104,8 +104,7 @@ static void efi_call_phys_prelog(void)
|
|||
local_flush_tlb();
|
||||
|
||||
cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
|
||||
__asm__ __volatile__("lgdt %0":"=m"
|
||||
(*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
|
||||
load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
|
||||
}
|
||||
|
||||
static void efi_call_phys_epilog(void)
|
||||
|
@ -114,8 +113,8 @@ static void efi_call_phys_epilog(void)
|
|||
|
||||
cpu_gdt_descr[0].address =
|
||||
(unsigned long) __va(cpu_gdt_descr[0].address);
|
||||
__asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr));
|
||||
__asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
|
||||
load_gdt(&cpu_gdt_descr[0]);
|
||||
cr4 = read_cr4();
|
||||
|
||||
if (cr4 & X86_CR4_PSE) {
|
||||
swapper_pg_dir[pgd_index(0)].pgd =
|
||||
|
@ -233,22 +232,23 @@ void __init efi_map_memmap(void)
|
|||
{
|
||||
memmap.map = NULL;
|
||||
|
||||
memmap.map = (efi_memory_desc_t *)
|
||||
bt_ioremap((unsigned long) memmap.phys_map,
|
||||
(memmap.nr_map * sizeof(efi_memory_desc_t)));
|
||||
|
||||
memmap.map = bt_ioremap((unsigned long) memmap.phys_map,
|
||||
(memmap.nr_map * memmap.desc_size));
|
||||
if (memmap.map == NULL)
|
||||
printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
|
||||
|
||||
memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
|
||||
}
|
||||
|
||||
#if EFI_DEBUG
|
||||
static void __init print_efi_memmap(void)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
void *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < memmap.nr_map; i++) {
|
||||
md = &memmap.map[i];
|
||||
for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
|
||||
md = p;
|
||||
printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
|
||||
"range=[0x%016llx-0x%016llx) (%lluMB)\n",
|
||||
i, md->type, md->attribute, md->phys_addr,
|
||||
|
@ -271,10 +271,10 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg)
|
|||
} prev, curr;
|
||||
efi_memory_desc_t *md;
|
||||
unsigned long start, end;
|
||||
int i;
|
||||
void *p;
|
||||
|
||||
for (i = 0; i < memmap.nr_map; i++) {
|
||||
md = &memmap.map[i];
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
|
||||
if ((md->num_pages == 0) || (!is_available_memory(md)))
|
||||
continue;
|
||||
|
@ -325,6 +325,7 @@ void __init efi_init(void)
|
|||
memmap.phys_map = EFI_MEMMAP;
|
||||
memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
|
||||
memmap.desc_version = EFI_MEMDESC_VERSION;
|
||||
memmap.desc_size = EFI_MEMDESC_SIZE;
|
||||
|
||||
efi.systab = (efi_system_table_t *)
|
||||
boot_ioremap((unsigned long) efi_phys.systab,
|
||||
|
@ -428,22 +429,30 @@ void __init efi_init(void)
|
|||
printk(KERN_ERR PFX "Could not map the runtime service table!\n");
|
||||
|
||||
/* Map the EFI memory map for use until paging_init() */
|
||||
|
||||
memmap.map = (efi_memory_desc_t *)
|
||||
boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
|
||||
|
||||
memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
|
||||
if (memmap.map == NULL)
|
||||
printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
|
||||
|
||||
if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) {
|
||||
printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't "
|
||||
"match the one from EFI!\n");
|
||||
}
|
||||
memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
|
||||
|
||||
#if EFI_DEBUG
|
||||
print_efi_memmap();
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void __init check_range_for_systab(efi_memory_desc_t *md)
|
||||
{
|
||||
if (((unsigned long)md->phys_addr <= (unsigned long)efi_phys.systab) &&
|
||||
((unsigned long)efi_phys.systab < md->phys_addr +
|
||||
((unsigned long)md->num_pages << EFI_PAGE_SHIFT))) {
|
||||
unsigned long addr;
|
||||
|
||||
addr = md->virt_addr - md->phys_addr +
|
||||
(unsigned long)efi_phys.systab;
|
||||
efi.systab = (efi_system_table_t *)addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will switch the EFI runtime services to virtual mode.
|
||||
* Essentially, look through the EFI memmap and map every region that
|
||||
|
@ -457,43 +466,32 @@ void __init efi_enter_virtual_mode(void)
|
|||
{
|
||||
efi_memory_desc_t *md;
|
||||
efi_status_t status;
|
||||
int i;
|
||||
void *p;
|
||||
|
||||
efi.systab = NULL;
|
||||
|
||||
for (i = 0; i < memmap.nr_map; i++) {
|
||||
md = &memmap.map[i];
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
|
||||
if (md->attribute & EFI_MEMORY_RUNTIME) {
|
||||
md->virt_addr =
|
||||
(unsigned long)ioremap(md->phys_addr,
|
||||
md->num_pages << EFI_PAGE_SHIFT);
|
||||
if (!(unsigned long)md->virt_addr) {
|
||||
printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
|
||||
(unsigned long)md->phys_addr);
|
||||
}
|
||||
if (!(md->attribute & EFI_MEMORY_RUNTIME))
|
||||
continue;
|
||||
|
||||
if (((unsigned long)md->phys_addr <=
|
||||
(unsigned long)efi_phys.systab) &&
|
||||
((unsigned long)efi_phys.systab <
|
||||
md->phys_addr +
|
||||
((unsigned long)md->num_pages <<
|
||||
EFI_PAGE_SHIFT))) {
|
||||
unsigned long addr;
|
||||
|
||||
addr = md->virt_addr - md->phys_addr +
|
||||
(unsigned long)efi_phys.systab;
|
||||
efi.systab = (efi_system_table_t *)addr;
|
||||
}
|
||||
md->virt_addr = (unsigned long)ioremap(md->phys_addr,
|
||||
md->num_pages << EFI_PAGE_SHIFT);
|
||||
if (!(unsigned long)md->virt_addr) {
|
||||
printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
|
||||
(unsigned long)md->phys_addr);
|
||||
}
|
||||
/* update the virtual address of the EFI system table */
|
||||
check_range_for_systab(md);
|
||||
}
|
||||
|
||||
if (!efi.systab)
|
||||
BUG();
|
||||
|
||||
status = phys_efi_set_virtual_address_map(
|
||||
sizeof(efi_memory_desc_t) * memmap.nr_map,
|
||||
sizeof(efi_memory_desc_t),
|
||||
memmap.desc_size * memmap.nr_map,
|
||||
memmap.desc_size,
|
||||
memmap.desc_version,
|
||||
memmap.phys_map);
|
||||
|
||||
|
@ -533,10 +531,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
|
|||
{
|
||||
struct resource *res;
|
||||
efi_memory_desc_t *md;
|
||||
int i;
|
||||
void *p;
|
||||
|
||||
for (i = 0; i < memmap.nr_map; i++) {
|
||||
md = &memmap.map[i];
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
|
||||
if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
|
||||
0x100000000ULL)
|
||||
|
@ -613,10 +611,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
|
|||
u32 efi_mem_type(unsigned long phys_addr)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
int i;
|
||||
void *p;
|
||||
|
||||
for (i = 0; i < memmap.nr_map; i++) {
|
||||
md = &memmap.map[i];
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
if ((md->phys_addr <= phys_addr) && (phys_addr <
|
||||
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
|
||||
return md->type;
|
||||
|
@ -627,10 +625,10 @@ u32 efi_mem_type(unsigned long phys_addr)
|
|||
u64 efi_mem_attributes(unsigned long phys_addr)
|
||||
{
|
||||
efi_memory_desc_t *md;
|
||||
int i;
|
||||
void *p;
|
||||
|
||||
for (i = 0; i < memmap.nr_map; i++) {
|
||||
md = &memmap.map[i];
|
||||
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||
md = p;
|
||||
if ((md->phys_addr <= phys_addr) && (phys_addr <
|
||||
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
|
||||
return md->attribute;
|
||||
|
|
|
@ -203,7 +203,7 @@ sysenter_past_esp:
|
|||
GET_THREAD_INFO(%ebp)
|
||||
|
||||
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
|
||||
testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
|
||||
testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
|
||||
jnz syscall_trace_entry
|
||||
cmpl $(nr_syscalls), %eax
|
||||
jae syscall_badsys
|
||||
|
@ -226,9 +226,9 @@ ENTRY(system_call)
|
|||
pushl %eax # save orig_eax
|
||||
SAVE_ALL
|
||||
GET_THREAD_INFO(%ebp)
|
||||
# system call tracing in operation
|
||||
# system call tracing in operation / emulation
|
||||
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
|
||||
testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
|
||||
testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
|
||||
jnz syscall_trace_entry
|
||||
cmpl $(nr_syscalls), %eax
|
||||
jae syscall_badsys
|
||||
|
@ -338,6 +338,9 @@ syscall_trace_entry:
|
|||
movl %esp, %eax
|
||||
xorl %edx,%edx
|
||||
call do_syscall_trace
|
||||
cmpl $0, %eax
|
||||
jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU,
|
||||
# so must skip actual syscall
|
||||
movl ORIG_EAX(%esp), %eax
|
||||
cmpl $(nr_syscalls), %eax
|
||||
jnae syscall_call
|
||||
|
|
|
@ -77,6 +77,32 @@ ENTRY(startup_32)
|
|||
subl %edi,%ecx
|
||||
shrl $2,%ecx
|
||||
rep ; stosl
|
||||
/*
|
||||
* Copy bootup parameters out of the way.
|
||||
* Note: %esi still has the pointer to the real-mode data.
|
||||
* With the kexec as boot loader, parameter segment might be loaded beyond
|
||||
* kernel image and might not even be addressable by early boot page tables.
|
||||
* (kexec on panic case). Hence copy out the parameters before initializing
|
||||
* page tables.
|
||||
*/
|
||||
movl $(boot_params - __PAGE_OFFSET),%edi
|
||||
movl $(PARAM_SIZE/4),%ecx
|
||||
cld
|
||||
rep
|
||||
movsl
|
||||
movl boot_params - __PAGE_OFFSET + NEW_CL_POINTER,%esi
|
||||
andl %esi,%esi
|
||||
jnz 2f # New command line protocol
|
||||
cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
|
||||
jne 1f
|
||||
movzwl OLD_CL_OFFSET,%esi
|
||||
addl $(OLD_CL_BASE_ADDR),%esi
|
||||
2:
|
||||
movl $(saved_command_line - __PAGE_OFFSET),%edi
|
||||
movl $(COMMAND_LINE_SIZE/4),%ecx
|
||||
rep
|
||||
movsl
|
||||
1:
|
||||
|
||||
/*
|
||||
* Initialize page tables. This creates a PDE and a set of page
|
||||
|
@ -214,28 +240,6 @@ ENTRY(startup_32_smp)
|
|||
*/
|
||||
call setup_idt
|
||||
|
||||
/*
|
||||
* Copy bootup parameters out of the way.
|
||||
* Note: %esi still has the pointer to the real-mode data.
|
||||
*/
|
||||
movl $boot_params,%edi
|
||||
movl $(PARAM_SIZE/4),%ecx
|
||||
cld
|
||||
rep
|
||||
movsl
|
||||
movl boot_params+NEW_CL_POINTER,%esi
|
||||
andl %esi,%esi
|
||||
jnz 2f # New command line protocol
|
||||
cmpw $(OLD_CL_MAGIC),OLD_CL_MAGIC_ADDR
|
||||
jne 1f
|
||||
movzwl OLD_CL_OFFSET,%esi
|
||||
addl $(OLD_CL_BASE_ADDR),%esi
|
||||
2:
|
||||
movl $saved_command_line,%edi
|
||||
movl $(COMMAND_LINE_SIZE/4),%ecx
|
||||
rep
|
||||
movsl
|
||||
1:
|
||||
checkCPUtype:
|
||||
|
||||
movl $-1,X86_CPUID # -1 for no CPUID initially
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* i8237.c: 8237A DMA controller suspend functions.
|
||||
*
|
||||
* Written by Pierre Ossman, 2005.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
|
||||
/*
|
||||
* This module just handles suspend/resume issues with the
|
||||
* 8237A DMA controller (used for ISA and LPC).
|
||||
* Allocation is handled in kernel/dma.c and normal usage is
|
||||
* in asm/dma.h.
|
||||
*/
|
||||
|
||||
static int i8237A_resume(struct sys_device *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
flags = claim_dma_lock();
|
||||
|
||||
dma_outb(DMA1_RESET_REG, 0);
|
||||
dma_outb(DMA2_RESET_REG, 0);
|
||||
|
||||
for (i = 0;i < 8;i++) {
|
||||
set_dma_addr(i, 0x000000);
|
||||
/* DMA count is a bit weird so this is not 0 */
|
||||
set_dma_count(i, 1);
|
||||
}
|
||||
|
||||
/* Enable cascade DMA or channel 0-3 won't work */
|
||||
enable_dma(4);
|
||||
|
||||
release_dma_lock(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i8237A_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class i8237_sysdev_class = {
|
||||
set_kset_name("i8237"),
|
||||
.suspend = i8237A_suspend,
|
||||
.resume = i8237A_resume,
|
||||
};
|
||||
|
||||
static struct sys_device device_i8237A = {
|
||||
.id = 0,
|
||||
.cls = &i8237_sysdev_class,
|
||||
};
|
||||
|
||||
static int __init i8237A_init_sysfs(void)
|
||||
{
|
||||
int error = sysdev_class_register(&i8237_sysdev_class);
|
||||
if (!error)
|
||||
error = sysdev_register(&device_i8237A);
|
||||
return error;
|
||||
}
|
||||
|
||||
device_initcall(i8237A_init_sysfs);
|
|
@ -132,6 +132,7 @@ asmlinkage long sys_iopl(unsigned long unused)
|
|||
volatile struct pt_regs * regs = (struct pt_regs *) &unused;
|
||||
unsigned int level = regs->ebx;
|
||||
unsigned int old = (regs->eflags >> 12) & 3;
|
||||
struct thread_struct *t = ¤t->thread;
|
||||
|
||||
if (level > 3)
|
||||
return -EINVAL;
|
||||
|
@ -140,8 +141,8 @@ asmlinkage long sys_iopl(unsigned long unused)
|
|||
if (!capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
}
|
||||
regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
|
||||
/* Make sure we return the long way (not sysenter) */
|
||||
set_thread_flag(TIF_IRET);
|
||||
t->iopl = level << 12;
|
||||
regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
|
||||
set_iopl_mask(t->iopl);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ static int read_default_ldt(void __user * ptr, unsigned long bytecount)
|
|||
static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
|
||||
{
|
||||
struct mm_struct * mm = current->mm;
|
||||
__u32 entry_1, entry_2, *lp;
|
||||
__u32 entry_1, entry_2;
|
||||
int error;
|
||||
struct user_desc ldt_info;
|
||||
|
||||
|
@ -205,8 +205,6 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
|
||||
|
||||
/* Allow LDTs to be cleared by the user. */
|
||||
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
|
||||
if (oldmode || LDT_empty(&ldt_info)) {
|
||||
|
@ -223,8 +221,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
|
|||
|
||||
/* Install the new entry ... */
|
||||
install:
|
||||
*lp = entry_1;
|
||||
*(lp+1) = entry_2;
|
||||
write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, entry_2);
|
||||
error = 0;
|
||||
|
||||
out_unlock:
|
||||
|
|
|
@ -17,13 +17,7 @@
|
|||
#include <asm/apic.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/desc.h>
|
||||
|
||||
static inline unsigned long read_cr3(void)
|
||||
{
|
||||
unsigned long cr3;
|
||||
asm volatile("movl %%cr3,%0": "=r"(cr3));
|
||||
return cr3;
|
||||
}
|
||||
#include <asm/system.h>
|
||||
|
||||
#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
|
||||
|
||||
|
@ -99,10 +93,7 @@ static void set_idt(void *newidt, __u16 limit)
|
|||
curidt.size = limit;
|
||||
curidt.address = (unsigned long)newidt;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"lidtl %0\n"
|
||||
: : "m" (curidt)
|
||||
);
|
||||
load_idt(&curidt);
|
||||
};
|
||||
|
||||
|
||||
|
@ -114,10 +105,7 @@ static void set_gdt(void *newgdt, __u16 limit)
|
|||
curgdt.size = limit;
|
||||
curgdt.address = (unsigned long)newgdt;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"lgdtl %0\n"
|
||||
: : "m" (curgdt)
|
||||
);
|
||||
load_gdt(&curgdt);
|
||||
};
|
||||
|
||||
static void load_segments(void)
|
||||
|
|
|
@ -164,7 +164,8 @@ static void collect_cpu_info (void *unused)
|
|||
}
|
||||
|
||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
|
||||
/* see notes above for revision 1.07. Apparent chip bug */
|
||||
serialize_cpu();
|
||||
/* get the current revision from MSR 0x8B */
|
||||
rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
|
||||
pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
|
||||
|
@ -377,7 +378,9 @@ static void do_update_one (void * unused)
|
|||
(unsigned long) uci->mc->bits >> 16 >> 16);
|
||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
||||
|
||||
__asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
|
||||
/* see notes above for revision 1.07. Apparent chip bug */
|
||||
serialize_cpu();
|
||||
|
||||
/* get the current revision from MSR 0x8B */
|
||||
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ int nr_ioapics;
|
|||
int pic_mode;
|
||||
unsigned long mp_lapic_addr;
|
||||
|
||||
unsigned int def_to_bigsmp = 0;
|
||||
|
||||
/* Processor that is doing the boot up */
|
||||
unsigned int boot_cpu_physical_apicid = -1U;
|
||||
/* Internal processor count */
|
||||
|
@ -120,7 +122,7 @@ static int MP_valid_apicid(int apicid, int version)
|
|||
|
||||
static void __init MP_processor_info (struct mpc_config_processor *m)
|
||||
{
|
||||
int ver, apicid;
|
||||
int ver, apicid, cpu, found_bsp = 0;
|
||||
physid_mask_t tmp;
|
||||
|
||||
if (!(m->mpc_cpuflag & CPU_ENABLED))
|
||||
|
@ -179,6 +181,7 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
|
|||
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
|
||||
Dprintk(" Bootup CPU\n");
|
||||
boot_cpu_physical_apicid = m->mpc_apicid;
|
||||
found_bsp = 1;
|
||||
}
|
||||
|
||||
if (num_processors >= NR_CPUS) {
|
||||
|
@ -202,6 +205,11 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
|
|||
return;
|
||||
}
|
||||
|
||||
if (found_bsp)
|
||||
cpu = 0;
|
||||
else
|
||||
cpu = num_processors - 1;
|
||||
cpu_set(cpu, cpu_possible_map);
|
||||
tmp = apicid_to_cpu_present(apicid);
|
||||
physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
|
||||
|
||||
|
@ -213,6 +221,13 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
|
|||
ver = 0x10;
|
||||
}
|
||||
apic_version[m->mpc_apicid] = ver;
|
||||
if ((num_processors > 8) &&
|
||||
APIC_XAPIC(ver) &&
|
||||
(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL))
|
||||
def_to_bigsmp = 1;
|
||||
else
|
||||
def_to_bigsmp = 0;
|
||||
|
||||
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,23 +46,13 @@
|
|||
|
||||
static struct class *msr_class;
|
||||
|
||||
/* Note: "err" is handled in a funny way below. Otherwise one version
|
||||
of gcc or another breaks. */
|
||||
|
||||
static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
|
||||
{
|
||||
int err;
|
||||
|
||||
asm volatile ("1: wrmsr\n"
|
||||
"2:\n"
|
||||
".section .fixup,\"ax\"\n"
|
||||
"3: movl %4,%0\n"
|
||||
" jmp 2b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
" .align 4\n" " .long 1b,3b\n" ".previous":"=&bDS" (err)
|
||||
:"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0));
|
||||
|
||||
err = wrmsr_safe(reg, eax, edx);
|
||||
if (err)
|
||||
err = -EIO;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -70,18 +60,9 @@ static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
|
|||
{
|
||||
int err;
|
||||
|
||||
asm volatile ("1: rdmsr\n"
|
||||
"2:\n"
|
||||
".section .fixup,\"ax\"\n"
|
||||
"3: movl %4,%0\n"
|
||||
" jmp 2b\n"
|
||||
".previous\n"
|
||||
".section __ex_table,\"a\"\n"
|
||||
" .align 4\n"
|
||||
" .long 1b,3b\n"
|
||||
".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx)
|
||||
:"c"(reg), "i"(-EIO), "0"(0));
|
||||
|
||||
err = rdmsr_safe(reg, eax, edx);
|
||||
if (err)
|
||||
err = -EIO;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -501,8 +501,11 @@ void nmi_watchdog_tick (struct pt_regs * regs)
|
|||
*/
|
||||
alert_counter[cpu]++;
|
||||
if (alert_counter[cpu] == 5*nmi_hz)
|
||||
/*
|
||||
* die_nmi will return ONLY if NOTIFY_STOP happens..
|
||||
*/
|
||||
die_nmi(regs, "NMI Watchdog detected LOCKUP");
|
||||
} else {
|
||||
|
||||
last_irq_sums[cpu] = sum;
|
||||
alert_counter[cpu] = 0;
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ static inline void play_dead(void)
|
|||
*/
|
||||
local_irq_disable();
|
||||
while (1)
|
||||
__asm__ __volatile__("hlt":::"memory");
|
||||
halt();
|
||||
}
|
||||
#else
|
||||
static inline void play_dead(void)
|
||||
|
@ -313,16 +313,12 @@ void show_regs(struct pt_regs * regs)
|
|||
printk(" DS: %04x ES: %04x\n",
|
||||
0xffff & regs->xds,0xffff & regs->xes);
|
||||
|
||||
__asm__("movl %%cr0, %0": "=r" (cr0));
|
||||
__asm__("movl %%cr2, %0": "=r" (cr2));
|
||||
__asm__("movl %%cr3, %0": "=r" (cr3));
|
||||
/* This could fault if %cr4 does not exist */
|
||||
__asm__("1: movl %%cr4, %0 \n"
|
||||
"2: \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
".long 1b,2b \n"
|
||||
".previous \n"
|
||||
: "=r" (cr4): "0" (0));
|
||||
cr0 = read_cr0();
|
||||
cr2 = read_cr2();
|
||||
cr3 = read_cr3();
|
||||
if (current_cpu_data.x86 > 4) {
|
||||
cr4 = read_cr4();
|
||||
}
|
||||
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
|
||||
show_trace(NULL, ®s->esp);
|
||||
}
|
||||
|
@ -682,22 +678,27 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
|||
__unlazy_fpu(prev_p);
|
||||
|
||||
/*
|
||||
* Reload esp0, LDT and the page table pointer:
|
||||
* Reload esp0.
|
||||
*/
|
||||
load_esp0(tss, next);
|
||||
|
||||
/*
|
||||
* Save away %fs and %gs. No need to save %es and %ds, as
|
||||
* those are always kernel segments while inside the kernel.
|
||||
* Doing this before setting the new TLS descriptors avoids
|
||||
* the situation where we temporarily have non-reloadable
|
||||
* segments in %fs and %gs. This could be an issue if the
|
||||
* NMI handler ever used %fs or %gs (it does not today), or
|
||||
* if the kernel is running inside of a hypervisor layer.
|
||||
*/
|
||||
savesegment(fs, prev->fs);
|
||||
savesegment(gs, prev->gs);
|
||||
|
||||
/*
|
||||
* Load the per-thread Thread-Local Storage descriptor.
|
||||
*/
|
||||
load_TLS(next, cpu);
|
||||
|
||||
/*
|
||||
* Save away %fs and %gs. No need to save %es and %ds, as
|
||||
* those are always kernel segments while inside the kernel.
|
||||
*/
|
||||
asm volatile("mov %%fs,%0":"=m" (prev->fs));
|
||||
asm volatile("mov %%gs,%0":"=m" (prev->gs));
|
||||
|
||||
/*
|
||||
* Restore %fs and %gs if needed.
|
||||
*
|
||||
|
@ -710,6 +711,12 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
|||
if (prev->gs | next->gs)
|
||||
loadsegment(gs, next->gs);
|
||||
|
||||
/*
|
||||
* Restore IOPL if needed.
|
||||
*/
|
||||
if (unlikely(prev->iopl != next->iopl))
|
||||
set_iopl_mask(next->iopl);
|
||||
|
||||
/*
|
||||
* Now maybe reload the debug registers
|
||||
*/
|
||||
|
|
|
@ -271,6 +271,8 @@ static void clear_singlestep(struct task_struct *child)
|
|||
void ptrace_disable(struct task_struct *child)
|
||||
{
|
||||
clear_singlestep(child);
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -509,15 +511,20 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
|
|||
}
|
||||
break;
|
||||
|
||||
case PTRACE_SYSEMU: /* continue and stop at next syscall, which will not be executed */
|
||||
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
|
||||
case PTRACE_CONT: /* restart after signal. */
|
||||
ret = -EIO;
|
||||
if (!valid_signal(data))
|
||||
break;
|
||||
if (request == PTRACE_SYSCALL) {
|
||||
if (request == PTRACE_SYSEMU) {
|
||||
set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
} else if (request == PTRACE_SYSCALL) {
|
||||
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
}
|
||||
else {
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||
} else {
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
}
|
||||
child->exit_code = data;
|
||||
|
@ -542,10 +549,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
|
|||
wake_up_process(child);
|
||||
break;
|
||||
|
||||
case PTRACE_SYSEMU_SINGLESTEP: /* Same as SYSEMU, but singlestep if not syscall */
|
||||
case PTRACE_SINGLESTEP: /* set the trap flag. */
|
||||
ret = -EIO;
|
||||
if (!valid_signal(data))
|
||||
break;
|
||||
|
||||
if (request == PTRACE_SYSEMU_SINGLESTEP)
|
||||
set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||
else
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
set_singlestep(child);
|
||||
child->exit_code = data;
|
||||
|
@ -678,26 +692,52 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
|
|||
* - triggered by current->work.syscall_trace
|
||||
*/
|
||||
__attribute__((regparm(3)))
|
||||
void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
||||
int do_syscall_trace(struct pt_regs *regs, int entryexit)
|
||||
{
|
||||
int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU), ret = 0;
|
||||
/* With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP for syscall
|
||||
* interception. */
|
||||
int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP);
|
||||
|
||||
/* do the secure computing check first */
|
||||
secure_computing(regs->orig_eax);
|
||||
|
||||
if (unlikely(current->audit_context) && entryexit)
|
||||
audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
|
||||
if (unlikely(current->audit_context)) {
|
||||
if (entryexit)
|
||||
audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
|
||||
/* Debug traps, when using PTRACE_SINGLESTEP, must be sent only
|
||||
* on the syscall exit path. Normally, when TIF_SYSCALL_AUDIT is
|
||||
* not used, entry.S will call us only on syscall exit, not
|
||||
* entry; so when TIF_SYSCALL_AUDIT is used we must avoid
|
||||
* calling send_sigtrap() on syscall entry.
|
||||
*
|
||||
* Note that when PTRACE_SYSEMU_SINGLESTEP is used,
|
||||
* is_singlestep is false, despite his name, so we will still do
|
||||
* the correct thing.
|
||||
*/
|
||||
else if (is_singlestep)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(current->ptrace & PT_PTRACED))
|
||||
goto out;
|
||||
|
||||
/* If a process stops on the 1st tracepoint with SYSCALL_TRACE
|
||||
* and then is resumed with SYSEMU_SINGLESTEP, it will come in
|
||||
* here. We have to check this and return */
|
||||
if (is_sysemu && entryexit)
|
||||
return 0;
|
||||
|
||||
/* Fake a debug trap */
|
||||
if (test_thread_flag(TIF_SINGLESTEP))
|
||||
if (is_singlestep)
|
||||
send_sigtrap(current, regs, 0);
|
||||
|
||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu)
|
||||
goto out;
|
||||
|
||||
/* the 0x80 provides a way for the tracing parent to distinguish
|
||||
between a syscall stop and SIGTRAP delivery */
|
||||
/* Note that the debugger could change the result of test_thread_flag!*/
|
||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
|
||||
|
||||
/*
|
||||
|
@ -709,9 +749,16 @@ void do_syscall_trace(struct pt_regs *regs, int entryexit)
|
|||
send_sig(current->exit_code, current, 1);
|
||||
current->exit_code = 0;
|
||||
}
|
||||
ret = is_sysemu;
|
||||
out:
|
||||
if (unlikely(current->audit_context) && !entryexit)
|
||||
audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
|
||||
regs->ebx, regs->ecx, regs->edx, regs->esi);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
|
||||
regs->orig_eax = -1; /* force skip of syscall restarting */
|
||||
if (unlikely(current->audit_context))
|
||||
audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/dmi.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/desc.h>
|
||||
#include "mach_reboot.h"
|
||||
#include <linux/reboot_fixups.h>
|
||||
|
||||
|
@ -242,13 +243,13 @@ void machine_real_restart(unsigned char *code, int length)
|
|||
|
||||
/* Set up the IDT for real mode. */
|
||||
|
||||
__asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
|
||||
load_idt(&real_mode_idt);
|
||||
|
||||
/* Set up a GDT from which we can load segment descriptors for real
|
||||
mode. The GDT is not used in real mode; it is just needed here to
|
||||
prepare the descriptors. */
|
||||
|
||||
__asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt));
|
||||
load_gdt(&real_mode_gdt);
|
||||
|
||||
/* Load the data segment registers, and thus the descriptors ready for
|
||||
real mode. The base address of each segment is 0x100, 16 times the
|
||||
|
@ -316,7 +317,7 @@ void machine_emergency_restart(void)
|
|||
if (!reboot_thru_bios) {
|
||||
if (efi_enabled) {
|
||||
efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
|
||||
__asm__ __volatile__("lidt %0": :"m" (no_idt));
|
||||
load_idt(&no_idt);
|
||||
__asm__ __volatile__("int3");
|
||||
}
|
||||
/* rebooting needs to touch the page at absolute addr 0 */
|
||||
|
@ -325,7 +326,7 @@ void machine_emergency_restart(void)
|
|||
mach_reboot_fixups(); /* for board specific fixups */
|
||||
mach_reboot();
|
||||
/* That didn't work - force a triple fault.. */
|
||||
__asm__ __volatile__("lidt %0": :"m" (no_idt));
|
||||
load_idt(&no_idt);
|
||||
__asm__ __volatile__("int3");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,170 +13,8 @@
|
|||
* rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
|
||||
*/
|
||||
#include <linux/config.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
/*
|
||||
* Semaphores are implemented using a two-way counter:
|
||||
* The "count" variable is decremented for each process
|
||||
* that tries to acquire the semaphore, while the "sleeping"
|
||||
* variable is a count of such acquires.
|
||||
*
|
||||
* Notably, the inline "up()" and "down()" functions can
|
||||
* efficiently test if they need to do any extra work (up
|
||||
* needs to do something only if count was negative before
|
||||
* the increment operation.
|
||||
*
|
||||
* "sleeping" and the contention routine ordering is protected
|
||||
* by the spinlock in the semaphore's waitqueue head.
|
||||
*
|
||||
* Note that these functions are only called when there is
|
||||
* contention on the lock, and as such all this is the
|
||||
* "non-critical" part of the whole semaphore business. The
|
||||
* critical part is the inline stuff in <asm/semaphore.h>
|
||||
* where we want to avoid any extra jumps and calls.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Logic:
|
||||
* - only on a boundary condition do we need to care. When we go
|
||||
* from a negative count to a non-negative, we wake people up.
|
||||
* - when we go from a non-negative count to a negative do we
|
||||
* (a) synchronize with the "sleeper" count and (b) make sure
|
||||
* that we're on the wakeup list before we synchronize so that
|
||||
* we cannot lose wakeup events.
|
||||
*/
|
||||
|
||||
static fastcall void __attribute_used__ __up(struct semaphore *sem)
|
||||
{
|
||||
wake_up(&sem->wait);
|
||||
}
|
||||
|
||||
static fastcall void __attribute_used__ __sched __down(struct semaphore * sem)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
DECLARE_WAITQUEUE(wait, tsk);
|
||||
unsigned long flags;
|
||||
|
||||
tsk->state = TASK_UNINTERRUPTIBLE;
|
||||
spin_lock_irqsave(&sem->wait.lock, flags);
|
||||
add_wait_queue_exclusive_locked(&sem->wait, &wait);
|
||||
|
||||
sem->sleepers++;
|
||||
for (;;) {
|
||||
int sleepers = sem->sleepers;
|
||||
|
||||
/*
|
||||
* Add "everybody else" into it. They aren't
|
||||
* playing, because we own the spinlock in
|
||||
* the wait_queue_head.
|
||||
*/
|
||||
if (!atomic_add_negative(sleepers - 1, &sem->count)) {
|
||||
sem->sleepers = 0;
|
||||
break;
|
||||
}
|
||||
sem->sleepers = 1; /* us - see -1 above */
|
||||
spin_unlock_irqrestore(&sem->wait.lock, flags);
|
||||
|
||||
schedule();
|
||||
|
||||
spin_lock_irqsave(&sem->wait.lock, flags);
|
||||
tsk->state = TASK_UNINTERRUPTIBLE;
|
||||
}
|
||||
remove_wait_queue_locked(&sem->wait, &wait);
|
||||
wake_up_locked(&sem->wait);
|
||||
spin_unlock_irqrestore(&sem->wait.lock, flags);
|
||||
tsk->state = TASK_RUNNING;
|
||||
}
|
||||
|
||||
static fastcall int __attribute_used__ __sched __down_interruptible(struct semaphore * sem)
|
||||
{
|
||||
int retval = 0;
|
||||
struct task_struct *tsk = current;
|
||||
DECLARE_WAITQUEUE(wait, tsk);
|
||||
unsigned long flags;
|
||||
|
||||
tsk->state = TASK_INTERRUPTIBLE;
|
||||
spin_lock_irqsave(&sem->wait.lock, flags);
|
||||
add_wait_queue_exclusive_locked(&sem->wait, &wait);
|
||||
|
||||
sem->sleepers++;
|
||||
for (;;) {
|
||||
int sleepers = sem->sleepers;
|
||||
|
||||
/*
|
||||
* With signals pending, this turns into
|
||||
* the trylock failure case - we won't be
|
||||
* sleeping, and we* can't get the lock as
|
||||
* it has contention. Just correct the count
|
||||
* and exit.
|
||||
*/
|
||||
if (signal_pending(current)) {
|
||||
retval = -EINTR;
|
||||
sem->sleepers = 0;
|
||||
atomic_add(sleepers, &sem->count);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add "everybody else" into it. They aren't
|
||||
* playing, because we own the spinlock in
|
||||
* wait_queue_head. The "-1" is because we're
|
||||
* still hoping to get the semaphore.
|
||||
*/
|
||||
if (!atomic_add_negative(sleepers - 1, &sem->count)) {
|
||||
sem->sleepers = 0;
|
||||
break;
|
||||
}
|
||||
sem->sleepers = 1; /* us - see -1 above */
|
||||
spin_unlock_irqrestore(&sem->wait.lock, flags);
|
||||
|
||||
schedule();
|
||||
|
||||
spin_lock_irqsave(&sem->wait.lock, flags);
|
||||
tsk->state = TASK_INTERRUPTIBLE;
|
||||
}
|
||||
remove_wait_queue_locked(&sem->wait, &wait);
|
||||
wake_up_locked(&sem->wait);
|
||||
spin_unlock_irqrestore(&sem->wait.lock, flags);
|
||||
|
||||
tsk->state = TASK_RUNNING;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Trylock failed - make sure we correct for
|
||||
* having decremented the count.
|
||||
*
|
||||
* We could have done the trylock with a
|
||||
* single "cmpxchg" without failure cases,
|
||||
* but then it wouldn't work on a 386.
|
||||
*/
|
||||
static fastcall int __attribute_used__ __down_trylock(struct semaphore * sem)
|
||||
{
|
||||
int sleepers;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&sem->wait.lock, flags);
|
||||
sleepers = sem->sleepers + 1;
|
||||
sem->sleepers = 0;
|
||||
|
||||
/*
|
||||
* Add "everybody else" and us into it. They aren't
|
||||
* playing, because we own the spinlock in the
|
||||
* wait_queue_head.
|
||||
*/
|
||||
if (!atomic_add_negative(sleepers, &sem->count)) {
|
||||
wake_up_locked(&sem->wait);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&sem->wait.lock, flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The semaphore operations have a special calling sequence that
|
||||
* allow us to do a simpler in-line version of them. These routines
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue