Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
This commit is contained in:
commit
c08319a9d5
1339 changed files with 70020 additions and 27922 deletions
|
@ -223,6 +223,7 @@ CAST5 algorithm contributors:
|
||||||
|
|
||||||
TEA/XTEA algorithm contributors:
|
TEA/XTEA algorithm contributors:
|
||||||
Aaron Grothe
|
Aaron Grothe
|
||||||
|
Michael Ringe
|
||||||
|
|
||||||
Khazad algorithm contributors:
|
Khazad algorithm contributors:
|
||||||
Aaron Grothe
|
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
|
What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
|
||||||
When: November 2005
|
When: November 2005
|
||||||
Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
|
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
|
statm Process memory status information
|
||||||
status Process status in human readable form
|
status Process status in human readable form
|
||||||
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
|
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
|
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:
|
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 = { \
|
struct device_attribute dev_attr_##_name = { \
|
||||||
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
.attr = {.name = __stringify(_name) , .mode = _mode }, \
|
||||||
.show = _show, \
|
.show = _show, \
|
||||||
|
@ -99,14 +99,14 @@ struct device_attribute dev_attr_##_name = { \
|
||||||
|
|
||||||
For example, declaring
|
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:
|
is equivalent to doing:
|
||||||
|
|
||||||
static struct device_attribute dev_attr_foo = {
|
static struct device_attribute dev_attr_foo = {
|
||||||
.attr = {
|
.attr = {
|
||||||
.name = "foo",
|
.name = "foo",
|
||||||
.mode = 0644,
|
.mode = S_IWUSR | S_IRUGO,
|
||||||
},
|
},
|
||||||
.show = show_foo,
|
.show = show_foo,
|
||||||
.store = store_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.
|
show and store methods of the attribute owners.
|
||||||
|
|
||||||
struct sysfs_ops {
|
struct sysfs_ops {
|
||||||
ssize_t (*show)(struct kobject *, struct attribute *,char *);
|
ssize_t (*show)(struct kobject *, struct attribute *, char *);
|
||||||
ssize_t (*store)(struct kobject *,struct attribute *,const char *);
|
ssize_t (*store)(struct kobject *, struct attribute *, const char *);
|
||||||
};
|
};
|
||||||
|
|
||||||
[ Subsystems should have already defined a struct kobj_type as a
|
[ Subsystems should have already defined a struct kobj_type as a
|
||||||
|
@ -137,7 +137,7 @@ calls the associated methods.
|
||||||
|
|
||||||
To illustrate:
|
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)
|
#define to_dev(d) container_of(d, struct device, kobj)
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
|
@ -148,7 +148,7 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
|
|
||||||
if (dev_attr->show)
|
if (dev_attr->show)
|
||||||
ret = dev_attr->show(dev,buf);
|
ret = dev_attr->show(dev, buf);
|
||||||
return ret;
|
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)
|
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)
|
static ssize_t store_name(struct device * dev, const char * buf)
|
||||||
{
|
{
|
||||||
sscanf(buf,"%20s",dev->name);
|
sscanf(buf, "%20s", dev->name);
|
||||||
return strlen(buf);
|
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
|
(Note that the real implementation doesn't allow userspace to set the
|
||||||
|
@ -290,7 +290,7 @@ struct device_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
DEVICE_ATTR(_name,_str,_mode,_show,_store);
|
DEVICE_ATTR(_name, _str, _mode, _show, _store);
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
@ -310,7 +310,7 @@ struct bus_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
BUS_ATTR(_name,_mode,_show,_store)
|
BUS_ATTR(_name, _mode, _show, _store)
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
@ -331,7 +331,7 @@ struct driver_attribute {
|
||||||
|
|
||||||
Declaring:
|
Declaring:
|
||||||
|
|
||||||
DRIVER_ATTR(_name,_mode,_show,_store)
|
DRIVER_ATTR(_name, _mode, _show, _store)
|
||||||
|
|
||||||
Creation/Removal:
|
Creation/Removal:
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,11 @@ Kernel driver lm78
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Supported chips:
|
Supported chips:
|
||||||
* National Semiconductor LM78
|
* National Semiconductor LM78 / LM78-J
|
||||||
Prefix: 'lm78'
|
Prefix: 'lm78'
|
||||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||||
Datasheet: Publicly available at the National Semiconductor website
|
Datasheet: Publicly available at the National Semiconductor website
|
||||||
http://www.national.com/
|
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
|
* National Semiconductor LM79
|
||||||
Prefix: 'lm79'
|
Prefix: 'lm79'
|
||||||
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
|
||||||
|
|
174
Documentation/hwmon/w83792d
Normal file
174
Documentation/hwmon/w83792d
Normal file
|
@ -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:
|
Supported chips:
|
||||||
* Maxim MAX6874, MAX6875
|
* Maxim MAX6874, MAX6875
|
||||||
Prefix: 'max6875'
|
Prefix: 'max6875'
|
||||||
Addresses scanned: 0x50, 0x52
|
Addresses scanned: None (see below)
|
||||||
Datasheet:
|
Datasheet:
|
||||||
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
|
http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
|
||||||
|
|
||||||
Author: Ben Gardner <bgardner@wabtec.com>
|
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
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
@ -33,34 +24,85 @@ registers.
|
||||||
|
|
||||||
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
|
The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
|
||||||
and outputs:
|
and outputs:
|
||||||
|
|
||||||
vin gpi vout
|
vin gpi vout
|
||||||
MAX6874 6 4 8
|
MAX6874 6 4 8
|
||||||
MAX6875 4 3 5
|
MAX6875 4 3 5
|
||||||
|
|
||||||
MAX6874 chips can have four different addresses (as opposed to only two for
|
See the datasheet for more information.
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
Sysfs entries
|
Sysfs entries
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
|
eeprom - 512 bytes of user-defined EEPROM space.
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
General Remarks
|
General Remarks
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
A typical application will require that the EEPROMs be programmed once and
|
Valid addresses for the MAX6875 are 0x50 and 0x52.
|
||||||
never altered afterwards.
|
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
|
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
|
to use the /dev interface. You will still have to check whether the
|
||||||
functionality you need is supported, of course. This is done using
|
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:
|
program, is below:
|
||||||
|
|
||||||
int file;
|
int file;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Revision 4, 2004-03-30
|
Revision 5, 2005-07-29
|
||||||
Jean Delvare <khali@linux-fr.org>
|
Jean Delvare <khali@linux-fr.org>
|
||||||
Greg KH <greg@kroah.com>
|
Greg KH <greg@kroah.com>
|
||||||
|
|
||||||
|
@ -17,20 +17,22 @@ yours for best results.
|
||||||
|
|
||||||
Technical changes:
|
Technical changes:
|
||||||
|
|
||||||
* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
|
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||||
<linux/i2c-sensor.h>. Includes typically look like that:
|
Includes typically look like that:
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-sensor.h>
|
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||||
#include <linux/i2c-vid.h> /* if you need VRM support */
|
#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 */
|
#include <asm/io.h> /* if you have I/O operations */
|
||||||
Please respect this inclusion order. Some extra headers may be
|
Please respect this inclusion order. Some extra headers may be
|
||||||
required for a given driver (e.g. "lm75.h").
|
required for a given driver (e.g. "lm75.h").
|
||||||
|
|
||||||
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
|
* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
|
||||||
becomes I2C_CLIENT_ISA_END.
|
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
|
* [Client data] Get rid of sysctl_id. Try using standard names for
|
||||||
register values (for example, temp_os becomes temp_max). You're
|
register values (for example, temp_os becomes temp_max). You're
|
||||||
|
@ -66,13 +68,15 @@ Technical changes:
|
||||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||||
return 0;
|
return 0;
|
||||||
ISA-only drivers of course don't need this.
|
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.
|
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||||
The type_name and client_name strings are replaced by a single
|
The type_name and client_name strings are replaced by a single
|
||||||
name string, which will be filled with a lowercase, short string
|
name string, which will be filled with a lowercase, short string
|
||||||
(typically the driver name, e.g. "lm75").
|
(typically the driver name, e.g. "lm75").
|
||||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
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
|
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
|
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
|
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
|
device_create_file. Move the driver initialization before any
|
||||||
sysfs file creation.
|
sysfs file creation.
|
||||||
Drop client->id.
|
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
|
* [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
|
user-space). Chip should not be reset default (although a module
|
||||||
|
@ -93,7 +99,8 @@ Technical changes:
|
||||||
limited to the strictly necessary steps.
|
limited to the strictly necessary steps.
|
||||||
|
|
||||||
* [Detach] Get rid of data, remove the call to
|
* [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
|
* [Update] Don't access client->data directly, use
|
||||||
i2c_get_clientdata(client) instead.
|
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.
|
detection algorithm.
|
||||||
|
|
||||||
You do not have to use this parameter interface; but don't try to use
|
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
|
NOTE: If you want to write a `sensors' driver, the interface is slightly
|
||||||
different! See below.
|
different! See below.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Probing classes (i2c)
|
Probing classes
|
||||||
---------------------
|
---------------
|
||||||
|
|
||||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||||
terminated by I2C_CLIENT_END.
|
terminated by I2C_CLIENT_END.
|
||||||
|
@ -171,12 +171,18 @@ The following lists are used internally:
|
||||||
ignore: insmod parameter.
|
ignore: insmod parameter.
|
||||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
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.
|
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.
|
force: insmod parameter.
|
||||||
A list of pairs. The first value is a bus number (-1 for any I2C bus),
|
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 second is the I2C address. A device is blindly assumed to be on
|
||||||
the given address, no probing is done.
|
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'
|
Fortunately, as a module writer, you just have to define the `normal_i2c'
|
||||||
parameter. The complete declaration could look like this:
|
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 */
|
/* Magic definition of all other variables and things */
|
||||||
I2C_CLIENT_INSMOD;
|
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',
|
Note that you *have* to call the defined variable `normal_i2c',
|
||||||
without any prefix!
|
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
|
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);
|
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,
|
Remember, structure `addr_data' is defined by the macros explained above,
|
||||||
so you do not have to define it yourself.
|
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
|
function only for those i2c addresses that actually have a device on
|
||||||
them (unless a `force' parameter was used). In addition, addresses that
|
them (unless a `force' parameter was used). In addition, addresses that
|
||||||
are already in use (by some other registered client) are skipped.
|
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
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
The detect client function is called by i2c_probe or i2c_detect.
|
The detect client function is called by i2c_probe. The `kind' parameter
|
||||||
The `kind' parameter contains 0 if this call is due to a `force'
|
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
||||||
parameter, and -1 otherwise (for i2c_detect, it contains 0 if
|
number for a forced detection with a chip type forced.
|
||||||
this call is due to the generic `force' parameter, and the chip type
|
|
||||||
number if it is due to a specific `force' parameter).
|
|
||||||
|
|
||||||
Below, some things are only needed if this is a `sensors' driver. Those
|
Below, some things are only needed if this is a `sensors' driver. Those
|
||||||
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
||||||
markers.
|
markers.
|
||||||
|
|
||||||
This function should only return an error (any value != 0) if there is
|
Returning an error different from -ENODEV in a detect function will cause
|
||||||
some reason why no more detection should be done anymore. If the
|
the detection to stop: other addresses and adapters won't be scanned.
|
||||||
detection just fails for this address, return 0.
|
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.
|
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 = "";
|
const char *type_name = "";
|
||||||
int is_isa = i2c_is_isa_adapter(adapter);
|
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
|
if (is_isa) {
|
||||||
(call `goto ERROR0'). But for kicks, we will assume it is all
|
|
||||||
right. */
|
|
||||||
|
|
||||||
/* Discard immediately if this ISA range is already used */
|
/* Discard immediately if this ISA range is already used */
|
||||||
if (check_region(address,FOO_EXTENT))
|
if (check_region(address,FOO_EXTENT))
|
||||||
|
@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
|
||||||
/* SENSORS ONLY END */
|
/* SENSORS ONLY END */
|
||||||
|
|
||||||
/* Try to detach the client from i2c space */
|
/* Try to detach the client from i2c space */
|
||||||
if ((err = i2c_detach_client(client))) {
|
if ((err = i2c_detach_client(client)))
|
||||||
printk("foo.o: Client deregistration failed, client not detached.\n");
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
|
||||||
/* SENSORS ONLY START */
|
/* HYBRID SENSORS CHIP ONLY START */
|
||||||
if i2c_is_isa_client(client)
|
if i2c_is_isa_client(client)
|
||||||
release_region(client->addr,LM78_EXTENT);
|
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 */
|
kfree(client); /* Frees client data too, if allocated at the same time */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -872,7 +872,13 @@ When kbuild executes the following steps are followed (roughly):
|
||||||
Assignments to $(targets) are without $(obj)/ prefix.
|
Assignments to $(targets) are without $(obj)/ prefix.
|
||||||
if_changed may be used in conjunction with custom commands as
|
if_changed may be used in conjunction with custom commands as
|
||||||
defined in 6.7 "Custom kbuild commands".
|
defined in 6.7 "Custom kbuild commands".
|
||||||
|
|
||||||
Note: It is a typical mistake to forget the FORCE prerequisite.
|
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
|
ld
|
||||||
Link target. Often LDFLAGS_$@ is used to set specific options to ld.
|
Link target. Often LDFLAGS_$@ is used to set specific options to ld.
|
||||||
|
|
246
Documentation/networking/README.ipw2100
Normal file
246
Documentation/networking/README.ipw2100
Normal file
|
@ -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
|
||||||
|
|
300
Documentation/networking/README.ipw2200
Normal file
300
Documentation/networking/README.ipw2200
Normal file
|
@ -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
|
||||||
|
|
||||||
|
|
138
Documentation/power/swsusp-dmcrypt.txt
Normal file
138
Documentation/power/swsusp-dmcrypt.txt
Normal file
|
@ -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
|
system is shut down or suspended. Additionally use the encrypted
|
||||||
suspend image to prevent sensitive data from being stolen after
|
suspend image to prevent sensitive data from being stolen after
|
||||||
resume.
|
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
|
POSTing bios works. Ole Rohne has patch to do just that at
|
||||||
http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
|
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
|
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
|
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
|
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 Aspire 1406LC ole's late BIOS init (7), turn off DRI
|
||||||
Acer TM 242FX vbetool (6)
|
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 4052LCi s3_bios (2)
|
||||||
Acer TM 636Lci s3_bios vga=normal (2)
|
Acer TM 636Lci s3_bios vga=normal (2)
|
||||||
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
|
Acer TM 650 (Radeon M7) vga=normal plus boot-radeon (5) gets text console back
|
||||||
|
|
|
@ -111,24 +111,17 @@ hardware.
|
||||||
Interrupts: locally disabled.
|
Interrupts: locally disabled.
|
||||||
This call must not sleep
|
This call must not sleep
|
||||||
|
|
||||||
stop_tx(port,tty_stop)
|
stop_tx(port)
|
||||||
Stop transmitting characters. This might be due to the CTS
|
Stop transmitting characters. This might be due to the CTS
|
||||||
line becoming inactive or the tty layer indicating we want
|
line becoming inactive or the tty layer indicating we want
|
||||||
to stop transmission.
|
to stop transmission due to an XOFF character.
|
||||||
|
|
||||||
tty_stop: 1 if this call is due to the TTY layer issuing a
|
|
||||||
TTY stop to the driver (equiv to rs_stop).
|
|
||||||
|
|
||||||
Locking: port->lock taken.
|
Locking: port->lock taken.
|
||||||
Interrupts: locally disabled.
|
Interrupts: locally disabled.
|
||||||
This call must not sleep
|
This call must not sleep
|
||||||
|
|
||||||
start_tx(port,tty_start)
|
start_tx(port)
|
||||||
start transmitting characters. (incidentally, nonempty will
|
start transmitting characters.
|
||||||
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)
|
|
||||||
|
|
||||||
Locking: port->lock taken.
|
Locking: port->lock taken.
|
||||||
Interrupts: locally disabled.
|
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
|
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.
|
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 devices are chained in priority order from the "swap_list" header.
|
||||||
The "swap_list" is used for the round-robin swaphandle allocation strategy.
|
The "swap_list" is used for the round-robin swaphandle allocation strategy.
|
||||||
The #free swaphandles is maintained in "nr_swap_pages". These two together
|
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
|
The swap_lock also protects all the device reference counts on the
|
||||||
counts on the corresponding swaphandles, maintained in the "swap_map"
|
corresponding swaphandles, maintained in the "swap_map" array, and the
|
||||||
array, and the "highest_bit" and "lowest_bit" fields.
|
"highest_bit" and "lowest_bit" fields.
|
||||||
|
|
||||||
Both of these are spinlocks, and are never acquired from intr level. The
|
The swap_lock is a spinlock, and is never acquired from intr level.
|
||||||
locking hierarchy is swap_list_lock -> swap_device_lock.
|
|
||||||
|
|
||||||
To prevent races between swap space deletion or async readahead swapins
|
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
|
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.
|
The GETSTATUS call returns if the device is open or not.
|
||||||
[FIXME -- silliness again?]
|
[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
|
eurotechwdt.c -- Eurotech CPU-1220/1410
|
||||||
|
|
||||||
The timeout can be set using the SETTIMEOUT ioctl and defaults
|
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/
|
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
|
||||||
S: Maintained
|
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
|
HARMONY SOUND DRIVER
|
||||||
P: Kyle McMartin
|
P: Kyle McMartin
|
||||||
M: kyle@parisc-linux.org
|
M: kyle@parisc-linux.org
|
||||||
|
@ -991,6 +998,13 @@ M: mike.miller@hp.com
|
||||||
L: iss_storagedev@hp.com
|
L: iss_storagedev@hp.com
|
||||||
S: Supported
|
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
|
HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series
|
||||||
P: Jaroslav Kysela
|
P: Jaroslav Kysela
|
||||||
M: perex@suse.cz
|
M: perex@suse.cz
|
||||||
|
@ -1007,7 +1021,7 @@ P: William Irwin
|
||||||
M: wli@holomorphy.com
|
M: wli@holomorphy.com
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
I2C AND SENSORS DRIVERS
|
I2C SUBSYSTEM
|
||||||
P: Greg Kroah-Hartman
|
P: Greg Kroah-Hartman
|
||||||
M: greg@kroah.com
|
M: greg@kroah.com
|
||||||
P: Jean Delvare
|
P: Jean Delvare
|
||||||
|
@ -2643,11 +2657,6 @@ S: Maintained
|
||||||
UCLINUX (AND M68KNOMMU)
|
UCLINUX (AND M68KNOMMU)
|
||||||
P: Greg Ungerer
|
P: Greg Ungerer
|
||||||
M: gerg@uclinux.org
|
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/
|
W: http://www.uclinux.org/
|
||||||
L: uclinux-dev@uclinux.org (subscribers-only)
|
L: uclinux-dev@uclinux.org (subscribers-only)
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
164
Makefile
164
Makefile
|
@ -109,10 +109,9 @@ $(if $(KBUILD_OUTPUT),, \
|
||||||
.PHONY: $(MAKECMDGOALS)
|
.PHONY: $(MAKECMDGOALS)
|
||||||
|
|
||||||
$(filter-out _all,$(MAKECMDGOALS)) _all:
|
$(filter-out _all,$(MAKECMDGOALS)) _all:
|
||||||
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
|
||||||
KBUILD_SRC=$(CURDIR) KBUILD_VERBOSE=$(KBUILD_VERBOSE) \
|
KBUILD_SRC=$(CURDIR) \
|
||||||
KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)" \
|
KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile $@
|
||||||
-f $(CURDIR)/Makefile $@
|
|
||||||
|
|
||||||
# Leave processing to above invocation of make
|
# Leave processing to above invocation of make
|
||||||
skip-makefile := 1
|
skip-makefile := 1
|
||||||
|
@ -233,7 +232,7 @@ ifeq ($(MAKECMDGOALS),)
|
||||||
KBUILD_MODULES := 1
|
KBUILD_MODULES := 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
|
export KBUILD_MODULES KBUILD_BUILTIN
|
||||||
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
|
export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
|
||||||
|
|
||||||
# Beautify output
|
# 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
|
# Look for make include files relative to root of kernel src
|
||||||
MAKEFLAGS += --include-dir=$(srctree)
|
MAKEFLAGS += --include-dir=$(srctree)
|
||||||
|
|
||||||
|
# We need some generic definitions
|
||||||
|
include $(srctree)/scripts/Kbuild.include
|
||||||
|
|
||||||
# For maximum performance (+ possibly random breakage, uncomment
|
# For maximum performance (+ possibly random breakage, uncomment
|
||||||
# the following)
|
# the following)
|
||||||
|
|
||||||
|
@ -348,7 +350,7 @@ LINUXINCLUDE := -Iinclude \
|
||||||
|
|
||||||
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)
|
||||||
|
|
||||||
CFLAGS := -Wall -Wstrict-prototypes -Wno-trigraphs \
|
CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
|
||||||
-fno-strict-aliasing -fno-common \
|
-fno-strict-aliasing -fno-common \
|
||||||
-ffreestanding
|
-ffreestanding
|
||||||
AFLAGS := -D__ASSEMBLY__
|
AFLAGS := -D__ASSEMBLY__
|
||||||
|
@ -367,15 +369,10 @@ export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
|
||||||
# even be read-only.
|
# even be read-only.
|
||||||
export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
|
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
|
# 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_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
|
RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# Rules shared between *config targets and build targets
|
# 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
|
# images. Default is /boot, but you can set it to other values
|
||||||
export INSTALL_PATH ?= /boot
|
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
|
# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
|
||||||
# relocations required by build roots. This is not defined in the
|
# relocations required by build roots. This is not defined in the
|
||||||
|
@ -691,8 +708,10 @@ endef
|
||||||
|
|
||||||
# Update vmlinux version before link
|
# Update vmlinux version before link
|
||||||
# Use + in front of this rule to silent warning about make -j1
|
# 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__)
|
cmd_ksym_ld = $(cmd_vmlinux__)
|
||||||
define rule_ksym_ld
|
define rule_ksym_ld
|
||||||
|
:
|
||||||
+$(call cmd,vmlinux_version)
|
+$(call cmd,vmlinux_version)
|
||||||
$(call cmd,vmlinux__)
|
$(call cmd,vmlinux__)
|
||||||
$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
|
$(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.
|
# Needs to visit scripts/ before $(KALLSYMS) can be used.
|
||||||
$(KALLSYMS): scripts ;
|
$(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
|
endif # ifdef CONFIG_KALLSYMS
|
||||||
|
|
||||||
# vmlinux image - including updated kernel symbols
|
# vmlinux image - including updated kernel symbols
|
||||||
|
@ -757,7 +786,7 @@ $(vmlinux-dirs): prepare-all scripts
|
||||||
prepare2:
|
prepare2:
|
||||||
ifneq ($(KBUILD_SRC),)
|
ifneq ($(KBUILD_SRC),)
|
||||||
@echo ' Using $(srctree) as source for kernel'
|
@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 " $(srctree) is not clean, please run 'make mrproper'";\
|
||||||
echo " in the '$(srctree)' directory.";\
|
echo " in the '$(srctree)' directory.";\
|
||||||
/bin/false; \
|
/bin/false; \
|
||||||
|
@ -769,7 +798,8 @@ endif
|
||||||
# prepare1 creates a makefile if using a separate output directory
|
# prepare1 creates a makefile if using a separate output directory
|
||||||
prepare1: prepare2 outputmakefile
|
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),)
|
ifneq ($(KBUILD_MODULES),)
|
||||||
$(Q)rm -rf $(MODVERDIR)
|
$(Q)rm -rf $(MODVERDIR)
|
||||||
$(Q)mkdir -p $(MODVERDIR)
|
$(Q)mkdir -p $(MODVERDIR)
|
||||||
|
@ -875,7 +905,7 @@ modules_install: _modinst_ _modinst_post
|
||||||
|
|
||||||
.PHONY: _modinst_
|
.PHONY: _modinst_
|
||||||
_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 "Warning: you may need to install module-init-tools"; \
|
||||||
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
|
echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
|
||||||
sleep 1; \
|
sleep 1; \
|
||||||
|
@ -1159,37 +1189,49 @@ else
|
||||||
__srctree = $(srctree)/
|
__srctree = $(srctree)/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ALLSOURCE_ARCHS := $(ARCH)
|
||||||
|
|
||||||
define all-sources
|
define all-sources
|
||||||
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
( find $(__srctree) $(RCS_FIND_IGNORE) \
|
||||||
\( -name include -o -name arch \) -prune -o \
|
\( -name include -o -name arch \) -prune -o \
|
||||||
-name '*.[chS]' -print; \
|
-name '*.[chS]' -print; \
|
||||||
find $(__srctree)arch/$(ARCH) $(RCS_FIND_IGNORE) \
|
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||||
-name '*.[chS]' -print; \
|
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
|
||||||
|
-name '*.[chS]' -print; \
|
||||||
|
done ; \
|
||||||
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print; \
|
-name '*.[chS]' -print; \
|
||||||
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
find $(__srctree)include $(RCS_FIND_IGNORE) \
|
||||||
\( -name config -o -name 'asm-*' \) -prune \
|
\( -name config -o -name 'asm-*' \) -prune \
|
||||||
-o -name '*.[chS]' -print; \
|
-o -name '*.[chS]' -print; \
|
||||||
find $(__srctree)include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
|
for ARCH in $(ALLSOURCE_ARCHS) ; do \
|
||||||
-name '*.[chS]' -print; \
|
find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
|
||||||
|
-name '*.[chS]' -print; \
|
||||||
|
done ; \
|
||||||
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
|
||||||
-name '*.[chS]' -print )
|
-name '*.[chS]' -print )
|
||||||
endef
|
endef
|
||||||
|
|
||||||
quiet_cmd_cscope-file = FILELST cscope.files
|
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
|
quiet_cmd_cscope = MAKE cscope.out
|
||||||
cmd_cscope = cscope -k -b -q
|
cmd_cscope = cscope -b
|
||||||
|
|
||||||
cscope: FORCE
|
cscope: FORCE
|
||||||
$(call cmd,cscope-file)
|
$(call cmd,cscope-file)
|
||||||
$(call cmd,cscope)
|
$(call cmd,cscope)
|
||||||
|
|
||||||
quiet_cmd_TAGS = MAKE $@
|
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 $@
|
quiet_cmd_tags = MAKE $@
|
||||||
define cmd_tags
|
define cmd_tags
|
||||||
|
@ -1198,9 +1240,6 @@ define cmd_tags
|
||||||
$(all-sources) | xargs ctags $$CTAGSF -a
|
$(all-sources) | xargs ctags $$CTAGSF -a
|
||||||
endef
|
endef
|
||||||
|
|
||||||
TAGS: FORCE
|
|
||||||
$(call cmd,TAGS)
|
|
||||||
|
|
||||||
tags: FORCE
|
tags: FORCE
|
||||||
$(call cmd,tags)
|
$(call cmd,tags)
|
||||||
|
|
||||||
|
@ -1268,82 +1307,11 @@ ifneq ($(cmd_files),)
|
||||||
include $(cmd_files)
|
include $(cmd_files)
|
||||||
endif
|
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
|
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
|
||||||
# Usage:
|
# Usage:
|
||||||
# $(Q)$(MAKE) $(clean)=dir
|
# $(Q)$(MAKE) $(clean)=dir
|
||||||
clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
|
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
|
endif # skip-makefile
|
||||||
|
|
||||||
FORCE:
|
FORCE:
|
||||||
|
|
|
@ -365,8 +365,8 @@ config NO_IDLE_HZ
|
||||||
|
|
||||||
Please note that dynamic tick may affect the accuracy of
|
Please note that dynamic tick may affect the accuracy of
|
||||||
timekeeping on some platforms depending on the implementation.
|
timekeeping on some platforms depending on the implementation.
|
||||||
Currently at least OMAP platform is known to have accurate
|
Currently at least OMAP, PXA2xx and SA11x0 platforms are known
|
||||||
timekeeping with dynamic tick.
|
to have accurate timekeeping with dynamic tick.
|
||||||
|
|
||||||
config ARCH_DISCONTIGMEM_ENABLE
|
config ARCH_DISCONTIGMEM_ENABLE
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
|
#include <linux/cpumask.h>
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
|
@ -177,7 +177,7 @@ static void locomo_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
d = irq_desc + irq;
|
d = irq_desc + irq;
|
||||||
for (i = 0; i <= 3; i++, d++, irq++) {
|
for (i = 0; i <= 3; i++, d++, irq++) {
|
||||||
if (req & (0x0100 << i)) {
|
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) {
|
if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
|
||||||
d = irq_desc + LOCOMO_IRQ_KEY_START;
|
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;
|
d = irq_desc + LOCOMO_IRQ_GPIO_START;
|
||||||
for (i = 0; i <= 15; i++, irq++, d++) {
|
for (i = 0; i <= 15; i++, irq++, d++) {
|
||||||
if (req & (0x0001 << i)) {
|
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) {
|
if (locomo_readl(mapbase + LOCOMO_LTINT) & 0x0001) {
|
||||||
d = irq_desc + LOCOMO_IRQ_LT_START;
|
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++) {
|
for (i = 0; i <= 3; i++, irq++, d++) {
|
||||||
if (req & (0x0001 << i)) {
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int locomo_remove_child(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
device_unregister(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void __locomo_remove(struct locomo *lchip)
|
static void __locomo_remove(struct locomo *lchip)
|
||||||
{
|
{
|
||||||
struct list_head *l, *n;
|
device_for_each_child(lchip->dev, NULL, locomo_remove_child);
|
||||||
|
|
||||||
list_for_each_safe(l, n, &lchip->dev->children) {
|
|
||||||
struct device *d = list_to_dev(l);
|
|
||||||
|
|
||||||
device_unregister(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lchip->irq != NO_IRQ) {
|
if (lchip->irq != NO_IRQ) {
|
||||||
set_irq_chained_handler(lchip->irq, NULL);
|
set_irq_chained_handler(lchip->irq, NULL);
|
||||||
|
|
|
@ -268,8 +268,8 @@ static struct irqchip sa1111_low_chip = {
|
||||||
.mask = sa1111_mask_lowirq,
|
.mask = sa1111_mask_lowirq,
|
||||||
.unmask = sa1111_unmask_lowirq,
|
.unmask = sa1111_unmask_lowirq,
|
||||||
.retrigger = sa1111_retrigger_lowirq,
|
.retrigger = sa1111_retrigger_lowirq,
|
||||||
.type = sa1111_type_lowirq,
|
.set_type = sa1111_type_lowirq,
|
||||||
.wake = sa1111_wake_lowirq,
|
.set_wake = sa1111_wake_lowirq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sa1111_mask_highirq(unsigned int irq)
|
static void sa1111_mask_highirq(unsigned int irq)
|
||||||
|
@ -364,8 +364,8 @@ static struct irqchip sa1111_high_chip = {
|
||||||
.mask = sa1111_mask_highirq,
|
.mask = sa1111_mask_highirq,
|
||||||
.unmask = sa1111_unmask_highirq,
|
.unmask = sa1111_unmask_highirq,
|
||||||
.retrigger = sa1111_retrigger_highirq,
|
.retrigger = sa1111_retrigger_highirq,
|
||||||
.type = sa1111_type_highirq,
|
.set_type = sa1111_type_highirq,
|
||||||
.wake = sa1111_wake_highirq,
|
.set_wake = sa1111_wake_highirq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sa1111_setup_irq(struct sa1111 *sachip)
|
static void sa1111_setup_irq(struct sa1111 *sachip)
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
|
|
||||||
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
|
#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 {
|
struct scoop_dev {
|
||||||
void *base;
|
void *base;
|
||||||
spinlock_t scoop_lock;
|
spinlock_t scoop_lock;
|
||||||
|
|
|
@ -284,7 +284,7 @@ __syscall_start:
|
||||||
.long sys_fstatfs64
|
.long sys_fstatfs64
|
||||||
.long sys_tgkill
|
.long sys_tgkill
|
||||||
.long sys_utimes
|
.long sys_utimes
|
||||||
/* 270 */ .long sys_fadvise64_64
|
/* 270 */ .long sys_arm_fadvise64_64_wrapper
|
||||||
.long sys_pciconfig_iobase
|
.long sys_pciconfig_iobase
|
||||||
.long sys_pciconfig_read
|
.long sys_pciconfig_read
|
||||||
.long sys_pciconfig_write
|
.long sys_pciconfig_write
|
||||||
|
|
|
@ -585,7 +585,7 @@ ecard_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||||
|
|
||||||
if (pending) {
|
if (pending) {
|
||||||
struct irqdesc *d = irq_desc + ec->irq;
|
struct irqdesc *d = irq_desc + ec->irq;
|
||||||
d->handle(ec->irq, d, regs);
|
desc_handle_irq(ec->irq, d, regs);
|
||||||
called ++;
|
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
|
* Serial cards should go in 0/1, ethernet/scsi in 2/3
|
||||||
* otherwise you will lose serial data at high speeds!
|
* otherwise you will lose serial data at high speeds!
|
||||||
*/
|
*/
|
||||||
d->handle(ec->irq, d, regs);
|
desc_handle_irq(ec->irq, d, regs);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "card%d: interrupt from unclaimed "
|
printk(KERN_WARNING "card%d: interrupt from unclaimed "
|
||||||
"card???\n", slot);
|
"card???\n", slot);
|
||||||
|
|
|
@ -265,6 +265,10 @@ sys_futex_wrapper:
|
||||||
str r5, [sp, #4] @ push sixth arg
|
str r5, [sp, #4] @ push sixth arg
|
||||||
b sys_futex
|
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
|
* Note: off_4k (r5) is always units of 4K. If we can't do the requested
|
||||||
* offset, we return EINVAL.
|
* offset, we return EINVAL.
|
||||||
|
|
|
@ -207,8 +207,8 @@ void enable_irq_wake(unsigned int irq)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||||
if (desc->chip->wake)
|
if (desc->chip->set_wake)
|
||||||
desc->chip->wake(irq, 1);
|
desc->chip->set_wake(irq, 1);
|
||||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(enable_irq_wake);
|
EXPORT_SYMBOL(enable_irq_wake);
|
||||||
|
@ -219,8 +219,8 @@ void disable_irq_wake(unsigned int irq)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
spin_lock_irqsave(&irq_controller_lock, flags);
|
||||||
if (desc->chip->wake)
|
if (desc->chip->set_wake)
|
||||||
desc->chip->wake(irq, 0);
|
desc->chip->set_wake(irq, 0);
|
||||||
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
spin_unlock_irqrestore(&irq_controller_lock, flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(disable_irq_wake);
|
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) {
|
list_for_each_safe(l, n, &head) {
|
||||||
desc = list_entry(l, struct irqdesc, pend);
|
desc = list_entry(l, struct irqdesc, pend);
|
||||||
list_del_init(&desc->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();
|
irq_enter();
|
||||||
spin_lock(&irq_controller_lock);
|
spin_lock(&irq_controller_lock);
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now re-run any pending interrupts.
|
* Now re-run any pending interrupts.
|
||||||
|
@ -624,9 +624,9 @@ int set_irq_type(unsigned int irq, unsigned int type)
|
||||||
}
|
}
|
||||||
|
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
if (desc->chip->type) {
|
if (desc->chip->set_type) {
|
||||||
spin_lock_irqsave(&irq_controller_lock, flags);
|
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);
|
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].probing = 1;
|
||||||
irq_desc[i].triggered = 0;
|
irq_desc[i].triggered = 0;
|
||||||
if (irq_desc[i].chip->type)
|
if (irq_desc[i].chip->set_type)
|
||||||
irq_desc[i].chip->type(i, IRQT_PROBE);
|
irq_desc[i].chip->set_type(i, IRQT_PROBE);
|
||||||
irq_desc[i].chip->unmask(i);
|
irq_desc[i].chip->unmask(i);
|
||||||
irqs += 1;
|
irqs += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||||
* We need to tell the secondary core where to find
|
* We need to tell the secondary core where to find
|
||||||
* its stack and the page tables.
|
* 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);
|
secondary_data.pgdir = virt_to_phys(pgd);
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
|
|
|
@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(execve);
|
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;
|
struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
|
||||||
|
|
||||||
write_seqlock(&xtime_lock);
|
if (dyn_tick) {
|
||||||
if (dyn_tick->state & DYN_TICK_ENABLED)
|
write_seqlock(&xtime_lock);
|
||||||
dyn_tick->reprogram(next_timer_interrupt() - jiffies);
|
if (dyn_tick->state & DYN_TICK_ENABLED)
|
||||||
write_sequnlock(&xtime_lock);
|
dyn_tick->reprogram(next_timer_interrupt() - jiffies);
|
||||||
|
write_sequnlock(&xtime_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
|
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 = 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", };
|
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) {
|
while (mask) {
|
||||||
if (mask & 1) {
|
if (mask & 1) {
|
||||||
IRQDBG("handling irq %d\n", irq);
|
IRQDBG("handling irq %d\n", irq);
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
|
|
|
@ -126,7 +126,7 @@ h7202_timerx_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
while (mask) {
|
while (mask) {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
|
|
@ -152,7 +152,7 @@ imx_gpio_handler(unsigned int mask, unsigned int irq,
|
||||||
while (mask) {
|
while (mask) {
|
||||||
if (mask & 1) {
|
if (mask & 1) {
|
||||||
DEBUG_IRQ("handling irq %d\n", irq);
|
DEBUG_IRQ("handling irq %d\n", irq);
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
|
@ -214,7 +214,7 @@ static struct irqchip imx_gpio_chip = {
|
||||||
.ack = imx_gpio_ack_irq,
|
.ack = imx_gpio_ack_irq,
|
||||||
.mask = imx_gpio_mask_irq,
|
.mask = imx_gpio_mask_irq,
|
||||||
.unmask = imx_gpio_unmask_irq,
|
.unmask = imx_gpio_unmask_irq,
|
||||||
.type = imx_gpio_irq_type,
|
.set_type = imx_gpio_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
|
|
|
@ -170,7 +170,7 @@ sic_handle_irq(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
|
||||||
irq += IRQ_SIC_START;
|
irq += IRQ_SIC_START;
|
||||||
|
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
} while (status);
|
} 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++) {
|
for (i = 0; i <= 7; i++) {
|
||||||
if (status & (1<<i)) {
|
if (status & (1<<i)) {
|
||||||
desc = irq_desc + i + IRQ_IXP2000_GPIO0;
|
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 = {
|
static struct irqchip ixp2000_GPIO_irq_chip = {
|
||||||
.type = ixp2000_GPIO_irq_type,
|
.ack = ixp2000_GPIO_irq_mask_ack,
|
||||||
.ack = ixp2000_GPIO_irq_mask_ack,
|
.mask = ixp2000_GPIO_irq_mask,
|
||||||
.mask = ixp2000_GPIO_irq_mask,
|
.unmask = ixp2000_GPIO_irq_unmask
|
||||||
.unmask = ixp2000_GPIO_irq_unmask
|
.set_type = ixp2000_GPIO_irq_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ixp2000_pci_irq_mask(unsigned int irq)
|
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;
|
struct irqdesc *cpld_desc;
|
||||||
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
||||||
cpld_desc = irq_desc + cpld_irq;
|
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;
|
struct irqdesc *cpld_desc;
|
||||||
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
int cpld_irq = IXP2000_BOARD_IRQ(0) + i;
|
||||||
cpld_desc = irq_desc + cpld_irq;
|
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/irq.h>
|
||||||
#include <asm/mach/time.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
|
* 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
|
* (be it PCI or something else) configures that GPIO line
|
||||||
* as an IRQ.
|
* 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)
|
static void ixp4xx_irq_mask(unsigned int irq)
|
||||||
{
|
{
|
||||||
if (cpu_is_ixp46x() && irq >= 32)
|
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 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;
|
int line = (irq < 32) ? irq2gpio[irq] : -1;
|
||||||
|
|
||||||
if (line >= 0)
|
if (line >= 0)
|
||||||
|
@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = {
|
||||||
.ack = ixp4xx_irq_mask,
|
.ack = ixp4xx_irq_mask,
|
||||||
.mask = ixp4xx_irq_mask,
|
.mask = ixp4xx_irq_mask,
|
||||||
.unmask = ixp4xx_irq_level_unmask,
|
.unmask = ixp4xx_irq_level_unmask,
|
||||||
|
.type = ixp4xx_set_irq_type
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip ixp4xx_irq_edge_chip = {
|
static struct irqchip ixp4xx_irq_edge_chip = {
|
||||||
.ack = ixp4xx_irq_ack,
|
.ack = ixp4xx_irq_ack,
|
||||||
.mask = ixp4xx_irq_mask,
|
.mask = ixp4xx_irq_mask,
|
||||||
.unmask = ixp4xx_irq_unmask,
|
.unmask = ixp4xx_irq_unmask,
|
||||||
|
.type = ixp4xx_set_irq_type
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type 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)
|
void __init coyote_pci_preinit(void)
|
||||||
{
|
{
|
||||||
gpio_line_config(COYOTE_PCI_SLOT0_PIN,
|
set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW);
|
||||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW);
|
||||||
|
|
||||||
gpio_line_config(COYOTE_PCI_SLOT1_PIN,
|
|
||||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
|
||||||
|
|
||||||
gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
|
gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN);
|
||||||
gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
|
gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN);
|
||||||
|
|
|
@ -24,11 +24,6 @@
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/flash.h>
|
#include <asm/mach/flash.h>
|
||||||
|
|
||||||
void __init coyote_map_io(void)
|
|
||||||
{
|
|
||||||
ixp4xx_map_io();
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct flash_platform_data coyote_flash_data = {
|
static struct flash_platform_data coyote_flash_data = {
|
||||||
.map_name = "cfi_probe",
|
.map_name = "cfi_probe",
|
||||||
.width = 2,
|
.width = 2,
|
||||||
|
@ -107,7 +102,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = coyote_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.boot_params = 0x0100,
|
||||||
|
@ -125,7 +120,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = coyote_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.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 int ixp4xx_setup(int nr, struct pci_sys_data *sys);
|
||||||
extern struct pci_bus *ixp4xx_scan_bus(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)
|
void __init gtwx5715_pci_preinit(void)
|
||||||
{
|
{
|
||||||
gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN);
|
set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW);
|
||||||
gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN);
|
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();
|
ixp4xx_pci_preinit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,12 +101,6 @@ static struct platform_device gtwx5715_uart_device = {
|
||||||
.resource = gtwx5715_uart_resources,
|
.resource = gtwx5715_uart_resources,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void __init gtwx5715_map_io(void)
|
|
||||||
{
|
|
||||||
ixp4xx_map_io();
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct flash_platform_data gtwx5715_flash_data = {
|
static struct flash_platform_data gtwx5715_flash_data = {
|
||||||
.map_name = "cfi_probe",
|
.map_name = "cfi_probe",
|
||||||
.width = 2,
|
.width = 2,
|
||||||
|
@ -144,7 +138,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_UART2_BASE_PHYS,
|
.phys_io = IXP4XX_UART2_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = gtwx5715_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.boot_params = 0x0100,
|
||||||
|
|
|
@ -27,14 +27,10 @@
|
||||||
|
|
||||||
void __init ixdp425_pci_preinit(void)
|
void __init ixdp425_pci_preinit(void)
|
||||||
{
|
{
|
||||||
gpio_line_config(IXDP425_PCI_INTA_PIN,
|
set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW);
|
||||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW);
|
||||||
gpio_line_config(IXDP425_PCI_INTB_PIN,
|
set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW);
|
||||||
IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_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);
|
|
||||||
|
|
||||||
gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
|
gpio_line_isr_clear(IXDP425_PCI_INTA_PIN);
|
||||||
gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
|
gpio_line_isr_clear(IXDP425_PCI_INTB_PIN);
|
||||||
|
|
|
@ -24,11 +24,6 @@
|
||||||
#include <asm/mach/arch.h>
|
#include <asm/mach/arch.h>
|
||||||
#include <asm/mach/flash.h>
|
#include <asm/mach/flash.h>
|
||||||
|
|
||||||
void __init ixdp425_map_io(void)
|
|
||||||
{
|
|
||||||
ixp4xx_map_io();
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct flash_platform_data ixdp425_flash_data = {
|
static struct flash_platform_data ixdp425_flash_data = {
|
||||||
.map_name = "cfi_probe",
|
.map_name = "cfi_probe",
|
||||||
.width = 2,
|
.width = 2,
|
||||||
|
@ -133,7 +128,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = ixdp425_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.boot_params = 0x0100,
|
||||||
|
@ -145,7 +140,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = ixdp425_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.boot_params = 0x0100,
|
||||||
|
@ -157,7 +152,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = ixdp425_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.boot_params = 0x0100,
|
||||||
|
@ -176,7 +171,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform")
|
||||||
.phys_ram = PHYS_OFFSET,
|
.phys_ram = PHYS_OFFSET,
|
||||||
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
.phys_io = IXP4XX_PERIPHERAL_BASE_PHYS,
|
||||||
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
.io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc,
|
||||||
.map_io = ixdp425_map_io,
|
.map_io = ixp4xx_map_io,
|
||||||
.init_irq = ixp4xx_init_irq,
|
.init_irq = ixp4xx_init_irq,
|
||||||
.timer = &ixp4xx_timer,
|
.timer = &ixp4xx_timer,
|
||||||
.boot_params = 0x0100,
|
.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)
|
void __init ixdpg425_pci_preinit(void)
|
||||||
{
|
{
|
||||||
gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW);
|
||||||
gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
|
set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW);
|
||||||
|
|
||||||
gpio_line_isr_clear(6);
|
gpio_line_isr_clear(6);
|
||||||
gpio_line_isr_clear(7);
|
gpio_line_isr_clear(7);
|
||||||
|
|
|
@ -13,4 +13,4 @@ extern struct sys_timer lh7a40x_timer;
|
||||||
extern void lh7a400_init_irq (void);
|
extern void lh7a400_init_irq (void);
|
||||||
extern void lh7a404_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) {
|
fpga_irq++, stat >>= 1) {
|
||||||
if (stat & 1) {
|
if (stat & 1) {
|
||||||
d = irq_desc + fpga_irq;
|
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,
|
.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 = {
|
struct platform_device corgiscoop_device = {
|
||||||
.name = "sharp-scoop",
|
.name = "sharp-scoop",
|
||||||
.id = -1,
|
.id = -1,
|
||||||
|
@ -241,6 +250,9 @@ static void __init corgi_init(void)
|
||||||
pxa_set_udc_info(&udc_info);
|
pxa_set_udc_info(&udc_info);
|
||||||
pxa_set_mci_info(&corgi_mci_platform_data);
|
pxa_set_mci_info(&corgi_mci_platform_data);
|
||||||
|
|
||||||
|
scoop_num = 1;
|
||||||
|
scoop_devs = &corgi_pcmcia_scoop[0];
|
||||||
|
|
||||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,7 @@ static struct irqchip pxa_low_gpio_chip = {
|
||||||
.ack = pxa_ack_low_gpio,
|
.ack = pxa_ack_low_gpio,
|
||||||
.mask = pxa_mask_low_irq,
|
.mask = pxa_mask_low_irq,
|
||||||
.unmask = pxa_unmask_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;
|
mask >>= 2;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -172,7 +172,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -187,7 +187,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -203,7 +203,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
|
@ -241,7 +241,7 @@ static struct irqchip pxa_muxed_gpio_chip = {
|
||||||
.ack = pxa_ack_muxed_gpio,
|
.ack = pxa_ack_muxed_gpio,
|
||||||
.mask = pxa_mask_muxed_gpio,
|
.mask = pxa_mask_muxed_gpio,
|
||||||
.unmask = pxa_unmask_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)) {
|
if (likely(pending)) {
|
||||||
irq = LUBBOCK_IRQ(0) + __ffs(pending);
|
irq = LUBBOCK_IRQ(0) + __ffs(pending);
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
|
pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
|
||||||
} while (pending);
|
} while (pending);
|
||||||
|
|
|
@ -72,7 +72,7 @@ static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
if (likely(pending)) {
|
if (likely(pending)) {
|
||||||
irq = MAINSTONE_IRQ(0) + __ffs(pending);
|
irq = MAINSTONE_IRQ(0) + __ffs(pending);
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
}
|
}
|
||||||
pending = MST_INTSETCLR & mainstone_irq_enabled;
|
pending = MST_INTSETCLR & mainstone_irq_enabled;
|
||||||
} while (pending);
|
} while (pending);
|
||||||
|
|
|
@ -62,6 +62,15 @@ struct platform_device poodle_scoop_device = {
|
||||||
.resource = poodle_scoop_resources,
|
.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 */
|
/* LoCoMo device */
|
||||||
static struct resource locomo_resources[] = {
|
static struct resource locomo_resources[] = {
|
||||||
|
@ -147,6 +156,9 @@ static void __init poodle_init(void)
|
||||||
|
|
||||||
set_pxa_fb_info(&poodle_fb_info);
|
set_pxa_fb_info(&poodle_fb_info);
|
||||||
|
|
||||||
|
scoop_num = 1;
|
||||||
|
scoop_devs = &poodle_pcmcia_scoop[0];
|
||||||
|
|
||||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
|
printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
|
||||||
|
|
|
@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void)
|
||||||
return usec;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_NO_IDLE_HZ
|
||||||
|
static unsigned long initial_match;
|
||||||
|
static int match_posponed;
|
||||||
|
#endif
|
||||||
|
|
||||||
static irqreturn_t
|
static irqreturn_t
|
||||||
pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
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);
|
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.
|
/* Loop until we get ahead of the free running timer.
|
||||||
* This ensures an exact clock tick count and time accuracy.
|
* This ensures an exact clock tick count and time accuracy.
|
||||||
* IRQs are disabled inside the loop to ensure coherence between
|
* Since IRQs are disabled at this point, coherence between
|
||||||
* lost_ticks (updated in do_timer()) and the match reg value, so we
|
* lost_ticks(updated in do_timer()) and the match reg value is
|
||||||
* can use do_gettimeofday() from interrupt handlers.
|
* ensured, hence we can use do_gettimeofday() from interrupt
|
||||||
|
* handlers.
|
||||||
*
|
*
|
||||||
* HACK ALERT: it seems that the PXA timer regs aren't updated right
|
* 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
|
* 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 */
|
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
|
#ifdef CONFIG_PM
|
||||||
static unsigned long osmr[4], oier;
|
static unsigned long osmr[4], oier;
|
||||||
|
|
||||||
|
@ -161,4 +210,7 @@ struct sys_timer pxa_timer = {
|
||||||
.suspend = pxa_timer_suspend,
|
.suspend = pxa_timer_suspend,
|
||||||
.resume = pxa_timer_resume,
|
.resume = pxa_timer_resume,
|
||||||
.offset = pxa_gettimeoffset,
|
.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];
|
irqno = bast_pc104_irqs[i];
|
||||||
desc = irq_desc + irqno;
|
desc = irq_desc + irqno;
|
||||||
|
|
||||||
desc->handle(irqno, desc, regs);
|
desc_handle_irq(irqno, desc, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
stat >>= 1;
|
stat >>= 1;
|
||||||
|
|
|
@ -388,6 +388,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
|
||||||
unsigned long hclk,
|
unsigned long hclk,
|
||||||
unsigned long pclk)
|
unsigned long pclk)
|
||||||
{
|
{
|
||||||
|
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
|
||||||
struct clk *clkp = init_clocks;
|
struct clk *clkp = init_clocks;
|
||||||
int ptr;
|
int ptr;
|
||||||
int ret;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,14 +184,14 @@ struct irqchip s3c_irq_level_chip = {
|
||||||
.ack = s3c_irq_maskack,
|
.ack = s3c_irq_maskack,
|
||||||
.mask = s3c_irq_mask,
|
.mask = s3c_irq_mask,
|
||||||
.unmask = s3c_irq_unmask,
|
.unmask = s3c_irq_unmask,
|
||||||
.wake = s3c_irq_wake
|
.set_wake = s3c_irq_wake
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip s3c_irq_chip = {
|
static struct irqchip s3c_irq_chip = {
|
||||||
.ack = s3c_irq_ack,
|
.ack = s3c_irq_ack,
|
||||||
.mask = s3c_irq_mask,
|
.mask = s3c_irq_mask,
|
||||||
.unmask = s3c_irq_unmask,
|
.unmask = s3c_irq_unmask,
|
||||||
.wake = s3c_irq_wake
|
.set_wake = s3c_irq_wake
|
||||||
};
|
};
|
||||||
|
|
||||||
/* S3C2410_EINTMASK
|
/* S3C2410_EINTMASK
|
||||||
|
@ -350,16 +350,16 @@ static struct irqchip s3c_irqext_chip = {
|
||||||
.mask = s3c_irqext_mask,
|
.mask = s3c_irqext_mask,
|
||||||
.unmask = s3c_irqext_unmask,
|
.unmask = s3c_irqext_unmask,
|
||||||
.ack = s3c_irqext_ack,
|
.ack = s3c_irqext_ack,
|
||||||
.type = s3c_irqext_type,
|
.set_type = s3c_irqext_type,
|
||||||
.wake = s3c_irqext_wake
|
.set_wake = s3c_irqext_wake
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irqchip s3c_irq_eint0t4 = {
|
static struct irqchip s3c_irq_eint0t4 = {
|
||||||
.ack = s3c_irq_ack,
|
.ack = s3c_irq_ack,
|
||||||
.mask = s3c_irq_mask,
|
.mask = s3c_irq_mask,
|
||||||
.unmask = s3c_irq_unmask,
|
.unmask = s3c_irq_unmask,
|
||||||
.wake = s3c_irq_wake,
|
.set_wake = s3c_irq_wake,
|
||||||
.type = s3c_irqext_type,
|
.set_type = s3c_irqext_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* mask values for the parent registers for each of the interrupt types */
|
/* 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 != 0) {
|
||||||
if (subsrc & 1) {
|
if (subsrc & 1) {
|
||||||
mydesc = irq_desc + IRQ_TC;
|
mydesc = irq_desc + IRQ_TC;
|
||||||
mydesc->handle( IRQ_TC, mydesc, regs);
|
desc_handle_irq(IRQ_TC, mydesc, regs);
|
||||||
}
|
}
|
||||||
if (subsrc & 2) {
|
if (subsrc & 2) {
|
||||||
mydesc = irq_desc + IRQ_ADC;
|
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;
|
desc = irq_desc + start;
|
||||||
|
|
||||||
if (subsrc & 1)
|
if (subsrc & 1)
|
||||||
desc->handle(start, desc, regs);
|
desc_handle_irq(start, desc, regs);
|
||||||
|
|
||||||
desc++;
|
desc++;
|
||||||
|
|
||||||
if (subsrc & 2)
|
if (subsrc & 2)
|
||||||
desc->handle(start+1, desc, regs);
|
desc_handle_irq(start+1, desc, regs);
|
||||||
|
|
||||||
desc++;
|
desc++;
|
||||||
|
|
||||||
if (subsrc & 4)
|
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();
|
s3c24xx_init_irq();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GPB3 is the line that controls the pull-up for the USB D+ line */
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void __init n30_init(void)
|
void __init n30_init(void)
|
||||||
{
|
{
|
||||||
s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
|
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")
|
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_ram = S3C2410_SDRAM_PA,
|
||||||
.phys_io = S3C2410_PA_UART,
|
.phys_io = S3C2410_PA_UART,
|
||||||
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
|
.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();
|
s3c2410_pm_check_store();
|
||||||
|
|
||||||
// need to make some form of time-delta
|
|
||||||
|
|
||||||
/* send the cpu to sleep... */
|
/* send the cpu to sleep... */
|
||||||
|
|
||||||
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
|
__raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
|
||||||
|
|
||||||
s3c2410_cpu_suspend(regs_save);
|
s3c2410_cpu_suspend(regs_save);
|
||||||
|
|
||||||
|
/* restore the cpu state */
|
||||||
|
|
||||||
|
cpu_init();
|
||||||
|
|
||||||
/* unset the return-from-sleep flag, to ensure reset */
|
/* unset the return-from-sleep flag, to ensure reset */
|
||||||
|
|
||||||
tmp = __raw_readl(S3C2410_GSTATUS2);
|
tmp = __raw_readl(S3C2410_GSTATUS2);
|
||||||
|
|
|
@ -68,6 +68,7 @@ static struct clk s3c2440_clk_ac97 = {
|
||||||
static int s3c2440_clk_add(struct sys_device *sysdev)
|
static int s3c2440_clk_add(struct sys_device *sysdev)
|
||||||
{
|
{
|
||||||
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
|
||||||
|
unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
|
||||||
struct clk *clk_h;
|
struct clk *clk_h;
|
||||||
struct clk *clk_p;
|
struct clk *clk_p;
|
||||||
struct clk *clk_xtal;
|
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);
|
s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate);
|
||||||
|
|
||||||
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
|
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n",
|
||||||
print_mhz(s3c2440_clk_upll.rate));
|
print_mhz(s3c2440_clk_upll.rate),
|
||||||
|
(camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
|
||||||
|
|
||||||
clk_p = clk_get(NULL, "pclk");
|
clk_p = clk_get(NULL, "pclk");
|
||||||
clk_h = clk_get(NULL, "hclk");
|
clk_h = clk_get(NULL, "hclk");
|
||||||
|
|
|
@ -64,11 +64,11 @@ static void s3c_irq_demux_wdtac97(unsigned int irq,
|
||||||
if (subsrc != 0) {
|
if (subsrc != 0) {
|
||||||
if (subsrc & 1) {
|
if (subsrc & 1) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
mydesc = irq_desc + IRQ_S3C2440_WDT;
|
||||||
mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
|
desc_handle_irq(IRQ_S3C2440_WDT, mydesc, regs);
|
||||||
}
|
}
|
||||||
if (subsrc & 2) {
|
if (subsrc & 2) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_AC97;
|
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 != 0) {
|
||||||
if (subsrc & 1) {
|
if (subsrc & 1) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_CAM_C;
|
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) {
|
if (subsrc & 2) {
|
||||||
mydesc = irq_desc + IRQ_S3C2440_CAM_P;
|
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,
|
.ack = sa1100_low_gpio_ack,
|
||||||
.mask = sa1100_low_gpio_mask,
|
.mask = sa1100_low_gpio_mask,
|
||||||
.unmask = sa1100_low_gpio_unmask,
|
.unmask = sa1100_low_gpio_unmask,
|
||||||
.type = sa1100_gpio_type,
|
.set_type = sa1100_gpio_type,
|
||||||
.wake = sa1100_low_gpio_wake,
|
.set_wake = sa1100_low_gpio_wake,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -126,7 +126,7 @@ sa1100_high_gpio_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
mask >>= 11;
|
mask >>= 11;
|
||||||
do {
|
do {
|
||||||
if (mask & 1)
|
if (mask & 1)
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
mask >>= 1;
|
mask >>= 1;
|
||||||
irq++;
|
irq++;
|
||||||
desc++;
|
desc++;
|
||||||
|
@ -181,8 +181,8 @@ static struct irqchip sa1100_high_gpio_chip = {
|
||||||
.ack = sa1100_high_gpio_ack,
|
.ack = sa1100_high_gpio_ack,
|
||||||
.mask = sa1100_high_gpio_mask,
|
.mask = sa1100_high_gpio_mask,
|
||||||
.unmask = sa1100_high_gpio_unmask,
|
.unmask = sa1100_high_gpio_unmask,
|
||||||
.type = sa1100_gpio_type,
|
.set_type = sa1100_gpio_type,
|
||||||
.wake = sa1100_high_gpio_wake,
|
.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) {
|
if (irr & IRR_ETHERNET) {
|
||||||
d = irq_desc + IRQ_NEPONSET_SMC9196;
|
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) {
|
if (irr & IRR_USAR) {
|
||||||
d = irq_desc + IRQ_NEPONSET_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);
|
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) {
|
if (irr & IRR_SA1111) {
|
||||||
d = irq_desc + IRQ_NEPONSET_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;
|
return usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#ifdef CONFIG_NO_IDLE_HZ
|
||||||
* We will be entered with IRQs enabled.
|
static unsigned long initial_match;
|
||||||
*
|
static int match_posponed;
|
||||||
* Loop until we get ahead of the free running timer.
|
#endif
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
static irqreturn_t
|
static irqreturn_t
|
||||||
sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
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);
|
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 {
|
do {
|
||||||
timer_tick(regs);
|
timer_tick(regs);
|
||||||
OSSR = OSSR_M0; /* Clear match on timer 0 */
|
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 */
|
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
|
#ifdef CONFIG_PM
|
||||||
unsigned long osmr[4], oier;
|
unsigned long osmr[4], oier;
|
||||||
|
|
||||||
|
@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = {
|
||||||
.suspend = sa1100_timer_suspend,
|
.suspend = sa1100_timer_suspend,
|
||||||
.resume = sa1100_timer_resume,
|
.resume = sa1100_timer_resume,
|
||||||
.offset = sa1100_gettimeoffset,
|
.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;
|
irq += IRQ_SIC_START;
|
||||||
|
|
||||||
desc = irq_desc + irq;
|
desc = irq_desc + irq;
|
||||||
desc->handle(irq, desc, regs);
|
desc_handle_irq(irq, desc, regs);
|
||||||
} while (status);
|
} while (status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
#define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
|
#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 LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */
|
||||||
|
|
||||||
#define RN_BITS(i) ((i >> 16) & 15) /* Rn */
|
#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_skipped;
|
||||||
static unsigned long ai_half;
|
static unsigned long ai_half;
|
||||||
static unsigned long ai_word;
|
static unsigned long ai_word;
|
||||||
|
static unsigned long ai_dword;
|
||||||
static unsigned long ai_multi;
|
static unsigned long ai_multi;
|
||||||
static int ai_usermode;
|
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, "Skipped:\t%lu\n", ai_skipped);
|
||||||
p += sprintf(p, "Half:\t\t%lu\n", ai_half);
|
p += sprintf(p, "Half:\t\t%lu\n", ai_half);
|
||||||
p += sprintf(p, "Word:\t\t%lu\n", ai_word);
|
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, "Multi:\t\t%lu\n", ai_multi);
|
||||||
p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
|
p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode,
|
||||||
usermode_action[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);
|
unsigned int rd = RD_BITS(instr);
|
||||||
|
|
||||||
if ((instr & 0x01f00ff0) == 0x01000090)
|
|
||||||
goto swp;
|
|
||||||
|
|
||||||
if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0)
|
|
||||||
goto bad;
|
|
||||||
|
|
||||||
ai_half += 1;
|
ai_half += 1;
|
||||||
|
|
||||||
if (user_mode(regs))
|
if (user_mode(regs))
|
||||||
|
@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r
|
||||||
|
|
||||||
return TYPE_LDST;
|
return TYPE_LDST;
|
||||||
|
|
||||||
swp:
|
fault:
|
||||||
printk(KERN_ERR "Alignment trap: not handling swp instruction\n");
|
return TYPE_FAULT;
|
||||||
bad:
|
}
|
||||||
return TYPE_ERROR;
|
|
||||||
|
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:
|
fault:
|
||||||
return TYPE_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;
|
regs->ARM_pc += thumb_mode(regs) ? 2 : 4;
|
||||||
|
|
||||||
switch (CODING_BITS(instr)) {
|
switch (CODING_BITS(instr)) {
|
||||||
case 0x00000000: /* ldrh or strh */
|
case 0x00000000: /* 3.13.4 load/store instruction extensions */
|
||||||
if (LDSTH_I_BIT(instr))
|
if (LDSTHD_I_BIT(instr))
|
||||||
offset.un = (instr & 0xf00) >> 4 | (instr & 15);
|
offset.un = (instr & 0xf00) >> 4 | (instr & 15);
|
||||||
else
|
else
|
||||||
offset.un = regs->uregs[RM_BITS(instr)];
|
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;
|
break;
|
||||||
|
|
||||||
case 0x04000000: /* ldr or str immediate */
|
case 0x04000000: /* ldr or str immediate */
|
||||||
|
|
|
@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 16; i += 1) {
|
for (i = 0; i < 16; i += 1) {
|
||||||
alloc_init_section(virt, phys & SUPERSECTION_MASK,
|
alloc_init_section(virt, phys, prot | PMD_SECT_SUPER);
|
||||||
prot | PMD_SECT_SUPER);
|
|
||||||
|
|
||||||
virt += (PGDIR_SIZE / 2);
|
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;
|
pte_t *ptep;
|
||||||
|
|
||||||
if (pmd_none(*pmdp)) {
|
if (pmd_none(*pmdp)) {
|
||||||
unsigned long pmdval;
|
|
||||||
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
|
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
|
||||||
sizeof(pte_t));
|
sizeof(pte_t));
|
||||||
|
|
||||||
pmdval = __pa(ptep) | prot_l1;
|
__pmd_populate(pmdp, __pa(ptep) | prot_l1);
|
||||||
pmdp[0] = __pmd(pmdval);
|
|
||||||
pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
|
|
||||||
flush_pmd_entry(pmdp);
|
|
||||||
}
|
}
|
||||||
ptep = pte_offset_kernel(pmdp, virt);
|
ptep = pte_offset_kernel(pmdp, virt);
|
||||||
|
|
||||||
|
@ -459,7 +453,7 @@ static void __init build_mem_type_table(void)
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
unsigned long v = pgprot_val(protection_map[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);
|
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)
|
void setup_mm_for_reboot(char mode)
|
||||||
{
|
{
|
||||||
unsigned long pmdval;
|
unsigned long base_pmdval;
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pmd_t *pmd;
|
|
||||||
int i;
|
int i;
|
||||||
int cpu_arch = cpu_architecture();
|
|
||||||
|
|
||||||
if (current->mm && current->mm->pgd)
|
if (current->mm && current->mm->pgd)
|
||||||
pgd = current->mm->pgd;
|
pgd = current->mm->pgd;
|
||||||
else
|
else
|
||||||
pgd = init_mm.pgd;
|
pgd = init_mm.pgd;
|
||||||
|
|
||||||
for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) {
|
base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
|
||||||
pmdval = (i << PGDIR_SHIFT) |
|
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ)
|
||||||
PMD_SECT_AP_WRITE | PMD_SECT_AP_READ |
|
base_pmdval |= PMD_BIT4;
|
||||||
PMD_TYPE_SECT;
|
|
||||||
if (cpu_arch <= CPU_ARCH_ARMv5TEJ)
|
for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
|
||||||
pmdval |= PMD_BIT4;
|
unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
|
||||||
|
pmd_t *pmd;
|
||||||
|
|
||||||
pmd = pmd_off(pgd, i << PGDIR_SHIFT);
|
pmd = pmd_off(pgd, i << PGDIR_SHIFT);
|
||||||
pmd[0] = __pmd(pmdval);
|
pmd[0] = __pmd(pmdval);
|
||||||
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
|
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, r1, c5, c0, 0 @ get FSR
|
||||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||||
ldr r8, [r0] @ read arm instruction
|
ldr r8, [r0] @ read arm instruction
|
||||||
tst r8, #1 << 20 @ L = 1 -> write?
|
tst r8, #1 << 20 @ L = 0 -> write?
|
||||||
orreq r1, r1, #1 << 8 @ yes.
|
orreq r1, r1, #1 << 11 @ yes.
|
||||||
and r7, r8, #15 << 24
|
and r7, r8, #15 << 24
|
||||||
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
|
add pc, pc, r7, lsr #22 @ Now branch to the relevant processing routine
|
||||||
nop
|
nop
|
||||||
|
@ -71,8 +71,8 @@ ENTRY(cpu_arm6_data_abort)
|
||||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||||
ldr r8, [r2] @ read arm instruction
|
ldr r8, [r2] @ read arm instruction
|
||||||
tst r8, #1 << 20 @ L = 1 -> write?
|
tst r8, #1 << 20 @ L = 0 -> write?
|
||||||
orreq r1, r1, #1 << 8 @ yes.
|
orreq r1, r1, #1 << 11 @ yes.
|
||||||
and r7, r8, #14 << 24
|
and r7, r8, #14 << 24
|
||||||
teq r7, #8 << 24 @ was it ldm/stm
|
teq r7, #8 << 24 @ was it ldm/stm
|
||||||
movne pc, lr
|
movne pc, lr
|
||||||
|
|
|
@ -590,7 +590,7 @@ static void gpio_irq_handler(unsigned int irq, struct irqdesc *desc,
|
||||||
if (!(isr & 1))
|
if (!(isr & 1))
|
||||||
continue;
|
continue;
|
||||||
d = irq_desc + gpio_irq;
|
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"
|
bool "Kernel profiling support"
|
||||||
|
|
||||||
config SYSTEM_PROFILER
|
config SYSTEM_PROFILER
|
||||||
bool "System profiling support"
|
bool "System profiling support"
|
||||||
|
|
||||||
|
source "lib/Kconfig.debug"
|
||||||
|
|
||||||
config ETRAX_KGDB
|
config ETRAX_KGDB
|
||||||
bool "Use kernel GDB debugger"
|
bool "Use kernel GDB debugger"
|
||||||
|
depends on DEBUG_KERNEL
|
||||||
---help---
|
---help---
|
||||||
The CRIS version of gdb can be used to remotely debug a running
|
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
|
Linux kernel via the serial debug port. Provided you have gdb-cris
|
||||||
|
@ -22,25 +25,11 @@ config ETRAX_KGDB
|
||||||
this option is turned on!
|
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
|
config DEBUG_NMI_OOPS
|
||||||
bool "NMI causes oops printout"
|
bool "NMI causes oops printout"
|
||||||
help
|
depends on DEBUG_KERNEL
|
||||||
If the system locks up without any debug information you can say Y
|
help
|
||||||
here to make it possible to dump an OOPS with an external NMI.
|
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
|
endmenu
|
||||||
|
|
|
@ -71,7 +71,6 @@ EXPORT_SYMBOL(memset);
|
||||||
EXPORT_SYMBOL(memcmp);
|
EXPORT_SYMBOL(memcmp);
|
||||||
EXPORT_SYMBOL(memscan);
|
EXPORT_SYMBOL(memscan);
|
||||||
EXPORT_SYMBOL(memmove);
|
EXPORT_SYMBOL(memmove);
|
||||||
EXPORT_SYMBOL(strtok);
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(get_wchan);
|
EXPORT_SYMBOL(get_wchan);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,10 @@ config X86
|
||||||
486, 586, Pentiums, and various instruction-set-compatible chips by
|
486, 586, Pentiums, and various instruction-set-compatible chips by
|
||||||
AMD, Cyrix, and others.
|
AMD, Cyrix, and others.
|
||||||
|
|
||||||
|
config SEMAPHORE_SLEEPERS
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config MMU
|
config MMU
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
@ -754,6 +758,7 @@ config NUMA
|
||||||
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
|
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
|
||||||
default n if X86_PC
|
default n if X86_PC
|
||||||
default y if (X86_NUMAQ || X86_SUMMIT)
|
default y if (X86_NUMAQ || X86_SUMMIT)
|
||||||
|
select SPARSEMEM_STATIC
|
||||||
|
|
||||||
# Need comments to help the hapless user trying to turn on NUMA support
|
# Need comments to help the hapless user trying to turn on NUMA support
|
||||||
comment "NUMA (NUMA-Q) requires SMP, 64GB highmem 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 \
|
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 \
|
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 \
|
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 += cpu/
|
||||||
obj-y += timers/
|
obj-y += timers/
|
||||||
|
|
|
@ -833,6 +833,9 @@ acpi_process_madt(void)
|
||||||
if (!error) {
|
if (!error) {
|
||||||
acpi_lapic = 1;
|
acpi_lapic = 1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_GENERICARCH
|
||||||
|
generic_bigsmp_probe();
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Parse MADT IO-APIC entries
|
* Parse MADT IO-APIC entries
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -613,8 +613,8 @@ void __devinit cpu_init(void)
|
||||||
memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
|
memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
|
||||||
GDT_ENTRY_TLS_ENTRIES * 8);
|
GDT_ENTRY_TLS_ENTRIES * 8);
|
||||||
|
|
||||||
__asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
|
load_gdt(&cpu_gdt_descr[cpu]);
|
||||||
__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
|
load_idt(&idt_descr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete NT
|
* Delete NT
|
||||||
|
@ -642,12 +642,12 @@ void __devinit cpu_init(void)
|
||||||
asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
|
asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
|
||||||
|
|
||||||
/* Clear all 6 debug registers: */
|
/* Clear all 6 debug registers: */
|
||||||
|
set_debugreg(0, 0);
|
||||||
#define CD(register) set_debugreg(0, register)
|
set_debugreg(0, 1);
|
||||||
|
set_debugreg(0, 2);
|
||||||
CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
|
set_debugreg(0, 3);
|
||||||
|
set_debugreg(0, 6);
|
||||||
#undef CD
|
set_debugreg(0, 7);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force FPU initialization:
|
* Force FPU initialization:
|
||||||
|
|
|
@ -64,8 +64,6 @@ static int dont_scale_voltage;
|
||||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
|
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
|
||||||
|
|
||||||
|
|
||||||
#define __hlt() __asm__ __volatile__("hlt": : :"memory")
|
|
||||||
|
|
||||||
/* Clock ratios multiplied by 10 */
|
/* Clock ratios multiplied by 10 */
|
||||||
static int clock_ratio[32];
|
static int clock_ratio[32];
|
||||||
static int eblcr_table[32];
|
static int eblcr_table[32];
|
||||||
|
@ -168,11 +166,9 @@ static void do_powersaver(union msr_longhaul *longhaul,
|
||||||
outb(0xFE,0x21); /* TMR0 only */
|
outb(0xFE,0x21); /* TMR0 only */
|
||||||
outb(0xFF,0x80); /* delay */
|
outb(0xFF,0x80); /* delay */
|
||||||
|
|
||||||
local_irq_enable();
|
safe_halt();
|
||||||
|
|
||||||
__hlt();
|
|
||||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
|
||||||
__hlt();
|
halt();
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
|
|
||||||
|
@ -251,9 +247,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
||||||
bcr2.bits.CLOCKMUL = clock_ratio_index;
|
bcr2.bits.CLOCKMUL = clock_ratio_index;
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
wrmsrl (MSR_VIA_BCR2, bcr2.val);
|
wrmsrl (MSR_VIA_BCR2, bcr2.val);
|
||||||
local_irq_enable();
|
safe_halt();
|
||||||
|
|
||||||
__hlt();
|
|
||||||
|
|
||||||
/* Disable software clock multiplier */
|
/* Disable software clock multiplier */
|
||||||
rdmsrl (MSR_VIA_BCR2, bcr2.val);
|
rdmsrl (MSR_VIA_BCR2, bcr2.val);
|
||||||
|
|
|
@ -132,11 +132,7 @@ static void __init set_cx86_memwb(void)
|
||||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
|
setCx86(CX86_CCR2, getCx86(CX86_CCR2) & ~0x04);
|
||||||
/* set 'Not Write-through' */
|
/* set 'Not Write-through' */
|
||||||
cr0 = 0x20000000;
|
cr0 = 0x20000000;
|
||||||
__asm__("movl %%cr0,%%eax\n\t"
|
write_cr0(read_cr0() | cr0);
|
||||||
"orl %0,%%eax\n\t"
|
|
||||||
"movl %%eax,%%cr0\n"
|
|
||||||
: : "r" (cr0)
|
|
||||||
:"ax");
|
|
||||||
/* CCR2 bit 2: lock NW bit and set WT1 */
|
/* CCR2 bit 2: lock NW bit and set WT1 */
|
||||||
setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
|
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)
|
static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
unsigned int eax;
|
unsigned int eax, ebx, ecx, edx;
|
||||||
|
|
||||||
if (c->cpuid_level < 4)
|
if (c->cpuid_level < 4)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
__asm__("cpuid"
|
/* Intel has a non-standard dependency on %ecx for this CPUID level. */
|
||||||
: "=a" (eax)
|
cpuid_count(4, 0, &eax, &ebx, &ecx, &edx);
|
||||||
: "0" (4), "c" (0)
|
|
||||||
: "bx", "dx");
|
|
||||||
|
|
||||||
if (eax & 0x1f)
|
if (eax & 0x1f)
|
||||||
return ((eax >> 26) + 1);
|
return ((eax >> 26) + 1);
|
||||||
else
|
else
|
||||||
|
|
|
@ -305,6 +305,9 @@ static void __devinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
|
||||||
{
|
{
|
||||||
struct _cpuid4_info *this_leaf;
|
struct _cpuid4_info *this_leaf;
|
||||||
unsigned long num_threads_sharing;
|
unsigned long num_threads_sharing;
|
||||||
|
#ifdef CONFIG_X86_HT
|
||||||
|
struct cpuinfo_x86 *c = cpu_data + cpu;
|
||||||
|
#endif
|
||||||
|
|
||||||
this_leaf = CPUID4_INFO_IDX(cpu, index);
|
this_leaf = CPUID4_INFO_IDX(cpu, index);
|
||||||
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
|
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
|
#ifdef CONFIG_X86_HT
|
||||||
else if (num_threads_sharing == smp_num_siblings)
|
else if (num_threads_sharing == smp_num_siblings)
|
||||||
this_leaf->shared_cpu_map = cpu_sibling_map[cpu];
|
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
|
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");
|
"any known set of CPUs\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static void __init cache_shared_cpu_map_setup(unsigned int cpu, int index) {}
|
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 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 i;
|
||||||
int size = num_var_ranges * sizeof(struct mtrr_value);
|
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();
|
disable_local_APIC();
|
||||||
atomic_dec(&waiting_for_crash_ipi);
|
atomic_dec(&waiting_for_crash_ipi);
|
||||||
/* Assume hlt works */
|
/* Assume hlt works */
|
||||||
__asm__("hlt");
|
halt();
|
||||||
for(;;);
|
for(;;);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -20,7 +20,7 @@ static void doublefault_fn(void)
|
||||||
struct Xgt_desc_struct gdt_desc = {0, 0};
|
struct Xgt_desc_struct gdt_desc = {0, 0};
|
||||||
unsigned long gdt, tss;
|
unsigned long gdt, tss;
|
||||||
|
|
||||||
__asm__ __volatile__("sgdt %0": "=m" (gdt_desc): :"memory");
|
store_gdt(&gdt_desc);
|
||||||
gdt = gdt_desc.address;
|
gdt = gdt_desc.address;
|
||||||
|
|
||||||
printk("double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size);
|
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
|
* directory. If I have PSE, I just need to duplicate one entry in
|
||||||
* page directory.
|
* page directory.
|
||||||
*/
|
*/
|
||||||
__asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
|
cr4 = read_cr4();
|
||||||
|
|
||||||
if (cr4 & X86_CR4_PSE) {
|
if (cr4 & X86_CR4_PSE) {
|
||||||
efi_bak_pg_dir_pointer[0].pgd =
|
efi_bak_pg_dir_pointer[0].pgd =
|
||||||
|
@ -104,8 +104,7 @@ static void efi_call_phys_prelog(void)
|
||||||
local_flush_tlb();
|
local_flush_tlb();
|
||||||
|
|
||||||
cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
|
cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
|
||||||
__asm__ __volatile__("lgdt %0":"=m"
|
load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
|
||||||
(*(struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void efi_call_phys_epilog(void)
|
static void efi_call_phys_epilog(void)
|
||||||
|
@ -114,8 +113,8 @@ static void efi_call_phys_epilog(void)
|
||||||
|
|
||||||
cpu_gdt_descr[0].address =
|
cpu_gdt_descr[0].address =
|
||||||
(unsigned long) __va(cpu_gdt_descr[0].address);
|
(unsigned long) __va(cpu_gdt_descr[0].address);
|
||||||
__asm__ __volatile__("lgdt %0":"=m"(cpu_gdt_descr));
|
load_gdt(&cpu_gdt_descr[0]);
|
||||||
__asm__ __volatile__("movl %%cr4, %0":"=r"(cr4));
|
cr4 = read_cr4();
|
||||||
|
|
||||||
if (cr4 & X86_CR4_PSE) {
|
if (cr4 & X86_CR4_PSE) {
|
||||||
swapper_pg_dir[pgd_index(0)].pgd =
|
swapper_pg_dir[pgd_index(0)].pgd =
|
||||||
|
@ -233,22 +232,23 @@ void __init efi_map_memmap(void)
|
||||||
{
|
{
|
||||||
memmap.map = NULL;
|
memmap.map = NULL;
|
||||||
|
|
||||||
memmap.map = (efi_memory_desc_t *)
|
memmap.map = bt_ioremap((unsigned long) memmap.phys_map,
|
||||||
bt_ioremap((unsigned long) memmap.phys_map,
|
(memmap.nr_map * memmap.desc_size));
|
||||||
(memmap.nr_map * sizeof(efi_memory_desc_t)));
|
|
||||||
|
|
||||||
if (memmap.map == NULL)
|
if (memmap.map == NULL)
|
||||||
printk(KERN_ERR PFX "Could not remap the EFI memmap!\n");
|
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
|
#if EFI_DEBUG
|
||||||
static void __init print_efi_memmap(void)
|
static void __init print_efi_memmap(void)
|
||||||
{
|
{
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
|
void *p;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < memmap.nr_map; i++) {
|
for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) {
|
||||||
md = &memmap.map[i];
|
md = p;
|
||||||
printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
|
printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, "
|
||||||
"range=[0x%016llx-0x%016llx) (%lluMB)\n",
|
"range=[0x%016llx-0x%016llx) (%lluMB)\n",
|
||||||
i, md->type, md->attribute, md->phys_addr,
|
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;
|
} prev, curr;
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
unsigned long start, end;
|
unsigned long start, end;
|
||||||
int i;
|
void *p;
|
||||||
|
|
||||||
for (i = 0; i < memmap.nr_map; i++) {
|
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||||
md = &memmap.map[i];
|
md = p;
|
||||||
|
|
||||||
if ((md->num_pages == 0) || (!is_available_memory(md)))
|
if ((md->num_pages == 0) || (!is_available_memory(md)))
|
||||||
continue;
|
continue;
|
||||||
|
@ -325,6 +325,7 @@ void __init efi_init(void)
|
||||||
memmap.phys_map = EFI_MEMMAP;
|
memmap.phys_map = EFI_MEMMAP;
|
||||||
memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
|
memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE;
|
||||||
memmap.desc_version = EFI_MEMDESC_VERSION;
|
memmap.desc_version = EFI_MEMDESC_VERSION;
|
||||||
|
memmap.desc_size = EFI_MEMDESC_SIZE;
|
||||||
|
|
||||||
efi.systab = (efi_system_table_t *)
|
efi.systab = (efi_system_table_t *)
|
||||||
boot_ioremap((unsigned long) efi_phys.systab,
|
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");
|
printk(KERN_ERR PFX "Could not map the runtime service table!\n");
|
||||||
|
|
||||||
/* Map the EFI memory map for use until paging_init() */
|
/* Map the EFI memory map for use until paging_init() */
|
||||||
|
memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
|
||||||
memmap.map = (efi_memory_desc_t *)
|
|
||||||
boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE);
|
|
||||||
|
|
||||||
if (memmap.map == NULL)
|
if (memmap.map == NULL)
|
||||||
printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
|
printk(KERN_ERR PFX "Could not map the EFI memory map!\n");
|
||||||
|
|
||||||
if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) {
|
memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size);
|
||||||
printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't "
|
|
||||||
"match the one from EFI!\n");
|
|
||||||
}
|
|
||||||
#if EFI_DEBUG
|
#if EFI_DEBUG
|
||||||
print_efi_memmap();
|
print_efi_memmap();
|
||||||
#endif
|
#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.
|
* This function will switch the EFI runtime services to virtual mode.
|
||||||
* Essentially, look through the EFI memmap and map every region that
|
* 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_memory_desc_t *md;
|
||||||
efi_status_t status;
|
efi_status_t status;
|
||||||
int i;
|
void *p;
|
||||||
|
|
||||||
efi.systab = NULL;
|
efi.systab = NULL;
|
||||||
|
|
||||||
for (i = 0; i < memmap.nr_map; i++) {
|
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||||
md = &memmap.map[i];
|
md = p;
|
||||||
|
|
||||||
if (md->attribute & EFI_MEMORY_RUNTIME) {
|
if (!(md->attribute & EFI_MEMORY_RUNTIME))
|
||||||
md->virt_addr =
|
continue;
|
||||||
(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 (((unsigned long)md->phys_addr <=
|
md->virt_addr = (unsigned long)ioremap(md->phys_addr,
|
||||||
(unsigned long)efi_phys.systab) &&
|
md->num_pages << EFI_PAGE_SHIFT);
|
||||||
((unsigned long)efi_phys.systab <
|
if (!(unsigned long)md->virt_addr) {
|
||||||
md->phys_addr +
|
printk(KERN_ERR PFX "ioremap of 0x%lX failed\n",
|
||||||
((unsigned long)md->num_pages <<
|
(unsigned long)md->phys_addr);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* update the virtual address of the EFI system table */
|
||||||
|
check_range_for_systab(md);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!efi.systab)
|
if (!efi.systab)
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
status = phys_efi_set_virtual_address_map(
|
status = phys_efi_set_virtual_address_map(
|
||||||
sizeof(efi_memory_desc_t) * memmap.nr_map,
|
memmap.desc_size * memmap.nr_map,
|
||||||
sizeof(efi_memory_desc_t),
|
memmap.desc_size,
|
||||||
memmap.desc_version,
|
memmap.desc_version,
|
||||||
memmap.phys_map);
|
memmap.phys_map);
|
||||||
|
|
||||||
|
@ -533,10 +531,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
|
||||||
{
|
{
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
int i;
|
void *p;
|
||||||
|
|
||||||
for (i = 0; i < memmap.nr_map; i++) {
|
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||||
md = &memmap.map[i];
|
md = p;
|
||||||
|
|
||||||
if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
|
if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >
|
||||||
0x100000000ULL)
|
0x100000000ULL)
|
||||||
|
@ -613,10 +611,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
|
||||||
u32 efi_mem_type(unsigned long phys_addr)
|
u32 efi_mem_type(unsigned long phys_addr)
|
||||||
{
|
{
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
int i;
|
void *p;
|
||||||
|
|
||||||
for (i = 0; i < memmap.nr_map; i++) {
|
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||||
md = &memmap.map[i];
|
md = p;
|
||||||
if ((md->phys_addr <= phys_addr) && (phys_addr <
|
if ((md->phys_addr <= phys_addr) && (phys_addr <
|
||||||
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
|
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
|
||||||
return md->type;
|
return md->type;
|
||||||
|
@ -627,10 +625,10 @@ u32 efi_mem_type(unsigned long phys_addr)
|
||||||
u64 efi_mem_attributes(unsigned long phys_addr)
|
u64 efi_mem_attributes(unsigned long phys_addr)
|
||||||
{
|
{
|
||||||
efi_memory_desc_t *md;
|
efi_memory_desc_t *md;
|
||||||
int i;
|
void *p;
|
||||||
|
|
||||||
for (i = 0; i < memmap.nr_map; i++) {
|
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
|
||||||
md = &memmap.map[i];
|
md = p;
|
||||||
if ((md->phys_addr <= phys_addr) && (phys_addr <
|
if ((md->phys_addr <= phys_addr) && (phys_addr <
|
||||||
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
|
(md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) ))
|
||||||
return md->attribute;
|
return md->attribute;
|
||||||
|
|
|
@ -203,7 +203,7 @@ sysenter_past_esp:
|
||||||
GET_THREAD_INFO(%ebp)
|
GET_THREAD_INFO(%ebp)
|
||||||
|
|
||||||
/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
|
/* 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
|
jnz syscall_trace_entry
|
||||||
cmpl $(nr_syscalls), %eax
|
cmpl $(nr_syscalls), %eax
|
||||||
jae syscall_badsys
|
jae syscall_badsys
|
||||||
|
@ -226,9 +226,9 @@ ENTRY(system_call)
|
||||||
pushl %eax # save orig_eax
|
pushl %eax # save orig_eax
|
||||||
SAVE_ALL
|
SAVE_ALL
|
||||||
GET_THREAD_INFO(%ebp)
|
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 */
|
/* 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
|
jnz syscall_trace_entry
|
||||||
cmpl $(nr_syscalls), %eax
|
cmpl $(nr_syscalls), %eax
|
||||||
jae syscall_badsys
|
jae syscall_badsys
|
||||||
|
@ -338,6 +338,9 @@ syscall_trace_entry:
|
||||||
movl %esp, %eax
|
movl %esp, %eax
|
||||||
xorl %edx,%edx
|
xorl %edx,%edx
|
||||||
call do_syscall_trace
|
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
|
movl ORIG_EAX(%esp), %eax
|
||||||
cmpl $(nr_syscalls), %eax
|
cmpl $(nr_syscalls), %eax
|
||||||
jnae syscall_call
|
jnae syscall_call
|
||||||
|
|
|
@ -77,6 +77,32 @@ ENTRY(startup_32)
|
||||||
subl %edi,%ecx
|
subl %edi,%ecx
|
||||||
shrl $2,%ecx
|
shrl $2,%ecx
|
||||||
rep ; stosl
|
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
|
* Initialize page tables. This creates a PDE and a set of page
|
||||||
|
@ -214,28 +240,6 @@ ENTRY(startup_32_smp)
|
||||||
*/
|
*/
|
||||||
call setup_idt
|
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:
|
checkCPUtype:
|
||||||
|
|
||||||
movl $-1,X86_CPUID # -1 for no CPUID initially
|
movl $-1,X86_CPUID # -1 for no CPUID initially
|
||||||
|
|
67
arch/i386/kernel/i8237.c
Normal file
67
arch/i386/kernel/i8237.c
Normal file
|
@ -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;
|
volatile struct pt_regs * regs = (struct pt_regs *) &unused;
|
||||||
unsigned int level = regs->ebx;
|
unsigned int level = regs->ebx;
|
||||||
unsigned int old = (regs->eflags >> 12) & 3;
|
unsigned int old = (regs->eflags >> 12) & 3;
|
||||||
|
struct thread_struct *t = ¤t->thread;
|
||||||
|
|
||||||
if (level > 3)
|
if (level > 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -140,8 +141,8 @@ asmlinkage long sys_iopl(unsigned long unused)
|
||||||
if (!capable(CAP_SYS_RAWIO))
|
if (!capable(CAP_SYS_RAWIO))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
|
t->iopl = level << 12;
|
||||||
/* Make sure we return the long way (not sysenter) */
|
regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
|
||||||
set_thread_flag(TIF_IRET);
|
set_iopl_mask(t->iopl);
|
||||||
return 0;
|
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)
|
static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
|
||||||
{
|
{
|
||||||
struct mm_struct * mm = current->mm;
|
struct mm_struct * mm = current->mm;
|
||||||
__u32 entry_1, entry_2, *lp;
|
__u32 entry_1, entry_2;
|
||||||
int error;
|
int error;
|
||||||
struct user_desc ldt_info;
|
struct user_desc ldt_info;
|
||||||
|
|
||||||
|
@ -205,8 +205,6 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
|
|
||||||
|
|
||||||
/* Allow LDTs to be cleared by the user. */
|
/* Allow LDTs to be cleared by the user. */
|
||||||
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
|
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
|
||||||
if (oldmode || LDT_empty(&ldt_info)) {
|
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 the new entry ... */
|
||||||
install:
|
install:
|
||||||
*lp = entry_1;
|
write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1, entry_2);
|
||||||
*(lp+1) = entry_2;
|
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
|
|
|
@ -17,13 +17,7 @@
|
||||||
#include <asm/apic.h>
|
#include <asm/apic.h>
|
||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
|
#include <asm/system.h>
|
||||||
static inline unsigned long read_cr3(void)
|
|
||||||
{
|
|
||||||
unsigned long cr3;
|
|
||||||
asm volatile("movl %%cr3,%0": "=r"(cr3));
|
|
||||||
return cr3;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
|
#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
|
||||||
|
|
||||||
|
@ -99,10 +93,7 @@ static void set_idt(void *newidt, __u16 limit)
|
||||||
curidt.size = limit;
|
curidt.size = limit;
|
||||||
curidt.address = (unsigned long)newidt;
|
curidt.address = (unsigned long)newidt;
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
load_idt(&curidt);
|
||||||
"lidtl %0\n"
|
|
||||||
: : "m" (curidt)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,10 +105,7 @@ static void set_gdt(void *newgdt, __u16 limit)
|
||||||
curgdt.size = limit;
|
curgdt.size = limit;
|
||||||
curgdt.address = (unsigned long)newgdt;
|
curgdt.address = (unsigned long)newgdt;
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
load_gdt(&curgdt);
|
||||||
"lgdtl %0\n"
|
|
||||||
: : "m" (curgdt)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void load_segments(void)
|
static void load_segments(void)
|
||||||
|
|
|
@ -164,7 +164,8 @@ static void collect_cpu_info (void *unused)
|
||||||
}
|
}
|
||||||
|
|
||||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
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 */
|
/* get the current revision from MSR 0x8B */
|
||||||
rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
|
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",
|
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);
|
(unsigned long) uci->mc->bits >> 16 >> 16);
|
||||||
wrmsr(MSR_IA32_UCODE_REV, 0, 0);
|
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 */
|
/* get the current revision from MSR 0x8B */
|
||||||
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,8 @@ int nr_ioapics;
|
||||||
int pic_mode;
|
int pic_mode;
|
||||||
unsigned long mp_lapic_addr;
|
unsigned long mp_lapic_addr;
|
||||||
|
|
||||||
|
unsigned int def_to_bigsmp = 0;
|
||||||
|
|
||||||
/* Processor that is doing the boot up */
|
/* Processor that is doing the boot up */
|
||||||
unsigned int boot_cpu_physical_apicid = -1U;
|
unsigned int boot_cpu_physical_apicid = -1U;
|
||||||
/* Internal processor count */
|
/* 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)
|
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;
|
physid_mask_t tmp;
|
||||||
|
|
||||||
if (!(m->mpc_cpuflag & CPU_ENABLED))
|
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) {
|
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
|
||||||
Dprintk(" Bootup CPU\n");
|
Dprintk(" Bootup CPU\n");
|
||||||
boot_cpu_physical_apicid = m->mpc_apicid;
|
boot_cpu_physical_apicid = m->mpc_apicid;
|
||||||
|
found_bsp = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_processors >= NR_CPUS) {
|
if (num_processors >= NR_CPUS) {
|
||||||
|
@ -202,6 +205,11 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (found_bsp)
|
||||||
|
cpu = 0;
|
||||||
|
else
|
||||||
|
cpu = num_processors - 1;
|
||||||
|
cpu_set(cpu, cpu_possible_map);
|
||||||
tmp = apicid_to_cpu_present(apicid);
|
tmp = apicid_to_cpu_present(apicid);
|
||||||
physids_or(phys_cpu_present_map, phys_cpu_present_map, tmp);
|
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;
|
ver = 0x10;
|
||||||
}
|
}
|
||||||
apic_version[m->mpc_apicid] = ver;
|
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;
|
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,23 +46,13 @@
|
||||||
|
|
||||||
static struct class *msr_class;
|
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)
|
static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
asm volatile ("1: wrmsr\n"
|
err = wrmsr_safe(reg, eax, edx);
|
||||||
"2:\n"
|
if (err)
|
||||||
".section .fixup,\"ax\"\n"
|
err = -EIO;
|
||||||
"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));
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,18 +60,9 @@ static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
asm volatile ("1: rdmsr\n"
|
err = rdmsr_safe(reg, eax, edx);
|
||||||
"2:\n"
|
if (err)
|
||||||
".section .fixup,\"ax\"\n"
|
err = -EIO;
|
||||||
"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));
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -501,8 +501,11 @@ void nmi_watchdog_tick (struct pt_regs * regs)
|
||||||
*/
|
*/
|
||||||
alert_counter[cpu]++;
|
alert_counter[cpu]++;
|
||||||
if (alert_counter[cpu] == 5*nmi_hz)
|
if (alert_counter[cpu] == 5*nmi_hz)
|
||||||
|
/*
|
||||||
|
* die_nmi will return ONLY if NOTIFY_STOP happens..
|
||||||
|
*/
|
||||||
die_nmi(regs, "NMI Watchdog detected LOCKUP");
|
die_nmi(regs, "NMI Watchdog detected LOCKUP");
|
||||||
} else {
|
|
||||||
last_irq_sums[cpu] = sum;
|
last_irq_sums[cpu] = sum;
|
||||||
alert_counter[cpu] = 0;
|
alert_counter[cpu] = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ static inline void play_dead(void)
|
||||||
*/
|
*/
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
while (1)
|
while (1)
|
||||||
__asm__ __volatile__("hlt":::"memory");
|
halt();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void play_dead(void)
|
static inline void play_dead(void)
|
||||||
|
@ -313,16 +313,12 @@ void show_regs(struct pt_regs * regs)
|
||||||
printk(" DS: %04x ES: %04x\n",
|
printk(" DS: %04x ES: %04x\n",
|
||||||
0xffff & regs->xds,0xffff & regs->xes);
|
0xffff & regs->xds,0xffff & regs->xes);
|
||||||
|
|
||||||
__asm__("movl %%cr0, %0": "=r" (cr0));
|
cr0 = read_cr0();
|
||||||
__asm__("movl %%cr2, %0": "=r" (cr2));
|
cr2 = read_cr2();
|
||||||
__asm__("movl %%cr3, %0": "=r" (cr3));
|
cr3 = read_cr3();
|
||||||
/* This could fault if %cr4 does not exist */
|
if (current_cpu_data.x86 > 4) {
|
||||||
__asm__("1: movl %%cr4, %0 \n"
|
cr4 = read_cr4();
|
||||||
"2: \n"
|
}
|
||||||
".section __ex_table,\"a\" \n"
|
|
||||||
".long 1b,2b \n"
|
|
||||||
".previous \n"
|
|
||||||
: "=r" (cr4): "0" (0));
|
|
||||||
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
|
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
|
||||||
show_trace(NULL, ®s->esp);
|
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);
|
__unlazy_fpu(prev_p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reload esp0, LDT and the page table pointer:
|
* Reload esp0.
|
||||||
*/
|
*/
|
||||||
load_esp0(tss, next);
|
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 the per-thread Thread-Local Storage descriptor.
|
||||||
*/
|
*/
|
||||||
load_TLS(next, cpu);
|
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.
|
* 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)
|
if (prev->gs | next->gs)
|
||||||
loadsegment(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
|
* 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)
|
void ptrace_disable(struct task_struct *child)
|
||||||
{
|
{
|
||||||
clear_singlestep(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;
|
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_SYSCALL: /* continue and stop at next (return from) syscall */
|
||||||
case PTRACE_CONT: /* restart after signal. */
|
case PTRACE_CONT: /* restart after signal. */
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (!valid_signal(data))
|
if (!valid_signal(data))
|
||||||
break;
|
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);
|
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
}
|
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||||
else {
|
} else {
|
||||||
|
clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
|
||||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
}
|
}
|
||||||
child->exit_code = data;
|
child->exit_code = data;
|
||||||
|
@ -542,10 +549,17 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
|
||||||
wake_up_process(child);
|
wake_up_process(child);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PTRACE_SYSEMU_SINGLESTEP: /* Same as SYSEMU, but singlestep if not syscall */
|
||||||
case PTRACE_SINGLESTEP: /* set the trap flag. */
|
case PTRACE_SINGLESTEP: /* set the trap flag. */
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (!valid_signal(data))
|
if (!valid_signal(data))
|
||||||
break;
|
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);
|
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||||
set_singlestep(child);
|
set_singlestep(child);
|
||||||
child->exit_code = data;
|
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
|
* - triggered by current->work.syscall_trace
|
||||||
*/
|
*/
|
||||||
__attribute__((regparm(3)))
|
__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 */
|
/* do the secure computing check first */
|
||||||
secure_computing(regs->orig_eax);
|
secure_computing(regs->orig_eax);
|
||||||
|
|
||||||
if (unlikely(current->audit_context) && entryexit)
|
if (unlikely(current->audit_context)) {
|
||||||
audit_syscall_exit(current, AUDITSC_RESULT(regs->eax), regs->eax);
|
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))
|
if (!(current->ptrace & PT_PTRACED))
|
||||||
goto out;
|
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 */
|
/* Fake a debug trap */
|
||||||
if (test_thread_flag(TIF_SINGLESTEP))
|
if (is_singlestep)
|
||||||
send_sigtrap(current, regs, 0);
|
send_sigtrap(current, regs, 0);
|
||||||
|
|
||||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* the 0x80 provides a way for the tracing parent to distinguish
|
/* the 0x80 provides a way for the tracing parent to distinguish
|
||||||
between a syscall stop and SIGTRAP delivery */
|
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));
|
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);
|
send_sig(current->exit_code, current, 1);
|
||||||
current->exit_code = 0;
|
current->exit_code = 0;
|
||||||
}
|
}
|
||||||
|
ret = is_sysemu;
|
||||||
out:
|
out:
|
||||||
if (unlikely(current->audit_context) && !entryexit)
|
if (unlikely(current->audit_context) && !entryexit)
|
||||||
audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
|
audit_syscall_entry(current, AUDIT_ARCH_I386, regs->orig_eax,
|
||||||
regs->ebx, regs->ecx, regs->edx, regs->esi);
|
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 <linux/dmi.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/apic.h>
|
#include <asm/apic.h>
|
||||||
|
#include <asm/desc.h>
|
||||||
#include "mach_reboot.h"
|
#include "mach_reboot.h"
|
||||||
#include <linux/reboot_fixups.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. */
|
/* 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
|
/* 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
|
mode. The GDT is not used in real mode; it is just needed here to
|
||||||
prepare the descriptors. */
|
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
|
/* Load the data segment registers, and thus the descriptors ready for
|
||||||
real mode. The base address of each segment is 0x100, 16 times the
|
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 (!reboot_thru_bios) {
|
||||||
if (efi_enabled) {
|
if (efi_enabled) {
|
||||||
efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
|
efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
|
||||||
__asm__ __volatile__("lidt %0": :"m" (no_idt));
|
load_idt(&no_idt);
|
||||||
__asm__ __volatile__("int3");
|
__asm__ __volatile__("int3");
|
||||||
}
|
}
|
||||||
/* rebooting needs to touch the page at absolute addr 0 */
|
/* 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_fixups(); /* for board specific fixups */
|
||||||
mach_reboot();
|
mach_reboot();
|
||||||
/* That didn't work - force a triple fault.. */
|
/* That didn't work - force a triple fault.. */
|
||||||
__asm__ __volatile__("lidt %0": :"m" (no_idt));
|
load_idt(&no_idt);
|
||||||
__asm__ __volatile__("int3");
|
__asm__ __volatile__("int3");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,170 +13,8 @@
|
||||||
* rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
|
* rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
|
||||||
*/
|
*/
|
||||||
#include <linux/config.h>
|
#include <linux/config.h>
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <asm/semaphore.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
|
* The semaphore operations have a special calling sequence that
|
||||||
* allow us to do a simpler in-line version of them. These routines
|
* 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…
Add table
Reference in a new issue