Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6

This commit is contained in:
Dmitry Torokhov 2007-05-08 01:31:11 -04:00
commit 334d0dd8b6
2168 changed files with 143813 additions and 45260 deletions

View file

@ -1745,8 +1745,9 @@ S: D-64295
S: Germany
N: Andi Kleen
E: ak@muc.de
D: network hacker, syncookies
E: andi@firstfloor.org
U: http://www.halobates.de
D: network, x86, NUMA, various hacks
S: Schwalbenstr. 96
S: 85551 Ottobrunn
S: Germany

View file

@ -41,7 +41,7 @@ psdocs: $(PS)
PDF := $(patsubst %.xml, %.pdf, $(BOOKS))
pdfdocs: $(PDF)
HTML := $(patsubst %.xml, %.html, $(BOOKS))
HTML := $(sort $(patsubst %.xml, %.html, $(BOOKS)))
htmldocs: $(HTML)
MAN := $(patsubst %.xml, %.9, $(BOOKS))
@ -152,6 +152,7 @@ quiet_cmd_db2man = MAN $@
@(which xmlto > /dev/null 2>&1) || \
(echo "*** You need to install xmlto ***"; \
exit 1)
$(Q)mkdir -p $(obj)/man
$(call cmd,db2man)
@touch $@
@ -212,11 +213,7 @@ clean-files := $(DOCBOOKS) \
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
$(C-procfs-example)
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS))
#man put files in man subdir - traverse down
subdir- := man/
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
# Declare the contents of the .PHONY variable as phony. We keep that
# information in a variable se we can use it in if_changed and friends.

View file

@ -1,3 +0,0 @@
# Rules are put in Documentation/DocBook
clean-files := *.9.gz *.sgml manpage.links manpage.refs

View file

@ -0,0 +1,11 @@
00-INDEX
- This file
cache-lock.txt
- HOWTO for blackfin cache locking.
cachefeatures.txt
- Supported cache features.
Filesystems
- Requirements for mounting the root file system.

View file

@ -0,0 +1,169 @@
/*
* File: Documentation/blackfin/Filesystems
* Based on:
* Author:
*
* Created:
* Description: This file contains the simple DMA Implementation for Blackfin
*
* Rev: $Id: Filesystems 2384 2006-11-01 04:12:43Z magicyang $
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
*/
How to mount the root file system in uClinux/Blackfin
-----------------------------------------------------
1 Mounting EXT3 File system.
------------------------
Creating an EXT3 File system for uClinux/Blackfin:
Please follow the steps to form the EXT3 File system and mount the same as root
file system.
a Make an ext3 file system as large as you want the final root file
system.
mkfs.ext3 /dev/ram0 <your-rootfs-size-in-1k-blocks>
b Mount this Empty file system on a free directory as:
mount -t ext3 /dev/ram0 ./test
where ./test is the empty directory.
c Copy your root fs directory that you have so carefully made over.
cp -af /tmp/my_final_rootfs_files/* ./test
(For ex: cp -af uClinux-dist/romfs/* ./test)
d If you have done everything right till now you should be able to see
the required "root" dir's (that's etc, root, bin, lib, sbin...)
e Now unmount the file system
umount ./test
f Create the root file system image.
dd if=/dev/ram0 bs=1k count=<your-rootfs-size-in-1k-blocks> \
> ext3fs.img
Now you have to tell the kernel that will be mounting this file system as
rootfs.
So do a make menuconfig under kernel and select the Ext3 journaling file system
support under File system --> submenu.
2. Mounting EXT2 File system.
-------------------------
By default the ext2 file system image will be created if you invoke make from
the top uClinux-dist directory.
3. Mounting CRAMFS File System
----------------------------
To create a CRAMFS file system image execute the command
mkfs.cramfs ./test cramfs.img
where ./test is the target directory.
4. Mounting ROMFS File System
--------------------------
To create a ROMFS file system image execute the command
genromfs -v -V "ROMdisk" -f romfs.img -d ./test
where ./test is the target directory
5. Mounting the JFFS2 Filesystem
-----------------------------
To create a compressed JFFS filesystem (JFFS2), please execute the command
mkfs.jffs2 -d ./test -o jffs2.img
where ./test is the target directory.
However, please make sure the following is in your kernel config.
/*
* RAM/ROM/Flash chip drivers
*/
#define CONFIG_MTD_CFI 1
#define CONFIG_MTD_ROM 1
/*
* Mapping drivers for chip access
*/
#define CONFIG_MTD_COMPLEX_MAPPINGS 1
#define CONFIG_MTD_BF533 1
#undef CONFIG_MTD_UCLINUX
Through the u-boot boot loader, use the jffs2.img in the corresponding
partition made in linux-2.6.x/drivers/mtd/maps/bf533_flash.c.
NOTE - Currently the Flash driver is available only for EZKIT. Watch out for a
STAMP driver soon.
6. Mounting the NFS File system
-----------------------------
For mounting the NFS please do the following in the kernel config.
In Networking Support --> Networking options --> TCP/IP networking -->
IP: kernel level autoconfiguration
Enable BOOTP Support.
In Kernel hacking --> Compiled-in kernel boot parameter add the following
root=/dev/nfs rw ip=bootp
In File system --> Network File system, Enable
NFS file system support --> NFSv3 client support
Root File system on NFS
in uClibc menuconfig, do the following
In Networking Support
enable Remote Procedure Call (RPC) support
Full RPC Support
On the Host side, ensure that /etc/dhcpd.conf looks something like this
ddns-update-style ad-hoc;
allow bootp;
subnet 10.100.4.0 netmask 255.255.255.0 {
default-lease-time 122209600;
max-lease-time 31557600;
group {
host bf533 {
hardware ethernet 00:CF:52:49:C3:01;
fixed-address 10.100.4.50;
option root-path "/home/nfsmount";
}
}
ensure that /etc/exports looks something like this
/home/nfsmount *(rw,no_root_squash,no_all_squash)
run the following commands as root (may differ depending on your
distribution) :
- service nfs start
- service portmap start
- service dhcpd start
- /usr/sbin/exportfs

View file

@ -0,0 +1,48 @@
/*
* File: Documentation/blackfin/cache-lock.txt
* Based on:
* Author:
*
* Created:
* Description: This file contains the simple DMA Implementation for Blackfin
*
* Rev: $Id: cache-lock.txt 2384 2006-11-01 04:12:43Z magicyang $
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
*/
How to lock your code in cache in uClinux/blackfin
--------------------------------------------------
There are only a few steps required to lock your code into the cache.
Currently you can lock the code by Way.
Below are the interface provided for locking the cache.
1. cache_grab_lock(int Ways);
This function grab the lock for locking your code into the cache specified
by Ways.
2. cache_lock(int Ways);
This function should be called after your critical code has been executed.
Once the critical code exits, the code is now loaded into the cache. This
function locks the code into the cache.
So, the example sequence will be:
cache_grab_lock(WAY0_L); /* Grab the lock */
critical_code(); /* Execute the code of interest */
cache_lock(WAY0_L); /* Lock the cache */
Where WAY0_L signifies WAY0 locking.

View file

@ -0,0 +1,65 @@
/*
* File: Documentation/blackfin/cachefeatures.txt
* Based on:
* Author:
*
* Created:
* Description: This file contains the simple DMA Implementation for Blackfin
*
* Rev: $Id: cachefeatures.txt 2384 2006-11-01 04:12:43Z magicyang $
*
* Modified:
* Copyright 2004-2006 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
*/
- Instruction and Data cache initialization.
icache_init();
dcache_init();
- Instruction and Data cache Invalidation Routines, when flushing the
same is not required.
_icache_invalidate();
_dcache_invalidate();
Also, for invalidating the entire instruction and data cache, the below
routines are provided (another method for invalidation, refer page no 267 and 287 of
ADSP-BF533 Hardware Reference manual)
invalidate_entire_dcache();
invalidate_entire_icache();
-External Flushing of Instruction and data cache routines.
flush_instruction_cache();
flush_data_cache();
- Internal Flushing of Instruction and Data Cache.
icplb_flush();
dcplb_flush();
- Locking the cache.
cache_grab_lock();
cache_lock();
Please refer linux-2.6.x/Documentation/blackfin/cache-lock.txt for how to
lock the cache.
Locking the cache is optional feature.
- Miscellaneous cache functions.
flush_cache_all();
flush_cache_mm();
invalidate_dcache_range();
flush_dcache_range();
flush_dcache_page();
flush_cache_range();
flush_cache_page();
invalidate_dcache_range();
flush_page_to_ram();

View file

@ -55,8 +55,8 @@ aic7*seq.h*
aicasm
aicdb.h*
asm
asm-offsets.*
asm_offsets.*
asm-offsets.h
asm_offsets.h
autoconf.h*
bbootsect
bin2c

View file

@ -182,7 +182,7 @@ For example, you can do something like the following.
...
devres_close_group(dev, my_midlayer_something);
devres_close_group(dev, my_midlayer_create_something);
return 0;
}

View file

@ -117,13 +117,6 @@ Who: Adrian Bunk <bunk@stusta.de>
---------------------------
What: pci_module_init(driver)
When: January 2007
Why: Is replaced by pci_register_driver(pci_driver).
Who: Richard Knutsson <ricknu-0@student.ltu.se> and Greg Kroah-Hartman <gregkh@suse.de>
---------------------------
What: Usage of invalid timevals in setitimer
When: March 2007
Why: POSIX requires to validate timevals in the setitimer call. This
@ -190,18 +183,10 @@ Who: Jean Delvare <khali@linux-fr.org>
---------------------------
What: i2c_adapter.dev
i2c_adapter.list
What: i2c_adapter.list
When: July 2007
Why: Superfluous, given i2c_adapter.class_dev:
* The "dev" was a stand-in for the physical device node that legacy
drivers would not have; but now it's almost always present. Any
remaining legacy drivers must upgrade (they now trigger warnings).
* The "list" duplicates class device children.
The delay in removing this is so upgraded lm_sensors and libsensors
can get deployed. (Removal causes minor changes in the sysfs layout,
notably the location of the adapter type name and parenting the i2c
client hardware directly from their controller.)
Why: Superfluous, this list duplicates the one maintained by the driver
core.
Who: Jean Delvare <khali@linux-fr.org>,
David Brownell <dbrownell@users.sourceforge.net>
@ -314,3 +299,27 @@ Why: Code was merged, then submitter immediately disappeared leaving
Who: David S. Miller <davem@davemloft.net>
---------------------------
What: read_dev_chars(), read_conf_data{,_lpm}() (s390 common I/O layer)
When: December 2007
Why: These functions are a leftover from 2.4 times. They have several
problems:
- Duplication of checks that are done in the device driver's
interrupt handler
- common I/O layer can't do device specific error recovery
- device driver can't be notified for conditions happening during
execution of the function
Device drivers should issue the read device characteristics and read
configuration data ccws and do the appropriate error handling
themselves.
Who: Cornelia Huck <cornelia.huck@de.ibm.com>
---------------------------
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
When: September 2007
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
I2C-over-GPIO drivers.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------

View file

@ -122,21 +122,22 @@ subdirectory has the entries listed in Table 1-1.
Table 1-1: Process specific entries in /proc
..............................................................................
File Content
cmdline Command line arguments
cpu Current and last cpu in which it was executed (2.4)(smp)
cwd Link to the current working directory
environ Values of environment variables
exe Link to the executable of this process
fd Directory, which contains all file descriptors
maps Memory maps to executables and library files (2.4)
mem Memory held by this process
root Link to the root directory of this process
stat Process status
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
smaps Extension based on maps, presenting the rss size for each mapped file
File Content
clear_refs Clears page referenced bits shown in smaps output
cmdline Command line arguments
cpu Current and last cpu in which it was executed (2.4)(smp)
cwd Link to the current working directory
environ Values of environment variables
exe Link to the executable of this process
fd Directory, which contains all file descriptors
maps Memory maps to executables and library files (2.4)
mem Memory held by this process
root Link to the root directory of this process
stat Process status
statm Process memory status information
status Process status in human readable form
wchan If CONFIG_KALLSYMS is set, a pre-decoded wchan
smaps Extension based on maps, the rss size for each mapped file
..............................................................................
For example, to get the status information of a process, all you have to do is

View file

@ -9,6 +9,8 @@ Supported adapters:
* nForce4 MCP-04 10de:0034
* nForce4 MCP51 10de:0264
* nForce4 MCP55 10de:0368
* nForce4 MCP61 10de:03EB
* nForce4 MCP65 10de:0446
Datasheet: not publicly available, but seems to be similar to the
AMD-8111 SMBus 2.0 adapter.

View file

@ -1,4 +1,4 @@
Revision 6, 2005-11-20
Revision 7, 2007-04-19
Jean Delvare <khali@linux-fr.org>
Greg KH <greg@kroah.com>
@ -20,6 +20,10 @@ yours for best results.
Technical changes:
* [Driver type] Any driver that was relying on i2c-isa has to be
converted to a proper isa, platform or pci driver. This is not
covered by this guide.
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
Includes typically look like that:
#include <linux/module.h>
@ -27,12 +31,10 @@ Technical changes:
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-isa.h> /* for ISA drivers */
#include <linux/hwmon.h> /* for hardware monitoring drivers */
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> /* if you need VRM support */
#include <linux/err.h> /* for class registration */
#include <asm/io.h> /* if you have I/O operations */
Please respect this inclusion order. Some extra headers may be
required for a given driver (e.g. "lm75.h").
@ -69,20 +71,16 @@ Technical changes:
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
patch to the Documentation/hwmon/sysfs-interface file.
* [Attach] For I2C drivers, the attach function should make sure
that the adapter's class has I2C_CLASS_HWMON (or whatever class is
suitable for your driver), using the following construct:
* [Attach] The attach function should make sure that the adapter's
class has I2C_CLASS_HWMON (or whatever class is suitable for your
driver), using the following construct:
if (!(adapter->class & I2C_CLASS_HWMON))
return 0;
ISA-only drivers of course don't need this.
Call i2c_probe() instead of i2c_detect().
* [Detect] As mentioned earlier, the flags parameter is gone.
The type_name and client_name strings are replaced by a single
name string, which will be filled with a lowercase, short string.
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
useless. Same for isa-only drivers, as the test would always be
true. Only hybrid drivers (which are quite rare) still need it.
The labels used for error paths are reduced to the number needed.
It is advised that the labels are given descriptive names such as
exit and exit_free. Don't forget to properly set err before

View file

@ -4,17 +4,23 @@ I2C and SMBus
=============
I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
slow two-wire protocol (10-400 kHz), but it suffices for many types of
devices.
slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
extension (3.4 MHz). It provides an inexpensive bus for connecting many
types of devices with infrequent or low bandwidth communications needs.
I2C is widely used with embedded systems. Some systems use variants that
don't meet branding requirements, and so are not advertised as being I2C.
SMBus (System Management Bus) is a subset of the I2C protocol. Many
modern mainboards have a System Management Bus. There are a lot of
devices which can be connected to a SMBus; the most notable are modern
memory chips with EEPROM memories and chips for hardware monitoring.
SMBus (System Management Bus) is based on the I2C protocol, and is mostly
a subset of I2C protocols and signaling. Many I2C devices will work on an
SMBus, but some SMBus protocols add semantics beyond what is required to
achieve I2C branding. Modern PC mainboards rely on SMBus. The most common
devices connected through SMBus are RAM modules configured using I2C EEPROMs,
and hardware monitoring chips.
Because the SMBus is just a special case of the generalized I2C bus, we
can simulate the SMBus protocol on plain I2C busses. The reverse is
regretfully impossible.
Because the SMBus is mostly a subset of the generalized I2C bus, we can
use its protocols on many I2C systems. However, there are systems that don't
meet both SMBus and I2C electrical constraints; and others which can't
implement all the common SMBus protocol semantics or messages.
Terminology
@ -29,6 +35,7 @@ When we talk about I2C, we use the following terms:
An Algorithm driver contains general code that can be used for a whole class
of I2C adapters. Each specific adapter driver depends on one algorithm
driver.
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely
@ -40,6 +47,10 @@ a separate Adapter and Algorithm driver), and drivers for your I2C devices
in this package. See the lm_sensors project http://www.lm-sensors.nu
for device drivers.
At this time, Linux only operates I2C (or SMBus) in master mode; you can't
use these APIs to make a Linux system behave as a slave/device, either to
speak a custom protocol or to emulate some other device.
Included Bus Drivers
====================

View file

