diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS Mon Mar 17 13:45:14 2003
+++ b/CREDITS Mon Mar 17 13:45:14 2003
@@ -3492,9 +3492,9 @@
N: Marc Zyngier
E: maz@wild-wind.fr.eu.org
+W: http://www.misterjones.org
D: MD driver
-S: 11 rue Victor HUGO
-S: 95560 Montsoult
+D: EISA/sysfs subsystem
S: France
# Don't add your name here, unless you really _are_ after Marc
diff -Nru a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl
--- a/Documentation/DocBook/journal-api.tmpl Mon Mar 17 13:45:09 2003
+++ b/Documentation/DocBook/journal-api.tmpl Mon Mar 17 13:45:09 2003
@@ -216,7 +216,7 @@
A new feature of jbd since 2.5.25 is commit callbacks with the new
journal_callback_set() function you can now ask the journalling layer
-to call you back when the transaction is finally commited to disk, so that
+to call you back when the transaction is finally committed to disk, so that
you can do some of your own management. The key to this is the journal_callback
struct, this maintains the internal callback information but you can
extend it like this:-
@@ -232,7 +232,7 @@
-this would be useful if you needed to know when data was commited to a
+this would be useful if you needed to know when data was committed to a
particular inode.
diff -Nru a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl
--- a/Documentation/DocBook/sis900.tmpl Mon Mar 17 13:45:13 2003
+++ b/Documentation/DocBook/sis900.tmpl Mon Mar 17 13:45:13 2003
@@ -536,7 +536,7 @@
November 13, 2000, Revision 1.07, seventh release, 630E problem fixed
-and furthur clean up.
+and further clean up.
diff -Nru a/Documentation/arm/Booting b/Documentation/arm/Booting
--- a/Documentation/arm/Booting Mon Mar 17 13:45:14 2003
+++ b/Documentation/arm/Booting Mon Mar 17 13:45:14 2003
@@ -47,7 +47,7 @@
used for debugging purposes, or communication with the target.)
As an alternative, the boot loader can pass the relevant 'console='
-option to the kernel via the tagged lists specifing the port, and
+option to the kernel via the tagged lists specifying the port, and
serial format options as described in
linux/Documentation/kernel-parameters.txt.
diff -Nru a/Documentation/arm/SA1100/serial_UART b/Documentation/arm/SA1100/serial_UART
--- a/Documentation/arm/SA1100/serial_UART Mon Mar 17 13:45:12 2003
+++ b/Documentation/arm/SA1100/serial_UART Mon Mar 17 13:45:12 2003
@@ -39,7 +39,7 @@
name. The classic example is the content of the /etc/inittab file where
you might have a getty process started on ttyS0. In this case:
-- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
+- replace occurrences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc.
- don't forget to add 'ttySA0', 'console', or the appropriate tty name
in /etc/securetty for root to be allowed to login as well.
diff -Nru a/Documentation/arm/Setup b/Documentation/arm/Setup
--- a/Documentation/arm/Setup Mon Mar 17 13:45:09 2003
+++ b/Documentation/arm/Setup Mon Mar 17 13:45:09 2003
@@ -97,7 +97,7 @@
initrd_size
This describes the kernel virtual start address and size of the
- inital ramdisk.
+ initial ramdisk.
rd_start
diff -Nru a/Documentation/arm/XScale/IOP3XX/dma.txt b/Documentation/arm/XScale/IOP3XX/dma.txt
--- a/Documentation/arm/XScale/IOP3XX/dma.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/arm/XScale/IOP3XX/dma.txt Mon Mar 17 13:45:14 2003
@@ -142,7 +142,7 @@
/* User's responsibility to keep buffers cached coherent */
cpu_dcache_clean(sgl->data, sgl->data + 1024);
- /* queing the buffer, this function will sleep since no callback */
+ /* queuing the buffer, this function will sleep since no callback */
err = dma_queue_buffer(channel, sgl_head);
/* now we are woken from DMA complete */
@@ -186,7 +186,7 @@
int dma_flush_all(dmach_t channel);
This completely flushes all queued buffers and on-going DMA transfers on a
-given channel. This is called when DMA channel errors have occured.
+given channel. This is called when DMA channel errors have occurred.
void dma_free(dmach_t channel);
diff -Nru a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment
--- a/Documentation/arm/mem_alignment Mon Mar 17 13:45:12 2003
+++ b/Documentation/arm/mem_alignment Mon Mar 17 13:45:12 2003
@@ -51,7 +51,7 @@
echo 1 > /proc/sys/debug/alignment
You can also read the content of the same file to get statistical
-information on unaligned access occurences plus the current mode of
+information on unaligned access occurrences plus the current mode of
operation for user space code.
diff -Nru a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/Documentation/basic_profiling.txt Mon Mar 17 13:45:16 2003
@@ -0,0 +1,48 @@
+These instructions are deliberately very basic. If you want something clever,
+go read the real docs ;-) Please don't add more stuff, but feel free to
+correct my mistakes ;-) (mbligh@aracnet.com)
+Thanks to John Levon, Dave Hansen, et al. for help writing this.
+
+ is the thing you're trying to measure.
+Make sure you have the correct System.map / vmlinux referenced!
+IMHO it's easier to use "make install" for linux and hack /sbin/installkernel
+to copy config files, system.map, vmlinux to /boot.
+
+Readprofile
+-----------
+You need a fixed readprofile command for 2.5 ... either get hold of
+a current version from:
+http://www.kernel.org/pub/linux/utils/util-linux/
+or get readprofile binary fixed for 2.5 / akpm's 2.5 patch from
+ftp://ftp.kernel.org/pub/linux/kernel/people/mbligh/tools/readprofile/
+
+Add "profile=2" to the kernel command line.
+
+clear readprofile -r
+
+dump output readprofile -m /boot/System.map > captured_profile
+
+Oprofile
+--------
+get source (I use 0.5) from http://oprofile.sourceforge.net/
+add "idle=poll" to the kernel command line
+Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
+./configure --with-kernel-support
+make install
+
+One time setup (pick appropriate one for your CPU):
+P3 opcontrol --setup --vmlinux=/boot/vmlinux \
+ --ctr0-event=CPU_CLK_UNHALTED --ctr0-count=100000
+Athlon/x86-64 opcontrol --setup --vmlinux=/boot/vmlinux \
+ --ctr0-event=RETIRED_INSNS --ctr0-count=100000
+P4 opcontrol --setup --vmlinux=/boot/vmlinux \
+ --ctr0-event=GLOBAL_POWER_EVENTS \
+ --ctr0-unit-mask=1 --ctr0-count=100000
+
+start daemon opcontrol --start-daemon
+clear opcontrol --reset
+start opcontrol --start
+
+stop opcontrol --stop
+dump output oprofpp -dl -i /boot/vmlinux > output_file
+
diff -Nru a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
--- a/Documentation/block/biodoc.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/block/biodoc.txt Mon Mar 17 13:45:14 2003
@@ -635,9 +635,9 @@
be one of the many segments in the current bio (i.e i/o completion unit).
The nr_sectors value refers to the total number of sectors in the whole
request that remain to be transferred (no change). The purpose of the
-hard_xxx values is for block to remember these counts everytime it hands
+hard_xxx values is for block to remember these counts every time it hands
over the request to the driver. These values are updated by block on
-end_that_request_first, i.e. everytime the driver completes a part of the
+end_that_request_first, i.e. every time the driver completes a part of the
transfer and invokes block end*request helpers to mark this. The
driver should not modify these values. The block layer sets up the
nr_sectors and current_nr_sectors fields (based on the corresponding
diff -Nru a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex
--- a/Documentation/cdrom/cdrom-standard.tex Mon Mar 17 13:45:10 2003
+++ b/Documentation/cdrom/cdrom-standard.tex Mon Mar 17 13:45:10 2003
@@ -758,11 +758,8 @@
\subsection{$Struct\ file_operations\ cdrom_fops$}
The contents of this structure were described in section~\ref{cdrom.c}.
-As already stated, this structure should be used to register block
-devices with the kernel:
-$$
-register_blkdev(major, , \&cdrom_fops);
-$$
+A pointer to this structure is assigned to the $fops$ field
+of the $struct gendisk$.
\subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi)$}
diff -Nru a/Documentation/computone.txt b/Documentation/computone.txt
--- a/Documentation/computone.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/computone.txt Mon Mar 17 13:45:14 2003
@@ -539,7 +539,7 @@
X for PORTNO in $MINORS
X do
X if test ! -c /dev/ttyF$PORTNO ; then
-X # We got the harware but no device - make it
+X # We got the hardware but no device - make it
X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
X fi
X done
@@ -552,7 +552,7 @@
X for PORTNO in $MINORS
X do
X if test ! -c /dev/cuf$PORTNO ; then
-X # We got the harware but no device - make it
+X # We got the hardware but no device - make it
X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
X fi
X done
diff -Nru a/Documentation/cpqarray.txt b/Documentation/cpqarray.txt
--- a/Documentation/cpqarray.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/cpqarray.txt Mon Mar 17 13:45:13 2003
@@ -49,9 +49,9 @@
-----------------
If you want to use an EISA controller you'll have to supply some
-insmod/lilo paramaters. If the driver is compiled into the kernel, must
+insmod/lilo parameters. If the driver is compiled into the kernel, must
give it the controller's IO port address at boot time (it is no longer
-necessary to specifiy the IRQ). For example, if you had two SMART-2/E
+necessary to specify the IRQ). For example, if you had two SMART-2/E
controllers, in EISA slots 1 and 2 you'd give it a boot argument like
this:
diff -Nru a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt
--- a/Documentation/cpu-freq/core.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/cpu-freq/core.txt Mon Mar 17 13:45:14 2003
@@ -35,6 +35,10 @@
kernel "constant" loops_per_jiffy is updated on frequency changes
here.
+Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu,
+which make sure that the cpufreq processor driver is correctly
+registered with the core, and will not be unloaded until
+cpufreq_put_cpu is called.
2. CPUFreq notifiers
====================
diff -Nru a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt
--- a/Documentation/cpu-freq/cpu-drivers.txt Mon Mar 17 13:45:16 2003
+++ b/Documentation/cpu-freq/cpu-drivers.txt Mon Mar 17 13:45:16 2003
@@ -35,7 +35,7 @@
So, you just got a brand-new CPU / chipset with datasheets and want to
add cpufreq support for this CPU / chipset? Great. Here are some hints
-on what is neccessary:
+on what is necessary:
1.1 Initialization
@@ -54,7 +54,7 @@
cpufreq_driver.init - A pointer to the per-CPU initialization
function.
-cpufreq_driver.verify - A pointer to a "verfication" funciton.
+cpufreq_driver.verify - A pointer to a "verification" function.
cpufreq_driver.setpolicy _or_
cpufreq_driver.target - See below on the differences.
@@ -63,13 +63,16 @@
cpufreq_driver.exit - A pointer to a per-CPU cleanup function.
+cpufreq_driver.attr - A pointer to a NULL-terminated list of
+ "struct freq_attr" which allow to
+ export values to sysfs.
1.2 Per-CPU Initialization
--------------------------
Whenever a new CPU is registered with the device model, or after the
-cpufreq driver registers itself, the per-CPU initialization fucntion
+cpufreq driver registers itself, the per-CPU initialization function
cpufreq_driver.init is called. It takes a struct cpufreq_policy
*policy as argument. What to do now?
@@ -91,7 +94,7 @@
this CPU (if appropriate)
policy->min,
policy->max,
-policy->policy and, if neccessary,
+policy->policy and, if necessary,
policy->governor must contain the "default policy" for
this CPU. A few moments later,
cpufreq_driver.verify and either
diff -Nru a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
--- a/Documentation/cpu-freq/governors.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/cpu-freq/governors.txt Mon Mar 17 13:45:13 2003
@@ -98,7 +98,7 @@
-------------
The CPUfreq governor "userspace" allows the user, or any userspace
-program running with UID "root", to set the CPU to a specifc frequency
+program running with UID "root", to set the CPU to a specific frequency
by making a sysfs file "scaling_setspeed" available in the CPU-device
directory.
diff -Nru a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
--- a/Documentation/cpu-freq/user-guide.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/cpu-freq/user-guide.txt Mon Mar 17 13:45:09 2003
@@ -58,7 +58,8 @@
Intel Pentium 4, Intel Xeon
National Semiconductors Geode GX
Transmeta Crusoe
-varios processors on some ACPI 2.0-compatible systems [**]
+VIA Cyrix 3 / C3
+various processors on some ACPI 2.0-compatible systems [**]
[*] only certain Intel mobile PIII processors are supported. If you
know that you own a speedstep-capable processor, pass the option
@@ -81,9 +82,9 @@
2. "Policy" / "Governor" ?
==========================
-Some CPU frequency scaling-capable processor switch between varios
+Some CPU frequency scaling-capable processor switch between various
frequencies and operating voltages "on the fly" without any kernel or
-user involvement. This guarantuees very fast switching to a frequency
+user involvement. This guarantees very fast switching to a frequency
which is high enough to serve the user's needs, but low enough to save
power.
@@ -93,7 +94,7 @@
On these systems, all you can do is select the lower and upper
frequency limit as well as whether you want more aggressive
-power-saving or more instantly avaialble processing power.
+power-saving or more instantly available processing power.
2.2 Governor
@@ -114,9 +115,9 @@
------------------------------
The preferred interface is located in the sysfs filesystem. If you
-mounted it at /sys, the cpufreq interface is located in the
-cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first
-CPU).
+mounted it at /sys, the cpufreq interface is located in a subdirectory
+"cpufreq" within the cpu-device directory
+(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU).
cpuinfo_min_freq : this file shows the minimum operating
frequency the processor can run at(in kHz)
@@ -125,7 +126,7 @@
scaling_driver : this file shows what cpufreq driver is
used to set the frequency on this CPU
-available_scaling_governors : this file shows the CPUfreq governors
+scaling_available_governors : this file shows the CPUfreq governors
available in this kernel. You can see the
currently activated governor in
diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/crypto/api-intro.txt Mon Mar 17 13:45:14 2003
@@ -38,9 +38,8 @@
Compressors. The compression algorithms especially seem to be performing
very well so far.
-An asynchronous scheduling interface is in planning but not yet
-implemented, as we need to further analyze the requirements of all of
-the possible hardware scenarios (e.g. IPsec NIC offload).
+Support for hardware crypto devices via an asynchronous interface is
+under development.
Here's an example of how to use the API:
@@ -87,8 +86,8 @@
DEVELOPER NOTES
-None of this code should be called from hardirq context, only softirq and
-user contexts.
+Transforms may only be allocated in user context, and cryptographic
+methods may only be called from softirq and user contexts.
When using the API for ciphers, performance will be optimal if each
scatterlist contains data which is a multiple of the cipher's block
@@ -137,16 +136,11 @@
list, see:
http://samba.org/~jamesm/crypto/
-Ongoing development discussion may also be found on
-kerneli cryptoapi-devel,
-see http://www.kerneli.org/mailman/listinfo/cryptoapi-devel
-
AUTHORS
James Morris
David S. Miller
-Jean-Francois Dive (SHA1 algorithm module)
CREDITS
@@ -191,6 +185,10 @@
Matthew Skala (Twofish)
Dag Arne Osvik (Serpent)
Brian Gladman (AES)
+
+
+SHA1 algorithm contributors:
+ Jean-Francois Dive
DES algorithm contributors:
Raimar Falke
@@ -215,6 +213,8 @@
Herbert Valerio Riedel
Kyle McMartin
Adam J. Richter
+
+Generic scatterwalk code by Adam J. Richter
Please send any credits updates or corrections to:
James Morris
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt Mon Mar 17 13:45:12 2003
+++ b/Documentation/devices.txt Mon Mar 17 13:45:12 2003
@@ -898,7 +898,7 @@
...
Network Block Device is somehow similar to loopback
- devices: If you read from it, it sends packet accross
+ devices: If you read from it, it sends packet across
network asking server for data. If you write to it, it
sends packet telling server to write. It could be used
to mounting filesystems over the net, swapping over
diff -Nru a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
--- a/Documentation/driver-model/driver.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/driver-model/driver.txt Mon Mar 17 13:45:13 2003
@@ -36,7 +36,7 @@
~~~~~~~~~~~~~~
The driver must initialize at least the name and bus fields. It should
-also initalize the devclass field (when it arrives), so it may obtain
+also initialize the devclass field (when it arrives), so it may obtain
the proper linkage internally. It should also initialize as many of
the callbacks as possible, though each is optional.
@@ -93,7 +93,7 @@
},
};
-Some may find the syntax of embedded struct intialization awkward or
+Some may find the syntax of embedded struct initialization awkward or
even a bit ugly. So far, it's the best way we've found to do what we want...
Registration
@@ -198,7 +198,7 @@
int (*suspend) (struct device * dev, u32 state, u32 level);
suspend is called to put the device in a low power state. There are
-several stages to sucessfully suspending a device, which is denoted in
+several stages to successfully suspending a device, which is denoted in
the @level parameter. Breaking the suspend transition into several
stages affords the platform flexibility in performing device power
management based on the requirements of the system and the
@@ -206,7 +206,7 @@
SUSPEND_NOTIFY notifies the device that a suspend transition is about
to happen. This happens on system power state transition to verify
-that all devices can sucessfully suspend.
+that all devices can successfully suspend.
A driver may choose to fail on this call, which should cause the
entire suspend transition to fail. A driver should fail only if it
diff -Nru a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
--- a/Documentation/driver-model/platform.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/driver-model/platform.txt Mon Mar 17 13:45:14 2003
@@ -34,7 +34,7 @@
gives them a common parent if they don't already have one.
But, besides the organizational benefits, the platform bus can also
-accomodate firmware-based enumeration.
+accommodate firmware-based enumeration.
Device Discovery
diff -Nru a/Documentation/eisa.txt b/Documentation/eisa.txt
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/Documentation/eisa.txt Mon Mar 17 13:45:16 2003
@@ -0,0 +1,164 @@
+EISA bus support (Marc Zyngier )
+
+This document groups random notes about porting EISA drivers to the
+new EISA/sysfs API.
+
+Starting from version 2.5.59, the EISA bus is almost given the same
+status as other much more mainstream busses such as PCI or USB. This
+has been possible through sysfs, which defines a nice enough set of
+abstractions to manage busses, devices and drivers.
+
+Although the new API is quite simple to use, converting existing
+drivers to the new infrastructure is not an easy task (mostly because
+detection code is generally also used to probe ISA cards). Moreover,
+most EISA drivers are among the oldest Linux drivers so, as you can
+imagine, some dust has settled here over the years.
+
+The EISA infrastructure is made up of three parts :
+
+ - The bus code implements most of the generic code. It is shared
+ among all the architectures that the EISA code runs on. It
+ implements bus probing (detecting EISA cards avaible on the bus),
+ allocates I/O resources, allows fancy naming through sysfs, and
+ offers interfaces for driver to register.
+
+ - The bus root driver implements the glue between the bus hardware
+ and the generic bus code. It is responsible for discovering the
+ device implementing the bus, and setting it up to be latter probed
+ by the bus code. This can go from something as simple as reserving
+ an I/O region on x86, to the rather more complex, like the hppa
+ EISA code. This is the part to implement in order to have EISA
+ running on an "new" platform.
+
+ - The driver offers the bus a list of devices that it manages, and
+ implements the necessary callbacks to probe and release devices
+ whenever told to.
+
+Every function/structure below lives in , which depends
+heavily on .
+
+** Bus root driver :
+
+int eisa_root_register (struct eisa_root_device *root);
+
+The eisa_root_register function is used to declare a device as the
+root of an EISA bus. The eisa_root_device structure holds a reference
+to this device, as well as some parameters for probing purposes.
+
+struct eisa_root_device {
+ struct list_head node;
+ struct device *dev; /* Pointer to bridge device */
+ struct resource *res;
+ unsigned long bus_base_addr;
+ int slots; /* Max slot number */
+ int bus_nr; /* Set by eisa_root_register */
+};
+
+node : used for eisa_root_register internal purpose
+dev : pointer to the root device
+res : root device I/O resource
+bus_base_addr : slot 0 address on this bus
+slots : max slot number to probe
+bus_nr : unique bus id, set by eisa_root_register
+
+** Driver :
+
+int eisa_driver_register (struct eisa_driver *edrv);
+void eisa_driver_unregister (struct eisa_driver *edrv);
+
+Clear enough ?
+
+struct eisa_device_id {
+ char sig[EISA_SIG_LEN];
+ unsigned long driver_data;
+};
+
+struct eisa_driver {
+ const struct eisa_device_id *id_table;
+ struct device_driver driver;
+};
+
+id_table : an array of NULL terminated EISA id strings,
+ followed by an empty string. Each string can be
+ paired with a driver-dependant value (driver_data).
+
+driver : a generic driver, such as described in
+ Documentation/driver-model/driver.txt. Only .name,
+ .probe and .remove members are mandatory.
+
+An example is the 3c509 driver :
+
+struct eisa_device_id el3_eisa_ids[] = {
+ { "TCM5092" },
+ { "TCM5093" },
+ { "" }
+};
+
+struct eisa_driver el3_eisa_driver = {
+ .id_table = el3_eisa_ids,
+ .driver = {
+ .name = "3c509",
+ .probe = el3_eisa_probe,
+ .remove = __devexit_p (el3_device_remove)
+ }
+};
+
+** Device :
+
+The sysfs framework calls .probe and .remove functions upon device
+discovery and removal (note that the .remove function is only called
+when driver is built as a module).
+
+Both functions are passed a pointer to a 'struct device', which is
+encapsulated in a 'struct eisa_device' described as follows :
+
+struct eisa_device {
+ struct eisa_device_id id;
+ int slot;
+ unsigned long base_addr;
+ struct resource res;
+ struct device dev; /* generic device */
+};
+
+id : EISA id, as read from device. id.driver_data is set from the
+ matching driver EISA id.
+slot : slot number which the device was detected on
+res : I/O resource allocated to this device
+dev : generic device (see Documentation/driver-model/device.txt)
+
+You can get the 'struct eisa_device' from 'struct device' using the
+'to_eisa_device' macro.
+
+** Misc stuff :
+
+void eisa_set_drvdata (struct eisa_device *edev, void *data);
+
+Stores data into the device's driver_data area.
+
+void *eisa_get_drvdata (struct eisa_device *edev):
+
+Gets the pointer previously stored into the device's driver_data area.
+
+** Random notes :
+
+Converting an EISA driver to the new API mostly involves *deleting*
+code (since probing is now in the core EISA code). Unfortunately, most
+drivers share their probing routine between ISA, MCA and EISA. Special
+care must be taken when ripping out the EISA code, so other busses
+won't suffer from these surgical strikes...
+
+You *must not* expect any EISA device to be detected when returning
+from eisa_driver_register, since the chances are that the bus has not
+yet been probed. In fact, that's what happens most of the time (the
+bus root driver usually kicks in rather late in the boot process).
+Unfortunately, most drivers are doing the probing by themselves, and
+expect to have explored the whole machine when they exit their probe
+routine.
+
+** Thanks :
+
+I'd like to thank the following people for their help :
+- Xavier Benigni for lending me a wonderful Alpha Jensen,
+- James Bottomley, Jeff Garzik for getting this stuff into the kernel,
+- Andries Brouwer for contributing numerous EISA ids,
+- Catrin Jones for coping with too many machines at home
diff -Nru a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting
--- a/Documentation/filesystems/Exporting Mon Mar 17 13:45:12 2003
+++ b/Documentation/filesystems/Exporting Mon Mar 17 13:45:12 2003
@@ -45,7 +45,7 @@
to already have a (non-connected) dentry, and must be able to move
that dentry into place (based on the parent and name in the
->lookup). This is particuarly needed for directories as
- it is a dcache invarient that directories only have one dentry.
+ it is a dcache invariant that directories only have one dentry.
To implement these features, the dcache has:
diff -Nru a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README
--- a/Documentation/filesystems/devfs/README Mon Mar 17 13:45:12 2003
+++ b/Documentation/filesystems/devfs/README Mon Mar 17 13:45:12 2003
@@ -56,7 +56,7 @@
Operational issues (essential reading)
Instructions for the impatient
-Permissions persistence accross reboots
+Permissions persistence across reboots
Dealing with drivers without devfs support
All the way with Devfs
Other Issues
@@ -1465,13 +1465,6 @@
The simplest option (especially when porting drivers to devfs) is to
keep using the old major and minor numbers. Devfs will take whatever
values are given for major&minor and pass them onto userspace.
-
-Alternatively, you can have devfs choose unique device numbers for
-you. When you register a character or block device using
-devfs_register you can provide the optional
-DEVFS_FL_AUTO_DEVNUM flag, which will then automatically allocate a
-unique device number (the allocation is separated for the character
-and block devices).
This device number is a 16 bit number, so this leaves plenty of space
for large numbers of discs and partitions. This scheme can also be
diff -Nru a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking
--- a/Documentation/filesystems/directory-locking Mon Mar 17 13:45:14 2003
+++ b/Documentation/filesystems/directory-locking Mon Mar 17 13:45:14 2003
@@ -110,4 +110,4 @@
Notice that "directory" in the above == "anything that might have
children", so if we are going to introduce hybrid objects we will need
either to make sure that link(2) doesn't work for them or to make changes
-in is_subdir() that would make it work even in presense of such beasts.
+in is_subdir() that would make it work even in presence of such beasts.
diff -Nru a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
--- a/Documentation/filesystems/ext3.txt Mon Mar 17 13:45:12 2003
+++ b/Documentation/filesystems/ext3.txt Mon Mar 17 13:45:12 2003
@@ -48,11 +48,11 @@
sb=n Use alternate superblock at this location.
-data=journal All data are commited into the journal prior
+data=journal All data are committed into the journal prior
to being written into the main file system.
data=ordered (*) All data are forced directly out to the main file
- system prior to its metadata being commited to
+ system prior to its metadata being committed to
the journal.
data=writeback Data ordering is not preserved, data may be
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt Mon Mar 17 13:45:10 2003
+++ b/Documentation/filesystems/proc.txt Mon Mar 17 13:45:10 2003
@@ -344,7 +344,7 @@
Each column represents the number of pages of a certain order which are
available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in
ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE
-availble in ZONE_NORMAL, etc...
+available in ZONE_NORMAL, etc...
1.3 IDE devices in /proc/ide
diff -Nru a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
--- a/Documentation/filesystems/sysfs.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/filesystems/sysfs.txt Mon Mar 17 13:45:09 2003
@@ -55,7 +55,7 @@
value per file, so it is socially acceptable to express an array of
values of the same type.
-Mixing types, expressing mulitple lines of data, and doing fancy
+Mixing types, expressing multiple lines of data, and doing fancy
formatting of data is heavily frowned upon. Doing these things may get
you publically humiliated and your code rewritten without notice.
diff -Nru a/Documentation/hw_random.txt b/Documentation/hw_random.txt
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/Documentation/hw_random.txt Mon Mar 17 13:45:13 2003
@@ -0,0 +1,134 @@
+ Hardware driver for Intel i810 Random Number Generator (RNG)
+ Copyright 2000,2001 Jeff Garzik
+ Copyright 2000,2001 Philipp Rumpf
+
+Introduction:
+
+ The i810_rng device driver is software that makes use of a
+ special hardware feature on the Intel i8xx-based chipsets,
+ a Random Number Generator (RNG).
+
+ In order to make effective use of this device driver, you
+ should download the support software as well. Download the
+ latest version of the "intel-rng-tools" package from the
+ i810_rng driver's official Web site:
+
+ http://sourceforge.net/projects/gkernel/
+
+About the Intel RNG hardware, from the firmware hub datasheet:
+
+ The Firmware Hub integrates a Random Number Generator (RNG)
+ using thermal noise generated from inherently random quantum
+ mechanical properties of silicon. When not generating new random
+ bits the RNG circuitry will enter a low power state. Intel will
+ provide a binary software driver to give third party software
+ access to our RNG for use as a security feature. At this time,
+ the RNG is only to be used with a system in an OS-present state.
+
+Theory of operation:
+
+ Character driver. Using the standard open()
+ and read() system calls, you can read random data from
+ the i810 RNG device. This data is NOT CHECKED by any
+ fitness tests, and could potentially be bogus (if the
+ hardware is faulty or has been tampered with). Data is only
+ output if the hardware "has-data" flag is set, but nevertheless
+ a security-conscious person would run fitness tests on the
+ data before assuming it is truly random.
+
+ /dev/intel_rng is char device major 10, minor 183.
+
+Driver notes:
+
+ * FIXME: support poll(2)
+
+ NOTE: request_mem_region was removed, for two reasons:
+ 1) Only one RNG is supported by this driver, 2) The location
+ used by the RNG is a fixed location in MMIO-addressable memory,
+ 3) users with properly working BIOS e820 handling will always
+ have the region in which the RNG is located reserved, so
+ request_mem_region calls always fail for proper setups.
+ However, for people who use mem=XX, BIOS e820 information is
+ -not- in /proc/iomem, and request_mem_region(RNG_ADDR) can
+ succeed.
+
+Driver details:
+
+ Based on:
+ Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet
+ May 1999 Order Number: 290658-002 R
+
+ Intel 82802 Firmware Hub: Random Number Generator
+ Programmer's Reference Manual
+ December 1999 Order Number: 298029-001 R
+
+ Intel 82802 Firmware HUB Random Number Generator Driver
+ Copyright (c) 2000 Matt Sottek
+
+ Special thanks to Matt Sottek. I did the "guts", he
+ did the "brains" and all the testing.
+
+Change history:
+
+ Version 0.9.8:
+ * Support other i8xx chipsets by adding 82801E detection
+ * 82801DB detection is the same as for 82801CA.
+
+ Version 0.9.7:
+ * Support other i8xx chipsets too (by adding 82801BA(M) and
+ 82801CA(M) detection)
+
+ Version 0.9.6:
+ * Internal driver cleanups, prep for 1.0.0 release.
+
+ Version 0.9.5:
+ * Rip out entropy injection via timer. It never ever worked,
+ and a better solution (rngd) is now available.
+
+ Version 0.9.4:
+ * Fix: Remove request_mem_region
+ * Fix: Horrible bugs in FIPS calculation and test execution
+
+ Version 0.9.3:
+ * Clean up rng_read a bit.
+ * Update i810_rng driver Web site URL.
+ * Increase default timer interval to 4 samples per second.
+ * Abort if mem region is not available.
+ * BSS zero-initialization cleanup.
+ * Call misc_register() from rng_init_one.
+ * Fix O_NONBLOCK to occur before we schedule.
+
+ Version 0.9.2:
+ * Simplify open blocking logic
+
+ Version 0.9.1:
+ * Support i815 chipsets too (Matt Sottek)
+ * Fix reference counting when statically compiled (prumpf)
+ * Rewrite rng_dev_read (prumpf)
+ * Make module races less likely (prumpf)
+ * Small miscellaneous bug fixes (prumpf)
+ * Use pci table for PCI id list
+
+ Version 0.9.0:
+ * Don't register a pci_driver, because we are really
+ using PCI bridge vendor/device ids, and someone
+ may want to register a driver for the bridge. (bug fix)
+ * Don't let the usage count go negative (bug fix)
+ * Clean up spinlocks (bug fix)
+ * Enable PCI device, if necessary (bug fix)
+ * iounmap on module unload (bug fix)
+ * If RNG chrdev is already in use when open(2) is called,
+ sleep until it is available.
+ * Remove redundant globals rng_allocated, rng_use_count
+ * Convert numeric globals to unsigned
+ * Module unload cleanup
+
+ Version 0.6.2:
+ * Clean up spinlocks. Since we don't have any interrupts
+ to worry about, but we do have a timer to worry about,
+ we use spin_lock_bh everywhere except the timer function
+ itself.
+ * Fix module load/unload.
+ * Fix timer function and h/w enable/disable logic
+ * New timer interval sysctl
+ * Clean up sysctl names
diff -Nru a/Documentation/i810_rng.txt b/Documentation/i810_rng.txt
--- a/Documentation/i810_rng.txt Mon Mar 17 13:45:13 2003
+++ /dev/null Wed Dec 31 16:00:00 1969
@@ -1,134 +0,0 @@
- Hardware driver for Intel i810 Random Number Generator (RNG)
- Copyright 2000,2001 Jeff Garzik
- Copyright 2000,2001 Philipp Rumpf
-
-Introduction:
-
- The i810_rng device driver is software that makes use of a
- special hardware feature on the Intel i8xx-based chipsets,
- a Random Number Generator (RNG).
-
- In order to make effective use of this device driver, you
- should download the support software as well. Download the
- latest version of the "intel-rng-tools" package from the
- i810_rng driver's official Web site:
-
- http://sourceforge.net/projects/gkernel/
-
-About the Intel RNG hardware, from the firmware hub datasheet:
-
- The Firmware Hub integrates a Random Number Generator (RNG)
- using thermal noise generated from inherently random quantum
- mechanical properties of silicon. When not generating new random
- bits the RNG circuitry will enter a low power state. Intel will
- provide a binary software driver to give third party software
- access to our RNG for use as a security feature. At this time,
- the RNG is only to be used with a system in an OS-present state.
-
-Theory of operation:
-
- Character driver. Using the standard open()
- and read() system calls, you can read random data from
- the i810 RNG device. This data is NOT CHECKED by any
- fitness tests, and could potentially be bogus (if the
- hardware is faulty or has been tampered with). Data is only
- output if the hardware "has-data" flag is set, but nevertheless
- a security-conscious person would run fitness tests on the
- data before assuming it is truly random.
-
- /dev/intel_rng is char device major 10, minor 183.
-
-Driver notes:
-
- * FIXME: support poll(2)
-
- NOTE: request_mem_region was removed, for two reasons:
- 1) Only one RNG is supported by this driver, 2) The location
- used by the RNG is a fixed location in MMIO-addressable memory,
- 3) users with properly working BIOS e820 handling will always
- have the region in which the RNG is located reserved, so
- request_mem_region calls always fail for proper setups.
- However, for people who use mem=XX, BIOS e820 information is
- -not- in /proc/iomem, and request_mem_region(RNG_ADDR) can
- succeed.
-
-Driver details:
-
- Based on:
- Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet
- May 1999 Order Number: 290658-002 R
-
- Intel 82802 Firmware Hub: Random Number Generator
- Programmer's Reference Manual
- December 1999 Order Number: 298029-001 R
-
- Intel 82802 Firmware HUB Random Number Generator Driver
- Copyright (c) 2000 Matt Sottek
-
- Special thanks to Matt Sottek. I did the "guts", he
- did the "brains" and all the testing.
-
-Change history:
-
- Version 0.9.8:
- * Support other i8xx chipsets by adding 82801E detection
- * 82801DB detection is the same as for 82801CA.
-
- Version 0.9.7:
- * Support other i8xx chipsets too (by adding 82801BA(M) and
- 82801CA(M) detection)
-
- Version 0.9.6:
- * Internal driver cleanups, prep for 1.0.0 release.
-
- Version 0.9.5:
- * Rip out entropy injection via timer. It never ever worked,
- and a better solution (rngd) is now available.
-
- Version 0.9.4:
- * Fix: Remove request_mem_region
- * Fix: Horrible bugs in FIPS calculation and test execution
-
- Version 0.9.3:
- * Clean up rng_read a bit.
- * Update i810_rng driver Web site URL.
- * Increase default timer interval to 4 samples per second.
- * Abort if mem region is not available.
- * BSS zero-initialization cleanup.
- * Call misc_register() from rng_init_one.
- * Fix O_NONBLOCK to occur before we schedule.
-
- Version 0.9.2:
- * Simplify open blocking logic
-
- Version 0.9.1:
- * Support i815 chipsets too (Matt Sottek)
- * Fix reference counting when statically compiled (prumpf)
- * Rewrite rng_dev_read (prumpf)
- * Make module races less likely (prumpf)
- * Small miscellaneous bug fixes (prumpf)
- * Use pci table for PCI id list
-
- Version 0.9.0:
- * Don't register a pci_driver, because we are really
- using PCI bridge vendor/device ids, and someone
- may want to register a driver for the bridge. (bug fix)
- * Don't let the usage count go negative (bug fix)
- * Clean up spinlocks (bug fix)
- * Enable PCI device, if necessary (bug fix)
- * iounmap on module unload (bug fix)
- * If RNG chrdev is already in use when open(2) is called,
- sleep until it is available.
- * Remove redundant globals rng_allocated, rng_use_count
- * Convert numeric globals to unsigned
- * Module unload cleanup
-
- Version 0.6.2:
- * Clean up spinlocks. Since we don't have any interrupts
- to worry about, but we do have a timer to worry about,
- we use spin_lock_bh everywhere except the timer function
- itself.
- * Fix module load/unload.
- * Fix timer function and h/w enable/disable logic
- * New timer interval sysctl
- * Clean up sysctl names
diff -Nru a/Documentation/ia64/IRQ-redir.txt b/Documentation/ia64/IRQ-redir.txt
--- a/Documentation/ia64/IRQ-redir.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/ia64/IRQ-redir.txt Mon Mar 17 13:45:13 2003
@@ -29,7 +29,7 @@
The output of the command
cat /proc/irq/IRQ#/smp_affinity
gives the target CPU mask for the specified interrupt vector. If the CPU
-mask is preceeded by the character "r", the interrupt is redirectable
+mask is preceded by the character "r", the interrupt is redirectable
(i.e. lowest priority mode routing is used), otherwise its route is
fixed.
diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt
--- a/Documentation/ia64/fsys.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/ia64/fsys.txt Mon Mar 17 13:45:13 2003
@@ -4,7 +4,7 @@
-----------------------------------
Started: 13-Jan-2003
- Last update: 24-Jan-2003
+ Last update: 11-Feb-2003
David Mosberger-Tang
@@ -42,9 +42,9 @@
can disable interrupts and avoid all other interruption-sources
to avoid preemption)
- - neither the memory nor the register stack can be trusted while
+ - neither the memory-stack nor the register-stack can be trusted while
in fsys-mode (they point to the user-level stacks, which may
- be invalid)
+ be invalid, or completely bogus addresses)
In summary, fsys-mode is much more similar to running in user-mode
than it is to running in kernel-mode. Of course, given that the
diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt
--- a/Documentation/ide.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/ide.txt Mon Mar 17 13:45:13 2003
@@ -4,7 +4,7 @@
==============================================================================
- The hdparm utility can be used to controll various IDE features on a
+ The hdparm utility can be used to control various IDE features on a
running system. It is packaged separately. Please Look for it on popular
linux FTP sites.
@@ -37,7 +37,7 @@
================================================================================
Common pitfalls:
-- 40-conductor IDE cables are capable of transfering data in DMA modes up to
+- 40-conductor IDE cables are capable of transferring data in DMA modes up to
udma2, but no faster.
- If possible devices should be attached to separate channels if they are
diff -Nru a/Documentation/input/ff.txt b/Documentation/input/ff.txt
--- a/Documentation/input/ff.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/input/ff.txt Mon Mar 17 13:45:13 2003
@@ -163,7 +163,7 @@
~~~~~~~~~~~~~~~~~~~~
Not all devices have the same strength. Therefore, users should set a gain
factor depending on how strong they want effects to be. This setting is
-persistent accross access to the driver, so you should not care about it if
+persistent across access to the driver, so you should not care about it if
you are writing games, as another utility probably already set this for you.
/* Set the gain of the device
@@ -200,7 +200,7 @@
Proceed as if you wanted to upload a new effect, except that instead of
setting the id field to -1, you set it to the wanted effect id.
Normally, the effect is not stopped and restarted. However, depending on the
-type of device, not all paramaters can be dynamically updated. For example,
+type of device, not all parameters can be dynamically updated. For example,
the direction of an effect cannot be updated with iforce devices. In this
case, the driver stops the effect, up-load it, and restart it.
diff -Nru a/Documentation/isdn/INTERFACE b/Documentation/isdn/INTERFACE
--- a/Documentation/isdn/INTERFACE Mon Mar 17 13:45:14 2003
+++ b/Documentation/isdn/INTERFACE Mon Mar 17 13:45:14 2003
@@ -735,7 +735,7 @@
driver = driver-Id
command = ISDN_STAT_PROT
arg = The lower 8 Bits define the addressed protocol as defined
- in ISDN_PTYPE..., the upper bits are used to differenciate
+ in ISDN_PTYPE..., the upper bits are used to differentiate
the protocol specific STAT.
para = protocol and function specific. See isdnif.h for detail.
diff -Nru a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
--- a/Documentation/kbuild/kconfig-language.txt Mon Mar 17 13:45:11 2003
+++ b/Documentation/kbuild/kconfig-language.txt Mon Mar 17 13:45:11 2003
@@ -69,7 +69,7 @@
default values are visible, only the first defined one is active.
Default values are not limited to the menu entry, where they are
defined, this means the default can be defined somewhere else or be
- overriden by an earlier definition.
+ overridden by an earlier definition.
The default value is only assigned to the config symbol if no other
value was set by the user (via the input prompt above). If an input
prompt is visible the default value is presented to the user and can
@@ -142,7 +142,7 @@
--------------
The position of a menu entry in the tree is determined in two ways. First
-it can be specified explicitely:
+it can be specified explicitly:
menu "Network device support"
depends NET
diff -Nru a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
--- a/Documentation/kbuild/makefiles.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/kbuild/makefiles.txt Mon Mar 17 13:45:14 2003
@@ -10,7 +10,7 @@
--- 3.1 Goal definitions
--- 3.2 Built-in object goals - obj-y
--- 3.3 Loadable module goals - obj-m
- --- 3.4 Objects which export symbols - export-objs
+ --- 3.4 Objects which export symbols
--- 3.5 Library file goals - L_TARGET
--- 3.6 Descending down in directories
--- 3.7 Compilation flags
@@ -208,32 +208,11 @@
kbuild will build an ext2.o file for you out of the individual
parts and then link this into built-in.o, as you would expect.
---- 3.4 Objects which export symbols - export-objs
+--- 3.4 Objects which export symbols
- When using loadable modules, not every global symbol in the
- kernel / other modules is automatically available, only those
- explicitly exported are available for your module.
-
- To make a symbol available for use in modules, to "export" it,
- use the EXPORT_SYMBOL() directive in your source. In
- addition, you need to list all object files which export symbols
- (i.e. their source contains an EXPORT_SYMBOL() directive) in the
- Makefile variable $(export-objs).
-
- Example:
- #drivers/isdn/i4l/Makefile
- # Objects that export symbols.
- export-objs := isdn_common.o
-
- since isdn_common.c contains
-
- EXPORT_SYMBOL(register_isdn);
-
- which makes the function register_isdn available to
- low-level ISDN drivers.
- There exist a EXPORT_SYMBOL_GPL() variant with similar functionality,
- but more restrictive with what may use that symbol. The requirement
- to list the .o file in export-objs is the same.
+ No special notation is required in the makefiles for
+ modules exporting symbols.
+ See also Documentation/modules.txt.
--- 3.5 Library file goals - L_TARGET
@@ -400,7 +379,7 @@
The second step is to add an explicit dependency to the executable.
This can be done in two ways. Either add the dependency in a rule,
-or utilise the variable build-targets.
+or utilise the variable $(always).
Both possibilities are described in the following.
--- 4.1 Simple Host Program
@@ -526,15 +505,15 @@
$(obj)/gen-devlist is updated. Note that references to
the host programs in special rules must be prefixed with $(obj).
- (2) Use $(build-targets)
+ (2) Use $(always)
When there is no suitable special rule, and the host program
- shall be built when a makefile is entered, the $(build-targets)
+ shall be built when a makefile is entered, the $(always)
variable shall be used.
Example:
#scripts/lxdialog/Makefile
host-progs := lxdialog
- build-targets := $(host-progs)
+ always := $(host-progs)
This will tell kbuild to build lxdialog even if not referenced in
any rule.
@@ -543,13 +522,13 @@
"make clean" deletes most generated files in the src tree where the kernel
is compiled. This includes generated files such as host programs.
-Kbuild knows targets listed in $(host-progs) and $(EXTRA_TARGETS) and
-they are all deleted during "make clean".
+Kbuild knows targets listed in $(host-progs), $(always), $(extra-y) and
+$(targets). They are all deleted during "make clean".
Files matching the patterns "*.[oas]", "*.ko", plus some additional files
generated by kbuild are deleted all over the kernel src tree when
"make clean" is executed.
-Additional files can be specified by means of $(clean-files).
+Additional files can be specified in kbuild makefiles by use of $(clean-files).
Example:
#drivers/pci/Makefile
@@ -561,7 +540,7 @@
Usually kbuild descends down in subdirectories due to "obj-* := dir/",
but in the architecture makefiles where the kbuild infrastructure
-is not sufficent this sometimes needs to be explicit.
+is not sufficient this sometimes needs to be explicit.
Example:
#arch/i386/boot/Makefile
@@ -818,31 +797,23 @@
--- 6.5 Building non-kbuild targets
- EXTRA_TARGETS
+ extra-y
- EXTRA_TARGETS specify additional targets created in current
+ extra-y specify additional targets created in current
directory, in addition to any targets specified by obj-*.
- Listing all targets in EXTRA_TARGETS is required for three purposes:
- 1) Avoid that the target is linked in as part of built-in.o
- 2) Enable kbuild to check changes in command lines
+ Listing all targets in extra-y is required for two purposes:
+ 1) Enable kbuild to check changes in command lines
- When $(call if_changed,xxx) is used
- 3) kbuild knows what file to delete during "make clean"
+ 2) kbuild knows what files to delete during "make clean"
Example:
#arch/i386/kernel/Makefile
- EXTRA_TARGETS := head.o init_task.o
+ extra-y := head.o init_task.o
- In this example EXTRA_TARGETS is used to list object files that
+ In this example extra-y is used to list object files that
shall be built, but shall not be linked as part of built-in.o.
- Example:
- #arch/i386/boot/Makefile
- EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o
-
- In this example EXTRA_TARGETS is used to list all intermediate
- targets, and all final targets.
- The targets are added to EXTRA_TARGETS to enable 2) and 3) above.
--- 6.6 Commands useful for building a boot image
@@ -861,9 +832,10 @@
needs an update, or the commandline has changed since last
invocation. The latter will force a rebuild if any options
to the executable have changed.
- Any target that utilises if_changed must be listed in EXTRA_TARGETS,
+ Any target that utilises if_changed must be listed in $(targets),
otherwise the command line check will fail, and the target will
always be built.
+ Assignments to $(targets) are without $(obj)/ prefix.
if_changed may be used in conjunction with custom commands as
defined in 6.7 "Custom kbuild commands".
Note: It is a typical mistake to forget the FORCE prerequisite.
@@ -874,10 +846,34 @@
objcopy
Copy binary. Uses OBJCOPYFLAGS usually specified in
arch/$(ARCH)/Makefile.
+ OBJCOPYFLAGS_$@ may be used to set additional options.
gzip
Compress target. Use maximum compression to compress target.
+ Example:
+ #arch/i386/boot/Makefile
+ LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
+ LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext
+
+ targets += setup setup.o bootsect bootsect.o
+ $(obj)/setup $(obj)/bootsect: %: %.o FORCE
+ $(call if_changed,ld)
+
+ In this example there is two possible targets, requiring different
+ options to the linker. the linker options are specified using the
+ LDFLAGS_$@ syntax - one for each potential target.
+ $(targets) are assinged all potential targets, herby kbuild knows
+ the targets and will:
+ 1) check for commandline changes
+ 2) delete target during make clean
+
+ The ": %: %.o" part of the prerequisite is a shorthand that
+ free us from listing the setup.o and bootsect.o files.
+ Note: It is a common mistake to forget the "target :=" assignment,
+ resulting in the target file being recompiled for no
+ obvious reason.
+
--- 6.7 Custom kbuild commands
@@ -894,6 +890,7 @@
cmd_image = $(obj)/tools/build $(BUILDFLAGS) \
$(obj)/vmlinux.bin > $@
+ targets += bzImage
$(obj)/bzImage: $(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
@echo 'Kernel: $@ is ready'
diff -Nru a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt
--- a/Documentation/kernel-doc-nano-HOWTO.txt Mon Mar 17 13:45:12 2003
+++ b/Documentation/kernel-doc-nano-HOWTO.txt Mon Mar 17 13:45:12 2003
@@ -21,7 +21,7 @@
This is a program for converting SGML template files into SGML
files. When a file is referenced it is searched for symbols
- exported (EXPORT_SYMBOL), to be able to distingush between internal
+ exported (EXPORT_SYMBOL), to be able to distinguish between internal
and external functions.
It invokes kernel-doc, giving it the list of functions that
are to be documented.
diff -Nru a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt
--- a/Documentation/kernel-docs.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/kernel-docs.txt Mon Mar 17 13:45:13 2003
@@ -488,7 +488,7 @@
memory allocation.
Description: Article written for people wishing to make their data
acquisition boards work on their GNU/Linux machines. Gives a basic
- overview on writting drivers, from the naming of functions to
+ overview on writing drivers, from the naming of functions to
interrupt handling.
Notes: Two-parts article. Part II is at
http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt Mon Mar 17 13:45:16 2003
+++ b/Documentation/kernel-parameters.txt Mon Mar 17 13:45:16 2003
@@ -71,6 +71,8 @@
Parameters denoted with BOOT are actually interpreted by the boot
loader, and have no meaning to the kernel directly.
+Do not modify the syntax of boot loader parameters without extreme
+need or coordination with .
Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
a trailing = on the name of any parameter states that that parameter will
@@ -502,30 +504,30 @@
Format: ,
Specifies range of consoles to be captured by the MDA.
- mem=exactmap [KNL,BOOT,IA-32] Enable setting of an exact
- E820 memory map, as specified by the user.
- Such mem=exactmap lines can be constructed based on
- BIOS output or other requirements. See the mem=nn@ss
- option description.
-
mem=nn[KMG] [KNL,BOOT] Force usage of a specific amount of memory
Amount of memory to be used when the kernel is not able
to see the whole system memory or for test.
- mem=nn[KMG]@ss[KMG]
- [KNL,BOOT] Force usage of a specific region of memory
- Region of memory to be used, from ss to ss+nn.
+ mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel
+ memory.
- mem=nn[KMG]#ss[KMG]
- [KNL,BOOT,ACPI] Mark specific memory as ACPI data.
+ memmap=exactmap [KNL,IA-32] Enable setting of an exact
+ E820 memory map, as specified by the user.
+ Such memmap=exactmap lines can be constructed based on
+ BIOS output or other requirements. See the memmap=nn@ss
+ option description.
+
+ memmap=nn[KMG]@ss[KMG]
+ [KNL] Force usage of a specific region of memory
Region of memory to be used, from ss to ss+nn.
- mem=nn[KMG]$ss[KMG]
- [KNL,BOOT,ACPI] Mark specific memory as reserved.
+ memmap=nn[KMG]#ss[KMG]
+ [KNL,ACPI] Mark specific memory as ACPI data.
Region of memory to be used, from ss to ss+nn.
- mem=nopentium [BUGS=IA-32] Disable usage of 4MB pages for kernel
- memory.
+ memmap=nn[KMG]$ss[KMG]
+ [KNL,ACPI] Mark specific memory as reserved.
+ Region of memory to be used, from ss to ss+nn.
memfrac= [KNL]
diff -Nru a/Documentation/kobject.txt b/Documentation/kobject.txt
--- a/Documentation/kobject.txt Mon Mar 17 13:45:10 2003
+++ b/Documentation/kobject.txt Mon Mar 17 13:45:10 2003
@@ -7,7 +7,7 @@
0. Introduction
-The kobject infrastructure performs basic object managment that larger
+The kobject infrastructure performs basic object management that larger
data structures and subsystems can leverage, rather than reimplement
similar functionality. This functionality consists primarily concerns:
diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt
--- a/Documentation/magic-number.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/magic-number.txt Mon Mar 17 13:45:13 2003
@@ -146,7 +146,7 @@
NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h
Note that there are also defined special per-driver magic numbers in sound
-memory managment. See include/sound/sndmagic.h for complete list of them. Many
+memory management. See include/sound/sndmagic.h for complete list of them. Many
OSS sound drivers have their magic numbers constructed from the soundcard PCI
ID - these are not listed here as well.
diff -Nru a/Documentation/md.txt b/Documentation/md.txt
--- a/Documentation/md.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/md.txt Mon Mar 17 13:45:13 2003
@@ -1,10 +1,10 @@
Tools that manage md devices can be found at
- http://www..kernel.org/pub/linux/daemons/raid/....
+ http://www..kernel.org/pub/linux/utils/raid/....
-You can boot (if you selected boot support in the configuration) with your md
-device with the following kernel command lines:
+You can boot with your md device with the following kernel command
+lines:
for old raid arrays without persistent superblocks:
md=,,,,dev0,dev1,...,devn
@@ -33,4 +33,64 @@
A possible loadlin line (Harald Hoyer ) looks like this:
e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro
-
+
+-------------------------------
+The md driver can support a variety of different superblock formats.
+(It doesn't yet, but it can)
+
+The kernel does *NOT* autodetect which format superblock is being
+used. It must be told.
+
+Superblock format '0' is treated differently to others for legacy
+reasons.
+
+
+General Rules - apply for all superblock formats
+------------------------------------------------
+
+An array is 'created' by writing appropriate superblocks to all
+devices.
+It is 'assembled' by associating each of these devices with an
+particular md virtual device. Once it is completely assembled, it can
+be accessed.
+
+An array should be created by a user-space tool. This will write
+superblocks to all devices. It will usually mark the array as
+'unclean', or with some devices missing so that the kernel md driver
+can create approrpriate redundancy (copying in raid1, parity
+calculation in raid4/5).
+
+When an array is assembled, it is first initialised with the
+SET_ARRAY_INFO ioctl. This contains, in particular, a major and minor
+version number. The major version number selects which superblock
+format is to be used. The minor number might be used to tune handling
+of the format, such as suggesting where on each device to look for the
+superblock.
+
+Then each device is added using the ADD_NEW_DISK ioctl. This
+provides, in particular, a major and minor number identifying the
+device to add.
+
+The array is started with the RUN_ARRAY ioctl.
+
+Once started, new devices can be added. They should have an
+appropriate superblock written to them, and then passed be in with
+ADD_NEW_DISK.
+
+Devices that have failed or are not yet active can be detached from an
+array using HOT_REMOVE_DISK.
+
+
+Specific Rules that apply to format-0 super block arrays, and
+ arrays with no superblock (non-presistant).
+-------------------------------------------------------------
+
+An array can be 'created' by describing the array (level, chunksize
+etc) in a SET_ARRAY_INFO ioctl. This must has major_version==0 and
+raid_disks != 0.
+Then uninitialised devices can be added with ADD_NEW_DISK. The
+structure passed to ADD_NEW_DISK must specify the state of the device
+and it's role in the array.
+
+One started with RUN_ARRAY, uninitialised spares can be added with
+HOT_ADD_DISK.
diff -Nru a/Documentation/networking/3c359.txt b/Documentation/networking/3c359.txt
--- a/Documentation/networking/3c359.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/networking/3c359.txt Mon Mar 17 13:45:14 2003
@@ -41,7 +41,7 @@
message_level: Controls level of messages created by the driver. Defaults to 0:
which only displays start-up and critical messages. Presently any non-zero
value will display all soft messages as well. NB This does not turn
-debuging messages on, that must be done by modified the source code.
+debugging messages on, that must be done by modified the source code.
Variable MTU size:
diff -Nru a/Documentation/networking/3c509.txt b/Documentation/networking/3c509.txt
--- a/Documentation/networking/3c509.txt Mon Mar 17 13:45:10 2003
+++ b/Documentation/networking/3c509.txt Mon Mar 17 13:45:10 2003
@@ -106,7 +106,7 @@
8 transceiver type and duplex mode taken from card's EEPROM config settings
12 10baseT (RJ-45 connector); force full-duplex mode
-Prior to driver version 1.18c, only tranceiver codes 0-4 were supported. Note
+Prior to driver version 1.18c, only transceiver codes 0-4 were supported. Note
that the new transceiver codes 8 and 12 are the *only* ones that will enable
full-duplex mode, no matter what the card's detected EEPROM settings might be.
This insured that merely upgrading the driver from an earlier version would
@@ -146,7 +146,7 @@
Tx Carrier Errors Reported in /proc/net/dev
If an EtherLink III appears to transmit packets, but the "Tx carrier errors"
field in /proc/net/dev increments as quickly as the Tx packet count, you
-likely have an unterminated network or the incorrect media tranceiver selected.
+likely have an unterminated network or the incorrect media transceiver selected.
3c509B card is not detected on machines with an ISA PnP BIOS.
While the updated driver works with most PnP BIOS programs, it does not work
diff -Nru a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt
--- a/Documentation/networking/NAPI_HOWTO.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/networking/NAPI_HOWTO.txt Mon Mar 17 13:45:13 2003
@@ -85,7 +85,7 @@
In this case your only choice is to move all to dev->poll()
II) Clear-on-write (COW)
- i) you clear the status by writting a 1 in the bit-location you want.
+ i) you clear the status by writing a 1 in the bit-location you want.
These are the majority of the NICs and work the best with NAPI.
Put only receive events in dev->poll(); leave the rest in
the old interrupt handler.
@@ -200,7 +200,7 @@
/* two new additions */
/* first register my poll method */
dev->poll = my_poll;
-/* next register my weight/quanta; can be overriden in /proc */
+/* next register my weight/quanta; can be overridden in /proc */
dev->weight = 16;
.
.
@@ -346,10 +346,10 @@
netif_rx_schedule_prep() returns 1 if device is in running state and
gets successfully added to the core poll list. If we get a zero value
we can _almost_ assume are already added to the list (instead of not running.
-Logic based on the fact that you shouldnt get interrupt if not running)
+Logic based on the fact that you shouldn't get interrupt if not running)
We rectify this by disabling rx and rxnobuf interrupts.
-II) that receive_packets(dev) and make_rx_buffs_avail() may have dissapeared.
+II) that receive_packets(dev) and make_rx_buffs_avail() may have disappeared.
These functionalities are still around actually......
infact, receive_packets(dev) is very close to my_poll() and
@@ -442,7 +442,7 @@
int rx_work_limit = dev->quota;
/************************ end note note *********************************/
- do { // outer beggining loop starts here
+ do { // outer beginning loop starts here
clear_rx_status_register_bit();
diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
--- a/Documentation/networking/bonding.txt Mon Mar 17 13:45:10 2003
+++ b/Documentation/networking/bonding.txt Mon Mar 17 13:45:10 2003
@@ -304,7 +304,7 @@
Configuring Multiple ARP Targets
================================
-While ARP monitoring can be done with just one target, it can be usefull
+While ARP monitoring can be done with just one target, it can be useful
in a High Availability setup to have several targets to monitor. In the
case of just one target, the target itself may go down or have a problem
making it unresponsive to ARP requests. Having an additional target (or
diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c
--- a/Documentation/networking/ifenslave.c Mon Mar 17 13:45:09 2003
+++ b/Documentation/networking/ifenslave.c Mon Mar 17 13:45:09 2003
@@ -540,7 +540,7 @@
static short mif_flags;
-/* Get the inteface configuration from the kernel. */
+/* Get the interface configuration from the kernel. */
static int if_getconfig(char *ifname)
{
struct ifreq ifr;
diff -Nru a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt
--- a/Documentation/networking/sis900.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/networking/sis900.txt Mon Mar 17 13:45:09 2003
@@ -243,7 +243,7 @@
Chapter 7. Revision History
* November 13, 2000, Revision 1.07, seventh release, 630E problem
- fixed and furthur clean up.
+ fixed and further clean up.
* November 4, 1999, Revision 1.06, Second release, lots of clean up
and optimization.
* August 8, 1999, Revision 1.05, Initial Public Release
diff -Nru a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt
--- a/Documentation/networking/sk98lin.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/networking/sk98lin.txt Mon Mar 17 13:45:13 2003
@@ -138,7 +138,7 @@
options sk98lin ...
For "...", use the same syntax as described below for the command
-line paramaters of modprobe.
+line parameters of modprobe.
You either have to reboot your computer or unload and reload
the driver to activate the new parameters.
The syntax of the driver parameters is:
@@ -276,7 +276,7 @@
Large frames (also called jumbo frames) are now supported by the
driver. This can result in a greatly improved throughput if
-transfering large amounts of data.
+transferring large amounts of data.
To enable large frames, set the MTU (maximum transfer unit)
of the interface to the value you wish (up to 9000). The command
for this is:
@@ -489,7 +489,7 @@
established (#10402)
- Installation problems with RedHat 6.0 (#10409)
New Features:
-- Connection state ouput at "network connection up"
+- Connection state output at "network connection up"
Known limitations:
- None
diff -Nru a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
--- a/Documentation/networking/tuntap.txt Mon Mar 17 13:45:12 2003
+++ b/Documentation/networking/tuntap.txt Mon Mar 17 13:45:12 2003
@@ -40,7 +40,7 @@
Set permissions:
e.g. chmod 0700 /dev/net/tun
- if you want the device only accesible by root. Giving regular users the
+ if you want the device only accessible by root. Giving regular users the
right to assign network devices is NOT a good idea. Users could assign
bogus network interfaces to trick firewalls or administrators.
diff -Nru a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt
--- a/Documentation/networking/wan-router.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/networking/wan-router.txt Mon Mar 17 13:45:09 2003
@@ -577,7 +577,7 @@
bata2-2.2.1 Feb 20 2001
o Bug fixes to the CHDLC device drivers.
- The driver had compilation problmes under kernels
+ The driver had compilation problems under kernels
2.2.14 or lower.
o Bug fixes to the Setup installation script.
diff -Nru a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt
--- a/Documentation/networking/wanpipe.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/networking/wanpipe.txt Mon Mar 17 13:45:09 2003
@@ -577,7 +577,7 @@
bata2-2.2.1 Feb 20 2001
o Bug fixes to the CHDLC device drivers.
- The driver had compilation problmes under kernels
+ The driver had compilation problems under kernels
2.2.14 or lower.
o Bug fixes to the Setup installation script.
diff -Nru a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt
--- a/Documentation/oops-tracing.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/oops-tracing.txt Mon Mar 17 13:45:09 2003
@@ -219,7 +219,7 @@
2: 'F' if any module was force loaded by insmod -f, ' ' if all
modules were loaded normally.
- 3: 'S' if the oops occured on an SMP kernel running on hardware that
+ 3: 'S' if the oops occurred on an SMP kernel running on hardware that
hasn't been certified as safe to run multiprocessor.
Currently this occurs only on various Athlons that are not
SMP capable.
diff -Nru a/Documentation/pnp.txt b/Documentation/pnp.txt
--- a/Documentation/pnp.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/pnp.txt Mon Mar 17 13:45:09 2003
@@ -96,7 +96,7 @@
All Plug and Play drivers, protocols, and services meet at a central location
called the Plug and Play Layer. This layer is responsible for the exchange of
information between PnP drivers and PnP protocols. Thus it automatically
-forwards commands to the proper protocol. This makes writting PnP drivers
+forwards commands to the proper protocol. This makes writing PnP drivers
significantly easier.
The following functions are available from the Plug and Play Layer:
diff -Nru a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt
--- a/Documentation/s390/Debugging390.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/s390/Debugging390.txt Mon Mar 17 13:45:09 2003
@@ -52,7 +52,7 @@
16 General propose registers, 32 bit on s/390 64 bit on z/Architecture, r0-r15 or gpr0-gpr15 used for arithmetic & addressing.
-16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory managment,
+16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory management,
interrupt control,debugging control etc.
16 Access registers ( ar0-ar15 ) 32 bit on s/390 & z/Architecture
@@ -243,7 +243,7 @@
spaces for the user & kernel.
This means we can support 2GB of non Extended RAM on s/390, & more
-with the Extended memory managment swap device &
+with the Extended memory management swap device &
currently 4TB of physical memory currently on z/Architecture.
@@ -385,7 +385,7 @@
of extra space on the callers stack which is obviously freed
up on function exit ( e.g. the caller may choose to allocate nothing
of a buffer of 4k if required for temporary purposes ), it generates
-very efficent code ( a few cycles ) when compared to alternatives
+very efficient code ( a few cycles ) when compared to alternatives
like malloc.
automatics: These are local variables on the stack,
@@ -1091,7 +1091,7 @@
The VM Debugger is case insensitive.
VM's strengths are usually other debuggers weaknesses you can get at any resource
-no matter how sensitive e.g. memory managment resources,change address translation
+no matter how sensitive e.g. memory management resources,change address translation
in the PSW. For kernel hacking you will reap dividends if you get good at it.
The VM Debugger displays operators but not operands, probably because some
@@ -1194,7 +1194,7 @@
Displaying & modifying Registers
--------------------------------
D G will display all the gprs
-Adding a extra G to all the commands is neccessary to access the full 64 bit
+Adding a extra G to all the commands is necessary to access the full 64 bit
content in VM on z/Architecture obviously this isn't required for access registers
as these are still 32 bit.
e.g. DGG instead of DG
@@ -1280,7 +1280,7 @@
Tracing particular processes
----------------------------
-The kernels text segment is intentionally at an address in memory that it will
+The kernel's text segment is intentionally at an address in memory that it will
very seldom collide with text segments of user programs ( thanks Martin ),
this simplifies debugging the kernel.
However it is quite common for user processes to have addresses which collide
@@ -1425,7 +1425,7 @@
shutdown -h now or halt.
do a Q CPUS to find out how many cpus you have
detach each one of them from cp except cpu 0
-by issueing a
+by issuing a
DETACH CPU 01-(number of cpus in configuration)
& boot linux again.
TR SIGP will trace inter processor signal processor instructions.
@@ -1671,7 +1671,7 @@
( & many other instructions ) they consist of a length field & an absolute address field.
For each IO typically get 1 or 2 interrupts one for channel end ( primary status ) when the
channel is idle & the second for device end ( secondary status ) sometimes you get both
-concurrently, you check how the IO went on by issueing a TEST SUBCHANNEL at each interrupt,
+concurrently, you check how the IO went on by issuing a TEST SUBCHANNEL at each interrupt,
from which you receive an Interruption response block (IRB). If you get channel & device end
status in the IRB without channel checks etc. your IO probably went okay. If you didn't you
probably need a doctorto examine the IRB & extended status word etc.
@@ -2153,14 +2153,14 @@
current working directory.
This is very useful in that a customer can mail a core dump to a technical support department
& the technical support department can reconstruct what happened.
-Provided the have an indentical copy of this program with debugging symbols compiled in &
+Provided the have an identical copy of this program with debugging symbols compiled in &
the source base of this build is available.
In short it is far more useful than something like a crash log could ever hope to be.
In theory all that is missing to restart a core dumped program is a kernel patch which
will do the following.
1) Make a new kernel task structure
-2) Reload all the dumped pages back into the kernels memory managment structures.
+2) Reload all the dumped pages back into the kernel's memory management structures.
3) Do the required clock fixups
4) Get all files & network connections for the process back into an identical state ( really difficult ).
5) A few more difficult things I haven't thought of.
@@ -2374,7 +2374,7 @@
e.g.
to switch on the lcs "debug feature"
echo 5 > /proc/s390dbf/lcs/level
-& then after the error occured.
+& then after the error occurred.
cat /proc/s390dbf/lcs/sprintf >/logfile
the logfile now contains some information which may help
tech support resolve a problem in the field.
@@ -2462,9 +2462,9 @@
SGI's lcrash tool which allows one to look at kernel structures in a
running kernel.
-It also complements a tool called dumptool which dumps all the kernels
+It also complements a tool called dumptool which dumps all the kernel's
memory pages & registers to either a tape or a disk.
-This can be used by tech support or an ambitous end user do
+This can be used by tech support or an ambitious end user do
post mortem debugging of a machine like gdb core dumps.
Going into how to use this tool in detail will be explained
diff -Nru a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt
--- a/Documentation/s390/cds.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/s390/cds.txt Mon Mar 17 13:45:14 2003
@@ -214,7 +214,7 @@
cdev - the ccw_device the data is requested for.
buffer - Pointer to a buffer pointer. The read_conf_data() routine
will allocate a buffer and initialize the buffer pointer
- accordingly. It's the device driver's responsability to
+ accordingly. It's the device driver's responsibility to
release the kernel memory if no longer needed.
length - Length of the buffer allocated and retrieved.
lpm - Logical path mask to be used for retrieving the data. If
@@ -224,7 +224,7 @@
0 - Successful completion
-ENODEV - cdev invalid.
-EINVAL - An invalid parameter was detected, or the function was called early.
--EIO - An irrecoverable I/O error occured or the device is
+-EIO - An irrecoverable I/O error occurred or the device is
not operational.
-ENOMEM - The read_conf_data() routine couldn't obtain storage.
-EOPNOTSUPP - The device doesn't support the read configuration
@@ -428,7 +428,7 @@
can handle lost data on the network to allow for enhanced I/O processing.
Unless the channel subsystem at any time presents a secondary status interrupt,
-exploiting this feature will cause only primary status interrups to be
+exploiting this feature will cause only primary status interrupts to be
presented to the device driver while overlapping I/O is performed. When a
secondary status without error (alert status) is presented, this indicates
successful completion for all overlapping ccw_device_start() requests that have
diff -Nru a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt
--- a/Documentation/s390/driver-model.txt Mon Mar 17 13:45:08 2003
+++ b/Documentation/s390/driver-model.txt Mon Mar 17 13:45:08 2003
@@ -53,7 +53,7 @@
a. Each driver can provide one or more parameter interfaces where parameters can
be specified. These interfaces are also in the driver's responsibility.
-b. After a. has been performed, if neccessary, the device is finally brought up
+b. After a. has been performed, if necessary, the device is finally brought up
via the 'online' interface.
@@ -145,7 +145,7 @@
The handler field of the struct ccw_device is meant to be set to the interrupt
-handler for the device. In order to accomodate drivers which use several
+handler for the device. In order to accommodate drivers which use several
distinct handlers (e.g. multi subchannel devices), this is a member of ccw_device
instead of ccw_driver.
The handler is registered with the common layer during set_online() processing
diff -Nru a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx
--- a/Documentation/scsi/ChangeLog.ncr53c8xx Mon Mar 17 13:45:14 2003
+++ b/Documentation/scsi/ChangeLog.ncr53c8xx Mon Mar 17 13:45:14 2003
@@ -247,7 +247,7 @@
- Add the 53c876 description to the chip table. This is only useful
for printing the right name of the controller.
- DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15).
- - Add additionnal checking of INQUIRY data:
+ - Add additional checking of INQUIRY data:
Check INQUIRY data received length is at least 7. Byte 7 of
inquiry data contains device features bits and the driver might
be confused by garbage. Also check peripheral qualifier.
@@ -420,7 +420,7 @@
- Split DATA_IN and DATA_OUT scripts into 2 sub-scripts.
64 segments are moved from on-chip RAM scripts.
If more segments, a script in main memory is used for the
- additionnal segments.
+ additional segments.
- Since the SCRIPTS processor continues SCRIPTS execution after
having won arbitration, do some stuff prior to testing any SCSI
phase on reselection. This should have the vertue to process
@@ -475,7 +475,7 @@
------------------------------
- Use FAST-5 instead of SLOW for slow scsi devices according to
new SPI-2 draft.
- - Make some changes in order to accomodate with 875 rev <= 3
+ - Make some changes in order to accommodate with 875 rev <= 3
device errata listing 397. Minor consequences are:
. Leave use of PCI Write and Invalidate under user control.
Now, by default the driver does not enable PCI MWI and option
diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx
--- a/Documentation/scsi/ChangeLog.sym53c8xx Mon Mar 17 13:45:14 2003
+++ b/Documentation/scsi/ChangeLog.sym53c8xx Mon Mar 17 13:45:14 2003
@@ -15,7 +15,7 @@
- In ncr_soft_reset(), only try to ABORT the current operation
for chips that support SRUN bit in ISTAT1 and if SCRIPTS are
currently running, as 896 and 1010 manuals suggest.
- - In the CCB abort path, donnot assume that the CCB is currently
+ - In the CCB abort path, do not assume that the CCB is currently
queued to SCRIPTS. This is not always true, notably after a
QUEUE FULL status or when using untagged commands.
@@ -562,7 +562,7 @@
* version pre-sym53c8xx-0.10
- Add the 53c876 description to the chip table. This is only useful
for printing the right name of the controller.
- - Add additionnal checking of INQUIRY data:
+ - Add additional checking of INQUIRY data:
Check INQUIRY data received length is at least 7. Byte 7 of
inquiry data contains device features bits and the driver might
be confused by garbage. Also check peripheral qualifier.
diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx_2 b/Documentation/scsi/ChangeLog.sym53c8xx_2
--- a/Documentation/scsi/ChangeLog.sym53c8xx_2 Mon Mar 17 13:45:12 2003
+++ b/Documentation/scsi/ChangeLog.sym53c8xx_2 Mon Mar 17 13:45:12 2003
@@ -32,7 +32,7 @@
missing free of this memory on instance detach.
- Check against GPIO3 pulled low for HVD controllers (driver did
just the opposite).
- Misdetection of BUS mode was triggerred on module reload only,
+ Misdetection of BUS mode was triggered on module reload only,
since BIOS settings were trusted instead on first load.
Wed Feb 7 21:00 2001 Gerard Roudier
@@ -71,7 +71,7 @@
#LUN <= 7.
- Set busy_itl in LCB to 1 if the LCB is allocated and a
SCSI command is active. This is a simplification.
- - In sym_hcb_free(), donnot scan the free_ccbq if no CCBs
+ - In sym_hcb_free(), do not scan the free_ccbq if no CCBs
has been allocated. This fixes a panic if attach failed.
- Add DT/ST (double/simple transition) in the transfer
negotiation announce.
diff -Nru a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt
--- a/Documentation/scsi/dpti.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/scsi/dpti.txt Mon Mar 17 13:45:14 2003
@@ -75,7 +75,7 @@
* to the board.
*
* The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the
- * interface files for Adaptecs managment routines. These define the structures used
+ * interface files for Adaptec's management routines. These define the structures used
* in the ioctls. They are written to be portable. They are hard to read, but I need
* to use them 'as is' or I can miss changes in the interface.
*
diff -Nru a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt
--- a/Documentation/scsi/ibmmca.txt Mon Mar 17 13:45:13 2003
+++ b/Documentation/scsi/ibmmca.txt Mon Mar 17 13:45:14 2003
@@ -810,9 +810,9 @@
commandline parameter is added, called 'activity'.
2) Added the READ_CONTROL bit for test_unit_ready SCSI-command.
3) Added some suppress_exception bits to read_device_capacity and
- all device_inquiry occurences in the driver code.
+ all device_inquiry occurrences in the driver code.
4) Complaints about the various KERNEL_VERSION implementations are
- taken into account. Every local_LinuxKernelVersion occurence is
+ taken into account. Every local_LinuxKernelVersion occurrence is
now replaced by KERNEL_VERSION, defined in linux/version.h.
Corresponding changes were applied to ibmmca.h, too. This was a
contribution to all kernel-parts by Philipp Hahn.
@@ -866,7 +866,7 @@
2) Adapter-information and autoadaption to address-space is done.
3) Auto-probing for maximum synchronous SCSI transfer rate is working.
4) Optimization to some embedded function calls is applied.
- 5) Added some comment for the user to wait for SCSI-devices beeing probed.
+ 5) Added some comment for the user to wait for SCSI-devices being probed.
6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but...
- Michael Lang
@@ -966,7 +966,7 @@
------DA
where '-' stays dark, 'D' shows the SCSI-device id
- and 'A' shows the SCSI hostindex, beeing currently
+ and 'A' shows the SCSI hostindex, being currently
accessed. During boottime, this will give the message
SCSIini*
@@ -1091,7 +1091,7 @@
now. Normally you really won't need to activate this flag in the
kernel configuration, as all post 1989 SCSI-devices should accept
the reset-signal, when the computer is switched on. The SCSI-
- subsystem generates this reset while beeing initialized. This flag
+ subsystem generates this reset while being initialized. This flag
is really reserved for users with very old, very strange or self-made
SCSI-devices.
Q: Why is the SCSI-order of my drives mirrored to the device-order
diff -Nru a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt
--- a/Documentation/scsi/ncr53c8xx.txt Mon Mar 17 13:45:08 2003
+++ b/Documentation/scsi/ncr53c8xx.txt Mon Mar 17 13:45:08 2003
@@ -238,7 +238,7 @@
optimizations based on actual head positions and its mechanical
characteristics. This feature may also reduce average command latency.
In order to really gain advantage of this feature, devices must have
-a reasonnable cache size (No miracle is to be expected for a low-end
+a reasonable cache size (No miracle is to be expected for a low-end
hard disk with 128 KB or less).
Some kown SCSI devices do not properly support tagged command queuing.
Generally, firmware revisions that fix this kind of problems are available
@@ -592,7 +592,7 @@
Some SCSI-2 devices do not report this feature in byte 7 of inquiry
response but do support it properly (TAMARACK scanners for example).
-CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonnable answer: n)
+CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonable answer: n)
If you suspect a device of yours does not properly support disconnections,
you can answer "y". Then, all SCSI devices will never disconnect the bus
even while performing long SCSI operations.
@@ -827,7 +827,7 @@
Available option bits:
0x0: No check.
- 0x1: Check and donnot attach the controller on error.
+ 0x1: Check and do not attach the controller on error.
0x2: Check and just warn on error.
0x4: Disable SCSI bus integrity checking.
@@ -850,7 +850,7 @@
10.2.22 Enable use of IMMEDIATE ARBITRATION
(only supported by the sym53c8xx driver. See 10.7 for more details)
- iarb:0 donnot use this feature.
+ iarb:0 do not use this feature.
iarb:#x use this feature according to bit fields as follow:
bit 0 (1) : enable IARB each time the initiator has been reselected
@@ -880,7 +880,7 @@
settle time 10 seconds settle:10
differential support from BIOS settings diff:1
irq mode from BIOS settings irqm:1
- SCSI BUS check donnot attach on error buschk:1
+ SCSI BUS check do not attach on error buschk:1
immediate arbitration disabled iarb:0
10.3 Advised boot setup commands
@@ -1272,7 +1272,7 @@
- terminations at both end of the SCSI chain
- linux syslog messages (some of them may help you)
-If you donnot find the source of problems, you can configure the
+If you do not find the source of problems, you can configure the
driver with no features enabled.
- only asynchronous data transfers
@@ -1345,14 +1345,14 @@
Field C : SIST io register (SCSI Interrupt Status)
Bit 0x08 : SGE SCSI GROSS ERROR
Indicates that the chip detected a severe error condition
- on the SCSI BUS that prevents the SCSI protocol from functionning
+ on the SCSI BUS that prevents the SCSI protocol from functioning
properly.
- Bit 0x04 : UDC Undexpected Disconnection
+ Bit 0x04 : UDC Unexpected Disconnection
Indicates that the device released the SCSI BUS when the chip
was not expecting this to happen. A device may behave so to
indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred.
Bit 0x02 : RST SCSI BUS Reset
- Generally SCSI targets donnot reset the SCSI BUS, although any
+ Generally SCSI targets do not reset the SCSI BUS, although any
device on the BUS can reset it at any time.
Bit 0x01 : PAR Parity
SCSI parity error detected.
diff -Nru a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
--- a/Documentation/scsi/sym53c8xx_2.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/scsi/sym53c8xx_2.txt Mon Mar 17 13:45:09 2003
@@ -205,7 +205,7 @@
optimizations based on actual head positions and its mechanical
characteristics. This feature may also reduce average command latency.
In order to really gain advantage of this feature, devices must have
-a reasonnable cache size (No miracle is to be expected for a low-end
+a reasonable cache size (No miracle is to be expected for a low-end
hard disk with 128 KB or less).
Some kown old SCSI devices do not properly support tagged command queuing.
Generally, firmware revisions that fix this kind of problems are available
@@ -579,7 +579,7 @@
Available option bits:
0x0: No check.
- 0x1: Check and donnot attach the controller on error.
+ 0x1: Check and do not attach the controller on error.
0x2: Check and just warn on error.
10.2.16 Exclude a host from being attached
@@ -698,7 +698,7 @@
- terminations at both end of the SCSI chain
- linux syslog messages (some of them may help you)
-If you donnot find the source of problems, you can configure the
+If you do not find the source of problems, you can configure the
driver or devices in the NVRAM with minimal features.
- only asynchronous data transfers
@@ -756,14 +756,14 @@
Field C : SIST io register (SCSI Interrupt Status)
Bit 0x08 : SGE SCSI GROSS ERROR
Indicates that the chip detected a severe error condition
- on the SCSI BUS that prevents the SCSI protocol from functionning
+ on the SCSI BUS that prevents the SCSI protocol from functioning
properly.
- Bit 0x04 : UDC Undexpected Disconnection
+ Bit 0x04 : UDC Unexpected Disconnection
Indicates that the device released the SCSI BUS when the chip
was not expecting this to happen. A device may behave so to
- indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occured.
+ indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred.
Bit 0x02 : RST SCSI BUS Reset
- Generally SCSI targets donnot reset the SCSI BUS, although any
+ Generally SCSI targets do not reset the SCSI BUS, although any
device on the BUS can reset it at any time.
Bit 0x01 : PAR Parity
SCSI parity error detected.
diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt
--- a/Documentation/sonypi.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/sonypi.txt Mon Mar 17 13:45:09 2003
@@ -130,7 +130,7 @@
tested) when using the driver with the fnkeyinit parameter. I cannot
reproduce it on my laptop and not all users have this problem.
This happens because the fnkeyinit parameter enables the ACPI
- mode (but without additionnal ACPI control, like processor
+ mode (but without additional ACPI control, like processor
speed handling etc). Use ACPI instead of APM if it works on your
laptop.
diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
--- a/Documentation/sound/alsa/ALSA-Configuration.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt Mon Mar 17 13:45:09 2003
@@ -659,7 +659,7 @@
Module supports autoprobe and multiple chips (max 8).
Note: on some notebooks the buffer address cannot be detected
automatically, or causes hang-up during initialization.
- In such a case, specify the buffer top address explicity via
+ In such a case, specify the buffer top address explicitly via
buffer_top option.
For example,
Sony F250: buffer_top=0x25a800
diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl Mon Mar 17 13:45:11 2003
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl Mon Mar 17 13:45:11 2003
@@ -2807,7 +2807,7 @@
- If you aquire a spinlock in the interrupt handler, and the
+ If you acquire a spinlock in the interrupt handler, and the
lock is used in other pcm callbacks, too, then you have to
release the lock before calling
snd_pcm_period_elapsed(), because
diff -Nru a/Documentation/sound/oss/NEWS b/Documentation/sound/oss/NEWS
--- a/Documentation/sound/oss/NEWS Mon Mar 17 13:45:14 2003
+++ b/Documentation/sound/oss/NEWS Mon Mar 17 13:45:14 2003
@@ -19,7 +19,7 @@
Before Linux 2.4 you had to specify the resources for sounddrivers
statically linked into the kernel at compile time
-(in make config/menuconfig/xconfig). In Linux 2.4 the ressources are
+(in make config/menuconfig/xconfig). In Linux 2.4 the resources are
now specified at the boot-time kernel commandline (e.g. the lilo
'append=' line or everything that's after the kernel name in grub).
Read the Configure.help entry for your card for the parameters.
diff -Nru a/Documentation/sound/oss/PSS-updates b/Documentation/sound/oss/PSS-updates
--- a/Documentation/sound/oss/PSS-updates Mon Mar 17 13:45:15 2003
+++ b/Documentation/sound/oss/PSS-updates Mon Mar 17 13:45:15 2003
@@ -22,12 +22,12 @@
This parameter takes a port address as its parameter. Any available port
address can be specified to enable the CDROM port, except for 0x0 and -1 as
these values would leave the port disabled. Like the joystick port, the cdrom
-port will require that an appropiate CDROM driver be loaded before you can make
+port will require that an appropriate CDROM driver be loaded before you can make
use of the newly enabled CDROM port. Like the joystick port option above,
remember to load the CDROM driver AFTER the pss sound driver. While it may
differ on some PSS sound cards, all the PSS sound cards that I have seen have a
builtin Wearnes CDROM port. If this is the case with your PSS sound card you
-should load aztcd with the appropiate port option that matches the port you
+should load aztcd with the appropriate port option that matches the port you
assigned to the CDROM port when you loaded your pss sound driver. (ex.
modprobe pss pss_cdrom_port=0x340 && modprobe aztcd aztcd=0x340) The default
setting of this parameter leaves the CDROM port disabled to maintain full
@@ -44,7 +44,7 @@
value will only attept to configure the CDROM and joystick ports. This
parameter can be used by a user who only wished to use the builtin joystick
and/or CDROM port(s) of his PSS sound card. If this driver is loaded with this
-parameter and with the paramter below set to true then a user can safely unload
+parameter and with the parameter below set to true then a user can safely unload
this driver with the following command "rmmod pss && rmmod ad1848 && rmmod
mpu401 && rmmod sound && rmmod soundcore" and retain the full functionality of
his CDROM and/or joystick port(s) while gaining back the memory previously used
diff -Nru a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx
--- a/Documentation/sound/oss/cs46xx Mon Mar 17 13:45:09 2003
+++ b/Documentation/sound/oss/cs46xx Mon Mar 17 13:45:09 2003
@@ -78,7 +78,7 @@
driver to disable compilation of the CS_DBGOUT print statements:
#define CSDEBUG 1
-Please see the defintions for cs_debuglevel and cs_debugmask for additional
+Please see the definitions for cs_debuglevel and cs_debugmask for additional
information on the debug levels and sections.
There is also a csdbg executable to allow runtime manipulation of these
diff -Nru a/Documentation/specialix.txt b/Documentation/specialix.txt
--- a/Documentation/specialix.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/specialix.txt Mon Mar 17 13:45:09 2003
@@ -326,7 +326,7 @@
Fixed bugs and restrictions:
- - During intialization, interrupts are blindly turned on.
+ - During initialization, interrupts are blindly turned on.
Having a shadow variable would cause an extra memory
access on every IO instruction.
- The interrupt (on the card) should be disabled when we
diff -Nru a/Documentation/swsusp.txt b/Documentation/swsusp.txt
--- a/Documentation/swsusp.txt Mon Mar 17 13:45:08 2003
+++ b/Documentation/swsusp.txt Mon Mar 17 13:45:08 2003
@@ -90,7 +90,7 @@
function do_software_suspend, it is called. Here we shrink everything including
dcache, inodes, buffers and memory (here mainly processes are swapped out). We
count how many pages we need to duplicate (we have to be atomical!) then we
-create an appropiate sized page directory. It will point to the original and
+create an appropriate sized page directory. It will point to the original and
the new (copied) address of the page. We get the free pages by
__get_free_pages() but since it changes state we have to be able to track it
later so it also flips in a bit in page's flags (a new Nosave flag). We
diff -Nru a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt
--- a/Documentation/uml/UserModeLinux-HOWTO.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/uml/UserModeLinux-HOWTO.txt Mon Mar 17 13:45:09 2003
@@ -2509,7 +2509,7 @@
1100..88.. ssttoopp
This puts the UML in a loop reading mconsole requests until a 'go'
- mconsole command is recieved. This is very useful for making backups
+ mconsole command is received. This is very useful for making backups
of UML filesystems, as the UML can be stopped, then synced via 'sysrq
s', so that everything is written to the filesystem. You can then copy
the filesystem and then send the UML 'go' via mconsole.
diff -Nru a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
--- a/Documentation/usb/URB.txt Mon Mar 17 13:45:11 2003
+++ b/Documentation/usb/URB.txt Mon Mar 17 13:45:11 2003
@@ -86,7 +86,7 @@
Return value is a pointer to the allocated URB, 0 if allocation failed.
The parameter isoframes specifies the number of isochronous transfer frames
-you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags paramter
+you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags parameter
holds standard memory allocation flags, letting you control (among other
things) whether the underlying code may block or not.
diff -Nru a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt
--- a/Documentation/usb/hiddev.txt Mon Mar 17 13:45:11 2003
+++ b/Documentation/usb/hiddev.txt Mon Mar 17 13:45:11 2003
@@ -173,7 +173,7 @@
usage to be retrieved can be specified as above, or the user can
choose to fill in the report_type field and specify the report_id as
HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be
-filled in with the report and field infomation associated with this
+filled in with the report and field information associated with this
usage if it is found.
HIDIOCSUSAGE - struct hiddev_usage_ref (write)
diff -Nru a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt
--- a/Documentation/usb/philips.txt Mon Mar 17 13:45:14 2003
+++ b/Documentation/usb/philips.txt Mon Mar 17 13:45:14 2003
@@ -27,9 +27,9 @@
Specifies the desired framerate. Is an integer in the range of 4-30.
fbufs
- This paramter specifies the number of internal buffers to use for storing
+ This parameter specifies the number of internal buffers to use for storing
frames from the cam. This will help if the process that reads images from
- the cam is a bit slow or momentarely busy. However, on slow machines it
+ the cam is a bit slow or momentarily busy. However, on slow machines it
only introduces lag, so choose carefully. The default is 3, which is
reasonable. You can set it between 2 and 5.
diff -Nru a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt
--- a/Documentation/usb/scanner.txt Mon Mar 17 13:45:15 2003
+++ b/Documentation/usb/scanner.txt Mon Mar 17 13:45:15 2003
@@ -282,7 +282,7 @@
}
if((fpout=fopen("out.dat", "w+")) == NULL) {
- perror("Unable to open ouput file");
+ perror("Unable to open output file");
exit(1);
}
diff -Nru a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ
--- a/Documentation/video4linux/bttv/Sound-FAQ Mon Mar 17 13:45:16 2003
+++ b/Documentation/video4linux/bttv/Sound-FAQ Mon Mar 17 13:45:16 2003
@@ -15,18 +15,18 @@
bttv0: model: BT848(Hauppauge old) [autodetected]
-You should verify this is correct. If it is'nt, you have to pass the
+You should verify this is correct. If it isn't, you have to pass the
correct board type as insmod argument, "insmod bttv card=2" for
example. The file CARDLIST has a list of valid arguments for card.
-If your card is'nt listed there, you might check the source code for
-new entries which are not listed yet. If there is'nt one for your
+If your card isn't listed there, you might check the source code for
+new entries which are not listed yet. If there isn't one for your
card, you can check if one of the existing entries does work for you
(just trial and error...).
Some boards have an extra processor for sound to do stereo decoding
and other nice features. The msp34xx chips are used by Hauppauge for
example. If your board has one, you might have to load a helper
-module like msp3400.o to make sound work. If there is'nt one for the
+module like msp3400.o to make sound work. If there isn't one for the
chip used on your board: Bad luck. Start writing a new one. Well,
you might want to check the video4linux mailing list archive first...
diff -Nru a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt
--- a/Documentation/video4linux/zr36120.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/video4linux/zr36120.txt Mon Mar 17 13:45:09 2003
@@ -146,10 +146,10 @@
The consequence is that, when loading the driver as a module,
the module may tell you it's out of memory, but 'free' says
otherwise. The reason is simple; the modules wants its memory
-contingious, not fragmented, and after a long uptime there
+contiguous, not fragmented, and after a long uptime there
probably isn't a fragment of memory large enough...
-The driver uses a double buffering scheme, which should realy
+The driver uses a double buffering scheme, which should really
be an n-way buffer, depending on the size of allocated framebuffer
and the requested grab-size/format.
This current version also fixes a dead-lock situation during irq
diff -Nru a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt
--- a/Documentation/vm/hugetlbpage.txt Mon Mar 17 13:45:09 2003
+++ b/Documentation/vm/hugetlbpage.txt Mon Mar 17 13:45:09 2003
@@ -69,7 +69,7 @@
mount none /mnt/huge -t hugetlbfs
-This commands mounts a (psuedo) filesystem of type hugetlbfs on the directory
+This command mounts a (pseudo) filesystem of type hugetlbfs on the directory
/mnt/huge. Any files created on /mnt/huge uses hugepages. An example is
given at the end of this document.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS Mon Mar 17 13:45:13 2003
+++ b/MAINTAINERS Mon Mar 17 13:45:13 2003
@@ -641,7 +641,7 @@
P: Rui Sousa
M: rui.p.m.sousa@clix.pt
L: emu10k1-devel@lists.sourceforge.net
-W: http://opensource.creative.com/
+W: http://sourceforge.net/projects/emu10k1/
S: Maintained
ETHEREXPRESS-16 NETWORK DRIVER
diff -Nru a/Makefile b/Makefile
--- a/Makefile Mon Mar 17 13:45:09 2003
+++ b/Makefile Mon Mar 17 13:45:09 2003
@@ -1,6 +1,6 @@
VERSION = 2
PATCHLEVEL = 5
-SUBLEVEL = 64
+SUBLEVEL = 65
EXTRAVERSION =
# *DOCUMENTATION*
@@ -107,6 +107,11 @@
# For now, leave verbose as default
+ifdef V
+ ifeq ("$(origin V)", "command line")
+ KBUILD_VERBOSE = $(V)
+ endif
+endif
ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 1
endif
@@ -193,7 +198,7 @@
comma := ,
depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
-noconfig_targets := xconfig menuconfig config oldconfig randconfig \
+noconfig_targets := xconfig gconfig menuconfig config oldconfig randconfig \
defconfig allyesconfig allnoconfig allmodconfig \
clean mrproper distclean rpm \
help tags TAGS cscope sgmldocs psdocs pdfdocs htmldocs \
@@ -328,8 +333,10 @@
. $(srctree)/scripts/mkversion > .tmp_version; \
mv -f .tmp_version .version; \
$(MAKE) $(build)=init; \
- )
- $(call cmd,vmlinux__); \
+ ) \
+ $(if $($(quiet)cmd_vmlinux__), \
+ echo ' $($(quiet)cmd_vmlinux__)' &&) \
+ $(cmd_vmlinux__); \
echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
endef
@@ -472,17 +479,19 @@
uts_len := 64
-include/linux/version.h: Makefile
- @if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \
+define filechk_version.h
+ if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
exit 1; \
fi;
- @echo -n ' GEN $@'
- @(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
+ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \
echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \
- ) > $@.tmp
- @$(update-if-changed)
+ )
+endef
+
+include/linux/version.h: Makefile
+ $(call filechk,version.h)
# ---------------------------------------------------------------------------
@@ -551,7 +560,7 @@
# Generate asm-offsets.h
# ---------------------------------------------------------------------------
-define generate-asm-offsets.h
+define filechk_gen-asm-offsets
(set -e; \
echo "#ifndef __ASM_OFFSETS_H__"; \
echo "#define __ASM_OFFSETS_H__"; \
@@ -567,7 +576,6 @@
echo "#endif" )
endef
-
else # ifdef include_config
ifeq ($(filter-out $(noconfig_targets),$(MAKECMDGOALS)),)
@@ -598,15 +606,18 @@
# Kernel configuration
# ---------------------------------------------------------------------------
-.PHONY: oldconfig xconfig menuconfig config \
+.PHONY: oldconfig xconfig gconfig menuconfig config \
make_with_config rpm
-scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf: scripts/fixdep FORCE
+scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf scripts/kconfig/gconf: scripts/fixdep FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
xconfig: scripts/kconfig/qconf
./scripts/kconfig/qconf arch/$(ARCH)/Kconfig
+gconfig: scripts/kconfig/gconf
+ ./scripts/kconfig/gconf arch/$(ARCH)/Kconfig
+
menuconfig: scripts/kconfig/mconf
$(Q)$(MAKE) $(build)=scripts/lxdialog
./scripts/kconfig/mconf arch/$(ARCH)/Kconfig
@@ -875,13 +886,28 @@
cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
-define update-if-changed
- if [ -r $@ ] && cmp -s $@ $@.tmp; then \
- echo ' (unchanged)'; \
- rm -f $@.tmp; \
- else \
- echo ' (updated)'; \
- mv -f $@.tmp $@; \
+# 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 $@'; \
+ $(filechk_$(1)) < $< > $@.tmp; \
+ if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ echo ' UPD $@'; \
+ mv -f $@.tmp $@; \
fi
endef
diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig
--- a/arch/alpha/Kconfig Mon Mar 17 13:45:14 2003
+++ b/arch/alpha/Kconfig Mon Mar 17 13:45:14 2003
@@ -15,10 +15,6 @@
bool
default y
-config SWAP
- bool
- default y
-
config UID16
bool
diff -Nru a/arch/alpha/Makefile b/arch/alpha/Makefile
--- a/arch/alpha/Makefile Mon Mar 17 13:45:13 2003
+++ b/arch/alpha/Makefile Mon Mar 17 13:45:13 2003
@@ -119,15 +119,12 @@
include/config/MARKER
include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
- @echo -n ' Generating $@'
- @$(generate-asm-offsets.h) < $< > $@.tmp
- @$(update-if-changed)
+ $(call filechk,gen-asm-offsets)
archclean:
$(Q)$(MAKE) -f scripts/Makefile.clean obj=$(boot)
-CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h.tmp \
- include/asm-$(ARCH)/asm_offsets.h
+CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
define archhelp
echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
diff -Nru a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile
--- a/arch/alpha/boot/Makefile Mon Mar 17 13:45:09 2003
+++ b/arch/alpha/boot/Makefile Mon Mar 17 13:45:09 2003
@@ -9,7 +9,7 @@
#
host-progs := tools/mkbb tools/objstrip
-EXTRA_TARGETS := vmlinux.gz vmlinux \
+targets := vmlinux.gz vmlinux \
vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
bootloader bootpheader
OBJSTRIP := $(obj)/tools/objstrip
diff -Nru a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
--- a/arch/alpha/kernel/Makefile Mon Mar 17 13:45:12 2003
+++ b/arch/alpha/kernel/Makefile Mon Mar 17 13:45:12 2003
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-EXTRA_TARGETS := head.o
+extra-y := head.o
EXTRA_AFLAGS := $(CFLAGS)
EXTRA_CFLAGS := -Werror -Wno-sign-compare
diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
--- a/arch/alpha/kernel/core_marvel.c Mon Mar 17 13:45:09 2003
+++ b/arch/alpha/kernel/core_marvel.c Mon Mar 17 13:45:09 2003
@@ -1076,7 +1076,7 @@
/*
* Fill it in.
*/
- agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
+ agp->type = ALPHA_CORE_AGP;
agp->hose = hose;
agp->private = NULL;
agp->ops = &marvel_agp_ops;
diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
--- a/arch/alpha/kernel/core_titan.c Mon Mar 17 13:45:11 2003
+++ b/arch/alpha/kernel/core_titan.c Mon Mar 17 13:45:11 2003
@@ -764,7 +764,7 @@
/*
* Fill it in.
*/
- agp->type = 0 /* FIXME: ALPHA_CORE_AGP */;
+ agp->type = ALPHA_CORE_AGP;
agp->hose = hose;
agp->private = port;
agp->ops = &titan_agp_ops;
diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
--- a/arch/alpha/kernel/irq.c Mon Mar 17 13:45:14 2003
+++ b/arch/alpha/kernel/irq.c Mon Mar 17 13:45:14 2003
@@ -515,6 +515,7 @@
#endif
int i;
struct irqaction * action;
+ unsigned long flags;
#ifdef CONFIG_SMP
seq_puts(p, " ");
@@ -525,9 +526,10 @@
#endif
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
- continue;
+ goto unlock;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
@@ -538,15 +540,18 @@
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %c%s",
- (action->flags & SA_INTERRUPT)?'+':' ',
- action->name);
+ (action->flags & SA_INTERRUPT)?'+':' ',
+ action->name);
for (action=action->next; action; action = action->next) {
seq_printf(p, ", %c%s",
- (action->flags & SA_INTERRUPT)?'+':' ',
- action->name);
+ (action->flags & SA_INTERRUPT)?'+':' ',
+ action->name);
}
+
seq_putc(p, '\n');
+unlock:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
#if CONFIG_SMP
seq_puts(p, "IPI: ");
diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
--- a/arch/alpha/kernel/pci.c Mon Mar 17 13:45:09 2003
+++ b/arch/alpha/kernel/pci.c Mon Mar 17 13:45:09 2003
@@ -12,7 +12,7 @@
* Nov 2000, Ivan Kokshaysky
* PCI-PCI bridges cleanup
*/
-
+#include
#include
#include
#include
@@ -264,45 +264,6 @@
}
}
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *parent,
- struct resource *res, int resource)
-{
- struct pci_controller *hose = dev->sysdata;
- struct resource *root;
- int where;
- u32 reg;
-
- if (resource < PCI_ROM_RESOURCE)
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- else if (resource == PCI_ROM_RESOURCE)
- where = dev->rom_base_reg;
- else {
- return; /* Don't update non-standard resources here. */
- }
-
- /* Point root at the hose root. */
- if (res->flags & IORESOURCE_IO)
- root = hose->io_space;
- else if (res->flags & IORESOURCE_MEM)
- root = hose->mem_space;
- else {
- return; /* Don't update non-standard resources here. */
- }
-
- reg = (res->start - root->start) | (res->flags & 0xf);
- pci_write_config_dword(dev, where, reg);
- if ((res->flags & (PCI_BASE_ADDRESS_SPACE
- | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
- == (PCI_BASE_ADDRESS_SPACE_MEMORY
- | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
- pci_write_config_dword(dev, where+4, 0);
- printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->dev.name);
- }
-
- /* ??? FIXME -- record old value for shutdown. */
-}
-
void __init
pcibios_update_irq(struct pci_dev *dev, int irq)
{
@@ -334,21 +295,25 @@
}
void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus,
- struct pbus_set_ranges_data * ranges)
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
{
- struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
- ranges->io_start -= hose->io_space->start;
- ranges->io_end -= hose->io_space->start;
- ranges->mem_start -= hose->mem_space->start;
- ranges->mem_end -= hose->mem_space->start;
-/* FIXME: On older alphas we could use dense memory space
- to access prefetchable resources. */
- ranges->prefetch_start -= hose->mem_space->start;
- ranges->prefetch_end -= hose->mem_space->start;
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_space->start;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_space->start;
+
+ region->start = res->start - offset;
+ region->end = res->end - offset;
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
int
pcibios_enable_device(struct pci_dev *dev, int mask)
{
@@ -393,26 +358,36 @@
}
static void __init
+pcibios_claim_one_bus(struct pci_bus *b)
+{
+ struct list_head *ld;
+ struct pci_bus *child_bus;
+
+ for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
+ struct pci_dev *dev = pci_dev_b(ld);
+ int i;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *r = &dev->resource[i];
+
+ if (r->parent || !r->start || !r->flags)
+ continue;
+ pci_claim_resource(dev, i);
+ }
+ }
+
+ list_for_each_entry(child_bus, &b->children, node)
+ pcibios_claim_one_bus(child_bus);
+}
+
+static void __init
pcibios_claim_console_setup(void)
{
struct list_head *lb;
for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) {
struct pci_bus *b = pci_bus_b(lb);
- struct list_head *ld;
-
- for (ld = b->devices.next; ld != &b->devices; ld = ld->next) {
- struct pci_dev *dev = pci_dev_b(ld);
- int i;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *r = &dev->resource[i];
-
- if (r->parent || !r->start || !r->flags)
- continue;
- pci_claim_resource(dev, i);
- }
- }
+ pcibios_claim_one_bus(b);
}
}
diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
--- a/arch/alpha/kernel/sys_nautilus.c Mon Mar 17 13:45:12 2003
+++ b/arch/alpha/kernel/sys_nautilus.c Mon Mar 17 13:45:12 2003
@@ -78,6 +78,8 @@
nautilus_kill_arch(int mode)
{
struct pci_bus *bus = pci_isa_hose->bus;
+ u32 pmuport;
+ int off;
switch (mode) {
case LINUX_REBOOT_CMD_RESTART:
@@ -92,14 +94,18 @@
break;
case LINUX_REBOOT_CMD_POWER_OFF:
- {
- u32 pmuport;
- pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
- pmuport &= 0xfffe;
- outl(0xffff, pmuport); /* clear pending events */
- outw(0x2000, pmuport+4); /* power off */
- /* NOTREACHED */
+ /* Assume M1543C */
+ off = 0x2000; /* SLP_TYPE = 0, SLP_EN = 1 */
+ pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
+ if (!pmuport) {
+ /* M1535D/D+ */
+ off = 0x3400; /* SLP_TYPE = 5, SLP_EN = 1 */
+ pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
}
+ pmuport &= 0xfffe;
+ outw(0xffff, pmuport); /* Clear pending events. */
+ outw(off, pmuport + 4);
+ /* NOTREACHED */
break;
}
}
diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
--- a/arch/alpha/mm/fault.c Mon Mar 17 13:45:11 2003
+++ b/arch/alpha/mm/fault.c Mon Mar 17 13:45:11 2003
@@ -232,11 +232,11 @@
else {
/* Synchronize this task's top level page-table
with the "reference" page table from init. */
- long offset = __pgd_offset(address);
+ long index = pgd_index(address);
pgd_t *pgd, *pgd_k;
- pgd = current->active_mm->pgd + offset;
- pgd_k = swapper_pg_dir + offset;
+ pgd = current->active_mm->pgd + index;
+ pgd_k = swapper_pg_dir + index;
if (!pgd_present(*pgd) && pgd_present(*pgd_k)) {
pgd_val(*pgd) = pgd_val(*pgd_k);
return;
diff -Nru a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c
--- a/arch/alpha/oprofile/op_model_ev4.c Mon Mar 17 13:45:12 2003
+++ b/arch/alpha/oprofile/op_model_ev4.c Mon Mar 17 13:45:12 2003
@@ -34,7 +34,7 @@
for these "disabled" counter overflows are ignored by the
interrupt handler.
- This is most irritating, becuase the hardware *can* enable and
+ This is most irritating, because the hardware *can* enable and
disable the interrupts for these counters independently, but the
wrperfmon interface doesn't allow it. */
diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S
--- a/arch/alpha/vmlinux.lds.S Mon Mar 17 13:45:13 2003
+++ b/arch/alpha/vmlinux.lds.S Mon Mar 17 13:45:13 2003
@@ -63,6 +63,13 @@
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
+ . = ALIGN(8);
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+
. = ALIGN(64);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig Mon Mar 17 13:45:13 2003
+++ b/arch/arm/Kconfig Mon Mar 17 13:45:13 2003
@@ -20,10 +20,6 @@
bool
default y
-config SWAP
- bool
- default y
-
config EISA
bool
---help---
@@ -534,15 +530,63 @@
written) to implement the policy. If you don't understand what this
is all about, it's safe to say 'N'.
+
+# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor
+
+config CPU_FREQ_SA1100
+ bool
+ depends on CPU_FREQ && SA1100_LART
+ default y
+
+config CPU_FREQ_SA1110
+ bool
+ depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3)
+ default y
+
+if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110)
+
+config CPU_FREQ_GOV_USERSPACE
+ bool
+ depends on CPU_FREQ
+ default y
+
config CPU_FREQ_24_API
bool
- depends on CPU_FREQ
+ depends on CPU_FREQ_GOV_USERSPACE && SYSCTL
default y
config CPU_FREQ_PROC_INTF
- tristate
- depends on CPU_FREQ
+ tristate "/proc/cpufreq interface (deprecated)"
+ depends on CPU_FREQ && PROC_FS
+ help
+ This enables the /proc/cpufreq interface for controlling
+ CPUFreq. Please note that it is recommended to use the sysfs
+ interface instead (which is built automatically).
+
+ For details, take a look at linux/Documentation/cpufreq.
+
+ If in doubt, say N.
+
+endif
+
+# CPUfreq on Integrator can use the generic cpufreq core
+
+config CPU_FREQ_INTEGRATOR
+ tristate "CPUfreq driver for ARM Integrator CPUs"
+ depends on ARCH_INTEGRATOR && CPU_FREQ
default y
+ help
+ This enables the CPUfreq driver for ARM Integrator CPUs.
+
+ For details, take a look at linux/Documentation/cpufreq.
+
+ If in doubt, say Y.
+
+if (CPU_FREQ_INTEGRATOR)
+
+source "drivers/cpufreq/Kconfig"
+
+endif
source "drivers/pci/Kconfig"
diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile
--- a/arch/arm/Makefile Mon Mar 17 13:45:12 2003
+++ b/arch/arm/Makefile Mon Mar 17 13:45:12 2003
@@ -211,9 +211,7 @@
include/config/MARKER
include/asm-$(ARCH)/constants.h: arch/$(ARCH)/kernel/asm-offsets.s
- @echo -n ' Generating $@'
- @$(generate-asm-offsets.h) < $< > $@.tmp
- @$(update-if-changed)
+ $(call filechk,gen-asm-offsets)
define archhelp
echo '* zImage - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
diff -Nru a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
--- a/arch/arm/boot/Makefile Mon Mar 17 13:45:09 2003
+++ b/arch/arm/boot/Makefile Mon Mar 17 13:45:09 2003
@@ -69,7 +69,7 @@
export ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS PARAMS_PHYS
-EXTRA_TARGETS := Image zImage bootpImage
+targets := Image zImage bootpImage
$(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy)
@@ -106,5 +106,4 @@
$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) \
$(obj)/zImage System.map "$(INSTALL_PATH)"
-clean-files := $(addprefix $(obj)/,Image zImage bootpImage)
subdir- := bootp compressed
diff -Nru a/arch/arm/boot/bootp/Makefile b/arch/arm/boot/bootp/Makefile
--- a/arch/arm/boot/bootp/Makefile Mon Mar 17 13:45:14 2003
+++ b/arch/arm/boot/bootp/Makefile Mon Mar 17 13:45:14 2003
@@ -7,7 +7,7 @@
--defsym initrd_addr=$(INITRD_PHYS) \
--defsym params=$(PARAMS_PHYS)
-EXTRA_TARGETS := bootp
+extra-y := bootp
# Note that bootp.lds picks up kernel.o and initrd.o
$(obj)/bootp: $(addprefix $(obj)/,init.o kernel.o initrd.o bootp.lds)
diff -Nru a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
--- a/arch/arm/boot/compressed/Makefile Mon Mar 17 13:45:09 2003
+++ b/arch/arm/boot/compressed/Makefile Mon Mar 17 13:45:09 2003
@@ -65,8 +65,8 @@
SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/LOAD_ADDR/$(ZRELADDR)/;s/BSS_START/$(ZBSSADDR)/
-EXTRA_TARGETS := vmlinux vmlinux.lds piggy piggy.gz\
- piggy.o font.o head.o $(OBJS)
+targets := vmlinux vmlinux.lds piggy piggy.gz piggy.o \
+ font.o head.o $(OBJS)
EXTRA_CFLAGS := $(CFLAGS_BOOT) -fpic
EXTRA_AFLAGS := -traditional
@@ -94,8 +94,6 @@
$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in Makefile arch/arm/boot/Makefile .config
@sed "$(SEDFLAGS)" < $< > $@
-
-clean-files := $(addprefix $(obj)/,vmlinux piggy* vmlinux.lds)
$(obj)/misc.o: $(obj)/misc.c include/asm/arch/uncompress.h lib/inflate.c
diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
--- a/arch/arm/common/sa1111.c Mon Mar 17 13:45:14 2003
+++ b/arch/arm/common/sa1111.c Mon Mar 17 13:45:14 2003
@@ -743,25 +743,23 @@
static int sa1111_suspend(struct device *dev, u32 state, u32 level)
{
struct sa1111 *sachip = dev_get_drvdata(dev);
+ struct sa1111_save_data *save;
unsigned long flags;
char *base;
+ if (!dev->saved_state && level == SUSPEND_NOTIFY)
+ dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
+ if (!dev->saved_state)
+ return -ENOMEM;
+
+ save = (struct sa1111_save_data *)dev->saved_state;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+
/*
* Save state.
*/
- if (level == SUSPEND_SAVE_STATE ||
- level == SUSPEND_DISABLE ||
- level == SUSPEND_POWER_DOWN) {
- struct sa1111_save_data *save;
-
- if (!dev->saved_state)
- dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
- if (!dev->saved_state)
- return -ENOMEM;
-
- save = (struct sa1111_save_data *)dev->saved_state;
-
- spin_lock_irqsave(&sachip->lock, flags);
+ if (level == SUSPEND_SAVE_STATE) {
base = sachip->base;
save->skcr = sa1111_readl(base + SA1111_SKCR);
save->skpcr = sa1111_readl(base + SA1111_SKPCR);
@@ -779,26 +777,21 @@
save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0);
save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1);
- spin_unlock_irqrestore(&sachip->lock, flags);
}
/*
* Disable.
*/
- if (level == SUSPEND_DISABLE && state == 4) {
- unsigned int val;
-
- spin_lock_irqsave(&sachip->lock, flags);
- base = sachip->base;
-
- sa1111_writel(0, base + SA1111_SKPWM0);
- sa1111_writel(0, base + SA1111_SKPWM1);
- val = sa1111_readl(base + SA1111_SKCR);
- sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR);
+ if (level == SUSPEND_POWER_DOWN && state == 4) {
+ unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR);
- spin_unlock_irqrestore(&sachip->lock, flags);
+ sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
+ sa1111_writel(0, sachip->base + SA1111_SKPWM0);
+ sa1111_writel(0, sachip->base + SA1111_SKPWM1);
}
+ spin_unlock_irqrestore(&sachip->lock, flags);
+
return 0;
}
@@ -819,17 +812,15 @@
unsigned long flags, id;
char *base;
- if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE)
- return 0;
-
save = (struct sa1111_save_data *)dev->saved_state;
if (!save)
return 0;
- dev->saved_state = NULL;
+ spin_lock_irqsave(&sachip->lock, flags);
/*
* Ensure that the SA1111 is still here.
+ * FIXME: shouldn't do this here.
*/
id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
@@ -839,29 +830,42 @@
return 0;
}
- spin_lock_irqsave(&sachip->lock, flags);
- sa1111_wake(sachip);
+ /*
+ * First of all, wake up the chip.
+ */
+ if (level == RESUME_POWER_ON) {
+ sa1111_wake(sachip);
+
+ sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
+ sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
+ }
+
+ if (level == RESUME_RESTORE_STATE) {
+ base = sachip->base;
+ sa1111_writel(save->skcr, base + SA1111_SKCR);
+ sa1111_writel(save->skpcr, base + SA1111_SKPCR);
+ sa1111_writel(save->skcdr, base + SA1111_SKCDR);
+ sa1111_writel(save->skaud, base + SA1111_SKAUD);
+ sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
+ sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
+
+ base = sachip->base + SA1111_INTC;
+ sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
+ sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
+ sa1111_writel(save->inten0, base + SA1111_INTEN0);
+ sa1111_writel(save->inten1, base + SA1111_INTEN1);
+ sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
+ sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
+ sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
+ sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
+ }
- base = sachip->base;
- sa1111_writel(save->skcr, base + SA1111_SKCR);
- sa1111_writel(save->skpcr, base + SA1111_SKPCR);
- sa1111_writel(save->skcdr, base + SA1111_SKCDR);
- sa1111_writel(save->skaud, base + SA1111_SKAUD);
- sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
- sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
-
- base = sachip->base + SA1111_INTC;
- sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
- sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
- sa1111_writel(save->inten0, base + SA1111_INTEN0);
- sa1111_writel(save->inten1, base + SA1111_INTEN1);
- sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
- sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
- sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
- sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
spin_unlock_irqrestore(&sachip->lock, flags);
- kfree(save);
+ if (level == RESUME_ENABLE) {
+ dev->saved_state = NULL;
+ kfree(save);
+ }
return 0;
}
diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
--- a/arch/arm/kernel/Makefile Mon Mar 17 13:45:14 2003
+++ b/arch/arm/kernel/Makefile Mon Mar 17 13:45:14 2003
@@ -11,11 +11,9 @@
obj-y := arch.o compat.o dma.o $(ENTRY_OBJ) entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o
-obj-m :=
-obj-n :=
-obj- :=
obj-$(CONFIG_APM) += apm.o
+obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o
obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o
obj-$(CONFIG_FOOTBRIDGE) += isa.o
@@ -34,7 +32,7 @@
obj-$(CONFIG_DEBUG_LL) += debug.o
endif
-EXTRA_TARGETS := $(head-y) init_task.o
+extra-y := $(head-y) init_task.o
# Spell out some dependencies that `make dep' doesn't spot
$(obj)/entry-armv.o: $(obj)/entry-header.S include/asm-arm/constants.h
diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/arm/kernel/apm.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,573 @@
+/*
+ * bios-less APM driver for ARM Linux
+ * Jamey Hicks
+ * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ * Intel Corporation, Microsoft Corporation. Advanced Power Management
+ * (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ * http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV 134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ * apm=on/off enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS 20
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+ struct list_head list;
+
+ int suser: 1;
+ int writer: 1;
+ int reader: 1;
+ int suspend_wait: 1;
+ int suspend_result;
+
+ int suspends_pending;
+ int standbys_pending;
+ unsigned int suspends_read;
+ unsigned int standbys_read;
+
+ int event_head;
+ int event_tail;
+ apm_event_t events[APM_MAX_EVENTS];
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int standbys_pending;
+static int apm_disabled;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(apm_user_list);
+
+/*
+ * The kapmd info.
+ */
+static struct task_struct *kapmd;
+static DECLARE_COMPLETION(kapmd_exit);
+
+static const char driver_version[] = "1.13"; /* no spaces */
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation. Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+ unsigned char ac_line_status;
+ unsigned char battery_status;
+ unsigned char battery_flag;
+ unsigned char battery_life;
+ int time;
+ int units;
+};
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600)
+ extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *,
+ u_char *, u_short *);
+
+ if (machine_is_h3600()) {
+ int dx;
+ h3600_apm_get_power_status(&info->ac_line_status,
+ &info->battery_status, &info->battery_flag,
+ &info->battery_life, &dx);
+ info->time = dx & 0x7fff;
+ info->units = dx & 0x8000 ? 0 : 1;
+ }
+#endif
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+static int queue_empty(struct apm_user *as)
+{
+ return as->event_head == as->event_tail;
+}
+
+static apm_event_t get_queued_event(struct apm_user *as)
+{
+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+ return as->events[as->event_tail];
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+ as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
+ if (as->event_head == as->event_tail) {
+ static int notified;
+
+ if (notified++ == 0)
+ printk(KERN_ERR "apm: an event queue overflowed\n");
+ as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+ }
+ as->events[as->event_head] = event;
+
+ if (!as->suser || !as->writer)
+ return;
+
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ as->suspends_pending++;
+ suspends_pending++;
+ break;
+
+ case APM_SYS_STANDBY:
+ case APM_USER_STANDBY:
+ as->standbys_pending++;
+ standbys_pending++;
+ break;
+ }
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+ struct list_head *l;
+
+ spin_lock(&user_list_lock);
+ list_for_each(l, &apm_user_list) {
+ struct apm_user *as = list_entry(l, struct apm_user, list);
+
+ if (as != sender && as->reader)
+ queue_event_one_user(as, event);
+ }
+ spin_unlock(&user_list_lock);
+ wake_up_interruptible(&apm_waitqueue);
+}
+
+/* defined in pm.c */
+extern int suspend(void);
+
+static int apm_suspend(void)
+{
+ struct list_head *l;
+ int err = suspend();
+
+ /*
+ * Anyone on the APM queues will think we're still suspended.
+ * Send a message so everyone knows we're now awake again.
+ */
+ queue_event(APM_NORMAL_RESUME, NULL);
+
+ /*
+ * Finally, wake up anyone who is sleeping on the suspend.
+ */
+ spin_lock(&user_list_lock);
+ list_for_each(l, &apm_user_list) {
+ struct apm_user *as = list_entry(l, struct apm_user, list);
+
+ as->suspend_result = err;
+ as->suspend_wait = 0;
+ }
+ spin_unlock(&user_list_lock);
+
+ wake_up_interruptible(&apm_suspend_waitqueue);
+ return err;
+}
+
+static ssize_t apm_read(struct file *fp, char *buf, size_t count, loff_t *ppos)
+{
+ struct apm_user *as = fp->private_data;
+ apm_event_t event;
+ int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK;
+
+ if (count < sizeof(apm_event_t))
+ return -EINVAL;
+
+ if (queue_empty(as) && nonblock)
+ return -EAGAIN;
+
+ wait_event_interruptible(apm_waitqueue, !queue_empty(as));
+
+ while ((i >= sizeof(event)) && !queue_empty(as)) {
+ event = get_queued_event(as);
+ printk(" apm_read: event=%d\n", event);
+
+ ret = -EFAULT;
+ if (copy_to_user(buf, &event, sizeof(event)))
+ break;
+
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ as->suspends_read++;
+ break;
+
+ case APM_SYS_STANDBY:
+ case APM_USER_STANDBY:
+ as->standbys_read++;
+ break;
+ }
+
+ buf += sizeof(event);
+ i -= sizeof(event);
+ }
+
+ if (i < count)
+ ret = count - i;
+
+ return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+ struct apm_user * as = fp->private_data;
+
+ poll_wait(fp, &apm_waitqueue, wait);
+ return queue_empty(as) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ * This IOCTL is overloaded, and performs two functions. It is used to:
+ * - initiate a suspend
+ * - acknowledge a suspend read from /dev/apm_bios.
+ * Only when everyone who has opened /dev/apm_bios with write permission
+ * has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+ struct apm_user *as = filp->private_data;
+ int err = -EINVAL;
+
+ if (!as->suser || !as->writer)
+ return -EPERM;
+
+ switch (cmd) {
+ case APM_IOC_STANDBY:
+ break;
+
+ case APM_IOC_SUSPEND:
+ /*
+ * If we read a suspend command from /dev/apm_bios,
+ * then the corresponding APM_IOC_SUSPEND ioctl is
+ * interpreted as an acknowledge.
+ */
+ if (as->suspends_read > 0) {
+ as->suspends_read--;
+ as->suspends_pending--;
+ suspends_pending--;
+ } else {
+ queue_event(APM_USER_SUSPEND, as);
+ }
+
+ /*
+ * If there are outstanding suspend requests for other
+ * people on /dev/apm_bios, we must sleep for them.
+ * Last one to bed turns the lights out.
+ */
+ if (suspends_pending > 0) {
+ as->suspend_wait = 1;
+ err = wait_event_interruptible(apm_suspend_waitqueue,
+ as->suspend_wait == 0);
+ if (err == 0)
+ err = as->suspend_result;
+ } else {
+ err = apm_suspend();
+ }
+ break;
+ }
+
+ return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+ struct apm_user *as = filp->private_data;
+ filp->private_data = NULL;
+
+ spin_lock(&user_list_lock);
+ list_del(&as->list);
+ spin_unlock(&user_list_lock);
+
+ /*
+ * We are now unhooked from the chain. As far as new
+ * events are concerned, we no longer exist. However, we
+ * need to balance standbys_pending and suspends_pending,
+ * which means the possibility of sleeping.
+ */
+ if (as->standbys_pending > 0) {
+ standbys_pending -= as->standbys_pending;
+// if (standbys_pending <= 0)
+// standby();
+ }
+ if (as->suspends_pending > 0) {
+ suspends_pending -= as->suspends_pending;
+ if (suspends_pending <= 0)
+ apm_suspend();
+ }
+
+ kfree(as);
+ return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+ struct apm_user *as;
+
+ as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
+ if (as) {
+ memset(as, 0, sizeof(*as));
+
+ /*
+ * XXX - this is a tiny bit broken, when we consider BSD
+ * process accounting. If the device is opened by root, we
+ * instantly flag that we used superuser privs. Who knows,
+ * we might close the device immediately without doing a
+ * privileged operation -- cevans
+ */
+ as->suser = capable(CAP_SYS_ADMIN);
+ as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+ as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+ spin_lock(&user_list_lock);
+ list_add(&as->list, &apm_user_list);
+ spin_unlock(&user_list_lock);
+
+ filp->private_data = as;
+ }
+
+ return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+ owner: THIS_MODULE,
+ read: apm_read,
+ poll: apm_poll,
+ ioctl: apm_ioctl,
+ open: apm_open,
+ release: apm_release,
+};
+
+static struct miscdevice apm_device = {
+ minor: APM_MINOR_DEV,
+ name: "apm_bios",
+ fops: &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ * 0) Linux driver version (this will change if format changes)
+ * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2.
+ * 2) APM flags from APM Installation Check (0x00):
+ * bit 0: APM_16_BIT_SUPPORT
+ * bit 1: APM_32_BIT_SUPPORT
+ * bit 2: APM_IDLE_SLOWS_CLOCK
+ * bit 3: APM_BIOS_DISABLED
+ * bit 4: APM_BIOS_DISENGAGED
+ * 3) AC line status
+ * 0x00: Off-line
+ * 0x01: On-line
+ * 0x02: On backup power (BIOS >= 1.1 only)
+ * 0xff: Unknown
+ * 4) Battery status
+ * 0x00: High
+ * 0x01: Low
+ * 0x02: Critical
+ * 0x03: Charging
+ * 0x04: Selected battery not present (BIOS >= 1.2 only)
+ * 0xff: Unknown
+ * 5) Battery flag
+ * bit 0: High
+ * bit 1: Low
+ * bit 2: Critical
+ * bit 3: Charging
+ * bit 7: No system battery
+ * 0xff: Unknown
+ * 6) Remaining battery life (percentage of charge):
+ * 0-100: valid
+ * -1: Unknown
+ * 7) Remaining battery life (time units):
+ * Number of remaining minutes or seconds
+ * -1: Unknown
+ * 8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+ struct apm_power_info info;
+ char *units;
+ int ret;
+
+ info.ac_line_status = 0xff;
+ info.battery_status = 0xff;
+ info.battery_flag = 0xff;
+ info.battery_life = 255;
+ info.time = -1;
+ info.units = -1;
+
+ if (apm_get_power_status)
+ apm_get_power_status(&info);
+
+ switch (info.units) {
+ default: units = "?"; break;
+ case 0: units = "min"; break;
+ case 1: units = "sec"; break;
+ }
+
+ ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+ driver_version, APM_32_BIT_SUPPORT,
+ info.ac_line_status, info.battery_status,
+ info.battery_flag, info.battery_life,
+ info.time, units);
+
+ return ret;
+}
+#endif
+
+#if 0
+static int kapmd(void *startup)
+{
+ struct task_struct *tsk = current;
+
+ daemonize();
+ strcpy(tsk->comm, "kapmd");
+ kapmd = tsk;
+
+ spin_lock_irq(&tsk->sigmask_lock);
+ siginitsetinv(&tsk->blocked, sigmask(SIGQUIT));
+ recalc_sigpending(tsk);
+ spin_unlock_irq(&tsk->sigmask_lock);
+
+ complete((struct completion *)startup);
+
+ do {
+ set_task_state(tsk, TASK_INTERRUPTIBLE);
+ schedule();
+ } while (!signal_pending(tsk));
+
+ complete_and_exit(&kapmd_exit, 0);
+}
+#endif
+
+static int __init apm_init(void)
+{
+// struct completion startup = COMPLETION_INITIALIZER(startup);
+ int ret;
+
+ if (apm_disabled) {
+ printk(KERN_NOTICE "apm: disabled on user request.\n");
+ return -ENODEV;
+ }
+
+ if (PM_IS_ACTIVE()) {
+ printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+ return -EINVAL;
+ }
+
+// ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES);
+// if (ret)
+// return ret;
+// wait_for_completion(&startup);
+
+ pm_active = 1;
+
+#ifdef CONFIG_PROC_FS
+ create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+ ret = misc_register(&apm_device);
+ if (ret != 0) {
+ pm_active = 0;
+ remove_proc_entry("apm", NULL);
+ send_sig(SIGQUIT, kapmd, 1);
+ wait_for_completion(&kapmd_exit);
+ }
+
+ return ret;
+}
+
+static void __exit apm_exit(void)
+{
+ misc_deregister(&apm_device);
+ remove_proc_entry("apm", NULL);
+ pm_active = 0;
+// send_sig(SIGQUIT, kapmd, 1);
+// wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+EXPORT_NO_SYMBOLS;
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+ while ((str != NULL) && (*str != '\0')) {
+ if (strncmp(str, "off", 3) == 0)
+ apm_disabled = 1;
+ if (strncmp(str, "on", 2) == 0)
+ apm_disabled = 0;
+ str = strchr(str, ',');
+ if (str != NULL)
+ str += strspn(str, ", \t");
+ }
+ return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
--- a/arch/arm/kernel/bios32.c Mon Mar 17 13:45:12 2003
+++ b/arch/arm/kernel/bios32.c Mon Mar 17 13:45:12 2003
@@ -18,7 +18,6 @@
#include
static int debug_pci;
-int have_isa_bridge;
void pcibios_report_status(u_int status_mask, int warn)
{
@@ -260,47 +259,6 @@
}, { 0 }
};
-void __devinit
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- struct pci_sys_data *sys = dev->sysdata;
- u32 val, check;
- int reg;
-
- if (debug_pci)
- printk("PCI: Assigning %3s %08lx to %s\n",
- res->flags & IORESOURCE_IO ? "IO" : "MEM",
- res->start, dev->dev.name);
-
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a
- * non-standard resource.
- */
- return;
- }
-
- val = res->start;
- if (res->flags & IORESOURCE_MEM)
- val -= sys->mem_offset;
- else
- val -= sys->io_offset;
- val |= res->flags & PCI_REGION_FLAG_MASK;
-
- pci_write_config_dword(dev, reg, val);
- pci_read_config_dword(dev, reg, &check);
- if ((val ^ check) & ((val & PCI_BASE_ADDRESS_SPACE_IO) ?
- PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name,
- resource, val, check);
- }
-}
-
void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
{
if (debug_pci)
@@ -363,9 +321,8 @@
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{
struct pci_sys_data *root = bus->sysdata;
- struct list_head *walk;
- u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
- u16 all_status = -1;
+ struct pci_dev *dev;
+ u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
pbus_assign_bus_resources(bus, root);
@@ -373,42 +330,43 @@
* Walk the devices on this bus, working out what we can
* and can't support.
*/
- for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) {
- struct pci_dev *dev = pci_dev_b(walk);
+ list_for_each_entry(dev, &bus->devices, bus_list) {
u16 status;
pdev_fixup_device_resources(root, dev);
pci_read_config_word(dev, PCI_STATUS, &status);
- all_status &= status;
+
+ /*
+ * If any device on this bus does not support fast back
+ * to back transfers, then the bus as a whole is not able
+ * to support them. Having fast back to back transfers
+ * on saves us one PCI cycle per transaction.
+ */
+ if (!(status & PCI_STATUS_FAST_BACK))
+ features &= ~PCI_COMMAND_FAST_BACK;
if (pdev_bad_for_parity(dev))
features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
- /*
- * If this device is an ISA bridge, set the have_isa_bridge
- * flag. We will then go looking for things like keyboard,
- * etc
- */
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
- dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
- have_isa_bridge = !0;
+ switch (dev->class >> 8) {
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+ case PCI_CLASS_BRIDGE_ISA:
+ case PCI_CLASS_BRIDGE_EISA:
+ /*
+ * If this device is an ISA bridge, set isa_bridge
+ * to point at this device. We will then go looking
+ * for things like keyboard, etc.
+ */
+ isa_bridge = dev;
+ break;
+#endif
}
/*
- * If any device on this bus does not support fast back to back
- * transfers, then the bus as a whole is not able to support them.
- * Having fast back to back transfers on saves us one PCI cycle
- * per transaction.
- */
- if (all_status & PCI_STATUS_FAST_BACK)
- features |= PCI_COMMAND_FAST_BACK;
-
- /*
* Now walk the devices again, this time setting them up.
*/
- for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) {
- struct pci_dev *dev = pci_dev_b(walk);
+ list_for_each_entry(dev, &bus->devices, bus_list) {
u16 cmd;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -416,7 +374,17 @@
pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
- SMP_CACHE_BYTES >> 2);
+ L1_CACHE_BYTES >> 2);
+ }
+
+ /*
+ * Propagate the flags to the PCI bridge.
+ */
+ if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ if (features & PCI_COMMAND_FAST_BACK)
+ bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+ if (features & PCI_COMMAND_PARITY)
+ bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
}
/*
@@ -430,18 +398,26 @@
* Convert from Linux-centric to bus-centric addresses for bridge devices.
*/
void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
{
- struct pci_sys_data *root = bus->sysdata;
+ struct pci_sys_data *root = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = root->io_offset;
+ if (res->flags & IORESOURCE_MEM)
+ offset = root->mem_offset;
- ranges->io_start -= root->io_offset;
- ranges->io_end -= root->io_offset;
- ranges->mem_start -= root->mem_offset;
- ranges->mem_end -= root->mem_offset;
- ranges->prefetch_start -= root->mem_offset;
- ranges->prefetch_end -= root->mem_offset;
+ region->start = res->start - offset;
+ region->end = res->end - offset;
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
/*
* This is the standard PCI-PCI bridge swizzling algorithm:
*
@@ -454,20 +430,17 @@
*/
u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp)
{
- int pin = *pinp;
+ int pin = *pinp - 1;
- if (pin != 0) {
- pin -= 1;
- while (dev->bus->self) {
- pin = (pin + PCI_SLOT(dev->devfn)) & 3;
- /*
- * move up the chain of bridges,
- * swizzling as we go.
- */
- dev = dev->bus->self;
- }
- *pinp = pin + 1;
+ while (dev->bus->self) {
+ pin = (pin + PCI_SLOT(dev->devfn)) & 3;
+ /*
+ * move up the chain of bridges,
+ * swizzling as we go.
+ */
+ dev = dev->bus->self;
}
+ *pinp = pin + 1;
return PCI_SLOT(dev->devfn);
}
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c Mon Mar 17 13:45:14 2003
+++ b/arch/arm/kernel/ecard.c Mon Mar 17 13:45:14 2003
@@ -37,7 +37,6 @@
#include
#include
#include
-#include
#include
#include
@@ -57,7 +56,7 @@
enum req {
req_readbytes,
- req_reset_all
+ req_reset
};
struct ecard_request {
@@ -131,14 +130,11 @@
#define POD_INT_ADDR(x) ((volatile unsigned char *)\
((BUS_ADDR((x)) - IO_BASE) + IO_START))
-static inline void ecard_task_reset(void)
+static inline void ecard_task_reset(struct ecard_request *req)
{
- ecard_t *ec;
-
- for (ec = cards; ec; ec = ec->next)
- if (ec->loader)
- ecard_loader_reset(POD_INT_ADDR(ec->podaddr),
- ec->loader);
+ struct expansion_card *ec = req->ec;
+ if (ec->loader)
+ ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
}
static void
@@ -218,8 +214,8 @@
ecard_task_readbytes(req);
break;
- case req_reset_all:
- ecard_task_reset();
+ case req_reset:
+ ecard_task_reset(req);
break;
}
}
@@ -355,60 +351,6 @@
/* ======================= Mid-level card control ===================== */
-/*
- * This function is responsible for resetting the expansion cards to a
- * sensible state immediately prior to rebooting the system. This function
- * has process state (keventd), so we can sleep.
- *
- * Possible "val" values here:
- * SYS_RESTART - restarting system
- * SYS_HALT - halting system
- * SYS_POWER_OFF - powering down system
- *
- * We ignore all calls, unless it is a SYS_RESTART call - power down/halts
- * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again.
- */
-static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
-{
- struct ecard_request req;
-
- if (val != SYS_RESTART)
- return 0;
-
- /*
- * Disable the expansion card interrupt
- */
- disable_irq(IRQ_EXPANSIONCARD);
-
- /*
- * If we have any expansion card loader code which will handle
- * the reset for us, call it now.
- */
- req.req = req_reset_all;
- ecard_call(&req);
-
- /*
- * Disable the expansion card interrupt again, just to be sure.
- */
- disable_irq(IRQ_EXPANSIONCARD);
-
- /*
- * Finally, reset the expansion card interrupt mask to
- * all enable (RISC OS doesn't set this)
- */
-#ifdef HAS_EXPMASK
- have_expmask = ~0;
- __raw_writeb(have_expmask, EXPMASK_ENABLE);
-#endif
- return 0;
-}
-
-static struct notifier_block ecard_reboot_notifier = {
- .notifier_call = ecard_reboot,
-};
-
-
-
static void
ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
{
@@ -1083,11 +1025,6 @@
{
int slot, irqhw;
- /*
- * Register our reboot notifier
- */
- register_reboot_notifier(&ecard_reboot_notifier);
-
#ifdef CONFIG_CPU_32
init_waitqueue_head(&ecard_wait);
#endif
@@ -1158,11 +1095,32 @@
return 0;
}
+/*
+ * Before rebooting, we must make sure that the expansion card is in a
+ * sensible state, so it can be re-detected. This means that the first
+ * page of the ROM must be visible. We call the expansion cards reset
+ * handler, if any.
+ */
+static void ecard_drv_shutdown(struct device *dev)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ struct ecard_driver *drv = ECARD_DRV(dev->driver);
+ struct ecard_request req;
+
+ if (drv->shutdown)
+ drv->shutdown(ec);
+ ecard_release(ec);
+ req.req = req_reset;
+ req.ec = ec;
+ ecard_call(&req);
+}
+
int ecard_register_driver(struct ecard_driver *drv)
{
drv->drv.bus = &ecard_bus_type;
drv->drv.probe = ecard_drv_probe;
drv->drv.remove = ecard_drv_remove;
+ drv->drv.shutdown = ecard_drv_shutdown;
return driver_register(&drv->drv);
}
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S Mon Mar 17 13:45:11 2003
+++ b/arch/arm/kernel/entry-armv.S Mon Mar 17 13:45:11 2003
@@ -1028,8 +1028,10 @@
@
@ now branch to the relevant MODE handling routine
@
- mov r13, #PSR_I_BIT | MODE_SVC
- msr spsr_c, r13 @ switch to SVC_32 mode
+ mrs r13, cpsr
+ bic r13, r13, #MODE_MASK
+ orr r13, r13, #MODE_SVC
+ msr spsr, r13 @ switch to SVC_32 mode
and lr, lr, #15
ldr lr, [pc, lr, lsl #2]
diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
--- a/arch/arm/kernel/entry-common.S Mon Mar 17 13:45:09 2003
+++ b/arch/arm/kernel/entry-common.S Mon Mar 17 13:45:09 2003
@@ -75,9 +75,8 @@
* This is how we return from a fork.
*/
ENTRY(ret_from_fork)
-#ifdef CONFIG_PREEMPT
+ ldr r0, [r0, #TI_TASK]
bl schedule_tail
-#endif
get_thread_info tsk
ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
mov why, #1
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c Mon Mar 17 13:45:08 2003
+++ b/arch/arm/kernel/irq.c Mon Mar 17 13:45:08 2003
@@ -165,17 +165,22 @@
{
int i;
struct irqaction * action;
+ unsigned long flags;
for (i = 0 ; i < NR_IRQS ; i++) {
+ spin_lock_irqsave(&irq_controller_lock, flags);
action = irq_desc[i].action;
if (!action)
- continue;
+ goto unlock;
+
seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
seq_printf(p, " %s", action->name);
- for (action = action->next; action; action = action->next) {
+ for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
- }
+
seq_putc(p, '\n');
+unlock:
+ spin_unlock_irqrestore(&irq_controller_lock, flags);
}
#ifdef CONFIG_ARCH_ACORN
diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/arm/kernel/pm.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/arm/kernel/suspend.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ *
+ * This is the common support code for suspending an ARM machine.
+ * pm_do_suspend() is responsible for actually putting the CPU to
+ * sleep.
+ */
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+int suspend(void)
+{
+ int ret;
+
+ /*
+ * Suspend "legacy" devices.
+ */
+ ret = pm_send_all(PM_SUSPEND, (void *)3);
+ if (ret != 0)
+ goto out;
+
+ /*
+ * Tell LDM devices we're going to suspend.
+ */
+ ret = device_suspend(4, SUSPEND_NOTIFY);
+ if (ret != 0)
+ goto resume_legacy;
+
+ /*
+ * Disable, devices, and save state.
+ */
+ device_suspend(4, SUSPEND_DISABLE);
+ device_suspend(4, SUSPEND_SAVE_STATE);
+
+ /*
+ * Tell devices that they're going to be powered off.
+ */
+ device_suspend(4, SUSPEND_POWER_DOWN);
+
+ local_irq_disable();
+ leds_event(led_stop);
+
+ ret = pm_do_suspend();
+
+ leds_event(led_start);
+ local_irq_enable();
+
+ /*
+ * Tell devices that they now have power.
+ */
+ device_resume(RESUME_POWER_ON);
+
+ /*
+ * Restore the CPU frequency settings.
+ */
+#ifdef CONFIG_CPU_FREQ
+ cpufreq_restore();
+#endif
+
+ /*
+ * Resume LDM devices.
+ */
+ device_resume(RESUME_RESTORE_STATE);
+ device_resume(RESUME_ENABLE);
+
+ resume_legacy:
+ /*
+ * Resume "legacy" devices.
+ */
+ pm_send_all(PM_RESUME, (void *)0);
+
+ out:
+ return ret;
+}
+
+#ifdef CONFIG_SYSCTL
+#include
+#include
+
+/*
+ * This came from arch/arm/mach-sa1100/pm.c:
+ * Copyright (c) 2001 Cliff Brake
+ * with modifications by Nicolas Pitre and Russell King.
+ *
+ * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
+ * linux/sysctl.h.
+ *
+ * This means our interface here won't survive long - it needs a new
+ * interface. Quick hack to get this working - use sysctl id 9999.
+ */
+#warning ACPI broke the kernel, this interface needs to be fixed up.
+#define CTL_ACPI 9999
+#define ACPI_S1_SLP_TYP 19
+
+static struct ctl_table pm_table[] =
+{
+ {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend},
+ {0}
+};
+
+static struct ctl_table pm_dir_table[] =
+{
+ {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
+ {0}
+};
+
+/*
+ * Initialize power interface
+ */
+static int __init pm_init(void)
+{
+ register_sysctl_table(pm_dir_table, 1);
+ return 0;
+}
+
+fs_initcall(pm_init);
+
+#endif
diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
--- a/arch/arm/kernel/time.c Mon Mar 17 13:45:14 2003
+++ b/arch/arm/kernel/time.c Mon Mar 17 13:45:14 2003
@@ -200,6 +200,7 @@
static struct irqaction timer_irq = {
.name = "timer",
+ .flags = SA_INTERRUPT,
};
/*
diff -Nru a/arch/arm/mach-arc/Makefile b/arch/arm/mach-arc/Makefile
--- a/arch/arm/mach-arc/Makefile Mon Mar 17 13:45:09 2003
+++ b/arch/arm/mach-arc/Makefile Mon Mar 17 13:45:09 2003
@@ -6,12 +6,9 @@
obj-y := arch.o dma.o fault.o irq.o mm.o oldlatches.o \
small_page.o
-obj-m :=
-obj-n :=
-obj- :=
obj-$(CONFIG_DEBUG_LL) += debug.o
-EXTRA_TARGETS := head.o
+extra-y := head.o
AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR)
diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
--- a/arch/arm/mach-integrator/Makefile Mon Mar 17 13:45:14 2003
+++ b/arch/arm/mach-integrator/Makefile Mon Mar 17 13:45:14 2003
@@ -4,10 +4,11 @@
# Object file lists.
-obj-y := arch.o cpu.o irq.o mm.o time.o
+obj-y := arch.o irq.o mm.o time.o
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o
+obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
--- a/arch/arm/mach-integrator/cpu.c Mon Mar 17 13:45:12 2003
+++ b/arch/arm/mach-integrator/cpu.c Mon Mar 17 13:45:12 2003
@@ -23,6 +23,8 @@
#include
#include
+static struct cpufreq_driver integrator_driver;
+
#define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET)
#define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET)
#define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET)
@@ -43,7 +45,6 @@
return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor;
}
-#ifdef CONFIG_CPU_FREQ
/*
* Divisor indexes in ascending divisor order
*/
@@ -69,21 +70,17 @@
return vco;
}
+
/*
- * Validate the speed in khz. If it is outside our
- * range, then return the lowest.
+ * Validate the speed policy.
*/
-static int integrator_verify_speed(struct cpufreq_policy *policy)
+static int integrator_verify_policy(struct cpufreq_policy *policy)
{
struct vco vco;
- if (policy->max > policy->cpuinfo.max_freq)
- policy->max = policy->cpuinfo.max_freq;
-
- if (policy->max < 12000)
- policy->max = 12000;
- if (policy->max > 160000)
- policy->max = 160000;
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
vco = freq_to_vco(policy->max, 1);
@@ -92,12 +89,28 @@
if (vco.vdw > 152)
vco.vdw = 152;
- policy->min = policy->max = vco_to_freq(vco, 1);
+ policy->max = vco_to_freq(vco, 1);
+
+ vco = freq_to_vco(policy->min, 1);
+
+ if (vco.vdw < 4)
+ vco.vdw = 4;
+ if (vco.vdw > 152)
+ vco.vdw = 152;
+
+ policy->min = vco_to_freq(vco, 1);
+
+ cpufreq_verify_within_limits(policy,
+ policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
return 0;
}
-static int integrator_set_policy(struct cpufreq_policy *policy)
+
+static int integrator_set_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
unsigned long cpus_allowed;
int cpu = policy->cpu;
@@ -121,9 +134,18 @@
cm_osc = __raw_readl(CM_OSC);
vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
-
freqs.old = vco_to_freq(vco, 1);
- freqs.new = target_freq;
+
+ /* freq_to_vco rounds down -- so we need the next larger freq in
+ * case of CPUFREQ_RELATION_L.
+ */
+ if (relation == CPUFREQ_RELATION_L)
+ target_freq += 1999;
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+ vco = freq_to_vco(target_freq, 1);
+ freqs.new = vco_to_freq(vco, 1);
+
freqs.cpu = policy->cpu;
if (freqs.old == freqs.new) {
@@ -132,7 +154,6 @@
}
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- vco = freq_to_vco(policy->max, 1);
cm_osc = __raw_readl(CM_OSC);
cm_osc &= 0xfffff800;
@@ -152,80 +173,64 @@
return 0;
}
-static struct cpufreq_policy integrator_policy = {
- .cpu = 0,
- .policy = CPUFREQ_POLICY_POWERSAVE,
- .cpuinfo = {
- .max_freq = 160000,
- .min_freq = 12000,
- .transition_latency = CPUFREQ_ETERNAL,
- },
-};
+static int integrator_cpufreq_init(struct cpufreq *policy)
+{
+ unsigned long cus_allowed;
+ unsigned int cpu = policy->cpu;
+ u_int cm_osc, cm_stat, mem_freq_khz;
+ struct vco vco;
-static struct cpufreq_driver integrator_driver = {
- .verify = integrator_verify_speed,
- .setpolicy = integrator_set_policy,
- .policy = &integrator_policy,
- .name = "integrator",
-};
-#endif
+ cpus_allowed = current->cpus_allowed;
-static int __init integrator_cpu_init(void)
-{
- struct cpufreq_policy *policies;
- unsigned long cpus_allowed;
- int cpu;
+ set_cpus_allowed(current, 1 << cpu);
+ BUG_ON(cpu != smp_processor_id());
- policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS,
- GFP_KERNEL);
- if (!policies) {
- printk(KERN_ERR "CPU: unable to allocate policies structure\n");
- return -ENOMEM;
- }
+ /* detect memory etc. */
+ cm_stat = __raw_readl(CM_STAT);
+ cm_osc = __raw_readl(CM_OSC);
+ vco.od = (cm_osc >> 20) & 7;
+ vco.vdw = (cm_osc >> 12) & 255;
+ mem_freq_khz = vco_to_freq(vco, 2);
+
+ printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
+ printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
+ cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
- cpus_allowed = current->cpus_allowed;
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- u_int cm_osc, cm_stat, mem_freq_khz;
- struct vco vco;
-
- if (!cpu_online(cpu))
- continue;
-
- set_cpus_allowed(current, 1 << cpu);
- BUG_ON(cpu != smp_processor_id());
-
- cm_stat = __raw_readl(CM_STAT);
- cm_osc = __raw_readl(CM_OSC);
- vco.od = (cm_osc >> 20) & 7;
- vco.vdw = (cm_osc >> 12) & 255;
- mem_freq_khz = vco_to_freq(vco, 2);
-
- printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
- printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
- cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
-
- vco.od = (cm_osc >> 8) & 7;
- vco.vdw = cm_osc & 255;
-
- policies[cpu].cpu = cpu;
- policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
- policies[cpu].cpuinfo.max_freq = 160000;
- policies[cpu].cpuinfo.min_freq = 12000;
- policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
- policies[cpu].min =
- policies[cpu].max = vco_to_freq(vco, 1);
- }
+ vco.od = (cm_osc >> 8) & 7;
+ vco.vdw = cm_osc & 255;
- set_cpus_allowed(current, cpus_allowed);
+ /* set default policy and cpuinfo */
+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+ policy->cpuinfo.max_freq = 160000;
+ policy->cpuinfo.min_freq = 12000;
+ policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */
+ policy->cur = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */
-#ifdef CONFIG_CPU_FREQ
- integrator_driver.policy = policies;
- cpufreq_register(&integrator_driver);
-#else
- kfree(policies);
-#endif
+ set_cpus_allowed(current, cpus_allowed);
return 0;
}
-arch_initcall(integrator_cpu_init);
+static struct cpufreq_driver integrator_driver = {
+ .verify = integrator_verify_policy,
+ .target = integrator_set_target,
+ .init = integrator_cpufreq_init,
+ .name = "integrator",
+};
+
+static int __init integrator_cpu_init(void)
+{
+ return cpufreq_register_driver(&integrator_driver);
+}
+
+static void __exit integrator_cpu_exit(void)
+{
+ cpufreq_unregister_driver(&integrator_driver);
+}
+
+MODULE_AUTHOR ("Russell M. King");
+MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
+MODULE_LICENSE ("GPL");
+
+module_init(integrator_cpu_init);
+module_exit(integrator_cpu_exit);
diff -Nru a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
--- a/arch/arm/mach-sa1100/Kconfig Mon Mar 17 13:45:16 2003
+++ b/arch/arm/mach-sa1100/Kconfig Mon Mar 17 13:45:16 2003
@@ -326,6 +326,15 @@
# help
# :: write me ::
+config SA1100_SSP
+ tristate "Generic PIO SSP"
+ depends on ARCH_SA1100
+ help
+ Say Y here to enable support for the generic PIO SSP driver.
+ This isn't for audio support, but for attached sensors and
+ other devices, eg for BadgePAD 4 sensor support, or Jornada
+ 720 touchscreen support.
+
config SA1100_USB
tristate "SA1100 USB function support"
depends on ARCH_SA1100
diff -Nru a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
--- a/arch/arm/mach-sa1100/Makefile Mon Mar 17 13:45:16 2003
+++ b/arch/arm/mach-sa1100/Makefile Mon Mar 17 13:45:16 2003
@@ -9,15 +9,8 @@
obj- :=
led-y := leds.o
-# This needs to be cleaned up. We probably need to have SA1100
-# and SA1110 config symbols.
-ifeq ($(CONFIG_CPU_FREQ),y)
-obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
-obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
-obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o
-obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o
-obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o
-endif
+obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o
+obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o
# Specific board support
obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o
@@ -99,3 +92,4 @@
# Miscelaneous functions
obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_SA1100_SSP) += ssp.o
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
--- a/arch/arm/mach-sa1100/cpu-sa1100.c Mon Mar 17 13:45:09 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c Mon Mar 17 13:45:09 2003
@@ -101,7 +101,7 @@
} sa1100_dram_regs_t;
-
+static struct cpufreq_driver sa1100_driver;
static sa1100_dram_regs_t sa1100_dram_settings[] =
{
@@ -176,60 +176,73 @@
}
}
-static int sa1100_setspeed(struct cpufreq_policy *policy)
+static int sa1100_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
unsigned int cur = sa11x0_getspeed();
+ unsigned int new_ppcr;
+
struct cpufreq_freqs freqs;
+ switch(relation){
+ case CPUFREQ_RELATION_L:
+ new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
+ new_ppcr--;
+ break;
+ case CPUFREQ_RELATION_H:
+ new_ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
+ (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
+ mew_ppcr--;
+ break;
+ }
freqs.old = cur;
- freqs.new = policy->max;
+ freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
freqs.cpu = 0;
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- if (policy->max > cur)
- sa1100_update_dram_timings(cur, policy->max);
+ if (freqs.new > cur)
+ sa1100_update_dram_timings(cur, freqs.new);
- PPCR = sa11x0_freq_to_ppcr(policy->max);
+ PPCR = new_ppcr;
- if (policy->max < cur)
- sa1100_update_dram_timings(cur, policy->max);
+ if (freqs.new < cur)
+ sa1100_update_dram_timings(cur, freqs.new);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0;
}
-static struct cpufreq_policy sa1100_policy = {
- .cpu = 0,
- .policy = CPUFREQ_POLICY_POWERSAVE,
- .cpuinfo = {
- .max_freq = 287000,
- .min_freq = 59000,
- .transition_latency = CPUFREQ_ETERNAL,
- },
-};
+static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+ policy->cur = policy->min = policy->max = sa11x0_getspeed();
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ policy->cpuinfo.min_freq = 59000;
+ policy->cpuinfo.max_freq = 287000;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ return 0;
+}
static struct cpufreq_driver sa1100_driver = {
.verify = sa11x0_verify_speed,
- .setpolicy = sa1100_setspeed,
- .policy = &sa1100_policy,
+ .target = sa1100_target,
+ .init = sa1100_cpu_init,
.name = "sa1100",
};
static int __init sa1100_dram_init(void)
{
- int ret = -ENODEV;
-
- if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
- sa1100_driver.cpu_cur_freq[0] =
- sa1100_policy.min =
- sa1100_policy.max = sa11x0_getspeed();
-
- ret = cpufreq_register(&sa1100_driver);
- }
-
- return ret;
+ cpufreq_gov_userspace_init();
+ if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID)
+ return cpufreq_register_driver(&sa1100_driver);
+ else
+ return -ENODEV;
}
arch_initcall(sa1100_dram_init);
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c Mon Mar 17 13:45:09 2003
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c Mon Mar 17 13:45:09 2003
@@ -32,6 +32,8 @@
#undef DEBUG
+static struct cpufreq_driver sa1110_driver;
+
struct sdram_params {
u_char rows; /* bits */
u_char cas_latency; /* cycles */
@@ -208,11 +210,11 @@
}
/*
- * Ok, set the CPU frequency. Since we've done the validation
- * above, we can match for an exact frequency. If we don't find
- * an exact match, we will to set the lowest frequency to be safe.
+ * Ok, set the CPU frequency.
*/
-static int sa1110_setspeed(struct cpufreq_policy *policy)
+static int sa1110_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
{
struct sdram_params *sdram = &sdram_params;
struct cpufreq_freqs freqs;
@@ -220,8 +222,25 @@
unsigned long flags;
unsigned int ppcr, unused;
- ppcr = sa11x0_freq_to_ppcr(policy->max);
- sdram_calculate_timing(&sd, policy->max, sdram);
+ switch(relation){
+ case CPUFREQ_RELATION_L:
+ ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
+ ppcr--;
+ break;
+ case CPUFREQ_RELATION_H:
+ ppcr = sa11x0_freq_to_ppcr(target_freq);
+ if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
+ (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
+ ppcr--;
+ break;
+ }
+
+ freqs.old = sa11x0_getspeed();
+ freqs.new = sa11x0_ppcr_to_freq(ppcr);
+ freqs.cpu = 0;
+
+ sdram_calculate_timing(&sd, freqs.new, sdram);
#if 0
/*
@@ -240,10 +259,6 @@
sd.mdcas[2] = 0xaaaaaaaa;
#endif
- freqs.old = sa11x0_getspeed();
- freqs.new = policy->max;
- freqs.cpu = 0;
-
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
/*
@@ -288,27 +303,29 @@
/*
* Now, return the SDRAM refresh back to normal.
*/
- sdram_update_refresh(policy->max, sdram);
+ sdram_update_refresh(freqs.new, sdram);
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return 0;
}
-static struct cpufreq_policy sa1110_policy = {
- .cpu = 0,
- .policy = CPUFREQ_POLICY_POWERSAVE,
- .cpuinfo = {
- .max_freq = 287000,
- .min_freq = 59000,
- .transition_latency = CPUFREQ_ETERNAL,
- },
-};
+static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
+{
+ if (policy->cpu != 0)
+ return -EINVAL;
+ policy->cur = policy->min = policy->max = sa11x0_getspeed();
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ policy->cpuinfo.min_freq = 59000;
+ policy->cpuinfo.max_freq = 287000;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ return 0;
+}
static struct cpufreq_driver sa1110_driver = {
- .verify = sa11x0_verify_speed,
- .setpolicy = sa1110_setspeed,
- .policy = &sa1110_policy,
+ .verify = sa11x0_verify_speed,
+ .target = sa1110_target,
+ .init = sa1110_cpu_init,
.name = "sa1110",
};
@@ -331,15 +348,11 @@
sdram->tck, sdram->trcd, sdram->trp,
sdram->twr, sdram->refresh, sdram->cas_latency);
+ cpufreq_gov_userspace_init();
+
memcpy(&sdram_params, sdram, sizeof(sdram_params));
- sa1110_driver.cpu_cur_freq[0] =
- sa1110_policy.min =
- sa1110_policy.max = sa11x0_getspeed();
-
- sa1110_setspeed(&sa1110_policy);
-
- return cpufreq_register(&sa1110_driver);
+ return cpufreq_register_driver(&sa1110_driver);
}
return 0;
diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
--- a/arch/arm/mach-sa1100/generic.c Mon Mar 17 13:45:10 2003
+++ b/arch/arm/mach-sa1100/generic.c Mon Mar 17 13:45:10 2003
@@ -48,33 +48,48 @@
2802 /* 280.2 MHz */
};
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110)
+/* rounds up(!) */
unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
{
int i;
khz /= 100;
- for (i = NR_FREQS - 1; i > 0; i--)
- if (cclk_frequency_100khz[i] <= khz)
+ for (i = 0; i < NR_FREQS; i++)
+ if (cclk_frequency_100khz[i] >= khz)
break;
return i;
}
-/*
- * Validate the policy. We aren't able to do any fancy in-kernel
- * scaling, so we force min=max, and set the policy to "performance".
- * If we can't generate the precise frequency requested, round it up.
+unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
+{
+ unsigned int freq = 0;
+ if (idx < NR_FREQS)
+ freq = cclk_frequency_100khz[idx] * 100;
+ return freq;
+}
+
+
+/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
+ * this platform, anyway.
*/
int sa11x0_verify_speed(struct cpufreq_policy *policy)
{
- if (policy->max > policy->cpuinfo.max_freq)
- policy->max = policy->cpuinfo.max_freq;
+ unsigned int tmp;
+ if (policy->cpu)
+ return -EINVAL;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+ /* make sure that at least one frequency is within the policy */
+ tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
+ if (tmp > policy->max)
+ policy->max = tmp;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
- policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100;
- policy->min = policy->max;
- policy->policy = CPUFREQ_POLICY_POWERSAVE;
return 0;
}
diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
--- a/arch/arm/mach-sa1100/generic.h Mon Mar 17 13:45:13 2003
+++ b/arch/arm/mach-sa1100/generic.h Mon Mar 17 13:45:13 2003
@@ -23,3 +23,4 @@
extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
extern unsigned int sa11x0_getspeed(void);
+extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
--- a/arch/arm/mach-sa1100/irq.c Mon Mar 17 13:45:15 2003
+++ b/arch/arm/mach-sa1100/irq.c Mon Mar 17 13:45:15 2003
@@ -211,6 +211,99 @@
.end = 0x9005ffff,
};
+struct sa1100irq_state {
+ unsigned int saved;
+ unsigned int icmr;
+ unsigned int iclr;
+ unsigned int iccr;
+};
+
+static int sa1100irq_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct sa1100irq_state *st;
+
+ if (!dev->saved_state && level == SUSPEND_NOTIFY)
+ dev->saved_state = kmalloc(sizeof(struct sa1100irq_state),
+ GFP_KERNEL);
+ if (!dev->saved_state)
+ return -ENOMEM;
+
+ if (level == SUSPEND_POWER_DOWN) {
+ st = (struct sa1100irq_state *)dev->saved_state;
+
+ st->saved = 1;
+ st->icmr = ICMR;
+ st->iclr = ICLR;
+ st->iccr = ICCR;
+
+ /*
+ * Disable all GPIO-based interrupts.
+ */
+ ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7|
+ IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2|
+ IC_GPIO1|IC_GPIO0);
+
+ /*
+ * Set the appropriate edges for wakeup.
+ */
+ GRER = PWER & GPIO_IRQ_rising_edge;
+ GFER = PWER & GPIO_IRQ_falling_edge;
+
+ /*
+ * Clear any pending GPIO interrupts.
+ */
+ GEDR = GEDR;
+ }
+ return 0;
+}
+
+static int sa1100irq_resume(struct device *dev, u32 level)
+{
+ struct sa1100irq_state *st;
+
+ if (level == RESUME_POWER_ON) {
+ st = (struct sa1100irq_state *)dev->saved_state;
+ dev->saved_state = NULL;
+
+ if (st->saved) {
+ ICCR = st->iccr;
+ ICLR = st->iclr;
+
+ GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask;
+ GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask;
+
+ ICMR = st->icmr;
+ }
+
+ kfree(st);
+ }
+ return 0;
+}
+
+static struct device_driver sa1100irq_driver = {
+ .name = "sa11x0-irq",
+ .bus = &system_bus_type,
+ .suspend = sa1100irq_suspend,
+ .resume = sa1100irq_resume,
+};
+
+static struct sys_device sa1100irq_device = {
+ .name = "irq",
+ .id = 0,
+ .dev = {
+ .name = "Intel SA11x0 [Interrupt Controller]",
+ .driver = &sa1100irq_driver,
+ },
+};
+
+static int __init sa1100irq_init_devicefs(void)
+{
+ driver_register(&sa1100irq_driver);
+ return sys_device_register(&sa1100irq_device);
+}
+
+device_initcall(sa1100irq_init_devicefs);
+
void __init sa1100_init_irq(void)
{
unsigned int irq;
diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
--- a/arch/arm/mach-sa1100/pm.c Mon Mar 17 13:45:09 2003
+++ b/arch/arm/mach-sa1100/pm.c Mon Mar 17 13:45:09 2003
@@ -22,25 +22,12 @@
* 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array.
* Storage is local on the stack now.
*/
-#include
-#include
-#include
-#include
-#include
#include
-#include
-#include
+#include
#include
#include
#include
-#include
-
-
-/*
- * Debug macros
- */
-#undef DEBUG
extern void sa1100_cpu_suspend(void);
extern void sa1100_cpu_resume(void);
@@ -58,10 +45,9 @@
SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER,
SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3,
- SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR,
+ SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR,
SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR,
- SLEEP_SAVE_ICMR,
SLEEP_SAVE_Ser1SDCR0,
SLEEP_SAVE_SIZE
@@ -72,10 +58,6 @@
{
unsigned long sleep_save[SLEEP_SAVE_SIZE];
- local_irq_disable();
-
- leds_event(led_stop);
-
/* preserve current time */
RCNR = xtime.tv_sec;
@@ -88,8 +70,6 @@
SAVE(OIER);
SAVE(GPDR);
- SAVE(GRER);
- SAVE(GFER);
SAVE(GAFR);
SAVE(PPDR);
@@ -99,13 +79,6 @@
SAVE(Ser1SDCR0);
- SAVE(ICMR);
-
- /* ... maybe a global variable initialized by arch code to set this? */
- GRER = PWER;
- GFER = 0;
- GEDR = GEDR;
-
/* Clear previous reset status */
RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
@@ -115,22 +88,23 @@
/* go zzz */
sa1100_cpu_suspend();
- /* ensure not to come back here if it wasn't intended */
+ /*
+ * Ensure not to come back here if it wasn't intended
+ */
PSPR = 0;
-#ifdef DEBUG
- printk(KERN_DEBUG "*** made it back from resume\n");
-#endif
+ /*
+ * Ensure interrupt sources are disabled; we will re-init
+ * the interrupt subsystem via the device manager.
+ */
+ ICLR = 0;
+ ICCR = 1;
+ ICMR = 0;
/* restore registers */
RESTORE(GPDR);
- RESTORE(GRER);
- RESTORE(GFER);
RESTORE(GAFR);
- /* clear any edge detect bit */
- GEDR = GEDR;
-
RESTORE(PPDR);
RESTORE(PPSR);
RESTORE(PPAR);
@@ -138,6 +112,9 @@
RESTORE(Ser1SDCR0);
+ /*
+ * Clear the peripheral sleep-hold bit.
+ */
PSSR = PSSR_PH;
RESTORE(OSMR0);
@@ -147,24 +124,9 @@
RESTORE(OSCR);
RESTORE(OIER);
- ICLR = 0;
- ICCR = 1;
- RESTORE(ICMR);
-
/* restore current time */
xtime.tv_sec = RCNR;
- leds_event(led_start);
-
- local_irq_enable();
-
- /*
- * Restore the CPU frequency settings.
- */
-#ifdef CONFIG_CPU_FREQ
- cpufreq_restore();
-#endif
-
return 0;
}
@@ -172,78 +134,3 @@
{
return virt_to_phys(sp);
}
-
-#ifdef CONFIG_SYSCTL
-/*
- * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than
- * linux/sysctl.h.
- *
- * This means our interface here won't survive long - it needs a new
- * interface. Quick hack to get this working - use sysctl id 9999.
- */
-#warning ACPI broke the kernel, this interface needs to be fixed up.
-#define CTL_ACPI 9999
-#define ACPI_S1_SLP_TYP 19
-
-/*
- * Send us to sleep.
- */
-static int sysctl_pm_do_suspend(void)
-{
- int retval;
-
- /*
- * Suspend "legacy" devices.
- */
- retval = pm_send_all(PM_SUSPEND, (void *)3);
- if (retval == 0) {
- /*
- * Suspend LDM devices.
- */
- device_suspend(4, SUSPEND_NOTIFY);
- device_suspend(4, SUSPEND_SAVE_STATE);
- device_suspend(4, SUSPEND_DISABLE);
-
- retval = pm_do_suspend();
-
- /*
- * Resume LDM devices.
- */
- device_resume(RESUME_RESTORE_STATE);
- device_resume(RESUME_ENABLE);
-
- /*
- * Resume "legacy" devices.
- */
- pm_send_all(PM_RESUME, (void *)0);
- }
-
- return retval;
-}
-
-static struct ctl_table pm_table[] =
-{
- {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend},
- {0}
-};
-
-static struct ctl_table pm_dir_table[] =
-{
- {CTL_ACPI, "pm", NULL, 0, 0555, pm_table},
- {0}
-};
-
-/*
- * Initialize power interface
- */
-static int __init pm_init(void)
-{
- register_sysctl_table(pm_dir_table, 1);
- return 0;
-}
-
-fs_initcall(pm_init);
-
-#endif
-
-EXPORT_SYMBOL(pm_do_suspend);
diff -Nru a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/arm/mach-sa1100/ssp.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,208 @@
+/*
+ * linux/arch/arm/mach-sa1100/ssp.c
+ *
+ * Copyright (C) 2003 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Generic SSP driver. This provides the generic core for simple
+ * IO-based SSP applications.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+static void ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int status = Ser4SSSR;
+
+ if (status & SSSR_ROR) {
+ printk(KERN_WARNING "SSP: receiver overrun\n");
+ }
+
+ Ser4SSSR = SSSR_ROR;
+}
+
+/**
+ * ssp_write_word - write a word to the SSP port
+ * @data: 16-bit, MSB justified data to write.
+ *
+ * Wait for a free entry in the SSP transmit FIFO, and write a data
+ * word to the SSP port.
+ *
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ * %-ETIMEDOUT timeout occurred (for future)
+ * 0 success
+ */
+int ssp_write_word(u16 data)
+{
+ while (!(Ser4SSSR & SSSR_TNF))
+ cpu_relax();
+
+ Ser4SSDR = data;
+
+ return 0;
+}
+
+/**
+ * ssp_read_word - read a word from the SSP port
+ *
+ * Wait for a data word in the SSP receive FIFO, and return the
+ * received data. Data is LSB justified.
+ *
+ * Note: Currently, if data is not expected to be received, this
+ * function will wait for ever.
+ *
+ * The caller is expected to perform the necessary locking.
+ *
+ * Returns:
+ * %-ETIMEDOUT timeout occurred (for future)
+ * 16-bit data success
+ */
+int ssp_read_word(void)
+{
+ while (!(Ser4SSSR & SSSR_RNE))
+ cpu_relax();
+
+ return Ser4SSDR;
+}
+
+/**
+ * ssp_flush - flush the transmit and receive FIFOs
+ *
+ * Wait for the SSP to idle, and ensure that the receive FIFO
+ * is empty.
+ *
+ * The caller is expected to perform the necessary locking.
+ */
+void ssp_flush(void)
+{
+ do {
+ while (Ser4SSSR & SSSR_RNE) {
+ (void) Ser4SSDR;
+ }
+ } while (Ser4SSSR & SSSR_BSY);
+}
+
+/**
+ * ssp_enable - enable the SSP port
+ *
+ * Turn on the SSP port.
+ */
+void ssp_enable(void)
+{
+ Ser4SSCR0 |= SSCR0_SSE;
+}
+
+/**
+ * ssp_disable - shut down the SSP port
+ *
+ * Turn off the SSP port, optionally powering it down.
+ */
+void ssp_disable(void)
+{
+ Ser4SSCR0 &= ~SSCR0_SSE;
+}
+
+/**
+ * ssp_save_state - save the SSP configuration
+ * @ssp: pointer to structure to save SSP configuration
+ *
+ * Save the configured SSP state for suspend.
+ */
+void ssp_save_state(struct ssp_state *ssp)
+{
+ ssp->cr0 = Ser4SSCR0;
+ ssp->cr1 = Ser4SSCR1;
+
+ Ser4SSCR0 &= ~SSCR0_SSE;
+}
+
+/**
+ * ssp_restore_state - restore a previously saved SSP configuration
+ * @ssp: pointer to configuration saved by ssp_save_state
+ *
+ * Restore the SSP configuration saved previously by ssp_save_state.
+ */
+void ssp_restore_state(struct ssp_state *ssp)
+{
+ Ser4SSSR = SSSR_ROR;
+
+ Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE;
+ Ser4SSCR1 = ssp->cr1;
+ Ser4SSCR0 = ssp->cr0;
+}
+
+/**
+ * ssp_init - setup the SSP port
+ *
+ * initialise and claim resources for the SSP port.
+ *
+ * Returns:
+ * %-ENODEV if the SSP port is unavailable
+ * %-EBUSY if the resources are already in use
+ * %0 on success
+ */
+int ssp_init(void)
+{
+ int ret;
+
+ if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE))
+ return -ENODEV;
+
+ if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) {
+ return -EBUSY;
+ }
+
+ Ser4SSSR = SSSR_ROR;
+
+ ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL);
+ if (ret)
+ goto out_region;
+
+ return 0;
+
+ out_region:
+ release_mem_region(__PREG(Ser4SSCR0), 0x18);
+ return ret;
+}
+
+/**
+ * ssp_exit - undo the effects of ssp_init
+ *
+ * release and free resources for the SSP port.
+ */
+void ssp_exit(void)
+{
+ Ser4SSCR0 &= ~SSCR0_SSE;
+
+ free_irq(IRQ_Ser4SSP, NULL);
+ release_mem_region(__PREG(Ser4SSCR0), 0x18);
+}
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("SA11x0 SSP PIO driver");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ssp_write_word);
+EXPORT_SYMBOL(ssp_read_word);
+EXPORT_SYMBOL(ssp_flush);
+EXPORT_SYMBOL(ssp_enable);
+EXPORT_SYMBOL(ssp_disable);
+EXPORT_SYMBOL(ssp_save_state);
+EXPORT_SYMBOL(ssp_restore_state);
+EXPORT_SYMBOL(ssp_init);
+EXPORT_SYMBOL(ssp_exit);
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c Mon Mar 17 13:45:14 2003
+++ b/arch/arm/mach-sa1100/system3.c Mon Mar 17 13:45:14 2003
@@ -213,11 +213,17 @@
static int sdram_notifier(struct notifier_block *nb, unsigned long event,
void *data)
{
+ struct cpufreq_policy *policy = data;
switch (event) {
- case CPUFREQ_MINMAX:
- cpufreq_updateminmax(data, 147500, 206000);
+ case CPUFREQ_ADJUST:
+ case CPUFREQ_INCOMPATIBLE:
+ cpufreq_verify_within_limits(policy, 147500, 206000);
+ break;
+ case CPUFREQ_NOTIFY:
+ if ((policy->min < 147500) ||
+ (policy->max > 206000))
+ panic("cpufreq failed to limit the speed\n");
break;
-
}
return 0;
}
@@ -405,7 +411,7 @@
goto DONE;
}
-#if defined( CONFIG_CPU_FREQ )
+#ifdef CONFIG_CPU_FREQ
ret = cpufreq_register_notifier(&system3_clkchg_block);
if ( ret != 0 ) {
printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" );
diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c
--- a/arch/arm/mm/fault-common.c Mon Mar 17 13:45:13 2003
+++ b/arch/arm/mm/fault-common.c Mon Mar 17 13:45:13 2003
@@ -342,20 +342,20 @@
struct pt_regs *regs)
{
struct task_struct *tsk;
- unsigned int offset;
+ unsigned int index;
pgd_t *pgd, *pgd_k;
pmd_t *pmd, *pmd_k;
if (addr < TASK_SIZE)
return do_page_fault(addr, fsr, regs);
- offset = __pgd_offset(addr);
+ index = pgd_index(addr);
/*
* FIXME: CP15 C1 is write only on ARMv3 architectures.
*/
- pgd = cpu_get_pgd() + offset;
- pgd_k = init_mm.pgd + offset;
+ pgd = cpu_get_pgd() + index;
+ pgd_k = init_mm.pgd + index;
if (pgd_none(*pgd_k))
goto bad_area;
diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types Mon Mar 17 13:45:12 2003
+++ b/arch/arm/tools/mach-types Mon Mar 17 13:45:12 2003
@@ -6,7 +6,7 @@
# To add an entry into this database, please see Documentation/arm/README,
# or contact rmk@arm.linux.org.uk
#
-# Last update: Mon Jan 13 22:55:16 2003
+# Last update: Wed Mar 5 22:11:59 2003
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -228,7 +228,7 @@
arnold SA1100_ARNOLD ARNOLD 217
psiboard SA1100_PSIBOARD PSIBOARD 218
jz8028 ARCH_JZ8028 JZ8028 219
-ipaq3 ARCH_IPAQ3 IPAQ3 220
+h5400 ARCH_IPAQ3 IPAQ3 220
forte SA1100_FORTE FORTE 221
acam SA1100_ACAM ACAM 222
abox SA1100_ABOX ABOX 223
@@ -259,7 +259,7 @@
stork_egg ARCH_STORK_EGG STORK_EGG 248
wismo SA1100_WISMO WISMO 249
ezlinx ARCH_EZLINX EZLINX 250
-at91rm9200 ARCH_AT91 AT91 251
+at91 ARCH_AT91 AT91 251
orion ARCH_ORION ORION 252
neptune ARCH_NEPTUNE NEPTUNE 253
hackkit SA1100_HACKKIT HACKKIT 254
@@ -281,3 +281,27 @@
siren ARCH_SIREN SIREN 270
greenlake ARCH_GREENLAKE GREENLAKE 271
argus ARCH_ARGUS ARGUS 272
+combadge SA1100_COMBADGE COMBADGE 273
+rokepxa ARCH_ROKEPXA ROKEPXA 274
+cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275
+guidea07 ARCH_GUIDEA07 GUIDEA07 276
+tat257 ARCH_TAT257 TAT257 277
+igp2425 ARCH_IGP2425 IGP2425 278
+bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279
+ipod ARCH_IPOD IPOD 280
+adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281
+trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282
+viper ARCH_VIPER VIPER 283
+adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284
+adsagc SA1100_ADSAGC ADSAGC 285
+stp7312 ARCH_STP7312 STP7312 286
+nx_phnx ARCH_PXA255 PXA255 287
+wep_ep250 ARCH_WEP_EP250 WEP_EP250 288
+inhandelf3 ARCH_INHANDELF3 INHANDELF3 289
+adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290
+iyonix ARCH_IYONIX IYONIX 291
+damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292
+meg03 ARCH_MEG03 MEG03 293
+pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294
+nwsc ARCH_NWSC NWSC 295
+nwlarm ARCH_NWLARM NWLARM 296
diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in
--- a/arch/arm/vmlinux-armo.lds.in Mon Mar 17 13:45:15 2003
+++ b/arch/arm/vmlinux-armo.lds.in Mon Mar 17 13:45:15 2003
@@ -38,6 +38,9 @@
*(.initcall6.init)
*(.initcall7.init)
__initcall_end = .;
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
. = ALIGN(32768);
__init_end = .;
}
diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in
--- a/arch/arm/vmlinux-armv.lds.in Mon Mar 17 13:45:11 2003
+++ b/arch/arm/vmlinux-armv.lds.in Mon Mar 17 13:45:11 2003
@@ -45,6 +45,9 @@
*(.initcall6.init)
*(.initcall7.init)
__initcall_end = .;
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
. = ALIGN(32);
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig
--- a/arch/cris/Kconfig Mon Mar 17 13:45:14 2003
+++ b/arch/cris/Kconfig Mon Mar 17 13:45:14 2003
@@ -9,10 +9,6 @@
bool
default y
-config SWAP
- bool
- default y
-
config UID16
bool
default y
diff -Nru a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile
--- a/arch/cris/kernel/Makefile Mon Mar 17 13:45:13 2003
+++ b/arch/cris/kernel/Makefile Mon Mar 17 13:45:13 2003
@@ -3,7 +3,7 @@
# Makefile for the linux kernel.
#
-EXTRA_TARGETS := head.o
+extra-y := head.o
obj-y := process.o signal.o entry.o traps.o irq.o \
ptrace.o setup.o time.o sys_cris.o shadows.o \
diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
--- a/arch/cris/kernel/irq.c Mon Mar 17 13:45:15 2003
+++ b/arch/cris/kernel/irq.c Mon Mar 17 13:45:15 2003
@@ -228,11 +228,13 @@
{
int i;
struct irqaction * action;
+ unsigned long flags;
for (i = 0; i < NR_IRQS; i++) {
+ local_irq_save(flags);
action = irq_action[i];
if (!action)
- continue;
+ goto skip;
seq_printf(p, "%2d: %10u %c %s",
i, kstat_cpu(0).irqs[i],
(action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -243,6 +245,8 @@
action->name);
}
seq_putc(p, '\n');
+skip:
+ local_irq_restore(flags);
}
return 0;
}
diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S
--- a/arch/cris/vmlinux.lds.S Mon Mar 17 13:45:12 2003
+++ b/arch/cris/vmlinux.lds.S Mon Mar 17 13:45:12 2003
@@ -69,7 +69,12 @@
*(.initcall6.init);
*(.initcall7.init);
__initcall_end = .;
-
+ }
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+
/* We fill to the next page, so we can discard all init
pages without needing to consider what payload might be
appended to the kernel image. */
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig Mon Mar 17 13:45:09 2003
+++ b/arch/i386/Kconfig Mon Mar 17 13:45:09 2003
@@ -18,15 +18,6 @@
bool
default y
-config SWAP
- bool "Support for paging of anonymous memory"
- default y
- help
- This option allows you to choose whether you want to have support
- for socalled swap devices or swap files in your kernel that are
- used to provide more virtual memory than the actual RAM present
- in your computer. If unusre say Y.
-
config SBUS
bool
@@ -488,7 +479,7 @@
# Common NUMA Features
config NUMA
bool "Numa Memory Allocation Support"
- depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)))
+ depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC
config DISCONTIGMEM
bool
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile Mon Mar 17 13:45:11 2003
+++ b/arch/i386/Makefile Mon Mar 17 13:45:11 2003
@@ -92,7 +92,8 @@
boot := arch/i386/boot
-.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install
+.PHONY: zImage bzImage compressed zlilo bzlilo \
+ zdisk bzdisk fdimage fdimage144 fdimage288 install
all: bzImage
@@ -110,8 +111,8 @@
zdisk bzdisk: vmlinux
$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
-install: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install
+install fdimage fdimage144 fdimage288: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
archclean:
$(Q)$(MAKE) $(clean)=arch/i386/boot
@@ -122,5 +123,8 @@
echo ' (your) ~/bin/installkernel or'
echo ' (distribution) /sbin/installkernel or'
echo ' install to $$(INSTALL_PATH) and run lilo'
+ echo ' bzdisk - Create a boot floppy in /dev/fd0'
+ echo ' fdimage - Create a boot floppy image'
endef
+CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf
diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
--- a/arch/i386/boot/Makefile Mon Mar 17 13:45:12 2003
+++ b/arch/i386/boot/Makefile Mon Mar 17 13:45:12 2003
@@ -25,9 +25,8 @@
#RAMDISK := -DRAMDISK=512
-EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \
- setup setup.o zImage bzImage
-
+targets := vmlinux.bin bootsect bootsect.o setup setup.o \
+ zImage bzImage
subdir- := compressed
host-progs := tools/build
@@ -62,8 +61,36 @@
$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
IMAGE_OFFSET=$(IMAGE_OFFSET) $@
-zdisk: $(BOOTIMAGE)
- dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+# Set this if you want to pass append arguments to the zdisk/fdimage kernel
+FDARGS =
+
+$(obj)/mtools.conf: $(src)/mtools.conf.in
+ sed -e 's|@OBJ@|$(obj)|g' < $< > $@
+
+# This requires write access to /dev/fd0
+zdisk: $(BOOTIMAGE) $(obj)/mtools.conf
+ MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync
+ syslinux /dev/fd0 ; sync
+ echo 'default linux $(FDARGS)' | \
+ MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg
+ MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync
+
+# These require being root or having syslinux 2.02 or higher installed
+fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf
+ dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440
+ MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync
+ syslinux $(obj)/fdimage ; sync
+ echo 'default linux $(FDARGS)' | \
+ MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg
+ MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync
+
+fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf
+ dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880
+ MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync
+ syslinux $(obj)/fdimage ; sync
+ echo 'default linux $(FDARGS)' | \
+ MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg
+ MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync
zlilo: $(BOOTIMAGE)
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
diff -Nru a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S
--- a/arch/i386/boot/bootsect.S Mon Mar 17 13:45:12 2003
+++ b/arch/i386/boot/bootsect.S Mon Mar 17 13:45:12 2003
@@ -4,29 +4,13 @@
* modified by Drew Eckhardt
* modified by Bruce Evans (bde)
* modified by Chris Noe (May 1999) (as86 -> gas)
- *
- * 360k/720k disk support: Andrzej Krzysztofowicz
+ * gutted by H. Peter Anvin (Jan 2003)
*
* BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
* addresses must be multiplied by 16 to obtain their respective linear
* addresses. To avoid confusion, linear addresses are written using leading
* hex while segment addresses are written as segment:offset.
*
- * bde - should not jump blindly, there may be systems with only 512K low
- * memory. Use int 0x12 to get the top of memory, etc.
- *
- * It then loads 'setup' directly after itself (0x90200), and the system
- * at 0x10000, using BIOS interrupts.
- *
- * NOTE! currently system is at most (8*65536-4096) bytes long. This should
- * be no problem, even in the future. I want to keep it simple. This 508 kB
- * kernel size should be enough, especially as this doesn't contain the
- * buffer cache as in minix (and especially now that the kernel is
- * compressed :-)
- *
- * The loader has been made as simple as possible, and continuous
- * read errors will result in a unbreakable loop. Reboot by hand. It
- * loads pretty fast by getting whole tracks at a time whenever possible.
*/
#include
@@ -59,359 +43,51 @@
.global _start
_start:
-# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there.
+ # Normalize the start address
+ jmpl $BOOTSEG, $start2
- movw $BOOTSEG, %ax
- movw %ax, %ds # %ds = BOOTSEG
- movw $INITSEG, %ax
- movw %ax, %es # %ax = %es = INITSEG
- movw $256, %cx
- subw %si, %si
- subw %di, %di
- cld
- rep
- movsw
- ljmp $INITSEG, $go
-
-# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We
-# wouldn't have to worry about this if we checked the top of memory. Also
-# my BIOS can be configured to put the wini drive tables in high memory
-# instead of in the vector table. The old stack might have clobbered the
-# drive table.
-
-go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >=
- # length of bootsect + length of
- # setup + room for stack;
- # 12 is disk parm size.
- movw %ax, %ds # %ax and %es already contain INITSEG
+start2:
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %es
movw %ax, %ss
- movw %di, %sp # put stack at INITSEG:0x4000-12.
+ movw $0x7c00, %sp
+ sti
+ cld
-# Many BIOS's default disk parameter tables will not recognize
-# multi-sector reads beyond the maximum sector number specified
-# in the default diskette parameter tables - this may mean 7
-# sectors in some cases.
-#
-# Since single sector reads are slow and out of the question,
-# we must take care of this by creating new parameter tables
-# (for the first disk) in RAM. We will set the maximum sector
-# count to 36 - the most we will encounter on an ED 2.88.
-#
-# High doesn't hurt. Low does.
-#
-# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
-# and %gs is unused.
-
- movw %cx, %fs # %fs = 0
- movw $0x78, %bx # %fs:%bx is parameter table address
- pushw %ds
- ldsw %fs:(%bx), %si # %ds:%si is source
- movb $6, %cl # copy 12 bytes
- pushw %di # %di = 0x4000-12.
- rep # don't worry about cld
- movsw # already done above
- popw %di
- popw %ds
- movb $36, 0x4(%di) # patch sector count
- movw %di, %fs:(%bx)
- movw %es, %fs:2(%bx)
-
-# Get disk drive parameters, specifically number of sectors/track.
-
-# It seems that there is no BIOS call to get the number of sectors.
-# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
-# can be read, 15 if sector 15 can be read. Otherwise guess 9.
-# Note that %cx = 0 from rep movsw above.
+ movw $bugger_off_msg, %si
- movw $disksizes, %si # table of sizes to try
-probe_loop:
+msg_loop:
lodsb
- cbtw # extend to word
- movw %ax, sectors
- cmpw $disksizes+4, %si
- jae got_sectors # If all else fails, try 9
-
- xchgw %cx, %ax # %cx = track and sector
- xorw %dx, %dx # drive 0, head 0
- movw $0x0200, %bx # address = 512, in INITSEG (%es = %cs)
- movw $0x0201, %ax # service 2, 1 sector
- int $0x13
- jc probe_loop # try next value
-
-got_sectors:
- movb $0x03, %ah # read cursor pos
- xorb %bh, %bh
- int $0x10
- movw $9, %cx
- movb $0x07, %bl # page 0, attribute 7 (normal)
- # %bh is set above; int10 doesn't
- # modify it
- movw $msg1, %bp
- movw $0x1301, %ax # write string, move cursor
- int $0x10 # tell the user we're loading..
-
-# Load the setup-sectors directly after the moved bootblock (at 0x90200).
-# We should know the drive geometry to do it, as setup may exceed first
-# cylinder (for 9-sector 360K and 720K floppies).
-
- movw $0x0001, %ax # set sread (sector-to-read) to 1 as
- movw $sread, %si # the boot sector has already been read
- movw %ax, (%si)
-
- call kill_motor # reset FDC
- movw $0x0200, %bx # address = 512, in INITSEG
-next_step:
- movb setup_sects, %al
- movw sectors, %cx
- subw (%si), %cx # (%si) = sread
- cmpb %cl, %al
- jbe no_cyl_crossing
- movw sectors, %ax
- subw (%si), %ax # (%si) = sread
-no_cyl_crossing:
- call read_track
- pushw %ax # save it
- call set_next # set %bx properly; it uses %ax,%cx,%dx
- popw %ax # restore
- subb %al, setup_sects # rest - for next step
- jnz next_step
-
- pushw $SYSSEG
- popw %es # %es = SYSSEG
- call read_it
- call kill_motor
- call print_nl
-
-# After that we check which root-device to use. If the device is
-# defined (!= 0), nothing is done and the given device is used.
-# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
-# depending on the number of sectors we pretend to know we have.
-
-# Segments are as follows: %cs = %ds = %ss = INITSEG,
-# %es = SYSSEG, %fs = 0, %gs is unused.
-
- movw root_dev, %ax
- orw %ax, %ax
- jne root_defined
-
- movw sectors, %bx
- movw $0x0208, %ax # /dev/ps0 - 1.2Mb
- cmpw $15, %bx
- je root_defined
-
- movb $0x1c, %al # /dev/PS0 - 1.44Mb
- cmpw $18, %bx
- je root_defined
-
- movb $0x20, %al # /dev/fd0H2880 - 2.88Mb
- cmpw $36, %bx
- je root_defined
-
- movb $0, %al # /dev/fd0 - autodetect
-root_defined:
- movw %ax, root_dev
-
-# After that (everything loaded), we jump to the setup-routine
-# loaded directly after the bootblock:
-
- ljmp $SETUPSEG, $0
-
-# These variables are addressed via %si register as it gives shorter code.
-
-sread: .word 0 # sectors read of current track
-head: .word 0 # current head
-track: .word 0 # current track
-
-# This routine loads the system at address SYSSEG, making sure
-# no 64kB boundaries are crossed. We try to load it as fast as
-# possible, loading whole tracks whenever we can.
-
-read_it:
- movw %es, %ax # %es = SYSSEG when called
- testw $0x0fff, %ax
-die: jne die # %es must be at 64kB boundary
- xorw %bx, %bx # %bx is starting address within segment
-rp_read:
-#ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge
- bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the
- lcall *bootsect_kludge # bootsector + bootsect_kludge offset
-#else
- movw %es, %ax
- subw $SYSSEG, %ax
- movw %bx, %cx
- shr $4, %cx
- add %cx, %ax # check offset
-#endif
- cmpw syssize, %ax # have we loaded everything yet?
- jbe ok1_read
-
- ret
-
-ok1_read:
- movw sectors, %ax
- subw (%si), %ax # (%si) = sread
- movw %ax, %cx
- shlw $9, %cx
- addw %bx, %cx
- jnc ok2_read
-
- je ok2_read
-
- xorw %ax, %ax
- subw %bx, %ax
- shrw $9, %ax
-ok2_read:
- call read_track
- call set_next
- jmp rp_read
-
-read_track:
- pusha
- pusha
- movw $0xe2e, %ax # loading... message 2e = .
+ andb %al, %al
+ jz die
+ movb $0xe, %ah
movw $7, %bx
- int $0x10
- popa
-
-# Accessing head, track, sread via %si gives shorter code.
+ int $0x10
+ jmp msg_loop
- movw 4(%si), %dx # 4(%si) = track
- movw (%si), %cx # (%si) = sread
- incw %cx
- movb %dl, %ch
- movw 2(%si), %dx # 2(%si) = head
- movb %dl, %dh
- andw $0x0100, %dx
- movb $2, %ah
- pushw %dx # save for error dump
- pushw %cx
- pushw %bx
- pushw %ax
- int $0x13
- jc bad_rt
-
- addw $8, %sp
- popa
- ret
-
-set_next:
- movw %ax, %cx
- addw (%si), %ax # (%si) = sread
- cmp sectors, %ax
- jne ok3_set
- movw $0x0001, %ax
- xorw %ax, 2(%si) # change head
- jne ok4_set
- incw 4(%si) # next track
-ok4_set:
+die:
+ # Allow the user to press a key, then reboot
xorw %ax, %ax
-ok3_set:
- movw %ax, (%si) # set sread
- shlw $9, %cx
- addw %cx, %bx
- jnc set_next_fin
- movw %es, %ax
- addb $0x10, %ah
- movw %ax, %es
- xorw %bx, %bx
-set_next_fin:
- ret
-
-bad_rt:
- pushw %ax # save error code
- call print_all # %ah = error, %al = read
- xorb %ah, %ah
- xorb %dl, %dl
- int $0x13
- addw $10, %sp
- popa
- jmp read_track
-
-# print_all is for debugging purposes.
-#
-# it will print out all of the registers. The assumption is that this is
-# called from a routine, with a stack frame like
-#
-# %dx
-# %cx
-# %bx
-# %ax
-# (error)
-# ret <- %sp
-
-print_all:
- movw $5, %cx # error code + 4 registers
- movw %sp, %bp
-print_loop:
- pushw %cx # save count remaining
- call print_nl # <-- for readability
- cmpb $5, %cl
- jae no_reg # see if register name is needed
-
- movw $0xe05 + 'A' - 1, %ax
- subb %cl, %al
- int $0x10
- movb $'X', %al
- int $0x10
- movb $':', %al
- int $0x10
-no_reg:
- addw $2, %bp # next register
- call print_hex # print it
- popw %cx
- loop print_loop
- ret
+ int $0x16
+ int $0x19
-print_nl:
- movw $0xe0d, %ax # CR
- int $0x10
- movb $0xa, %al # LF
- int $0x10
- ret
-
-# print_hex is for debugging purposes, and prints the word
-# pointed to by %ss:%bp in hexadecimal.
-
-print_hex:
- movw $4, %cx # 4 hex digits
- movw (%bp), %dx # load word into %dx
-print_digit:
- rolw $4, %dx # rotate to use low 4 bits
- movw $0xe0f, %ax # %ah = request
- andb %dl, %al # %al = mask for nybble
- addb $0x90, %al # convert %al to ascii hex
- daa # in only four instructions!
- adc $0x40, %al
- daa
- int $0x10
- loop print_digit
- ret
+ # int 0x19 should never return. In case it does anyway,
+ # invoke the BIOS reset code...
+ ljmp $0xf000,$0xfff0
-# This procedure turns off the floppy drive motor, so
-# that we enter the kernel in a known state, and
-# don't have to worry about it later.
-# NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
-
-kill_motor:
-#if 1
- xorw %ax, %ax # reset FDC
- xorb %dl, %dl
- int $0x13
-#else
- movw $0x3f2, %dx
- xorb %al, %al
- outb %al, %dx
-#endif
- ret
-sectors: .word 0
-disksizes: .byte 36, 21, 18, 15, 9
-msg1: .byte 13, 10
- .ascii "Loading"
+bugger_off_msg:
+ .ascii "Direct booting from floppy is no longer supported.\r\n"
+ .ascii "Please use a boot loader program instead.\r\n"
+ .ascii "\n"
+ .ascii "Remove disk and press any key to reboot . . .\r\n"
+ .byte 0
+
-# XXX: This is a fairly snug fit.
+ # Kernel attributes; used by setup
-.org 497
+ .org 497
setup_sects: .byte SETUPSECTS
root_flags: .word ROOT_RDONLY
syssize: .word SYSSIZE
diff -Nru a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile
--- a/arch/i386/boot/compressed/Makefile Mon Mar 17 13:45:14 2003
+++ b/arch/i386/boot/compressed/Makefile Mon Mar 17 13:45:14 2003
@@ -4,7 +4,7 @@
# create a compressed vmlinux image from the original vmlinux
#
-EXTRA_TARGETS := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
+targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
EXTRA_AFLAGS := -traditional
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32
diff -Nru a/arch/i386/boot/mtools.conf.in b/arch/i386/boot/mtools.conf.in
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/i386/boot/mtools.conf.in Mon Mar 17 13:45:16 2003
@@ -0,0 +1,17 @@
+#
+# mtools configuration file for "make (b)zdisk"
+#
+
+# Actual floppy drive
+drive a:
+ file="/dev/fd0"
+
+# 1.44 MB floppy disk image
+drive v:
+ file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter
+
+# 2.88 MB floppy disk image (mostly for virtual uses)
+drive w:
+ file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
+
+
diff -Nru a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
--- a/arch/i386/boot/tools/build.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/boot/tools/build.c Mon Mar 17 13:45:12 2003
@@ -150,13 +150,10 @@
sz = sb.st_size;
fprintf (stderr, "System is %d kB\n", sz/1024);
sys_size = (sz + 15) / 16;
- /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */
- if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
+ /* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
+ if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
die("System is too big. Try using %smodules.",
is_big_kernel ? "" : "bzImage or ");
- if (sys_size > 0xefff)
- fprintf(stderr,"warning: kernel is too big for standalone boot "
- "from floppy\n");
while (sz > 0) {
int l, n;
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/Makefile Mon Mar 17 13:45:09 2003
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-EXTRA_TARGETS := head.o init_task.o
+extra-y := head.o init_task.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
diff -Nru a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c
--- a/arch/i386/kernel/cpu/centaur.c Mon Mar 17 13:45:13 2003
+++ b/arch/i386/kernel/cpu/centaur.c Mon Mar 17 13:45:13 2003
@@ -248,6 +248,37 @@
}
#endif
+static void __init init_c3(struct cpuinfo_x86 *c)
+{
+ u32 lo, hi;
+
+ /* Test for Centaur Extended Feature Flags presence */
+ if (cpuid_eax(0xC0000000) >= 0xC0000001) {
+ /* store Centaur Extended Feature Flags as
+ * word 5 of the CPU capability bit array
+ */
+ c->x86_capability[5] = cpuid_edx(0xC0000001);
+ }
+
+ switch (c->x86_model) {
+ case 6 ... 8: /* Cyrix III family */
+ rdmsr (MSR_VIA_FCR, lo, hi);
+ lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */
+ wrmsr (MSR_VIA_FCR, lo, hi);
+
+ set_bit(X86_FEATURE_CX8, c->x86_capability);
+ set_bit(X86_FEATURE_3DNOW, c->x86_capability);
+
+ /* fall through */
+
+ case 9: /* Nehemiah */
+ default:
+ get_model_name(c);
+ display_cacheinfo(c);
+ break;
+ }
+}
+
static void __init init_centaur(struct cpuinfo_x86 *c)
{
enum {
@@ -386,21 +417,7 @@
break;
case 6:
- switch (c->x86_model) {
- case 6 ... 8: /* Cyrix III family */
- rdmsr (MSR_VIA_FCR, lo, hi);
- lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */
- wrmsr (MSR_VIA_FCR, lo, hi);
-
- set_bit(X86_FEATURE_CX8, c->x86_capability);
- set_bit(X86_FEATURE_3DNOW, c->x86_capability);
-
- case 9: /* Nehemiah */
- default:
- get_model_name(c);
- display_cacheinfo(c);
- break;
- }
+ init_c3(c);
break;
}
}
diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
--- a/arch/i386/kernel/cpu/common.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/cpu/common.c Mon Mar 17 13:45:09 2003
@@ -211,9 +211,10 @@
/* Intel-defined flags: level 0x00000001 */
if ( c->cpuid_level >= 0x00000001 ) {
- u32 capability;
- cpuid(0x00000001, &tfms, &junk, &junk, &capability);
+ u32 capability, excap;
+ cpuid(0x00000001, &tfms, &junk, &excap, &capability);
c->x86_capability[0] = capability;
+ c->x86_capability[4] = excap;
c->x86 = (tfms >> 8) & 15;
c->x86_model = (tfms >> 4) & 15;
c->x86_mask = tfms & 15;
@@ -480,7 +481,7 @@
*/
atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm;
- if(current->mm)
+ if (current->mm)
BUG();
enter_lazy_tlb(&init_mm, current, cpu);
@@ -508,7 +509,7 @@
/*
* Force FPU initialization:
*/
- clear_thread_flag(TIF_USEDFPU);
+ current_thread_info()->status = 0;
current->used_math = 0;
stts();
}
diff -Nru a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c
--- a/arch/i386/kernel/cpu/cpufreq/acpi.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/cpu/cpufreq/acpi.c Mon Mar 17 13:45:09 2003
@@ -619,6 +619,7 @@
.init = acpi_cpufreq_cpu_init,
.exit = acpi_cpufreq_cpu_exit,
.name = "acpi-cpufreq",
+ .owner = THIS_MODULE,
};
diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c Mon Mar 17 13:45:12 2003
@@ -250,6 +250,7 @@
.target = elanfreq_target,
.init = elanfreq_cpu_init,
.name = "elanfreq",
+ .owner = THIS_MODULE,
};
diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Mon Mar 17 13:45:12 2003
@@ -444,13 +444,14 @@
/*
* cpufreq_gx_init:
- * MediaGX/Geode GX initilize cpufreq driver
+ * MediaGX/Geode GX initialize cpufreq driver
*/
static struct cpufreq_driver gx_suspmod_driver = {
.verify = cpufreq_gx_verify,
.target = cpufreq_gx_target,
.init = cpufreq_gx_cpu_init,
.name = "gx-suspmod",
+ .owner = THIS_MODULE,
};
static int __init cpufreq_gx_init(void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Mon Mar 17 13:45:09 2003
@@ -40,18 +40,15 @@
#define dprintk(msg...) do { } while(0);
#endif
-static int numscales=16, numvscales;
+static unsigned int numscales=16, numvscales;
static int minvid, maxvid;
static int can_scale_voltage;
-static int can_scale_fsb;
static int vrmrev;
/* Module parameters */
-static int prefer_slow_fsb;
static int dont_scale_voltage;
-static int dont_scale_fsb;
-static int current_fsb;
+static unsigned int fsb;
#define __hlt() __asm__ __volatile__("hlt": : :"memory")
@@ -231,14 +228,6 @@
145, /* 1111 -> 14.5x */
};
-/* fsb values as defined in CPU */
-static unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
-/* fsb values to favour low fsb speed (lower power) */
-static unsigned int power_fsb_table[] = { 66, 100, 133, -1 };
-/* fsb values to favour high fsb speed (for e.g. if lowering CPU
- freq because of heat, but want to maintain highest performance possible) */
-static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 };
-
/* Voltage scales. Div by 1000 to get actual voltage. */
static int __initdata vrm85scales[32] = {
1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700,
@@ -258,21 +247,22 @@
static int clock_ratio[32];
static int eblcr_table[32];
static int voltage_table[32];
-static int highest_speed, lowest_speed; /* kHz */
+static unsigned int highest_speed, lowest_speed; /* kHz */
static int longhaul; /* version. */
static struct cpufreq_frequency_table *longhaul_table;
static int longhaul_get_cpu_fsb (void)
{
+ unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 };
unsigned long invalue=0,lo, hi;
- if (current_fsb == 0) {
+ if (fsb == 0) {
rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi);
invalue = (lo & (1<<18|1<<19)) >>18;
return eblcr_fsb_table[invalue];
} else {
- return current_fsb;
+ return fsb;
}
}
@@ -294,12 +284,11 @@
/**
* longhaul_set_cpu_frequency()
* @clock_ratio_index : index of clock_ratio[] for new frequency
- * @newfsb: the new FSB
*
* Sets a new clock ratio, and -if applicable- a new Front Side Bus
*/
-static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newfsb)
+static void longhaul_setstate (unsigned int clock_ratio_index)
{
unsigned long lo, hi;
unsigned int bits;
@@ -307,24 +296,21 @@
int vidindex, i;
struct cpufreq_freqs freqs;
- if (!newfsb || (clock_ratio[clock_ratio_index] == -1))
- return;
-
- if ((!can_scale_fsb) && (newfsb != current_fsb))
+ if (clock_ratio[clock_ratio_index] == -1)
return;
- if (((clock_ratio[clock_ratio_index] * newfsb * 100) > highest_speed) ||
- ((clock_ratio[clock_ratio_index] * newfsb * 100) < lowest_speed))
+ if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) ||
+ ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed))
return;
freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100;
- freqs.new = clock_ratio[clock_ratio_index] * newfsb * 100;
+ freqs.new = clock_ratio[clock_ratio_index] * fsb * 100;
freqs.cpu = 0; /* longhaul.c is UP only driver */
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- dprintk (KERN_INFO "longhaul: New FSB:%d Mult(x10):%d\n",
- newfsb, clock_ratio[clock_ratio_index]);
+ dprintk (KERN_INFO "longhaul: FSB:%d Mult(x10):%d\n",
+ fsb * 100, clock_ratio[clock_ratio_index]);
bits = clock_ratio_index;
/* "bits" contains the bitpattern of the new multiplier.
@@ -358,14 +344,9 @@
lo |= revkey;
if (can_scale_voltage) {
- if (can_scale_fsb==1) {
- dprintk (KERN_INFO "longhaul: Voltage scaling + FSB scaling not done yet.\n");
- goto bad_voltage;
- } else {
- /* PB: TODO fix this up */
- vidindex = (((highest_speed-lowest_speed) / (newfsb/2)) -
- ((highest_speed-((clock_ratio[clock_ratio_index] * newfsb * 100)/1000)) / (newfsb/2)));
- }
+ /* PB: TODO fix this up */
+ vidindex = (((highest_speed-lowest_speed) / (fsb/2)) -
+ ((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2)));
for (i=0;i<32;i++) {
dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n",
minvid+(vidindex*25), voltage_table[i]);
@@ -403,17 +384,6 @@
lo |= (1<<8); /* EnableSoftBusRatio */
lo |= revkey;
- /* Set FSB */
- if (can_scale_fsb==1) {
- lo &= ~(1<<28|1<<29);
- switch (newfsb) {
- case 66: lo |= (1<<28|1<<29); /* 11 */
- break;
- case 100: lo |= 1<<28; /* 01 */
- break;
- case 133: break; /* 00*/
- }
- }
wrmsr (MSR_VIA_LONGHAUL, lo, hi);
__hlt();
@@ -431,14 +401,11 @@
static int __init longhaul_get_ranges (void)
{
unsigned long lo, hi, invalue;
- unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0;
+ unsigned int minmult=0, maxmult=0;
unsigned int multipliers[32]= {
50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65,
-1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 };
- unsigned int fsb_table[4] = { 133, 100, -1, 66 };
- unsigned int fsbcount = 1;
- unsigned int i, j, k = 0;
- static unsigned int *fsb_search_table;
+ unsigned int j, k = 0;
switch (longhaul) {
case 1:
@@ -446,7 +413,6 @@
Assume min=3.0x & max = whatever we booted at. */
minmult = 30;
maxmult = longhaul_get_cpu_mult();
- minfsb = maxfsb = current_fsb;
break;
case 2 ... 3:
@@ -465,55 +431,30 @@
#else
minmult = 30; /* as per spec */
#endif
-
- if (can_scale_fsb==1) {
- invalue = (hi & (1<<9|1<<10)) >> 9;
- maxfsb = fsb_table[invalue];
-
- invalue = (hi & (1<<25|1<<26)) >> 25;
- minfsb = fsb_table[invalue];
-
- dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n",
- minfsb, maxfsb);
- fsbcount = 0;
- for (i=0;i<4;i++) {
- if((fsb_table[i] >= minfsb) && (fsb_table[i] <= maxfsb))
- fsbcount++;
- }
- } else {
- minfsb = maxfsb = current_fsb;
- }
break;
}
- highest_speed = maxmult * maxfsb * 100;
- lowest_speed = minmult * minfsb * 100;
+ highest_speed = maxmult * fsb * 100;
+ lowest_speed = minmult * fsb * 100;
dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n",
minmult, maxmult);
dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n",
lowest_speed, highest_speed);
- longhaul_table = kmalloc((numscales * fsbcount + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
+ longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL);
if(!longhaul_table)
return -ENOMEM;
- if (prefer_slow_fsb)
- fsb_search_table = perf_fsb_table; // yep, this is right: the last entry is preferred by cpufreq_frequency_table_* ...
- else
- fsb_search_table = power_fsb_table;
-
- for (i=0; (i<4); i++) {
- if ((fsb_search_table[i] > maxfsb) || (fsb_search_table[i] < minfsb) || (fsb_search_table[i] == -1))
+ for (j=0; (j maxmult) || (clock_ratio[j] < minmult) || (clock_ratio[j] == -1))
- continue;
- longhaul_table[k].frequency= clock_ratio[j] * fsb_search_table[i] * 100;
- longhaul_table[k].index = (j << 8) | (i);
- k++;
- }
+ if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult))
+ continue;
+ longhaul_table[k].frequency= clock_ratio[j] * fsb * 100;
+ longhaul_table[k].index = (j << 8);
+ k++;
}
-
+
longhaul_table[k].frequency = CPUFREQ_TABLE_END;
if (!k)
return -EINVAL;
@@ -568,16 +509,14 @@
unsigned int relation)
{
unsigned int table_index = 0;
- unsigned int new_fsb = 0;
unsigned int new_clock_ratio = 0;
if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
return -EINVAL;
new_clock_ratio = longhaul_table[table_index].index & 0xFF;
- new_fsb = power_fsb_table[(longhaul_table[table_index].index & 0xFF00) >> 8];
- longhaul_setstate(new_clock_ratio, new_fsb);
+ longhaul_setstate(new_clock_ratio);
return 0;
}
@@ -628,9 +567,6 @@
rdmsr (MSR_VIA_LONGHAUL, lo, hi);
if ((lo & (1<<0)) && (dont_scale_voltage==0))
longhaul_setup_voltagescaling (lo, hi);
-
- if ((lo & (1<<1)) && (dont_scale_fsb==0) && (current_fsb==0))
- can_scale_fsb = 1;
}
if (longhaul_get_ranges())
@@ -639,7 +575,7 @@
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
- policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100);
+ policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100);
return cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
}
@@ -649,6 +585,7 @@
.target = longhaul_target,
.init = longhaul_cpu_init,
.name = "longhaul",
+ .owner = THIS_MODULE,
};
static int __init longhaul_init (void)
@@ -676,10 +613,7 @@
kfree(longhaul_table);
}
-MODULE_PARM (dont_scale_fsb, "i");
MODULE_PARM (dont_scale_voltage, "i");
-MODULE_PARM (current_fsb, "i");
-MODULE_PARM (prefer_slow_fsb, "i");
MODULE_AUTHOR ("Dave Jones ");
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c Mon Mar 17 13:45:14 2003
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c Mon Mar 17 13:45:14 2003
@@ -253,6 +253,7 @@
.setpolicy = longrun_set_policy,
.init = longrun_cpu_init,
.name = "longrun",
+ .owner = THIS_MODULE,
};
diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Mon Mar 17 13:45:14 2003
+++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Mon Mar 17 13:45:14 2003
@@ -214,6 +214,7 @@
else
p4clockmod_table[i].frequency = (stock_freq * i)/8;
}
+ cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
/* cpuinfo and default policy values */
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
@@ -226,9 +227,14 @@
static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
{
+ cpufreq_frequency_table_put_attr(policy->cpu);
return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
}
+static struct freq_attr* p4clockmod_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
static struct cpufreq_driver p4clockmod_driver = {
.verify = cpufreq_p4_verify,
@@ -236,6 +242,8 @@
.init = cpufreq_p4_cpu_init,
.exit = cpufreq_p4_cpu_exit,
.name = "p4-clockmod",
+ .owner = THIS_MODULE,
+ .attr = p4clockmod_attr,
};
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Mon Mar 17 13:45:09 2003
@@ -190,6 +190,7 @@
.init = powernow_k6_cpu_init,
.exit = powernow_k6_cpu_exit,
.name = "powernow-k6",
+ .owner = THIS_MODULE,
};
diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Mon Mar 17 13:45:09 2003
@@ -151,7 +151,7 @@
}
if (!(edx & (1 << 1 | 1 << 2))) {
- printk (" nothing.\n");
+ printk ("nothing.\n");
return 0;
}
@@ -162,9 +162,8 @@
static int get_ranges (unsigned char *pst)
{
- int j;
+ unsigned int j, speed;
u8 fid, vid;
- unsigned int speed;
powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL);
if (!powernow_table)
@@ -239,12 +238,17 @@
__asm__("\tcli\n");
rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */
+
fidvidctl.bits.FID = fid;
- fidvidctl.bits.VID = vid;
- /* Note, we could set these lazily. Ie, only do voltage transition
- if its changed since last time (Some speeds have the same voltage) */
fidvidctl.bits.FIDC = 1;
- fidvidctl.bits.VIDC = 1;
+
+ /* Set the voltage lazily. Ie, only do voltage transition
+ if its changed since last time (Some speeds have the same voltage) */
+ if (fidvidctl.bits.VID != vid) {
+ fidvidctl.bits.VID = vid;
+ fidvidctl.bits.VIDC = 1;
+ }
+
wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val);
if (have_a0 == 1)
__asm__("\tsti\n");
@@ -253,7 +257,7 @@
}
-int powernow_decode_bios (int maxfid, int startvid)
+static int powernow_decode_bios (int maxfid, int startvid)
{
struct psb_s *psb;
struct pst_s *pst;
@@ -377,6 +381,7 @@
.target = powernow_target,
.init = powernow_cpu_init,
.name = "powernow-k7",
+ .owner = THIS_MODULE,
};
static int __init powernow_init (void)
diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- a/arch/i386/kernel/cpu/cpufreq/speedstep.c Mon Mar 17 13:45:08 2003
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c Mon Mar 17 13:45:08 2003
@@ -29,7 +29,6 @@
#include
-
/* speedstep_chipset:
* It is necessary to know which chipset is used. As accesses to
* this device occur at various places in this module, we need a
@@ -40,7 +39,7 @@
#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002
#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003
-
+#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004
/* speedstep_processor
*/
@@ -106,6 +105,7 @@
switch (speedstep_chipset) {
case SPEEDSTEP_CHIPSET_ICH2M:
case SPEEDSTEP_CHIPSET_ICH3M:
+ case SPEEDSTEP_CHIPSET_ICH4M:
/* get PMBASE */
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
if (!(pmbase & 0x01))
@@ -166,6 +166,7 @@
switch (speedstep_chipset) {
case SPEEDSTEP_CHIPSET_ICH2M:
case SPEEDSTEP_CHIPSET_ICH3M:
+ case SPEEDSTEP_CHIPSET_ICH4M:
/* get PMBASE */
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
if (!(pmbase & 0x01))
@@ -245,6 +246,7 @@
switch (speedstep_chipset) {
case SPEEDSTEP_CHIPSET_ICH2M:
case SPEEDSTEP_CHIPSET_ICH3M:
+ case SPEEDSTEP_CHIPSET_ICH4M:
{
u16 value = 0;
@@ -277,6 +279,14 @@
static unsigned int speedstep_detect_chipset (void)
{
speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82801DB_12,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ NULL);
+ if (speedstep_chipset_dev)
+ return SPEEDSTEP_CHIPSET_ICH4M;
+
+ speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801CA_12,
PCI_ANY_ID,
PCI_ANY_ID,
@@ -658,6 +668,7 @@
.verify = speedstep_verify,
.target = speedstep_target,
.init = speedstep_cpu_init,
+ .owner = THIS_MODULE,
};
diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
--- a/arch/i386/kernel/cpu/proc.c Mon Mar 17 13:45:14 2003
+++ b/arch/i386/kernel/cpu/proc.c Mon Mar 17 13:45:14 2003
@@ -37,7 +37,20 @@
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Other (Linux-defined) */
- "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL,
+ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* Intel-defined (#2) */
+ "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, NULL,
+ "tm2", NULL, "cnxt_id", NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* VIA/Cyrix/Centaur-defined */
+ NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/kernel/dmi_scan.c Mon Mar 17 13:45:12 2003
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -893,3 +894,5 @@
if(err == 0)
dmi_check_blacklist();
}
+
+EXPORT_SYMBOL(is_unsafe_smbus);
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S Mon Mar 17 13:45:10 2003
+++ b/arch/i386/kernel/entry.S Mon Mar 17 13:45:10 2003
@@ -72,6 +72,12 @@
NT_MASK = 0x00004000
VM_MASK = 0x00020000
+/*
+ * ESP0 is at offset 4. 0x100 is the size of the TSS, and
+ * also thus the top-of-stack pointer offset of SYSENTER_ESP
+ */
+TSS_ESP0_OFFSET = (4 - 0x100)
+
#ifdef CONFIG_PREEMPT
#define preempt_stop cli
#else
@@ -229,6 +235,8 @@
# sysenter call handler stub
ENTRY(sysenter_entry)
+ movl TSS_ESP0_OFFSET(%esp),%esp
+sysenter_past_esp:
sti
pushl $(__USER_DS)
pushl %ebp
@@ -458,12 +466,36 @@
addl $4, %esp
jmp ret_from_exception
+/*
+ * Debug traps and NMI can happen at the one SYSENTER instruction
+ * that sets up the real kernel stack. Check here, since we can't
+ * allow the wrong stack to be used.
+ *
+ * "TSS_ESP0_OFFSET+12" is because the NMI/debug handler will have
+ * already pushed 3 words if it hits on the sysenter instruction:
+ * eflags, cs and eip.
+ *
+ * We just load the right stack, and push the three (known) values
+ * by hand onto the new stack - while updating the return eip past
+ * the instruction that would have done it for sysenter.
+ */
+#define CHECK_SYSENTER_EIP \
+ cmpl $sysenter_entry,(%esp); \
+ jne 1f; \
+ movl TSS_ESP0_OFFSET+12(%esp),%esp; \
+ pushfl; \
+ pushl $__KERNEL_CS; \
+ pushl $sysenter_past_esp; \
+1:
+
ENTRY(debug)
+ CHECK_SYSENTER_EIP
pushl $0
pushl $do_debug
jmp error_code
ENTRY(nmi)
+ CHECK_SYSENTER_EIP
pushl %eax
SAVE_ALL
movl %esp, %edx
diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
--- a/arch/i386/kernel/head.S Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/head.S Mon Mar 17 13:45:09 2003
@@ -130,7 +130,7 @@
popfl
jmp checkCPUtype
1:
-#endif CONFIG_SMP
+#endif /* CONFIG_SMP */
/*
* Clear BSS first so that there are no surprises...
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c Mon Mar 17 13:45:15 2003
+++ b/arch/i386/kernel/i386_ksyms.c Mon Mar 17 13:45:15 2003
@@ -68,6 +68,7 @@
EXPORT_SYMBOL(MCA_bus);
#ifdef CONFIG_DISCONTIGMEM
EXPORT_SYMBOL(node_data);
+EXPORT_SYMBOL(physnode_map);
#endif
#ifdef CONFIG_X86_NUMAQ
EXPORT_SYMBOL(xquad_portio);
diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
--- a/arch/i386/kernel/i387.c Mon Mar 17 13:45:16 2003
+++ b/arch/i386/kernel/i387.c Mon Mar 17 13:45:16 2003
@@ -52,29 +52,13 @@
* FPU lazy state save handling.
*/
-static inline void __save_init_fpu( struct task_struct *tsk )
-{
- if ( cpu_has_fxsr ) {
- asm volatile( "fxsave %0 ; fnclex"
- : "=m" (tsk->thread.i387.fxsave) );
- } else {
- asm volatile( "fnsave %0 ; fwait"
- : "=m" (tsk->thread.i387.fsave) );
- }
- clear_tsk_thread_flag(tsk, TIF_USEDFPU);
-}
-
-void save_init_fpu( struct task_struct *tsk )
-{
- __save_init_fpu(tsk);
- stts();
-}
-
void kernel_fpu_begin(void)
{
+ struct thread_info *thread = current_thread_info();
+
preempt_disable();
- if (test_thread_flag(TIF_USEDFPU)) {
- __save_init_fpu(current);
+ if (thread->status & TS_USEDFPU) {
+ __save_init_fpu(thread->task);
return;
}
clts();
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c Mon Mar 17 13:45:11 2003
+++ b/arch/i386/kernel/io_apic.c Mon Mar 17 13:45:11 2003
@@ -221,8 +221,9 @@
# define Dprintk(x...)
# endif
-extern unsigned long irq_affinity [NR_IRQS];
-int __cacheline_aligned pending_irq_balance_apicid [NR_IRQS];
+extern unsigned long irq_affinity[NR_IRQS];
+
+static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS];
static int irqbalance_disabled = NO_BALANCE_IRQ;
static int physical_balance = 0;
@@ -251,8 +252,54 @@
#define BALANCED_IRQ_LESS_DELTA (HZ)
long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
-
-static inline void balance_irq(int cpu, int irq);
+
+static unsigned long move(int curr_cpu, unsigned long allowed_mask,
+ unsigned long now, int direction)
+{
+ int search_idle = 1;
+ int cpu = curr_cpu;
+
+ goto inside;
+
+ do {
+ if (unlikely(cpu == curr_cpu))
+ search_idle = 0;
+inside:
+ if (direction == 1) {
+ cpu++;
+ if (cpu >= NR_CPUS)
+ cpu = 0;
+ } else {
+ cpu--;
+ if (cpu == -1)
+ cpu = NR_CPUS-1;
+ }
+ } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
+ (search_idle && !IDLE_ENOUGH(cpu,now)));
+
+ return cpu;
+}
+
+static inline void balance_irq(int cpu, int irq)
+{
+ unsigned long now = jiffies;
+ unsigned long allowed_mask;
+ unsigned int new_cpu;
+
+ if (irqbalance_disabled)
+ return;
+
+ allowed_mask = cpu_online_map & irq_affinity[irq];
+ new_cpu = move(cpu, allowed_mask, now, 1);
+ if (cpu != new_cpu) {
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ pending_irq_balance_apicid[irq]=cpu_to_logical_apicid(new_cpu);
+ spin_unlock_irqrestore(&desc->lock, flags);
+ }
+}
static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold)
{
@@ -263,7 +310,8 @@
if (!irq_desc[j].action)
continue;
/* Is it a significant load ? */
- if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < useful_load_threshold)
+ if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) <
+ useful_load_threshold)
continue;
balance_irq(i, j);
}
@@ -430,7 +478,8 @@
* We seek the least loaded sibling by making the comparison
* (A+B)/2 vs B
*/
- if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > CPU_IRQ(cpu_sibling_map[min_loaded]))
+ if (physical_balance && (CPU_IRQ(min_loaded) >> 1) >
+ CPU_IRQ(cpu_sibling_map[min_loaded]))
min_loaded = cpu_sibling_map[min_loaded];
allowed_mask = cpu_online_map & irq_affinity[selected_irq];
@@ -438,11 +487,15 @@
if (target_cpu_mask & allowed_mask) {
irq_desc_t *desc = irq_desc + selected_irq;
- Dprintk("irq = %d moved to cpu = %d\n", selected_irq, min_loaded);
+ unsigned long flags;
+
+ Dprintk("irq = %d moved to cpu = %d\n",
+ selected_irq, min_loaded);
/* mark for change destination */
- spin_lock(&desc->lock);
- pending_irq_balance_apicid[selected_irq] = cpu_to_logical_apicid(min_loaded);
- spin_unlock(&desc->lock);
+ spin_lock_irqsave(&desc->lock, flags);
+ pending_irq_balance_apicid[selected_irq] =
+ cpu_to_logical_apicid(min_loaded);
+ spin_unlock_irqrestore(&desc->lock, flags);
/* Since we made a change, come back sooner to
* check for more variation.
*/
@@ -453,58 +506,16 @@
goto tryanotherirq;
not_worth_the_effort:
- /* if we did not find an IRQ to move, then adjust the time interval upward */
+ /*
+ * if we did not find an IRQ to move, then adjust the time interval
+ * upward
+ */
balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL,
balanced_irq_interval + BALANCED_IRQ_MORE_DELTA);
Dprintk("IRQ worth rotating not found\n");
return;
}
-static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction)
-{
- int search_idle = 1;
- int cpu = curr_cpu;
-
- goto inside;
-
- do {
- if (unlikely(cpu == curr_cpu))
- search_idle = 0;
-inside:
- if (direction == 1) {
- cpu++;
- if (cpu >= NR_CPUS)
- cpu = 0;
- } else {
- cpu--;
- if (cpu == -1)
- cpu = NR_CPUS-1;
- }
- } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
- (search_idle && !IDLE_ENOUGH(cpu,now)));
-
- return cpu;
-}
-
-static inline void balance_irq (int cpu, int irq)
-{
- unsigned long now = jiffies;
- unsigned long allowed_mask;
- unsigned int new_cpu;
-
- if (irqbalance_disabled)
- return;
-
- allowed_mask = cpu_online_map & irq_affinity[irq];
- new_cpu = move(cpu, allowed_mask, now, 1);
- if (cpu != new_cpu) {
- irq_desc_t *desc = irq_desc + irq;
- spin_lock(&desc->lock);
- pending_irq_balance_apicid[irq] = cpu_to_logical_apicid(new_cpu);
- spin_unlock(&desc->lock);
- }
-}
-
int balanced_irq(void *unused)
{
int i;
@@ -516,26 +527,32 @@
/* push everything to CPU 0 to give us a starting point. */
for (i = 0 ; i < NR_IRQS ; i++)
pending_irq_balance_apicid[i] = cpu_to_logical_apicid(0);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- time_remaining = schedule_timeout(time_remaining);
- if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
- Dprintk("balanced_irq: calling do_irq_balance() %lu\n", jiffies);
- do_irq_balance();
- prev_balance_time = jiffies;
- time_remaining = balanced_irq_interval;
- }
- }
+
+repeat:
+ set_current_state(TASK_INTERRUPTIBLE);
+ time_remaining = schedule_timeout(time_remaining);
+ if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) {
+ Dprintk("balanced_irq: calling do_irq_balance() %lu\n",
+ jiffies);
+ do_irq_balance();
+ prev_balance_time = jiffies;
+ time_remaining = balanced_irq_interval;
+ }
+ goto repeat;
}
static int __init balanced_irq_init(void)
{
int i;
struct cpuinfo_x86 *c;
+
c = &boot_cpu_data;
if (irqbalance_disabled)
return 0;
- /* Enable physical balance only if more than 1 physical processor is present */
+ /*
+ * Enable physical balance only if more than 1 physical processor
+ * is present
+ */
if (smp_num_siblings > 1 && cpu_online_map >> 2)
physical_balance = 1;
@@ -1150,11 +1167,8 @@
enable_8259A_irq(0);
}
-void __init UNEXPECTED_IO_APIC(void)
+static inline void UNEXPECTED_IO_APIC(void)
{
- printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n");
- printk(KERN_WARNING " http://bugzilla.kernel.org\n");
- printk(KERN_WARNING " if your kernel is less than 3 months old.\n");
}
void __init print_IO_APIC(void)
@@ -1566,7 +1580,7 @@
*/
static int __init timer_irq_works(void)
{
- unsigned int t1 = jiffies;
+ unsigned long t1 = jiffies;
local_irq_enable();
/* Let ten ticks pass... */
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/irq.c Mon Mar 17 13:45:09 2003
@@ -135,43 +135,47 @@
{
int i, j;
struct irqaction * action;
+ unsigned long flags;
seq_printf(p, " ");
for (j=0; jtypename);
seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
+
seq_putc(p, '\n');
+skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
}
seq_printf(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
- p += seq_printf(p, "%10u ", nmi_count(j));
+ seq_printf(p, "%10u ", nmi_count(j));
seq_putc(p, '\n');
#if CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
for (j = 0; j < NR_CPUS; j++)
if (cpu_online(j))
- p += seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
+ seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs);
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
--- a/arch/i386/kernel/microcode.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/microcode.c Mon Mar 17 13:45:09 2003
@@ -372,7 +372,6 @@
ret = (ssize_t)len;
}
out_fsize:
- devfs_set_file_size(devfs_handle, mc_fsize);
vfree(microcode);
out_unlock:
up_write(µcode_rwsem);
@@ -388,7 +387,6 @@
if (mc_applied) {
int bytes = NR_CPUS * sizeof(struct microcode);
- devfs_set_file_size(devfs_handle, 0);
kfree(mc_applied);
mc_applied = NULL;
printk(KERN_INFO "microcode: freed %d bytes\n", bytes);
diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
--- a/arch/i386/kernel/numaq.c Mon Mar 17 13:45:14 2003
+++ b/arch/i386/kernel/numaq.c Mon Mar 17 13:45:14 2003
@@ -31,8 +31,7 @@
#include
/* These are needed before the pgdat's are created */
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern long node_start_pfn[], node_end_pfn[];
#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
@@ -64,26 +63,6 @@
}
}
}
-
-/*
- * -----------------------------------------
- *
- * functions related to physnode_map
- *
- * -----------------------------------------
- */
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id. so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(physnode_map);
/*
* for each node mark the regions
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c Mon Mar 17 13:45:08 2003
+++ b/arch/i386/kernel/process.c Mon Mar 17 13:45:08 2003
@@ -275,6 +275,15 @@
release_x86_irqs(dead_task);
}
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+ unlazy_fpu(tsk);
+}
+
int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
unsigned long unused,
struct task_struct * p, struct pt_regs * regs)
@@ -297,9 +306,6 @@
savesegment(gs,p->thread.gs);
tsk = current;
- unlazy_fpu(tsk);
- struct_cpy(&p->thread.i387, &tsk->thread.i387);
-
if (unlikely(NULL != tsk->thread.ts_io_bitmap)) {
p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!p->thread.ts_io_bitmap)
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/kernel/setup.c Mon Mar 17 13:45:12 2003
@@ -525,8 +525,11 @@
* "mem=nopentium" disables the 4MB page tables.
* "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
* to , overriding the bios size.
- * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+ * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
* to +, overriding the bios size.
+ *
+ * HPA tells me bootloaders need to parse mem=, so no new
+ * option should be mem= [also see Documentation/i386/boot.txt]
*/
if (c == ' ' && !memcmp(from, "mem=", 4)) {
if (to != command_line)
@@ -535,8 +538,26 @@
from += 9+4;
clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
disable_pse = 1;
- } else if (!memcmp(from+4, "exactmap", 8)) {
- from += 8+4;
+ } else {
+ /* If the user specifies memory size, we
+ * limit the BIOS-provided memory map to
+ * that size. exactmap can be used to specify
+ * the exact map. mem=number can be used to
+ * trim the existing memory map.
+ */
+ unsigned long long mem_size;
+
+ mem_size = memparse(from+4, &from);
+ limit_regions(mem_size);
+ userdef=1;
+ }
+ }
+
+ if (c == ' ' && !memcmp(from, "memmap=", 7)) {
+ if (to != command_line)
+ to--;
+ if (!memcmp(from+7, "exactmap", 8)) {
+ from += 8+7;
e820.nr_map = 0;
userdef = 1;
} else {
@@ -548,7 +569,7 @@
*/
unsigned long long start_at, mem_size;
- mem_size = memparse(from+4, &from);
+ mem_size = memparse(from+7, &from);
if (*from == '@') {
start_at = memparse(from+1, &from);
add_memory_region(start_at, mem_size, E820_RAM);
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
--- a/arch/i386/kernel/smpboot.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/kernel/smpboot.c Mon Mar 17 13:45:12 2003
@@ -966,6 +966,7 @@
if (APIC_init_uniprocessor())
printk(KERN_NOTICE "Local APIC not detected."
" Using dummy APIC emulation.\n");
+ map_cpu_to_logical_apicid();
return;
}
diff -Nru a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
--- a/arch/i386/kernel/srat.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/srat.c Mon Mar 17 13:45:09 2003
@@ -57,8 +57,7 @@
static int zholes_size_init;
static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+extern unsigned long node_start_pfn[], node_end_pfn[];
extern void * boot_ioremap(unsigned long, unsigned long);
@@ -182,30 +181,19 @@
}
}
-/*
- * physnode_map keeps track of the physical memory layout of the
- * numaq nodes on a 256Mb break (each element of the array will
- * represent 256Mb of memory and will be marked by the node id. so,
- * if the first gig is on node 0, and the second gig is on node 1
- * physnode_map will contain:
- * physnode_map[0-3] = 0;
- * physnode_map[4-7] = 1;
- * physnode_map[8- ] = -1;
- */
-int pfnnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
-EXPORT_SYMBOL(pfnnode_map);
-
-static void __init initialize_pfnnode_map(void)
+static void __init initialize_physnode_map(void)
{
- unsigned long topofchunk, cur = 0;
int i;
-
- for (i = 0; i < num_memory_chunks; i++) {
- cur = node_memory_chunk[i].start_pfn;
- topofchunk = node_memory_chunk[i].end_pfn;
- while (cur < topofchunk) {
- pfnnode_map[PFN_TO_ELEMENT(cur)] = node_memory_chunk[i].nid;
- cur ++;
+ unsigned long pfn;
+ struct node_memory_chunk_s *nmcp;
+
+ /* Run the list of memory chunks and fill in the phymap. */
+ nmcp = node_memory_chunk;
+ for (i = num_memory_chunks; --i >= 0; nmcp++) {
+ for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn;
+ pfn += PAGES_PER_ELEMENT)
+ {
+ physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid;
}
}
}
@@ -272,7 +260,7 @@
for (i = 0; i < num_memory_chunks; i++)
node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
- initialize_pfnnode_map();
+ initialize_physnode_map();
printk("pxm bitmap: ");
for (i = 0; i < sizeof(pxm_bitmap); i++) {
diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
--- a/arch/i386/kernel/sysenter.c Mon Mar 17 13:45:15 2003
+++ b/arch/i386/kernel/sysenter.c Mon Mar 17 13:45:15 2003
@@ -40,8 +40,10 @@
int cpu = get_cpu();
struct tss_struct *tss = init_tss + cpu;
+ tss->ss1 = __KERNEL_CS;
+ tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
- wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0);
+ wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0);
wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0);
printk("Enabling SEP on CPU %d\n", cpu);
diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
--- a/arch/i386/kernel/traps.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/traps.c Mon Mar 17 13:45:09 2003
@@ -737,13 +737,14 @@
*/
asmlinkage void math_state_restore(struct pt_regs regs)
{
- struct task_struct *tsk = current;
- clts(); /* Allow maths ops (or we recurse) */
+ struct thread_info *thread = current_thread_info();
+ struct task_struct *tsk = thread->task;
+ clts(); /* Allow maths ops (or we recurse) */
if (!tsk->used_math)
init_fpu(tsk);
restore_fpu(tsk);
- set_thread_flag(TIF_USEDFPU); /* So we fnsave on switch_to() */
+ thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
}
#ifndef CONFIG_MATH_EMULATION
diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c
--- a/arch/i386/kernel/vm86.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/kernel/vm86.c Mon Mar 17 13:45:09 2003
@@ -291,7 +291,7 @@
tss = init_tss + smp_processor_id();
tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
- disable_sysenter();
+ disable_sysenter(tss);
tsk->thread.screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
--- a/arch/i386/mm/discontig.c Mon Mar 17 13:45:13 2003
+++ b/arch/i386/mm/discontig.c Mon Mar 17 13:45:13 2003
@@ -36,11 +36,36 @@
struct pglist_data *node_data[MAX_NUMNODES];
bootmem_data_t node0_bdata;
+/*
+ * numa interface - we expect the numa architecture specfic code to have
+ * populated the following initialisation.
+ *
+ * 1) numnodes - the total number of nodes configured in the system
+ * 2) physnode_map - the mapping between a pfn and owning node
+ * 3) node_start_pfn - the starting page frame number for a node
+ * 3) node_end_pfn - the ending page fram number for a node
+ */
+
+/*
+ * physnode_map keeps track of the physical memory layout of a generic
+ * numa node on a 256Mb break (each element of the array will
+ * represent 256Mb of memory and will be marked by the node id. so,
+ * if the first gig is on node 0, and the second gig is on node 1
+ * physnode_map will contain:
+ *
+ * physnode_map[0-3] = 0;
+ * physnode_map[4-7] = 1;
+ * physnode_map[8- ] = -1;
+ */
+u8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+
+unsigned long node_start_pfn[MAX_NUMNODES];
+unsigned long node_end_pfn[MAX_NUMNODES];
+
extern unsigned long find_max_low_pfn(void);
extern void find_max_pfn(void);
extern void one_highpage_init(struct page *, int, int);
-extern unsigned long node_start_pfn[], node_end_pfn[];
extern struct e820map e820;
extern char _end;
extern unsigned long highend_pfn, highstart_pfn;
@@ -55,6 +80,36 @@
unsigned long node_remap_offset[MAX_NUMNODES];
void *node_remap_start_vaddr[MAX_NUMNODES];
void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
+
+/*
+ * FLAT - support for basic PC memory model with discontig enabled, essentially
+ * a single node with all available processors in it with a flat
+ * memory map.
+ */
+void __init get_memcfg_numa_flat(void)
+{
+ int pfn;
+
+ printk("NUMA - single node, flat memory mode\n");
+
+ /* Run the memory configuration and find the top of memory. */
+ find_max_pfn();
+ node_start_pfn[0] = 0;
+ node_end_pfn[0] = max_pfn;
+
+ /* Fill in the physnode_map with our simplistic memory model,
+ * all memory is in node 0.
+ */
+ for (pfn = node_start_pfn[0]; pfn <= node_end_pfn[0];
+ pfn += PAGES_PER_ELEMENT)
+ {
+ physnode_map[pfn / PAGES_PER_ELEMENT] = 0;
+ }
+
+ /* Indicate there is one node available. */
+ node_set_online(0);
+ numnodes = 1;
+}
/*
* Find the highest page frame number we have available for the node
diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c Mon Mar 17 13:45:08 2003
+++ b/arch/i386/mm/fault.c Mon Mar 17 13:45:08 2003
@@ -394,14 +394,14 @@
* Do _not_ use "tsk" here. We might be inside
* an interrupt in the middle of a task switch..
*/
- int offset = __pgd_offset(address);
+ int index = pgd_index(address);
pgd_t *pgd, *pgd_k;
pmd_t *pmd, *pmd_k;
pte_t *pte_k;
asm("movl %%cr3,%0":"=r" (pgd));
- pgd = offset + (pgd_t *)__va(pgd);
- pgd_k = init_mm.pgd + offset;
+ pgd = index + (pgd_t *)__va(pgd);
+ pgd_k = init_mm.pgd + index;
if (!pgd_present(*pgd_k))
goto no_context;
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c Mon Mar 17 13:45:14 2003
+++ b/arch/i386/mm/init.c Mon Mar 17 13:45:14 2003
@@ -98,26 +98,26 @@
{
pgd_t *pgd;
pmd_t *pmd;
- int pgd_ofs, pmd_ofs;
+ int pgd_idx, pmd_idx;
unsigned long vaddr;
vaddr = start;
- pgd_ofs = __pgd_offset(vaddr);
- pmd_ofs = __pmd_offset(vaddr);
- pgd = pgd_base + pgd_ofs;
+ pgd_idx = pgd_index(vaddr);
+ pmd_idx = pmd_index(vaddr);
+ pgd = pgd_base + pgd_idx;
- for ( ; (pgd_ofs < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_ofs++) {
+ for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
if (pgd_none(*pgd))
one_md_table_init(pgd);
pmd = pmd_offset(pgd, vaddr);
- for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) {
+ for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
if (pmd_none(*pmd))
one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
- pmd_ofs = 0;
+ pmd_idx = 0;
}
}
@@ -132,17 +132,17 @@
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- int pgd_ofs, pmd_ofs, pte_ofs;
+ int pgd_idx, pmd_idx, pte_ofs;
- pgd_ofs = __pgd_offset(PAGE_OFFSET);
- pgd = pgd_base + pgd_ofs;
+ pgd_idx = pgd_index(PAGE_OFFSET);
+ pgd = pgd_base + pgd_idx;
pfn = 0;
- for (; pgd_ofs < PTRS_PER_PGD; pgd++, pgd_ofs++) {
+ for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
pmd = one_md_table_init(pgd);
if (pfn >= max_low_pfn)
continue;
- for (pmd_ofs = 0; pmd_ofs < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_ofs++) {
+ for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
/* Map with big pages if possible, otherwise create normal page tables. */
if (cpu_has_pse) {
set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
@@ -214,7 +214,7 @@
vaddr = PKMAP_BASE;
page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
- pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pgd = swapper_pg_dir + pgd_index(vaddr);
pmd = pmd_offset(pgd, vaddr);
pte = pte_offset_kernel(pmd, vaddr);
pkmap_page_table = pte;
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c Mon Mar 17 13:45:10 2003
+++ b/arch/i386/mm/ioremap.c Mon Mar 17 13:45:10 2003
@@ -148,7 +148,7 @@
*/
offset = phys_addr & ~PAGE_MASK;
phys_addr &= PAGE_MASK;
- size = PAGE_ALIGN(last_addr) - phys_addr;
+ size = PAGE_ALIGN(last_addr+1) - phys_addr;
/*
* Ok, go for it..
diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
--- a/arch/i386/mm/pgtable.c Mon Mar 17 13:45:16 2003
+++ b/arch/i386/mm/pgtable.c Mon Mar 17 13:45:16 2003
@@ -64,7 +64,7 @@
pmd_t *pmd;
pte_t *pte;
- pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pgd = swapper_pg_dir + pgd_index(vaddr);
if (pgd_none(*pgd)) {
BUG();
return;
@@ -104,7 +104,7 @@
printk ("set_pmd_pfn: pfn misaligned\n");
return; /* BUG(); */
}
- pgd = swapper_pg_dir + __pgd_offset(vaddr);
+ pgd = swapper_pg_dir + pgd_index(vaddr);
if (pgd_none(*pgd)) {
printk ("set_pmd_pfn: pgd_none\n");
return; /* BUG(); */
diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
--- a/arch/i386/oprofile/nmi_int.c Mon Mar 17 13:45:15 2003
+++ b/arch/i386/oprofile/nmi_int.c Mon Mar 17 13:45:15 2003
@@ -58,7 +58,7 @@
unsigned int const nr_ctrls = model->num_controls;
struct op_msr_group * counters = &msrs->counters;
struct op_msr_group * controls = &msrs->controls;
- int i;
+ unsigned int i;
for (i = 0; i < nr_ctrs; ++i) {
rdmsr(counters->addrs[i],
@@ -108,7 +108,7 @@
unsigned int const nr_ctrls = model->num_controls;
struct op_msr_group * counters = &msrs->counters;
struct op_msr_group * controls = &msrs->controls;
- int i;
+ unsigned int i;
for (i = 0; i < nr_ctrls; ++i) {
wrmsr(controls->addrs[i],
@@ -182,7 +182,7 @@
static int nmi_create_files(struct super_block * sb, struct dentry * root)
{
- int i;
+ unsigned int i;
for (i = 0; i < model->num_counters; ++i) {
struct dentry * dir;
diff -Nru a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
--- a/arch/i386/oprofile/op_model_athlon.c Mon Mar 17 13:45:14 2003
+++ b/arch/i386/oprofile/op_model_athlon.c Mon Mar 17 13:45:14 2003
@@ -104,10 +104,11 @@
if (CTR_OVERFLOWED(low)) {
oprofile_add_sample(eip, is_kernel, i, cpu);
CTR_WRITE(reset_value[i], msrs, i);
- return 1;
}
}
- return 0;
+
+ /* See op_model_ppro.c */
+ return 1;
}
diff -Nru a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
--- a/arch/i386/oprofile/op_model_p4.c Mon Mar 17 13:45:09 2003
+++ b/arch/i386/oprofile/op_model_p4.c Mon Mar 17 13:45:09 2003
@@ -389,7 +389,7 @@
static void p4_fill_in_addresses(struct op_msrs * const msrs)
{
- int i;
+ unsigned int i;
unsigned int addr, stag;
setup_num_counters();
@@ -608,13 +608,14 @@
CTR_WRITE(reset_value[i], real);
/* P4 quirk: you have to re-unmask the apic vector */
apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
- return 1;
}
}
/* P4 quirk: you have to re-unmask the apic vector */
apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
- return 0;
+
+ /* See op_model_ppro.c */
+ return 1;
}
diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
--- a/arch/i386/oprofile/op_model_ppro.c Mon Mar 17 13:45:13 2003
+++ b/arch/i386/oprofile/op_model_ppro.c Mon Mar 17 13:45:13 2003
@@ -98,10 +98,17 @@
if (CTR_OVERFLOWED(low)) {
oprofile_add_sample(eip, is_kernel, i, cpu);
CTR_WRITE(reset_value[i], msrs, i);
- return 1;
}
}
- return 0;
+
+ /* We can't work out if we really handled an interrupt. We
+ * might have caught a *second* counter just after overflowing
+ * the interrupt for this counter then arrives
+ * and we don't find a counter that's overflowed, so we
+ * would return 0 and get dazed + confused. Instead we always
+ * assume we found an overflow. This sucks.
+ */
+ return 1;
}
diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c
--- a/arch/i386/pci/common.c Mon Mar 17 13:45:12 2003
+++ b/arch/i386/pci/common.c Mon Mar 17 13:45:12 2003
@@ -90,11 +90,6 @@
}
}
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}
-
/*
* Called after each bus is probed, but before its children
* are examined.
diff -Nru a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
--- a/arch/i386/pci/i386.c Mon Mar 17 13:45:10 2003
+++ b/arch/i386/pci/i386.c Mon Mar 17 13:45:10 2003
@@ -33,34 +33,6 @@
#include "pci.h"
-void
-pcibios_update_resource(struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- u32 new, check;
- int reg;
-
- new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
- if (resource < 6) {
- reg = PCI_BASE_ADDRESS_0 + 4*resource;
- } else if (resource == PCI_ROM_RESOURCE) {
- res->flags |= PCI_ROM_ADDRESS_ENABLE;
- new |= PCI_ROM_ADDRESS_ENABLE;
- reg = dev->rom_base_reg;
- } else {
- /* Somebody might have asked allocation of a non-standard resource */
- return;
- }
-
- pci_write_config_dword(dev, reg, new);
- pci_read_config_dword(dev, reg, &check);
- if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
- printk(KERN_ERR "PCI: Error while updating region "
- "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
- new, check);
- }
-}
-
/*
* We need to avoid collisions with `mirrored' VGA ports
* and other strange ISA hardware, so we always want the
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c Mon Mar 17 13:45:15 2003
+++ b/arch/i386/pci/irq.c Mon Mar 17 13:45:15 2003
@@ -804,6 +804,7 @@
int pirq_enable_irq(struct pci_dev *dev)
{
u8 pin;
+ extern int interrupt_line_quirk;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
char *msg;
@@ -813,9 +814,17 @@
msg = "";
else
msg = " Please try using pci=biosirq.";
+
+ /* With IDE legacy devices the IRQ lookup failure is not a problem.. */
+ if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
+ return 0;
+
printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
'A' + pin - 1, dev->slot_name, msg);
}
-
+ /* VIA bridges use interrupt line for apic/pci steering across
+ the V-Link */
+ else if (interrupt_line_quirk)
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
return 0;
}
diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S
--- a/arch/i386/vmlinux.lds.S Mon Mar 17 13:45:09 2003
+++ b/arch/i386/vmlinux.lds.S Mon Mar 17 13:45:09 2003
@@ -74,6 +74,9 @@
*(.initcall7.init)
}
__initcall_end = .;
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/Kconfig Mon Mar 17 13:45:15 2003
@@ -22,11 +22,7 @@
bool
default y
-config SWAP
- bool
- default y
-
-config RWSEM_GENERIC_SPINLOCK
+config RWSEM_XCHGADD_ALGORITHM
bool
default y
@@ -424,6 +420,18 @@
If you don't know what to do here, say N.
+config PREEMPT
+ bool "Preemptible Kernel"
+ help
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+ This allows applications to run more reliably even when the system is
+ under load.
+
+ Say Y here if you are building a kernel for a desktop, embedded
+ or real-time system. Say N if you are unsure.
+
config IA32_SUPPORT
bool "Support running of Linux/x86 binaries"
help
@@ -874,6 +882,12 @@
and certain other kinds of spinlock errors commonly made. This is
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
+
+config DEBUG_SPINLOCK_SLEEP
+ bool "Sleep-inside-spinlock checking"
+ help
+ If you say Y here, various routines which may sleep will become very
+ noisy if they are called with a spinlock held.
config IA64_DEBUG_CMPXCHG
bool "Turn on compare-and-exchange bug checking (slow!)"
diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile Mon Mar 17 13:45:09 2003
+++ b/arch/ia64/Makefile Mon Mar 17 13:45:09 2003
@@ -52,18 +52,19 @@
core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/
core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/kernel/ \
arch/ia64/sn/io/ \
+ arch/ia64/sn/io/sn2/ \
+ arch/ia64/sn/io/sn2/pcibr/ \
arch/ia64/sn/kernel/sn2/
drivers-$(CONFIG_PCI) += arch/ia64/pci/
drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/
drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/
-drivers-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/fakeprom/
boot := arch/ia64/boot
tools := arch/ia64/tools
.PHONY: boot compressed include/asm-ia64/offsets.h
-all: vmlinux
+all: prepare vmlinux
compressed: vmlinux.gz
diff -Nru a/arch/ia64/boot/Makefile b/arch/ia64/boot/Makefile
--- a/arch/ia64/boot/Makefile Mon Mar 17 13:45:13 2003
+++ b/arch/ia64/boot/Makefile Mon Mar 17 13:45:13 2003
@@ -8,16 +8,14 @@
# Copyright (C) 1998 by David Mosberger-Tang
#
-EXTRA_TARGETS := vmlinux.bin vmlinux.gz
-
targets-$(CONFIG_IA64_HP_SIM) += bootloader
targets-$(CONFIG_IA64_GENERIC) += bootloader
-EXTRA_TARGETS += $(sort $(targets-y))
+targets := vmlinux.bin vmlinux.gz $(targets-y)
quiet_cmd_cptotop = LN $@
cmd_cptotop = ln -f $< $@
-vmlinux.gz: $(obj)/vmlinux.gz $(targets-y)
+vmlinux.gz: $(obj)/vmlinux.gz $(addprefix $(obj)/,$(targets-y))
$(call cmd,cptotop)
@echo ' Kernel: $@ is ready'
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/hp/sim/simscsi.c Mon Mar 17 13:45:12 2003
@@ -156,7 +156,7 @@
if (sc->request_bufflen < req.len)
return;
- stat.fd = desc[sc->target];
+ stat.fd = desc[sc->device->id];
if (DBG)
printk("simscsi_%s @ %lx (off %lx)\n",
mode == SSC_READ ? "read":"write", req.addr, offset);
@@ -178,7 +178,7 @@
struct disk_stat stat;
struct disk_req req;
- stat.fd = desc[sc->target];
+ stat.fd = desc[sc->device->id];
while (list_len) {
req.addr = __pa(page_address(sl->page) + sl->offset);
@@ -259,6 +259,7 @@
int
simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
{
+ unsigned int target_id = sc->device->id;
char fname[MAX_ROOT_LEN+16];
size_t disk_size;
char *buf;
@@ -267,21 +268,21 @@
if (DBG)
printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n",
- sc->target, sc->cmnd[0], sc->serial_number, sp, done);
+ target_id, sc->cmnd[0], sc->serial_number, sp, done);
#endif
sc->result = DID_BAD_TARGET << 16;
sc->scsi_done = done;
- if (sc->target <= 15 && sc->lun == 0) {
+ if (target_id <= 15 && sc->device->lun == 0) {
switch (sc->cmnd[0]) {
case INQUIRY:
if (sc->request_bufflen < 35) {
break;
}
- sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
- desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
- 0, 0, SSC_OPEN);
- if (desc[sc->target] < 0) {
+ sprintf (fname, "%s%c", simscsi_root, 'a' + target_id);
+ desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
+ 0, 0, SSC_OPEN);
+ if (desc[target_id] < 0) {
/* disk doesn't exist... */
break;
}
@@ -303,37 +304,37 @@
break;
case READ_6:
- if (desc[sc->target] < 0 )
+ if (desc[target_id] < 0 )
break;
simscsi_readwrite6(sc, SSC_READ);
break;
case READ_10:
- if (desc[sc->target] < 0 )
+ if (desc[target_id] < 0 )
break;
simscsi_readwrite10(sc, SSC_READ);
break;
case WRITE_6:
- if (desc[sc->target] < 0)
+ if (desc[target_id] < 0)
break;
simscsi_readwrite6(sc, SSC_WRITE);
break;
case WRITE_10:
- if (desc[sc->target] < 0)
+ if (desc[target_id] < 0)
break;
simscsi_readwrite10(sc, SSC_WRITE);
break;
case READ_CAPACITY:
- if (desc[sc->target] < 0 || sc->request_bufflen < 8) {
+ if (desc[target_id] < 0 || sc->request_bufflen < 8) {
break;
}
buf = sc->request_buffer;
- disk_size = simscsi_get_disk_size(desc[sc->target]);
+ disk_size = simscsi_get_disk_size(desc[target_id]);
/* pretend to be a 1GB disk (partition table contains real stuff): */
buf[0] = (disk_size >> 24) & 0xff;
diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
--- a/arch/ia64/hp/sim/simserial.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/hp/sim/simserial.c Mon Mar 17 13:45:12 2003
@@ -63,7 +63,6 @@
static char *serial_name = "SimSerial driver";
static char *serial_version = "0.6";
-static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
/*
* This has been extracted from asm/serial.h. We need one eventually but
@@ -235,14 +234,14 @@
if (!tty || !info->xmit.buf) return;
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
return;
}
info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
}
static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
@@ -250,7 +249,8 @@
int count;
unsigned long flags;
- spin_lock_irqsave(&serial_lock, flags);
+
+ local_irq_save(flags);
if (info->x_char) {
char c = info->x_char;
@@ -293,7 +293,7 @@
info->xmit.tail += count;
}
out:
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
}
static void rs_flush_chars(struct tty_struct *tty)
@@ -334,7 +334,7 @@
break;
}
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
{
c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
SERIAL_XMIT_SIZE);
@@ -344,7 +344,7 @@
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
}
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
buf += c;
count -= c;
@@ -352,7 +352,7 @@
}
up(&tmp_buf_sem);
} else {
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
if (count < c)
@@ -367,7 +367,7 @@
count -= c;
ret += c;
}
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
}
/*
* Hey, we transmit directly from here in our case
@@ -398,9 +398,9 @@
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
info->xmit.head = info->xmit.tail = 0;
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
wake_up_interruptible(&tty->write_wait);
@@ -573,7 +573,7 @@
state->irq);
#endif
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
{
/*
* First unlink the serial port from the IRQ chain...
@@ -611,7 +611,7 @@
info->flags &= ~ASYNC_INITIALIZED;
}
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
}
/*
@@ -634,13 +634,13 @@
state = info->state;
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
if (tty_hung_up_p(filp)) {
#ifdef SIMSERIAL_DEBUG
printk("rs_close: hung_up\n");
#endif
MOD_DEC_USE_COUNT;
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
return;
}
#ifdef SIMSERIAL_DEBUG
@@ -665,11 +665,11 @@
}
if (state->count) {
MOD_DEC_USE_COUNT;
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
/*
* Now we wait for the transmit buffer to clear; and we notify
@@ -776,7 +776,7 @@
if (!page)
return -ENOMEM;
- spin_lock_irqsave(&serial_lock, flags);
+ local_irq_save(flags);
if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
@@ -857,11 +857,11 @@
}
info->flags |= ASYNC_INITIALIZED;
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
return 0;
errout:
- spin_unlock_irqrestore(&serial_lock, flags);
+ local_irq_restore(flags);
return retval;
}
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S Mon Mar 17 13:45:13 2003
+++ b/arch/ia64/ia32/ia32_entry.S Mon Mar 17 13:45:13 2003
@@ -300,7 +300,7 @@
data8 compat_sys_statfs
data8 compat_sys_fstatfs /* 100 */
data8 sys32_ioperm
- data8 sys32_socketcall
+ data8 compat_sys_socketcall
data8 sys_syslog
data8 compat_sys_setitimer
data8 compat_sys_getitimer /* 105 */
@@ -424,6 +424,26 @@
data8 sys_ni_syscall /* reserved for Security */
data8 sys_gettid
data8 sys_readahead /* 225 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 230 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 235 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 compat_sys_futex /* 240 */
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall
+ data8 sys_ni_syscall /* 245 */
data8 sys_ni_syscall
data8 sys_ni_syscall
data8 sys_ni_syscall
diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
--- a/arch/ia64/ia32/ia32_ioctl.c Mon Mar 17 13:45:14 2003
+++ b/arch/ia64/ia32/ia32_ioctl.c Mon Mar 17 13:45:14 2003
@@ -97,11 +97,9 @@
int info; /* [o] auxiliary information */
} sg_io_hdr32_t; /* 64 bytes long (on IA32) */
-struct iovec32 { unsigned int iov_base; int iov_len; };
-
static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
- struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
+ struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
sg_iovec_t *kiov;
int i;
@@ -136,7 +134,7 @@
static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
{
- struct iovec32 *uiov = (struct iovec32 *) P(uptr32);
+ struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
int i;
diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
--- a/arch/ia64/ia32/ia32_support.c Mon Mar 17 13:45:09 2003
+++ b/arch/ia64/ia32/ia32_support.c Mon Mar 17 13:45:09 2003
@@ -93,7 +93,7 @@
{
unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
struct pt_regs *regs = ia64_task_regs(t);
- int nr = smp_processor_id(); /* LDT and TSS depend on CPU number: */
+ int nr = get_cpu(); /* LDT and TSS depend on CPU number: */
eflag = t->thread.eflag;
fsr = t->thread.fsr;
@@ -119,6 +119,7 @@
regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17;
regs->r30 = load_desc(_LDT(nr)); /* LDTD */
+ put_cpu();
}
/*
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c Mon Mar 17 13:45:13 2003
+++ b/arch/ia64/ia32/sys_ia32.c Mon Mar 17 13:45:13 2003
@@ -924,12 +924,11 @@
(struct compat_timeval *) A(a.tvp));
}
-struct iovec32 { unsigned int iov_base; int iov_len; };
asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);
asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);
static struct iovec *
-get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type)
+get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type)
{
int i;
u32 buf, len;
@@ -939,7 +938,7 @@
if (!count)
return 0;
- if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))
+ if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count))
return NULL;
if (count > UIO_MAXIOV)
return NULL;
@@ -971,14 +970,14 @@
}
asmlinkage long
-sys32_readv (int fd, struct iovec32 *vector, u32 count)
+sys32_readv (int fd, struct compat_iovec *vector, u32 count)
{
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov;
long ret;
mm_segment_t old_fs = get_fs();
- iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);
+ iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE);
if (!iov)
return -EFAULT;
set_fs(KERNEL_DS);
@@ -990,14 +989,14 @@
}
asmlinkage long
-sys32_writev (int fd, struct iovec32 *vector, u32 count)
+sys32_writev (int fd, struct compat_iovec *vector, u32 count)
{
struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov;
long ret;
mm_segment_t old_fs = get_fs();
- iov = get_iovec32(vector, iovstack, count, VERIFY_READ);
+ iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ);
if (!iov)
return -EFAULT;
set_fs(KERNEL_DS);
@@ -1080,701 +1079,6 @@
}
/*
- * Declare the IA32 version of the msghdr
- */
-
-struct msghdr32 {
- unsigned int msg_name; /* Socket name */
- int msg_namelen; /* Length of name */
- unsigned int msg_iov; /* Data blocks */
- unsigned int msg_iovlen; /* Number of blocks */
- unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
- unsigned int msg_controllen; /* Length of cmsg list */
- unsigned msg_flags;
-};
-
-struct cmsghdr32 {
- compat_size_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
-};
-
-/* Bleech... */
-#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
-#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
-#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
-#define CMSG32_DATA(cmsg) \
- ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
-#define CMSG32_SPACE(len) \
- (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
-#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
-#define __CMSG32_FIRSTHDR(ctl,len) \
- ((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL)
-#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-
-static inline struct cmsghdr32 *
-__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len)
-{
- struct cmsghdr32 * ptr;
-
- ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len));
- if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size)
- return NULL;
- return ptr;
-}
-
-static inline struct cmsghdr32 *
-cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len)
-{
- return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len);
-}
-
-static inline int
-get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32)
-{
- int ret;
- unsigned int i;
-
- if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))
- return -EFAULT;
- ret = __get_user(i, &mp32->msg_name);
- mp->msg_name = (void *)A(i);
- ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);
- ret |= __get_user(i, &mp32->msg_iov);
- mp->msg_iov = (struct iovec *)A(i);
- ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);
- ret |= __get_user(i, &mp32->msg_control);
- mp->msg_control = (void *)A(i);
- ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);
- ret |= __get_user(mp->msg_flags, &mp32->msg_flags);
- return ret ? -EFAULT : 0;
-}
-
-/*
- * There is a lot of hair here because the alignment rules (and thus placement) of cmsg
- * headers and length are different for 32-bit apps. -DaveM
- */
-static int
-get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize)
-{
- struct cmsghdr *kcmsg, *kcmsg_base;
- __kernel_size_t kcmlen, tmp;
- compat_size_t ucmlen;
- struct cmsghdr32 *ucmsg;
- long err;
-
- kcmlen = 0;
- kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
- ucmsg = CMSG32_FIRSTHDR(kmsg);
- while (ucmsg != NULL) {
- if (get_user(ucmlen, &ucmsg->cmsg_len))
- return -EFAULT;
-
- /* Catch bogons. */
- if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32)))
- return -EINVAL;
- if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen)
- > kmsg->msg_controllen)
- return -EINVAL;
-
- tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
- CMSG_ALIGN(sizeof(struct cmsghdr)));
- kcmlen += tmp;
- ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
- }
- if (kcmlen == 0)
- return -EINVAL;
-
- /*
- * The kcmlen holds the 64-bit version of the control length. It may not be
- * modified as we do not stick it into the kmsg until we have successfully copied
- * over all of the data from the user.
- */
- if (kcmlen > *bufsize) {
- *bufsize = kcmlen;
- kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
- }
- if (kcmsg == NULL)
- return -ENOBUFS;
-
- /* Now copy them over neatly. */
- memset(kcmsg, 0, kcmlen);
- ucmsg = CMSG32_FIRSTHDR(kmsg);
- while (ucmsg != NULL) {
- err = get_user(ucmlen, &ucmsg->cmsg_len);
- tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
- CMSG_ALIGN(sizeof(struct cmsghdr)));
- kcmsg->cmsg_len = tmp;
- err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
- err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
-
- /* Copy over the data. */
- err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg),
- (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))));
- if (err)
- goto out_free_efault;
-
- /* Advance. */
- kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
- ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
- }
-
- /* Ok, looks like we made it. Hook it up and return success. */
- kmsg->msg_control = kcmsg_base;
- kmsg->msg_controllen = kcmlen;
- return 0;
-
-out_free_efault:
- if (kcmsg_base != (struct cmsghdr *)stackbuf)
- sock_kfree_s(sk, kcmsg_base, kcmlen);
- return -EFAULT;
-}
-
-/*
- * Verify & re-shape IA32 iovec. The caller must ensure that the
- * iovec is big enough to hold the re-shaped message iovec.
- *
- * Save time not doing verify_area. copy_*_user will make this work
- * in any case.
- *
- * Don't need to check the total size for overflow (cf net/core/iovec.c),
- * 32-bit sizes can't overflow a 64-bit count.
- */
-
-static inline int
-verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode)
-{
- int size, err, ct;
- struct iovec32 *iov32;
-
- if (m->msg_namelen) {
- if (mode == VERIFY_READ) {
- err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
- if (err < 0)
- goto out;
- }
- m->msg_name = address;
- } else
- m->msg_name = NULL;
-
- err = -EFAULT;
- size = m->msg_iovlen * sizeof(struct iovec32);
- if (copy_from_user(iov, m->msg_iov, size))
- goto out;
- m->msg_iov = iov;
-
- err = 0;
- iov32 = (struct iovec32 *)iov;
- for (ct = m->msg_iovlen; ct-- > 0; ) {
- iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;
- iov[ct].iov_base = (void *) A(iov32[ct].iov_base);
- err += iov[ct].iov_len;
- }
-out:
- return err;
-}
-
-static void
-put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data)
-{
- struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
- struct cmsghdr32 cmhdr;
- int cmlen = CMSG32_LEN(len);
-
- if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
- kmsg->msg_flags |= MSG_CTRUNC;
- return;
- }
-
- if(kmsg->msg_controllen < cmlen) {
- kmsg->msg_flags |= MSG_CTRUNC;
- cmlen = kmsg->msg_controllen;
- }
- cmhdr.cmsg_level = level;
- cmhdr.cmsg_type = type;
- cmhdr.cmsg_len = cmlen;
-
- if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
- return;
- if(copy_to_user(CMSG32_DATA(cm), data,
- cmlen - sizeof(struct cmsghdr32)))
- return;
- cmlen = CMSG32_SPACE(len);
- kmsg->msg_control += cmlen;
- kmsg->msg_controllen -= cmlen;
-}
-
-static void
-scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm)
-{
- struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
- int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32))
- / sizeof(int);
- int fdnum = scm->fp->count;
- struct file **fp = scm->fp->fp;
- int *cmfptr;
- int err = 0, i;
-
- if (fdnum < fdmax)
- fdmax = fdnum;
-
- for (i = 0, cmfptr = (int *) CMSG32_DATA(cm);
- i < fdmax;
- i++, cmfptr++) {
- int new_fd;
- err = get_unused_fd();
- if (err < 0)
- break;
- new_fd = err;
- err = put_user(new_fd, cmfptr);
- if (err) {
- put_unused_fd(new_fd);
- break;
- }
- /* Bump the usage count and install the file. */
- get_file(fp[i]);
- current->files->fd[new_fd] = fp[i];
- }
-
- if (i > 0) {
- int cmlen = CMSG32_LEN(i * sizeof(int));
- if (!err)
- err = put_user(SOL_SOCKET, &cm->cmsg_level);
- if (!err)
- err = put_user(SCM_RIGHTS, &cm->cmsg_type);
- if (!err)
- err = put_user(cmlen, &cm->cmsg_len);
- if (!err) {
- cmlen = CMSG32_SPACE(i * sizeof(int));
- kmsg->msg_control += cmlen;
- kmsg->msg_controllen -= cmlen;
- }
- }
- if (i < fdnum)
- kmsg->msg_flags |= MSG_CTRUNC;
-
- /*
- * All of the files that fit in the message have had their
- * usage counts incremented, so we just free the list.
- */
- __scm_destroy(scm);
-}
-
-/*
- * In these cases we (currently) can just copy to data over verbatim because all CMSGs
- * created by the kernel have well defined types which have the same layout in both the
- * 32-bit and 64-bit API. One must add some special cased conversions here if we start
- * sending control messages with incompatible types.
- *
- * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
- * we do our work. The remaining cases are:
- *
- * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean
- * IP_TTL int 32-bit clean
- * IP_TOS __u8 32-bit clean
- * IP_RECVOPTS variable length 32-bit clean
- * IP_RETOPTS variable length 32-bit clean
- * (these last two are clean because the types are defined
- * by the IPv4 protocol)
- * IP_RECVERR struct sock_extended_err +
- * struct sockaddr_in 32-bit clean
- * SOL_IPV6 IPV6_RECVERR struct sock_extended_err +
- * struct sockaddr_in6 32-bit clean
- * IPV6_PKTINFO struct in6_pktinfo 32-bit clean
- * IPV6_HOPLIMIT int 32-bit clean
- * IPV6_FLOWINFO u32 32-bit clean
- * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean
- * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean
- * IPV6_RTHDR ipv6 routing exthdr 32-bit clean
- * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean
- */
-static void
-cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
-{
- unsigned char *workbuf, *wp;
- unsigned long bufsz, space_avail;
- struct cmsghdr *ucmsg;
- long err;
-
- bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
- space_avail = kmsg->msg_controllen + bufsz;
- wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
- if (workbuf == NULL)
- goto fail;
-
- /* To make this more sane we assume the kernel sends back properly
- * formatted control messages. Because of how the kernel will truncate
- * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
- */
- ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
- while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) {
- struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
- int clen64, clen32;
-
- /*
- * UCMSG is the 64-bit format CMSG entry in user-space. KCMSG32 is within
- * the kernel space temporary buffer we use to convert into a 32-bit style
- * CMSG.
- */
- err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
- err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
- err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
- if (err)
- goto fail2;
-
- clen64 = kcmsg32->cmsg_len;
- copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
- clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
- clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
- CMSG32_ALIGN(sizeof(struct cmsghdr32)));
- kcmsg32->cmsg_len = clen32;
-
- ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
- wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
- }
-
- /* Copy back fixed up data, and adjust pointers. */
- bufsz = (wp - workbuf);
- if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz))
- goto fail2;
-
- kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz);
- kmsg->msg_controllen = space_avail - bufsz;
- kfree(workbuf);
- return;
-
- fail2:
- kfree(workbuf);
- fail:
- /*
- * If we leave the 64-bit format CMSG chunks in there, the application could get
- * confused and crash. So to ensure greater recovery, we report no CMSGs.
- */
- kmsg->msg_controllen += bufsz;
- kmsg->msg_control = (void *) orig_cmsg_uptr;
-}
-
-/* XXX This really belongs in some header file... -DaveM */
-#define MAX_SOCK_ADDR 128 /* 108 for Unix domain -
- 16 for IP, 16 for IPX,
- 24 for IPv6,
- about 80 for AX.25 */
-/*
- * BSD sendmsg interface
- */
-
-int
-sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags)
-{
- struct socket *sock;
- char address[MAX_SOCK_ADDR];
- struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
- unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */
- unsigned char *ctl_buf = ctl;
- struct msghdr msg_sys;
- int err, iov_size, total_len;
- size_t ctl_len;
-
- err = -EFAULT;
- if (get_msghdr32(&msg_sys, msg))
- goto out;
-
- sock = sockfd_lookup(fd, &err);
- if (!sock)
- goto out;
-
- /* do not move before msg_sys is valid */
- err = -EINVAL;
- if (msg_sys.msg_iovlen > UIO_MAXIOV)
- goto out_put;
-
- /* Check whether to allocate the iovec area*/
- err = -ENOMEM;
- iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);
- if (msg_sys.msg_iovlen > UIO_FASTIOV) {
- iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
- if (!iov)
- goto out_put;
- }
-
- /* This will also move the address data into kernel space */
- err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);
- if (err < 0)
- goto out_freeiov;
- total_len = err;
-
- err = -ENOBUFS;
-
- if (msg_sys.msg_controllen > INT_MAX)
- goto out_freeiov;
- if (msg_sys.msg_controllen) {
- ctl_len = sizeof(ctl);
- err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len);
- if (err)
- goto out_freeiov;
- ctl_buf = msg_sys.msg_control;
- }
- msg_sys.msg_flags = flags;
-
- if (sock->file->f_flags & O_NONBLOCK)
- msg_sys.msg_flags |= MSG_DONTWAIT;
- err = sock_sendmsg(sock, &msg_sys, total_len);
-
- if (ctl_buf != ctl)
- sock_kfree_s(sock->sk, ctl_buf, ctl_len);
-out_freeiov:
- if (iov != iovstack)
- sock_kfree_s(sock->sk, iov, iov_size);
-out_put:
- sockfd_put(sock);
-out:
- return err;
-}
-
-/*
- * BSD recvmsg interface
- */
-
-int
-sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags)
-{
- struct socket *sock;
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov=iovstack;
- struct msghdr msg_sys;
- unsigned long cmsg_ptr;
- int err, iov_size, total_len, len;
-
- /* kernel mode address */
- char addr[MAX_SOCK_ADDR];
-
- /* user mode address pointers */
- struct sockaddr *uaddr;
- int *uaddr_len;
-
- err = -EFAULT;
- if (get_msghdr32(&msg_sys, msg))
- goto out;
-
- sock = sockfd_lookup(fd, &err);
- if (!sock)
- goto out;
-
- err = -EINVAL;
- if (msg_sys.msg_iovlen > UIO_MAXIOV)
- goto out_put;
-
- /* Check whether to allocate the iovec area*/
- err = -ENOMEM;
- iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);
- if (msg_sys.msg_iovlen > UIO_FASTIOV) {
- iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);
- if (!iov)
- goto out_put;
- }
-
- /*
- * Save the user-mode address (verify_iovec will change the
- * kernel msghdr to use the kernel address space)
- */
-
- uaddr = msg_sys.msg_name;
- uaddr_len = &msg->msg_namelen;
- err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);
- if (err < 0)
- goto out_freeiov;
- total_len=err;
-
- cmsg_ptr = (unsigned long)msg_sys.msg_control;
- msg_sys.msg_flags = 0;
-
- if (sock->file->f_flags & O_NONBLOCK)
- flags |= MSG_DONTWAIT;
-
- /* XXX This code needs massive updating... -DaveM */
- lock_kernel();
- {
- struct sock_iocb *si;
- struct kiocb iocb;
-
- init_sync_kiocb(&iocb, NULL);
- si = kiocb_to_siocb(&iocb);
- si->sock = sock;
- si->scm = &si->async_scm;
- si->msg = &msg_sys;
- si->size = total_len;
- si->flags = flags;
- memset(si->scm, 0, sizeof(*si->scm));
-
- err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len,
- flags, si->scm);
- if (-EIOCBQUEUED == err)
- err = wait_on_sync_kiocb(&iocb);
-
- if (err < 0)
- goto out_unlock_freeiov;
-
- len = err;
- if (!msg_sys.msg_control) {
- if (sock->passcred || si->scm->fp)
- msg_sys.msg_flags |= MSG_CTRUNC;
- if (si->scm->fp)
- __scm_destroy(si->scm);
- } else {
- /*
- * If recvmsg processing itself placed some control messages into
- * user space, it's is using 64-bit CMSG processing, so we need to
- * fix it up before we tack on more stuff.
- */
- if ((unsigned long) msg_sys.msg_control != cmsg_ptr)
- cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr);
-
- /* Wheee... */
- if (sock->passcred)
- put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS,
- sizeof(si->scm->creds),
- &si->scm->creds);
- if (si->scm->fp != NULL)
- scm_detach_fds32(&msg_sys, si->scm);
- }
- }
- unlock_kernel();
-
- if (uaddr != NULL) {
- err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);
- if (err < 0)
- goto out_freeiov;
- }
- err = __put_user(msg_sys.msg_flags, &msg->msg_flags);
- if (err)
- goto out_freeiov;
- err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,
- &msg->msg_controllen);
- if (err)
- goto out_freeiov;
- err = len;
-
- out_freeiov:
- if (iov != iovstack)
- sock_kfree_s(sock->sk, iov, iov_size);
- out_put:
- sockfd_put(sock);
- out:
- return err;
-
- out_unlock_freeiov:
- goto out_freeiov;
-}
-
-/* Argument list sizes for sys_socketcall */
-#define AL(x) ((x) * sizeof(u32))
-static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
- AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
- AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
-#undef AL
-
-extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
-extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,
- int addrlen);
-extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,
- int *upeer_addrlen);
-extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
- int *usockaddr_len);
-extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
- int *usockaddr_len);
-extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
-extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
- unsigned flags, u32 addr, int addr_len);
-extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
-extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
- unsigned flags, u32 addr, u32 addr_len);
-extern asmlinkage long sys_setsockopt(int fd, int level, int optname,
- char *optval, int optlen);
-extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
- u32 optval, u32 optlen);
-
-extern asmlinkage long sys_socket(int family, int type, int protocol);
-extern asmlinkage long sys_socketpair(int family, int type, int protocol,
- int usockvec[2]);
-extern asmlinkage long sys_shutdown(int fd, int how);
-extern asmlinkage long sys_listen(int fd, int backlog);
-
-asmlinkage long
-sys32_socketcall (int call, u32 *args)
-{
- int ret;
- u32 a[6];
- u32 a0,a1;
-
- if (callSYS_RECVMSG)
- return -EINVAL;
- if (copy_from_user(a, args, nas[call]))
- return -EFAULT;
- a0=a[0];
- a1=a[1];
-
- switch(call)
- {
- case SYS_SOCKET:
- ret = sys_socket(a0, a1, a[2]);
- break;
- case SYS_BIND:
- ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
- break;
- case SYS_CONNECT:
- ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
- break;
- case SYS_LISTEN:
- ret = sys_listen(a0, a1);
- break;
- case SYS_ACCEPT:
- ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
- break;
- case SYS_GETSOCKNAME:
- ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
- break;
- case SYS_GETPEERNAME:
- ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
- break;
- case SYS_SOCKETPAIR:
- ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
- break;
- case SYS_SEND:
- ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
- break;
- case SYS_SENDTO:
- ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
- break;
- case SYS_RECV:
- ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
- break;
- case SYS_RECVFROM:
- ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
- break;
- case SYS_SHUTDOWN:
- ret = sys_shutdown(a0,a1);
- break;
- case SYS_SETSOCKOPT:
- ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
- a[4]);
- break;
- case SYS_GETSOCKOPT:
- ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
- break;
- case SYS_SENDMSG:
- ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]);
- break;
- case SYS_RECVMSG:
- ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]);
- break;
- default:
- ret = EINVAL;
- break;
- }
- return ret;
-}
-
-/*
* sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
*
* This is really horribly ugly.
@@ -3151,6 +2455,7 @@
asmlinkage long
sys32_sysctl (struct sysctl32 *args)
{
+#ifdef CONFIG_SYSCTL
struct sysctl32 a32;
mm_segment_t old_fs = get_fs ();
void *oldvalp, *newvalp;
@@ -3188,6 +2493,9 @@
return -EFAULT;
return ret;
+#else
+ return -ENOSYS;
+#endif
}
asmlinkage long
@@ -3433,8 +2741,12 @@
u32 bufferram;
u32 totalswap;
u32 freeswap;
- unsigned short procs;
- char _f[22];
+ u16 procs;
+ u16 pad;
+ u32 totalhigh;
+ u32 freehigh;
+ u32 mem_unit;
+ char _f[8];
};
asmlinkage long
@@ -3463,6 +2775,9 @@
err |= __put_user(s.totalswap, &info->totalswap);
err |= __put_user(s.freeswap, &info->freeswap);
err |= __put_user(s.procs, &info->procs);
+ err |= __put_user (s.totalhigh, &info->totalhigh);
+ err |= __put_user (s.freehigh, &info->freehigh);
+ err |= __put_user (s.mem_unit, &info->mem_unit);
if (err)
return -EFAULT;
return ret;
diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
--- a/arch/ia64/kernel/Makefile Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/kernel/Makefile Mon Mar 17 13:45:15 2003
@@ -2,7 +2,7 @@
# Makefile for the linux kernel.
#
-EXTRA_TARGETS := head.o init_task.o
+extra-y := head.o init_task.o
obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o \
irq.o irq_ia64.o irq_lsapic.o ivt.o \
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/kernel/acpi.c Mon Mar 17 13:45:12 2003
@@ -55,6 +55,7 @@
asm (".weak iosapic_override_isa_irq");
asm (".weak iosapic_register_platform_intr");
asm (".weak iosapic_init");
+asm (".weak iosapic_system_init");
asm (".weak iosapic_version");
void (*pm_idle) (void);
@@ -182,7 +183,9 @@
#define ACPI_MAX_PLATFORM_INTERRUPTS 256
/* Array to record platform interrupt vectors for generic interrupt routing. */
-int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };
+int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = {
+ [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1
+};
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
@@ -291,40 +294,6 @@
static int __init
-acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address)
-{
- struct acpi_table_iosapic *iosapic;
- int ver;
- int max_pin;
- char *p;
- char *end;
-
- if (!gsi_base || !iosapic_address)
- return -ENODEV;
-
- p = (char *) (acpi_madt + 1);
- end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt));
-
- while (p < end) {
- if (*p == ACPI_MADT_IOSAPIC) {
- iosapic = (struct acpi_table_iosapic *) p;
-
- *gsi_base = iosapic->global_irq_base;
- *iosapic_address = ioremap(iosapic->address, 0);
-
- ver = iosapic_version(*iosapic_address);
- max_pin = (ver >> 16) & 0xff;
-
- if ((gsi - *gsi_base) <= max_pin)
- return 0; /* Found it! */
- }
- p += p[1];
- }
- return -ENODEV;
-}
-
-
-static int __init
acpi_parse_iosapic (acpi_table_entry_header *header)
{
struct acpi_table_iosapic *iosapic;
@@ -335,16 +304,9 @@
acpi_table_print_madt_entry(header);
- if (iosapic_init) {
-#ifndef CONFIG_ITANIUM
- /* PCAT_COMPAT flag indicates dual-8259 setup */
- iosapic_init(iosapic->address, iosapic->global_irq_base,
- acpi_madt->flags.pcat_compat);
-#else
- /* Firmware on old Itanium systems is broken */
- iosapic_init(iosapic->address, iosapic->global_irq_base, 1);
-#endif
- }
+ if (iosapic_init)
+ iosapic_init(iosapic->address, iosapic->global_irq_base);
+
return 0;
}
@@ -354,8 +316,6 @@
{
struct acpi_table_plat_int_src *plintsrc;
int vector;
- u32 gsi_base;
- char *iosapic_address;
plintsrc = (struct acpi_table_plat_int_src *) header;
if (!plintsrc)
@@ -368,11 +328,6 @@
return -ENODEV;
}
- if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) {
- printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
- return -ENODEV;
- }
-
/*
* Get vector assignment for this interrupt, set attributes,
* and program the IOSAPIC routing table.
@@ -382,10 +337,8 @@
plintsrc->iosapic_vector,
plintsrc->eid,
plintsrc->id,
- (plintsrc->flags.polarity == 1) ? 1 : 0,
- (plintsrc->flags.trigger == 1) ? 1 : 0,
- gsi_base,
- iosapic_address);
+ (plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+ (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
platform_intr_list[plintsrc->type] = vector;
return 0;
@@ -408,8 +361,8 @@
return 0;
iosapic_override_isa_irq(p->bus_irq, p->global_irq,
- (p->flags.polarity == 1) ? 1 : 0,
- (p->flags.trigger == 1) ? 1 : 0);
+ (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+ (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
return 0;
}
@@ -439,7 +392,13 @@
acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
/* remember the value for reference after free_initmem() */
+#ifdef CONFIG_ITANIUM
+ has_8259 = 1; /* Firmware on old Itanium systems is broken */
+#else
has_8259 = acpi_madt->flags.pcat_compat;
+#endif
+ if (iosapic_system_init)
+ iosapic_system_init(has_8259);
/* Get base address of IPI Message Block */
@@ -571,7 +530,7 @@
}
void __init
-acpi_numa_arch_fixup(void)
+acpi_numa_arch_fixup (void)
{
int i, j, node_from, node_to;
@@ -618,7 +577,7 @@
if (!pxm_bit_test(j))
continue;
node_to = pxm_to_nid_map[j];
- node_distance(node_from, node_to) =
+ node_distance(node_from, node_to) =
slit_table->entry[i*slit_table->localities + j];
}
}
@@ -639,8 +598,7 @@
{
struct acpi_table_header *fadt_header;
struct fadt_descriptor_rev2 *fadt;
- u32 sci_irq, gsi_base;
- char *iosapic_address;
+ u32 sci_irq;
if (!phys_addr || !size)
return -EINVAL;
@@ -662,8 +620,7 @@
if (has_8259 && sci_irq < 16)
return 0; /* legacy, no setup required */
- if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address))
- iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address);
+ iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
return 0;
}
@@ -717,8 +674,6 @@
if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
(spcr->int_type == ACPI_SERIAL_INT_SAPIC))
{
- u32 gsi_base;
- char *iosapic_address;
int vector;
/* We have a UART in memory space with an SAPIC interrupt */
@@ -728,11 +683,7 @@
(spcr->global_int[1] << 8) |
(spcr->global_int[0]) );
- /* Which iosapic does this interrupt belong to? */
-
- if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
- vector = iosapic_register_intr(gsi, 1, 1,
- gsi_base, iosapic_address);
+ vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
}
return 0;
}
@@ -741,7 +692,7 @@
int __init
-acpi_boot_init (char *cmdline)
+acpi_boot_init (void)
{
/*
@@ -812,20 +763,20 @@
smp_boot_data.cpu_count = total_cpus;
smp_build_cpu_map();
-#ifdef CONFIG_NUMA
+# ifdef CONFIG_NUMA
build_cpu_to_node_map();
-#endif
+# endif
#endif
/* Make boot-up look pretty */
printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
return 0;
}
+/*
+ * PCI Interrupt Routing
+ */
-/* --------------------------------------------------------------------------
- PCI Interrupt Routing
- -------------------------------------------------------------------------- */
-
+#ifdef CONFIG_PCI
int __init
acpi_get_prt (struct pci_vector_struct **vectors, int *count)
{
@@ -866,6 +817,7 @@
*count = acpi_prt.count;
return 0;
}
+#endif /* CONFIG_PCI */
/* Assume IA64 always use I/O SAPIC */
@@ -888,12 +840,10 @@
return gsi_to_vector(irq);
}
-int __init
+int
acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
{
int vector = 0;
- u32 irq_base;
- char *iosapic_address;
if (acpi_madt->flags.pcat_compat && (gsi < 16))
return isa_irq_to_vector(gsi);
@@ -901,12 +851,9 @@
if (!iosapic_register_intr)
return 0;
- /* Find the IOSAPIC */
- if (!acpi_find_iosapic(gsi, &irq_base, &iosapic_address)) {
- /* Turn it on */
- vector = iosapic_register_intr (gsi, polarity, trigger,
- irq_base, iosapic_address);
- }
+ /* Turn it on */
+ vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
+ trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
return vector;
}
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S Mon Mar 17 13:45:10 2003
+++ b/arch/ia64/kernel/entry.S Mon Mar 17 13:45:10 2003
@@ -586,10 +586,21 @@
// work.need_resched etc. mustn't get changed by this CPU before it returns to
// user- or fsys-mode:
(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk
+#ifdef CONFIG_PREEMPT
+ rsm psr.i // disable interrupts
+ adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+ ;;
+(pKStk) ld4 r21=[r20] // preempt_count ->r21
+ ;;
+(pKStk) cmp4.eq p6,p0=r21,r0 // p6 <- preempt_count == 0
+ ;;
+#else /* CONFIG_PREEMPT */
(pUStk) rsm psr.i
;;
(pUStk) adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
;;
+#endif /* CONFIG_PREEMPT */
.work_processed:
(p6) ld4 r18=[r17] // load current_thread_info()->flags
adds r2=PT(R8)+16,r12
@@ -701,7 +712,7 @@
* NOTE: alloc, loadrs, and cover can't be predicated.
*/
(pNonSys) br.cond.dpnt dont_preserve_current_frame
- cover // add current frame into dirty partition
+ cover // add current frame into dirty partition and set cr.ifs
;;
mov r19=ar.bsp // get new backing store pointer
sub r16=r16,r18 // krbs = old bsp - size of dirty partition
@@ -727,7 +738,7 @@
# define Nregs 14
#endif
alloc loc0=ar.pfs,2,Nregs-2,2,0
- shr.u loc1=r18,9 // RNaTslots <= dirtySize / (64*8) + 1
+ shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8))
sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize
;;
mov ar.rsc=r19 // load ar.rsc to be used for "loadrs"
@@ -774,13 +785,13 @@
;;
mov loc3=0
mov loc4=0
- mov loc9=0
mov loc5=0
mov loc6=0
+ mov loc7=0
(pRecurse) br.call.sptk.many b6=rse_clear_invalid
;;
- mov loc7=0
mov loc8=0
+ mov loc9=0
cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret
mov loc10=0
mov loc11=0
@@ -810,15 +821,27 @@
.work_pending:
tbit.z p6,p0=r18,TIF_NEED_RESCHED // current_thread_info()->need_resched==0?
(p6) br.cond.sptk.few .notify
+#ifdef CONFIG_PREEMPT
+(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1
+ ;;
+(pKStk) st4 [r20]=r21
+ ssm psr.i // enable interrupts
+#endif
+
#if __GNUC__ < 3
br.call.spnt.many rp=invoke_schedule
#else
br.call.spnt.many rp=schedule
#endif
.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1
- rsm psr.i
+ rsm psr.i // disable interrupts
;;
adds r17=TI_FLAGS+IA64_TASK_SIZE,r13
+#if CONFIG_PREEMPT
+(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13
+ ;;
+(pKStk) st4 [r20]=r0 // preempt_count() <- 0
+#endif
br.cond.sptk.many .work_processed // re-check
.notify:
@@ -904,13 +927,14 @@
mov r9=ar.unat
mov loc0=rp // save return address
mov out0=0 // there is no "oldset"
- adds out1=0,sp // out1=&sigscratch
+ adds out1=8,sp // out1=&sigscratch->ar_pfs
(pSys) mov out2=1 // out2==1 => we're in a syscall
;;
(pNonSys) mov out2=0 // out2==0 => not a syscall
.fframe 16
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
+ st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
.body
br.call.sptk.many rp=do_notify_resume_user
.ret15: .restore sp
@@ -931,11 +955,12 @@
mov loc0=rp // save return address
mov out0=in0 // mask
mov out1=in1 // sigsetsize
- adds out2=0,sp // out2=&sigscratch
+ adds out2=8,sp // out2=&sigscratch->ar_pfs
;;
.fframe 16
.spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
+ st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
br.call.sptk.many rp=ia64_rt_sigsuspend
.ret17: .restore sp
@@ -1242,7 +1267,7 @@
data8 sys_sched_setaffinity
data8 sys_sched_getaffinity
data8 sys_set_tid_address
- data8 ia64_ni_syscall
+ data8 sys_fadvise64
data8 ia64_ni_syscall // 1235
data8 sys_exit_group
data8 sys_lookup_dcookie
@@ -1256,15 +1281,15 @@
data8 sys_epoll_wait // 1245
data8 sys_restart_syscall
data8 sys_semtimedop
- data8 ia64_ni_syscall
- data8 ia64_ni_syscall
- data8 ia64_ni_syscall // 1250
- data8 ia64_ni_syscall
- data8 ia64_ni_syscall
- data8 ia64_ni_syscall
- data8 ia64_ni_syscall
- data8 ia64_ni_syscall // 1255
- data8 ia64_ni_syscall
+ data8 sys_timer_create
+ data8 sys_timer_settime
+ data8 sys_timer_gettime // 1250
+ data8 sys_timer_getoverrun
+ data8 sys_timer_delete
+ data8 sys_clock_settime
+ data8 sys_clock_gettime
+ data8 sys_clock_getres // 1255
+ data8 sys_clock_nanosleep
data8 ia64_ni_syscall
data8 ia64_ni_syscall
data8 ia64_ni_syscall
diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
--- a/arch/ia64/kernel/fsys.S Mon Mar 17 13:45:08 2003
+++ b/arch/ia64/kernel/fsys.S Mon Mar 17 13:45:08 2003
@@ -3,11 +3,16 @@
*
* Copyright (C) 2003 Hewlett-Packard Co
* David Mosberger-Tang
+ *
+ * 18-Feb-03 louisk Implement fsys_gettimeofday().
+ * 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more,
+ * probably broke it along the way... ;-)
*/
#include
#include
#include
+#include
#include
/*
@@ -123,6 +128,183 @@
br.ret.sptk.many b6
END(fsys_set_tid_address)
+/*
+ * Note 1: This routine uses floating-point registers, but only with registers that
+ * operate on integers. Because of that, we don't need to set ar.fpsr to the
+ * kernel default value.
+ *
+ * Note 2: For now, we will assume that all CPUs run at the same clock-frequency.
+ * If that wasn't the case, we would have to disable preemption (e.g.,
+ * by disabling interrupts) between reading the ITC and reading
+ * local_cpu_data->nsec_per_cyc.
+ *
+ * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector,
+ * we ought to either skip the ITC-based interpolation or run an ntp-like
+ * daemon to keep the ITCs from drifting too far apart.
+ */
+ENTRY(fsys_gettimeofday)
+ add r9=TI_FLAGS+IA64_TASK_SIZE,r16
+ movl r3=THIS_CPU(cpu_info)
+
+ mov.m r31=ar.itc // put time stamp into r31 (ITC) == now (35 cyc)
+ movl r19=xtime // xtime is a timespec struct
+ ;;
+
+#ifdef CONFIG_SMP
+ movl r10=__per_cpu_offset
+ ;;
+ ld8 r10=[r10] // r10 <- __per_cpu_offset[0]
+ movl r21=cpu_info__per_cpu
+ ;;
+ add r10=r21, r10 // r10 <- &cpu_data(time_keeper_id)
+#else
+ mov r10=r3
+#endif
+ ld4 r9=[r9]
+ movl r17=xtime_lock
+ ;;
+
+ // r32, r33 should contain the 2 args of gettimeofday
+ adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10
+ mov r2=-1
+ tnat.nz p6,p7=r32 // guard against NaT args
+ ;;
+
+ adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10
+(p7) tnat.nz p6,p0=r33
+(p6) br.cond.spnt.few .fail
+
+ adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3
+ movl r24=2361183241434822607 // for division hack (only for / 1000)
+ ;;
+
+ ldf8 f7=[r10] // f7 now contains itm_delta
+ setf.sig f11=r2
+ adds r10=8, r32
+
+ adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19 // r20 = &xtime->tv_nsec
+ movl r26=jiffies
+
+ setf.sig f9=r24 // f9 is used for division hack
+ movl r27=wall_jiffies
+
+ and r9=TIF_ALLWORK_MASK,r9
+ movl r25=last_nsec_offset
+ ;;
+
+ /*
+ * Verify that we have permission to write to struct timeval. Note:
+ * Another thread might unmap the mapping before we actually get
+ * to store the result. That's OK as long as the stores are also
+ * protect by EX().
+ */
+EX(.fail, probe.w.fault r32, 3) // this must come _after_ NaT-check
+EX(.fail, probe.w.fault r10, 3) // this must come _after_ NaT-check
+ nop 0
+
+ ldf8 f10=[r8] // f10 <- local_cpu_data->nsec_per_cyc value
+ cmp.ne p8, p0=0, r9
+(p8) br.spnt.many fsys_fallback_syscall
+ ;;
+.retry: // *** seq = read_seqbegin(&xtime_lock); ***
+ ld4.acq r23=[r17] // since &xtime_lock == &xtime_lock->sequence
+ ld8 r14=[r25] // r14 (old) = last_nsec_offset
+
+ ld8 r28=[r26] // r28 = jiffies
+ ld8 r29=[r27] // r29 = wall_jiffies
+ ;;
+
+ ldf8 f8=[r21] // f8 now contains itm_next
+ sub r28=r29, r28, 1 // r28 now contains "-(lost + 1)"
+ tbit.nz p9, p10=r23, 0 // p9 <- is_odd(r23), p10 <- is_even(r23)
+ ;;
+
+ ld8 r2=[r19] // r2 = sec = xtime.tv_sec
+ ld8 r29=[r20] // r29 = nsec = xtime.tv_nsec
+
+ setf.sig f6=r28 // f6 <- -(lost + 1) (6 cyc)
+ ;;
+
+ mf
+ xma.l f8=f6, f7, f8 // f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next (5 cyc)
+ nop 0
+
+ setf.sig f12=r31 // f12 <- ITC (6 cyc)
+ // *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; ***
+ ld4 r24=[r17] // r24 = xtime_lock->sequence (re-read)
+ nop 0
+ ;;
+
+ mov r31=ar.itc // re-read ITC in case we .retry (35 cyc)
+ xma.l f8=f11, f8, f12 // f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick)
+ nop 0
+ ;;
+
+ getf.sig r18=f8 // r18 <- (now - last_tick)
+ xmpy.l f8=f8, f10 // f8 <- elapsed_cycles*nsec_per_cyc (5 cyc)
+ add r3=r29, r14 // r3 = (nsec + old)
+ ;;
+
+ cmp.lt p7, p8=r18, r0 // if now < last_tick, set p7 = 1, p8 = 0
+ getf.sig r18=f8 // r18 = elapsed_cycles*nsec_per_cyc (6 cyc)
+ nop 0
+ ;;
+
+(p10) cmp.ne p9, p0=r23, r24 // if xtime_lock->sequence != seq, set p9
+ shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT // r18 <- offset
+(p9) br.spnt.many .retry
+ ;;
+
+ mov ar.ccv=r14 // ar.ccv = old (1 cyc)
+ cmp.leu p7, p8=r18, r14 // if (offset <= old), set p7 = 1, p8 = 0
+ ;;
+
+(p8) cmpxchg8.rel r24=[r25], r18, ar.ccv // compare-and-exchange (atomic!)
+(p8) add r3=r29, r18 // r3 = (nsec + offset)
+ ;;
+ shr.u r3=r3, 3 // initiate dividing r3 by 1000
+ ;;
+ setf.sig f8=r3 // (6 cyc)
+ mov r10=1000000 // r10 = 1000000
+ ;;
+(p8) cmp.ne.unc p9, p0=r24, r14
+ xmpy.hu f6=f8, f9 // (5 cyc)
+(p9) br.spnt.many .retry
+ ;;
+
+ getf.sig r3=f6 // (6 cyc)
+ ;;
+ shr.u r3=r3, 4 // end of division, r3 is divided by 1000 (=usec)
+ ;;
+
+1: cmp.geu p7, p0=r3, r10 // while (usec >= 1000000)
+ ;;
+(p7) sub r3=r3, r10 // usec -= 1000000
+(p7) adds r2=1, r2 // ++sec
+(p7) br.spnt.many 1b
+
+ // finally: r2 = sec, r3 = usec
+EX(.fail, st8 [r32]=r2)
+ adds r9=8, r32
+ mov r8=r0 // success
+ ;;
+EX(.fail, st8 [r9]=r3) // store them in the timeval struct
+ mov r10=0
+ MCKINLEY_E9_WORKAROUND
+ br.ret.sptk.many b6 // return to caller
+ /*
+ * Note: We are NOT clearing the scratch registers here. Since the only things
+ * in those registers are time-related variables and some addresses (which
+ * can be obtained from System.map), none of this should be security-sensitive
+ * and we should be fine.
+ */
+
+.fail: adds r8=EINVAL, r0 // r8 = EINVAL
+ adds r10=-1, r0 // r10 = -1
+ MCKINLEY_E9_WORKAROUND
+ br.ret.spnt.many b6 // return with r8 set to EINVAL
+END(fsys_gettimeofday)
+
.rodata
.align 8
.globl fsyscall_table
@@ -190,7 +372,7 @@
data8 fsys_fallback_syscall // setrlimit
data8 fsys_fallback_syscall // getrlimit // 1085
data8 fsys_fallback_syscall // getrusage
- data8 fsys_fallback_syscall // gettimeofday
+ data8 fsys_gettimeofday // gettimeofday
data8 fsys_fallback_syscall // settimeofday
data8 fsys_fallback_syscall // select
data8 fsys_fallback_syscall // poll // 1090
diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S
--- a/arch/ia64/kernel/gate.S Mon Mar 17 13:45:14 2003
+++ b/arch/ia64/kernel/gate.S Mon Mar 17 13:45:14 2003
@@ -145,11 +145,12 @@
*/
#define SIGTRAMP_SAVES \
- .unwabi @svr4, 's' // mark this as a sigtramp handler (saves scratch regs) \
- .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF \
- .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF \
- .savesp pr, PR_OFF+SIGCONTEXT_OFF \
- .savesp rp, RP_OFF+SIGCONTEXT_OFF \
+ .unwabi @svr4, 's'; /* mark this as a sigtramp handler (saves scratch regs) */ \
+ .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF; \
+ .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF; \
+ .savesp pr, PR_OFF+SIGCONTEXT_OFF; \
+ .savesp rp, RP_OFF+SIGCONTEXT_OFF; \
+ .savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF; \
.vframesp SP_OFF+SIGCONTEXT_OFF
GLOBAL_ENTRY(ia64_sigtramp)
@@ -173,9 +174,7 @@
.spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF
(p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16)
back_from_setup_rbs:
-
- .spillreg ar.pfs, r8
- alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8
+ alloc r8=ar.pfs,0,0,3,0
ld8 out0=[base0],16 // load arg0 (signum)
adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1
;;
@@ -184,17 +183,12 @@
;;
ld8 out2=[base0] // load arg2 (sigcontextp)
ld8 gp=[r17] // get signal handler's global pointer
-
adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp
;;
.spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF
- st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp
- dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits
- adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
- ;;
- .spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF
- st8 [base0]=r8 // save CFM0
+ st8 [base0]=r9 // save sc_ar_bsp
adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp
+ adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp
;;
stf.spill [base0]=f6,32
stf.spill [base1]=f7,32
@@ -217,7 +211,6 @@
ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF
mov r14=ar.bsp
;;
- ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0
cmp.ne p8,p0=r14,r15 // do we need to restore the rbs?
(p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7)
;;
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/kernel/init_task.c Mon Mar 17 13:45:15 2003
@@ -17,6 +17,7 @@
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm);
/*
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/kernel/iosapic.c Mon Mar 17 13:45:12 2003
@@ -29,6 +29,9 @@
* 02/07/29 T. Kochi Allocate interrupt vectors dynamically
* 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.)
* 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code.
+ * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC.
+ * Remove iosapic_address & gsi_base from external interfaces.
+ * Rationalize __init/__devinit attributes.
*/
/*
* Here is what the interrupt logic between a PCI device and the kernel looks like:
@@ -111,16 +114,17 @@
char *addr; /* base address of IOSAPIC */
unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
unsigned short num_rte; /* number of RTE in this IOSAPIC */
- unsigned char pcat_compat; /* 8259 compatibility flag */
-} iosapic_lists[256] __devinitdata;
+} iosapic_lists[256];
-static int num_iosapic = 0;
+static int num_iosapic;
+
+static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */
/*
* Find an IOSAPIC associated with a GSI
*/
-static inline int __devinit
+static inline int
find_iosapic (unsigned int gsi)
{
int i;
@@ -423,7 +427,7 @@
* if the given vector is already owned by other,
* assign a new vector for the other and make the vector available
*/
-static void
+static void __init
iosapic_reassign_vector (int vector)
{
int new_vector;
@@ -443,50 +447,36 @@
static void
register_intr (unsigned int gsi, int vector, unsigned char delivery,
- unsigned long polarity, unsigned long edge_triggered,
- unsigned int gsi_base, char *iosapic_address)
+ unsigned long polarity, unsigned long trigger)
{
irq_desc_t *idesc;
struct hw_interrupt_type *irq_type;
int rte_index;
+ int index;
+ unsigned long gsi_base;
+ char *iosapic_address;
+
+ index = find_iosapic(gsi);
+ if (index < 0) {
+ printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi);
+ return;
+ }
+
+ iosapic_address = iosapic_lists[index].addr;
+ gsi_base = iosapic_lists[index].gsi_base;
rte_index = gsi - gsi_base;
iosapic_intr_info[vector].rte_index = rte_index;
- iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
+ iosapic_intr_info[vector].polarity = polarity;
iosapic_intr_info[vector].dmode = delivery;
+ iosapic_intr_info[vector].addr = iosapic_address;
+ iosapic_intr_info[vector].gsi_base = gsi_base;
+ iosapic_intr_info[vector].trigger = trigger;
- /*
- * In override, it may not provide addr/gsi_base. GSI is enough to
- * locate iosapic addr, gsi_base and rte_index by examining
- * gsi_base and num_rte of registered iosapics (tbd)
- */
-#ifndef OVERRIDE_DEBUG
- if (iosapic_address) {
- iosapic_intr_info[vector].addr = iosapic_address;
- iosapic_intr_info[vector].gsi_base = gsi_base;
- }
-#else
- if (iosapic_address) {
- if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address))
- printk(KERN_WARNING "warning: register_intr: diff IOSAPIC ADDRESS for "
- "GSI 0x%x, vector %d\n", gsi, vector);
- iosapic_intr_info[vector].addr = iosapic_address;
- if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) {
- printk(KERN_WARNING "warning: register_intr: diff GSI base 0x%x for "
- "GSI 0x%x, vector %d\n", gsi_base, gsi, vector);
- }
- iosapic_intr_info[vector].gsi_base = gsi_base;
- } else if (!iosapic_intr_info[vector].addr)
- printk(KERN_WARNING "warning: register_intr: invalid override for GSI 0x%x, "
- "vector %d\n", gsi, vector);
-#endif
- if (edge_triggered) {
- iosapic_intr_info[vector].trigger = IOSAPIC_EDGE;
+ if (trigger == IOSAPIC_EDGE)
irq_type = &irq_type_iosapic_edge;
- } else {
- iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL;
+ else
irq_type = &irq_type_iosapic_level;
- }
idesc = irq_desc(vector);
if (idesc->handler != irq_type) {
@@ -504,8 +494,7 @@
*/
int
iosapic_register_intr (unsigned int gsi,
- unsigned long polarity, unsigned long edge_triggered,
- unsigned int gsi_base, char *iosapic_address)
+ unsigned long polarity, unsigned long trigger)
{
int vector;
unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
@@ -515,11 +504,11 @@
vector = ia64_alloc_vector();
register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,
- polarity, edge_triggered, gsi_base, iosapic_address);
+ polarity, trigger);
printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
- gsi, (polarity ? "high" : "low"),
- (edge_triggered ? "edge" : "level"), dest, vector);
+ gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+ (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
/* program the IOSAPIC routing table */
set_rte(vector, dest);
@@ -530,11 +519,10 @@
* ACPI calls this when it finds an entry for a platform interrupt.
* Note that the irq_base and IOSAPIC address must be set in iosapic_init().
*/
-int
+int __init
iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
int iosapic_vector, u16 eid, u16 id,
- unsigned long polarity, unsigned long edge_triggered,
- unsigned int gsi_base, char *iosapic_address)
+ unsigned long polarity, unsigned long trigger)
{
unsigned char delivery;
int vector;
@@ -564,11 +552,11 @@
}
register_intr(gsi, vector, delivery, polarity,
- edge_triggered, gsi_base, iosapic_address);
+ trigger);
printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n",
- int_type, gsi, (polarity ? "high" : "low"),
- (edge_triggered ? "edge" : "level"), dest, vector);
+ int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
+ (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector);
/* program the IOSAPIC routing table */
set_rte(vector, dest);
@@ -580,54 +568,36 @@
* ACPI calls this when it finds an entry for a legacy ISA IRQ override.
* Note that the gsi_base and IOSAPIC address must be set in iosapic_init().
*/
-void
+void __init
iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
unsigned long polarity,
- unsigned long edge_triggered)
+ unsigned long trigger)
{
- int index, vector;
- unsigned int gsi_base;
- char *addr;
+ int vector;
unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
- index = find_iosapic(gsi);
-
- if (index < 0) {
- printk(KERN_ERR "ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n",
- isa_irq, gsi);
- return;
- }
-
vector = isa_irq_to_vector(isa_irq);
- addr = iosapic_lists[index].addr;
- gsi_base = iosapic_lists[index].gsi_base;
- register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered,
- gsi_base, addr);
+ register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);
DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n",
isa_irq, gsi,
- polarity ? "high" : "low", edge_triggered ? "edge" : "level",
+ polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level",
dest, vector);
/* program the IOSAPIC routing table */
set_rte(vector, dest);
}
-void __devinit
-iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat)
+void __init
+iosapic_system_init (int system_pcat_compat)
{
- int num_rte, vector;
- unsigned int isa_irq, ver;
- char *addr;
- static int first_time = 1;
+ int vector;
- if (first_time) {
- first_time = 0;
- for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
- iosapic_intr_info[vector].rte_index = -1; /* mark as unused */
- }
+ for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
+ iosapic_intr_info[vector].rte_index = -1; /* mark as unused */
+ pcat_compat = system_pcat_compat;
if (pcat_compat) {
/*
* Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
@@ -637,6 +607,14 @@
outb(0xff, 0xA1);
outb(0xff, 0x21);
}
+}
+
+void __init
+iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
+{
+ int num_rte;
+ unsigned int isa_irq, ver;
+ char *addr;
addr = ioremap(phys_addr, 0);
ver = iosapic_version(addr);
@@ -649,7 +627,6 @@
num_rte = ((ver >> 16) & 0xff) + 1;
iosapic_lists[num_iosapic].addr = addr;
- iosapic_lists[num_iosapic].pcat_compat = pcat_compat;
iosapic_lists[num_iosapic].gsi_base = gsi_base;
iosapic_lists[num_iosapic].num_rte = num_rte;
num_iosapic++;
@@ -658,30 +635,18 @@
(ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1);
if ((gsi_base == 0) && pcat_compat) {
- unsigned int dest = (ia64_get_lid() >> 16) & 0xffff;
/*
* Map the legacy ISA devices into the IOSAPIC data. Some of these may
* get reprogrammed later on with data from the ACPI Interrupt Source
* Override table.
*/
- for (isa_irq = 0; isa_irq < 16; ++isa_irq) {
- vector = isa_irq_to_vector(isa_irq);
-
- register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY,
- /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */
- 1, 1, gsi_base, addr);
-
- DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n",
- isa_irq, isa_irq, dest, vector);
-
- /* program the IOSAPIC routing table: */
- set_rte(vector, dest);
- }
+ for (isa_irq = 0; isa_irq < 16; ++isa_irq)
+ iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
}
}
-static void
+static void __init
fixup_vector (int vector, unsigned int gsi, const char *pci_id)
{
struct hw_interrupt_type *irq_type = &irq_type_iosapic_level;
@@ -731,10 +696,9 @@
{
struct acpi_prt_entry *entry;
struct list_head *node;
- unsigned int gsi, gsi_base;
- int index, vector, pcat_compat;
+ unsigned int gsi;
+ int vector;
char pci_id[16];
- char *addr;
list_for_each(node, &acpi_prt.entries) {
entry = list_entry(node, struct acpi_prt_entry, node);
@@ -748,23 +712,13 @@
vector = gsi_to_vector(gsi);
if (vector < 0) {
/* allocate a vector for this interrupt line */
- index = find_iosapic(gsi);
-
- if (index < 0) {
- printk(KERN_WARNING "IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi);
- continue;
- }
- addr = iosapic_lists[index].addr;
- gsi_base = iosapic_lists[index].gsi_base;
- pcat_compat = iosapic_lists[index].pcat_compat;
-
if (pcat_compat && (gsi < 16))
vector = isa_irq_to_vector(gsi);
else
/* new GSI; allocate a vector for it */
vector = ia64_alloc_vector();
- register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr);
+ register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL);
}
snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]",
entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin);
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c Mon Mar 17 13:45:14 2003
+++ b/arch/ia64/kernel/irq.c Mon Mar 17 13:45:14 2003
@@ -154,6 +154,7 @@
int i, j;
struct irqaction * action;
irq_desc_t *idesc;
+ unsigned long flags;
seq_puts(p, " ");
for (j=0; jlock, flags);
action = idesc->action;
if (!action)
- continue;
+ goto skip;
seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
@@ -176,10 +178,12 @@
#endif
seq_printf(p, " %14s", idesc->handler->typename);
seq_printf(p, " %s", action->name);
-
for (action=action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
+
seq_putc(p, '\n');
+skip:
+ spin_unlock_irqrestore(&idesc->lock, flags);
}
seq_puts(p, "NMI: ");
for (j = 0; j < NR_CPUS; j++)
@@ -340,12 +344,14 @@
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
- int cpu = smp_processor_id();
+ int cpu;
irq_desc_t *desc = irq_desc(irq);
struct irqaction * action;
unsigned int status;
irq_enter();
+ cpu = smp_processor_id();
+
kstat_cpu(cpu).irqs[irq]++;
if (desc->status & IRQ_PER_CPU) {
diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
--- a/arch/ia64/kernel/ivt.S Mon Mar 17 13:45:09 2003
+++ b/arch/ia64/kernel/ivt.S Mon Mar 17 13:45:09 2003
@@ -848,7 +848,7 @@
alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
;;
ld4 r8=[r14],8 // r8 == eax (syscall number)
- mov r15=230 // number of entries in ia32 system call table
+ mov r15=250 // number of entries in ia32 system call table
;;
cmp.ltu.unc p6,p7=r8,r15
ld4 out1=[r14],8 // r9 == ecx
diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
--- a/arch/ia64/kernel/machvec.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/kernel/machvec.c Mon Mar 17 13:45:12 2003
@@ -10,19 +10,6 @@
struct ia64_machine_vector ia64_mv;
-/*
- * Most platforms use this routine for mapping page frame addresses into a memory map
- * index.
- *
- * Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if
- * X is outside the identity mapped kernel space.
- */
-unsigned long
-map_nr_dense (unsigned long addr)
-{
- return (addr - PAGE_OFFSET) >> PAGE_SHIFT;
-}
-
static struct ia64_machine_vector *
lookup_machvec (const char *name)
{
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/kernel/mca.c Mon Mar 17 13:45:12 2003
@@ -825,7 +825,7 @@
plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
proc_ptr = &plog_ptr->proc_err;
- ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area);
+ ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
/* Clear the INIT SAL logs now that they have been saved in the OS buffer */
ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT);
@@ -1620,7 +1620,7 @@
* absent. Also, current implementations only allocate space for number of
* elements used. So we walk the data pointer from here on.
*/
- p_data = &slpi->cache_check_info[0];
+ p_data = &slpi->info[0];
/* Print the cache check information if any*/
for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++)
diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
--- a/arch/ia64/kernel/palinfo.c Mon Mar 17 13:45:09 2003
+++ b/arch/ia64/kernel/palinfo.c Mon Mar 17 13:45:09 2003
@@ -341,11 +341,11 @@
return 0;
}
- p += sprintf(p, "\nTLB walker : %s implemented\n" \
+ p += sprintf(p, "\nTLB walker : %simplemented\n" \
"Number of DTR : %d\n" \
"Number of ITR : %d\n" \
"TLB insertable page sizes : ",
- vm_info_1.pal_vm_info_1_s.vw ? "\b":"not",
+ vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
@@ -894,10 +894,12 @@
* in SMP mode, we may need to call another CPU to get correct
* information. PAL, by definition, is processor specific
*/
- if (f->req_cpu == smp_processor_id())
+ if (f->req_cpu == get_cpu())
len = (*palinfo_entries[f->func_id].proc_read)(page);
else
len = palinfo_handle_smp(f, page);
+
+ put_cpu();
if (len <= off+count) *eof = 1;
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/kernel/perfmon.c Mon Mar 17 13:45:15 2003
@@ -8,7 +8,7 @@
* Modifications by Stephane Eranian, Hewlett-Packard Co.
* Modifications by David Mosberger-Tang, Hewlett-Packard Co.
*
- * Copyright (C) 1999-2002 Hewlett Packard Co
+ * Copyright (C) 1999-2003 Hewlett Packard Co
* Stephane Eranian
* David Mosberger-Tang
*/
@@ -230,9 +230,15 @@
unsigned int protected:1; /* allow access to creator of context only */
unsigned int using_dbreg:1; /* using range restrictions (debug registers) */
unsigned int excl_idle:1; /* exclude idle task in system wide session */
- unsigned int reserved:23;
+ unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */
+ unsigned int reserved:21;
} pfm_context_flags_t;
+#define PFM_TRAP_REASON_NONE 0x0 /* default value */
+#define PFM_TRAP_REASON_BLOCKSIG 0x1 /* we need to block on overflow and signal user */
+#define PFM_TRAP_REASON_SIG 0x2 /* we simply need to signal user */
+#define PFM_TRAP_REASON_RESET 0x3 /* we need to reset PMDs */
+
/*
* perfmon context: encapsulates all the state of a monitoring session
* XXX: probably need to change layout
@@ -277,6 +283,7 @@
#define ctx_fl_protected ctx_flags.protected
#define ctx_fl_using_dbreg ctx_flags.using_dbreg
#define ctx_fl_excl_idle ctx_flags.excl_idle
+#define ctx_fl_trap_reason ctx_flags.trap_reason
/*
* global information about all sessions
@@ -1225,6 +1232,8 @@
ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0;
ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0;
ctx->ctx_fl_frozen = 0;
+ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
+
/*
* setting this flag to 0 here means, that the creator or the task that the
* context is being attached are granted access. Given that a context can only
@@ -1505,7 +1514,7 @@
unsigned long value, hw_value;
unsigned int cnum;
int i;
- int ret = 0;
+ int ret = -EINVAL;
/* we don't quite support this right now */
if (task != current) return -EINVAL;
@@ -1514,10 +1523,10 @@
* Cannot do anything before PMU is enabled
*/
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
+ preempt_disable();
/* XXX: ctx locking may be required here */
- ret = -EINVAL;
for (i = 0; i < count; i++, req++) {
@@ -1591,10 +1600,12 @@
ctx->ctx_used_pmds[0],
ctx->ctx_soft_pmds[cnum].reset_pmds[0]));
}
-
+ preempt_enable();
return 0;
abort_mission:
+ preempt_enable();
+
/*
* for now, we have only one possibility for error
*/
@@ -1639,6 +1650,7 @@
DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid));
for (i = 0; i < count; i++, req++) {
+ int me;
#if __GNUC__ < 3
foo = __get_user(cnum, &req->reg_num);
if (foo) return -EFAULT;
@@ -1666,13 +1678,16 @@
* PMU state is still in the local live register due to lazy ctxsw.
* If true, then we read directly from the registers.
*/
- if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){
+ me = get_cpu();
+ if (atomic_read(&ctx->ctx_last_cpu) == me){
ia64_srlz_d();
val = ia64_get_pmd(cnum);
DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val));
} else {
val = th->pmd[cnum];
}
+
+
if (PMD_IS_COUNTING(cnum)) {
/*
* XXX: need to check for overflow
@@ -1694,6 +1709,8 @@
PFM_REG_RETFLAG_SET(reg_flags, ret);
+ put_cpu();
+
DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n",
cnum, ret, val, ia64_get_pmc(cnum)));
@@ -1831,6 +1848,7 @@
ctx->ctx_fl_frozen,
ctx->ctx_ovfl_regs[0]));
+ preempt_disable();
pfm_reset_regs(ctx, ctx->ctx_ovfl_regs, PFM_PMD_LONG_RESET);
ctx->ctx_ovfl_regs[0] = 0UL;
@@ -1849,6 +1867,8 @@
/* simply unfreeze */
pfm_unfreeze_pmu();
+ preempt_enable();
+
return 0;
}
/* restart on another task */
@@ -1906,6 +1926,7 @@
ctx->ctx_fl_system, PMU_OWNER(),
current));
+ preempt_disable();
/* simply stop monitoring but not the PMU */
if (ctx->ctx_fl_system) {
@@ -1933,6 +1954,7 @@
*/
ia64_psr(regs)->up = 0;
}
+ preempt_enable();
return 0;
}
@@ -1945,6 +1967,7 @@
if (!CTX_IS_ENABLED(ctx)) return -EINVAL;
+ preempt_disable();
/*
* stop monitoring, freeze PMU, and save state in context
* this call will clear IA64_THREAD_PM_VALID for per-task sessions.
@@ -1965,6 +1988,7 @@
DBprintk(("enabling psr.sp for [%d]\n", current->pid));
ctx->ctx_flags.state = PFM_CTX_DISABLED;
+ preempt_enable();
return 0;
}
@@ -2314,6 +2338,7 @@
return -EINVAL;
}
+ preempt_disable();
if (ctx->ctx_fl_system) {
PFM_CPUINFO_SET(PFM_CPUINFO_DCR_PP);
@@ -2331,6 +2356,7 @@
} else {
if ((task->thread.flags & IA64_THREAD_PM_VALID) == 0) {
+ preempt_enable();
printk(KERN_DEBUG "perfmon: pfm_start task flag not set for [%d]\n",
task->pid);
return -EINVAL;
@@ -2344,6 +2370,7 @@
ia64_srlz_i();
}
+ preempt_enable();
return 0;
}
@@ -2351,9 +2378,13 @@
pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count,
struct pt_regs *regs)
{
+ int me;
+
/* we don't quite support this right now */
if (task != current) return -EINVAL;
+ me = get_cpu(); /* make sure we're not migrated or preempted */
+
if (ctx->ctx_fl_system == 0 && PMU_OWNER() && PMU_OWNER() != current)
pfm_lazy_save_regs(PMU_OWNER());
@@ -2397,11 +2428,13 @@
SET_PMU_OWNER(task);
ctx->ctx_flags.state = PFM_CTX_ENABLED;
- atomic_set(&ctx->ctx_last_cpu, smp_processor_id());
+ atomic_set(&ctx->ctx_last_cpu, me);
/* simply unfreeze */
pfm_unfreeze_pmu();
+ put_cpu();
+
return 0;
}
@@ -2547,6 +2580,10 @@
task = find_task_by_pid(pid);
+ if (task) get_task_struct(task);
+
+ read_unlock(&tasklist_lock);
+
if (!task) goto abort_call;
ret = -EPERM;
@@ -2584,16 +2621,116 @@
ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(task, ctx, arg, count, regs);
abort_call:
- if (task != current) read_unlock(&tasklist_lock);
+ if (task && task != current) put_task_struct(task);
return ret;
}
+/*
+ * send SIGPROF to register task, must be invoked when it
+ * is safe to send a signal, e.g., not holding any runqueue
+ * related locks.
+ */
+static int
+pfm_notify_user(pfm_context_t *ctx)
+{
+ struct siginfo si;
+ int ret;
+
+ if (ctx->ctx_notify_task == NULL) {
+ DBprintk(("[%d] no notifier\n", current->pid));
+ return -EINVAL;
+ }
+
+ si.si_errno = 0;
+ si.si_addr = NULL;
+ si.si_pid = current->pid; /* who is sending */
+ si.si_signo = SIGPROF;
+ si.si_code = PROF_OVFL;
+
+ si.si_pfm_ovfl[0] = ctx->ctx_ovfl_regs[0];
+
+ /*
+ * when the target of the signal is not ourself, we have to be more
+ * careful. The notify_task may being cleared by the target task itself
+ * in release_thread(). We must ensure mutual exclusion here such that
+ * the signal is delivered (even to a dying task) safely.
+ */
+
+ if (ctx->ctx_notify_task != current) {
+ /*
+ * grab the notification lock for this task
+ * This guarantees that the sequence: test + send_signal
+ * is atomic with regards to the ctx_notify_task field.
+ *
+ * We need a spinlock and not just an atomic variable for this.
+ *
+ */
+ spin_lock(&ctx->ctx_lock);
+
+ /*
+ * now notify_task cannot be modified until we're done
+ * if NULL, they it got modified while we were in the handler
+ */
+ if (ctx->ctx_notify_task == NULL) {
+
+ spin_unlock(&ctx->ctx_lock);
+
+ /*
+ * If we've lost the notified task, then we will run
+ * to completion wbut keep the PMU frozen. Results
+ * will be incorrect anyway. We do not kill task
+ * to leave it possible to attach perfmon context
+ * to already running task.
+ */
+ printk("perfmon: pfm_notify_user() lost notify_task\n");
+ DBprintk_ovfl(("notification task has disappeared !\n"));
+
+ /* we cannot afford to block now */
+ ctx->ctx_fl_block = 0;
+
+ return -EINVAL;
+ }
+
+ /*
+ * required by send_sig_info() to make sure the target
+ * task does not disappear on us.
+ */
+ read_lock(&tasklist_lock);
+ }
+ /*
+ * in this case, we don't stop the task, we let it go on. It will
+ * necessarily go to the signal handler (if any) when it goes back to
+ * user mode.
+ */
+ DBprintk_ovfl(("[%d] sending notification to [%d]\n",
+ current->pid, ctx->ctx_notify_task->pid));
+
+ /*
+ * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
+ */
+ ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task);
+ if (ret) {
+ printk("perfmon: send_sig_info(process %d, SIGPROF)=%d\n",
+ ctx->ctx_notify_task->pid, ret);
+ }
+
+ /*
+ * now undo the protections in order
+ */
+ if (ctx->ctx_notify_task != current) {
+ read_unlock(&tasklist_lock);
+ spin_unlock(&ctx->ctx_lock);
+ }
+ return ret;
+}
+
void
pfm_ovfl_block_reset(void)
{
struct thread_struct *th = ¤t->thread;
pfm_context_t *ctx = current->thread.pfm_context;
+ unsigned int reason;
int ret;
/*
@@ -2609,8 +2746,31 @@
printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid);
return;
}
+ /*
+ * extract reason for being here and clear
+ */
+ reason = ctx->ctx_fl_trap_reason;
+ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
- if (CTX_OVFL_NOBLOCK(ctx)) goto non_blocking;
+ DBprintk(("[%d] reason=%d\n", current->pid, reason));
+
+ /*
+ * just here for a reset (non-blocking context only)
+ */
+ if (reason == PFM_TRAP_REASON_RESET) goto non_blocking;
+
+ /*
+ * first notify user. This can fail if notify_task has disappeared.
+ */
+ if (reason == PFM_TRAP_REASON_SIG || reason == PFM_TRAP_REASON_BLOCKSIG) {
+ ret = pfm_notify_user(ctx);
+ if (ret) return;
+ }
+
+ /*
+ * came here just to signal (non-blocking)
+ */
+ if (reason == PFM_TRAP_REASON_SIG) return;
DBprintk(("[%d] before sleeping\n", current->pid));
@@ -2691,7 +2851,7 @@
* initialize entry header
*/
h->pid = current->pid;
- h->cpu = smp_processor_id();
+ h->cpu = get_cpu();
h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL;
h->ip = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL;
h->regs = ovfl_mask; /* which registers overflowed */
@@ -2718,7 +2878,7 @@
DBprintk_ovfl(("e=%p pmd%d =0x%lx\n", (void *)e, j, *e));
e++;
}
- pfm_stats[smp_processor_id()].pfm_recorded_samples_count++;
+ pfm_stats[h->cpu].pfm_recorded_samples_count++;
/*
* make the new entry visible to user, needs to be atomic
@@ -2735,9 +2895,11 @@
/*
* XXX: must reset buffer in blocking mode and lost notified
*/
- pfm_stats[smp_processor_id()].pfm_full_smpl_buffer_count++;
+ pfm_stats[h->cpu].pfm_full_smpl_buffer_count++;
+ put_cpu();
return 1;
}
+ put_cpu();
return 0;
}
@@ -2756,7 +2918,6 @@
unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL;
int i;
int ret = 1;
- struct siginfo si;
/*
* It is never safe to access the task for which the overflow interrupt is destinated
* using the current variable as the interrupt may occur in the middle of a context switch
@@ -2770,6 +2931,8 @@
* valid one, i.e. the one that caused the interrupt.
*/
+ preempt_disable();
+
t = &task->thread;
/*
@@ -2779,6 +2942,7 @@
if ((t->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) {
printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d not "
"using perfmon\n", task->pid);
+ preempt_enable_no_resched();
return 0x1;
}
/*
@@ -2787,6 +2951,7 @@
if ((pmc0 & 0x1) == 0) {
printk(KERN_DEBUG "perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n",
task->pid, pmc0);
+ preempt_enable_no_resched();
return 0x0;
}
@@ -2869,7 +3034,8 @@
if (ovfl_notify == 0UL) {
if (ovfl_pmds)
pfm_reset_regs(ctx, &ovfl_pmds, PFM_PMD_SHORT_RESET);
- return 0x0;
+ preempt_enable_no_resched();
+ return 0x0UL;
}
/*
@@ -2877,142 +3043,35 @@
*/
ctx->ctx_ovfl_regs[0] = ovfl_pmds;
- /*
- * we have come to this point because there was an overflow and that notification
- * was requested. The notify_task may have disappeared, in which case notify_task
- * is NULL.
- */
- if (ctx->ctx_notify_task) {
-
- si.si_errno = 0;
- si.si_addr = NULL;
- si.si_pid = task->pid; /* who is sending */
-
- si.si_signo = SIGPROF;
- si.si_code = PROF_OVFL; /* indicates a perfmon SIGPROF signal */
- /*
- * Shift the bitvector such that the user sees bit 4 for PMD4 and so on.
- * We only use smpl_ovfl[0] for now. It should be fine for quite a while
- * until we have more than 61 PMD available.
- */
- si.si_pfm_ovfl[0] = ovfl_notify;
-
- /*
- * when the target of the signal is not ourself, we have to be more
- * careful. The notify_task may being cleared by the target task itself
- * in release_thread(). We must ensure mutual exclusion here such that
- * the signal is delivered (even to a dying task) safely.
- */
-
- if (ctx->ctx_notify_task != current) {
- /*
- * grab the notification lock for this task
- * This guarantees that the sequence: test + send_signal
- * is atomic with regards to the ctx_notify_task field.
- *
- * We need a spinlock and not just an atomic variable for this.
- *
- */
- spin_lock(&ctx->ctx_lock);
-
- /*
- * now notify_task cannot be modified until we're done
- * if NULL, they it got modified while we were in the handler
- */
- if (ctx->ctx_notify_task == NULL) {
-
- spin_unlock(&ctx->ctx_lock);
+ DBprintk_ovfl(("block=%d notify [%d] current [%d]\n",
+ ctx->ctx_fl_block,
+ ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1,
+ current->pid ));
- /*
- * If we've lost the notified task, then we will run
- * to completion wbut keep the PMU frozen. Results
- * will be incorrect anyway. We do not kill task
- * to leave it possible to attach perfmon context
- * to already running task.
- */
- goto lost_notify;
- }
- /*
- * required by send_sig_info() to make sure the target
- * task does not disappear on us.
- */
- read_lock(&tasklist_lock);
- }
- /*
- * in this case, we don't stop the task, we let it go on. It will
- * necessarily go to the signal handler (if any) when it goes back to
- * user mode.
- */
- DBprintk_ovfl(("[%d] sending notification to [%d]\n",
- task->pid, ctx->ctx_notify_task->pid));
-
-
- /*
- * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock
- */
- ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task);
- if (ret != 0)
- printk(KERN_DEBUG "send_sig_info(process %d, SIGPROF)=%d\n",
- ctx->ctx_notify_task->pid, ret);
- /*
- * now undo the protections in order
- */
- if (ctx->ctx_notify_task != current) {
- read_unlock(&tasklist_lock);
- spin_unlock(&ctx->ctx_lock);
- }
-
- /*
- * if we block set the pfm_must_block bit
- * when in block mode, we can effectively block only when the notified
- * task is not self, otherwise we would deadlock.
- * in this configuration, the notification is sent, the task will not
- * block on the way back to user mode, but the PMU will be kept frozen
- * until PFM_RESTART.
- * Note that here there is still a race condition with notify_task
- * possibly being nullified behind our back, but this is fine because
- * it can only be changed to NULL which by construction, can only be
- * done when notify_task != current. So if it was already different
- * before, changing it to NULL will still maintain this invariant.
- * Of course, when it is equal to current it cannot change at this point.
- */
- DBprintk_ovfl(("block=%d notify [%d] current [%d]\n",
- ctx->ctx_fl_block,
- ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1,
- current->pid ));
-
- if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != task) {
- t->pfm_ovfl_block_reset = 1; /* will cause blocking */
- }
+ /*
+ * ctx_notify_task could already be NULL, checked in pfm_notify_user()
+ */
+ if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) {
+ t->pfm_ovfl_block_reset = 1; /* will cause blocking */
+ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG;
} else {
-lost_notify: /* XXX: more to do here, to convert to non-blocking (reset values) */
-
- DBprintk_ovfl(("notification task has disappeared !\n"));
- /*
- * for a non-blocking context, we make sure we do not fall into the
- * pfm_overflow_notify() trap. Also in the case of a blocking context with lost
- * notify process, then we do not want to block either (even though it is
- * interruptible). In this case, the PMU will be kept frozen and the process will
- * run to completion without monitoring enabled.
- *
- * Of course, we cannot loose notify process when self-monitoring.
- */
- t->pfm_ovfl_block_reset = 0;
-
+ t->pfm_ovfl_block_reset = 1; /* will cause blocking */
+ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG;
}
+
/*
- * If notification was successful, then we rely on the pfm_restart()
- * call to unfreeze and reset (in both blocking or non-blocking mode).
- *
- * If notification failed, then we will keep the PMU frozen and run
- * the task to completion
+ * keep the PMU frozen until either pfm_restart() or
+ * task completes (non-blocking or notify_task gone).
*/
ctx->ctx_fl_frozen = 1;
- DBprintk_ovfl(("return pmc0=0x%x must_block=%ld\n",
- ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset));
+ DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n",
+ ctx->ctx_fl_frozen ? 0x1 : 0x0,
+ t->pfm_ovfl_block_reset,
+ ctx->ctx_fl_trap_reason));
- return ctx->ctx_fl_frozen ? 0x1 : 0x0;
+ preempt_enable_no_resched();
+ return 0x1UL;
}
static void
@@ -3022,13 +3081,14 @@
struct task_struct *task;
pfm_context_t *ctx;
- pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++;
+ pfm_stats[get_cpu()].pfm_ovfl_intr_count++;
/*
* if an alternate handler is registered, just bypass the default one
*/
if (pfm_alternate_intr_handler) {
(*pfm_alternate_intr_handler->handler)(irq, arg, regs);
+ put_cpu();
return;
}
@@ -3053,6 +3113,7 @@
if (!ctx) {
printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has "
"no PFM context\n", task->pid);
+ put_cpu();
return;
}
@@ -3060,17 +3121,25 @@
* assume PMC[0].fr = 1 at this point
*/
pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs);
-
/*
- * We always clear the overflow status bits and either unfreeze
- * or keep the PMU frozen.
+ * we can only update pmc0 when the overflow
+ * is for the current context. In UP the current
+ * task may not be the one owning the PMU
*/
- ia64_set_pmc(0, pmc0);
- ia64_srlz_d();
-
+ if (task == current) {
+ /*
+ * We always clear the overflow status bits and either unfreeze
+ * or keep the PMU frozen.
+ */
+ ia64_set_pmc(0, pmc0);
+ ia64_srlz_d();
+ } else {
+ task->thread.pmc[0] = pmc0;
+ }
} else {
pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++;
}
+ put_cpu_no_resched();
}
/* for debug only */
@@ -3141,6 +3210,7 @@
unsigned long dcr;
unsigned long dcr_pp;
+ preempt_disable();
dcr_pp = info & PFM_CPUINFO_DCR_PP ? 1 : 0;
/*
@@ -3151,6 +3221,7 @@
regs = (struct pt_regs *)((unsigned long) task + IA64_STK_OFFSET);
regs--;
ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0;
+ preempt_enable();
return;
}
/*
@@ -3166,6 +3237,7 @@
ia64_set_dcr(dcr & ~IA64_DCR_PP);
pfm_clear_psr_pp();
ia64_srlz_i();
+ preempt_enable();
return;
}
/*
@@ -3179,6 +3251,7 @@
pfm_set_psr_pp();
ia64_srlz_i();
}
+ preempt_enable();
}
void
@@ -3189,6 +3262,8 @@
u64 psr;
int i;
+ preempt_disable();
+
ctx = task->thread.pfm_context;
@@ -3242,6 +3317,7 @@
*/
atomic_set(&ctx->ctx_last_cpu, -1);
#endif
+ preempt_enable();
}
static void
@@ -3252,6 +3328,7 @@
unsigned long mask;
int i;
+ preempt_disable();
DBprintk(("on [%d] by [%d]\n", task->pid, current->pid));
t = &task->thread;
@@ -3278,6 +3355,7 @@
/* not owned by this CPU */
atomic_set(&ctx->ctx_last_cpu, -1);
+ preempt_enable();
}
void
@@ -3290,11 +3368,14 @@
u64 psr;
int i;
+ preempt_disable();
+
owner = PMU_OWNER();
ctx = task->thread.pfm_context;
t = &task->thread;
if (ctx == NULL) {
+ preempt_enable();
printk("perfmon: pfm_load_regs: null ctx for [%d]\n", task->pid);
return;
}
@@ -3333,7 +3414,7 @@
psr = ctx->ctx_saved_psr;
pfm_set_psr_l(psr);
-
+ preempt_enable();
return;
}
@@ -3373,16 +3454,20 @@
if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]);
}
+ /*
+ * manually invoke core interrupt handler
+ * if the task had a pending overflow when it was ctxsw out.
+ * Side effect on ctx_fl_frozen is possible.
+ */
if (t->pmc[0] & ~0x1) {
- pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
+ t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL);
}
/*
- * fl_frozen==1 when we are in blocking mode waiting for restart
+ * unfreeze PMU if possible
*/
- if (ctx->ctx_fl_frozen == 0) {
- pfm_unfreeze_pmu();
- }
+ if (ctx->ctx_fl_frozen == 0) pfm_unfreeze_pmu();
+
atomic_set(&ctx->ctx_last_cpu, smp_processor_id());
SET_PMU_OWNER(task);
@@ -3391,6 +3476,7 @@
* restore the psr we changed in pfm_save_regs()
*/
psr = ctx->ctx_saved_psr;
+ preempt_enable();
pfm_set_psr_l(psr);
}
@@ -3408,6 +3494,7 @@
printk("perfmon: invalid task in pfm_reset_pmu()\n");
return;
}
+ preempt_disable();
/* Let's make sure the PMU is frozen */
pfm_freeze_pmu();
@@ -3490,6 +3577,7 @@
ctx->ctx_used_dbrs[0] = 0UL;
ia64_srlz_d();
+ preempt_enable();
}
/*
@@ -3519,6 +3607,7 @@
*/
if (ctx->ctx_flags.state == PFM_CTX_DISABLED) return;
+ preempt_disable();
/*
* stop monitoring:
* This is the only way to stop monitoring without destroying overflow
@@ -3646,7 +3735,7 @@
* indicates that context has been saved
*/
atomic_set(&ctx->ctx_last_cpu, -1);
-
+ preempt_enable();
}
@@ -3669,6 +3758,7 @@
ctx = task->thread.pfm_context;
thread = &task->thread;
+ preempt_disable();
/*
* make sure child cannot mess up the monitoring session
*/
@@ -3723,6 +3813,8 @@
*/
ia64_psr(regs)->up = 0;
+ preempt_enable();
+
/* copy_thread() clears IA64_THREAD_PM_VALID */
return 0;
}
@@ -3770,8 +3862,9 @@
}
}
- nctx->ctx_fl_frozen = 0;
- nctx->ctx_ovfl_regs[0] = 0UL;
+ nctx->ctx_fl_frozen = 0;
+ nctx->ctx_ovfl_regs[0] = 0UL;
+ nctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE;
atomic_set(&nctx->ctx_last_cpu, -1);
/*
@@ -3827,6 +3920,8 @@
thread->flags |= IA64_THREAD_PM_VALID;
}
+ preempt_enable();
+
return 0;
}
@@ -3848,6 +3943,7 @@
/*
* check sampling buffer
*/
+ preempt_disable();
if (ctx->ctx_psb) {
pfm_smpl_buffer_desc_t *psb = ctx->ctx_psb;
@@ -3940,6 +4036,7 @@
}
UNLOCK_CTX(ctx);
+ preempt_enable();
pfm_unreserve_session(task, ctx->ctx_fl_system, 1UL << ctx->ctx_cpu);
@@ -4118,17 +4215,27 @@
{
int ret;
+
/* some sanity checks */
- if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
+ if (hdl == NULL || hdl->handler == NULL) {
+ return -EINVAL;
+ }
/* do the easy test first */
- if (pfm_alternate_intr_handler) return -EBUSY;
+ if (pfm_alternate_intr_handler) {
+ return -EBUSY;
+ }
+ preempt_disable();
/* reserve our session */
ret = pfm_reserve_session(NULL, 1, cpu_online_map);
- if (ret) return ret;
+ if (ret) {
+ preempt_enable();
+ return ret;
+ }
if (pfm_alternate_intr_handler) {
+ preempt_enable();
printk(KERN_DEBUG "perfmon: install_alternate, intr_handler not NULL "
"after reserve\n");
return -EINVAL;
@@ -4136,17 +4243,21 @@
pfm_alternate_intr_handler = hdl;
+ preempt_enable();
return 0;
}
int
pfm_remove_alternate_syswide_subsystem(pfm_intr_handler_desc_t *hdl)
{
- if (hdl == NULL) return -EINVAL;
+ if (hdl == NULL)
+ return -EINVAL;
/* cannot remove someone else's handler! */
- if (pfm_alternate_intr_handler != hdl) return -EINVAL;
+ if (pfm_alternate_intr_handler != hdl)
+ return -EINVAL;
+ preempt_disable();
pfm_alternate_intr_handler = NULL;
/*
@@ -4154,6 +4265,8 @@
*/
pfm_unreserve_session(NULL, 1, cpu_online_map);
+ preempt_enable();
+
return 0;
}
@@ -4234,8 +4347,9 @@
pfm_init_percpu(void)
{
int i;
+ int me = get_cpu();
- if (smp_processor_id() == 0)
+ if (me == 0)
register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
ia64_set_pmv(IA64_PERFMON_VECTOR);
@@ -4259,6 +4373,7 @@
if (PMD_IS_IMPL(i) == 0) continue;
ia64_set_pmd(i, 0UL);
}
+ put_cpu();
pfm_freeze_pmu();
}
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/kernel/process.c Mon Mar 17 13:45:12 2003
@@ -746,7 +746,7 @@
memcpy(tsk, orig, sizeof(struct task_struct) + sizeof(struct thread_info));
tsk->thread_info = (struct thread_info *) ((char *) tsk + IA64_TASK_SIZE);
- atomic_set(&tsk->usage, 1);
+ atomic_set(&tsk->usage, 2);
return tsk;
}
diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
--- a/arch/ia64/kernel/ptrace.c Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/kernel/ptrace.c Mon Mar 17 13:45:15 2003
@@ -1,7 +1,7 @@
/*
* Kernel support for the ptrace() and syscall tracing interfaces.
*
- * Copyright (C) 1999-2002 Hewlett-Packard Co
+ * Copyright (C) 1999-2003 Hewlett-Packard Co
* David Mosberger-Tang
*
* Derived from the x86 and Alpha versions. Most of the code in here
@@ -1235,19 +1235,12 @@
ret = 0;
goto out_tsk;
- case PTRACE_GETSIGINFO:
- ret = -EIO;
- if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo)
- goto out_tsk;
- ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo);
+ case PTRACE_OLD_GETSIGINFO: /* for backwards-compatibility */
+ ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data);
goto out_tsk;
- case PTRACE_SETSIGINFO:
- ret = -EIO;
- if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t))
- || child->thread.siginfo == 0)
- goto out_tsk;
- ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data);
+ case PTRACE_OLD_SETSIGINFO: /* for backwards-compatibility */
+ ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data);
goto out_tsk;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
@@ -1349,15 +1342,12 @@
* The 0x80 provides a way for the tracing parent to distinguish between a syscall
* stop and SIGTRAP delivery.
*/
- current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0);
- set_current_state(TASK_STOPPED);
- notify_parent(current, SIGCHLD);
- schedule();
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+
/*
- * This isn't the same as continuing with a signal, but it
- * will do for normal use. strace only continues with a
- * signal if the stopping signal is not SIGTRAP. -brl
+ * This isn't the same as continuing with a signal, but it will do for normal use.
+ * strace only continues with a signal if the stopping signal is not SIGTRAP.
+ * -brl
*/
if (current->exit_code) {
send_sig(current->exit_code, current, 1);
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c Mon Mar 17 13:45:09 2003
+++ b/arch/ia64/kernel/setup.c Mon Mar 17 13:45:09 2003
@@ -363,7 +363,7 @@
#ifdef CONFIG_ACPI_BOOT
/* Initialize the ACPI boot-time table parser */
- acpi_table_init(*cmdline_p);
+ acpi_table_init();
# ifdef CONFIG_ACPI_NUMA
acpi_numa_init();
# endif
@@ -422,7 +422,7 @@
cpu_init(); /* initialize the bootstrap CPU */
#ifdef CONFIG_ACPI_BOOT
- acpi_boot_init(*cmdline_p);
+ acpi_boot_init();
#endif
#ifdef CONFIG_SERIAL_HCDP
if (efi.hcdp) {
diff -Nru a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
--- a/arch/ia64/kernel/sigframe.h Mon Mar 17 13:45:14 2003
+++ b/arch/ia64/kernel/sigframe.h Mon Mar 17 13:45:14 2003
@@ -1,6 +1,6 @@
struct sigscratch {
unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */
- unsigned long pad;
+ unsigned long ar_pfs; /* for syscalls, the user-level function-state */
struct pt_regs pt;
};
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c Mon Mar 17 13:45:13 2003
+++ b/arch/ia64/kernel/signal.c Mon Mar 17 13:45:13 2003
@@ -315,7 +315,7 @@
static long
setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr)
{
- unsigned long flags = 0, ifs, nat;
+ unsigned long flags = 0, ifs, cfm, nat;
long err;
ifs = scr->pt.cr_ifs;
@@ -325,7 +325,9 @@
if ((ifs & (1UL << 63)) == 0) {
/* if cr_ifs isn't valid, we got here through a syscall */
flags |= IA64_SC_FLAG_IN_SYSCALL;
- }
+ cfm = scr->ar_pfs & ((1UL << 38) - 1);
+ } else
+ cfm = ifs & ((1UL << 38) - 1);
ia64_flush_fph(current);
if ((current->thread.flags & IA64_THREAD_FPH_VALID)) {
flags |= IA64_SC_FLAG_FPH_VALID;
@@ -344,6 +346,7 @@
err |= __put_user(nat, &sc->sc_nat);
err |= PUT_SIGSET(mask, &sc->sc_mask);
+ err |= __put_user(cfm, &sc->sc_cfm);
err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
@@ -422,6 +425,15 @@
scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */
scr->pt.cr_iip = tramp_addr;
ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */
+ /*
+ * Force the interruption function mask to zero. This has no effect when a
+ * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is
+ * ignored), but it has the desirable effect of making it possible to deliver a
+ * signal with an incomplete register frame (which happens when a mandatory RSE
+ * load faults). Furthermore, it has no negative effect on the getting the user's
+ * dirty partition preserved, because that's governed by scr->pt.loadrs.
+ */
+ scr->pt.cr_ifs = (1UL << 63);
/*
* Note: this affects only the NaT bits of the scratch regs (the ones saved in
@@ -522,7 +534,7 @@
if (signr <= 0)
break;
- ka = ¤t->sig->action[signr - 1];
+ ka = ¤t->sighand->action[signr - 1];
if (restart) {
switch (errno) {
diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
--- a/arch/ia64/kernel/smp.c Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/kernel/smp.c Mon Mar 17 13:45:15 2003
@@ -90,7 +90,7 @@
void
handle_IPI (int irq, void *dev_id, struct pt_regs *regs)
{
- int this_cpu = smp_processor_id();
+ int this_cpu = get_cpu();
unsigned long *pending_ipis = &__get_cpu_var(ipi_operation);
unsigned long ops;
@@ -146,8 +146,12 @@
} while (ops);
mb(); /* Order data access and bit testing. */
}
+ put_cpu();
}
+/*
+ * Called with preeemption disabled
+ */
static inline void
send_IPI_single (int dest_cpu, int op)
{
@@ -155,6 +159,9 @@
platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0);
}
+/*
+ * Called with preeemption disabled
+ */
static inline void
send_IPI_allbutself (int op)
{
@@ -166,6 +173,9 @@
}
}
+/*
+ * Called with preeemption disabled
+ */
static inline void
send_IPI_all (int op)
{
@@ -176,12 +186,18 @@
send_IPI_single(i, op);
}
+/*
+ * Called with preeemption disabled
+ */
static inline void
send_IPI_self (int op)
{
send_IPI_single(smp_processor_id(), op);
}
+/*
+ * Called with preeemption disabled
+ */
void
smp_send_reschedule (int cpu)
{
@@ -197,12 +213,15 @@
smp_send_reschedule_all (void)
{
int i;
+ int cpu = get_cpu(); /* disable preemption */
for (i = 0; i < NR_CPUS; i++)
- if (cpu_online(i) && i != smp_processor_id())
+ if (cpu_online(i) && i != cpu)
smp_send_reschedule(i);
+ put_cpu();
}
+
void
smp_flush_tlb_all (void)
{
@@ -247,9 +266,11 @@
{
struct call_data_struct data;
int cpus = 1;
+ int me = get_cpu(); /* prevent preemption and reschedule on another processor */
- if (cpuid == smp_processor_id()) {
+ if (cpuid == me) {
printk("%s: trying to call self\n", __FUNCTION__);
+ put_cpu();
return -EBUSY;
}
@@ -276,6 +297,7 @@
call_data = NULL;
spin_unlock_bh(&call_lock);
+ put_cpu();
return 0;
}
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c Mon Mar 17 13:45:13 2003
+++ b/arch/ia64/kernel/sys_ia64.c Mon Mar 17 13:45:13 2003
@@ -33,17 +33,8 @@
return -ENOMEM;
#ifdef CONFIG_HUGETLB_PAGE
-#define COLOR_HALIGN(addr) ((addr + HPAGE_SIZE - 1) & ~(HPAGE_SIZE - 1))
-#define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE)
- if (filp && is_file_hugepages(filp)) {
- if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE -1)))
- addr = TASK_HPAGE_BASE;
- addr = COLOR_HALIGN(addr);
- }
- else {
- if (REGION_NUMBER(addr) == REGION_HPAGE)
- addr = 0;
- }
+ if (REGION_NUMBER(addr) == REGION_HPAGE)
+ addr = 0;
#endif
if (!addr)
addr = TASK_UNMAPPED_BASE;
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c Mon Mar 17 13:45:09 2003
+++ b/arch/ia64/kernel/time.c Mon Mar 17 13:45:09 2003
@@ -25,7 +25,7 @@
#include
extern unsigned long wall_jiffies;
-extern unsigned long last_time_offset;
+extern unsigned long last_nsec_offset;
u64 jiffies_64 = INITIAL_JIFFIES;
@@ -74,13 +74,13 @@
- (lost + 1)*cpu_data(time_keeper_id)->itm_delta);
now = ia64_get_itc();
- if ((long) (now - last_tick) < 0) {
+ if (unlikely((long) (now - last_tick) < 0)) {
printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n",
smp_processor_id(), now, last_tick);
- return last_time_offset;
+ return last_nsec_offset;
}
elapsed_cycles = now - last_tick;
- return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT;
+ return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT;
}
void
@@ -115,30 +115,55 @@
void
do_gettimeofday (struct timeval *tv)
{
- unsigned long seq, usec, sec, old;
+ unsigned long seq, nsec, usec, sec, old, offset;
- do {
+ while (1) {
seq = read_seqbegin(&xtime_lock);
- usec = gettimeoffset();
-
+ {
+ old = last_nsec_offset;
+ offset = gettimeoffset();
+ sec = xtime.tv_sec;
+ nsec = xtime.tv_nsec;
+ }
+ if (unlikely(read_seqretry(&xtime_lock, seq)))
+ continue;
/*
- * Ensure time never goes backwards, even when ITC on
- * different CPUs are not perfectly synchronized.
+ * Ensure that for any pair of causally ordered gettimeofday() calls, time
+ * never goes backwards (even when ITC on different CPUs are not perfectly
+ * synchronized). (A pair of concurrent calls to gettimeofday() is by
+ * definition non-causal and hence it makes no sense to talk about
+ * time-continuity for such calls.)
+ *
+ * Doing this in a lock-free and race-free manner is tricky. Here is why
+ * it works (most of the time): read_seqretry() just succeeded, which
+ * implies we calculated a consistent (valid) value for "offset". If the
+ * cmpxchg() below succeeds, we further know that last_nsec_offset still
+ * has the same value as at the beginning of the loop, so there was
+ * presumably no timer-tick or other updates to last_nsec_offset in the
+ * meantime. This isn't 100% true though: there _is_ a possibility of a
+ * timer-tick occurring right right after read_seqretry() and then getting
+ * zero or more other readers which will set last_nsec_offset to the same
+ * value as the one we read at the beginning of the loop. If this
+ * happens, we'll end up returning a slightly newer time than we ought to
+ * (the jump forward is at most "offset" nano-seconds). There is no
+ * danger of causing time to go backwards, though, so we are safe in that
+ * sense. We could make the probability of this unlucky case occurring
+ * arbitrarily small by encoding a version number in last_nsec_offset, but
+ * even without versioning, the probability of this unlucky case should be
+ * so small that we won't worry about it.
*/
- do {
- old = last_time_offset;
- if (usec <= old) {
- usec = old;
- break;
- }
- } while (cmpxchg(&last_time_offset, old, usec) != old);
-
- sec = xtime.tv_sec;
- usec += xtime.tv_nsec / 1000;
- } while (read_seqend(&xtime_lock, seq));
+ if (offset <= old) {
+ offset = old;
+ break;
+ } else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old))
+ break;
+
+ /* someone else beat us to updating last_nsec_offset; try again */
+ }
+ usec = (nsec + offset) / 1000;
- while (usec >= 1000000) {
+ while (unlikely(usec >= 1000000)) {
usec -= 1000000;
++sec;
}
@@ -278,7 +303,7 @@
local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den;
local_cpu_data->itc_freq = itc_freq;
local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000;
- local_cpu_data->usec_per_cyc = ((1000000UL<nsec_per_cyc = ((1000000000UL<> 4) & 0xf) == 2) {
/* NaT page consumption */
sig = SIGSEGV;
code = SEGV_ACCERR;
+ addr = (void *) ifa;
} else {
/* register NaT consumption */
sig = SIGILL;
code = ILL_ILLOPN;
+ addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
}
siginfo.si_signo = sig;
siginfo.si_code = code;
siginfo.si_errno = 0;
- siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+ siginfo.si_addr = addr;
siginfo.si_imm = vector;
siginfo.si_flags = __ISR_VALID;
siginfo.si_isr = isr;
diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
--- a/arch/ia64/kernel/unwind.c Mon Mar 17 13:45:16 2003
+++ b/arch/ia64/kernel/unwind.c Mon Mar 17 13:45:16 2003
@@ -51,18 +51,24 @@
#define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1)
#define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE)
-#define UNW_DEBUG 0
#define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */
-#if UNW_DEBUG
- static long unw_debug_level = 255;
-# define debug(level,format...) if (unw_debug_level > level) printk(format)
-# define dprintk(format...) printk(format)
-# define inline
-#else
-# define debug(level,format...)
-# define dprintk(format...)
-#endif
+#ifdef UNW_DEBUG
+ static unsigned int unw_debug_level = UNW_DEBUG;
+# ifdef CONFIG_KDB
+# include
+# define UNW_DEBUG_ON(n) (unw_debug_level >= n && !KDB_IS_RUNNING())
+# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__)
+# else /* !CONFIG_KDB */
+# define UNW_DEBUG_ON(n) unw_debug_level >= n
+ /* Do not code a printk level, not all debug lines end in newline */
+# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
+# endif /* CONFIG_KDB */
+# define inline
+#else /* !UNW_DEBUG */
+# define UNW_DEBUG_ON(n) 0
+# define UNW_DPRINT(n, ...)
+#endif /* UNW_DEBUG */
#if UNW_STATS
# define STAT(x...) x
@@ -111,7 +117,7 @@
/* script cache: */
struct unw_script cache[UNW_CACHE_SIZE];
-# if UNW_DEBUG
+# ifdef UNW_DEBUG
const char *preg_name[UNW_NUM_REGS];
# endif
# if UNW_STATS
@@ -190,7 +196,7 @@
struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
},
.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
-#if UNW_DEBUG
+#ifdef UNW_DEBUG
.preg_name = {
"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
"r4", "r5", "r6", "r7",
@@ -223,10 +229,22 @@
else if (reg <= 31)
off = struct_offset(struct pt_regs, r16) + 8*(reg - 16);
else
- dprintk("unwind: bad scratch reg r%lu\n", reg);
+ UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
return off;
}
+static inline struct pt_regs *
+get_scratch_regs (struct unw_frame_info *info)
+{
+ if (!info->pt) {
+ /* This should not happen with valid unwind info. */
+ UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__);
+ info->pt = info->sp - 16;
+ }
+ UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt);
+ return (struct pt_regs *) info->pt;
+}
+
int
unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
{
@@ -235,7 +253,8 @@
struct pt_regs *pt;
if ((unsigned) regnum - 1 >= 127) {
- dprintk("unwind: trying to access non-existent r%u\n", regnum);
+ UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n",
+ __FUNCTION__, regnum);
return -1;
}
@@ -280,8 +299,9 @@
if ((unsigned long) addr < info->regstk.limit
|| (unsigned long) addr >= info->regstk.top)
{
- dprintk("unwind: %p outside of regstk "
- "[0x%lx-0x%lx)\n", (void *) addr,
+ UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
+ "[0x%lx-0x%lx)\n",
+ __FUNCTION__, (void *) addr,
info->regstk.limit,
info->regstk.top);
return -1;
@@ -298,11 +318,13 @@
}
} else {
/* access a scratch register */
- if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
- pt = (struct pt_regs *) info->psp - 1;
- else
- pt = (struct pt_regs *) info->sp - 1;
- addr = (unsigned long *) ((long) pt + pt_regs_off(regnum));
+ if (!info->pt) {
+ UNW_DPRINT(0, "unwind.%s: no pt-regs; cannot access r%d\n",
+ __FUNCTION__, regnum);
+ return -1;
+ }
+ pt = get_scratch_regs(info);
+ addr = (unsigned long *) (pt + pt_regs_off(regnum));
if (info->pri_unat_loc)
nat_addr = info->pri_unat_loc;
else
@@ -316,7 +338,8 @@
if ((unsigned long) addr < info->regstk.limit
|| (unsigned long) addr >= info->regstk.top)
{
- dprintk("unwind: ignoring attempt to access register outside of rbs\n");
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside "
+ "of rbs\n", __FUNCTION__);
return -1;
}
if ((unsigned long) nat_addr >= info->regstk.top)
@@ -348,10 +371,7 @@
unsigned long *addr;
struct pt_regs *pt;
- if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
- pt = (struct pt_regs *) info->psp - 1;
- else
- pt = (struct pt_regs *) info->sp - 1;
+ pt = get_scratch_regs(info);
switch (regnum) {
/* scratch: */
case 0: addr = &pt->b0; break;
@@ -366,7 +386,8 @@
break;
default:
- dprintk("unwind: trying to access non-existent b%u\n", regnum);
+ UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n",
+ __FUNCTION__, regnum);
return -1;
}
if (write)
@@ -383,14 +404,12 @@
struct pt_regs *pt;
if ((unsigned) (regnum - 2) >= 126) {
- dprintk("unwind: trying to access non-existent f%u\n", regnum);
+ UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n",
+ __FUNCTION__, regnum);
return -1;
}
- if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
- pt = (struct pt_regs *) info->psp - 1;
- else
- pt = (struct pt_regs *) info->sp - 1;
+ pt = get_scratch_regs(info);
if (regnum <= 5) {
addr = *(&info->f2_loc + (regnum - 2));
@@ -428,11 +447,7 @@
unsigned long *addr;
struct pt_regs *pt;
- if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
- pt = (struct pt_regs *) info->psp - 1;
- else
- pt = (struct pt_regs *) info->sp - 1;
-
+ pt = get_scratch_regs(info);
switch (regnum) {
case UNW_AR_BSP:
addr = info->bsp_loc;
@@ -495,7 +510,8 @@
break;
default:
- dprintk("unwind: trying to access non-existent ar%u\n", regnum);
+ UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
+ __FUNCTION__, regnum);
return -1;
}
@@ -612,7 +628,7 @@
default:
break;
}
- dprintk("unwind: bad abreg=0x%x\n", abreg);
+ UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg);
return UNW_REG_LC;
}
@@ -652,7 +668,7 @@
return;
}
}
- dprintk("unwind: excess spill!\n");
+ UNW_DPRINT(0, "unwind.%s: excess spill!\n", __FUNCTION__);
}
static inline void
@@ -720,7 +736,7 @@
desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,
struct unw_state_record *sr)
{
- int i;
+ int i, region_start;
if (!(sr->in_body || sr->first_region))
finish_prologue(sr);
@@ -732,19 +748,20 @@
return;
}
+ region_start = sr->region_start + sr->region_len;
+
for (i = 0; i < sr->epilogue_count; ++i)
pop(sr);
sr->epilogue_count = 0;
sr->epilogue_start = UNW_WHEN_NEVER;
- if (!body)
- push(sr);
-
- sr->region_start += sr->region_len;
+ sr->region_start = region_start;
sr->region_len = rlen;
sr->in_body = body;
if (!body) {
+ push(sr);
+
for (i = 0; i < 4; ++i) {
if (mask & 0x8)
set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,
@@ -765,10 +782,13 @@
static inline void
desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
{
- if (abi == 0 && context == 'i')
+ if (abi == 0 && context == 'i') {
sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
+ UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __FUNCTION__);
+ }
else
- dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context);
+ UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
+ __FUNCTION__, abi, context);
}
static inline void
@@ -1136,6 +1156,9 @@
unsigned short index;
unsigned long ip, pr;
+ if (UNW_DEBUG_ON(0))
+ return 0; /* Always regenerate scripts in debug mode */
+
STAT(++unw.stat.cache.lookups);
ip = info->ip;
@@ -1260,8 +1283,8 @@
script_emit (struct unw_script *script, struct unw_insn insn)
{
if (script->count >= UNW_MAX_SCRIPT_LEN) {
- dprintk("unwind: script exceeds maximum size of %u instructions!\n",
- UNW_MAX_SCRIPT_LEN);
+ UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
+ __FUNCTION__, UNW_MAX_SCRIPT_LEN);
return;
}
script->insn[script->count++] = insn;
@@ -1302,7 +1325,8 @@
break;
default:
- dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where);
+ UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",
+ __FUNCTION__, r->where);
return;
}
insn.opc = opc;
@@ -1339,8 +1363,9 @@
}
val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
} else {
- opc = UNW_INSN_ADD_SP;
- val = -sizeof(struct pt_regs) + pt_regs_off(rval);
+ /* register got spilled to a scratch register */
+ opc = UNW_INSN_MOVE_SCRATCH;
+ val = pt_regs_off(rval);
}
break;
@@ -1350,12 +1375,12 @@
else if (rval >= 16 && rval <= 31)
val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
else {
- opc = UNW_INSN_ADD_SP;
- val = -sizeof(struct pt_regs);
+ opc = UNW_INSN_MOVE_SCRATCH;
if (rval <= 9)
- val += struct_offset(struct pt_regs, f6) + 16*(rval - 6);
+ val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
else
- dprintk("unwind: kernel may not touch f%lu\n", rval);
+ UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
+ __FUNCTION__, rval);
}
break;
@@ -1363,14 +1388,13 @@
if (rval >= 1 && rval <= 5)
val = unw.preg_index[UNW_REG_B1 + (rval - 1)];
else {
- opc = UNW_INSN_ADD_SP;
- val = -sizeof(struct pt_regs);
+ opc = UNW_INSN_MOVE_SCRATCH;
if (rval == 0)
- val += struct_offset(struct pt_regs, b0);
+ val = struct_offset(struct pt_regs, b0);
else if (rval == 6)
- val += struct_offset(struct pt_regs, b6);
+ val = struct_offset(struct pt_regs, b6);
else
- val += struct_offset(struct pt_regs, b7);
+ val = struct_offset(struct pt_regs, b7);
}
break;
@@ -1383,7 +1407,8 @@
break;
default:
- dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where);
+ UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n",
+ __FUNCTION__, i, r->where);
break;
}
insn.opc = opc;
@@ -1456,9 +1481,10 @@
r->when = UNW_WHEN_NEVER;
sr.pr_val = info->pr;
+ UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip);
script = script_new(ip);
if (!script) {
- dprintk("unwind: failed to create unwind script\n");
+ UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __FUNCTION__);
STAT(unw.stat.script.build_time += ia64_get_itc() - start);
return 0;
}
@@ -1476,8 +1502,8 @@
}
if (!e) {
/* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */
- dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip,
- unw.cache[info->prev_script].ip);
+ UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
+ __FUNCTION__, ip, unw.cache[info->prev_script].ip);
sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
sr.curr.reg[UNW_REG_RP].when = -1;
sr.curr.reg[UNW_REG_RP].val = 0;
@@ -1525,26 +1551,32 @@
sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
sr.curr.reg[UNW_REG_RP].when = -1;
sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
+ UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
+ __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where,
+ sr.curr.reg[UNW_REG_RP].val);
}
-#if UNW_DEBUG
- printk("unwind: state record for func 0x%lx, t=%u:\n",
- table->segment_base + e->start_offset, sr.when_target);
+#ifdef UNW_DEBUG
+ UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
+ __FUNCTION__, table->segment_base + e->start_offset, sr.when_target);
for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
- printk(" %s <- ", unw.preg_name[r - sr.curr.reg]);
+ UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]);
switch (r->where) {
- case UNW_WHERE_GR: printk("r%lu", r->val); break;
- case UNW_WHERE_FR: printk("f%lu", r->val); break;
- case UNW_WHERE_BR: printk("b%lu", r->val); break;
- case UNW_WHERE_SPREL: printk("[sp+0x%lx]", r->val); break;
- case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break;
+ case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break;
+ case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break;
+ case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break;
+ case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
+ case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
case UNW_WHERE_NONE:
- printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
+ UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
+ break;
+
+ default:
+ UNW_DPRINT(1, "BADWHERE(%d)", r->where);
break;
- default: printk("BADWHERE(%d)", r->where); break;
}
- printk("\t\t%d\n", r->when);
+ UNW_DPRINT(1, "\t\t%d\n", r->when);
}
}
#endif
@@ -1642,6 +1674,16 @@
s[dst] = s[val];
break;
+ case UNW_INSN_MOVE_SCRATCH:
+ if (state->pt) {
+ s[dst] = (unsigned long) get_scratch_regs(state) + val;
+ } else {
+ s[dst] = 0;
+ UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n",
+ __FUNCTION__, dst, val);
+ }
+ break;
+
case UNW_INSN_MOVE_STACKED:
s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
val);
@@ -1667,11 +1709,12 @@
break;
case UNW_INSN_LOAD:
-#if UNW_DEBUG
+#ifdef UNW_DEBUG
if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
|| s[val] < TASK_SIZE)
{
- debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]);
+ UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
+ __FUNCTION__, s[val]);
break;
}
#endif
@@ -1704,7 +1747,8 @@
if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
/* don't let obviously bad addresses pollute the cache */
- debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip);
+ /* FIXME: should really be level 0 but it occurs too often. KAO */
+ UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip);
info->rp_loc = 0;
return -1;
}
@@ -1713,8 +1757,9 @@
if (!scr) {
scr = build_script(info);
if (!scr) {
- dprintk("unwind: failed to locate/build unwind script for ip %lx\n",
- info->ip);
+ UNW_DPRINT(0,
+ "unwind.%s: failed to locate/build unwind script for ip %lx\n",
+ __FUNCTION__, info->ip);
return -1;
}
have_write_lock = 1;
@@ -1747,7 +1792,9 @@
/* restore the ip */
if (!info->rp_loc) {
- debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip);
+ /* FIXME: should really be level 0 but it occurs too often. KAO */
+ UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
+ __FUNCTION__, info->ip);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
}
@@ -1757,14 +1804,14 @@
* We don't have unwind info for the gate page, so we consider that part
* of user-space for the purpose of unwinding.
*/
- debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip);
+ UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
}
/* restore the cfm: */
if (!info->pfs_loc) {
- dprintk("unwind: failed to locate ar.pfs!\n");
+ UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
}
@@ -1774,16 +1821,18 @@
pr = info->pr;
num_regs = 0;
if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
+ info->pt = info->sp + 16;
if ((pr & (1UL << pNonSys)) != 0)
num_regs = *info->cfm_loc & 0x7f; /* size of frame */
info->pfs_loc =
- (unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs));
+ (unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs));
+ UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt);
} else
num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */
info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
- dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
- info->bsp, info->regstk.limit, info->regstk.top);
+ UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
+ __FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
}
@@ -1791,14 +1840,15 @@
/* restore the sp: */
info->sp = info->psp;
if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
- dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
- info->sp, info->memstk.top, info->memstk.limit);
+ UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
+ __FUNCTION__, info->sp, info->memstk.top, info->memstk.limit);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
}
if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
- dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip);
+ UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n",
+ __FUNCTION__, ip);
STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
return -1;
}
@@ -1822,7 +1872,8 @@
while (unw_unwind(info) >= 0) {
if (unw_get_rp(info, &ip) < 0) {
unw_get_ip(info, &ip);
- dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip);
+ UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
+ __FUNCTION__, ip);
return -1;
}
/*
@@ -1833,7 +1884,7 @@
return 0;
}
unw_get_ip(info, &ip);
- dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip);
+ UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
return -1;
}
@@ -1874,11 +1925,30 @@
info->task = t;
info->sw = sw;
info->sp = info->psp = (unsigned long) (sw + 1) - 16;
+ info->pt = 0;
info->cfm_loc = &sw->ar_pfs;
sol = (*info->cfm_loc >> 7) & 0x7f;
info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
info->ip = sw->b0;
info->pr = sw->pr;
+ UNW_DPRINT(3,
+ "unwind.%s\n"
+ " rbslimit 0x%lx\n"
+ " rbstop 0x%lx\n"
+ " stklimit 0x%lx\n"
+ " stktop 0x%lx\n"
+ " task 0x%lx\n"
+ " sw 0x%lx\n",
+ __FUNCTION__, rbslimit, rbstop, stklimit, stktop,
+ (unsigned long)(info->task),
+ (unsigned long)(info->sw));
+ UNW_DPRINT(3,
+ " sp/psp 0x%lx\n"
+ " sol 0x%lx\n"
+ " bsp 0x%lx\n"
+ " ip 0x%lx\n"
+ " pr 0x%lx\n",
+ info->sp, sol, info->bsp, info->ip, info->pr);
find_save_locs(info);
STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
@@ -1889,6 +1959,7 @@
{
struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
+ UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__);
unw_init_frame_info(info, t, sw);
}
@@ -1916,7 +1987,8 @@
unsigned long flags;
if (end - start <= 0) {
- dprintk("unwind: ignoring attempt to insert empty unwind table\n");
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
+ __FUNCTION__);
return 0;
}
@@ -1946,13 +2018,15 @@
long index;
if (!handle) {
- dprintk("unwind: ignoring attempt to remove non-existent unwind table\n");
+ UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n",
+ __FUNCTION__);
return;
}
table = handle;
if (table == &unw.kernel_table) {
- dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n");
+ UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a "
+ "no-can-do!\n", __FUNCTION__);
return;
}
@@ -1964,7 +2038,8 @@
if (prev->next == table)
break;
if (!prev) {
- dprintk("unwind: failed to find unwind table %p\n", (void *) table);
+ UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n",
+ __FUNCTION__, (void *) table);
spin_unlock_irqrestore(&unw.lock, flags);
return;
}
diff -Nru a/arch/ia64/kernel/unwind_i.h b/arch/ia64/kernel/unwind_i.h
--- a/arch/ia64/kernel/unwind_i.h Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/kernel/unwind_i.h Mon Mar 17 13:45:12 2003
@@ -137,7 +137,8 @@
UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK;
s[dst+1].nat.off = *s.pri_unat - s[dst] */
UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */
- UNW_INSN_LOAD /* s[dst] = *s[val] */
+ UNW_INSN_LOAD, /* s[dst] = *s[val] */
+ UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
};
struct unw_insn {
diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
--- a/arch/ia64/mm/fault.c Mon Mar 17 13:45:15 2003
+++ b/arch/ia64/mm/fault.c Mon Mar 17 13:45:15 2003
@@ -55,7 +55,7 @@
/*
* If we're in an interrupt or have no user context, we must not take the fault..
*/
- if (in_interrupt() || !mm)
+ if (in_atomic() || !mm)
goto no_context;
down_read(&mm->mmap_sem);
@@ -79,7 +79,7 @@
# if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
|| (1 << VM_EXEC_BIT) != VM_EXEC)
-# error File is out of sync with . Pleaes update.
+# error File is out of sync with . Please update.
# endif
mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- a/arch/ia64/mm/hugetlbpage.c Mon Mar 17 13:45:13 2003
+++ b/arch/ia64/mm/hugetlbpage.c Mon Mar 17 13:45:13 2003
@@ -19,6 +19,8 @@
#include
+#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT)
+
static long htlbpagemem;
int htlbpage_max;
static long htlbzone_pages;
@@ -98,7 +100,6 @@
set_pte(page_table, entry);
return;
}
-
/*
* This function checks for proper alignment of input addr and len parameters.
*/
@@ -108,6 +109,20 @@
return -EINVAL;
if (addr & ~HPAGE_MASK)
return -EINVAL;
+ if (REGION_NUMBER(addr) != REGION_HPAGE)
+ return -EINVAL;
+
+ return 0;
+}
+/* This function checks if the address and address+len falls out of HugeTLB region. It
+ * return -EINVAL if any part of address range falls in HugeTLB region.
+ */
+int is_invalid_hugepage_range(unsigned long addr, unsigned long len)
+{
+ if (REGION_NUMBER(addr) == REGION_HPAGE)
+ return -EINVAL;
+ if (REGION_NUMBER(addr+len) == REGION_HPAGE)
+ return -EINVAL;
return 0;
}
@@ -173,6 +188,39 @@
return i;
}
+struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr)
+{
+ if (mm->used_hugetlb) {
+ if (REGION_NUMBER(addr) == REGION_HPAGE) {
+ struct vm_area_struct *vma = find_vma(mm, addr);
+ if (vma && is_vm_hugetlb_page(vma))
+ return vma;
+ }
+ }
+ return NULL;
+}
+
+struct page *follow_huge_addr(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int write)
+{
+ struct page *page;
+ pte_t *ptep;
+
+ ptep = huge_pte_offset(mm, addr);
+ page = pte_page(*ptep);
+ page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT);
+ get_page(page);
+ return page;
+}
+int pmd_huge(pmd_t pmd)
+{
+ return 0;
+}
+struct page *
+follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write)
+{
+ return NULL;
+}
+
void free_huge_page(struct page *page)
{
BUG_ON(page_count(page));
@@ -204,8 +252,6 @@
BUG_ON(start & (HPAGE_SIZE - 1));
BUG_ON(end & (HPAGE_SIZE - 1));
- spin_lock(&htlbpage_lock);
- spin_unlock(&htlbpage_lock);
for (address = start; address < end; address += HPAGE_SIZE) {
pte = huge_pte_offset(mm, address);
if (pte_none(*pte))
@@ -257,8 +303,12 @@
ret = -ENOMEM;
goto out;
}
- add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+ ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
unlock_page(page);
+ if (ret) {
+ free_huge_page(page);
+ goto out;
+ }
}
set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
}
@@ -267,6 +317,29 @@
return ret;
}
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
+ unsigned long pgoff, unsigned long flags)
+{
+ struct vm_area_struct *vmm;
+
+ if (len > RGN_MAP_LIMIT)
+ return -ENOMEM;
+ if (len & ~HPAGE_MASK)
+ return -EINVAL;
+ /* This code assumes that REGION_HPAGE != 0. */
+ if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
+ addr = TASK_HPAGE_BASE;
+ else
+ addr = ALIGN(addr, HPAGE_SIZE);
+ for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
+ /* At this point: (!vmm || addr < vmm->vm_end). */
+ if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT)
+ return -ENOMEM;
+ if (!vmm || (addr + len) <= vmm->vm_start)
+ return addr;
+ addr = ALIGN(vmm->vm_end, HPAGE_SIZE);
+ }
+}
void update_and_free_page(struct page *page)
{
int j;
@@ -302,8 +375,8 @@
break;
}
page = list_entry(p, struct page, list);
- if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem
- map = page;
+ if (!PageHighMem(page))
+ map = page;
}
if (map) {
list_del(&map->list);
@@ -317,8 +390,8 @@
int set_hugetlb_mem_size(int count)
{
- int j, lcount;
- struct page *page, *map;
+ int lcount;
+ struct page *page ;
extern long htlbzone_pages;
extern struct list_head htlbpage_freelist;
@@ -417,5 +490,4 @@
struct vm_operations_struct hugetlb_vm_ops = {
.nopage = hugetlb_nopage,
- .close = zap_hugetlb_resources,
};
diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
--- a/arch/ia64/mm/tlb.c Mon Mar 17 13:45:14 2003
+++ b/arch/ia64/mm/tlb.c Mon Mar 17 13:45:14 2003
@@ -81,9 +81,13 @@
}
read_unlock(&tasklist_lock);
/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
- for (i = 0; i < NR_CPUS; ++i)
- if (i != smp_processor_id())
- per_cpu(ia64_need_tlb_flush, i) = 1;
+ {
+ int cpu = get_cpu(); /* prevent preemption/migration */
+ for (i = 0; i < NR_CPUS; ++i)
+ if (i != cpu)
+ per_cpu(ia64_need_tlb_flush, i) = 1;
+ put_cpu();
+ }
local_flush_tlb_all();
}
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c Mon Mar 17 13:45:12 2003
+++ b/arch/ia64/pci/pci.c Mon Mar 17 13:45:12 2003
@@ -143,21 +143,7 @@
return;
}
-void __devinit
-pcibios_update_resource (struct pci_dev *dev, struct resource *root,
- struct resource *res, int resource)
-{
- unsigned long where, size;
- u32 reg;
-
- where = PCI_BASE_ADDRESS_0 + (resource * 4);
- size = res->end - res->start;
- pci_read_config_dword(dev, where, ®);
- reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
- pci_write_config_dword(dev, where, reg);
-
- /* ??? FIXME -- record old value for shutdown. */
-}
+#warning pcibios_update_resource() is now a generic implementation - please check
void __devinit
pcibios_update_irq (struct pci_dev *dev, int irq)
@@ -167,11 +153,6 @@
/* ??? FIXME -- record old value for shutdown. */
}
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
-{
-}
-
static inline int
pcibios_enable_resources (struct pci_dev *dev, int mask)
{
@@ -271,4 +252,77 @@
return -EAGAIN;
return 0;
+}
+
+/**
+ * pci_cacheline_size - determine cacheline size for PCI devices
+ * @dev: void
+ *
+ * We want to use the line-size of the outer-most cache. We assume
+ * that this line-size is the same for all CPUs.
+ *
+ * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
+ *
+ * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ */
+static unsigned long
+pci_cacheline_size (void)
+{
+ u64 levels, unique_caches;
+ s64 status;
+ pal_cache_config_info_t cci;
+ static u8 cacheline_size;
+
+ if (cacheline_size)
+ return cacheline_size;
+
+ status = ia64_pal_cache_summary(&levels, &unique_caches);
+ if (status != 0) {
+ printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
+ __FUNCTION__, status);
+ return SMP_CACHE_BYTES;
+ }
+
+ status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2,
+ &cci);
+ if (status != 0) {
+ printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n",
+ __FUNCTION__, status);
+ return SMP_CACHE_BYTES;
+ }
+ cacheline_size = 1 << cci.pcci_line_size;
+ return cacheline_size;
+}
+
+/**
+ * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi()
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * For ia64, we can get the cacheline sizes from PAL.
+ *
+ * RETURNS: An appropriate -ERRNO error value on eror, or zero for success.
+ */
+int
+pcibios_prep_mwi (struct pci_dev *dev)
+{
+ unsigned long desired_linesize, current_linesize;
+ int rc = 0;
+ u8 pci_linesize;
+
+ desired_linesize = pci_cacheline_size();
+
+ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize);
+ current_linesize = 4 * pci_linesize;
+ if (desired_linesize != current_linesize) {
+ printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,",
+ dev->slot_name, current_linesize);
+ if (current_linesize > desired_linesize) {
+ printk(" expected %lu bytes instead\n", desired_linesize);
+ rc = -EINVAL;
+ } else {
+ printk(" correcting to %lu\n", desired_linesize);
+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4);
+ }
+ }
+ return rc;
}
diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile
--- a/arch/ia64/sn/io/Makefile Mon Mar 17 13:45:10 2003
+++ b/arch/ia64/sn/io/Makefile Mon Mar 17 13:45:10 2003
@@ -17,6 +17,6 @@
hcl.o labelcl.o invent.o sgi_io_sim.o \
klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \
alenlist.o pci.o pci_dma.o ate_utils.o \
- ifconfig_net.o io.o ifconfig_bus.o
+ ifconfig_net.o io.o ioconfig_bus.o
obj-$(CONFIG_PCIBA) += pciba.o
diff -Nru a/arch/ia64/sn/io/ioconfig_bus.c b/arch/ia64/sn/io/ioconfig_bus.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/ioconfig_bus.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,402 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * ioconfig_bus - SGI's Persistent PCI Bus Numbering.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
+#define SGI_IOCONFIG_BUS_VERSION "1.0"
+
+/*
+ * Some Global definitions.
+ */
+devfs_handle_t ioconfig_bus_handle = NULL;
+unsigned long ioconfig_bus_debug = 0;
+
+#ifdef IOCONFIG_BUS_DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u64 ioconfig_file = 0;
+u64 ioconfig_file_size = 0;
+u64 ioconfig_activated = 0;
+char ioconfig_kernopts[128];
+
+/*
+ * For debugging purpose .. hardcode a table ..
+ */
+struct ascii_moduleid *ioconfig_bus_table;
+u64 ioconfig_bus_table_size = 0;
+
+
+int free_entry = 0;
+int new_entry = 0;
+
+int next_basebus_number = 0;
+
+void
+ioconfig_get_busnum(char *io_moduleid, int *bus_num)
+{
+ struct ascii_moduleid *temp;
+ int index;
+
+ DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
+
+ *bus_num = -1;
+ temp = ioconfig_bus_table;
+ for (index = 0; index < free_entry; temp++, index++) {
+ if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
+ (io_moduleid[1] == temp->io_moduleid[1]) &&
+ (io_moduleid[2] == temp->io_moduleid[2]) &&
+ (io_moduleid[4] == temp->io_moduleid[4]) &&
+ (io_moduleid[5] == temp->io_moduleid[5]) ) {
+ *bus_num = index * 0x10;
+ return;
+ }
+ }
+
+ /*
+ * New IO Brick encountered.
+ */
+ if (((int)io_moduleid[0]) == 0) {
+ DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
+ return;
+ }
+
+ io_moduleid[3] = '#';
+ strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
+ *bus_num = free_entry * 0x10;
+ free_entry++;
+}
+
+void
+dump_ioconfig_table()
+{
+
+ int index = 0;
+ struct ascii_moduleid *temp;
+
+ temp = ioconfig_bus_table;
+ while (index < free_entry) {
+ DBG("ASSCI Module ID %s\n", temp->io_moduleid);
+ temp++;
+ index++;
+ }
+}
+
+/*
+ * nextline
+ * This routine returns the nextline in the buffer.
+ */
+int nextline(char *buffer, char **next, char *line)
+{
+
+ char *temp;
+
+ if (buffer[0] == 0x0) {
+ return(0);
+ }
+
+ temp = buffer;
+ while (*temp != 0) {
+ *line = *temp;
+ if (*temp != '\n'){
+ *line = *temp;
+ temp++; line++;
+ } else
+ break;
+ }
+
+ if (*temp == 0)
+ *next = temp;
+ else
+ *next = ++temp;
+
+ return(1);
+}
+
+/*
+ * build_pcibus_name
+ * This routine parses the ioconfig contents read into
+ * memory by ioconfig command in EFI and builds the
+ * persistent pci bus naming table.
+ */
+void
+build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
+{
+ /*
+ * Read the whole file into memory.
+ */
+ int rc;
+ char *name;
+ char *temp;
+ char *next;
+ char *current;
+ char *line;
+ struct ascii_moduleid *moduleid;
+
+ line = kmalloc(256, GFP_KERNEL);
+ memset(line, 0,256);
+ name = kmalloc(125, GFP_KERNEL);
+ memset(name, 0, 125);
+ moduleid = table;
+ current = file_contents;
+ while (nextline(current, &next, line)){
+
+ DBG("current 0x%lx next 0x%lx\n", current, next);
+
+ temp = line;
+ /*
+ * Skip all leading Blank lines ..
+ */
+ while (isspace(*temp))
+ if (*temp != '\n')
+ temp++;
+ else
+ break;
+
+ if (*temp == '\n') {
+ current = next;
+ memset(line, 0, 256);
+ continue;
+ }
+
+ /*
+ * Skip comment lines
+ */
+ if (*temp == '#') {
+ current = next;
+ memset(line, 0, 256);
+ continue;
+ }
+
+ /*
+ * Get the next free entry in the table.
+ */
+ rc = sscanf(temp, "%s", name);
+ strcpy(&moduleid->io_moduleid[0], name);
+ DBG("Found %s\n", name);
+ moduleid++;
+ free_entry++;
+ current = next;
+ memset(line, 0, 256);
+ }
+
+ new_entry = free_entry;
+ kfree(line);
+ kfree(name);
+
+ return;
+}
+
+void
+ioconfig_bus_init(void)
+{
+
+ struct ia64_sal_retval ret_stuff;
+ u64 *temp;
+ int cnode;
+
+ DBG("ioconfig_bus_init called.\n");
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+ nasid_t nasid;
+ /*
+ * Make SAL call to get the address of the bus configuration table.
+ */
+ ret_stuff.status = (uint64_t)0;
+ ret_stuff.v0 = (uint64_t)0;
+ ret_stuff.v1 = (uint64_t)0;
+ ret_stuff.v2 = (uint64_t)0;
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+ SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0);
+ temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0);
+ ioconfig_file = *temp;
+ DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid,
+ ret_stuff.v0);
+ if (ioconfig_file) {
+ ioconfig_file_size = ret_stuff.v1;
+ ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE);
+ ioconfig_activated = 1;
+ break;
+ }
+ }
+
+ DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n",
+ ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size);
+
+ ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
+ memset(ioconfig_bus_table, 0, 512);
+
+ /*
+ * If ioconfig options are given on the bootline .. take it.
+ */
+ if (*ioconfig_kernopts != '\0') {
+ /*
+ * ioconfig="..." kernel options given.
+ */
+ DBG("ioconfig_bus_init: Kernel Options given.\n");
+ (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table);
+ (void) dump_ioconfig_table(ioconfig_bus_table);
+ return;
+ }
+
+ if (ioconfig_activated) {
+ DBG("ioconfig_bus_init: ioconfig file given.\n");
+ (void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table);
+ (void) dump_ioconfig_table(ioconfig_bus_table);
+ } else {
+ DBG("ioconfig_bus_init: ioconfig command not executed in prom\n");
+ }
+
+}
+
+void
+ioconfig_bus_new_entries(void)
+{
+
+
+ int index = 0;
+ struct ascii_moduleid *temp;
+
+ if ((ioconfig_activated) && (free_entry > new_entry)) {
+ printk("### Please add the following new IO Bricks Module ID \n");
+ printk("### to your Persistent Bus Numbering Config File\n");
+ } else
+ return;
+
+ index = new_entry;
+ temp = &ioconfig_bus_table[index];
+ while (index < free_entry) {
+ printk("%s\n", temp);
+ temp++;
+ index++;
+ }
+ printk("### End\n");
+
+}
+static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+
+ struct ioconfig_parm parm;
+
+ /*
+ * Copy in the parameters.
+ */
+ copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
+ parm.number = free_entry - new_entry;
+ parm.ioconfig_activated = ioconfig_activated;
+ copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm));
+ copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry));
+
+ return 0;
+}
+
+/*
+ * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
+ */
+static int ioconfig_bus_open(struct inode * inode, struct file * filp)
+{
+ if (ioconfig_bus_debug) {
+ DBG("ioconfig_bus_open called.\n");
+ }
+
+ return(0);
+
+}
+
+/*
+ * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
+ */
+static int ioconfig_bus_close(struct inode * inode, struct file * filp)
+{
+
+ if (ioconfig_bus_debug) {
+ DBG("ioconfig_bus_close called.\n");
+ }
+
+ return(0);
+}
+
+struct file_operations ioconfig_bus_fops = {
+ ioctl:ioconfig_bus_ioctl,
+ open:ioconfig_bus_open, /* open */
+ release:ioconfig_bus_close /* release */
+};
+
+
+/*
+ * init_ifconfig_bus() - Boot time initialization. Ensure that it is called
+ * after devfs has been initialized.
+ *
+ */
+int init_ioconfig_bus(void)
+{
+ ioconfig_bus_handle = NULL;
+ ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
+ 0, DEVFS_FL_AUTO_DEVNUM,
+ 0, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+ &ioconfig_bus_fops, NULL);
+
+ if (ioconfig_bus_handle == NULL) {
+ panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
+ }
+
+ return(0);
+
+}
+
+static int __init ioconfig_bus_setup (char *str)
+{
+
+ char *temp;
+
+ DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
+
+ temp = (char *)ioconfig_kernopts;
+ memset(temp, 0, 128);
+ while ( (*str != '\0') && !isspace (*str) ) {
+ if (*str == ',') {
+ *temp = '\n';
+ temp++;
+ str++;
+ continue;
+ }
+ *temp = *str;
+ temp++;
+ str++;
+ }
+
+ return(0);
+
+}
+__setup("ioconfig=", ioconfig_bus_setup);
diff -Nru a/arch/ia64/sn/io/sn2/Makefile b/arch/ia64/sn/io/sn2/Makefile
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/Makefile Mon Mar 17 13:45:16 2003
@@ -0,0 +1,19 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
+#
+# Makefile for the sn2 specific io routines.
+
+EXTRA_CFLAGS := -DLITTLE_ENDIAN
+
+obj-y += bte_error.o geo_op.o klconflib.o klgraph.o l1.o \
+ l1_command.o ml_iograph.o ml_SN_init.o ml_SN_intr.o module.o \
+ pci_bus_cvlink.o pciio.o pic.o sgi_io_init.o shub.o shuberror.o \
+ shub_intr.o shubio.o xbow.o xtalk.o
+
+obj-$(CONFIG_KDB) += kdba_io.o
+
+obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o
diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/geo_op.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,314 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * @doc file m:hwcfg
+ * DESCRIPTION:
+ *
+ * This file contains routines for manipulating and generating
+ * Geographic IDs. They are in a file by themself since they have
+ * no dependencies on other modules.
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/********** Global functions and data (visible outside the module) ***********/
+
+/*
+ * @doc gf:geo_module
+ *
+ * moduleid_t geo_module(geoid_t g)
+ *
+ * DESCRIPTION:
+ *
+ * Return the moduleid component of a geoid.
+ *
+ * INTERNALS:
+ *
+ * Return INVALID_MODULE for an invalid geoid. Otherwise extract the
+ * moduleid from the structure, and return it.
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+moduleid_t
+geo_module(geoid_t g)
+{
+ if (g.any.type == GEO_TYPE_INVALID)
+ return INVALID_MODULE;
+ else
+ return g.any.module;
+}
+
+
+/*
+ * @doc gf:geo_slab
+ *
+ * slabid_t geo_slab(geoid_t g)
+ *
+ * DESCRIPTION:
+ *
+ * Return the slabid component of a geoid.
+ *
+ * INTERNALS:
+ *
+ * Return INVALID_SLAB for an invalid geoid. Otherwise extract the
+ * slabid from the structure, and return it.
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+slabid_t
+geo_slab(geoid_t g)
+{
+ if (g.any.type == GEO_TYPE_INVALID)
+ return INVALID_SLAB;
+ else
+ return g.any.slab;
+}
+
+
+/*
+ * @doc gf:geo_type
+ *
+ * geo_type_t geo_type(geoid_t g)
+ *
+ * DESCRIPTION:
+ *
+ * Return the type component of a geoid.
+ *
+ * INTERNALS:
+ *
+ * Extract the type from the structure, and return it.
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+geo_type_t
+geo_type(geoid_t g)
+{
+ return g.any.type;
+}
+
+
+/*
+ * @doc gf:geo_valid
+ *
+ * int geo_valid(geoid_t g)
+ *
+ * DESCRIPTION:
+ *
+ * Return nonzero if g has a valid geoid type.
+ *
+ * INTERNALS:
+ *
+ * Test the type against GEO_TYPE_INVALID, and return the result.
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+int
+geo_valid(geoid_t g)
+{
+ return g.any.type != GEO_TYPE_INVALID;
+}
+
+
+/*
+ * @doc gf:geo_cmp
+ *
+ * int geo_cmp(geoid_t g0, geoid_t g1)
+ *
+ * DESCRIPTION:
+ *
+ * Compare two geoid_t values, from the coarsest field to the finest.
+ * The comparison should be consistent with the physical locations of
+ * of the hardware named by the geoids.
+ *
+ * INTERNALS:
+ *
+ * First compare the module, then the slab, type, and type-specific fields.
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+int
+geo_cmp(geoid_t g0, geoid_t g1)
+{
+ int rv;
+
+ /* Compare the common fields */
+ rv = MODULE_CMP(geo_module(g0), geo_module(g1));
+ if (rv != 0)
+ return rv;
+
+ rv = geo_slab(g0) - geo_slab(g1);
+ if (rv != 0)
+ return rv;
+
+ /* Within a slab, sort by type */
+ rv = geo_type(g0) - geo_type(g1);
+ if (rv != 0)
+ return rv;
+
+ switch(geo_type(g0)) {
+ case GEO_TYPE_CPU:
+ rv = g0.cpu.slice - g1.cpu.slice;
+ break;
+
+ case GEO_TYPE_IOCARD:
+ rv = g0.pcicard.bus - g1.pcicard.bus;
+ if (rv) break;
+ rv = SLOTNUM_GETSLOT(g0.pcicard.slot) -
+ SLOTNUM_GETSLOT(g1.pcicard.slot);
+ break;
+
+ case GEO_TYPE_MEM:
+ rv = g0.mem.membus - g1.mem.membus;
+ if (rv) break;
+ rv = g0.mem.memslot - g1.mem.memslot;
+ break;
+
+ default:
+ rv = 0;
+ }
+
+ return rv;
+}
+
+
+/*
+ * @doc gf:geo_new
+ *
+ * geoid_t geo_new(geo_type_t type, ...)
+ *
+ * DESCRIPTION:
+ *
+ * Generate a new geoid_t value of the given type from its components.
+ * Expected calling sequences:
+ * \@itemize \@bullet
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_INVALID)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\}
+ * \@item
+ * \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\}
+ * \@end itemize
+ *
+ * Invalid types return a GEO_TYPE_INVALID geoid_t.
+ *
+ * INTERNALS:
+ *
+ * Use the type to determine which fields to expect. Write the fields into
+ * a new geoid_t and return it. Note: scalars smaller than an "int" are
+ * promoted to "int" by the "..." operator, so we need extra casts on "char",
+ * "slotid_t", and "slabid_t".
+ *
+ * ORIGIN:
+ *
+ * New for SN2
+ */
+
+geoid_t
+geo_new(geo_type_t type, ...)
+{
+ va_list al;
+ geoid_t g;
+ memset(&g, 0, sizeof(g));
+
+ va_start(al, type);
+
+ /* Make sure the type is sane */
+ if (type >= GEO_TYPE_MAX)
+ type = GEO_TYPE_INVALID;
+
+ g.any.type = type;
+ if (type == GEO_TYPE_INVALID)
+ goto done; /* invalid geoids have no components at all */
+
+ g.any.module = va_arg(al, moduleid_t);
+ if (type == GEO_TYPE_MODULE)
+ goto done;
+
+ g.any.slab = (slabid_t)va_arg(al, int);
+
+ /* Some types have additional components */
+ switch(type) {
+ case GEO_TYPE_CPU:
+ g.cpu.slice = (char)va_arg(al, int);
+ break;
+
+ case GEO_TYPE_IOCARD:
+ g.pcicard.bus = (char)va_arg(al, int);
+ g.pcicard.slot = (slotid_t)va_arg(al, int);
+ break;
+
+ case GEO_TYPE_MEM:
+ g.mem.membus = (char)va_arg(al, int);
+ g.mem.memslot = (char)va_arg(al, int);
+ break;
+
+ default:
+ break;
+ }
+
+ done:
+ va_end(al);
+ return g;
+}
diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/klconflib.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,933 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define printf printk
+int hasmetarouter;
+
+#define LDEBUG 0
+#define NIC_UNKNOWN ((nic_t) -1)
+
+#undef DEBUG_KLGRAPH
+#ifdef DEBUG_KLGRAPH
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG_KLGRAPH */
+
+static void sort_nic_names(lboard_t *) ;
+
+u64 klgraph_addr[MAX_COMPACT_NODES];
+int module_number = 0;
+
+lboard_t *
+find_lboard(lboard_t *start, unsigned char brd_type)
+{
+ /* Search all boards stored on this node. */
+ while (start) {
+ if (start->brd_type == brd_type)
+ return start;
+ start = KLCF_NEXT(start);
+ }
+
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_class(lboard_t *start, unsigned char brd_type)
+{
+ /* Search all boards stored on this node. */
+ while (start) {
+ if (KLCLASS(start->brd_type) == KLCLASS(brd_type))
+ return start;
+ start = KLCF_NEXT(start);
+ }
+
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+klinfo_t *
+find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
+{
+ int index, j;
+
+ if (kli == (klinfo_t *)NULL) {
+ index = 0;
+ } else {
+ for (j = 0; j < KLCF_NUM_COMPS(brd); j++) {
+ if (kli == KLCF_COMP(brd, j))
+ break;
+ }
+ index = j;
+ if (index == KLCF_NUM_COMPS(brd)) {
+ DBG("find_component: Bad pointer: 0x%p\n", kli);
+ return (klinfo_t *)NULL;
+ }
+ index++; /* next component */
+ }
+
+ for (; index < KLCF_NUM_COMPS(brd); index++) {
+ kli = KLCF_COMP(brd, index);
+ DBG("find_component: brd %p kli %p request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli));
+ if (KLCF_COMP_TYPE(kli) == struct_type)
+ return kli;
+ }
+
+ /* Didn't find it. */
+ return (klinfo_t *)NULL;
+}
+
+klinfo_t *
+find_first_component(lboard_t *brd, unsigned char struct_type)
+{
+ return find_component(brd, (klinfo_t *)NULL, struct_type);
+}
+
+lboard_t *
+find_lboard_modslot(lboard_t *start, geoid_t geoid)
+{
+ /* Search all boards stored on this node. */
+ while (start) {
+ if (geo_cmp(start->brd_geoid, geoid))
+ return start;
+ start = KLCF_NEXT(start);
+ }
+
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_module(lboard_t *start, geoid_t geoid)
+{
+ /* Search all boards stored on this node. */
+ while (start) {
+ if (geo_cmp(start->brd_geoid, geoid))
+ return start;
+ start = KLCF_NEXT(start);
+ }
+
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+lboard_t *
+find_lboard_module_class(lboard_t *start, geoid_t geoid,
+ unsigned char brd_type)
+{
+ while (start) {
+ DBG("find_lboard_module_class: lboard 0x%p, start->brd_geoid 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_geoid, geoid, start->brd_type, brd_type);
+
+ if (geo_cmp(start->brd_geoid, geoid) &&
+ (KLCLASS(start->brd_type) == KLCLASS(brd_type)))
+ return start;
+ start = KLCF_NEXT(start);
+ }
+
+ /* Didn't find it. */
+ return (lboard_t *)NULL;
+}
+
+/*
+ * Convert a NIC name to a name for use in the hardware graph.
+ */
+void
+nic_name_convert(char *old_name, char *new_name)
+{
+ int i;
+ char c;
+ char *compare_ptr;
+
+ if ((old_name[0] == '\0') || (old_name[1] == '\0')) {
+ strcpy(new_name, EDGE_LBL_XWIDGET);
+ } else {
+ for (i = 0; i < strlen(old_name); i++) {
+ c = old_name[i];
+
+ if (isalpha(c))
+ new_name[i] = tolower(c);
+ else if (isdigit(c))
+ new_name[i] = c;
+ else
+ new_name[i] = '_';
+ }
+ new_name[i] = '\0';
+ }
+
+ /* XXX -
+ * Since a bunch of boards made it out with weird names like
+ * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and
+ * replace it with "baseio" to avoid confusion in the field.
+ * We also have to make sure we don't report media_io instead of
+ * baseio.
+ */
+
+ /* Skip underscores at the beginning of the name */
+ for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++)
+ ;
+
+ /*
+ * Check for some names we need to replace. Early boards
+ * had junk following the name so check only the first
+ * characters.
+ */
+ if (!strncmp(new_name, "io6", 3) ||
+ !strncmp(new_name, "mio", 3) ||
+ !strncmp(new_name, "media_io", 8))
+ strcpy(new_name, "baseio");
+ else if (!strncmp(new_name, "divo", 4))
+ strcpy(new_name, "divo") ;
+
+}
+
+/*
+ * Find the lboard structure and get the board name.
+ * If we can't find the structure or it's too low a revision,
+ * use default name.
+ */
+lboard_t *
+get_board_name(nasid_t nasid, geoid_t geoid, slotid_t slot, char *name)
+{
+ lboard_t *brd;
+
+ brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid),
+ geoid);
+
+#ifndef _STANDALONE
+ {
+ cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid);
+
+ if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID))
+ brd = find_lboard_modslot((lboard_t *)
+ KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer),
+ geoid);
+ }
+#endif
+
+ if (!brd || (brd->brd_sversion < 2)) {
+ strcpy(name, EDGE_LBL_XWIDGET);
+ } else {
+ nic_name_convert(brd->brd_name, name);
+ }
+
+ /*
+ * PV # 540860
+ * If the name is not 'baseio'
+ * get the lowest of all the names in the nic string.
+ * This is needed for boards like divo, which can have
+ * a bunch of daughter cards, but would like to be called
+ * divo. We could do this for baseio
+ * but it has some special case names that we would not
+ * like to disturb at this point.
+ */
+
+ /* gfx boards don't need any of this name scrambling */
+ if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) {
+ return(brd);
+ }
+
+ if (!(!strcmp(name, "baseio") )) {
+ if (brd) {
+ sort_nic_names(brd) ;
+ /* Convert to small case, '-' to '_' etc */
+ nic_name_convert(brd->brd_name, name) ;
+ }
+ }
+
+ return(brd);
+}
+
+/*
+ * get_actual_nasid
+ *
+ * Completely disabled brds have their klconfig on
+ * some other nasid as they have no memory. But their
+ * actual nasid is hidden in the klconfig. Use this
+ * routine to get it. Works for normal boards too.
+ */
+nasid_t
+get_actual_nasid(lboard_t *brd)
+{
+ klhub_t *hub ;
+
+ if (!brd)
+ return INVALID_NASID ;
+
+ /* find out if we are a completely disabled brd. */
+
+ hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+ if (!hub)
+ return INVALID_NASID ;
+ if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */
+ return hub->hub_info.physid ;
+ else
+ return brd->brd_nasid ;
+}
+
+int
+xbow_port_io_enabled(nasid_t nasid, int link)
+{
+ lboard_t *brd;
+ klxbow_t *xbow_p;
+
+ /*
+ * look for boards that might contain an xbow or xbridge
+ */
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW);
+ if (brd == NULL) return 0;
+
+ if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
+ == NULL)
+ return 0;
+
+ if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link))
+ return 0;
+
+ return 1;
+}
+
+void
+board_to_path(lboard_t *brd, char *path)
+{
+ moduleid_t modnum;
+ char *board_name;
+ char buffer[16];
+
+ ASSERT(brd);
+
+ switch (KLCLASS(brd->brd_type)) {
+
+ case KLCLASS_NODE:
+ board_name = EDGE_LBL_NODE;
+ break;
+ case KLCLASS_ROUTER:
+ if (brd->brd_type == KLTYPE_META_ROUTER) {
+ board_name = EDGE_LBL_META_ROUTER;
+ hasmetarouter++;
+ } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) {
+ board_name = EDGE_LBL_REPEATER_ROUTER;
+ hasmetarouter++;
+ } else
+ board_name = EDGE_LBL_ROUTER;
+ break;
+ case KLCLASS_MIDPLANE:
+ board_name = EDGE_LBL_MIDPLANE;
+ break;
+ case KLCLASS_IO:
+ board_name = EDGE_LBL_IO;
+ break;
+ case KLCLASS_IOBRICK:
+ if (brd->brd_type == KLTYPE_PBRICK)
+ board_name = EDGE_LBL_PBRICK;
+ else if (brd->brd_type == KLTYPE_IBRICK)
+ board_name = EDGE_LBL_IBRICK;
+ else if (brd->brd_type == KLTYPE_XBRICK)
+ board_name = EDGE_LBL_XBRICK;
+ else
+ board_name = EDGE_LBL_IOBRICK;
+ break;
+ default:
+ board_name = EDGE_LBL_UNKNOWN;
+ }
+
+ modnum = geo_module(brd->brd_geoid);
+ memset(buffer, 0, 16);
+ format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF);
+ sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name);
+}
+
+/*
+ * Get the module number for a NASID.
+ */
+moduleid_t
+get_module_id(nasid_t nasid)
+{
+ lboard_t *brd;
+
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+
+ if (!brd)
+ return INVALID_MODULE;
+ else
+ return geo_module(brd->brd_geoid);
+}
+
+
+#define MHZ 1000000
+
+
+/* Get the canonical hardware graph name for the given pci component
+ * on the given io board.
+ */
+void
+device_component_canonical_name_get(lboard_t *brd,
+ klinfo_t *component,
+ char *name)
+{
+ slotid_t slot;
+ char board_name[20];
+
+ ASSERT(brd);
+
+ /* Convert the [ CLASS | TYPE ] kind of slotid
+ * into a string
+ */
+ slot = brd->brd_slot;
+
+ /* Get the io board name */
+ if (!brd || (brd->brd_sversion < 2)) {
+ strcpy(name, EDGE_LBL_XWIDGET);
+ } else {
+ nic_name_convert(brd->brd_name, board_name);
+ }
+
+ /* Give out the canonical name of the pci device*/
+ sprintf(name,
+ "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/"
+ EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d",
+ geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid),
+ board_name, KLCF_BRIDGE_W_ID(component));
+}
+
+/*
+ * Get the serial number of the main component of a board
+ * Returns 0 if a valid serial number is found
+ * 1 otherwise.
+ * Assumptions: Nic manufacturing string has the following format
+ * *Serial:;*
+ */
+static int
+component_serial_number_get(lboard_t *board,
+ klconf_off_t mfg_nic_offset,
+ char *serial_number,
+ char *key_pattern)
+{
+
+ char *mfg_nic_string;
+ char *serial_string,*str;
+ int i;
+ char *serial_pattern = "Serial:";
+
+ /* We have an error on a null mfg nic offset */
+ if (!mfg_nic_offset)
+ return(1);
+ /* Get the hub's manufacturing nic information
+ * which is in the form of a pre-formatted string
+ */
+ mfg_nic_string =
+ (char *)NODE_OFFSET_TO_K0(NASID_GET(board),
+ mfg_nic_offset);
+ /* There is no manufacturing nic info */
+ if (!mfg_nic_string)
+ return(1);
+
+ str = mfg_nic_string;
+ /* Look for the key pattern first (if it is specified)
+ * and then print the serial number corresponding to that.
+ */
+ if (strcmp(key_pattern,"") &&
+ !(str = strstr(mfg_nic_string,key_pattern)))
+ return(1);
+
+ /* There is no serial number info in the manufacturing
+ * nic info
+ */
+ if (!(serial_string = strstr(str,serial_pattern)))
+ return(1);
+
+ serial_string = serial_string + strlen(serial_pattern);
+ /* Copy the serial number information from the klconfig */
+ i = 0;
+ while (serial_string[i] != ';') {
+ serial_number[i] = serial_string[i];
+ i++;
+ }
+ serial_number[i] = 0;
+
+ return(0);
+}
+/*
+ * Get the serial number of a board
+ * Returns 0 if a valid serial number is found
+ * 1 otherwise.
+ */
+
+int
+board_serial_number_get(lboard_t *board,char *serial_number)
+{
+ ASSERT(board && serial_number);
+ if (!board || !serial_number)
+ return(1);
+
+ strcpy(serial_number,"");
+ switch(KLCLASS(board->brd_type)) {
+ case KLCLASS_CPU: { /* Node board */
+ klhub_t *hub;
+
+ /* Get the hub component information */
+ hub = (klhub_t *)find_first_component(board,
+ KLSTRUCT_HUB);
+ /* If we don't have a hub component on an IP27
+ * then we have a weird klconfig.
+ */
+ if (!hub)
+ return(1);
+ /* Get the serial number information from
+ * the hub's manufacturing nic info
+ */
+ if (component_serial_number_get(board,
+ hub->hub_mfg_nic,
+ serial_number,
+ "IP37"))
+ return(1);
+ break;
+ }
+ case KLCLASS_IO: { /* IO board */
+ if (KLTYPE(board->brd_type) == KLTYPE_TPU) {
+ /* Special case for TPU boards */
+ kltpu_t *tpu;
+
+ /* Get the tpu component information */
+ tpu = (kltpu_t *)find_first_component(board,
+ KLSTRUCT_TPU);
+ /* If we don't have a tpu component on a tpu board
+ * then we have a weird klconfig.
+ */
+ if (!tpu)
+ return(1);
+ /* Get the serial number information from
+ * the tpu's manufacturing nic info
+ */
+ if (component_serial_number_get(board,
+ tpu->tpu_mfg_nic,
+ serial_number,
+ ""))
+ return(1);
+ break;
+ } else if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ||
+ (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) {
+ /* Special case for GSN boards */
+ klgsn_t *gsn;
+
+ /* Get the gsn component information */
+ gsn = (klgsn_t *)find_first_component(board,
+ ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ?
+ KLSTRUCT_GSN_A : KLSTRUCT_GSN_B));
+ /* If we don't have a gsn component on a gsn board
+ * then we have a weird klconfig.
+ */
+ if (!gsn)
+ return(1);
+ /* Get the serial number information from
+ * the gsn's manufacturing nic info
+ */
+ if (component_serial_number_get(board,
+ gsn->gsn_mfg_nic,
+ serial_number,
+ ""))
+ return(1);
+ break;
+ } else {
+ klbri_t *bridge;
+
+ /* Get the bridge component information */
+ bridge = (klbri_t *)find_first_component(board,
+ KLSTRUCT_BRI);
+ /* If we don't have a bridge component on an IO board
+ * then we have a weird klconfig.
+ */
+ if (!bridge)
+ return(1);
+ /* Get the serial number information from
+ * the bridge's manufacturing nic info
+ */
+ if (component_serial_number_get(board,
+ bridge->bri_mfg_nic,
+ serial_number,
+ ""))
+ return(1);
+ break;
+ }
+ }
+ case KLCLASS_ROUTER: { /* Router board */
+ klrou_t *router;
+
+ /* Get the router component information */
+ router = (klrou_t *)find_first_component(board,
+ KLSTRUCT_ROU);
+ /* If we don't have a router component on a router board
+ * then we have a weird klconfig.
+ */
+ if (!router)
+ return(1);
+ /* Get the serial number information from
+ * the router's manufacturing nic info
+ */
+ if (component_serial_number_get(board,
+ router->rou_mfg_nic,
+ serial_number,
+ ""))
+ return(1);
+ break;
+ }
+ case KLCLASS_GFX: { /* Gfx board */
+ klgfx_t *graphics;
+
+ /* Get the graphics component information */
+ graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX);
+ /* If we don't have a gfx component on a gfx board
+ * then we have a weird klconfig.
+ */
+ if (!graphics)
+ return(1);
+ /* Get the serial number information from
+ * the graphics's manufacturing nic info
+ */
+ if (component_serial_number_get(board,
+ graphics->gfx_mfg_nic,
+ serial_number,
+ ""))
+ return(1);
+ break;
+ }
+ default:
+ strcpy(serial_number,"");
+ break;
+ }
+ return(0);
+}
+
+#include "asm/sn/sn_private.h"
+
+xwidgetnum_t
+nodevertex_widgetnum_get(devfs_handle_t node_vtx)
+{
+ hubinfo_t hubinfo_p;
+
+ hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO,
+ (arbitrary_info_t *) &hubinfo_p);
+ return(hubinfo_p->h_widgetid);
+}
+
+devfs_handle_t
+nodevertex_xbow_peer_get(devfs_handle_t node_vtx)
+{
+ hubinfo_t hubinfo_p;
+ nasid_t xbow_peer_nasid;
+ cnodeid_t xbow_peer;
+
+ hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO,
+ (arbitrary_info_t *) &hubinfo_p);
+ xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer;
+ if(xbow_peer_nasid == INVALID_NASID)
+ return ( (devfs_handle_t)-1);
+ xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid);
+ return(NODEPDA(xbow_peer)->node_vertex);
+}
+
+/* NIC Sorting Support */
+
+#define MAX_NICS_PER_STRING 32
+#define MAX_NIC_NAME_LEN 32
+
+static char *
+get_nic_string(lboard_t *lb)
+{
+ int i;
+ klinfo_t *k = NULL ;
+ klconf_off_t mfg_off = 0 ;
+ char *mfg_nic = NULL ;
+
+ for (i = 0; i < KLCF_NUM_COMPS(lb); i++) {
+ k = KLCF_COMP(lb, i) ;
+ switch(k->struct_type) {
+ case KLSTRUCT_BRI:
+ mfg_off = ((klbri_t *)k)->bri_mfg_nic ;
+ break ;
+
+ case KLSTRUCT_HUB:
+ mfg_off = ((klhub_t *)k)->hub_mfg_nic ;
+ break ;
+
+ case KLSTRUCT_ROU:
+ mfg_off = ((klrou_t *)k)->rou_mfg_nic ;
+ break ;
+
+ case KLSTRUCT_GFX:
+ mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ;
+ break ;
+
+ case KLSTRUCT_TPU:
+ mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ;
+ break ;
+
+ case KLSTRUCT_GSN_A:
+ case KLSTRUCT_GSN_B:
+ mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ;
+ break ;
+
+ case KLSTRUCT_XTHD:
+ mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ;
+ break;
+
+ default:
+ mfg_off = 0 ;
+ break ;
+ }
+ if (mfg_off)
+ break ;
+ }
+
+ if ((mfg_off) && (k))
+ mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ;
+
+ return mfg_nic ;
+}
+
+char *
+get_first_string(char **ptrs, int n)
+{
+ int i ;
+ char *tmpptr ;
+
+ if ((ptrs == NULL) || (n == 0))
+ return NULL ;
+
+ tmpptr = ptrs[0] ;
+
+ if (n == 1)
+ return tmpptr ;
+
+ for (i = 0 ; i < n ; i++) {
+ if (strcmp(tmpptr, ptrs[i]) > 0)
+ tmpptr = ptrs[i] ;
+ }
+
+ return tmpptr ;
+}
+
+int
+get_ptrs(char *idata, char **ptrs, int n, char *label)
+{
+ int i = 0 ;
+ char *tmp = idata ;
+
+ if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0))
+ return 0 ;
+
+ while ( (tmp = strstr(tmp, label)) ){
+ tmp += strlen(label) ;
+ /* check for empty name field, and last NULL ptr */
+ if ((i < (n-1)) && (*tmp != ';')) {
+ ptrs[i++] = tmp ;
+ }
+ }
+
+ ptrs[i] = NULL ;
+
+ return i ;
+}
+
+/*
+ * sort_nic_names
+ *
+ * Does not really do sorting. Find the alphabetically lowest
+ * name among all the nic names found in a nic string.
+ *
+ * Return:
+ * Nothing
+ *
+ * Side Effects:
+ *
+ * lb->brd_name gets the new name found
+ */
+
+static void
+sort_nic_names(lboard_t *lb)
+{
+ char *nic_str ;
+ char *ptrs[MAX_NICS_PER_STRING] ;
+ char name[MAX_NIC_NAME_LEN] ;
+ char *tmp, *tmp1 ;
+
+ *name = 0 ;
+
+ /* Get the nic pointer from the lb */
+
+ if ((nic_str = get_nic_string(lb)) == NULL)
+ return ;
+
+ tmp = get_first_string(ptrs,
+ get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ;
+
+ if (tmp == NULL)
+ return ;
+
+ if ( (tmp1 = strchr(tmp, ';')) ){
+ strncpy(name, tmp, tmp1-tmp) ;
+ name[tmp1-tmp] = 0 ;
+ } else {
+ strncpy(name, tmp, (sizeof(name) -1)) ;
+ name[sizeof(name)-1] = 0 ;
+ }
+
+ strcpy(lb->brd_name, name) ;
+}
+
+
+
+char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#012345";
+
+/*
+ * Format a module id for printing.
+ */
+void
+format_module_id(char *buffer, moduleid_t m, int fmt)
+{
+ int rack, position;
+ char brickchar;
+
+ rack = MODULE_GET_RACK(m);
+ ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES);
+ brickchar = MODULE_GET_BTCHAR(m);
+ position = MODULE_GET_BPOS(m);
+
+ if (fmt == MODULE_FORMAT_BRIEF) {
+ /* Brief module number format, eg. 002c15 */
+
+ /* Decompress the rack number */
+ *buffer++ = '0' + RACK_GET_CLASS(rack);
+ *buffer++ = '0' + RACK_GET_GROUP(rack);
+ *buffer++ = '0' + RACK_GET_NUM(rack);
+
+ /* Add the brick type */
+ *buffer++ = brickchar;
+ }
+ else if (fmt == MODULE_FORMAT_LONG) {
+ /* Fuller hwgraph format, eg. rack/002/bay/15 */
+
+ strcpy(buffer, EDGE_LBL_RACK "/"); buffer += strlen(buffer);
+
+ *buffer++ = '0' + RACK_GET_CLASS(rack);
+ *buffer++ = '0' + RACK_GET_GROUP(rack);
+ *buffer++ = '0' + RACK_GET_NUM(rack);
+
+ strcpy(buffer, "/" EDGE_LBL_RPOS "/"); buffer += strlen(buffer);
+ }
+
+ /* Add the bay position, using at least two digits */
+ if (position < 10)
+ *buffer++ = '0';
+ sprintf(buffer, "%d", position);
+
+}
+
+/*
+ * Parse a module id, in either brief or long form.
+ * Returns < 0 on error.
+ * The long form does not include a brick type, so it defaults to 0 (CBrick)
+ */
+int
+parse_module_id(char *buffer)
+{
+ unsigned int v, rack, bay, type, form;
+ moduleid_t m;
+ char c;
+
+ if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) {
+ form = MODULE_FORMAT_LONG;
+ buffer += strlen(EDGE_LBL_RACK "/");
+
+ /* A long module ID must be exactly 5 non-template chars. */
+ if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5)
+ return -1;
+ }
+ else {
+ form = MODULE_FORMAT_BRIEF;
+
+ /* A brief module id must be exactly 6 characters */
+ if (strlen(buffer) != 6)
+ return -2;
+ }
+
+ /* The rack number must be exactly 3 digits */
+ if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2])))
+ return -3;
+
+ rack = 0;
+ v = *buffer++ - '0';
+ if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
+ return -4;
+ RACK_ADD_CLASS(rack, v);
+
+ v = *buffer++ - '0';
+ if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
+ return -5;
+ RACK_ADD_GROUP(rack, v);
+
+ v = *buffer++ - '0';
+ /* rack numbers are 1-based */
+ if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
+ return -6;
+ RACK_ADD_NUM(rack, v);
+
+ if (form == MODULE_FORMAT_BRIEF) {
+ /* Next should be a module type character. Accept ucase or lcase. */
+ c = *buffer++;
+ if (!isalpha(c))
+ return -7;
+
+ /* strchr() returns a pointer into brick_types[], or NULL */
+ type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types);
+ if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT)
+ return -8;
+ }
+ else {
+ /* Hardcode the module type, and skip over the boilerplate */
+ type = MODULE_CBRICK;
+
+ if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer)
+ return -9;
+
+ buffer += strlen("/" EDGE_LBL_RPOS "/");
+ }
+
+ /* The bay number is last. Make sure it's exactly two digits */
+
+ if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2]))
+ return -10;
+
+ bay = 10 * (buffer[0] - '0') + (buffer[1] - '0');
+
+ if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
+ return -11;
+
+ m = RBT_TO_MODULE(rack, bay, type);
+
+ /* avoid sign extending the moduleid_t */
+ return (int)(unsigned short)m;
+}
diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/klgraph.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,866 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/*
+ * klgraph.c-
+ * This file specifies the interface between the kernel and the PROM's
+ * configuration data structures.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// #define KLGRAPH_DEBUG 1
+#ifdef KLGRAPH_DEBUG
+#define GRPRINTF(x) printk x
+#define CE_GRPANIC CE_PANIC
+#else
+#define GRPRINTF(x)
+#define CE_GRPANIC CE_PANIC
+#endif
+
+#include
+
+extern char arg_maxnodes[];
+extern u64 klgraph_addr[];
+void mark_cpuvertex_as_cpu(devfs_handle_t vhdl, cpuid_t cpuid);
+
+
+/*
+ * Support for verbose inventory via hardware graph.
+ * klhwg_invent_alloc allocates the necessary size of inventory information
+ * and fills in the generic information.
+ */
+invent_generic_t *
+klhwg_invent_alloc(cnodeid_t cnode, int class, int size)
+{
+ invent_generic_t *invent;
+
+ invent = kern_malloc(size);
+ if (!invent) return NULL;
+
+ invent->ig_module = NODE_MODULEID(cnode);
+ invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode));
+ invent->ig_invclass = class;
+
+ return invent;
+}
+
+/*
+ * Add detailed disabled cpu inventory info to the hardware graph.
+ */
+void
+klhwg_disabled_cpu_invent_info(devfs_handle_t cpuv,
+ cnodeid_t cnode,
+ klcpu_t *cpu, slotid_t slot)
+{
+ invent_cpuinfo_t *cpu_invent;
+ diag_inv_t *diag_invent;
+
+ cpu_invent = (invent_cpuinfo_t *)
+ klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
+ if (!cpu_invent)
+ return;
+
+ /* Diag information on this processor */
+ diag_invent = (diag_inv_t *)
+ klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t));
+
+ if (!diag_invent)
+ return;
+
+
+ /* Disabled CPU */
+ cpu_invent->ic_gen.ig_flag = 0x0;
+ cpu_invent->ic_gen.ig_slot = slot;
+ cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
+ cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
+ cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
+
+ cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
+ cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
+ cpu_invent->ic_slice = cpu->cpu_info.physid;
+
+ /* Disabled CPU label */
+ hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+ (arbitrary_info_t) cpu_invent);
+ hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+ sizeof(invent_cpuinfo_t));
+
+ /* Diagval label - stores reason for disable +{virt,phys}id +diagval*/
+ hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL,
+ (arbitrary_info_t) diag_invent);
+
+ hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL,
+ sizeof(diag_inv_t));
+}
+
+/*
+ * Add detailed cpu inventory info to the hardware graph.
+ */
+void
+klhwg_cpu_invent_info(devfs_handle_t cpuv,
+ cnodeid_t cnode,
+ klcpu_t *cpu)
+{
+ invent_cpuinfo_t *cpu_invent;
+
+ cpu_invent = (invent_cpuinfo_t *)
+ klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t));
+ if (!cpu_invent)
+ return;
+
+ if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu))
+ cpu_invent->ic_gen.ig_flag = INVENT_ENABLED;
+ else
+ cpu_invent->ic_gen.ig_flag = 0x0;
+
+ cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid;
+ cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed;
+ cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed;
+
+ cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz;
+ cpu_invent->ic_cpuid = cpu->cpu_info.virtid;
+ cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid);
+
+ hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+ (arbitrary_info_t) cpu_invent);
+ hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT,
+ sizeof(invent_cpuinfo_t));
+}
+
+/*
+ * Add information about the baseio prom version number
+ * as a part of detailed inventory info in the hwgraph.
+ */
+void
+klhwg_baseio_inventory_add(devfs_handle_t baseio_vhdl,cnodeid_t cnode)
+{
+ invent_miscinfo_t *baseio_inventory;
+ unsigned char version = 0,revision = 0;
+
+ /* Allocate memory for the "detailed inventory" info
+ * for the baseio
+ */
+ baseio_inventory = (invent_miscinfo_t *)
+ klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t));
+ baseio_inventory->im_type = INV_IO6PROM;
+ /* Store the revision info in the inventory */
+ baseio_inventory->im_version = version;
+ baseio_inventory->im_rev = revision;
+ /* Put the inventory info in the hardware graph */
+ hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
+ (arbitrary_info_t) baseio_inventory);
+ /* Make the information available to the user programs
+ * thru hwgfs.
+ */
+ hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT,
+ sizeof(invent_miscinfo_t));
+}
+
+char *hub_rev[] = {
+ "0.0",
+ "1.0",
+ "2.0",
+ "2.1",
+ "2.2",
+ "2.3"
+};
+
+/*
+ * Add detailed cpu inventory info to the hardware graph.
+ */
+void
+klhwg_hub_invent_info(devfs_handle_t hubv,
+ cnodeid_t cnode,
+ klhub_t *hub)
+{
+ invent_miscinfo_t *hub_invent;
+
+ hub_invent = (invent_miscinfo_t *)
+ klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t));
+ if (!hub_invent)
+ return;
+
+ if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub))
+ hub_invent->im_gen.ig_flag = INVENT_ENABLED;
+
+ hub_invent->im_type = INV_HUB;
+ hub_invent->im_rev = hub->hub_info.revision;
+ hub_invent->im_speed = hub->hub_speed;
+ hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT,
+ (arbitrary_info_t) hub_invent);
+ hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT,
+ sizeof(invent_miscinfo_t));
+}
+
+/* ARGSUSED */
+void
+klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode)
+{
+ devfs_handle_t myhubv;
+ devfs_handle_t hub_mon;
+ int rc;
+ extern struct file_operations shub_mon_fops;
+
+ GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB));
+ (void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
+ rc = device_master_set(myhubv, node_vertex);
+ hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
+ 0, DEVFS_FL_AUTO_DEVNUM,
+ 0, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+ &shub_mon_fops, (void *)(long)cnode);
+}
+
+/* ARGSUSED */
+void
+klhwg_add_disabled_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot)
+{
+ devfs_handle_t my_cpu;
+ char name[120];
+ cpuid_t cpu_id;
+ nasid_t nasid;
+
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+ cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
+ if(cpu_id != -1){
+ sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
+ (void) hwgraph_path_add(node_vertex, name, &my_cpu);
+
+ mark_cpuvertex_as_cpu(my_cpu, cpu_id);
+ device_master_set(my_cpu, node_vertex);
+
+ klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot);
+ return;
+ }
+}
+
+/* ARGSUSED */
+void
+klhwg_add_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu)
+{
+ devfs_handle_t my_cpu, cpu_dir;
+ char name[120];
+ cpuid_t cpu_id;
+ nasid_t nasid;
+
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+ cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid);
+
+ sprintf(name, "%s/%d/%c",
+ EDGE_LBL_CPUBUS,
+ 0,
+ 'a' + cpu->cpu_info.physid);
+
+ GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex));
+ (void) hwgraph_path_add(node_vertex, name, &my_cpu);
+ mark_cpuvertex_as_cpu(my_cpu, cpu_id);
+ device_master_set(my_cpu, node_vertex);
+
+ /* Add an alias under the node's CPU directory */
+ if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
+ sprintf(name, "%c", 'a' + cpu->cpu_info.physid);
+ (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
+ }
+
+ klhwg_cpu_invent_info(my_cpu, cnode, cpu);
+}
+
+
+void
+klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
+{
+ lboard_t *brd;
+ klxbow_t *xbow_p;
+ nasid_t hub_nasid;
+ cnodeid_t hub_cnode;
+ int widgetnum;
+ devfs_handle_t xbow_v, hubv;
+ /*REFERENCED*/
+ graph_error_t err;
+
+ if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
+ return;
+
+ if (KL_CONFIG_DUPLICATE_BOARD(brd))
+ return;
+
+ GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n",
+ cnode, nasid));
+
+ if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
+ == NULL)
+ return;
+
+ for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+ if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum))
+ continue;
+
+ hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum);
+ if (hub_nasid == INVALID_NASID) {
+ printk(KERN_WARNING "hub widget %d, skipping xbow graph\n", widgetnum);
+ continue;
+ }
+
+ hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid);
+
+ if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) {
+ continue;
+ }
+
+ hubv = cnodeid_to_vertex(hub_cnode);
+
+ err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v);
+ if (err != GRAPH_SUCCESS) {
+ if (err == GRAPH_DUP)
+ printk(KERN_WARNING "klhwg_add_xbow: Check for "
+ "working routers and router links!");
+
+ PRINT_PANIC("klhwg_add_xbow: Failed to add "
+ "edge: vertex 0x%p to vertex 0x%p,"
+ "error %d\n",
+ (void *)hubv, (void *)xbow_v, err);
+ }
+ xswitch_vertex_init(xbow_v);
+
+ NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
+
+ /*
+ * XXX - This won't work is we ever hook up two hubs
+ * by crosstown through a crossbow.
+ */
+ if (hub_nasid != nasid) {
+ NODEPDA(hub_cnode)->xbow_peer = nasid;
+ NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer =
+ hub_nasid;
+ }
+
+ GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n",
+ hub_nasid, EDGE_LBL_XTALK, hubv));
+ }
+}
+
+
+/* ARGSUSED */
+void
+klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap)
+{
+ nasid_t nasid;
+ lboard_t *brd;
+ klhub_t *hub;
+ devfs_handle_t node_vertex = NULL;
+ char path_buffer[100];
+ int rv;
+ char *s;
+ int board_disabled = 0;
+ klcpu_t *cpu;
+
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+ GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n",
+ cnode, nasid, brd));
+ ASSERT(brd);
+
+ do {
+ devfs_handle_t cpu_dir;
+
+ /* Generate a hardware graph path for this board. */
+ board_to_path(brd, path_buffer);
+
+ GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n",
+ path_buffer, hwgraph_root));
+ rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+
+ if (rv != GRAPH_SUCCESS)
+ PRINT_PANIC("Node vertex creation failed. "
+ "Path == %s",
+ path_buffer);
+
+ hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+ ASSERT(hub);
+ if(hub->hub_info.flags & KLINFO_ENABLE)
+ board_disabled = 0;
+ else
+ board_disabled = 1;
+
+ if(!board_disabled) {
+ mark_nodevertex_as_node(node_vertex,
+ cnode + board_disabled * numnodes);
+
+ s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
+ NODEPDA(cnode)->hwg_node_name =
+ kmalloc(strlen(s) + 1,
+ GFP_KERNEL);
+ ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
+ strcpy(NODEPDA(cnode)->hwg_node_name, s);
+
+ hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
+
+ /* Set up node board's slot */
+ NODEPDA(cnode)->slotdesc = brd->brd_slot;
+
+ /* Set up the module we're in */
+ NODEPDA(cnode)->geoid = brd->brd_geoid;
+ NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
+ }
+
+ /* Get the first CPU structure */
+ cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
+
+ /*
+ * If there's at least 1 CPU, add a "cpu" directory to represent
+ * the collection of all CPUs attached to this node.
+ */
+ if (cpu) {
+ graph_error_t rv;
+
+ rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir);
+ if (rv != GRAPH_SUCCESS)
+ panic("klhwg_add_node: Cannot create CPU directory\n");
+ }
+
+ /* Add each CPU */
+ while (cpu) {
+ cpuid_t cpu_id;
+ cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid);
+ if (cpu_enabled(cpu_id))
+ klhwg_add_cpu(node_vertex, cnode, cpu);
+ else
+ klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot);
+
+ cpu = (klcpu_t *)
+ find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU);
+ } /* while */
+
+ if(!board_disabled)
+ klhwg_add_hub(node_vertex, hub, cnode);
+
+ brd = KLCF_NEXT(brd);
+ if (brd)
+ brd = find_lboard(brd, KLTYPE_SNIA);
+ else
+ break;
+ } while(brd);
+}
+
+
+/* ARGSUSED */
+void
+klhwg_add_all_routers(devfs_handle_t hwgraph_root)
+{
+ nasid_t nasid;
+ cnodeid_t cnode;
+ lboard_t *brd;
+ devfs_handle_t node_vertex;
+ char path_buffer[100];
+ int rv;
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n",
+ cnode));
+
+ brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+ KLTYPE_ROUTER);
+
+ if (!brd)
+ /* No routers stored in this node's memory */
+ continue;
+
+ do {
+ ASSERT(brd);
+ GRPRINTF(("Router board struct is %p\n", brd));
+
+ /* Don't add duplicate boards. */
+ if (brd->brd_flags & DUPLICATE_BOARD)
+ continue;
+
+ GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_geoid));
+ /* Generate a hardware graph path for this board. */
+ board_to_path(brd, path_buffer);
+
+ GRPRINTF(("Router path is %s\n", path_buffer));
+
+ /* Add the router */
+ GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n",
+ path_buffer, hwgraph_root));
+ rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+
+ if (rv != GRAPH_SUCCESS)
+ PRINT_PANIC("Router vertex creation "
+ "failed. Path == %s",
+ path_buffer);
+
+ GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n",
+ brd));
+ /* Find the rest of the routers stored on this node. */
+ } while ( (brd = find_lboard_class(KLCF_NEXT(brd),
+ KLTYPE_ROUTER)) );
+
+ GRPRINTF(("klhwg_add_all_routers: Done.\n"));
+ }
+
+}
+
+/* ARGSUSED */
+void
+klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd,
+ cnodeid_t cnode, nasid_t nasid)
+{
+ klrou_t *router;
+ char path_buffer[50];
+ char dest_path[50];
+ devfs_handle_t router_hndl;
+ devfs_handle_t dest_hndl;
+ int rc;
+ int port;
+ lboard_t *dest_brd;
+
+ GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n",
+ cnode));
+
+ /* Don't add duplicate boards. */
+ if (brd->brd_flags & DUPLICATE_BOARD) {
+ GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n",
+ brd, cnode));
+ return;
+ }
+
+ /* Generate a hardware graph path for this board. */
+ board_to_path(brd, path_buffer);
+
+ rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl);
+
+ if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes))
+ return;
+
+ if (rc != GRAPH_SUCCESS)
+ printk(KERN_WARNING "Can't find router: %s", path_buffer);
+
+ /* We don't know what to do with multiple router components */
+ if (brd->brd_numcompts != 1) {
+ PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n",
+ brd->brd_numcompts);
+ return;
+ }
+
+
+ /* Convert component 0 to klrou_t ptr */
+ router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd),
+ brd->brd_compts[0]);
+
+ for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
+ /* See if the port's active */
+ if (router->rou_port[port].port_nasid == INVALID_NASID) {
+ GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n",
+ port));
+ continue;
+ }
+ if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid)
+ == INVALID_CNODEID) {
+ continue;
+ }
+
+ dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+ router->rou_port[port].port_nasid,
+ router->rou_port[port].port_offset);
+
+ /* Generate a hardware graph path for this board. */
+ board_to_path(dest_brd, dest_path);
+
+ rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
+
+ if (rc != GRAPH_SUCCESS) {
+ if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
+ continue;
+ PRINT_PANIC("Can't find router: %s", dest_path);
+ }
+ GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n",
+ path_buffer, port, dest_path));
+
+ sprintf(dest_path, "%d", port);
+
+ rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path);
+
+ if (rc == GRAPH_DUP) {
+ GRPRINTF(("Skipping port %d. nasid %d %s/%s\n",
+ port, router->rou_port[port].port_nasid,
+ path_buffer, dest_path));
+ continue;
+ }
+
+ if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
+ PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
+ path_buffer, dest_path, (void *)dest_hndl, rc);
+
+ }
+}
+
+
+void
+klhwg_connect_routers(devfs_handle_t hwgraph_root)
+{
+ nasid_t nasid;
+ cnodeid_t cnode;
+ lboard_t *brd;
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n",
+ cnode));
+
+ brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
+ KLTYPE_ROUTER);
+
+ if (!brd)
+ continue;
+
+ do {
+
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ klhwg_connect_one_router(hwgraph_root, brd,
+ cnode, nasid);
+
+ /* Find the rest of the routers stored on this node. */
+ } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
+ }
+}
+
+
+
+void
+klhwg_connect_hubs(devfs_handle_t hwgraph_root)
+{
+ nasid_t nasid;
+ cnodeid_t cnode;
+ lboard_t *brd;
+ klhub_t *hub;
+ lboard_t *dest_brd;
+ devfs_handle_t hub_hndl;
+ devfs_handle_t dest_hndl;
+ char path_buffer[50];
+ char dest_path[50];
+ graph_error_t rc;
+ int port;
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+ GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n",
+ cnode));
+
+ brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+ ASSERT(brd);
+
+ hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+ ASSERT(hub);
+
+ for (port = 1; port <= MAX_NI_PORTS; port++) {
+ /* See if the port's active */
+ if (hub->hub_port[port].port_nasid == INVALID_NASID) {
+ GRPRINTF(("klhwg_connect_hubs: port inactive.\n"));
+ continue;
+ }
+
+ if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID)
+ continue;
+
+ /* Generate a hardware graph path for this board. */
+ board_to_path(brd, path_buffer);
+
+ GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer));
+ rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
+
+ if (rc != GRAPH_SUCCESS)
+ printk(KERN_WARNING "Can't find hub: %s", path_buffer);
+
+ dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
+ hub->hub_port[port].port_nasid,
+ hub->hub_port[port].port_offset);
+
+ /* Generate a hardware graph path for this board. */
+ board_to_path(dest_brd, dest_path);
+
+ rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl);
+
+ if (rc != GRAPH_SUCCESS) {
+ if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
+ continue;
+ PRINT_PANIC("Can't find board: %s", dest_path);
+ } else {
+ char buf[1024];
+
+
+ GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n",
+ path_buffer, dest_path));
+
+ rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl);
+ sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT);
+ rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl);
+ sprintf(buf,"%d",port);
+ rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf);
+
+ if (rc != GRAPH_SUCCESS)
+ PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
+ path_buffer, dest_path, (void *)dest_hndl, rc);
+
+ }
+ }
+ }
+}
+
+/* Store the pci/vme disabled board information as extended administrative
+ * hints which can later be used by the drivers using the device/driver
+ * admin interface.
+ */
+void
+klhwg_device_disable_hints_add(void)
+{
+ cnodeid_t cnode; /* node we are looking at */
+ nasid_t nasid; /* nasid of the node */
+ lboard_t *board; /* board we are looking at */
+ int comp_index; /* component index */
+ klinfo_t *component; /* component in the board we are
+ * looking at
+ */
+ char device_name[MAXDEVNAME];
+
+ for(cnode = 0; cnode < numnodes; cnode++) {
+ nasid = COMPACT_TO_NASID_NODEID(cnode);
+ board = (lboard_t *)KL_CONFIG_INFO(nasid);
+ /* Check out all the board info stored on a node */
+ while(board) {
+ /* No need to look at duplicate boards or non-io
+ * boards
+ */
+ if (KL_CONFIG_DUPLICATE_BOARD(board) ||
+ KLCLASS(board->brd_type) != KLCLASS_IO) {
+ board = KLCF_NEXT(board);
+ continue;
+ }
+ /* Check out all the components of a board */
+ for (comp_index = 0;
+ comp_index < KLCF_NUM_COMPS(board);
+ comp_index++) {
+ component = KLCF_COMP(board,comp_index);
+ /* If the component is enabled move on to
+ * the next component
+ */
+ if (KLCONFIG_INFO_ENABLED(component))
+ continue;
+ /* NOTE : Since the prom only supports
+ * the disabling of pci devices the following
+ * piece of code makes sense.
+ * Make sure that this assumption is valid
+ */
+ /* This component is disabled. Store this
+ * hint in the extended device admin table
+ */
+ /* Get the canonical name of the pci device */
+ device_component_canonical_name_get(board,
+ component,
+ device_name);
+#ifdef DEBUG
+ printf("%s DISABLED\n",device_name);
+#endif
+ }
+ /* go to the next board info stored on this
+ * node
+ */
+ board = KLCF_NEXT(board);
+ }
+ }
+}
+
+void
+klhwg_add_all_modules(devfs_handle_t hwgraph_root)
+{
+ cmoduleid_t cm;
+ char name[128];
+ devfs_handle_t vhdl;
+ devfs_handle_t module_vhdl;
+ int rc;
+ char buffer[16];
+
+ /* Add devices under each module */
+
+ for (cm = 0; cm < nummodules; cm++) {
+ /* Use module as module vertex fastinfo */
+
+ memset(buffer, 0, 16);
+ format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF);
+ sprintf(name, EDGE_LBL_MODULE "/%s", buffer);
+
+ rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
+ ASSERT(rc == GRAPH_SUCCESS);
+ rc = rc;
+
+ hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
+
+ /* Add system controller */
+ sprintf(name,
+ EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1,
+ buffer);
+
+ rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
+ ASSERT_ALWAYS(rc == GRAPH_SUCCESS);
+ rc = rc;
+
+ hwgraph_info_add_LBL(vhdl,
+ INFO_LBL_ELSC,
+ (arbitrary_info_t) (__psint_t) 1);
+
+ }
+}
+
+void
+klhwg_add_all_nodes(devfs_handle_t hwgraph_root)
+{
+ cnodeid_t cnode;
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+ klhwg_add_node(hwgraph_root, cnode, NULL);
+ }
+
+ for (cnode = 0; cnode < numnodes; cnode++) {
+ klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode));
+ }
+
+ /*
+ * As for router hardware inventory information, we set this
+ * up in router.c.
+ */
+
+ klhwg_add_all_routers(hwgraph_root);
+ klhwg_connect_routers(hwgraph_root);
+ klhwg_connect_hubs(hwgraph_root);
+
+ /* Go through the entire system's klconfig
+ * to figure out which pci components have been disabled
+ */
+ klhwg_device_disable_hints_add();
+
+}
diff -Nru a/arch/ia64/sn/io/sn2/l1.c b/arch/ia64/sn/io/sn2/l1.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/l1.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,244 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+/* In general, this file is organized in a hierarchy from lower-level
+ * to higher-level layers, as follows:
+ *
+ * UART routines
+ * Bedrock/L1 "PPP-like" protocol implementation
+ * System controller "message" interface (allows multiplexing
+ * of various kinds of requests and responses with
+ * console I/O)
+ * Console interface:
+ * "l1_cons", the glue that allows the L1 to act
+ * as the system console for the stdio libraries
+ *
+ * Routines making use of the system controller "message"-style interface
+ * can be found in l1_command.c.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#define UART_BAUD_RATE 57600
+
+int
+get_L1_baud(void)
+{
+ return UART_BAUD_RATE;
+}
+
+
+
+/* Return the current interrupt level */
+int
+l1_get_intr_value( void )
+{
+ return(0);
+}
+
+/* Disconnect the callup functions - throw away interrupts */
+
+void
+l1_unconnect_intr(void)
+{
+}
+
+/* Set up uart interrupt handling for this node's uart */
+
+void
+l1_connect_intr(void *rx_notify, void *tx_notify)
+{
+#if 0
+ // Will need code here for sn2 - something like this
+ console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid());
+ intr_connect_level(console_nodepda->node_first_cpu,
+ SGI_UART_VECTOR, INTPEND0_MAXMASK,
+ dummy_intr_func);
+ request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8),
+ intr_func, SA_INTERRUPT | SA_SHIRQ,
+ "l1_protocol_driver", (void *)sc);
+#endif
+}
+
+
+/* These are functions to use from serial_in/out when in protocol
+ * mode to send and receive uart control regs. These are external
+ * interfaces into the protocol driver.
+ */
+
+void
+l1_control_out(int offset, int value)
+{
+ /* quietly ignore unless simulator */
+ if ( IS_RUNNING_ON_SIMULATOR() ) {
+ extern u64 master_node_bedrock_address;
+ if ( master_node_bedrock_address != (u64)0 ) {
+ writeb(value, (unsigned long)master_node_bedrock_address +
+ (offset<< 3));
+ }
+ return;
+ }
+}
+
+/* Console input exported interface. Return a register value. */
+
+int
+l1_control_in_polled(int offset)
+{
+ static int l1_control_in_local(int);
+
+ return(l1_control_in_local(offset));
+}
+
+int
+l1_control_in(int offset)
+{
+ static int l1_control_in_local(int);
+
+ return(l1_control_in_local(offset));
+}
+
+static int
+l1_control_in_local(int offset)
+{
+ int sal_call_status = 0, input;
+ int ret = 0;
+
+ if ( IS_RUNNING_ON_SIMULATOR() ) {
+ extern u64 master_node_bedrock_address;
+ ret = readb((unsigned long)master_node_bedrock_address +
+ (offset<< 3));
+ return(ret);
+ }
+ if ( offset == REG_LSR ) {
+ ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */
+ sal_call_status = ia64_sn_console_check(&input);
+ if ( !sal_call_status && input ) {
+ /* input pending */
+ ret |= LSR_RCA;
+ }
+ }
+ return(ret);
+}
+
+/*
+ * Console input exported interface. Return a character (if one is available)
+ */
+
+int
+l1_serial_in_polled(void)
+{
+ static int l1_serial_in_local(void);
+
+ return(l1_serial_in_local());
+}
+
+int
+l1_serial_in(void)
+{
+ static int l1_serial_in_local(void);
+
+ if ( IS_RUNNING_ON_SIMULATOR() ) {
+ extern u64 master_node_bedrock_address;
+ return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
+ }
+ return(l1_serial_in_local());
+}
+
+static int
+l1_serial_in_local(void)
+{
+ int ch;
+
+ if ( IS_RUNNING_ON_SIMULATOR() ) {
+ extern u64 master_node_bedrock_address;
+ return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3)));
+ }
+
+ if ( !(ia64_sn_console_getc(&ch)) )
+ return(ch);
+ else
+ return(0);
+}
+
+/* Console output exported interface. Write message to the console. */
+
+int
+l1_serial_out( char *str, int len )
+{
+ int counter = len;
+
+ /* Ignore empty messages */
+ if ( len == 0 )
+ return(len);
+
+#if defined(CONFIG_IA64_EARLY_PRINTK)
+ /* Need to setup SAL calls so the PROM calls will work */
+ {
+ static int inited;
+ void early_sn_setup(void);
+ if(!inited) {
+ inited=1;
+ early_sn_setup();
+ }
+ }
+#endif
+
+ if ( IS_RUNNING_ON_SIMULATOR() ) {
+ extern u64 master_node_bedrock_address;
+ void early_sn_setup(void);
+ if (!master_node_bedrock_address)
+ early_sn_setup();
+ if ( master_node_bedrock_address != (u64)0 ) {
+#ifdef FLAG_DIRECT_CONSOLE_WRITES
+ /* This is an easy way to pre-pend the output to know whether the output
+ * was done via sal or directly */
+ writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+ writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+ writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+ writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+#endif /* FLAG_DIRECT_CONSOLE_WRITES */
+ while ( counter > 0 ) {
+ writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3));
+ counter--;
+ str++;
+ }
+ }
+ return(len);
+ }
+
+ /* Attempt to write things out thru the sal */
+ if ( ia64_sn_console_putb(str, len) )
+ return(0);
+
+ return((counter <= 0) ? 0 : (len - counter));
+}
diff -Nru a/arch/ia64/sn/io/sn2/l1_command.c b/arch/ia64/sn/io/sn2/l1_command.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/l1_command.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,207 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define ELSC_TIMEOUT 1000000 /* ELSC response timeout (usec) */
+#define LOCK_TIMEOUT 5000000 /* Hub lock timeout (usec) */
+
+#define hub_cpu_get() 0
+
+#define LBYTE(caddr) (*(char *) caddr)
+
+extern char *bcopy(const char * src, char * dest, int count);
+
+#define LDEBUG 0
+
+/*
+ * ELSC data is in NVRAM page 7 at the following offsets.
+ */
+
+#define NVRAM_MAGIC_AD 0x700 /* magic number used for init */
+#define NVRAM_PASS_WD 0x701 /* password (4 bytes in length) */
+#define NVRAM_DBG1 0x705 /* virtual XOR debug switches */
+#define NVRAM_DBG2 0x706 /* physical XOR debug switches */
+#define NVRAM_CFG 0x707 /* ELSC Configuration info */
+#define NVRAM_MODULE 0x708 /* system module number */
+#define NVRAM_BIST_FLG 0x709 /* BIST flags (2 bits per nodeboard) */
+#define NVRAM_PARTITION 0x70a /* module's partition id */
+#define NVRAM_DOMAIN 0x70b /* module's domain id */
+#define NVRAM_CLUSTER 0x70c /* module's cluster id */
+#define NVRAM_CELL 0x70d /* module's cellid */
+
+#define NVRAM_MAGIC_NO 0x37 /* value of magic number */
+#define NVRAM_SIZE 16 /* 16 bytes in nvram */
+
+
+/* elsc_display_line writes up to 12 characters to either the top or bottom
+ * line of the L1 display. line points to a buffer containing the message
+ * to be displayed. The zero-based line number is specified by lnum (so
+ * lnum == 0 specifies the top line and lnum == 1 specifies the bottom).
+ * Lines longer than 12 characters, or line numbers not less than
+ * L1_DISPLAY_LINES, cause elsc_display_line to return an error.
+ */
+int elsc_display_line(nasid_t nasid, char *line, int lnum)
+{
+ return 0;
+}
+
+/*
+ * iobrick routines
+ */
+
+/* iobrick_rack_bay_type_get fills in the three int * arguments with the
+ * rack number, bay number and brick type of the L1 being addressed. Note
+ * that if the L1 operation fails and this function returns an error value,
+ * garbage may be written to brick_type.
+ */
+
+
+int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack,
+ uint *bay, uint *brick_type )
+{
+ int result = 0;
+
+ if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
+ return( ELSC_ERROR_CMD_SEND );
+
+ *rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT;
+ *bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT;
+ *brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT;
+ *brick_type = toupper(*brick_type);
+
+ return 0;
+}
+
+
+int iomoduleid_get(nasid_t nasid)
+{
+
+ int result = 0;
+
+ if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) )
+ return( ELSC_ERROR_CMD_SEND );
+
+ return result;
+
+}
+
+int iobrick_module_get(nasid_t nasid)
+{
+ uint rnum, rack, bay, brick_type, t;
+ int ret;
+
+ /* construct module ID from rack and slot info */
+
+ if ((ret = iobrick_rack_bay_type_get(nasid, &rnum, &bay, &brick_type)) < 0)
+ return ret;
+
+ if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT)
+ return ELSC_ERROR_MODULE;
+
+ /* Build a moduleid_t-compatible rack number */
+
+ rack = 0;
+ t = rnum / 100; /* rack class (CPU/IO) */
+ if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack))
+ return ELSC_ERROR_MODULE;
+ RACK_ADD_CLASS(rack, t);
+ rnum %= 100;
+
+ t = rnum / 10; /* rack group */
+ if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack))
+ return ELSC_ERROR_MODULE;
+ RACK_ADD_GROUP(rack, t);
+
+ t = rnum % 10; /* rack number (one-based) */
+ if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack))
+ return ELSC_ERROR_MODULE;
+ RACK_ADD_NUM(rack, t);
+
+ switch( brick_type ) {
+ case 'I':
+ brick_type = MODULE_IBRICK; break;
+ case 'P':
+ brick_type = MODULE_PBRICK; break;
+ case 'X':
+ brick_type = MODULE_XBRICK; break;
+ }
+
+ ret = RBT_TO_MODULE(rack, bay, brick_type);
+
+ return ret;
+}
+
+/*
+ * iobrick_module_get_nasid() returns a module_id which has the brick
+ * type encoded in bits 15-12, but this is not the true brick type...
+ * The module_id returned by iobrick_module_get_nasid() is modified
+ * to make a PEBRICKs & PXBRICKs look like a PBRICK. So this routine
+ * iobrick_type_get_nasid() returns the true unmodified brick type.
+ */
+int
+iobrick_type_get_nasid(nasid_t nasid)
+{
+ uint rack, bay, type;
+ int t, ret;
+ extern char brick_types[];
+
+ if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) {
+ return ret;
+ }
+
+ /* convert brick_type to lower case */
+ if ((type >= 'A') && (type <= 'Z'))
+ type = type - 'A' + 'a';
+
+ /* convert to a module.h brick type */
+ for( t = 0; t < MAX_BRICK_TYPES; t++ ) {
+ if( brick_types[t] == type )
+ return t;
+ }
+
+ return -1; /* unknown brick */
+}
+
+int iobrick_module_get_nasid(nasid_t nasid)
+{
+ int io_moduleid;
+
+#ifdef PIC_LATER
+ uint rack, bay;
+
+ if (PEBRICK_NODE(nasid)) {
+ if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) {
+ printf("Could not read rack and bay location "
+ "of PEBrick at nasid %d\n", nasid);
+ }
+
+ io_moduleid = peer_iobrick_module_get(sc, rack, bay);
+ }
+#endif /* PIC_LATER */
+ io_moduleid = iobrick_module_get(nasid);
+ return io_moduleid;
+}
diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/ml_SN_init.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,160 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern int numcpus;
+extern char arg_maxnodes[];
+extern cpuid_t master_procid;
+
+extern int hasmetarouter;
+
+int maxcpus;
+cpumask_t boot_cpumask;
+hubreg_t region_mask = 0;
+
+
+extern xwidgetnum_t hub_widget_id(nasid_t);
+
+extern int valid_icache_reasons; /* Reasons to flush the icache */
+extern int valid_dcache_reasons; /* Reasons to flush the dcache */
+extern u_char miniroot;
+extern volatile int need_utlbmiss_patch;
+extern void iograph_early_init(void);
+
+nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */
+nasid_t master_baseio_nasid = INVALID_NASID; /* This is the master base I/O nasid */
+
+
+/*
+ * mlreset(void)
+ * very early machine reset - at this point NO interrupts have been
+ * enabled; nor is memory, tlb, p0, etc setup.
+ *
+ * slave is zero when mlreset is called for the master processor and
+ * is nonzero thereafter.
+ */
+
+
+void
+mlreset(int slave)
+{
+ /*
+ * We are the master cpu and node.
+ */
+ master_nasid = get_nasid();
+ set_master_bridge_base();
+
+ /* We're the master processor */
+ master_procid = smp_processor_id();
+ master_nasid = cpuid_to_nasid(master_procid);
+
+ /*
+ * master_nasid we get back better be same as one from
+ * get_nasid()
+ */
+ ASSERT_ALWAYS(master_nasid == get_nasid());
+
+ /* early initialization of iograph */
+ iograph_early_init();
+
+ /* Initialize Hub Pseudodriver Management */
+ hubdev_init();
+}
+
+
+/* XXX - Move the meat of this to intr.c ? */
+/*
+ * Set up the platform-dependent fields in the nodepda.
+ */
+void init_platform_nodepda(nodepda_t *npda, cnodeid_t node)
+{
+ hubinfo_t hubinfo;
+
+ extern void router_map_init(nodepda_t *);
+ extern void router_queue_init(nodepda_t *,cnodeid_t);
+ extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int);
+
+ /* Allocate per-node platform-dependent data */
+ hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s));
+
+ npda->pdinfo = (void *)hubinfo;
+ hubinfo->h_nodepda = npda;
+ hubinfo->h_cnodeid = node;
+ hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
+
+ spin_lock_init(&hubinfo->h_crblock);
+
+ hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
+ npda->xbow_peer = INVALID_NASID;
+
+ /*
+ * Initialize the linked list of
+ * router info pointers to the dependent routers
+ */
+ npda->npda_rip_first = NULL;
+
+ /*
+ * npda_rip_last always points to the place
+ * where the next element is to be inserted
+ * into the list
+ */
+ npda->npda_rip_last = &npda->npda_rip_first;
+ npda->geoid.any.type = GEO_TYPE_INVALID;
+
+ mutex_init_locked(&npda->xbow_sema); /* init it locked? */
+}
+
+/* XXX - Move the interrupt stuff to intr.c ? */
+/*
+ * Set up the platform-dependent fields in the processor pda.
+ * Must be done _after_ init_platform_nodepda().
+ * If we need a lock here, something else is wrong!
+ */
+void init_platform_pda(cpuid_t cpu)
+{
+}
+
+void
+update_node_information(cnodeid_t cnodeid)
+{
+ nodepda_t *npda = NODEPDA(cnodeid);
+ nodepda_router_info_t *npda_rip;
+
+ /* Go through the list of router info
+ * structures and copy some frequently
+ * accessed info from the info hanging
+ * off the corresponding router vertices
+ */
+ npda_rip = npda->npda_rip_first;
+ while(npda_rip) {
+ if (npda_rip->router_infop) {
+ npda_rip->router_portmask =
+ npda_rip->router_infop->ri_portmask;
+ npda_rip->router_slot =
+ npda_rip->router_infop->ri_slotnum;
+ } else {
+ /* No router, no ports. */
+ npda_rip->router_portmask = 0;
+ }
+ npda_rip = npda_rip->router_next;
+ }
+}
diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/sn/io/sn2/ml_iograph.c Mon Mar 17 13:45:16 2003
@@ -0,0 +1,1395 @@
+/* $Id$
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* #define IOGRAPH_DEBUG */
+#ifdef IOGRAPH_DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* IOGRAPH_DEBUG */
+
+/* #define PROBE_TEST */
+
+/* At most 2 hubs can be connected to an xswitch */
+#define NUM_XSWITCH_VOLUNTEER 2
+
+extern unsigned char Is_pic_on_this_nasid[512];
+
+/*
+ * Track which hubs have volunteered to manage devices hanging off of
+ * a Crosstalk Switch (e.g. xbow). This structure is allocated,
+ * initialized, and hung off the xswitch vertex early on when the
+ * xswitch vertex is created.
+ */
+typedef struct xswitch_vol_s {
+ mutex_t xswitch_volunteer_mutex;
+ int xswitch_volunteer_count;
+ devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];
+} *xswitch_vol_t;
+
+void
+xswitch_vertex_init(devfs_handle_t xswitch)
+{
+ xswitch_vol_t xvolinfo;
+ int rc;
+ extern void * snia_kmem_zalloc(size_t size, int flag);
+
+ xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);
+ mutex_init(&xvolinfo->xswitch_volunteer_mutex);
+ rc = hwgraph_info_add_LBL(xswitch,
+ INFO_LBL_XSWITCH_VOL,
+ (arbitrary_info_t)xvolinfo);
+ ASSERT(rc == GRAPH_SUCCESS); rc = rc;
+}
+
+
+/*
+ * When assignment of hubs to widgets is complete, we no longer need the
+ * xswitch volunteer structure hanging around. Destroy it.
+ */
+static void
+xswitch_volunteer_delete(devfs_handle_t xswitch)
+{
+ xswitch_vol_t xvolinfo;
+ int rc;
+ extern void snia_kmem_free(void *ptr, size_t size);
+
+ rc = hwgraph_info_remove_LBL(xswitch,
+ INFO_LBL_XSWITCH_VOL,
+ (arbitrary_info_t *)&xvolinfo);
+ snia_kmem_free(xvolinfo, sizeof(struct xswitch_vol_s));
+}
+/*
+ * A Crosstalk master volunteers to manage xwidgets on the specified xswitch.
+ */
+/* ARGSUSED */
+static void
+volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master)
+{
+ xswitch_vol_t xvolinfo = NULL;
+ devfs_handle_t hubv;
+ hubinfo_t hubinfo;
+
+ (void)hwgraph_info_get_LBL(xswitch,
+ INFO_LBL_XSWITCH_VOL,
+ (arbitrary_info_t *)&xvolinfo);
+ if (xvolinfo == NULL) {
+ if (!is_headless_node_vertex(master))
+ printk(KERN_WARNING
+ "volunteer for widgets: vertex 0x%p has no info label",
+ (void *)xswitch);
+ return;
+ }
+
+ mutex_lock(&xvolinfo->xswitch_volunteer_mutex);
+ ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);
+ xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;
+ xvolinfo->xswitch_volunteer_count++;
+
+ /*
+ * if dual ported, make the lowest widgetid always be
+ * xswitch_volunteer[0].
+ */
+ if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) {
+ hubv = xvolinfo->xswitch_volunteer[0];
+ hubinfo_get(hubv, &hubinfo);
+ if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) {
+ xvolinfo->xswitch_volunteer[0] =
+ xvolinfo->xswitch_volunteer[1];
+ xvolinfo->xswitch_volunteer[1] = hubv;
+ }
+ }
+ mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);
+}
+
+extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);
+
+/*
+ * Assign all the xwidgets hanging off the specified xswitch to the
+ * Crosstalk masters that have volunteered for xswitch duty.
+ */
+/* ARGSUSED */
+static void
+assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv)
+{
+ xswitch_info_t xswitch_info;
+ xswitch_vol_t xvolinfo = NULL;
+ xwidgetnum_t widgetnum;
+ int num_volunteer;
+ nasid_t nasid;
+ hubinfo_t hubinfo;
+ extern int iobrick_type_get_nasid(nasid_t);
+
+
+ hubinfo_get(hubv, &hubinfo);
+ nasid = hubinfo->h_nasid;
+
+ xswitch_info = xswitch_info_get(xswitch);
+ ASSERT(xswitch_info != NULL);
+
+ (void)hwgraph_info_get_LBL(xswitch,
+ INFO_LBL_XSWITCH_VOL,
+ (arbitrary_info_t *)&xvolinfo);
+ if (xvolinfo == NULL) {
+ if (!is_headless_node_vertex(hubv))
+ printk(KERN_WARNING
+ "assign_widgets_to_volunteers:vertex 0x%p has "
+ " no info label",
+ (void *)xswitch);
+ return;
+ }
+
+ num_volunteer = xvolinfo->xswitch_volunteer_count;
+ ASSERT(num_volunteer > 0);
+
+ /* Assign master hub for xswitch itself. */
+ if (HUB_WIDGET_ID_MIN > 0) {
+ hubv = xvolinfo->xswitch_volunteer[0];
+ xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv);
+ }
+
+ /*
+ * TBD: Use administrative information to alter assignment of
+ * widgets to hubs.
+ */
+ for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+ int i;
+
+ /*
+ * Ignore disabled/empty ports.
+ */
+ if (!xbow_port_io_enabled(nasid, widgetnum))
+ continue;
+
+ /*
+ * If this is the master IO board, assign it to the same
+ * hub that owned it in the prom.
+ */
+ if (is_master_baseio_nasid_widget(nasid, widgetnum)) {
+ extern nasid_t get_master_baseio_nasid(void);
+ for (i=0; i