@ -1,5 +1,5 @@
This is a small guide for those who want to write kernel drivers for I2C
or SMBus devices.
or SMBus devices, using Linux as the protocol host/master (not slave).
To set up a driver, you need to do several things. Some are optional, and
some things can be done slightly or completely different. Use this as a
@ -29,8 +29,16 @@ static struct i2c_driver foo_driver = {
.driver = {
.name = "foo",
},
/* iff driver uses driver model ("new style") binding model: */
.probe = foo_probe,
.remove = foo_remove,
/* else, driver uses "legacy" binding model: */
.attach_adapter = foo_attach_adapter,
.detach_client = foo_detach_client,
/* these may be used regardless of the driver binding model */
.shutdown = foo_shutdown, /* optional */
.suspend = foo_suspend, /* optional */
.resume = foo_resume, /* optional */
@ -40,7 +48,8 @@ static struct i2c_driver foo_driver = {
The name field is the driver name, and must not contain spaces. It
should match the module name (if the driver can be compiled as a module),
although you can use MODULE_ALIAS (passing "foo" in this example) to add
another name for the module.
another name for the module. If the driver name doesn't match the module
name, the module won't be automatically loaded (hotplug/coldplug).
All other fields are for call-back functions which will be explained
below.
@ -65,16 +74,13 @@ An example structure is below.
struct foo_data {
struct i2c_client client;
struct semaphore lock; /* For ISA access in `sensors' drivers. */
int sysctl_id; /* To keep the /proc directory entry for
`sensors' drivers. */
enum chips type; /* To keep the chips type for `sensors' drivers. */
/* Because the i2c bus is slow, it is often useful to cache the read
information of a chip for some time (for example, 1 or 2 seconds).
It depends of course on the device whether this is really worthwhile
or even sensible. */
struct semaphore update_lock; /* When we are reading lots of information,
struct mutex update_lock; /* When we are reading lots of information,
another process should not update the
below information */
char valid; /* != 0 if the following fields are valid. */
@ -95,8 +101,7 @@ some obscure clients). But we need generic reading and writing routines.
I have found it useful to define foo_read and foo_write function for this.
For some cases, it will be easier to call the i2c functions directly,
but many chips have some kind of register-value idea that can easily
be encapsulated. Also, some chips have both ISA and I2C interfaces, and
it useful to abstract from this (only for `sensors' drivers).
be encapsulated.
The below functions are simple examples, and should not be copied
literally.
@ -119,28 +124,101 @@ literally.
return i2c_smbus_write_word_data(client,reg,value);
}
For sensors code, you may have to cope with ISA registers too. Something
like the below often works. Note the locking!
int foo_read_value(struct i2c_client *client, u8 reg)
{
int res;
if (i2c_is_isa_client(client)) {
down(&(((struct foo_data *) (client->data)) -> lock));
outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET);
res = inb_p(client->addr + FOO_DATA_REG_OFFSET);
up(&(((struct foo_data *) (client->data)) -> lock));
return res;
} else
return i2c_smbus_read_byte_data(client,reg);
}
Writing is done the same way.
Probing and attaching
=====================
The Linux I2C stack was originally written to support access to hardware
monitoring chips on PC motherboards, and thus it embeds some assumptions
that are more appropriate to SMBus (and PCs) than to I2C. One of these
assumptions is that most adapters and devices drivers support the SMBUS_QUICK
protocol to probe device presence. Another is that devices and their drivers
can be sufficiently configured using only such probe primitives.
As Linux and its I2C stack became more widely used in embedded systems
and complex components such as DVB adapters, those assumptions became more
problematic. Drivers for I2C devices that issue interrupts need more (and
different) configuration information, as do drivers handling chip variants
that can't be distinguished by protocol probing, or which need some board
specific information to operate correctly.
Accordingly, the I2C stack now has two models for associating I2C devices
with their drivers: the original "legacy" model, and a newer one that's
fully compatible with the Linux 2.6 driver model. These models do not mix,
since the "legacy" model requires drivers to create "i2c_client" device
objects after SMBus style probing, while the Linux driver model expects
drivers to be given such device objects in their probe() routines.
Standard Driver Model Binding ("New Style")
-------------------------------------------
System infrastructure, typically board-specific initialization code or
boot firmware, reports what I2C devices exist. For example, there may be
a table, in the kernel or from the boot loader, identifying I2C devices
and linking them to board-specific configuration information about IRQs
and other wiring artifacts, chip type, and so on. That could be used to
create i2c_client objects for each I2C device.
I2C device drivers using this binding model work just like any other
kind of driver in Linux: they provide a probe() method to bind to
those devices, and a remove() method to unbind.
static int foo_probe(struct i2c_client *client);
static int foo_remove(struct i2c_client *client);
Remember that the i2c_driver does not create those client handles. The
handle may be used during foo_probe(). If foo_probe() reports success
(zero not a negative status code) it may save the handle and use it until
foo_remove() returns. That binding model is used by most Linux drivers.
Drivers match devices when i2c_client.driver_name and the driver name are
the same; this approach is used in several other busses that don't have
device typing support in the hardware. The driver and module name should
match, so hotplug/coldplug mechanisms will modprobe the driver.
Device Creation (Standard driver model)
---------------------------------------
If you know for a fact that an I2C device is connected to a given I2C bus,
you can instantiate that device by simply filling an i2c_board_info
structure with the device address and driver name, and calling
i2c_new_device(). This will create the device, then the driver core will
take care of finding the right driver and will call its probe() method.
If a driver supports different device types, you can specify the type you
want using the type field. You can also specify an IRQ and platform data
if needed.
Sometimes you know that a device is connected to a given I2C bus, but you
don't know the exact address it uses. This happens on TV adapters for
example, where the same driver supports dozens of slightly different
models, and I2C device addresses change from one model to the next. In
that case, you can use the i2c_new_probed_device() variant, which is
similar to i2c_new_device(), except that it takes an additional list of
possible I2C addresses to probe. A device is created for the first
responsive address in the list. If you expect more than one device to be
present in the address range, simply call i2c_new_probed_device() that
many times.
The call to i2c_new_device() or i2c_new_probed_device() typically happens
in the I2C bus driver. You may want to save the returned i2c_client
reference for later use.
Device Deletion (Standard driver model)
---------------------------------------
Each I2C device which has been created using i2c_new_device() or
i2c_new_probed_device() can be unregistered by calling
i2c_unregister_device(). If you don't call it explicitly, it will be
called automatically before the underlying I2C bus itself is removed, as a
device can't survive its parent in the device driver model.
Legacy Driver Binding Model
---------------------------
Most i2c devices can be present on several i2c addresses; for some this
is determined in hardware (by soldering some chip pins to Vcc or Ground),
for others this can be changed in software (by writing to specific client
@ -157,13 +235,9 @@ detection algorithm.
You do not have to use this parameter interface; but don't try to use
function i2c_probe() if you don't.
NOTE: If you want to write a `sensors' driver, the interface is slightly
different! See below.
Probing classes
---------------
Probing classes (Legacy model)
------------------------------
All parameters are given as lists of unsigned 16-bit integers. Lists are
terminated by I2C_CLIENT_END.
@ -210,8 +284,8 @@ Note that you *have* to call the defined variable `normal_i2c',
without any prefix!
Attaching to an adapter
-----------------------
Attaching to an adapter (Legacy model)
--------------------------------------
Whenever a new adapter is inserted, or for all adapters if the driver is
being registered, the callback attach_adapter() is called. Now is the
@ -237,17 +311,13 @@ them (unless a `force' parameter was used). In addition, addresses that
are already in use (by some other registered client) are skipped.
The detect client function
--------------------------
The detect client function (Legacy model)
-----------------------------------------
The detect client function is called by i2c_probe. The `kind' parameter
contains -1 for a probed detection, 0 for a forced detection, or a positive
number for a forced detection with a chip type forced.
Below, some things are only needed if this is a `sensors' driver. Those
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
markers.
Returning an error different from -ENODEV in a detect function will cause
the detection to stop: other addresses and adapters won't be scanned.
This should only be done on fatal or internal errors, such as a memory
@ -256,64 +326,20 @@ shortage or i2c_attach_client failing.
For now, you can ignore the `flags' parameter. It is there for future use.
int foo_detect_client(struct i2c_adapter *adapter, int address,
unsigned short flags, int kind)
int kind)
{
int err = 0;
int i;
struct i2c_client *new_client;
struct i2c_client *client;
struct foo_data *data;
const char *client_name = ""; /* For non-`sensors' drivers, put the real
name here! */
const char *name = "";
/* Let's see whether this adapter can support what we need.
Please substitute the things you need here!
For `sensors' drivers, add `! is_isa &&' to the if statement */
Please substitute the things you need here! */
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_WRITE_BYTE))
goto ERROR0;
/* SENSORS ONLY START */
const char *type_name = "";
int is_isa = i2c_is_isa_adapter(adapter);
/* Do this only if the chip can additionally be found on the ISA bus
(hybrid chip). */
if (is_isa) {
/* Discard immediately if this ISA range is already used */
/* FIXME: never use check_region(), only request_region() */
if (check_region(address,FOO_EXTENT))
goto ERROR0;
/* Probe whether there is anything on this address.
Some example code is below, but you will have to adapt this
for your own driver */
if (kind < 0) /* Only if no force parameter was used */ {
/* We may need long timeouts at least for some chips. */
#define REALLY_SLOW_IO
i = inb_p(address + 1);
if (inb_p(address + 2) != i)
goto ERROR0;
if (inb_p(address + 3) != i)
goto ERROR0;
if (inb_p(address + 7) != i)
goto ERROR0;
#undef REALLY_SLOW_IO
/* Let's just hope nothing breaks here */
i = inb_p(address + 5) & 0x7f;
outb_p(~i & 0x7f,address+5);
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
outb_p(i,address+5);
return 0;
}
}
}
/* SENSORS ONLY END */
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet.
But it allows us to access several i2c functions safely */
@ -323,13 +349,12 @@ For now, you can ignore the `flags' parameter. It is there for future use.
goto ERROR0;
}
new_client = &data->client;
i2c_set_clientdata(new_client, data);
client = &data->client;
i2c_set_clientdata(client, data);
new_client->addr = address;
new_client->adapter = adapter;
new_client->driver = &foo_driver;
new_client->flags = 0;
client->addr = address;
client->adapter = adapter;
client->driver = &foo_driver;
/* Now, we do the remaining detection. If no `force' parameter is used. */
@ -337,19 +362,17 @@ For now, you can ignore the `flags' parameter. It is there for future use.
parameter was used. */
if (kind < 0) {
/* The below is of course bogus */
if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
goto ERROR1;
}
/* SENSORS ONLY START */
/* Next, specific detection. This is especially important for `sensors'
devices. */
/* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
was used. */
if (kind <= 0) {
i = foo_read(new_client,FOO_REG_CHIPTYPE);
i = foo_read(client, FOO_REG_CHIPTYPE);
if (i == FOO_TYPE_1)
kind = chip1; /* As defined in the enum */
else if (i == FOO_TYPE_2)
@ -363,63 +386,31 @@ For now, you can ignore the `flags' parameter. It is there for future use.
/* Now set the type and chip names */
if (kind == chip1) {
type_name = "chip1"; /* For /proc entry */
client_name = "CHIP 1";
name = "chip1";
} else if (kind == chip2) {
type_name = "chip2"; /* For /proc entry */
client_name = "CHIP 2";
name = "chip2";
}
/* Reserve the ISA region */
if (is_isa)
request_region(address,FOO_EXTENT,type_name);
/* SENSORS ONLY END */
/* Fill in the remaining client fields. */
strcpy(new_client->name,client_name);
/* SENSORS ONLY BEGIN */
strlcpy(client->name, name, I2C_NAME_SIZE);
data->type = kind;
/* SENSORS ONLY END */
data->valid = 0; /* Only if you use this field */
init_MUTEX(&data->update_lock); /* Only if you use this field */
mutex_init(&data->update_lock); /* Only if you use this field */
/* Any other initializations in data must be done here too. */
/* Tell the i2c layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
/* SENSORS ONLY BEGIN */
/* Register a new directory entry with module sensors. See below for
the `template' structure. */
if ((i = i2c_register_entry(new_client, type_name,
foo_dir_table_template,THIS_MODULE)) < 0) {
err = i;
goto ERROR4;
}
data->sysctl_id = i;
/* SENSORS ONLY END */
/* This function can write default values to the client registers, if
needed. */
foo_init_client(new_client);
foo_init_client(client);
/* Tell the i2c layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto ERROR1;
return 0;
/* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */
ERROR4:
i2c_detach_client(new_client);
ERROR3:
ERROR2:
/* SENSORS ONLY START */
if (is_isa)
release_region(address,FOO_EXTENT);
/* SENSORS ONLY END */
ERROR1:
kfree(data);
ERROR0:
@ -427,8 +418,8 @@ For now, you can ignore the `flags' parameter. It is there for future use.
}
Removing the client
===================
Removing the client (Legacy model)
==================================
The detach_client call back function is called when a client should be
removed. It may actually fail, but only when panicking. This code is
@ -436,22 +427,12 @@ much simpler than the attachment code, fortunately!
int foo_detach_client(struct i2c_client *client)
{
int err,i;
/* SENSORS ONLY START */
/* Deregister with the `i2c-proc' module. */
i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
/* SENSORS ONLY END */
int err;
/* Try to detach the client from i2c space */
if ((err = i2c_detach_client(client)))
return err;
/* HYBRID SENSORS CHIP ONLY START */
if i2c_is_isa_client(client)
release_region(client->addr,LM78_EXTENT);
/* HYBRID SENSORS CHIP ONLY END */
kfree(i2c_get_clientdata(client));
return 0;
}
@ -464,45 +445,34 @@ When the kernel is booted, or when your foo driver module is inserted,
you have to do some initializing. Fortunately, just attaching (registering)
the driver module is usually enough.
/* Keep track of how far we got in the initialization process. If several
things have to initialized, and we fail halfway, only those things
have to be cleaned up! */
static int __initdata foo_initialized = 0;
static int __init foo_init(void)
{
int res;
printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
if ((res = i2c_add_driver(&foo_driver))) {
printk("foo: Driver registration failed, module not inserted.\n");
foo_cleanup();
return res;
}
foo_initialized ++;
return 0;
}
void foo_cleanup(void)
static void __exit foo_cleanup(void)
{
if (foo_initialized == 1) {
if ((res = i2c_del_driver(&foo_driver))) {
printk("foo: Driver registration failed, module not removed.\n");
return;
}
foo_initialized --;
}
i2c_del_driver(&foo_driver);
}
/* Substitute your own name and email address */
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
/* a few non-GPL license types are also allowed */
MODULE_LICENSE("GPL");
module_init(foo_init);
module_exit(foo_cleanup);
Note that some functions are marked by `__init', and some data structures
by `__init_data'. Hose functions and structures can be removed after
by `__initdata'. These functions and structures can be removed after
kernel booting (or module loading) is completed.
@ -632,110 +602,7 @@ General purpose routines
Below all general purpose routines are listed, that were not mentioned
before.
/* This call returns a unique low identifier for each registered adapter,
* or -1 if the adapter was not registered.
/* This call returns a unique low identifier for each registered adapter.
*/
extern int i2c_adapter_id(struct i2c_adapter *adap);
The sensors sysctl/proc interface
=================================
This section only applies if you write `sensors' drivers.
Each sensors driver creates a directory in /proc/sys/dev/sensors for each
registered client. The directory is called something like foo-i2c-4-65.
The sensors module helps you to do this as easily as possible.
The template
------------
You will need to define a ctl_table template. This template will automatically
be copied to a newly allocated structure and filled in where necessary when
you call sensors_register_entry.
First, I will give an example definition.
static ctl_table foo_dir_table_template[] = {
{ FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,
&i2c_sysctl_real,NULL,&foo_func },
{ FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,
&i2c_sysctl_real,NULL,&foo_func },
{ FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,
&i2c_sysctl_real,NULL,&foo_data },
{ 0 }
};
In the above example, three entries are defined. They can either be
accessed through the /proc interface, in the /proc/sys/dev/sensors/*
directories, as files named func1, func2 and data, or alternatively
through the sysctl interface, in the appropriate table, with identifiers
FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.
The third, sixth and ninth parameters should always be NULL, and the
fourth should always be 0. The fifth is the mode of the /proc file;
0644 is safe, as the file will be owned by root:root.
The seventh and eighth parameters should be &i2c_proc_real and
&i2c_sysctl_real if you want to export lists of reals (scaled
integers). You can also use your own function for them, as usual.
Finally, the last parameter is the call-back to gather the data
(see below) if you use the *_proc_real functions.
Gathering the data
------------------
The call back functions (foo_func and foo_data in the above example)
can be called in several ways; the operation parameter determines
what should be done:
* If operation == SENSORS_PROC_REAL_INFO, you must return the
magnitude (scaling) in nrels_mag;
* If operation == SENSORS_PROC_REAL_READ, you must read information
from the chip and return it in results. The number of integers
to display should be put in nrels_mag;
* If operation == SENSORS_PROC_REAL_WRITE, you must write the
supplied information to the chip. nrels_mag will contain the number
of integers, results the integers themselves.
The *_proc_real functions will display the elements as reals for the
/proc interface. If you set the magnitude to 2, and supply 345 for
SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would
write 45.6 to the /proc file, it would be returned as 4560 for
SENSORS_PROC_REAL_WRITE. A magnitude may even be negative!
An example function:
/* FOO_FROM_REG and FOO_TO_REG translate between scaled values and
register values. Note the use of the read cache. */
void foo_in(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
struct foo_data *data = client->data;
int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 2;
else if (operation == SENSORS_PROC_REAL_READ) {
/* Update the readings cache (if necessary) */
foo_update_client(client);
/* Get the readings from the cache */
results[0] = FOO_FROM_REG(data->foo_func_base[nr]);
results[1] = FOO_FROM_REG(data->foo_func_more[nr]);
results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);
*nrels_mag = 2;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
/* Update the cache */
data->foo_base[nr] = FOO_TO_REG(results[0]);
/* Update the chip */
foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);
}
if (*nrels_mag >= 2) {
/* Update the cache */
data->foo_more[nr] = FOO_TO_REG(results[1]);
/* Update the chip */
foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);
}
}
}

View file

@ -2,7 +2,7 @@
----------------------------
H. Peter Anvin <hpa@zytor.com>
Last update 2007-01-26
Last update 2007-03-06
On the i386 platform, the Linux kernel uses a rather complicated boot
convention. This has evolved partially due to historical aspects, as
@ -35,9 +35,13 @@ Protocol 2.03: (Kernel 2.4.18-pre1) Explicitly makes the highest possible
initrd address available to the bootloader.
Protocol 2.04: (Kernel 2.6.14) Extend the syssize field to four bytes.
Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable.
Introduce relocatable_kernel and kernel_alignment fields.
Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of
the boot command line
**** MEMORY LAYOUT
@ -133,6 +137,8 @@ Offset Proto Name Meaning
022C/4 2.03+ initrd_addr_max Highest legal initrd address
0230/4 2.05+ kernel_alignment Physical addr alignment required for kernel
0234/1 2.05+ relocatable_kernel Whether kernel is relocatable or not
0235/3 N/A pad2 Unused
0238/4 2.06+ cmdline_size Maximum size of the kernel command line
(1) For backwards compatibility, if the setup_sects field contains 0, the
real value is 4.
@ -233,6 +239,12 @@ filled out, however:
if your ramdisk is exactly 131072 bytes long and this field is
0x37FFFFFF, you can start your ramdisk at 0x37FE0000.)
cmdline_size:
The maximum size of the command line without the terminating
zero. This means that the command line can contain at most
cmdline_size characters. With protocol version 2.05 and
earlier, the maximum size was 255.
**** THE KERNEL COMMAND LINE
@ -241,11 +253,10 @@ loader to communicate with the kernel. Some of its options are also
relevant to the boot loader itself, see "special command line options"
below.
The kernel command line is a null-terminated string currently up to
255 characters long, plus the final null. A string that is too long
will be automatically truncated by the kernel, a boot loader may allow
a longer command line to be passed to permit future kernels to extend
this limit.
The kernel command line is a null-terminated string. The maximum
length can be retrieved from the field cmdline_size. Before protocol
version 2.06, the maximum was 255 characters. A string that is too
long will be automatically truncated by the kernel.
If the boot protocol version is 2.02 or later, the address of the
kernel command line is given by the header field cmd_line_ptr (see

View file

@ -0,0 +1,247 @@
/*
* Exercise /dev/mem mmap cases that have been troublesome in the past
*
* (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
int sum;
int map_mem(char *path, off_t offset, size_t length, int touch)
{
int fd, rc;
void *addr;
int *c;
fd = open(path, O_RDWR);
if (fd == -1) {
perror(path);
return -1;
}
addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (addr == MAP_FAILED)
return 1;
if (touch) {
c = (int *) addr;
while (c < (int *) (offset + length))
sum += *c++;
}
rc = munmap(addr, length);
if (rc == -1) {
perror("munmap");
return -1;
}
close(fd);
return 0;
}
int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
{
struct dirent **namelist;
char *name, *path2;
int i, n, r, rc, result = 0;
struct stat buf;
n = scandir(path, &namelist, 0, alphasort);
if (n < 0) {
perror("scandir");
return -1;
}
for (i = 0; i < n; i++) {
name = namelist[i]->d_name;
if (fnmatch(".", name, 0) == 0)
goto skip;
if (fnmatch("..", name, 0) == 0)
goto skip;
path2 = malloc(strlen(path) + strlen(name) + 3);
strcpy(path2, path);
strcat(path2, "/");
strcat(path2, name);
if (fnmatch(file, name, 0) == 0) {
rc = map_mem(path2, offset, length, touch);
if (rc == 0)
fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
else if (rc > 0)
fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
else {
fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
return rc;
}
} else {
r = lstat(path2, &buf);
if (r == 0 && S_ISDIR(buf.st_mode)) {
rc = scan_sysfs(path2, file, offset, length, touch);
if (rc < 0)
return rc;
}
}
result |= rc;
free(path2);
skip:
free(namelist[i]);
}
free(namelist);
return rc;
}
char buf[1024];
int read_rom(char *path)
{
int fd, rc;
size_t size = 0;
fd = open(path, O_RDWR);
if (fd == -1) {
perror(path);
return -1;
}
rc = write(fd, "1", 2);
if (rc <= 0) {
perror("write");
return -1;
}
do {
rc = read(fd, buf, sizeof(buf));
if (rc > 0)
size += rc;
} while (rc > 0);
close(fd);
return size;
}
int scan_rom(char *path, char *file)
{
struct dirent **namelist;
char *name, *path2;
int i, n, r, rc, result = 0;
struct stat buf;
n = scandir(path, &namelist, 0, alphasort);
if (n < 0) {
perror("scandir");
return -1;
}
for (i = 0; i < n; i++) {
name = namelist[i]->d_name;
if (fnmatch(".", name, 0) == 0)
goto skip;
if (fnmatch("..", name, 0) == 0)
goto skip;
path2 = malloc(strlen(path) + strlen(name) + 3);
strcpy(path2, path);
strcat(path2, "/");
strcat(path2, name);
if (fnmatch(file, name, 0) == 0) {
rc = read_rom(path2);
/*
* It's OK if the ROM is unreadable. Maybe there
* is no ROM, or some other error ocurred. The
* important thing is that no MCA happened.
*/
if (rc > 0)
fprintf(stderr, "PASS: %s read %ld bytes\n", path2, rc);
else {
fprintf(stderr, "PASS: %s not readable\n", path2);
return rc;
}
} else {
r = lstat(path2, &buf);
if (r == 0 && S_ISDIR(buf.st_mode)) {
rc = scan_rom(path2, file);
if (rc < 0)
return rc;
}
}
result |= rc;
free(path2);
skip:
free(namelist[i]);
}
free(namelist);
return rc;
}
main()
{
int rc;
if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
/*
* It's not safe to blindly read the VGA frame buffer. If you know
* how to poke the card the right way, it should respond, but it's
* not safe in general. Many machines, e.g., Intel chipsets, cover
* up a non-responding card by just returning -1, but others will
* report the failure as a machine check.
*/
if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
/*
* Often you can map all the individual pieces above (0-0xA0000,
* 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
* thing at once. This is because the individual pieces use different
* attributes, and there's no single attribute supported over the
* whole region.
*/
rc = map_mem("/dev/mem", 0, 1024*1024, 0);
if (rc == 0)
fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
else if (rc > 0)
fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
else
fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
scan_rom("/sys/devices", "rom");
}

View file

@ -112,16 +112,6 @@ POTENTIAL ATTRIBUTE ALIASING CASES
The /dev/mem mmap constraints apply.
However, since this is for mapping legacy MMIO space, WB access
does not make sense. This matters on machines without legacy
VGA support: these machines may have WB memory for the entire
first megabyte (or even the entire first granule).
On these machines, we could mmap legacy_mem as WB, which would
be safe in terms of attribute aliasing, but X has no way of
knowing that it is accessing regular memory, not a frame buffer,
so the kernel should fail the mmap rather than doing it with WB.
read/write of /dev/mem
This uses copy_from_user(), which implicitly uses a kernel
@ -138,14 +128,20 @@ POTENTIAL ATTRIBUTE ALIASING CASES
ioremap()
This returns a kernel identity mapping for use inside the
kernel.
This returns a mapping for use inside the kernel.
If the region is in kern_memmap, we should use the attribute
specified there. Otherwise, if the EFI memory map reports that
the entire granule supports WB, we should use that (granules
that are partially reserved or occupied by firmware do not appear
in kern_memmap). Otherwise, we should use a UC mapping.
specified there.
If the EFI memory map reports that the entire granule supports
WB, we should use that (granules that are partially reserved
or occupied by firmware do not appear in kern_memmap).
If the granule contains non-WB memory, but we can cover the
region safely with kernel page table mappings, we can use
ioremap_page_range() as most other architectures do.
Failing all of the above, we have to fall back to a UC mapping.
PAST PROBLEM CASES
@ -158,7 +154,7 @@ PAST PROBLEM CASES
succeed. It may create either WB or UC user mappings, depending
on whether the region is in kern_memmap or the EFI memory map.
mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
mmap of 0x0-0x9FFFF /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
See https://bugzilla.novell.com/show_bug.cgi?id=140858.
@ -171,28 +167,25 @@ PAST PROBLEM CASES
so it is safe to use WB mappings.
The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
which will use a granule-sized UC mapping covering 0-0xFFFFF. This
granule covers some WB-only memory, but since UC is non-speculative,
the processor will never generate an uncacheable reference to the
WB-only areas unless the driver explicitly touches them.
which uses a granule-sized UC mapping. This granule will cover some
WB-only memory, but since UC is non-speculative, the processor will
never generate an uncacheable reference to the WB-only areas unless
the driver explicitly touches them.
mmap of 0x0-0xFFFFF legacy_mem by "X"
If the EFI memory map reports this entire range as WB, there
is no VGA MMIO hole, and the mmap should fail or be done with
a WB mapping.
If the EFI memory map reports that the entire range supports the
same attributes, we can allow the mmap (and we will prefer WB if
supported, as is the case with HP sx[12]000 machines with VGA
disabled).
There's no easy way for X to determine whether the 0xA0000-0xBFFFF
region is a frame buffer or just memory, so I think it's best to
just fail this mmap request rather than using a WB mapping. As
far as I know, there's no need to map legacy_mem with WB
mappings.
If EFI reports the range as partly WB and partly UC (as on sx[12]000
machines with VGA enabled), we must fail the mmap because there's no
safe attribute to use.
Otherwise, a UC mapping of the entire region is probably safe.
The VGA hole means the region will not be in kern_memmap. The
HP sx1000 chipset doesn't support UC access to the memory surrounding
the VGA hole, but X doesn't need that area anyway and should not
reference it.
If EFI reports some of the range but not all (as on Intel firmware
that doesn't report the VGA frame buffer at all), we should fail the
mmap and force the user to map just the specific region of interest.
mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
@ -202,6 +195,16 @@ PAST PROBLEM CASES
This is a special case of the previous case, and the mmap should
fail for the same reason as above.
read of /sys/devices/.../rom
For VGA devices, this may cause an ioremap() of 0xC0000. This
used to be done with a UC mapping, because the VGA frame buffer
at 0xA0000 prevents use of a WB granule. The UC mapping causes
an MCA on HP sx[12]000 chipsets.
We should use WB page table mappings to avoid covering the VGA
frame buffer.
NOTES
[1] SDM rev 2.2, vol 2, sec 4.4.1.

File diff suppressed because it is too large Load diff

View file

@ -249,7 +249,7 @@ following files:
--> filename: Makefile
KERNELDIR := /lib/modules/`uname -r`/build
all::
$(MAKE) -C $KERNELDIR M=`pwd` $@
$(MAKE) -C $(KERNELDIR) M=`pwd` $@
# Module specific targets
genbin:

View file

@ -64,6 +64,7 @@ parameter is applicable:
GENERIC_TIME The generic timeofday code is enabled.
NFS Appropriate NFS support is enabled.
OSS OSS sound support is enabled.
PV_OPS A paravirtualized kernel
PARIDE The ParIDE subsystem is enabled.
PARISC The PA-RISC architecture is enabled.
PCI PCI bus support is enabled.
@ -695,8 +696,15 @@ and is between 256 and 4096 characters. It is defined in the file
idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed
See Documentation/ide.txt.
idle= [HW]
Format: idle=poll or idle=halt
idle= [X86]
Format: idle=poll or idle=mwait
Poll forces a polling idle loop that can slightly improves the performance
of waking up a idle CPU, but will use a lot of power and make the system
run hot. Not recommended.
idle=mwait. On systems which support MONITOR/MWAIT but the kernel chose
to not use it because it doesn't save as much power as a normal idle
loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
as idle=poll.
ignore_loglevel [KNL]
Ignore loglevel setting - this will print /all/
@ -1157,6 +1165,11 @@ and is between 256 and 4096 characters. It is defined in the file
nomce [IA-32] Machine Check Exception
noreplace-paravirt [IA-32,PV_OPS] Don't patch paravirt_ops
noreplace-smp [IA-32,SMP] Don't replace SMP instructions
with UP alternatives
noresidual [PPC] Don't use residual data on PReP machines.
noresume [SWSUSP] Disables resume and restores original swap
@ -1562,6 +1575,9 @@ and is between 256 and 4096 characters. It is defined in the file
smart2= [HW]
Format: <io1>[,<io2>[,...,<io8>]]
smp-alt-once [IA-32,SMP] On a hotplug CPU system, only
attempt to substitute SMP alternatives once at boot.
snd-ad1816a= [HW,ALSA]
snd-ad1848= [HW,ALSA]
@ -1820,6 +1836,7 @@ and is between 256 and 4096 characters. It is defined in the file
[USBHID] The interval which mice are to be polled at.
vdso= [IA-32,SH]
vdso=2: enable compat VDSO (default with COMPAT_VDSO)
vdso=1: enable VDSO (default)
vdso=0: disable VDSO mapping

View file

@ -124,10 +124,6 @@ initialization with a pointer to a structure describing the driver
err_handler See Documentation/pci-error-recovery.txt
multithread_probe Enable multi-threaded probe/scan. Driver must
provide its own locking/syncronization for init
operations if this is enabled.
The ID table is an array of struct pci_device_id entries ending with an
all-zero entry. Each entry consists of:
@ -163,9 +159,9 @@ echo "vendor device subvendor subdevice class class_mask driver_data" > \
/sys/bus/pci/drivers/{driver}/new_id
All fields are passed in as hexadecimal values (no leading 0x).
Users need pass only as many fields as necessary:
o vendor, device, subvendor, and subdevice fields default
to PCI_ANY_ID (FFFFFFFF),
The vendor and device fields are mandatory, the others are optional. Users
need pass only as many optional fields as necessary:
o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF)
o class and classmask fields default to 0
o driver_data defaults to 0UL.
@ -549,8 +545,6 @@ pci_find_slot() Find pci_dev corresponding to given bus and
pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3)
pci_find_capability() Find specified capability in device's capability
list.
pci_module_init() Inline helper function for ensuring correct
pci_driver initialization and error handling.
pci_resource_start() Returns bus start address for a given PCI region
pci_resource_end() Returns bus end address for a given PCI region
pci_resource_len() Returns the byte length of a PCI region

View file

@ -0,0 +1,30 @@
PCMCIA Driver
-------------
sysfs
-----
New PCMCIA IDs may be added to a device driver pcmcia_device_id table at
runtime as shown below:
echo "match_flags manf_id card_id func_id function device_no \
prod_id_hash[0] prod_id_hash[1] prod_id_hash[2] prod_id_hash[3]" > \
/sys/bus/pcmcia/drivers/{driver}/new_id
All fields are passed in as hexadecimal values (no leading 0x).
The meaning is described in the PCMCIA specification, the match_flags is
a bitwise or-ed combination from PCMCIA_DEV_ID_MATCH_* constants
defined in include/linux/mod_devicetable.h.
Once added, the driver probe routine will be invoked for any unclaimed
PCMCIA device listed in its (newly updated) pcmcia_device_id list.
A common use-case is to add a new device according to the manufacturer ID
and the card ID (form the manf_id and card_id file in the device tree).
For this, just use:
echo "0x3 manf_id card_id 0 0 0 0 0 0 0" > \
/sys/bus/pcmcia/drivers/{driver}/new_id
after loading the driver.

View file

@ -34,8 +34,12 @@ for 5 seconds, resume devices, unfreeze tasks and enable nonboot CPUs. Then,
we are able to look in the log messages and work out, for example, which code
is being slow and which device drivers are misbehaving.
Reading from this file will display what the mode is currently set
to. Writing to this file will accept one of
Reading from this file will display all supported modes and the currently
selected one in brackets, for example
[shutdown] reboot test testproc
Writing to this file will accept one of
'platform' (only if the platform supports it)
'shutdown'

View file

@ -203,7 +203,7 @@ resume
Usage:
if (dev->driver && dev->driver->suspend)
if (dev->driver && dev->driver->resume)
dev->driver->resume(dev)
The resume callback may be called from any power state, and is always meant to

View file

@ -37,7 +37,11 @@ Supported Cards/Chipsets
9005:0286:9005:029d Adaptec 2420SA (Intruder HP release)
9005:0286:9005:02ac Adaptec 1800 (Typhoon44)
9005:0285:9005:02b5 Adaptec 5445 (Voodoo44)
9005:0285:15d9:02b5 SMC AOC-USAS-S4i
9005:0285:15d9:02c9 SMC AOC-USAS-S4iR
9005:0285:9005:02b6 Adaptec 5805 (Voodoo80)
9005:0285:15d9:02b6 SMC AOC-USAS-S8i
9005:0285:15d9:02ca SMC AOC-USAS-S8iR
9005:0285:9005:02b7 Adaptec 5085 (Voodoo08)
9005:0285:9005:02bb Adaptec 3405 (Marauder40LP)
9005:0285:9005:02bc Adaptec 3805 (Marauder80LP)
@ -93,6 +97,9 @@ Supported Cards/Chipsets
9005:0286:9005:02ae (Aurora Lite ARK)
9005:0285:9005:02b0 (Sunrise Lake ARK)
9005:0285:9005:02b1 Adaptec (Voodoo 8 internal 8 external)
9005:0285:108e:7aac SUN STK RAID REM (Voodoo44 Coyote)
9005:0285:108e:0286 SUN SG-XPCIESAS-R-IN (Cougar)
9005:0285:108e:0287 SUN SG-XPCIESAS-R-EX (Prometheus)
People
-------------------------

View file

@ -562,11 +562,6 @@ if only one has a flaw for some SCSI feature, you can disable the
support by the driver of this feature at linux start-up and enable
this feature after boot-up only for devices that support it safely.
CONFIG_SCSI_NCR53C8XX_PROFILE_SUPPORT (default answer: n)
This option must be set for profiling information to be gathered
and printed out through the proc file system. This features may
impact performances.
CONFIG_SCSI_NCR53C8XX_IOMAPPED (default answer: n)
Answer "y" if you suspect your mother board to not allow memory mapped I/O.
May slow down performance a little. This option is required by

32
Documentation/sh/clk.txt Normal file
View file

@ -0,0 +1,32 @@
Clock framework on SuperH architecture
The framework on SH extends existing API by the function clk_set_rate_ex,
which prototype is as follows:
clk_set_rate_ex (struct clk *clk, unsigned long rate, int algo_id)
The algo_id parameter is used to specify algorithm used to recalculate clocks,
adjanced to clock, specified as first argument. It is assumed that algo_id==0
means no changes to adjanced clock
Internally, the clk_set_rate_ex forwards request to clk->ops->set_rate method,
if it is present in ops structure. The method should set the clock rate and adjust
all needed clocks according to the passed algo_id.
Exact values for algo_id are machine-dependend. For the sh7722, the following
values are defined:
NO_CHANGE = 0,
IUS_N1_N1, /* I:U = N:1, U:Sh = N:1 */
IUS_322, /* I:U:Sh = 3:2:2 */
IUS_522, /* I:U:Sh = 5:2:2 */
IUS_N11, /* I:U:Sh = N:1:1 */
SB_N1, /* Sh:B = N:1 */
SB3_N1, /* Sh:B3 = N:1 */
SB3_32, /* Sh:B3 = 3:2 */
SB3_43, /* Sh:B3 = 4:3 */
SB3_54, /* Sh:B3 = 5:4 */
BP_N1, /* B:P = N:1 */
IP_N1 /* I:P = N:1 */
Each of these constants means relation between clocks that can be set via the FRQCR
register

View file

@ -62,7 +62,7 @@ static struct resource pxa_spi_nssp_resources[] = {
static struct pxa2xx_spi_master pxa_nssp_master_info = {
.ssp_type = PXA25x_NSSP, /* Type of SSP */
.clock_enable = CKEN9_NSSP, /* NSSP Peripheral clock */
.clock_enable = CKEN_NSSP, /* NSSP Peripheral clock */
.num_chipselect = 1, /* Matches the number of chips attached to NSSP */
.enable_dma = 1, /* Enables NSSP DMA */
};

View file

@ -197,11 +197,22 @@ and may not be fast.
panic_on_oom
This enables or disables panic on out-of-memory feature. If this is set to 1,
the kernel panics when out-of-memory happens. If this is set to 0, the kernel
will kill some rogue process, called oom_killer. Usually, oom_killer can kill
rogue processes and system will survive. If you want to panic the system
rather than killing rogue processes, set this to 1.
This enables or disables panic on out-of-memory feature.
If this is set to 0, the kernel will kill some rogue process,
called oom_killer. Usually, oom_killer can kill rogue processes and
system will survive.
If this is set to 1, the kernel panics when out-of-memory happens.
However, if a process limits using nodes by mempolicy/cpusets,
and those nodes become memory exhaustion status, one process
may be killed by oom-killer. No panic occurs in this case.
Because other nodes' memory may be free. This means system total status
may be not fatal yet.
If this is set to 2, the kernel panics compulsorily even on the
above-mentioned.
The default value is 0.
1 and 2 are for failover of clustering. Please select either
according to your policy of failover.

View file

@ -1,6 +1,6 @@
Linux Magic System Request Key Hacks
Documentation for sysrq.c
Last update: 2007-JAN-06
Last update: 2007-MAR-14
* What is the magic SysRq key?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -75,7 +75,7 @@ On all - write a character to /proc/sysrq-trigger. e.g.:
'f' - Will call oom_kill to kill a memory hog process.
'g' - Used by kgdb on ppc platforms.
'g' - Used by kgdb on ppc and sh platforms.
'h' - Will display help (actually any other key than those listed
above will display help. but 'h' is easy to remember :-)

View file

@ -42,7 +42,7 @@ ConnectTech WhiteHEAT 4 port converter
http://www.connecttech.com
For any questions or problems with this driver, please contact
Stuart MacDonald at stuartm@connecttech.com
Connect Tech's Support Department at support@connecttech.com
HandSpring Visor, Palm USB, and Clié USB driver

943
Documentation/vm/slabinfo.c Normal file
View file

@ -0,0 +1,943 @@
/*
* Slabinfo: Tool to get reports about slabs
*
* (C) 2007 sgi, Christoph Lameter <clameter@sgi.com>
*
* Compile by:
*
* gcc -o slabinfo slabinfo.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <getopt.h>
#include <regex.h>
#define MAX_SLABS 500
#define MAX_ALIASES 500
#define MAX_NODES 1024
struct slabinfo {
char *name;
int alias;
int refs;
int aliases, align, cache_dma, cpu_slabs, destroy_by_rcu;
int hwcache_align, object_size, objs_per_slab;
int sanity_checks, slab_size, store_user, trace;
int order, poison, reclaim_account, red_zone;
unsigned long partial, objects, slabs;
int numa[MAX_NODES];
int numa_partial[MAX_NODES];
} slabinfo[MAX_SLABS];
struct aliasinfo {
char *name;
char *ref;
struct slabinfo *slab;
} aliasinfo[MAX_ALIASES];
int slabs = 0;
int aliases = 0;
int alias_targets = 0;
int highest_node = 0;
char buffer[4096];
int show_alias = 0;
int show_slab = 0;
int skip_zero = 1;
int show_numa = 0;
int show_track = 0;
int show_first_alias = 0;
int validate = 0;
int shrink = 0;
int show_inverted = 0;
int show_single_ref = 0;
int show_totals = 0;
int sort_size = 0;
int page_size;
regex_t pattern;
void fatal(const char *x, ...)
{
va_list ap;
va_start(ap, x);
vfprintf(stderr, x, ap);
va_end(ap);
exit(1);
}
void usage(void)
{
printf("slabinfo [-ahnpvtsz] [slab-regexp]\n"
"-a|--aliases Show aliases\n"
"-h|--help Show usage information\n"
"-n|--numa Show NUMA information\n"
"-s|--shrink Shrink slabs\n"
"-v|--validate Validate slabs\n"
"-t|--tracking Show alloc/free information\n"
"-T|--Totals Show summary information\n"
"-l|--slabs Show slabs\n"
"-S|--Size Sort by size\n"
"-z|--zero Include empty slabs\n"
"-f|--first-alias Show first alias\n"
"-i|--inverted Inverted list\n"
"-1|--1ref Single reference\n"
);
}
unsigned long read_obj(char *name)
{
FILE *f = fopen(name, "r");
if (!f)
buffer[0] = 0;
else {
if (!fgets(buffer,sizeof(buffer), f))
buffer[0] = 0;
fclose(f);
if (buffer[strlen(buffer)] == '\n')
buffer[strlen(buffer)] = 0;
}
return strlen(buffer);
}
/*
* Get the contents of an attribute
*/
unsigned long get_obj(char *name)
{
if (!read_obj(name))
return 0;
return atol(buffer);
}
unsigned long get_obj_and_str(char *name, char **x)
{
unsigned long result = 0;
char *p;
*x = NULL;
if (!read_obj(name)) {
x = NULL;
return 0;
}
result = strtoul(buffer, &p, 10);
while (*p == ' ')
p++;
if (*p)
*x = strdup(p);
return result;
}
void set_obj(struct slabinfo *s, char *name, int n)
{
char x[100];
sprintf(x, "%s/%s", s->name, name);
FILE *f = fopen(x, "w");
if (!f)
fatal("Cannot write to %s\n", x);
fprintf(f, "%d\n", n);
fclose(f);
}
/*
* Put a size string together
*/
int store_size(char *buffer, unsigned long value)
{
unsigned long divisor = 1;
char trailer = 0;
int n;
if (value > 1000000000UL) {
divisor = 100000000UL;
trailer = 'G';
} else if (value > 1000000UL) {
divisor = 100000UL;
trailer = 'M';
} else if (value > 1000UL) {
divisor = 100;
trailer = 'K';
}
value /= divisor;
n = sprintf(buffer, "%ld",value);
if (trailer) {
buffer[n] = trailer;
n++;
buffer[n] = 0;
}
if (divisor != 1) {
memmove(buffer + n - 2, buffer + n - 3, 4);
buffer[n-2] = '.';
n++;
}
return n;
}
void decode_numa_list(int *numa, char *t)
{
int node;
int nr;
memset(numa, 0, MAX_NODES * sizeof(int));
while (*t == 'N') {
t++;
node = strtoul(t, &t, 10);
if (*t == '=') {
t++;
nr = strtoul(t, &t, 10);
numa[node] = nr;
if (node > highest_node)
highest_node = node;
}
while (*t == ' ')
t++;
}
}
void slab_validate(struct slabinfo *s)
{
set_obj(s, "validate", 1);
}
void slab_shrink(struct slabinfo *s)
{
set_obj(s, "shrink", 1);
}
int line = 0;
void first_line(void)
{
printf("Name Objects Objsize Space "
"Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n");
}
/*
* Find the shortest alias of a slab
*/
struct aliasinfo *find_one_alias(struct slabinfo *find)
{
struct aliasinfo *a;
struct aliasinfo *best = NULL;
for(a = aliasinfo;a < aliasinfo + aliases; a++) {
if (a->slab == find &&
(!best || strlen(best->name) < strlen(a->name))) {
best = a;
if (strncmp(a->name,"kmall", 5) == 0)
return best;
}
}
if (best)
return best;
fatal("Cannot find alias for %s\n", find->name);
return NULL;
}
unsigned long slab_size(struct slabinfo *s)
{
return s->slabs * (page_size << s->order);
}
void slabcache(struct slabinfo *s)
{
char size_str[20];
char dist_str[40];
char flags[20];
char *p = flags;
if (skip_zero && !s->slabs)
return;
store_size(size_str, slab_size(s));
sprintf(dist_str,"%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs);
if (!line++)
first_line();
if (s->aliases)
*p++ = '*';
if (s->cache_dma)
*p++ = 'd';
if (s->hwcache_align)
*p++ = 'A';
if (s->poison)
*p++ = 'P';
if (s->reclaim_account)
*p++ = 'a';
if (s->red_zone)
*p++ = 'Z';
if (s->sanity_checks)
*p++ = 'F';
if (s->store_user)
*p++ = 'U';
if (s->trace)
*p++ = 'T';
*p = 0;
printf("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n",
s->name, s->objects, s->object_size, size_str, dist_str,
s->objs_per_slab, s->order,
s->slabs ? (s->partial * 100) / s->slabs : 100,
s->slabs ? (s->objects * s->object_size * 100) /
(s->slabs * (page_size << s->order)) : 100,
flags);
}
void slab_numa(struct slabinfo *s)
{
int node;
if (!highest_node)
fatal("No NUMA information available.\n");
if (skip_zero && !s->slabs)
return;
if (!line) {
printf("\nSlab Node ");
for(node = 0; node <= highest_node; node++)
printf(" %4d", node);
printf("\n----------------------");
for(node = 0; node <= highest_node; node++)
printf("-----");
printf("\n");
}
printf("%-21s ", s->name);
for(node = 0; node <= highest_node; node++) {
char b[20];
store_size(b, s->numa[node]);
printf(" %4s", b);
}
printf("\n");
line++;
}
void show_tracking(struct slabinfo *s)
{
printf("\n%s: Calls to allocate a slab object\n", s->name);
printf("---------------------------------------------------\n");
if (read_obj("alloc_calls"))
printf(buffer);
printf("%s: Calls to free a slab object\n", s->name);
printf("-----------------------------------------------\n");
if (read_obj("free_calls"))
printf(buffer);
}
void totals(void)
{
struct slabinfo *s;
int used_slabs = 0;
char b1[20], b2[20], b3[20], b4[20];
unsigned long long max = 1ULL << 63;
/* Object size */
unsigned long long min_objsize = max, max_objsize = 0, avg_objsize;
/* Number of partial slabs in a slabcache */
unsigned long long min_partial = max, max_partial = 0,
avg_partial, total_partial = 0;
/* Number of slabs in a slab cache */
unsigned long long min_slabs = max, max_slabs = 0,
avg_slabs, total_slabs = 0;
/* Size of the whole slab */
unsigned long long min_size = max, max_size = 0,
avg_size, total_size = 0;
/* Bytes used for object storage in a slab */
unsigned long long min_used = max, max_used = 0,
avg_used, total_used = 0;
/* Waste: Bytes used for alignment and padding */
unsigned long long min_waste = max, max_waste = 0,
avg_waste, total_waste = 0;
/* Number of objects in a slab */
unsigned long long min_objects = max, max_objects = 0,
avg_objects, total_objects = 0;
/* Waste per object */
unsigned long long min_objwaste = max,
max_objwaste = 0, avg_objwaste,
total_objwaste = 0;
/* Memory per object */
unsigned long long min_memobj = max,
max_memobj = 0, avg_memobj,
total_objsize = 0;
/* Percentage of partial slabs per slab */
unsigned long min_ppart = 100, max_ppart = 0,
avg_ppart, total_ppart = 0;
/* Number of objects in partial slabs */
unsigned long min_partobj = max, max_partobj = 0,
avg_partobj, total_partobj = 0;
/* Percentage of partial objects of all objects in a slab */
unsigned long min_ppartobj = 100, max_ppartobj = 0,
avg_ppartobj, total_ppartobj = 0;
for (s = slabinfo; s < slabinfo + slabs; s++) {
unsigned long long size;
unsigned long used;
unsigned long long wasted;
unsigned long long objwaste;
long long objects_in_partial_slabs;
unsigned long percentage_partial_slabs;
unsigned long percentage_partial_objs;
if (!s->slabs || !s->objects)
continue;
used_slabs++;
size = slab_size(s);
used = s->objects * s->object_size;
wasted = size - used;
objwaste = s->slab_size - s->object_size;
objects_in_partial_slabs = s->objects -
(s->slabs - s->partial - s ->cpu_slabs) *
s->objs_per_slab;
if (objects_in_partial_slabs < 0)
objects_in_partial_slabs = 0;
percentage_partial_slabs = s->partial * 100 / s->slabs;
if (percentage_partial_slabs > 100)
percentage_partial_slabs = 100;
percentage_partial_objs = objects_in_partial_slabs * 100
/ s->objects;
if (percentage_partial_objs > 100)
percentage_partial_objs = 100;
if (s->object_size < min_objsize)
min_objsize = s->object_size;
if (s->partial < min_partial)
min_partial = s->partial;
if (s->slabs < min_slabs)
min_slabs = s->slabs;
if (size < min_size)
min_size = size;
if (wasted < min_waste)
min_waste = wasted;
if (objwaste < min_objwaste)
min_objwaste = objwaste;
if (s->objects < min_objects)
min_objects = s->objects;
if (used < min_used)
min_used = used;
if (objects_in_partial_slabs < min_partobj)
min_partobj = objects_in_partial_slabs;
if (percentage_partial_slabs < min_ppart)
min_ppart = percentage_partial_slabs;
if (percentage_partial_objs < min_ppartobj)
min_ppartobj = percentage_partial_objs;
if (s->slab_size < min_memobj)
min_memobj = s->slab_size;
if (s->object_size > max_objsize)
max_objsize = s->object_size;
if (s->partial > max_partial)
max_partial = s->partial;
if (s->slabs > max_slabs)
max_slabs = s->slabs;
if (size > max_size)
max_size = size;
if (wasted > max_waste)
max_waste = wasted;
if (objwaste > max_objwaste)
max_objwaste = objwaste;
if (s->objects > max_objects)
max_objects = s->objects;
if (used > max_used)
max_used = used;
if (objects_in_partial_slabs > max_partobj)
max_partobj = objects_in_partial_slabs;
if (percentage_partial_slabs > max_ppart)
max_ppart = percentage_partial_slabs;
if (percentage_partial_objs > max_ppartobj)
max_ppartobj = percentage_partial_objs;
if (s->slab_size > max_memobj)
max_memobj = s->slab_size;
total_partial += s->partial;
total_slabs += s->slabs;
total_size += size;
total_waste += wasted;
total_objects += s->objects;
total_used += used;
total_partobj += objects_in_partial_slabs;
total_ppart += percentage_partial_slabs;
total_ppartobj += percentage_partial_objs;
total_objwaste += s->objects * objwaste;
total_objsize += s->objects * s->slab_size;
}
if (!total_objects) {
printf("No objects\n");
return;
}
if (!used_slabs) {
printf("No slabs\n");
return;
}
/* Per slab averages */
avg_partial = total_partial / used_slabs;
avg_slabs = total_slabs / used_slabs;
avg_size = total_size / used_slabs;
avg_waste = total_waste / used_slabs;
avg_objects = total_objects / used_slabs;
avg_used = total_used / used_slabs;
avg_partobj = total_partobj / used_slabs;
avg_ppart = total_ppart / used_slabs;
avg_ppartobj = total_ppartobj / used_slabs;
/* Per object object sizes */
avg_objsize = total_used / total_objects;
avg_objwaste = total_objwaste / total_objects;
avg_partobj = total_partobj * 100 / total_objects;
avg_memobj = total_objsize / total_objects;
printf("Slabcache Totals\n");
printf("----------------\n");
printf("Slabcaches : %3d Aliases : %3d->%-3d Active: %3d\n",
slabs, aliases, alias_targets, used_slabs);
store_size(b1, total_size);store_size(b2, total_waste);
store_size(b3, total_waste * 100 / total_used);
printf("Memory used: %6s # Loss : %6s MRatio: %6s%%\n", b1, b2, b3);
store_size(b1, total_objects);store_size(b2, total_partobj);
store_size(b3, total_partobj * 100 / total_objects);
printf("# Objects : %6s # PartObj: %6s ORatio: %6s%%\n", b1, b2, b3);
printf("\n");
printf("Per Cache Average Min Max Total\n");
printf("---------------------------------------------------------\n");
store_size(b1, avg_objects);store_size(b2, min_objects);
store_size(b3, max_objects);store_size(b4, total_objects);
printf("#Objects %10s %10s %10s %10s\n",
b1, b2, b3, b4);
store_size(b1, avg_slabs);store_size(b2, min_slabs);
store_size(b3, max_slabs);store_size(b4, total_slabs);
printf("#Slabs %10s %10s %10s %10s\n",
b1, b2, b3, b4);
store_size(b1, avg_partial);store_size(b2, min_partial);
store_size(b3, max_partial);store_size(b4, total_partial);
printf("#PartSlab %10s %10s %10s %10s\n",
b1, b2, b3, b4);
store_size(b1, avg_ppart);store_size(b2, min_ppart);
store_size(b3, max_ppart);
store_size(b4, total_partial * 100 / total_slabs);
printf("%%PartSlab %10s%% %10s%% %10s%% %10s%%\n",
b1, b2, b3, b4);
store_size(b1, avg_partobj);store_size(b2, min_partobj);
store_size(b3, max_partobj);
store_size(b4, total_partobj);
printf("PartObjs %10s %10s %10s %10s\n",
b1, b2, b3, b4);
store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj);
store_size(b3, max_ppartobj);
store_size(b4, total_partobj * 100 / total_objects);
printf("%% PartObj %10s%% %10s%% %10s%% %10s%%\n",
b1, b2, b3, b4);
store_size(b1, avg_size);store_size(b2, min_size);
store_size(b3, max_size);store_size(b4, total_size);
printf("Memory %10s %10s %10s %10s\n",
b1, b2, b3, b4);
store_size(b1, avg_used);store_size(b2, min_used);
store_size(b3, max_used);store_size(b4, total_used);
printf("Used %10s %10s %10s %10s\n",
b1, b2, b3, b4);
store_size(b1, avg_waste);store_size(b2, min_waste);
store_size(b3, max_waste);store_size(b4, total_waste);
printf("Loss %10s %10s %10s %10s\n",
b1, b2, b3, b4);
printf("\n");
printf("Per Object Average Min Max\n");
printf("---------------------------------------------\n");
store_size(b1, avg_memobj);store_size(b2, min_memobj);
store_size(b3, max_memobj);
printf("Memory %10s %10s %10s\n",
b1, b2, b3);
store_size(b1, avg_objsize);store_size(b2, min_objsize);
store_size(b3, max_objsize);
printf("User %10s %10s %10s\n",
b1, b2, b3);
store_size(b1, avg_objwaste);store_size(b2, min_objwaste);
store_size(b3, max_objwaste);
printf("Loss %10s %10s %10s\n",
b1, b2, b3);
}
void sort_slabs(void)
{
struct slabinfo *s1,*s2;
for (s1 = slabinfo; s1 < slabinfo + slabs; s1++) {
for (s2 = s1 + 1; s2 < slabinfo + slabs; s2++) {
int result;
if (sort_size)
result = slab_size(s1) < slab_size(s2);
else
result = strcasecmp(s1->name, s2->name);
if (show_inverted)
result = -result;
if (result > 0) {
struct slabinfo t;
memcpy(&t, s1, sizeof(struct slabinfo));
memcpy(s1, s2, sizeof(struct slabinfo));
memcpy(s2, &t, sizeof(struct slabinfo));
}
}
}
}
void sort_aliases(void)
{
struct aliasinfo *a1,*a2;
for (a1 = aliasinfo; a1 < aliasinfo + aliases; a1++) {
for (a2 = a1 + 1; a2 < aliasinfo + aliases; a2++) {
char *n1, *n2;
n1 = a1->name;
n2 = a2->name;
if (show_alias && !show_inverted) {
n1 = a1->ref;
n2 = a2->ref;
}
if (strcasecmp(n1, n2) > 0) {
struct aliasinfo t;
memcpy(&t, a1, sizeof(struct aliasinfo));
memcpy(a1, a2, sizeof(struct aliasinfo));
memcpy(a2, &t, sizeof(struct aliasinfo));
}
}
}
}
void link_slabs(void)
{
struct aliasinfo *a;
struct slabinfo *s;
for (a = aliasinfo; a < aliasinfo + aliases; a++) {
for(s = slabinfo; s < slabinfo + slabs; s++)
if (strcmp(a->ref, s->name) == 0) {
a->slab = s;
s->refs++;
break;
}
if (s == slabinfo + slabs)
fatal("Unresolved alias %s\n", a->ref);
}
}
void alias(void)
{
struct aliasinfo *a;
char *active = NULL;
sort_aliases();
link_slabs();
for(a = aliasinfo; a < aliasinfo + aliases; a++) {
if (!show_single_ref && a->slab->refs == 1)
continue;
if (!show_inverted) {
if (active) {
if (strcmp(a->slab->name, active) == 0) {
printf(" %s", a->name);
continue;
}
}
printf("\n%-20s <- %s", a->slab->name, a->name);
active = a->slab->name;
}
else
printf("%-20s -> %s\n", a->name, a->slab->name);
}
if (active)
printf("\n");
}
void rename_slabs(void)
{
struct slabinfo *s;
struct aliasinfo *a;
for (s = slabinfo; s < slabinfo + slabs; s++) {
if (*s->name != ':')
continue;
if (s->refs > 1 && !show_first_alias)
continue;
a = find_one_alias(s);
s->name = a->name;
}
}
int slab_mismatch(char *slab)
{
return regexec(&pattern, slab, 0, NULL, 0);
}
void read_slab_dir(void)
{
DIR *dir;
struct dirent *de;
struct slabinfo *slab = slabinfo;
struct aliasinfo *alias = aliasinfo;
char *p;
char *t;
int count;
dir = opendir(".");
while ((de = readdir(dir))) {
if (de->d_name[0] == '.' ||
slab_mismatch(de->d_name))
continue;
switch (de->d_type) {
case DT_LNK:
alias->name = strdup(de->d_name);
count = readlink(de->d_name, buffer, sizeof(buffer));
if (count < 0)
fatal("Cannot read symlink %s\n", de->d_name);
buffer[count] = 0;
p = buffer + count;
while (p > buffer && p[-1] != '/')
p--;
alias->ref = strdup(p);
alias++;
break;
case DT_DIR:
if (chdir(de->d_name))
fatal("Unable to access slab %s\n", slab->name);
slab->name = strdup(de->d_name);
slab->alias = 0;
slab->refs = 0;
slab->aliases = get_obj("aliases");
slab->align = get_obj("align");
slab->cache_dma = get_obj("cache_dma");
slab->cpu_slabs = get_obj("cpu_slabs");
slab->destroy_by_rcu = get_obj("destroy_by_rcu");
slab->hwcache_align = get_obj("hwcache_align");
slab->object_size = get_obj("object_size");
slab->objects = get_obj("objects");
slab->objs_per_slab = get_obj("objs_per_slab");
slab->order = get_obj("order");
slab->partial = get_obj("partial");
slab->partial = get_obj_and_str("partial", &t);
decode_numa_list(slab->numa_partial, t);
slab->poison = get_obj("poison");
slab->reclaim_account = get_obj("reclaim_account");
slab->red_zone = get_obj("red_zone");
slab->sanity_checks = get_obj("sanity_checks");
slab->slab_size = get_obj("slab_size");
slab->slabs = get_obj_and_str("slabs", &t);
decode_numa_list(slab->numa, t);
slab->store_user = get_obj("store_user");
slab->trace = get_obj("trace");
chdir("..");
if (slab->name[0] == ':')
alias_targets++;
slab++;
break;
default :
fatal("Unknown file type %lx\n", de->d_type);
}
}
closedir(dir);
slabs = slab - slabinfo;
aliases = alias - aliasinfo;
if (slabs > MAX_SLABS)
fatal("Too many slabs\n");
if (aliases > MAX_ALIASES)
fatal("Too many aliases\n");
}
void output_slabs(void)
{
struct slabinfo *slab;
for (slab = slabinfo; slab < slabinfo + slabs; slab++) {
if (slab->alias)
continue;
if (show_numa)
slab_numa(slab);
else
if (show_track)
show_tracking(slab);
else
if (validate)
slab_validate(slab);
else
if (shrink)
slab_shrink(slab);
else {
if (show_slab)
slabcache(slab);
}
}
}
struct option opts[] = {
{ "aliases", 0, NULL, 'a' },
{ "slabs", 0, NULL, 'l' },
{ "numa", 0, NULL, 'n' },
{ "zero", 0, NULL, 'z' },
{ "help", 0, NULL, 'h' },
{ "validate", 0, NULL, 'v' },
{ "first-alias", 0, NULL, 'f' },
{ "shrink", 0, NULL, 's' },
{ "track", 0, NULL, 't'},
{ "inverted", 0, NULL, 'i'},
{ "1ref", 0, NULL, '1'},
{ NULL, 0, NULL, 0 }
};
int main(int argc, char *argv[])
{
int c;
int err;
char *pattern_source;
page_size = getpagesize();
if (chdir("/sys/slab"))
fatal("This kernel does not have SLUB support.\n");
while ((c = getopt_long(argc, argv, "afhil1npstvzTS", opts, NULL)) != -1)
switch(c) {
case '1':
show_single_ref = 1;
break;
case 'a':
show_alias = 1;
break;
case 'f':
show_first_alias = 1;
break;
case 'h':
usage();
return 0;
case 'i':
show_inverted = 1;
break;
case 'n':
show_numa = 1;
break;
case 's':
shrink = 1;
break;
case 'l':
show_slab = 1;
break;
case 't':
show_track = 1;
break;
case 'v':
validate = 1;
break;
case 'z':
skip_zero = 0;
break;
case 'T':
show_totals = 1;
break;
case 'S':
sort_size = 1;
break;
default:
fatal("%s: Invalid option '%c'\n", argv[0], optopt);
}
if (!show_slab && !show_alias && !show_track
&& !validate && !shrink)
show_slab = 1;
if (argc > optind)
pattern_source = argv[optind];
else
pattern_source = ".*";
err = regcomp(&pattern, pattern_source, REG_ICASE|REG_NOSUB);
if (err)
fatal("%s: Invalid pattern '%s' code %d\n",
argv[0], pattern_source, err);
read_slab_dir();
if (show_alias)
alias();
else
if (show_totals)
totals();
else {
link_slabs();
rename_slabs();
sort_slabs();
output_slabs();
}
return 0;
}

113
Documentation/vm/slub.txt Normal file
View file

@ -0,0 +1,113 @@
Short users guide for SLUB
--------------------------
First of all slub should transparently replace SLAB. If you enable
SLUB then everything should work the same (Note the word "should".
There is likely not much value in that word at this point).
The basic philosophy of SLUB is very different from SLAB. SLAB
requires rebuilding the kernel to activate debug options for all
SLABS. SLUB always includes full debugging but its off by default.
SLUB can enable debugging only for selected slabs in order to avoid
an impact on overall system performance which may make a bug more
difficult to find.
In order to switch debugging on one can add a option "slub_debug"
to the kernel command line. That will enable full debugging for
all slabs.
Typically one would then use the "slabinfo" command to get statistical
data and perform operation on the slabs. By default slabinfo only lists
slabs that have data in them. See "slabinfo -h" for more options when
running the command. slabinfo can be compiled with
gcc -o slabinfo Documentation/vm/slabinfo.c
Some of the modes of operation of slabinfo require that slub debugging
be enabled on the command line. F.e. no tracking information will be
available without debugging on and validation can only partially
be performed if debugging was not switched on.
Some more sophisticated uses of slub_debug:
-------------------------------------------
Parameters may be given to slub_debug. If none is specified then full
debugging is enabled. Format:
slub_debug=<Debug-Options> Enable options for all slabs
slub_debug=<Debug-Options>,<slab name>
Enable options only for select slabs
Possible debug options are
F Sanity checks on (enables SLAB_DEBUG_FREE. Sorry
SLAB legacy issues)
Z Red zoning
P Poisoning (object and padding)
U User tracking (free and alloc)
T Trace (please only use on single slabs)
F.e. in order to boot just with sanity checks and red zoning one would specify:
slub_debug=FZ
Trying to find an issue in the dentry cache? Try
slub_debug=,dentry_cache
to only enable debugging on the dentry cache.
Red zoning and tracking may realign the slab. We can just apply sanity checks
to the dentry cache with
slub_debug=F,dentry_cache
In case you forgot to enable debugging on the kernel command line: It is
possible to enable debugging manually when the kernel is up. Look at the
contents of:
/sys/slab/<slab name>/
Look at the writable files. Writing 1 to them will enable the
corresponding debug option. All options can be set on a slab that does
not contain objects. If the slab already contains objects then sanity checks
and tracing may only be enabled. The other options may cause the realignment
of objects.
Careful with tracing: It may spew out lots of information and never stop if
used on the wrong slab.
SLAB Merging
------------
If no debugging is specified then SLUB may merge similar slabs together
in order to reduce overhead and increase cache hotness of objects.
slabinfo -a displays which slabs were merged together.
Getting more performance
------------------------
To some degree SLUB's performance is limited by the need to take the
list_lock once in a while to deal with partial slabs. That overhead is
governed by the order of the allocation for each slab. The allocations
can be influenced by kernel parameters:
slub_min_objects=x (default 8)
slub_min_order=x (default 0)
slub_max_order=x (default 4)
slub_min_objects allows to specify how many objects must at least fit
into one slab in order for the allocation order to be acceptable.
In general slub will be able to perform this number of allocations
on a slab without consulting centralized resources (list_lock) where
contention may occur.
slub_min_order specifies a minim order of slabs. A similar effect like
slub_min_objects.
slub_max_order specified the order at which slub_min_objects should no
longer be checked. This is useful to avoid SLUB trying to generate
super large order pages to fit slub_min_objects of a slab cache with
large object sizes into one high order page.
Christoph Lameter, <clameter@sgi.com>, April 10, 2007

View file

@ -149,7 +149,19 @@ NUMA
numa=noacpi Don't parse the SRAT table for NUMA setup
numa=fake=X Fake X nodes and ignore NUMA setup of the actual machine.
numa=fake=CMDLINE
If a number, fakes CMDLINE nodes and ignores NUMA setup of the
actual machine. Otherwise, system memory is configured
depending on the sizes and coefficients listed. For example:
numa=fake=2*512,1024,4*256,*128
gives two 512M nodes, a 1024M node, four 256M nodes, and the
rest split into 128M chunks. If the last character of CMDLINE
is a *, the remaining memory is divided up equally among its
coefficient:
numa=fake=2*512,2*
gives two 512M nodes and the rest split into two nodes.
Otherwise, the remaining system RAM is allocated to an
additional node.
numa=hotadd=percent
Only allow hotadd memory to preallocate page structures upto

View file

@ -0,0 +1,66 @@
Using numa=fake and CPUSets for Resource Management
Written by David Rientjes <rientjes@cs.washington.edu>
This document describes how the numa=fake x86_64 command-line option can be used
in conjunction with cpusets for coarse memory management. Using this feature,
you can create fake NUMA nodes that represent contiguous chunks of memory and
assign them to cpusets and their attached tasks. This is a way of limiting the
amount of system memory that are available to a certain class of tasks.
For more information on the features of cpusets, see Documentation/cpusets.txt.
There are a number of different configurations you can use for your needs. For
more information on the numa=fake command line option and its various ways of
configuring fake nodes, see Documentation/x86_64/boot-options.txt.
For the purposes of this introduction, we'll assume a very primitive NUMA
emulation setup of "numa=fake=4*512,". This will split our system memory into
four equal chunks of 512M each that we can now use to assign to cpusets. As
you become more familiar with using this combination for resource control,
you'll determine a better setup to minimize the number of nodes you have to deal
with.
A machine may be split as follows with "numa=fake=4*512," as reported by dmesg:
Faking node 0 at 0000000000000000-0000000020000000 (512MB)
Faking node 1 at 0000000020000000-0000000040000000 (512MB)
Faking node 2 at 0000000040000000-0000000060000000 (512MB)
Faking node 3 at 0000000060000000-0000000080000000 (512MB)
...
On node 0 totalpages: 130975
On node 1 totalpages: 131072
On node 2 totalpages: 131072
On node 3 totalpages: 131072
Now following the instructions for mounting the cpusets filesystem from
Documentation/cpusets.txt, you can assign fake nodes (i.e. contiguous memory
address spaces) to individual cpusets:
[root@xroads /]# mkdir exampleset
[root@xroads /]# mount -t cpuset none exampleset
[root@xroads /]# mkdir exampleset/ddset
[root@xroads /]# cd exampleset/ddset
[root@xroads /exampleset/ddset]# echo 0-1 > cpus
[root@xroads /exampleset/ddset]# echo 0-1 > mems
Now this cpuset, 'ddset', will only allowed access to fake nodes 0 and 1 for
memory allocations (1G).
You can now assign tasks to these cpusets to limit the memory resources
available to them according to the fake nodes assigned as mems:
[root@xroads /exampleset/ddset]# echo $$ > tasks
[root@xroads /exampleset/ddset]# dd if=/dev/zero of=tmp bs=1024 count=1G
[1] 13425
Notice the difference between the system memory usage as reported by
/proc/meminfo between the restricted cpuset case above and the unrestricted
case (i.e. running the same 'dd' command without assigning it to a fake NUMA
cpuset):
Unrestricted Restricted
MemTotal: 3091900 kB 3091900 kB
MemFree: 42113 kB 1513236 kB
This allows for coarse memory management for the tasks you assign to particular
cpusets. Since cpusets can form a hierarchy, you can create some pretty
interesting combinations of use-cases for various classes of tasks for your
memory management needs.

View file

@ -36,7 +36,12 @@ between all CPUs.
check_interval
How often to poll for corrected machine check errors, in seconds
(Note output is hexademical). Default 5 minutes.
(Note output is hexademical). Default 5 minutes. When the poller
finds MCEs it triggers an exponential speedup (poll more often) on
the polling interval. When the poller stops finding MCEs, it
triggers an exponential backoff (poll less often) on the polling
interval. The check_interval variable is both the initial and
maximum polling interval.
tolerant
Tolerance level. When a machine check exception occurs for a non

11
Kbuild
View file

@ -2,6 +2,7 @@
# Kbuild for top-level directory of the kernel
# This file takes care of the following:
# 1) Generate asm-offsets.h
# 2) Check for missing system calls
#####
# 1) Generate asm-offsets.h
@ -46,3 +47,13 @@ $(obj)/$(offsets-file): arch/$(ARCH)/kernel/asm-offsets.s Kbuild
$(Q)mkdir -p $(dir $@)
$(call cmd,offsets)
#####
# 2) Check for missing system calls
#
quiet_cmd_syscalls = CALL $<
cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags)
PHONY += missing-syscalls
missing-syscalls: scripts/checksyscalls.sh FORCE
$(call cmd,syscalls)

View file

@ -700,6 +700,44 @@ P: Richard Purdie
M: rpurdie@rpsys.net
S: Maintained
BLACKFIN ARCHITECTURE
P: Aubrey Li
M: aubrey.li@analog.com
P: Bernd Schmidt
M: bernd.schmidt@analog.com
P: Bryan Wu
M: bryan.wu@analog.com
P: Grace Pan
M: grace.pan@analog.com
P: Michael Hennerich
M: michael.hennerich@analog.com
P: Mike Frysinger
M: michael.frysinger@analog.com
P: Jane Lv
M: jane.lv@analog.com
P: Jerry Zeng
M: jerry.zeng@analog.com
P: Jie Zhang
M: jie.zhang@analog.com
P: Robin Getz
M: robin.getz@analog.com
P: Roy Huang
M: roy.huang@analog.com
P: Sonic Zhang
M: sonic.zhang@analog.com
P: Yi Li
M: yi.li@analog.com
L: uclinux-dist-devel@blackfin.uclinux.org
W: http://blackfin.uclinux.org
S: Supported
BLACKFIN SERIAL DRIVER
P: Aubrey Li
M: aubrey.li@analog.com
L: uclinux-dist-devel@blackfin.uclinux.org
W: http://blackfin.uclinux.org
S: Supported
BAYCOM/HDLCDRV DRIVERS FOR AX.25
P: Thomas Sailer
M: t.sailer@alumni.ethz.ch
@ -733,6 +771,13 @@ M: tigran@aivazian.fsnet.co.uk
L: linux-kernel@vger.kernel.org
S: Maintained
BLACKFIN I2C TWI DRIVER
P: Sonic Zhang
M: sonic.zhang@analog.com
L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
W: http://blackfin.uclinux.org/
S: Supported
BLOCK LAYER
P: Jens Axboe
M: axboe@kernel.dk
@ -1459,6 +1504,11 @@ L: linux-scsi@vger.kernel.org
W: http://www.icp-vortex.com/
S: Supported
GENERIC GPIO I2C DRIVER
P: Haavard Skinnemoen
M: hskinnemoen@atmel.com
S: Supported
GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
P: Krzysztof Halasa
M: khc@pm.waw.pl
@ -1605,7 +1655,7 @@ S: Maintained
HPET: x86_64
P: Andi Kleen and Vojtech Pavlik
M: ak@muc.de and vojtech@suse.cz
M: andi@firstfloor.org and vojtech@suse.cz
S: Maintained
HPET: ACPI hpet.c
@ -1631,6 +1681,13 @@ L: i2c@lm-sensors.org
T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
S: Maintained
I2C-TINY-USB DRIVER
P: Till Harbaum
M: till@harbaum.org
L: i2c@lm-sensors.org
T: http://www.harbaum.org/till/i2c_tiny_usb
S: Maintained
i386 BOOT CODE
P: Riley H. Williams
M: Riley@Williams.Name
@ -2209,6 +2266,16 @@ M: philb@gnu.org
W: http://www.tazenda.demon.co.uk/phil/linux-hp
S: Maintained
MAC80211
P: Jiri Benc
M: jbenc@suse.cz
P: Michael Wu
M: flamingice@sourmilk.net
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git kernel.org:/pub/scm/linux/kernel/git/jbenc/mac80211.git
S: Maintained
MARVELL YUKON / SYSKONNECT DRIVER
P: Mirko Lindner
M: mlindner@syskonnect.de
@ -2623,6 +2690,19 @@ T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
T: cvs cvs.parisc-linux.org:/var/cvs/linux-2.6
S: Maintained
PARAVIRT_OPS INTERFACE
P: Jeremy Fitzhardinge
M: jeremy@xensource.com
P: Chris Wright
M: chrisw@sous-sol.org
P: Zachary Amsden
M: zach@vmware.com
P: Rusty Russell
M: rusty@rustcorp.com.au
L: virtualization@lists.osdl.org
L: linux-kernel@vger.kernel.org
S: Supported
PC87360 HARDWARE MONITORING DRIVER
P: Jim Cromie
M: jim.cromie@gmail.com
@ -3627,8 +3707,8 @@ W: http://www.kroah.com/linux/
S: Maintained
USB SERIAL WHITEHEAT DRIVER
P: Stuart MacDonald
M: stuartm@connecttech.com
P: Support Department
M: support@connecttech.com
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
W: http://www.connecttech.com
@ -3847,6 +3927,15 @@ M: eis@baty.hanse.de
L: linux-x25@vger.kernel.org
S: Maintained
XEN HYPERVISOR INTERFACE
P: Jeremy Fitzhardinge
M: jeremy@xensource.com
P: Chris Wright
M: chrisw@sous-sol.org
L: virtualization@lists.osdl.org
L: xen-devel@lists.xensource.com
S: Supported
XFS FILESYSTEM
P: Silicon Graphics Inc
P: Tim Shimmin, David Chatterton

View file

@ -491,7 +491,7 @@ endif
include $(srctree)/arch/$(ARCH)/Makefile
ifdef CONFIG_FRAME_POINTER
CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
else
CFLAGS += -fomit-frame-pointer
endif
@ -576,7 +576,7 @@ libs-y := $(libs-y1) $(libs-y2)
# ---------------------------------------------------------------------------
# vmlinux is built from the objects selected by $(vmlinux-init) and
# $(vmlinux-main). Most are built-in.o files from top-level directories
# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
# in the kernel tree, others are specified in arch/$(ARCH)/Makefile.
# Ordering when linking is important, and $(vmlinux-init) must be first.
#
# vmlinux
@ -603,6 +603,7 @@ vmlinux-init := $(head-y) $(init-y)
vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
vmlinux-all := $(vmlinux-init) $(vmlinux-main)
vmlinux-lds := arch/$(ARCH)/kernel/vmlinux.lds
export KBUILD_VMLINUX_OBJS := $(vmlinux-all)
# Rule to link vmlinux - also used during CONFIG_KALLSYMS
# May be overridden by arch/$(ARCH)/Makefile
@ -855,6 +856,7 @@ archprepare: prepare1 scripts_basic
prepare0: archprepare FORCE
$(Q)$(MAKE) $(build)=.
$(Q)$(MAKE) $(build)=. missing-syscalls
# All the preparing..
prepare: prepare0
@ -1277,10 +1279,7 @@ endif
ALLSOURCE_ARCHS := $(ARCH)
define find-sources
( find $(__srctree) $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name $1 -print; \
for ARCH in $(ALLSOURCE_ARCHS) ; do \
( for ARCH in $(ALLSOURCE_ARCHS) ; do \
find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
-name $1 -print; \
done ; \
@ -1294,7 +1293,11 @@ define find-sources
-name $1 -print; \
done ; \
find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-name $1 -print )
-name $1 -print; \
find $(__srctree) $(RCS_FIND_IGNORE) \
\( -name include -o -name arch \) -prune -o \
-name $1 -print; \
)
endef
define all-sources

View file

@ -467,3 +467,9 @@ start_kernel(void)
#endif
runkernel();
}
/* dummy function, should never be called. */
void *__kmalloc(size_t size, gfp_t flags)
{
return (void *)NULL;
}

View file

@ -98,7 +98,7 @@ extern int end;
static ulg free_mem_ptr;
static ulg free_mem_ptr_end;
#define HEAP_SIZE 0x2000
#define HEAP_SIZE 0x3000
#include "../../../lib/inflate.c"

View file

@ -25,7 +25,6 @@
#include <linux/a.out.h>
#include <linux/coff.h>
#include <linux/param.h>
#include <linux/string.h>
#ifdef __ELF__
# include <linux/elf.h>
#endif

View file

@ -7,7 +7,6 @@
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>

View file

@ -7,7 +7,6 @@
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>

View file

@ -7,7 +7,6 @@
*/
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/io.h>

View file

@ -93,7 +93,6 @@ osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
* offset differences aren't the same as "d_reclen").
*/
#define NAME_OFFSET offsetof (struct osf_dirent, d_name)
#define ROUND_UP(x) (((x)+3) & ~3)
struct osf_dirent {
unsigned int d_ino;
@ -115,7 +114,7 @@ osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
{
struct osf_dirent __user *dirent;
struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
unsigned int reclen = ALIGN(NAME_OFFSET + namlen + 1, sizeof(u32));
unsigned int d_ino;
buf->error = -EINVAL; /* only used if we fail */
@ -174,7 +173,6 @@ osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
return error;
}
#undef ROUND_UP
#undef NAME_OFFSET
asmlinkage unsigned long
@ -1267,6 +1265,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
if (len > limit)
return -ENOMEM;
if (flags & MAP_FIXED)
return addr;
/* First, see if the given suggestion fits.
The OSF/1 loader (/sbin/loader) relies on us returning an

View file

@ -164,9 +164,9 @@ srmcons_get_private_struct(struct srmcons_private **ps)
int retval = 0;
if (srmconsp == NULL) {
srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
spin_lock_irqsave(&srmconsp_lock, flags);
srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
if (srmconsp == NULL)
retval = -ENOMEM;
else {

View file

@ -69,7 +69,7 @@ SECTIONS
. = ALIGN(8);
SECURITY_INIT
. = ALIGN(64);
. = ALIGN(8192);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;

View file

@ -29,6 +29,10 @@ config GENERIC_TIME
bool
default n
config GENERIC_CLOCKEVENTS
bool
default n
config MMU
bool
default y
@ -67,6 +71,14 @@ config GENERIC_HARDIRQS
bool
default y
config STACKTRACE_SUPPORT
bool
default y
config LOCKDEP_SUPPORT
bool
default y
config TRACE_IRQFLAGS_SUPPORT
bool
default y
@ -162,6 +174,8 @@ config ARCH_VERSATILE
select ARM_AMBA
select ARM_VIC
select ICST307
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
This enables support for ARM Ltd Versatile board.
@ -255,6 +269,7 @@ config ARCH_IOP13XX
depends on MMU
select PLAT_IOP
select PCI
select ARCH_SUPPORTS_MSI
help
Support for Intel's IOP13XX (XScale) family of processors.
@ -262,6 +277,7 @@ config ARCH_IXP4XX
bool "IXP4xx-based"
depends on MMU
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
help
Support for Intel's IXP4XX (XScale) family of processors.
@ -363,6 +379,7 @@ config ARCH_LH7A40X
config ARCH_OMAP
bool "TI OMAP"
select GENERIC_GPIO
select GENERIC_TIME
help
Support for TI's OMAP platform (OMAP1 and OMAP2).
@ -513,6 +530,8 @@ endmenu
menu "Kernel Features"
source "kernel/time/Kconfig"
config SMP
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
depends on EXPERIMENTAL && REALVIEW_MPCORE
@ -572,6 +591,7 @@ config PREEMPT
config NO_IDLE_HZ
bool "Dynamic tick timer"
depends on !GENERIC_CLOCKEVENTS
help
Select this option if you want to disable continuous timer ticks
and have them programmed to occur as required. This option saves
@ -669,6 +689,7 @@ config LEDS_TIMER
bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
depends on LEDS
depends on !GENERIC_CLOCKEVENTS
default y if ARCH_EBSA110
help
If you say Y here, one of the system LEDs (the green one on the

View file

@ -61,6 +61,12 @@
cmp r7, r3
beq 99f
@ picotux 200 : 963
mov r3, #(MACH_TYPE_PICOTUX2XX & 0xff)
orr r3, r3, #(MACH_TYPE_PICOTUX2XX & 0xff00)
cmp r7, r3
beq 99f
@ Ajeco 1ARM : 1075
mov r3, #(MACH_TYPE_ONEARM & 0xff)
orr r3, r3, #(MACH_TYPE_ONEARM & 0xff00)

View file

@ -239,7 +239,7 @@ extern int end;
static ulg free_mem_ptr;
static ulg free_mem_ptr_end;
#define HEAP_SIZE 0x2000
#define HEAP_SIZE 0x3000
#include "../../../../lib/inflate.c"

View file

@ -18,7 +18,6 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>

View file

@ -1,6 +1,5 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/init.h>

View file

@ -117,11 +117,13 @@ CONFIG_ARCH_ADI_COYOTE=y
CONFIG_ARCH_IXDP425=y
CONFIG_MACH_IXDPG425=y
CONFIG_MACH_IXDP465=y
CONFIG_MACH_KIXRP435=y
CONFIG_ARCH_IXCDP1100=y
CONFIG_ARCH_PRPMC1100=y
CONFIG_MACH_NAS100D=y
CONFIG_ARCH_IXDP4XX=y
CONFIG_CPU_IXP46X=y
CONFIG_CPU_IXP43X=y
# CONFIG_MACH_GTWX5715 is not set
#

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,8 @@ AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
# Object file lists.
obj-y := compat.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o
process.o ptrace.o semaphore.o setup.o signal.o \
sys_arm.o stacktrace.o time.o traps.o
obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.o

View file

@ -40,6 +40,7 @@
#include <linux/device.h>
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/kthread.h>
#include <asm/dma.h>
#include <asm/ecard.h>
@ -50,6 +51,8 @@
#include <asm/mach/irq.h>
#include <asm/tlbflush.h>
#include "ecard.h"
#ifndef CONFIG_ARCH_RPC
#define HAVE_EXPMASK
#endif
@ -123,7 +126,7 @@ static void ecard_task_reset(struct ecard_request *req)
res = ec->slot_no == 8
? &ec->resource[ECARD_RES_MEMC]
: ec->type == ECARD_EASI
: ec->easi
? &ec->resource[ECARD_RES_EASI]
: &ec->resource[ECARD_RES_IOCSYNC];
@ -178,7 +181,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
index += 1;
}
} else {
unsigned long base = (ec->type == ECARD_EASI
unsigned long base = (ec->easi
? &ec->resource[ECARD_RES_EASI]
: &ec->resource[ECARD_RES_IOCSYNC])->start;
void __iomem *pbase = (void __iomem *)base;
@ -263,8 +266,6 @@ static int ecard_init_mm(void)
static int
ecard_task(void * unused)
{
daemonize("kecardd");
/*
* Allocate a mm. We're not a lazy-TLB kernel task since we need
* to set page table entries where the user space would be. Note
@ -727,7 +728,7 @@ static int ecard_prints(char *buffer, ecard_t *ec)
char *start = buffer;
buffer += sprintf(buffer, " %d: %s ", ec->slot_no,
ec->type == ECARD_EASI ? "EASI" : " ");
ec->easi ? "EASI" : " ");
if (ec->cid.id == 0) {
struct in_chunk_dir incd;
@ -814,7 +815,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
}
ec->slot_no = slot;
ec->type = type;
ec->easi = type == ECARD_EASI;
ec->irq = NO_IRQ;
ec->fiq = NO_IRQ;
ec->dma = NO_DMA;
@ -825,6 +826,7 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
ec->dev.bus = &ecard_bus_type;
ec->dev.dma_mask = &ec->dma_mask;
ec->dma_mask = (u64)0xffffffff;
ec->dev.coherent_dma_mask = ec->dma_mask;
if (slot < 4) {
ec_set_resource(ec, ECARD_RES_MEMC,
@ -907,7 +909,7 @@ static ssize_t ecard_show_device(struct device *dev, struct device_attribute *at
static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
return sprintf(buf, "%s\n", ec->easi ? "EASI" : "IOC");
}
static struct device_attribute ecard_dev_attrs[] = {
@ -1058,13 +1060,14 @@ ecard_probe(int slot, card_type_t type)
*/
static int __init ecard_init(void)
{
int slot, irqhw, ret;
struct task_struct *task;
int slot, irqhw;
ret = kernel_thread(ecard_task, NULL, CLONE_KERNEL);
if (ret < 0) {
printk(KERN_ERR "Ecard: unable to create kernel thread: %d\n",
ret);
return ret;
task = kthread_run(ecard_task, NULL, "kecardd");
if (IS_ERR(task)) {
printk(KERN_ERR "Ecard: unable to create kernel thread: %ld\n",
PTR_ERR(task));
return PTR_ERR(task);
}
printk("Probing expansion cards\n");

56
arch/arm/kernel/ecard.h Normal file
View file

@ -0,0 +1,56 @@
/*
* ecard.h
*
* Copyright 2007 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.
*/
/* Definitions internal to ecard.c - for it's use only!!
*
* External expansion card header as read from the card
*/
struct ex_ecid {
unsigned char r_irq:1;
unsigned char r_zero:1;
unsigned char r_fiq:1;
unsigned char r_id:4;
unsigned char r_a:1;
unsigned char r_cd:1;
unsigned char r_is:1;
unsigned char r_w:2;
unsigned char r_r1:4;
unsigned char r_r2:8;
unsigned char r_prod[2];
unsigned char r_manu[2];
unsigned char r_country;
unsigned char r_fiqmask;
unsigned char r_fiqoff[3];
unsigned char r_irqmask;
unsigned char r_irqoff[3];
};
/*
* Chunk directory entry as read from the card
*/
struct ex_chunk_dir {
unsigned char r_id;
unsigned char r_len[3];
unsigned long r_start;
union {
char string[256];
char data[1];
} d;
#define c_id(x) ((x)->r_id)
#define c_len(x) ((x)->r_len[0]|((x)->r_len[1]<<8)|((x)->r_len[2]<<16))
#define c_start(x) ((x)->r_start)
};

View file

@ -257,7 +257,9 @@ __create_page_tables:
* Map some ram to cover our .data and .bss areas.
*/
orr r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
.if (KERNEL_RAM_PADDR & 0x00f00000)
orr r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
.endif
add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> 18
str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
ldr r6, =(_end - 1)
@ -274,7 +276,9 @@ __create_page_tables:
*/
add r0, r4, #PAGE_OFFSET >> 18
orr r6, r7, #(PHYS_OFFSET & 0xff000000)
orr r6, r6, #(PHYS_OFFSET & 0x00e00000)
.if (PHYS_OFFSET & 0x00f00000)
orr r6, r6, #(PHYS_OFFSET & 0x00f00000)
.endif
str r6, [r0]
#ifdef CONFIG_DEBUG_LL

View file

@ -27,7 +27,6 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/smp.h>
@ -109,7 +108,7 @@ static struct irq_desc bad_irq_desc = {
* come via this function. Instead, they should provide their
* own 'handler'
*/
asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
struct irq_desc *desc = irq_desc + irq;

View file

@ -16,7 +16,6 @@
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
@ -28,6 +27,7 @@
#include <linux/cpu.h>
#include <linux/elfcore.h>
#include <linux/pm.h>
#include <linux/tick.h>
#include <asm/leds.h>
#include <asm/processor.h>
@ -160,9 +160,11 @@ void cpu_idle(void)
if (!idle)
idle = default_idle;
leds_event(led_idle_start);
tick_nohz_stop_sched_tick();
while (!need_resched())
idle();
leds_event(led_idle_end);
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
schedule();
preempt_disable();

View file

@ -457,13 +457,10 @@ void ptrace_cancel_bpt(struct task_struct *child)
/*
* Called by kernel/ptrace.c when detaching..
*
* Make sure the single step bit is not set.
*/
void ptrace_disable(struct task_struct *child)
{
child->ptrace &= ~PT_SINGLESTEP;
ptrace_cancel_bpt(child);
single_step_disable(child);
}
/*
@ -712,9 +709,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
else
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
/* make sure single-step breakpoint is gone. */
child->ptrace &= ~PT_SINGLESTEP;
ptrace_cancel_bpt(child);
single_step_disable(child);
wake_up_process(child);
ret = 0;
break;
@ -725,9 +720,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* exit.
*/
case PTRACE_KILL:
/* make sure single-step breakpoint is gone. */
child->ptrace &= ~PT_SINGLESTEP;
ptrace_cancel_bpt(child);
single_step_disable(child);
if (child->exit_state != EXIT_ZOMBIE) {
child->exit_code = SIGKILL;
wake_up_process(child);
@ -742,7 +735,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
ret = -EIO;
if (!valid_signal(data))
break;
child->ptrace |= PT_SINGLESTEP;
single_step_enable(child);
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
child->exit_code = data;
/* give it a chance to run. */
@ -786,8 +779,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break;
case PTRACE_SET_SYSCALL:
task_thread_info(child)->syscall = data;
ret = 0;
child->ptrace_message = data;
break;
#ifdef CONFIG_CRUNCH
@ -824,7 +817,7 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
ip = regs->ARM_ip;
regs->ARM_ip = why;
current->ptrace_message = scno;
current_thread_info()->syscall = scno;
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
@ -841,5 +834,5 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
}
regs->ARM_ip = ip;
return current->ptrace_message;
return current_thread_info()->syscall;
}

View file

@ -7,6 +7,45 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/ptrace.h>
extern void ptrace_cancel_bpt(struct task_struct *);
extern void ptrace_set_bpt(struct task_struct *);
extern void ptrace_break(struct task_struct *, struct pt_regs *);
/*
* make sure single-step breakpoint is gone.
*/
static inline void single_step_disable(struct task_struct *task)
{
task->ptrace &= ~PT_SINGLESTEP;
ptrace_cancel_bpt(task);
}
static inline void single_step_enable(struct task_struct *task)
{
task->ptrace |= PT_SINGLESTEP;
}
/*
* Send SIGTRAP if we're single-stepping
*/
static inline void single_step_trap(struct task_struct *task)
{
if (task->ptrace & PT_SINGLESTEP) {
ptrace_cancel_bpt(task);
send_sig(SIGTRAP, task, 1);
}
}
static inline void single_step_clear(struct task_struct *task)
{
if (task->ptrace & PT_SINGLESTEP)
ptrace_cancel_bpt(task);
}
static inline void single_step_set(struct task_struct *task)
{
if (task->ptrace & PT_SINGLESTEP)
ptrace_set_bpt(task);
}

View file

@ -9,7 +9,6 @@
*/
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/ptrace.h>
#include <linux/personality.h>
#include <linux/freezer.h>
@ -285,11 +284,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
if (restore_sigframe(regs, frame))
goto badframe;
/* Send SIGTRAP if we're single-stepping */
if (current->ptrace & PT_SINGLESTEP) {
ptrace_cancel_bpt(current);
send_sig(SIGTRAP, current, 1);
}
single_step_trap(current);
return regs->ARM_r0;
@ -324,11 +319,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
goto badframe;
/* Send SIGTRAP if we're single-stepping */
if (current->ptrace & PT_SINGLESTEP) {
ptrace_cancel_bpt(current);
send_sig(SIGTRAP, current, 1);
}
single_step_trap(current);
return regs->ARM_r0;
@ -644,14 +635,12 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (try_to_freeze())
goto no_signal;
if (current->ptrace & PT_SINGLESTEP)
ptrace_cancel_bpt(current);
single_step_clear(current);
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
handle_signal(signr, &ka, &info, oldset, regs, syscall);
if (current->ptrace & PT_SINGLESTEP)
ptrace_set_bpt(current);
single_step_set(current);
return 1;
}
@ -705,8 +694,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
restart_syscall(regs);
}
}
if (current->ptrace & PT_SINGLESTEP)
ptrace_set_bpt(current);
single_step_set(current);
return 0;
}

View file

@ -0,0 +1,73 @@
#include <linux/sched.h>
#include <linux/stacktrace.h>
#include "stacktrace.h"
int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
int (*fn)(struct stackframe *, void *), void *data)
{
struct stackframe *frame;
do {
/*
* Check current frame pointer is within bounds
*/
if ((fp - 12) < low || fp + 4 >= high)
break;
frame = (struct stackframe *)(fp - 12);
if (fn(frame, data))
break;
/*
* Update the low bound - the next frame must always
* be at a higher address than the current frame.
*/
low = fp + 4;
fp = frame->fp;
} while (fp);
return 0;
}
#ifdef CONFIG_STACKTRACE
struct stack_trace_data {
struct stack_trace *trace;
unsigned int skip;
};
static int save_trace(struct stackframe *frame, void *d)
{
struct stack_trace_data *data = d;
struct stack_trace *trace = data->trace;
if (data->skip) {
data->skip--;
return 0;
}
trace->entries[trace->nr_entries++] = frame->lr;
return trace->nr_entries >= trace->max_entries;
}
void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
{
struct stack_trace_data data;
unsigned long fp, base;
data.trace = trace;
data.skip = trace->skip;
if (task) {
base = (unsigned long)task_stack_page(task);
fp = 0; /* FIXME */
} else {
base = (unsigned long)task_stack_page(current);
asm("mov %0, fp" : "=r" (fp));
}
walk_stackframe(fp, base, base + THREAD_SIZE, save_trace, &data);
}
#endif

View file

@ -0,0 +1,9 @@
struct stackframe {
unsigned long fp;
unsigned long sp;
unsigned long lr;
unsigned long pc;
};
int walk_stackframe(unsigned long fp, unsigned long low, unsigned long high,
int (*fn)(struct stackframe *, void *), void *data);

View file

@ -327,6 +327,7 @@ void restore_time_delta(struct timespec *delta, struct timespec *rtc)
}
EXPORT_SYMBOL(restore_time_delta);
#ifndef CONFIG_GENERIC_CLOCKEVENTS
/*
* Kernel system timer support.
*/
@ -340,8 +341,9 @@ void timer_tick(void)
update_process_times(user_mode(get_irq_regs()));
#endif
}
#endif
#ifdef CONFIG_PM
#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
static int timer_suspend(struct sys_device *dev, pm_message_t state)
{
struct sys_timer *timer = container_of(dev, struct sys_timer, dev);

View file

@ -16,7 +16,6 @@
#include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/personality.h>
#include <linux/ptrace.h>
#include <linux/kallsyms.h>
#include <linux/delay.h>
#include <linux/init.h>
@ -45,7 +44,18 @@ static int __init user_debug_setup(char *str)
__setup("user_debug=", user_debug_setup);
#endif
void dump_backtrace_entry(unsigned long where, unsigned long from)
static void dump_mem(const char *str, unsigned long bottom, unsigned long top);
static inline int in_exception_text(unsigned long ptr)
{
extern char __exception_text_start[];
extern char __exception_text_end[];
return ptr >= (unsigned long)&__exception_text_start &&
ptr < (unsigned long)&__exception_text_end;
}
void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
{
#ifdef CONFIG_KALLSYMS
printk("[<%08lx>] ", where);
@ -55,6 +65,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from)
#else
printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
#endif
if (in_exception_text(where))
dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
}
/*
@ -266,13 +279,14 @@ void unregister_undef_hook(struct undef_hook *hook)
spin_unlock_irqrestore(&undef_lock, flags);
}
asmlinkage void do_undefinstr(struct pt_regs *regs)
asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
{
unsigned int correction = thumb_mode(regs) ? 2 : 4;
unsigned int instr;
struct undef_hook *hook;
siginfo_t info;
void __user *pc;
unsigned long flags;
/*
* According to the ARM ARM, PC is 2 or 4 bytes ahead,
@ -291,7 +305,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
get_user(instr, (u32 __user *)pc);
}
spin_lock_irq(&undef_lock);
spin_lock_irqsave(&undef_lock, flags);
list_for_each_entry(hook, &undef_hook, node) {
if ((instr & hook->instr_mask) == hook->instr_val &&
(regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) {
@ -301,7 +315,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
}
}
}
spin_unlock_irq(&undef_lock);
spin_unlock_irqrestore(&undef_lock, flags);
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_UNDEFINED) {

View file

@ -59,7 +59,7 @@ SECTIONS
usr/built-in.o(.init.ramfs)
__initramfs_end = .;
#endif
. = ALIGN(64);
. = ALIGN(4096);
__per_cpu_start = .;
*(.data.percpu)
__per_cpu_end = .;
@ -83,6 +83,9 @@ SECTIONS
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
__exception_text_start = .;
*(.exception.text)
__exception_text_end = .;
*(.text)
SCHED_TEXT
LOCK_TEXT

View file

@ -17,8 +17,8 @@
@ fp is 0 or stack frame
#define frame r4
#define next r5
#define save r6
#define sv_fp r5
#define sv_pc r6
#define mask r7
#define offset r8
@ -31,108 +31,106 @@ ENTRY(c_backtrace)
#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
mov pc, lr
#else
stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
tst r1, #0x10 @ 26 or 32-bit?
moveq mask, #0xfc000003
movne mask, #0
tst mask, r0
movne r0, #0
movs frame, r0
1: moveq r0, #-2
ldmeqfd sp!, {r4 - r8, pc}
movs frame, r0 @ if frame pointer is zero
beq no_frame @ we have no stack frames
2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction
ldr r0, [sp], #4
adr r1, 2b - 4
tst r1, #0x10 @ 26 or 32-bit mode?
moveq mask, #0xfc000003 @ mask for 26-bit
movne mask, #0 @ mask for 32-bit
1: stmfd sp!, {pc} @ calculate offset of PC stored
ldr r0, [sp], #4 @ by stmfd for this CPU
adr r1, 1b
sub offset, r0, r1
3: tst frame, mask @ Check for address exceptions...
bne 1b
/*
* Stack frame layout:
* optionally saved caller registers (r4 - r10)
* saved fp
* saved sp
* saved lr
* frame => saved pc
* optionally saved arguments (r0 - r3)
* saved sp => <next word>
*
* Functions start with the following code sequence:
* mov ip, sp
* stmfd sp!, {r0 - r3} (optional)
* corrected pc => stmfd sp!, {..., fp, ip, lr, pc}
*/
for_each_frame: tst frame, mask @ Check for address exceptions
bne no_frame
1001: ldr next, [frame, #-12] @ get fp
1002: ldr r2, [frame, #-4] @ get lr
1003: ldr r3, [frame, #0] @ get pc
sub save, r3, offset @ Correct PC for prefetching
bic save, save, mask
1004: ldr r1, [save, #0] @ get instruction at function
mov r1, r1, lsr #10
ldr r3, .Ldsi+4
teq r1, r3
subeq save, save, #4
mov r0, save
bic r1, r2, mask
1001: ldr sv_pc, [frame, #0] @ get saved pc
1002: ldr sv_fp, [frame, #-12] @ get saved fp
sub sv_pc, sv_pc, offset @ Correct PC for prefetching
bic sv_pc, sv_pc, mask @ mask PC/LR for the mode
1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
teq r3, r2, lsr #10 @ instruction
subne r0, sv_pc, #4 @ allow for mov
subeq r0, sv_pc, #8 @ allow for mov + stmia
ldr r1, [frame, #-4] @ get saved lr
mov r2, frame
bic r1, r1, mask @ mask PC/LR for the mode
bl dump_backtrace_entry
ldr r0, [frame, #-8] @ get sp
sub r0, r0, #4
1005: ldr r1, [save, #4] @ get instruction at function+4
mov r3, r1, lsr #10
ldr r2, .Ldsi+4
teq r3, r2 @ Check for stmia sp!, {args}
addeq save, save, #4 @ next instruction
bleq .Ldumpstm
ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
ldr r3, .Ldsi+4
teq r3, r1, lsr #10
ldreq r0, [frame, #-8] @ get sp
subeq r0, r0, #4 @ point at the last arg
bleq .Ldumpstm @ dump saved registers
sub r0, frame, #16
1006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction
mov r3, r1, lsr #10
ldr r2, .Ldsi
teq r3, r2
bleq .Ldumpstm
1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc}
ldr r3, .Ldsi @ instruction exists,
teq r3, r1, lsr #10
subeq r0, frame, #16
bleq .Ldumpstm @ dump saved registers
/*
* A zero next framepointer means we're done.
*/
teq next, #0
ldmeqfd sp!, {r4 - r8, pc}
teq sv_fp, #0 @ zero saved fp means
beq no_frame @ no further frames
/*
* The next framepointer must be above the
* current framepointer.
*/
cmp next, frame
mov frame, next
bhi 3b
b 1007f
cmp sv_fp, frame @ next frame must be
mov frame, sv_fp @ above the current frame
bhi for_each_frame
/*
* Fixup for LDMDB. Note that this must not be in the fixup section.
*/
1007: ldr r0, =.Lbad
1006: adr r0, .Lbad
mov r1, frame
bl printk
ldmfd sp!, {r4 - r8, pc}
.ltorg
no_frame: ldmfd sp!, {r4 - r8, pc}
.section __ex_table,"a"
.align 3
.long 1001b, 1007b
.long 1002b, 1007b
.long 1003b, 1007b
.long 1004b, 1007b
.long 1005b, 1007b
.long 1006b, 1007b
.long 1001b, 1006b
.long 1002b, 1006b
.long 1003b, 1006b
.long 1004b, 1006b
.previous
#define instr r4
#define reg r5
#define stack r6
.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, r8, lr}
.Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
mov stack, r0
mov instr, r1
mov reg, #9
mov reg, #10
mov r7, #0
1: mov r3, #1
tst instr, r3, lsl reg
beq 2f
add r7, r7, #1
teq r7, #4
moveq r7, #0
moveq r3, #'\n'
movne r3, #' '
ldr r2, [stack], #-4
mov r1, reg
teq r7, #6
moveq r7, #1
moveq r1, #'\n'
movne r1, #' '
ldr r3, [stack], #-4
mov r2, reg
adr r0, .Lfp
bl printk
2: subs reg, reg, #1
@ -140,14 +138,13 @@ ENTRY(c_backtrace)
teq r7, #0
adrne r0, .Lcr
blne printk
mov r0, stack
ldmfd sp!, {instr, reg, stack, r7, r8, pc}
ldmfd sp!, {instr, reg, stack, r7, pc}
.Lfp: .asciz " r%d = %08X%c"
.Lfp: .asciz "%cr%d:%08x"
.Lcr: .asciz "\n"
.Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
.align
.Ldsi: .word 0x00e92dd8 >> 2
.word 0x00e92d00 >> 2
.Ldsi: .word 0xe92dd800 >> 10 @ stmfd sp!, {... fp, ip, lr, pc}
.word 0xe92d0000 >> 10 @ stmfd sp!, {}
#endif

View file

@ -26,8 +26,6 @@
* Note that ADDR_LIMIT is either 0 or 0xc0000000.
* Note also that it is intended that __get_user_bad is not global.
*/
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
.global __get_user_1

View file

@ -26,8 +26,6 @@
* Note that ADDR_LIMIT is either 0 or 0xc0000000
* Note also that it is intended that __put_user_bad is not global.
*/
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/errno.h>
.global __put_user_1

View file

@ -81,6 +81,13 @@ config MACH_KB9200
Select this if you are using KwikByte's KB920x board.
<http://kwikbyte.com/KB9202_description_new.htm>
config MACH_PICOTUX2XX
bool "picotux 200"
depends on ARCH_AT91RM9200
help
Select this if you are using a picotux 200.
<http://www.picotux.com/>
config MACH_KAFA
bool "Sperry-Sun KAFA board"
depends on ARCH_AT91RM9200

View file

@ -25,6 +25,7 @@ obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o
obj-$(CONFIG_MACH_KB9200) += board-kb9202.o
obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o
obj-$(CONFIG_MACH_KAFA) += board-kafa.o
obj-$(CONFIG_MACH_PICOTUX2XX) += board-picotux200.o
# AT91SAM9260 board-specific support
obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o

View file

@ -117,6 +117,21 @@ static struct clk pioD_clk = {
.pmc_mask = 1 << AT91RM9200_ID_PIOD,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc0_clk = {
.name = "ssc0_clk",
.pmc_mask = 1 << AT91RM9200_ID_SSC0,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc1_clk = {
.name = "ssc1_clk",
.pmc_mask = 1 << AT91RM9200_ID_SSC1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc2_clk = {
.name = "ssc2_clk",
.pmc_mask = 1 << AT91RM9200_ID_SSC2,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk tc0_clk = {
.name = "tc0_clk",
.pmc_mask = 1 << AT91RM9200_ID_TC0,
@ -161,7 +176,9 @@ static struct clk *periph_clocks[] __initdata = {
&udc_clk,
&twi_clk,
&spi_clk,
// ssc 0 .. ssc2
&ssc0_clk,
&ssc1_clk,
&ssc2_clk,
&tc0_clk,
&tc1_clk,
&tc2_clk,

View file

@ -119,6 +119,11 @@ static struct clk spi1_clk = {
.pmc_mask = 1 << AT91SAM9260_ID_SPI1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc_clk = {
.name = "ssc_clk",
.pmc_mask = 1 << AT91SAM9260_ID_SSC,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk tc0_clk = {
.name = "tc0_clk",
.pmc_mask = 1 << AT91SAM9260_ID_TC0,
@ -193,7 +198,7 @@ static struct clk *periph_clocks[] __initdata = {
&twi_clk,
&spi0_clk,
&spi1_clk,
// ssc
&ssc_clk,
&tc0_clk,
&tc1_clk,
&tc2_clk,

View file

@ -97,6 +97,21 @@ static struct clk spi1_clk = {
.pmc_mask = 1 << AT91SAM9261_ID_SPI1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc0_clk = {
.name = "ssc0_clk",
.pmc_mask = 1 << AT91SAM9261_ID_SSC0,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc1_clk = {
.name = "ssc1_clk",
.pmc_mask = 1 << AT91SAM9261_ID_SSC1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc2_clk = {
.name = "ssc2_clk",
.pmc_mask = 1 << AT91SAM9261_ID_SSC2,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk tc0_clk = {
.name = "tc0_clk",
.pmc_mask = 1 << AT91SAM9261_ID_TC0,
@ -135,7 +150,9 @@ static struct clk *periph_clocks[] __initdata = {
&twi_clk,
&spi0_clk,
&spi1_clk,
// ssc 0 .. ssc2
&ssc0_clk,
&ssc1_clk,
&ssc2_clk,
&tc0_clk,
&tc1_clk,
&tc2_clk,

View file

@ -430,9 +430,9 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
* LCD Controller
* -------------------------------------------------------------------- */
#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE)
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
static u64 lcdc_dmamask = 0xffffffffUL;
static struct at91fb_info lcdc_data;
static struct atmel_lcdfb_info lcdc_data;
static struct resource lcdc_resources[] = {
[0] = {
@ -455,7 +455,7 @@ static struct resource lcdc_resources[] = {
};
static struct platform_device at91_lcdc_device = {
.name = "at91-fb",
.name = "atmel_lcdfb",
.id = 0,
.dev = {
.dma_mask = &lcdc_dmamask,
@ -466,7 +466,7 @@ static struct platform_device at91_lcdc_device = {
.num_resources = ARRAY_SIZE(lcdc_resources),
};
void __init at91_add_device_lcdc(struct at91fb_info *data)
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
{
if (!data) {
return;
@ -499,7 +499,7 @@ void __init at91_add_device_lcdc(struct at91fb_info *data)
platform_device_register(&at91_lcdc_device);
}
#else
void __init at91_add_device_lcdc(struct at91fb_info *data) {}
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
#endif

View file

@ -87,6 +87,11 @@ static struct clk mmc1_clk = {
.pmc_mask = 1 << AT91SAM9263_ID_MCI1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk can_clk = {
.name = "can_clk",
.pmc_mask = 1 << AT91SAM9263_ID_CAN,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk twi_clk = {
.name = "twi_clk",
.pmc_mask = 1 << AT91SAM9263_ID_TWI,
@ -102,16 +107,46 @@ static struct clk spi1_clk = {
.pmc_mask = 1 << AT91SAM9263_ID_SPI1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc0_clk = {
.name = "ssc0_clk",
.pmc_mask = 1 << AT91SAM9263_ID_SSC0,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ssc1_clk = {
.name = "ssc1_clk",
.pmc_mask = 1 << AT91SAM9263_ID_SSC1,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk ac97_clk = {
.name = "ac97_clk",
.pmc_mask = 1 << AT91SAM9263_ID_AC97C,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk tcb_clk = {
.name = "tcb_clk",
.pmc_mask = 1 << AT91SAM9263_ID_TCB,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk pwmc_clk = {
.name = "pwmc_clk",
.pmc_mask = 1 << AT91SAM9263_ID_PWMC,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk macb_clk = {
.name = "macb_clk",
.pmc_mask = 1 << AT91SAM9263_ID_EMAC,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk dma_clk = {
.name = "dma_clk",
.pmc_mask = 1 << AT91SAM9263_ID_DMA,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk twodge_clk = {
.name = "2dge_clk",
.pmc_mask = 1 << AT91SAM9263_ID_2DGE,
.type = CLK_TYPE_PERIPHERAL,
};
static struct clk udc_clk = {
.name = "udc_clk",
.pmc_mask = 1 << AT91SAM9263_ID_UDP,
@ -142,20 +177,21 @@ static struct clk *periph_clocks[] __initdata = {
&usart2_clk,
&mmc0_clk,
&mmc1_clk,
// can
&can_clk,
&twi_clk,
&spi0_clk,
&spi1_clk,
// ssc0 .. ssc1
// ac97
&ssc0_clk,
&ssc1_clk,
&ac97_clk,
&tcb_clk,
// pwmc
&pwmc_clk,
&macb_clk,
// 2dge
&twodge_clk,
&udc_clk,
&isi_clk,
&lcdc_clk,
// dma
&dma_clk,
&ohci_clk,
// irq0 .. irq1
};

View file

@ -572,6 +572,130 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
#endif
/* --------------------------------------------------------------------
* AC97
* -------------------------------------------------------------------- */
#if defined(CONFIG_SND_AT91_AC97) || defined(CONFIG_SND_AT91_AC97_MODULE)
static u64 ac97_dmamask = 0xffffffffUL;
static struct atmel_ac97_data ac97_data;
static struct resource ac97_resources[] = {
[0] = {
.start = AT91SAM9263_BASE_AC97C,
.end = AT91SAM9263_BASE_AC97C + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9263_ID_AC97C,
.end = AT91SAM9263_ID_AC97C,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device at91sam9263_ac97_device = {
.name = "ac97c",
.id = 1,
.dev = {
.dma_mask = &ac97_dmamask,
.coherent_dma_mask = 0xffffffff,
.platform_data = &ac97_data,
},
.resource = ac97_resources,
.num_resources = ARRAY_SIZE(ac97_resources),
};
void __init at91_add_device_ac97(struct atmel_ac97_data *data)
{
if (!data)
return;
at91_set_A_periph(AT91_PIN_PB0, 0); /* AC97FS */
at91_set_A_periph(AT91_PIN_PB1, 0); /* AC97CK */
at91_set_A_periph(AT91_PIN_PB2, 0); /* AC97TX */
at91_set_A_periph(AT91_PIN_PB3, 0); /* AC97RX */
/* reset */
if (data->reset_pin)
at91_set_gpio_output(data->reset_pin, 0);
ac97_data = *ek_data;
platform_device_register(&at91sam9263_ac97_device);
}
#else
void __init at91_add_device_ac97(struct atmel_ac97_data *data) {}
#endif
/* --------------------------------------------------------------------
* LCD Controller
* -------------------------------------------------------------------- */
#if defined(CONFIG_FB_ATMEL) || defined(CONFIG_FB_ATMEL_MODULE)
static u64 lcdc_dmamask = 0xffffffffUL;
static struct atmel_lcdfb_info lcdc_data;
static struct resource lcdc_resources[] = {
[0] = {
.start = AT91SAM9263_LCDC_BASE,
.end = AT91SAM9263_LCDC_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9263_ID_LCDC,
.end = AT91SAM9263_ID_LCDC,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device at91_lcdc_device = {
.name = "atmel_lcdfb",
.id = 0,
.dev = {
.dma_mask = &lcdc_dmamask,
.coherent_dma_mask = 0xffffffff,
.platform_data = &lcdc_data,
},
.resource = lcdc_resources,
.num_resources = ARRAY_SIZE(lcdc_resources),
};
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
{
if (!data)
return;
at91_set_A_periph(AT91_PIN_PC1, 0); /* LCDHSYNC */
at91_set_A_periph(AT91_PIN_PC2, 0); /* LCDDOTCK */
at91_set_A_periph(AT91_PIN_PC3, 0); /* LCDDEN */
at91_set_B_periph(AT91_PIN_PB9, 0); /* LCDCC */
at91_set_A_periph(AT91_PIN_PC6, 0); /* LCDD2 */
at91_set_A_periph(AT91_PIN_PC7, 0); /* LCDD3 */
at91_set_A_periph(AT91_PIN_PC8, 0); /* LCDD4 */
at91_set_A_periph(AT91_PIN_PC9, 0); /* LCDD5 */
at91_set_A_periph(AT91_PIN_PC10, 0); /* LCDD6 */
at91_set_A_periph(AT91_PIN_PC11, 0); /* LCDD7 */
at91_set_A_periph(AT91_PIN_PC14, 0); /* LCDD10 */
at91_set_A_periph(AT91_PIN_PC15, 0); /* LCDD11 */
at91_set_A_periph(AT91_PIN_PC16, 0); /* LCDD12 */
at91_set_B_periph(AT91_PIN_PC12, 0); /* LCDD13 */
at91_set_A_periph(AT91_PIN_PC18, 0); /* LCDD14 */
at91_set_A_periph(AT91_PIN_PC19, 0); /* LCDD15 */
at91_set_A_periph(AT91_PIN_PC22, 0); /* LCDD18 */
at91_set_A_periph(AT91_PIN_PC23, 0); /* LCDD19 */
at91_set_A_periph(AT91_PIN_PC24, 0); /* LCDD20 */
at91_set_B_periph(AT91_PIN_PC17, 0); /* LCDD21 */
at91_set_A_periph(AT91_PIN_PC26, 0); /* LCDD22 */
at91_set_A_periph(AT91_PIN_PC27, 0); /* LCDD23 */
lcdc_data = *data;
platform_device_register(&at91_lcdc_device);
}
#else
void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) {}
#endif
/* --------------------------------------------------------------------
* LEDs
* -------------------------------------------------------------------- */

View file

@ -0,0 +1,166 @@
/*
* linux/arch/arm/mach-at91/board-picotux200.c
*
* Copyright (C) 2005 SAN People
* Copyright (C) 2007 Kleinhenz Elektronik GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/mtd/physmap.h>
#include <asm/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
#include <asm/arch/board.h>
#include <asm/arch/gpio.h>
#include <asm/arch/at91rm9200_mc.h>
#include "generic.h"
/*
* Serial port configuration.
* 0 .. 3 = USART0 .. USART3
* 4 = DBGU
*/
static struct at91_uart_config __initdata picotux200_uart_config = {
.console_tty = 0, /* ttyS0 */
.nr_tty = 2,
.tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */
};
static void __init picotux200_map_io(void)
{
/* Initialize processor: 18.432 MHz crystal */
at91rm9200_initialize(18432000, AT91RM9200_BGA);
/* Setup the serial ports and console */
at91_init_serial(&picotux200_uart_config);
}
static void __init picotux200_init_irq(void)
{
at91rm9200_init_interrupts(NULL);
}
static struct at91_eth_data __initdata picotux200_eth_data = {
.phy_irq_pin = AT91_PIN_PC4,
.is_rmii = 1,
};
static struct at91_usbh_data __initdata picotux200_usbh_data = {
.ports = 1,
};
// static struct at91_udc_data __initdata picotux200_udc_data = {
// .vbus_pin = AT91_PIN_PD4,
// .pullup_pin = AT91_PIN_PD5,
// };
static struct at91_mmc_data __initdata picotux200_mmc_data = {
.det_pin = AT91_PIN_PB27,
.slot_b = 0,
.wire4 = 1,
.wp_pin = AT91_PIN_PA17,
};
// static struct spi_board_info picotux200_spi_devices[] = {
// { /* DataFlash chip */
// .modalias = "mtd_dataflash",
// .chip_select = 0,
// .max_speed_hz = 15 * 1000 * 1000,
// },
// #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
// { /* DataFlash card */
// .modalias = "mtd_dataflash",
// .chip_select = 3,
// .max_speed_hz = 15 * 1000 * 1000,
// },
// #endif
// };
#define PICOTUX200_FLASH_BASE AT91_CHIPSELECT_0
#define PICOTUX200_FLASH_SIZE 0x400000
static struct physmap_flash_data picotux200_flash_data = {
.width = 2,
};
static struct resource picotux200_flash_resource = {
.start = PICOTUX200_FLASH_BASE,
.end = PICOTUX200_FLASH_BASE + PICOTUX200_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device picotux200_flash = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &picotux200_flash_data,
},
.resource = &picotux200_flash_resource,
.num_resources = 1,
};
static void __init picotux200_board_init(void)
{
/* Serial */
at91_add_device_serial();
/* Ethernet */
at91_add_device_eth(&picotux200_eth_data);
/* USB Host */
at91_add_device_usbh(&picotux200_usbh_data);
/* USB Device */
// at91_add_device_udc(&picotux200_udc_data);
// at91_set_multi_drive(picotux200_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */
/* I2C */
at91_add_device_i2c();
/* SPI */
// at91_add_device_spi(picotux200_spi_devices, ARRAY_SIZE(picotux200_spi_devices));
#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
/* DataFlash card */
at91_set_gpio_output(AT91_PIN_PB22, 0);
#else
/* MMC */
at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */
at91_add_device_mmc(0, &picotux200_mmc_data);
#endif
/* NOR Flash */
platform_device_register(&picotux200_flash);
}
MACHINE_START(PICOTUX2XX, "picotux 200")
/* Maintainer: Kleinhenz Elektronik GmbH */
.phys_io = AT91_BASE_SYS,
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
.boot_params = AT91_SDRAM_BASE + 0x100,
.timer = &at91rm9200_timer,
.map_io = picotux200_map_io,
.init_irq = picotux200_init_irq,
.init_machine = picotux200_board_init,
MACHINE_END

View file

@ -104,9 +104,9 @@ static struct spi_board_info ek_spi_devices[] = {
},
#endif
#endif
#if defined(CONFIG_SND_AT73C213)
#if defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
{ /* AT73C213 DAC */
.modalias = "snd_at73c213",
.modalias = "at73c213",
.chip_select = 0,
.max_speed_hz = 10 * 1000 * 1000,
.bus_num = 1,
@ -118,7 +118,7 @@ static struct spi_board_info ek_spi_devices[] = {
/*
* MACB Ethernet device
*/
static struct __initdata at91_eth_data ek_macb_data = {
static struct at91_eth_data __initdata ek_macb_data = {
.phy_irq_pin = AT91_PIN_PA7,
.is_rmii = 1,
};
@ -140,7 +140,7 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
},
};
static struct mtd_partition *nand_partitions(int size, int *num_partitions)
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
{
*num_partitions = ARRAY_SIZE(ek_nand_partition);
return ek_nand_partition;
@ -188,6 +188,8 @@ static void __init ek_board_init(void)
at91_add_device_eth(&ek_macb_data);
/* MMC */
at91_add_device_mmc(0, &ek_mmc_data);
/* I2C */
at91_add_device_i2c();
}
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")

View file

@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/dm9000.h>
#include <asm/hardware.h>
@ -194,6 +195,41 @@ static struct at91_nand_data __initdata ek_nand_data = {
#endif
};
/*
* ADS7846 Touchscreen
*/
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
static int ads7843_pendown_state(void)
{
return !at91_get_gpio_value(AT91_PIN_PC2); /* Touchscreen PENIRQ */
}
static struct ads7846_platform_data ads_info = {
.model = 7843,
.x_min = 150,
.x_max = 3830,
.y_min = 190,
.y_max = 3830,
.vref_delay_usecs = 100,
.x_plate_ohms = 450,
.y_plate_ohms = 250,
.pressure_max = 15000,
.debounce_max = 1,
.debounce_rep = 0,
.debounce_tol = (~0),
.get_pendown_state = ads7843_pendown_state,
};
static void __init ek_add_device_ts(void)
{
at91_set_B_periph(AT91_PIN_PC2, 1); /* External IRQ0, with pullup */
at91_set_gpio_input(AT91_PIN_PA11, 1); /* Touchscreen BUSY signal */
}
#else
static void __init ek_add_device_ts(void) {}
#endif
/*
* SPI devices
*/
@ -204,6 +240,16 @@ static struct spi_board_info ek_spi_devices[] = {
.max_speed_hz = 15 * 1000 * 1000,
.bus_num = 0,
},
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
{
.modalias = "ads7846",
.chip_select = 2,
.max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */
.bus_num = 0,
.platform_data = &ads_info,
.irq = AT91SAM9261_ID_IRQ0,
},
#endif
#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
{ /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */
.modalias = "mtd_dataflash",
@ -211,9 +257,9 @@ static struct spi_board_info ek_spi_devices[] = {
.max_speed_hz = 15 * 1000 * 1000,
.bus_num = 0,
},
#elif defined(CONFIG_SND_AT73C213)
#elif defined(CONFIG_SND_AT73C213) || defined(CONFIG_SND_AT73C213_MODULE)
{ /* AT73C213 DAC */
.modalias = "snd_at73c213",
.modalias = "at73c213",
.chip_select = 3,
.max_speed_hz = 10 * 1000 * 1000,
.bus_num = 0,
@ -241,6 +287,8 @@ static void __init ek_board_init(void)
#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE)
/* SPI */
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
/* Touchscreen */
ek_add_device_ts();
#else
/* MMC */
at91_add_device_mmc(0, &ek_mmc_data);

View file

@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <asm/hardware.h>
#include <asm/setup.h>
@ -85,6 +86,40 @@ static struct at91_udc_data __initdata ek_udc_data = {
};
/*
* ADS7846 Touchscreen
*/
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
static int ads7843_pendown_state(void)
{
return !at91_get_gpio_value(AT91_PIN_PA15); /* Touchscreen PENIRQ */
}
static struct ads7846_platform_data ads_info = {
.model = 7843,
.x_min = 150,
.x_max = 3830,
.y_min = 190,
.y_max = 3830,
.vref_delay_usecs = 100,
.x_plate_ohms = 450,
.y_plate_ohms = 250,
.pressure_max = 15000,
.debounce_max = 1,
.debounce_rep = 0,
.debounce_tol = (~0),
.get_pendown_state = ads7843_pendown_state,
};
static void __init ek_add_device_ts(void)
{
at91_set_B_periph(AT91_PIN_PA15, 1); /* External IRQ1, with pullup */
at91_set_gpio_input(AT91_PIN_PA31, 1); /* Touchscreen BUSY signal */
}
#else
static void __init ek_add_device_ts(void) {}
#endif
/*
* SPI devices.
*/
@ -97,6 +132,16 @@ static struct spi_board_info ek_spi_devices[] = {
.bus_num = 0,
},
#endif
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
{
.modalias = "ads7846",
.chip_select = 3,
.max_speed_hz = 125000 * 26, /* (max sample rate @ 3V) * (cmd + data + overhead) */
.bus_num = 0,
.platform_data = &ads_info,
.irq = AT91SAM9263_ID_IRQ1,
},
#endif
};
@ -111,6 +156,14 @@ static struct at91_mmc_data __initdata ek_mmc_data = {
};
/*
* MACB Ethernet device
*/
static struct at91_eth_data __initdata ek_macb_data = {
.is_rmii = 1,
};
/*
* NAND flash
*/
@ -148,6 +201,14 @@ static struct at91_nand_data __initdata ek_nand_data = {
};
/*
* AC97
*/
static struct atmel_ac97_data ek_ac97_data = {
.reset_pin = AT91_PIN_PA13,
};
static void __init ek_board_init(void)
{
/* Serial */
@ -157,11 +218,20 @@ static void __init ek_board_init(void)
/* USB Device */
at91_add_device_udc(&ek_udc_data);
/* SPI */
at91_set_gpio_output(AT91_PIN_PE20, 1); /* select spi0 clock */
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
/* Touchscreen */
ek_add_device_ts();
/* MMC */
at91_add_device_mmc(1, &ek_mmc_data);
/* Ethernet */
at91_add_device_eth(&ek_macb_data);
/* NAND */
at91_add_device_nand(&ek_nand_data);
/* I2C */
at91_add_device_i2c();
/* AC97 */
at91_add_device_ac97(&ek_ac97_data);
}
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")

View file

@ -102,6 +102,26 @@ EXPORT_SYMBOL(__readb);
EXPORT_SYMBOL(__readw);
EXPORT_SYMBOL(__readl);
void readsw(void __iomem *addr, void *data, int len)
{
void __iomem *a = __isamem_convert_addr(addr);
BUG_ON((unsigned long)addr & 1);
__raw_readsw(a, data, len);
}
EXPORT_SYMBOL(readsw);
void readsl(void __iomem *addr, void *data, int len)
{
void __iomem *a = __isamem_convert_addr(addr);
BUG_ON((unsigned long)addr & 3);
__raw_readsl(a, data, len);
}
EXPORT_SYMBOL(readsl);
void __writeb(u8 val, void __iomem *addr)
{
void __iomem *a = __isamem_convert_addr(addr);
@ -137,6 +157,26 @@ EXPORT_SYMBOL(__writeb);
EXPORT_SYMBOL(__writew);
EXPORT_SYMBOL(__writel);
void writesw(void __iomem *addr, void *data, int len)
{
void __iomem *a = __isamem_convert_addr(addr);
BUG_ON((unsigned long)addr & 1);
__raw_writesw(a, data, len);
}
EXPORT_SYMBOL(writesw);
void writesl(void __iomem *addr, void *data, int len)
{
void __iomem *a = __isamem_convert_addr(addr);
BUG_ON((unsigned long)addr & 3);
__raw_writesl(a, data, len);
}
EXPORT_SYMBOL(writesl);
#define SUPERIO_PORT(p) \
(((p) >> 3) == (0x3f8 >> 3) || \
((p) >> 3) == (0x2f8 >> 3) || \

View file

@ -27,6 +27,10 @@ struct clk {
u32 enable_mask;
};
static struct clk clk_uart = {
.name = "UARTCLK",
.rate = 14745600,
};
static struct clk clk_pll1 = {
.name = "pll1",
};
@ -50,6 +54,7 @@ static struct clk clk_usb_host = {
static struct clk *clocks[] = {
&clk_uart,
&clk_pll1,
&clk_f,
&clk_h,

View file

@ -10,7 +10,6 @@
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/slab.h>

View file

@ -23,7 +23,6 @@
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/init.h>

View file

@ -22,7 +22,6 @@
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>

View file

@ -7,5 +7,6 @@ obj-$(CONFIG_ARCH_IOP13XX) += setup.o
obj-$(CONFIG_ARCH_IOP13XX) += irq.o
obj-$(CONFIG_ARCH_IOP13XX) += pci.o
obj-$(CONFIG_ARCH_IOP13XX) += io.o
obj-$(CONFIG_ARCH_IOP13XX) += tpmi.o
obj-$(CONFIG_MACH_IQ81340SC) += iq81340sc.o
obj-$(CONFIG_MACH_IQ81340MC) += iq81340mc.o

View file

@ -41,7 +41,7 @@ void * __iomem __iop13xx_io(unsigned long io_addr)
EXPORT_SYMBOL(__iop13xx_io);
void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
unsigned long flags)
unsigned int mtype)
{
void __iomem * retval;
@ -61,9 +61,9 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
(cookie - IOP13XX_PCIE_LOWER_MEM_RA));
break;
case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
retval = __ioremap(IOP13XX_PBI_LOWER_MEM_PA +
(cookie - IOP13XX_PBI_LOWER_MEM_RA),
size, flags);
retval = __arm_ioremap(IOP13XX_PBI_LOWER_MEM_PA +
(cookie - IOP13XX_PBI_LOWER_MEM_RA),
size, mtype);
break;
case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
@ -75,7 +75,7 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
break;
default:
retval = __ioremap(cookie, size, flags);
retval = __arm_ioremap(cookie, size, mtype);
}
return retval;

View file

@ -75,11 +75,14 @@ static void __init iq81340mc_init(void)
{
iop13xx_platform_init();
iq81340mc_pci_init();
iop13xx_add_tpmi_devices();
}
static void __init iq81340mc_timer_init(void)
{
iop_init_time(400000000);
unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
printk(KERN_DEBUG "%s: bus frequency: %lu\n", __FUNCTION__, bus_freq);
iop_init_time(bus_freq);
}
static struct sys_timer iq81340mc_timer = {

View file

@ -77,11 +77,14 @@ static void __init iq81340sc_init(void)
{
iop13xx_platform_init();
iq81340sc_pci_init();
iop13xx_add_tpmi_devices();
}
static void __init iq81340sc_timer_init(void)
{
iop_init_time(400000000);
unsigned long bus_freq = iop13xx_core_freq() / iop13xx_xsi_bus_ratio();
printk(KERN_DEBUG "%s: bus frequency: %lu\n", __FUNCTION__, bus_freq);
iop_init_time(bus_freq);
}
static struct sys_timer iq81340sc_timer = {

View file

@ -88,9 +88,9 @@ void iop13xx_map_pci_memory(void)
if (end) {
iop13xx_atux_mem_base =
(u32) __ioremap_pfn(
(u32) __arm_ioremap_pfn(
__phys_to_pfn(IOP13XX_PCIX_LOWER_MEM_PA)
, 0, iop13xx_atux_mem_size, 0);
, 0, iop13xx_atux_mem_size, MT_DEVICE);
if (!iop13xx_atux_mem_base) {
printk("%s: atux allocation "
"failed\n", __FUNCTION__);
@ -114,9 +114,9 @@ void iop13xx_map_pci_memory(void)
if (end) {
iop13xx_atue_mem_base =
(u32) __ioremap_pfn(
(u32) __arm_ioremap_pfn(
__phys_to_pfn(IOP13XX_PCIE_LOWER_MEM_PA)
, 0, iop13xx_atue_mem_size, 0);
, 0, iop13xx_atue_mem_size, MT_DEVICE);
if (!iop13xx_atue_mem_base) {
printk("%s: atue allocation "
"failed\n", __FUNCTION__);
@ -1023,7 +1023,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
<< IOP13XX_ATUX_PCIXSR_FUNC_NUM;
__raw_writel(pcixsr, IOP13XX_ATUX_PCIXSR);
res[0].start = IOP13XX_PCIX_LOWER_IO_PA;
res[0].start = IOP13XX_PCIX_LOWER_IO_PA + IOP13XX_PCIX_IO_BUS_OFFSET;
res[0].end = IOP13XX_PCIX_UPPER_IO_PA;
res[0].name = "IQ81340 ATUX PCI I/O Space";
res[0].flags = IORESOURCE_IO;
@ -1033,7 +1033,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
res[1].name = "IQ81340 ATUX PCI Memory Space";
res[1].flags = IORESOURCE_MEM;
sys->mem_offset = IOP13XX_PCIX_MEM_OFFSET;
sys->io_offset = IOP13XX_PCIX_IO_OFFSET;
sys->io_offset = IOP13XX_PCIX_LOWER_IO_PA;
break;
case IOP13XX_INIT_ATU_ATUE:
/* Note: the function number field in the PCSR is ro */
@ -1044,7 +1044,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
__raw_writel(pcsr, IOP13XX_ATUE_PCSR);
res[0].start = IOP13XX_PCIE_LOWER_IO_PA;
res[0].start = IOP13XX_PCIE_LOWER_IO_PA + IOP13XX_PCIE_IO_BUS_OFFSET;
res[0].end = IOP13XX_PCIE_UPPER_IO_PA;
res[0].name = "IQ81340 ATUE PCI I/O Space";
res[0].flags = IORESOURCE_IO;
@ -1054,7 +1054,7 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
res[1].name = "IQ81340 ATUE PCI Memory Space";
res[1].flags = IORESOURCE_MEM;
sys->mem_offset = IOP13XX_PCIE_MEM_OFFSET;
sys->io_offset = IOP13XX_PCIE_IO_OFFSET;
sys->io_offset = IOP13XX_PCIE_LOWER_IO_PA;
sys->map_irq = iop13xx_pcie_map_irq;
break;
default:

View file

@ -258,15 +258,11 @@ void __init iop13xx_platform_init(void)
if (init_uart == IOP13XX_INIT_UART_DEFAULT) {
switch (iop13xx_dev_id()) {
/* enable both uarts on iop341 and iop342 */
/* enable both uarts on iop341 */
case 0x3380:
case 0x3384:
case 0x3388:
case 0x338c:
case 0x3382:
case 0x3386:
case 0x338a:
case 0x338e:
init_uart |= IOP13XX_INIT_UART_0;
init_uart |= IOP13XX_INIT_UART_1;
break;

View file

@ -0,0 +1,234 @@
/*
* iop13xx tpmi device resources
* Copyright (c) 2005-2006, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/sizes.h>
/* assumes CONTROLLER_ONLY# is never asserted in the ESSR register */
#define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12))
#define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13))
#define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10))
#define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1)
#define IOP13XX_TPMI_MEM_SIZE (255)
#define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1)
#define IOP13XX_TPMI_RESOURCE_MMR 0
#define IOP13XX_TPMI_RESOURCE_MEM 1
#define IOP13XX_TPMI_RESOURCE_CTRL 2
#define IOP13XX_TPMI_RESOURCE_IRQ 3
static struct resource iop13xx_tpmi_0_resources[] = {
[IOP13XX_TPMI_RESOURCE_MMR] = {
.start = IOP13XX_TPMI_MMR(4), /* tpmi0 starts at dev == 4 */
.end = IOP13XX_TPMI_MMR(4) + IOP13XX_TPMI_MMR_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_MEM] = {
.start = IOP13XX_TPMI_MEM(0),
.end = IOP13XX_TPMI_MEM(0) + IOP13XX_TPMI_MEM_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_CTRL] = {
.start = IOP13XX_TPMI_CTRL(0),
.end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI0_OUT,
.end = IRQ_IOP13XX_TPMI0_OUT,
.flags = IORESOURCE_IRQ
}
};
static struct resource iop13xx_tpmi_1_resources[] = {
[IOP13XX_TPMI_RESOURCE_MMR] = {
.start = IOP13XX_TPMI_MMR(1),
.end = IOP13XX_TPMI_MMR(1) + IOP13XX_TPMI_MMR_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_MEM] = {
.start = IOP13XX_TPMI_MEM(1),
.end = IOP13XX_TPMI_MEM(1) + IOP13XX_TPMI_MEM_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_CTRL] = {
.start = IOP13XX_TPMI_CTRL(1),
.end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI1_OUT,
.end = IRQ_IOP13XX_TPMI1_OUT,
.flags = IORESOURCE_IRQ
}
};
static struct resource iop13xx_tpmi_2_resources[] = {
[IOP13XX_TPMI_RESOURCE_MMR] = {
.start = IOP13XX_TPMI_MMR(2),
.end = IOP13XX_TPMI_MMR(2) + IOP13XX_TPMI_MMR_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_MEM] = {
.start = IOP13XX_TPMI_MEM(2),
.end = IOP13XX_TPMI_MEM(2) + IOP13XX_TPMI_MEM_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_CTRL] = {
.start = IOP13XX_TPMI_CTRL(2),
.end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI2_OUT,
.end = IRQ_IOP13XX_TPMI2_OUT,
.flags = IORESOURCE_IRQ
}
};
static struct resource iop13xx_tpmi_3_resources[] = {
[IOP13XX_TPMI_RESOURCE_MMR] = {
.start = IOP13XX_TPMI_MMR(3),
.end = IOP13XX_TPMI_MMR(3) + IOP13XX_TPMI_MMR_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_MEM] = {
.start = IOP13XX_TPMI_MEM(3),
.end = IOP13XX_TPMI_MEM(3) + IOP13XX_TPMI_MEM_SIZE,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_CTRL] = {
.start = IOP13XX_TPMI_CTRL(3),
.end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL,
.flags = IORESOURCE_MEM,
},
[IOP13XX_TPMI_RESOURCE_IRQ] = {
.start = IRQ_IOP13XX_TPMI3_OUT,
.end = IRQ_IOP13XX_TPMI3_OUT,
.flags = IORESOURCE_IRQ
}
};
u64 iop13xx_tpmi_mask = DMA_64BIT_MASK;
static struct platform_device iop13xx_tpmi_0_device = {
.name = "iop-tpmi",
.id = 0,
.num_resources = 4,
.resource = iop13xx_tpmi_0_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
.coherent_dma_mask = DMA_64BIT_MASK,
},
};
static struct platform_device iop13xx_tpmi_1_device = {
.name = "iop-tpmi",
.id = 1,
.num_resources = 4,
.resource = iop13xx_tpmi_1_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
.coherent_dma_mask = DMA_64BIT_MASK,
},
};
static struct platform_device iop13xx_tpmi_2_device = {
.name = "iop-tpmi",
.id = 2,
.num_resources = 4,
.resource = iop13xx_tpmi_2_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
.coherent_dma_mask = DMA_64BIT_MASK,
},
};
static struct platform_device iop13xx_tpmi_3_device = {
.name = "iop-tpmi",
.id = 3,
.num_resources = 4,
.resource = iop13xx_tpmi_3_resources,
.dev = {
.dma_mask = &iop13xx_tpmi_mask,
.coherent_dma_mask = DMA_64BIT_MASK,
},
};
__init void iop13xx_add_tpmi_devices(void)
{
unsigned short device_id;
/* tpmi's not present on iop341 or iop342 */
if (__raw_readl(IOP13XX_ESSR0) & IOP13XX_INTERFACE_SEL_PCIX)
/* ATUE must be present */
device_id = __raw_readw(IOP13XX_ATUE_DID);
else
/* ATUX must be present */
device_id = __raw_readw(IOP13XX_ATUX_DID);
switch (device_id) {
/* iop34[1|2] 0-tpmi */
case 0x3380:
case 0x3384:
case 0x3388:
case 0x338c:
case 0x3382:
case 0x3386:
case 0x338a:
case 0x338e:
return;
/* iop348 1-tpmi */
case 0x3310:
case 0x3312:
case 0x3314:
case 0x3318:
case 0x331a:
case 0x331c:
case 0x33c0:
case 0x33c2:
case 0x33c4:
case 0x33c8:
case 0x33ca:
case 0x33cc:
case 0x33b0:
case 0x33b2:
case 0x33b4:
case 0x33b8:
case 0x33ba:
case 0x33bc:
case 0x3320:
case 0x3322:
case 0x3324:
case 0x3328:
case 0x332a:
case 0x332c:
platform_device_register(&iop13xx_tpmi_0_device);
return;
default:
platform_device_register(&iop13xx_tpmi_0_device);
platform_device_register(&iop13xx_tpmi_1_device);
platform_device_register(&iop13xx_tpmi_2_device);
platform_device_register(&iop13xx_tpmi_3_device);
return;
}
}

View file

@ -34,6 +34,14 @@ config MACH_N2100
Say Y here if you want to run your kernel on the Thecus n2100
NAS appliance.
config IOP3XX_ATU
bool "Enable the PCI Controller"
default y
help
Say Y here if you want the IOP to initialize its PCI Controller.
Say N if the IOP is an add in card, the host system owns the PCI
bus in this case.
endmenu
endif

View file

@ -178,9 +178,10 @@ static struct hw_pci iq31244_pci __initdata = {
static int __init iq31244_pci_init(void)
{
if (is_ep80219())
pci_common_init(&ep80219_pci);
else if (machine_is_iq31244()) {
if (is_ep80219()) {
if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
pci_common_init(&ep80219_pci);
} else if (machine_is_iq31244()) {
if (is_80219()) {
printk("note: iq31244 board type has been selected\n");
printk("note: to select ep80219 operation:\n");
@ -189,7 +190,9 @@ static int __init iq31244_pci_init(void)
printk("\t2/ update boot loader to pass"
" the ep80219 id: %d\n", MACH_TYPE_EP80219);
}
pci_common_init(&iq31244_pci);
if (iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE)
pci_common_init(&iq31244_pci);
}
return 0;

View file

@ -113,7 +113,8 @@ static struct hw_pci iq80321_pci __initdata = {
static int __init iq80321_pci_init(void)
{
if (machine_is_iq80321())
if ((iop3xx_get_init_atu() == IOP3XX_INIT_ATU_ENABLE) &&
machine_is_iq80321())
pci_common_init(&iq80321_pci);
return 0;

Some files were not shown because too many files have changed in this diff Show more