Auto-update from upstream
This commit is contained in:
commit
25da097460
|
@ -23,6 +23,7 @@ Module.symvers
|
|||
# Generated include files
|
||||
#
|
||||
include/asm
|
||||
include/asm-*/asm-offsets.h
|
||||
include/config
|
||||
include/linux/autoconf.h
|
||||
include/linux/compile.h
|
||||
|
|
1
CREDITS
1
CREDITS
|
@ -1883,6 +1883,7 @@ N: Jaya Kumar
|
|||
E: jayalk@intworks.biz
|
||||
W: http://www.intworks.biz
|
||||
D: Arc monochrome LCD framebuffer driver, x86 reboot fixups
|
||||
D: pirq addr, CS5535 alsa audio driver
|
||||
S: Gurgaon, India
|
||||
S: Kuala Lumpur, Malaysia
|
||||
|
||||
|
|
|
@ -253,6 +253,7 @@
|
|||
!Edrivers/usb/core/urb.c
|
||||
!Edrivers/usb/core/message.c
|
||||
!Edrivers/usb/core/file.c
|
||||
!Edrivers/usb/core/driver.c
|
||||
!Edrivers/usb/core/usb.c
|
||||
!Edrivers/usb/core/hub.c
|
||||
</chapter>
|
||||
|
|
|
@ -158,7 +158,7 @@ Even if the maintainer did not respond in step #4, make sure to ALWAYS
|
|||
copy the maintainer when you change their code.
|
||||
|
||||
For small patches you may want to CC the Trivial Patch Monkey
|
||||
trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
|
||||
trivial@kernel.org managed by Adrian Bunk; which collects "trivial"
|
||||
patches. Trivial patches must qualify for one of the following rules:
|
||||
Spelling fixes in documentation
|
||||
Spelling fixes which could break grep(1).
|
||||
|
@ -171,7 +171,7 @@ patches. Trivial patches must qualify for one of the following rules:
|
|||
since people copy, as long as it's trivial)
|
||||
Any fix by the author/maintainer of the file. (ie. patch monkey
|
||||
in re-transmission mode)
|
||||
URL: <http://www.kernel.org/pub/linux/kernel/people/rusty/trivial/>
|
||||
URL: <http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ The following people helped with review comments and inputs for this
|
|||
document:
|
||||
Christoph Hellwig <hch@infradead.org>
|
||||
Arjan van de Ven <arjanv@redhat.com>
|
||||
Randy Dunlap <rddunlap@osdl.org>
|
||||
Randy Dunlap <rdunlap@xenotime.net>
|
||||
Andre Hedrick <andre@linux-ide.org>
|
||||
|
||||
The following people helped with fixes/contributions to the bio patches
|
||||
|
@ -263,14 +263,8 @@ A flag in the bio structure, BIO_BARRIER is used to identify a barrier i/o.
|
|||
The generic i/o scheduler would make sure that it places the barrier request and
|
||||
all other requests coming after it after all the previous requests in the
|
||||
queue. Barriers may be implemented in different ways depending on the
|
||||
driver. A SCSI driver for example could make use of ordered tags to
|
||||
preserve the necessary ordering with a lower impact on throughput. For IDE
|
||||
this might be two sync cache flush: a pre and post flush when encountering
|
||||
a barrier write.
|
||||
|
||||
There is a provision for queues to indicate what kind of barriers they
|
||||
can provide. This is as of yet unmerged, details will be added here once it
|
||||
is in the kernel.
|
||||
driver. For more details regarding I/O barriers, please read barrier.txt
|
||||
in this directory.
|
||||
|
||||
1.2.2 Request Priority/Latency
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ Contents:
|
|||
2.2 Powersave
|
||||
2.3 Userspace
|
||||
2.4 Ondemand
|
||||
2.5 Conservative
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
|
||||
|
@ -110,9 +111,64 @@ directory.
|
|||
|
||||
The CPUfreq govenor "ondemand" sets the CPU depending on the
|
||||
current usage. To do this the CPU must have the capability to
|
||||
switch the frequency very fast.
|
||||
switch the frequency very quickly. There are a number of sysfs file
|
||||
accessible parameters:
|
||||
|
||||
sampling_rate: measured in uS (10^-6 seconds), this is how often you
|
||||
want the kernel to look at the CPU usage and to make decisions on
|
||||
what to do about the frequency. Typically this is set to values of
|
||||
around '10000' or more.
|
||||
|
||||
show_sampling_rate_(min|max): the minimum and maximum sampling rates
|
||||
available that you may set 'sampling_rate' to.
|
||||
|
||||
up_threshold: defines what the average CPU usaged between the samplings
|
||||
of 'sampling_rate' needs to be for the kernel to make a decision on
|
||||
whether it should increase the frequency. For example when it is set
|
||||
to its default value of '80' it means that between the checking
|
||||
intervals the CPU needs to be on average more than 80% in use to then
|
||||
decide that the CPU frequency needs to be increased.
|
||||
|
||||
sampling_down_factor: this parameter controls the rate that the CPU
|
||||
makes a decision on when to decrease the frequency. When set to its
|
||||
default value of '5' it means that at 1/5 the sampling_rate the kernel
|
||||
makes a decision to lower the frequency. Five "lower rate" decisions
|
||||
have to be made in a row before the CPU frequency is actually lower.
|
||||
If set to '1' then the frequency decreases as quickly as it increases,
|
||||
if set to '2' it decreases at half the rate of the increase.
|
||||
|
||||
ignore_nice_load: this parameter takes a value of '0' or '1', when set
|
||||
to '0' (its default) then all processes are counted towards towards the
|
||||
'cpu utilisation' value. When set to '1' then processes that are
|
||||
run with a 'nice' value will not count (and thus be ignored) in the
|
||||
overal usage calculation. This is useful if you are running a CPU
|
||||
intensive calculation on your laptop that you do not care how long it
|
||||
takes to complete as you can 'nice' it and prevent it from taking part
|
||||
in the deciding process of whether to increase your CPU frequency.
|
||||
|
||||
|
||||
2.5 Conservative
|
||||
----------------
|
||||
|
||||
The CPUfreq governor "conservative", much like the "ondemand"
|
||||
governor, sets the CPU depending on the current usage. It differs in
|
||||
behaviour in that it gracefully increases and decreases the CPU speed
|
||||
rather than jumping to max speed the moment there is any load on the
|
||||
CPU. This behaviour more suitable in a battery powered environment.
|
||||
The governor is tweaked in the same manner as the "ondemand" governor
|
||||
through sysfs with the addition of:
|
||||
|
||||
freq_step: this describes what percentage steps the cpu freq should be
|
||||
increased and decreased smoothly by. By default the cpu frequency will
|
||||
increase in 5% chunks of your maximum cpu frequency. You can change this
|
||||
value to anywhere between 0 and 100 where '0' will effectively lock your
|
||||
CPU at a speed regardless of its load whilst '100' will, in theory, make
|
||||
it behave identically to the "ondemand" governor.
|
||||
|
||||
down_threshold: same as the 'up_threshold' found for the "ondemand"
|
||||
governor but for the opposite direction. For example when set to its
|
||||
default value of '20' it means that if the CPU usage needs to be below
|
||||
20% between samples to have the frequency decreased.
|
||||
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
=============================================
|
||||
|
|
|
@ -47,17 +47,6 @@ Who: Paul E. McKenney <paulmck@us.ibm.com>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: IEEE1394 Audio and Music Data Transmission Protocol driver,
|
||||
Connection Management Procedures driver
|
||||
When: November 2005
|
||||
Files: drivers/ieee1394/{amdtp,cmp}*
|
||||
Why: These are incomplete, have never worked, and are better implemented
|
||||
in userland via raw1394 (see http://freebob.sourceforge.net/ for
|
||||
example.)
|
||||
Who: Jody McIntyre <scjody@steamballoon.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
|
||||
When: November 2005
|
||||
Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
|
||||
|
|
|
@ -12,14 +12,16 @@ cifs.txt
|
|||
- description of the CIFS filesystem
|
||||
coda.txt
|
||||
- description of the CODA filesystem.
|
||||
configfs/
|
||||
- directory containing configfs documentation and example code.
|
||||
cramfs.txt
|
||||
- info on the cram filesystem for small storage (ROMs etc)
|
||||
devfs/
|
||||
- directory containing devfs documentation.
|
||||
dlmfs.txt
|
||||
- info on the userspace interface to the OCFS2 DLM.
|
||||
ext2.txt
|
||||
- info, mount options and specifications for the Ext2 filesystem.
|
||||
fat_cvf.txt
|
||||
- info on the Compressed Volume Files extension to the FAT filesystem
|
||||
hpfs.txt
|
||||
- info and mount options for the OS/2 HPFS.
|
||||
isofs.txt
|
||||
|
@ -32,6 +34,8 @@ ntfs.txt
|
|||
- info and mount options for the NTFS filesystem (Windows NT).
|
||||
proc.txt
|
||||
- info on Linux's /proc filesystem.
|
||||
ocfs2.txt
|
||||
- info and mount options for the OCFS2 clustered filesystem.
|
||||
romfs.txt
|
||||
- Description of the ROMFS filesystem.
|
||||
smbfs.txt
|
||||
|
|
|
@ -0,0 +1,434 @@
|
|||
|
||||
configfs - Userspace-driven kernel object configuation.
|
||||
|
||||
Joel Becker <joel.becker@oracle.com>
|
||||
|
||||
Updated: 31 March 2005
|
||||
|
||||
Copyright (c) 2005 Oracle Corporation,
|
||||
Joel Becker <joel.becker@oracle.com>
|
||||
|
||||
|
||||
[What is configfs?]
|
||||
|
||||
configfs is a ram-based filesystem that provides the converse of
|
||||
sysfs's functionality. Where sysfs is a filesystem-based view of
|
||||
kernel objects, configfs is a filesystem-based manager of kernel
|
||||
objects, or config_items.
|
||||
|
||||
With sysfs, an object is created in kernel (for example, when a device
|
||||
is discovered) and it is registered with sysfs. Its attributes then
|
||||
appear in sysfs, allowing userspace to read the attributes via
|
||||
readdir(3)/read(2). It may allow some attributes to be modified via
|
||||
write(2). The important point is that the object is created and
|
||||
destroyed in kernel, the kernel controls the lifecycle of the sysfs
|
||||
representation, and sysfs is merely a window on all this.
|
||||
|
||||
A configfs config_item is created via an explicit userspace operation:
|
||||
mkdir(2). It is destroyed via rmdir(2). The attributes appear at
|
||||
mkdir(2) time, and can be read or modified via read(2) and write(2).
|
||||
As with sysfs, readdir(3) queries the list of items and/or attributes.
|
||||
symlink(2) can be used to group items together. Unlike sysfs, the
|
||||
lifetime of the representation is completely driven by userspace. The
|
||||
kernel modules backing the items must respond to this.
|
||||
|
||||
Both sysfs and configfs can and should exist together on the same
|
||||
system. One is not a replacement for the other.
|
||||
|
||||
[Using configfs]
|
||||
|
||||
configfs can be compiled as a module or into the kernel. You can access
|
||||
it by doing
|
||||
|
||||
mount -t configfs none /config
|
||||
|
||||
The configfs tree will be empty unless client modules are also loaded.
|
||||
These are modules that register their item types with configfs as
|
||||
subsystems. Once a client subsystem is loaded, it will appear as a
|
||||
subdirectory (or more than one) under /config. Like sysfs, the
|
||||
configfs tree is always there, whether mounted on /config or not.
|
||||
|
||||
An item is created via mkdir(2). The item's attributes will also
|
||||
appear at this time. readdir(3) can determine what the attributes are,
|
||||
read(2) can query their default values, and write(2) can store new
|
||||
values. Like sysfs, attributes should be ASCII text files, preferably
|
||||
with only one value per file. The same efficiency caveats from sysfs
|
||||
apply. Don't mix more than one attribute in one attribute file.
|
||||
|
||||
Like sysfs, configfs expects write(2) to store the entire buffer at
|
||||
once. When writing to configfs attributes, userspace processes should
|
||||
first read the entire file, modify the portions they wish to change, and
|
||||
then write the entire buffer back. Attribute files have a maximum size
|
||||
of one page (PAGE_SIZE, 4096 on i386).
|
||||
|
||||
When an item needs to be destroyed, remove it with rmdir(2). An
|
||||
item cannot be destroyed if any other item has a link to it (via
|
||||
symlink(2)). Links can be removed via unlink(2).
|
||||
|
||||
[Configuring FakeNBD: an Example]
|
||||
|
||||
Imagine there's a Network Block Device (NBD) driver that allows you to
|
||||
access remote block devices. Call it FakeNBD. FakeNBD uses configfs
|
||||
for its configuration. Obviously, there will be a nice program that
|
||||
sysadmins use to configure FakeNBD, but somehow that program has to tell
|
||||
the driver about it. Here's where configfs comes in.
|
||||
|
||||
When the FakeNBD driver is loaded, it registers itself with configfs.
|
||||
readdir(3) sees this just fine:
|
||||
|
||||
# ls /config
|
||||
fakenbd
|
||||
|
||||
A fakenbd connection can be created with mkdir(2). The name is
|
||||
arbitrary, but likely the tool will make some use of the name. Perhaps
|
||||
it is a uuid or a disk name:
|
||||
|
||||
# mkdir /config/fakenbd/disk1
|
||||
# ls /config/fakenbd/disk1
|
||||
target device rw
|
||||
|
||||
The target attribute contains the IP address of the server FakeNBD will
|
||||
connect to. The device attribute is the device on the server.
|
||||
Predictably, the rw attribute determines whether the connection is
|
||||
read-only or read-write.
|
||||
|
||||
# echo 10.0.0.1 > /config/fakenbd/disk1/target
|
||||
# echo /dev/sda1 > /config/fakenbd/disk1/device
|
||||
# echo 1 > /config/fakenbd/disk1/rw
|
||||
|
||||
That's it. That's all there is. Now the device is configured, via the
|
||||
shell no less.
|
||||
|
||||
[Coding With configfs]
|
||||
|
||||
Every object in configfs is a config_item. A config_item reflects an
|
||||
object in the subsystem. It has attributes that match values on that
|
||||
object. configfs handles the filesystem representation of that object
|
||||
and its attributes, allowing the subsystem to ignore all but the
|
||||
basic show/store interaction.
|
||||
|
||||
Items are created and destroyed inside a config_group. A group is a
|
||||
collection of items that share the same attributes and operations.
|
||||
Items are created by mkdir(2) and removed by rmdir(2), but configfs
|
||||
handles that. The group has a set of operations to perform these tasks
|
||||
|
||||
A subsystem is the top level of a client module. During initialization,
|
||||
the client module registers the subsystem with configfs, the subsystem
|
||||
appears as a directory at the top of the configfs filesystem. A
|
||||
subsystem is also a config_group, and can do everything a config_group
|
||||
can.
|
||||
|
||||
[struct config_item]
|
||||
|
||||
struct config_item {
|
||||
char *ci_name;
|
||||
char ci_namebuf[UOBJ_NAME_LEN];
|
||||
struct kref ci_kref;
|
||||
struct list_head ci_entry;
|
||||
struct config_item *ci_parent;
|
||||
struct config_group *ci_group;
|
||||
struct config_item_type *ci_type;
|
||||
struct dentry *ci_dentry;
|
||||
};
|
||||
|
||||
void config_item_init(struct config_item *);
|
||||
void config_item_init_type_name(struct config_item *,
|
||||
const char *name,
|
||||
struct config_item_type *type);
|
||||
struct config_item *config_item_get(struct config_item *);
|
||||
void config_item_put(struct config_item *);
|
||||
|
||||
Generally, struct config_item is embedded in a container structure, a
|
||||
structure that actually represents what the subsystem is doing. The
|
||||
config_item portion of that structure is how the object interacts with
|
||||
configfs.
|
||||
|
||||
Whether statically defined in a source file or created by a parent
|
||||
config_group, a config_item must have one of the _init() functions
|
||||
called on it. This initializes the reference count and sets up the
|
||||
appropriate fields.
|
||||
|
||||
All users of a config_item should have a reference on it via
|
||||
config_item_get(), and drop the reference when they are done via
|
||||
config_item_put().
|
||||
|
||||
By itself, a config_item cannot do much more than appear in configfs.
|
||||
Usually a subsystem wants the item to display and/or store attributes,
|
||||
among other things. For that, it needs a type.
|
||||
|
||||
[struct config_item_type]
|
||||
|
||||
struct configfs_item_operations {
|
||||
void (*release)(struct config_item *);
|
||||
ssize_t (*show_attribute)(struct config_item *,
|
||||
struct configfs_attribute *,
|
||||
char *);
|
||||
ssize_t (*store_attribute)(struct config_item *,
|
||||
struct configfs_attribute *,
|
||||
const char *, size_t);
|
||||
int (*allow_link)(struct config_item *src,
|
||||
struct config_item *target);
|
||||
int (*drop_link)(struct config_item *src,
|
||||
struct config_item *target);
|
||||
};
|
||||
|
||||
struct config_item_type {
|
||||
struct module *ct_owner;
|
||||
struct configfs_item_operations *ct_item_ops;
|
||||
struct configfs_group_operations *ct_group_ops;
|
||||
struct configfs_attribute **ct_attrs;
|
||||
};
|
||||
|
||||
The most basic function of a config_item_type is to define what
|
||||
operations can be performed on a config_item. All items that have been
|
||||
allocated dynamically will need to provide the ct_item_ops->release()
|
||||
method. This method is called when the config_item's reference count
|
||||
reaches zero. Items that wish to display an attribute need to provide
|
||||
the ct_item_ops->show_attribute() method. Similarly, storing a new
|
||||
attribute value uses the store_attribute() method.
|
||||
|
||||
[struct configfs_attribute]
|
||||
|
||||
struct configfs_attribute {
|
||||
char *ca_name;
|
||||
struct module *ca_owner;
|
||||
mode_t ca_mode;
|
||||
};
|
||||
|
||||
When a config_item wants an attribute to appear as a file in the item's
|
||||
configfs directory, it must define a configfs_attribute describing it.
|
||||
It then adds the attribute to the NULL-terminated array
|
||||
config_item_type->ct_attrs. When the item appears in configfs, the
|
||||
attribute file will appear with the configfs_attribute->ca_name
|
||||
filename. configfs_attribute->ca_mode specifies the file permissions.
|
||||
|
||||
If an attribute is readable and the config_item provides a
|
||||
ct_item_ops->show_attribute() method, that method will be called
|
||||
whenever userspace asks for a read(2) on the attribute. The converse
|
||||
will happen for write(2).
|
||||
|
||||
[struct config_group]
|
||||
|
||||
A config_item cannot live in a vaccum. The only way one can be created
|
||||
is via mkdir(2) on a config_group. This will trigger creation of a
|
||||
child item.
|
||||
|
||||
struct config_group {
|
||||
struct config_item cg_item;
|
||||
struct list_head cg_children;
|
||||
struct configfs_subsystem *cg_subsys;
|
||||
struct config_group **default_groups;
|
||||
};
|
||||
|
||||
void config_group_init(struct config_group *group);
|
||||
void config_group_init_type_name(struct config_group *group,
|
||||
const char *name,
|
||||
struct config_item_type *type);
|
||||
|
||||
|
||||
The config_group structure contains a config_item. Properly configuring
|
||||
that item means that a group can behave as an item in its own right.
|
||||
However, it can do more: it can create child items or groups. This is
|
||||
accomplished via the group operations specified on the group's
|
||||
config_item_type.
|
||||
|
||||
struct configfs_group_operations {
|
||||
struct config_item *(*make_item)(struct config_group *group,
|
||||
const char *name);
|
||||
struct config_group *(*make_group)(struct config_group *group,
|
||||
const char *name);
|
||||
int (*commit_item)(struct config_item *item);
|
||||
void (*drop_item)(struct config_group *group,
|
||||
struct config_item *item);
|
||||
};
|
||||
|
||||
A group creates child items by providing the
|
||||
ct_group_ops->make_item() method. If provided, this method is called from mkdir(2) in the group's directory. The subsystem allocates a new
|
||||
config_item (or more likely, its container structure), initializes it,
|
||||
and returns it to configfs. Configfs will then populate the filesystem
|
||||
tree to reflect the new item.
|
||||
|
||||
If the subsystem wants the child to be a group itself, the subsystem
|
||||
provides ct_group_ops->make_group(). Everything else behaves the same,
|
||||
using the group _init() functions on the group.
|
||||
|
||||
Finally, when userspace calls rmdir(2) on the item or group,
|
||||
ct_group_ops->drop_item() is called. As a config_group is also a
|
||||
config_item, it is not necessary for a seperate drop_group() method.
|
||||
The subsystem must config_item_put() the reference that was initialized
|
||||
upon item allocation. If a subsystem has no work to do, it may omit
|
||||
the ct_group_ops->drop_item() method, and configfs will call
|
||||
config_item_put() on the item on behalf of the subsystem.
|
||||
|
||||
IMPORTANT: drop_item() is void, and as such cannot fail. When rmdir(2)
|
||||
is called, configfs WILL remove the item from the filesystem tree
|
||||
(assuming that it has no children to keep it busy). The subsystem is
|
||||
responsible for responding to this. If the subsystem has references to
|
||||
the item in other threads, the memory is safe. It may take some time
|
||||
for the item to actually disappear from the subsystem's usage. But it
|
||||
is gone from configfs.
|
||||
|
||||
A config_group cannot be removed while it still has child items. This
|
||||
is implemented in the configfs rmdir(2) code. ->drop_item() will not be
|
||||
called, as the item has not been dropped. rmdir(2) will fail, as the
|
||||
directory is not empty.
|
||||
|
||||
[struct configfs_subsystem]
|
||||
|
||||
A subsystem must register itself, ususally at module_init time. This
|
||||
tells configfs to make the subsystem appear in the file tree.
|
||||
|
||||
struct configfs_subsystem {
|
||||
struct config_group su_group;
|
||||
struct semaphore su_sem;
|
||||
};
|
||||
|
||||
int configfs_register_subsystem(struct configfs_subsystem *subsys);
|
||||
void configfs_unregister_subsystem(struct configfs_subsystem *subsys);
|
||||
|
||||
A subsystem consists of a toplevel config_group and a semaphore.
|
||||
The group is where child config_items are created. For a subsystem,
|
||||
this group is usually defined statically. Before calling
|
||||
configfs_register_subsystem(), the subsystem must have initialized the
|
||||
group via the usual group _init() functions, and it must also have
|
||||
initialized the semaphore.
|
||||
When the register call returns, the subsystem is live, and it
|
||||
will be visible via configfs. At that point, mkdir(2) can be called and
|
||||
the subsystem must be ready for it.
|
||||
|
||||
[An Example]
|
||||
|
||||
The best example of these basic concepts is the simple_children
|
||||
subsystem/group and the simple_child item in configfs_example.c It
|
||||
shows a trivial object displaying and storing an attribute, and a simple
|
||||
group creating and destroying these children.
|
||||
|
||||
[Hierarchy Navigation and the Subsystem Semaphore]
|
||||
|
||||
There is an extra bonus that configfs provides. The config_groups and
|
||||
config_items are arranged in a hierarchy due to the fact that they
|
||||
appear in a filesystem. A subsystem is NEVER to touch the filesystem
|
||||
parts, but the subsystem might be interested in this hierarchy. For
|
||||
this reason, the hierarchy is mirrored via the config_group->cg_children
|
||||
and config_item->ci_parent structure members.
|
||||
|
||||
A subsystem can navigate the cg_children list and the ci_parent pointer
|
||||
to see the tree created by the subsystem. This can race with configfs'
|
||||
management of the hierarchy, so configfs uses the subsystem semaphore to
|
||||
protect modifications. Whenever a subsystem wants to navigate the
|
||||
hierarchy, it must do so under the protection of the subsystem
|
||||
semaphore.
|
||||
|
||||
A subsystem will be prevented from acquiring the semaphore while a newly
|
||||
allocated item has not been linked into this hierarchy. Similarly, it
|
||||
will not be able to acquire the semaphore while a dropping item has not
|
||||
yet been unlinked. This means that an item's ci_parent pointer will
|
||||
never be NULL while the item is in configfs, and that an item will only
|
||||
be in its parent's cg_children list for the same duration. This allows
|
||||
a subsystem to trust ci_parent and cg_children while they hold the
|
||||
semaphore.
|
||||
|
||||
[Item Aggregation Via symlink(2)]
|
||||
|
||||
configfs provides a simple group via the group->item parent/child
|
||||
relationship. Often, however, a larger environment requires aggregation
|
||||
outside of the parent/child connection. This is implemented via
|
||||
symlink(2).
|
||||
|
||||
A config_item may provide the ct_item_ops->allow_link() and
|
||||
ct_item_ops->drop_link() methods. If the ->allow_link() method exists,
|
||||
symlink(2) may be called with the config_item as the source of the link.
|
||||
These links are only allowed between configfs config_items. Any
|
||||
symlink(2) attempt outside the configfs filesystem will be denied.
|
||||
|
||||
When symlink(2) is called, the source config_item's ->allow_link()
|
||||
method is called with itself and a target item. If the source item
|
||||
allows linking to target item, it returns 0. A source item may wish to
|
||||
reject a link if it only wants links to a certain type of object (say,
|
||||
in its own subsystem).
|
||||
|
||||
When unlink(2) is called on the symbolic link, the source item is
|
||||
notified via the ->drop_link() method. Like the ->drop_item() method,
|
||||
this is a void function and cannot return failure. The subsystem is
|
||||
responsible for responding to the change.
|
||||
|
||||
A config_item cannot be removed while it links to any other item, nor
|
||||
can it be removed while an item links to it. Dangling symlinks are not
|
||||
allowed in configfs.
|
||||
|
||||
[Automatically Created Subgroups]
|
||||
|
||||
A new config_group may want to have two types of child config_items.
|
||||
While this could be codified by magic names in ->make_item(), it is much
|
||||
more explicit to have a method whereby userspace sees this divergence.
|
||||
|
||||
Rather than have a group where some items behave differently than
|
||||
others, configfs provides a method whereby one or many subgroups are
|
||||
automatically created inside the parent at its creation. Thus,
|
||||
mkdir("parent) results in "parent", "parent/subgroup1", up through
|
||||
"parent/subgroupN". Items of type 1 can now be created in
|
||||
"parent/subgroup1", and items of type N can be created in
|
||||
"parent/subgroupN".
|
||||
|
||||
These automatic subgroups, or default groups, do not preclude other
|
||||
children of the parent group. If ct_group_ops->make_group() exists,
|
||||
other child groups can be created on the parent group directly.
|
||||
|
||||
A configfs subsystem specifies default groups by filling in the
|
||||
NULL-terminated array default_groups on the config_group structure.
|
||||
Each group in that array is populated in the configfs tree at the same
|
||||
time as the parent group. Similarly, they are removed at the same time
|
||||
as the parent. No extra notification is provided. When a ->drop_item()
|
||||
method call notifies the subsystem the parent group is going away, it
|
||||
also means every default group child associated with that parent group.
|
||||
|
||||
As a consequence of this, default_groups cannot be removed directly via
|
||||
rmdir(2). They also are not considered when rmdir(2) on the parent
|
||||
group is checking for children.
|
||||
|
||||
[Committable Items]
|
||||
|
||||
NOTE: Committable items are currently unimplemented.
|
||||
|
||||
Some config_items cannot have a valid initial state. That is, no
|
||||
default values can be specified for the item's attributes such that the
|
||||
item can do its work. Userspace must configure one or more attributes,
|
||||
after which the subsystem can start whatever entity this item
|
||||
represents.
|
||||
|
||||
Consider the FakeNBD device from above. Without a target address *and*
|
||||
a target device, the subsystem has no idea what block device to import.
|
||||
The simple example assumes that the subsystem merely waits until all the
|
||||
appropriate attributes are configured, and then connects. This will,
|
||||
indeed, work, but now every attribute store must check if the attributes
|
||||
are initialized. Every attribute store must fire off the connection if
|
||||
that condition is met.
|
||||
|
||||
Far better would be an explicit action notifying the subsystem that the
|
||||
config_item is ready to go. More importantly, an explicit action allows
|
||||
the subsystem to provide feedback as to whether the attibutes are
|
||||
initialized in a way that makes sense. configfs provides this as
|
||||
committable items.
|
||||
|
||||
configfs still uses only normal filesystem operations. An item is
|
||||
committed via rename(2). The item is moved from a directory where it
|
||||
can be modified to a directory where it cannot.
|
||||
|
||||
Any group that provides the ct_group_ops->commit_item() method has
|
||||
committable items. When this group appears in configfs, mkdir(2) will
|
||||
not work directly in the group. Instead, the group will have two
|
||||
subdirectories: "live" and "pending". The "live" directory does not
|
||||
support mkdir(2) or rmdir(2) either. It only allows rename(2). The
|
||||
"pending" directory does allow mkdir(2) and rmdir(2). An item is
|
||||
created in the "pending" directory. Its attributes can be modified at
|
||||
will. Userspace commits the item by renaming it into the "live"
|
||||
directory. At this point, the subsystem recieves the ->commit_item()
|
||||
callback. If all required attributes are filled to satisfaction, the
|
||||
method returns zero and the item is moved to the "live" directory.
|
||||
|
||||
As rmdir(2) does not work in the "live" directory, an item must be
|
||||
shutdown, or "uncommitted". Again, this is done via rename(2), this
|
||||
time from the "live" directory back to the "pending" one. The subsystem
|
||||
is notified by the ct_group_ops->uncommit_object() method.
|
||||
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
/*
|
||||
* vim: noexpandtab ts=8 sts=0 sw=8:
|
||||
*
|
||||
* configfs_example.c - This file is a demonstration module containing
|
||||
* a number of configfs subsystems.
|
||||
*
|
||||
* 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 021110-1307, USA.
|
||||
*
|
||||
* Based on sysfs:
|
||||
* sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
|
||||
*
|
||||
* configfs Copyright (C) 2005 Oracle. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/configfs.h>
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* 01-childless
|
||||
*
|
||||
* This first example is a childless subsystem. It cannot create
|
||||
* any config_items. It just has attributes.
|
||||
*
|
||||
* Note that we are enclosing the configfs_subsystem inside a container.
|
||||
* This is not necessary if a subsystem has no attributes directly
|
||||
* on the subsystem. See the next example, 02-simple-children, for
|
||||
* such a subsystem.
|
||||
*/
|
||||
|
||||
struct childless {
|
||||
struct configfs_subsystem subsys;
|
||||
int showme;
|
||||
int storeme;
|
||||
};
|
||||
|
||||
struct childless_attribute {
|
||||
struct configfs_attribute attr;
|
||||
ssize_t (*show)(struct childless *, char *);
|
||||
ssize_t (*store)(struct childless *, const char *, size_t);
|
||||
};
|
||||
|
||||
static inline struct childless *to_childless(struct config_item *item)
|
||||
{
|
||||
return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct childless, subsys) : NULL;
|
||||
}
|
||||
|
||||
static ssize_t childless_showme_read(struct childless *childless,
|
||||
char *page)
|
||||
{
|
||||
ssize_t pos;
|
||||
|
||||
pos = sprintf(page, "%d\n", childless->showme);
|
||||
childless->showme++;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t childless_storeme_read(struct childless *childless,
|
||||
char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n", childless->storeme);
|
||||
}
|
||||
|
||||
static ssize_t childless_storeme_write(struct childless *childless,
|
||||
const char *page,
|
||||
size_t count)
|
||||
{
|
||||
unsigned long tmp;
|
||||
char *p = (char *) page;
|
||||
|
||||
tmp = simple_strtoul(p, &p, 10);
|
||||
if (!p || (*p && (*p != '\n')))
|
||||
return -EINVAL;
|
||||
|
||||
if (tmp > INT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
childless->storeme = tmp;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t childless_description_read(struct childless *childless,
|
||||
char *page)
|
||||
{
|
||||
return sprintf(page,
|
||||
"[01-childless]\n"
|
||||
"\n"
|
||||
"The childless subsystem is the simplest possible subsystem in\n"
|
||||
"configfs. It does not support the creation of child config_items.\n"
|
||||
"It only has a few attributes. In fact, it isn't much different\n"
|
||||
"than a directory in /proc.\n");
|
||||
}
|
||||
|
||||
static struct childless_attribute childless_attr_showme = {
|
||||
.attr = { .ca_owner = THIS_MODULE, .ca_name = "showme", .ca_mode = S_IRUGO },
|
||||
.show = childless_showme_read,
|
||||
};
|
||||
static struct childless_attribute childless_attr_storeme = {
|
||||
.attr = { .ca_owner = THIS_MODULE, .ca_name = "storeme", .ca_mode = S_IRUGO | S_IWUSR },
|
||||
.show = childless_storeme_read,
|
||||
.store = childless_storeme_write,
|
||||
};
|
||||
static struct childless_attribute childless_attr_description = {
|
||||
.attr = { .ca_owner = THIS_MODULE, .ca_name = "description", .ca_mode = S_IRUGO },
|
||||
.show = childless_description_read,
|
||||
};
|
||||
|
||||
static struct configfs_attribute *childless_attrs[] = {
|
||||
&childless_attr_showme.attr,
|
||||
&childless_attr_storeme.attr,
|
||||
&childless_attr_description.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t childless_attr_show(struct config_item *item,
|
||||
struct configfs_attribute *attr,
|
||||
char *page)
|
||||
{
|
||||
struct childless *childless = to_childless(item);
|
||||
struct childless_attribute *childless_attr =
|
||||
container_of(attr, struct childless_attribute, attr);
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (childless_attr->show)
|
||||
ret = childless_attr->show(childless, page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t childless_attr_store(struct config_item *item,
|
||||
struct configfs_attribute *attr,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct childless *childless = to_childless(item);
|
||||
struct childless_attribute *childless_attr =
|
||||
container_of(attr, struct childless_attribute, attr);
|
||||
ssize_t ret = -EINVAL;
|
||||
|
||||
if (childless_attr->store)
|
||||
ret = childless_attr->store(childless, page, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct configfs_item_operations childless_item_ops = {
|
||||
.show_attribute = childless_attr_show,
|
||||
.store_attribute = childless_attr_store,
|
||||
};
|
||||
|
||||
static struct config_item_type childless_type = {
|
||||
.ct_item_ops = &childless_item_ops,
|
||||
.ct_attrs = childless_attrs,
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct childless childless_subsys = {
|
||||
.subsys = {
|
||||
.su_group = {
|
||||
.cg_item = {
|
||||
.ci_namebuf = "01-childless",
|
||||
.ci_type = &childless_type,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* 02-simple-children
|
||||
*
|
||||
* This example merely has a simple one-attribute child. Note that
|
||||
* there is no extra attribute structure, as the child's attribute is
|
||||
* known from the get-go. Also, there is no container for the
|
||||
* subsystem, as it has no attributes of its own.
|
||||
*/
|
||||
|
||||
struct simple_child {
|
||||
struct config_item item;
|
||||
int storeme;
|
||||
};
|
||||
|
||||
static inline struct simple_child *to_simple_child(struct config_item *item)
|
||||
{
|
||||
return item ? container_of(item, struct simple_child, item) : NULL;
|
||||
}
|
||||
|
||||
static struct configfs_attribute simple_child_attr_storeme = {
|
||||
.ca_owner = THIS_MODULE,
|
||||
.ca_name = "storeme",
|
||||
.ca_mode = S_IRUGO | S_IWUSR,
|
||||
};
|
||||
|
||||
static struct configfs_attribute *simple_child_attrs[] = {
|
||||
&simple_child_attr_storeme,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t simple_child_attr_show(struct config_item *item,
|
||||
struct configfs_attribute *attr,
|
||||
char *page)
|
||||
{
|
||||
ssize_t count;
|
||||
struct simple_child *simple_child = to_simple_child(item);
|
||||
|
||||
count = sprintf(page, "%d\n", simple_child->storeme);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t simple_child_attr_store(struct config_item *item,
|
||||
struct configfs_attribute *attr,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct simple_child *simple_child = to_simple_child(item);
|
||||
unsigned long tmp;
|
||||
char *p = (char *) page;
|
||||
|
||||
tmp = simple_strtoul(p, &p, 10);
|
||||
if (!p || (*p && (*p != '\n')))
|
||||
return -EINVAL;
|
||||
|
||||
if (tmp > INT_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
simple_child->storeme = tmp;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void simple_child_release(struct config_item *item)
|
||||
{
|
||||
kfree(to_simple_child(item));
|
||||
}
|
||||
|
||||
static struct configfs_item_operations simple_child_item_ops = {
|
||||
.release = simple_child_release,
|
||||
.show_attribute = simple_child_attr_show,
|
||||
.store_attribute = simple_child_attr_store,
|
||||
};
|
||||
|
||||
static struct config_item_type simple_child_type = {
|
||||
.ct_item_ops = &simple_child_item_ops,
|
||||
.ct_attrs = simple_child_attrs,
|
||||
.ct_owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
|
||||
static struct config_item *simple_children_make_item(struct config_group *group, const char *name)
|
||||
{
|
||||
struct simple_child *simple_child;
|
||||
|
||||
simple_child = kmalloc(sizeof(struct simple_child), GFP_KERNEL);
|
||||
if (!simple_child)
|
||||
return NULL;
|
||||
|
||||
memset(simple_child, 0, sizeof(struct simple_child));
|
||||
|
||||
config_item_init_type_name(&simple_child->item, name,
|
||||
&simple_child_type);
|
||||
|
||||
simple_child->storeme = 0;
|
||||
|
||||
return &simple_child->item;
|
||||
}
|
||||
|
||||
static struct configfs_attribute simple_children_attr_description = {
|
||||
.ca_owner = THIS_MODULE,
|
||||
.ca_name = "description",
|
||||
.ca_mode = S_IRUGO,
|
||||
};
|
||||
|
||||
static struct configfs_attribute *simple_children_attrs[] = {
|
||||
&simple_children_attr_description,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t simple_children_attr_show(struct config_item *item,
|
||||
struct configfs_attribute *attr,
|
||||
char *page)
|
||||
{
|
||||
return sprintf(page,
|
||||
"[02-simple-children]\n"
|
||||
"\n"
|
||||
"This subsystem allows the creation of child config_items. These\n"
|
||||
"items have only one attribute that is readable and writeable.\n");
|
||||
}
|
||||
|
||||
static struct configfs_item_operations simple_children_item_ops = {
|
||||
.show_attribute = simple_children_attr_show,
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that, since no extra work is required on ->drop_item(),
|
||||
* no ->drop_item() is provided.
|
||||
*/
|
||||
static struct configfs_group_operations simple_children_group_ops = {
|
||||
.make_item = simple_children_make_item,
|
||||
};
|
||||
|
||||
static struct config_item_type simple_children_type = {
|
||||
.ct_item_ops = &simple_children_item_ops,
|
||||
.ct_group_ops = &simple_children_group_ops,
|
||||
.ct_attrs = simple_children_attrs,
|
||||
};
|
||||
|
||||
static struct configfs_subsystem simple_children_subsys = {
|
||||
.su_group = {
|
||||
.cg_item = {
|
||||
.ci_namebuf = "02-simple-children",
|
||||
.ci_type = &simple_children_type,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* 03-group-children
|
||||
*
|
||||
* This example reuses the simple_children group from above. However,
|
||||
* the simple_children group is not the subsystem itself, it is a
|
||||
* child of the subsystem. Creation of a group in the subsystem creates
|
||||
* a new simple_children group. That group can then have simple_child
|
||||
* children of its own.
|
||||
*/
|
||||
|
||||
struct simple_children {
|
||||
struct config_group group;
|
||||
};
|
||||
|
||||
static struct config_group *group_children_make_group(struct config_group *group, const char *name)
|
||||
{
|
||||
struct simple_children *simple_children;
|
||||
|
||||
simple_children = kmalloc(sizeof(struct simple_children),
|
||||
GFP_KERNEL);
|
||||
if (!simple_children)
|
||||
return NULL;
|
||||
|
||||
memset(simple_children, 0, sizeof(struct simple_children));
|
||||
|
||||
config_group_init_type_name(&simple_children->group, name,
|
||||
&simple_children_type);
|
||||
|
||||
return &simple_children->group;
|
||||
}
|
||||
|
||||
static struct configfs_attribute group_children_attr_description = {
|
||||
.ca_owner = THIS_MODULE,
|
||||
.ca_name = "description",
|
||||
.ca_mode = S_IRUGO,
|
||||
};
|
||||
|
||||
static struct configfs_attribute *group_children_attrs[] = {
|
||||
&group_children_attr_description,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t group_children_attr_show(struct config_item *item,
|
||||
struct configfs_attribute *attr,
|
||||
char *page)
|
||||
{
|
||||
return sprintf(page,
|
||||
"[03-group-children]\n"
|
||||
"\n"
|
||||
"This subsystem allows the creation of child config_groups. These\n"
|
||||
"groups are like the subsystem simple-children.\n");
|
||||
}
|
||||
|
||||
static struct configfs_item_operations group_children_item_ops = {
|
||||
.show_attribute = group_children_attr_show,
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that, since no extra work is required on ->drop_item(),
|
||||
* no ->drop_item() is provided.
|
||||
*/
|
||||
static struct configfs_group_operations group_children_group_ops = {
|
||||
.make_group = group_children_make_group,
|
||||
};
|
||||
|
||||
static struct config_item_type group_children_type = {
|
||||
.ct_item_ops = &group_children_item_ops,
|
||||
.ct_group_ops = &group_children_group_ops,
|
||||
.ct_attrs = group_children_attrs,
|
||||
};
|
||||
|
||||
static struct configfs_subsystem group_children_subsys = {
|
||||
.su_group = {
|
||||
.cg_item = {
|
||||
.ci_namebuf = "03-group-children",
|
||||
.ci_type = &group_children_type,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* We're now done with our subsystem definitions.
|
||||
* For convenience in this module, here's a list of them all. It
|
||||
* allows the init function to easily register them. Most modules
|
||||
* will only have one subsystem, and will only call register_subsystem
|
||||
* on it directly.
|
||||
*/
|
||||
static struct configfs_subsystem *example_subsys[] = {
|
||||
&childless_subsys.subsys,
|
||||
&simple_children_subsys,
|
||||
&group_children_subsys,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int __init configfs_example_init(void)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
struct configfs_subsystem *subsys;
|
||||
|
||||
for (i = 0; example_subsys[i]; i++) {
|
||||
subsys = example_subsys[i];
|
||||
|
||||
config_group_init(&subsys->su_group);
|
||||
init_MUTEX(&subsys->su_sem);
|
||||
ret = configfs_register_subsystem(subsys);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "Error %d while registering subsystem %s\n",
|
||||
ret,
|
||||
subsys->su_group.cg_item.ci_namebuf);
|
||||
goto out_unregister;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
for (; i >= 0; i--) {
|
||||
configfs_unregister_subsystem(example_subsys[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit configfs_example_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; example_subsys[i]; i++) {
|
||||
configfs_unregister_subsystem(example_subsys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
module_init(configfs_example_init);
|
||||
module_exit(configfs_example_exit);
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,130 @@
|
|||
dlmfs
|
||||
==================
|
||||
A minimal DLM userspace interface implemented via a virtual file
|
||||
system.
|
||||
|
||||
dlmfs is built with OCFS2 as it requires most of its infrastructure.
|
||||
|
||||
Project web page: http://oss.oracle.com/projects/ocfs2
|
||||
Tools web page: http://oss.oracle.com/projects/ocfs2-tools
|
||||
OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
|
||||
|
||||
All code copyright 2005 Oracle except when otherwise noted.
|
||||
|
||||
CREDITS
|
||||
=======
|
||||
|
||||
Some code taken from ramfs which is Copyright (C) 2000 Linus Torvalds
|
||||
and Transmeta Corp.
|
||||
|
||||
Mark Fasheh <mark.fasheh@oracle.com>
|
||||
|
||||
Caveats
|
||||
=======
|
||||
- Right now it only works with the OCFS2 DLM, though support for other
|
||||
DLM implementations should not be a major issue.
|
||||
|
||||
Mount options
|
||||
=============
|
||||
None
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
If you're just interested in OCFS2, then please see ocfs2.txt. The
|
||||
rest of this document will be geared towards those who want to use
|
||||
dlmfs for easy to setup and easy to use clustered locking in
|
||||
userspace.
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
dlmfs requires that the OCFS2 cluster infrastructure be in
|
||||
place. Please download ocfs2-tools from the above url and configure a
|
||||
cluster.
|
||||
|
||||
You'll want to start heartbeating on a volume which all the nodes in
|
||||
your lockspace can access. The easiest way to do this is via
|
||||
ocfs2_hb_ctl (distributed with ocfs2-tools). Right now it requires
|
||||
that an OCFS2 file system be in place so that it can automatically
|
||||
find it's heartbeat area, though it will eventually support heartbeat
|
||||
against raw disks.
|
||||
|
||||
Please see the ocfs2_hb_ctl and mkfs.ocfs2 manual pages distributed
|
||||
with ocfs2-tools.
|
||||
|
||||
Once you're heartbeating, DLM lock 'domains' can be easily created /
|
||||
destroyed and locks within them accessed.
|
||||
|
||||
Locking
|
||||
=======
|
||||
|
||||
Users may access dlmfs via standard file system calls, or they can use
|
||||
'libo2dlm' (distributed with ocfs2-tools) which abstracts the file
|
||||
system calls and presents a more traditional locking api.
|
||||
|
||||
dlmfs handles lock caching automatically for the user, so a lock
|
||||
request for an already acquired lock will not generate another DLM
|
||||
call. Userspace programs are assumed to handle their own local
|
||||
locking.
|
||||
|
||||
Two levels of locks are supported - Shared Read, and Exlcusive.
|
||||
Also supported is a Trylock operation.
|
||||
|
||||
For information on the libo2dlm interface, please see o2dlm.h,
|
||||
distributed with ocfs2-tools.
|
||||
|
||||
Lock value blocks can be read and written to a resource via read(2)
|
||||
and write(2) against the fd obtained via your open(2) call. The
|
||||
maximum currently supported LVB length is 64 bytes (though that is an
|
||||
OCFS2 DLM limitation). Through this mechanism, users of dlmfs can share
|
||||
small amounts of data amongst their nodes.
|
||||
|
||||
mkdir(2) signals dlmfs to join a domain (which will have the same name
|
||||
as the resulting directory)
|
||||
|
||||
rmdir(2) signals dlmfs to leave the domain
|
||||
|
||||
Locks for a given domain are represented by regular inodes inside the
|
||||
domain directory. Locking against them is done via the open(2) system
|
||||
call.
|
||||
|
||||
The open(2) call will not return until your lock has been granted or
|
||||
an error has occurred, unless it has been instructed to do a trylock
|
||||
operation. If the lock succeeds, you'll get an fd.
|
||||
|
||||
open(2) with O_CREAT to ensure the resource inode is created - dlmfs does
|
||||
not automatically create inodes for existing lock resources.
|
||||
|
||||
Open Flag Lock Request Type
|
||||
--------- -----------------
|
||||
O_RDONLY Shared Read
|
||||
O_RDWR Exclusive
|
||||
|
||||
Open Flag Resulting Locking Behavior
|
||||
--------- --------------------------
|
||||
O_NONBLOCK Trylock operation
|
||||
|
||||
You must provide exactly one of O_RDONLY or O_RDWR.
|
||||
|
||||
If O_NONBLOCK is also provided and the trylock operation was valid but
|
||||
could not lock the resource then open(2) will return ETXTBUSY.
|
||||
|
||||
close(2) drops the lock associated with your fd.
|
||||
|
||||
Modes passed to mkdir(2) or open(2) are adhered to locally. Chown is
|
||||
supported locally as well. This means you can use them to restrict
|
||||
access to the resources via dlmfs on your local node only.
|
||||
|
||||
The resource LVB may be read from the fd in either Shared Read or
|
||||
Exclusive modes via the read(2) system call. It can be written via
|
||||
write(2) only when open in Exclusive mode.
|
||||
|
||||
Once written, an LVB will be visible to other nodes who obtain Read
|
||||
Only or higher level locks on the resource.
|
||||
|
||||
See Also
|
||||
========
|
||||
http://opendlm.sourceforge.net/cvsmirror/opendlm/docs/dlmbook_final.pdf
|
||||
|
||||
For more information on the VMS distributed locking API.
|
|
@ -0,0 +1,55 @@
|
|||
OCFS2 filesystem
|
||||
==================
|
||||
OCFS2 is a general purpose extent based shared disk cluster file
|
||||
system with many similarities to ext3. It supports 64 bit inode
|
||||
numbers, and has automatically extending metadata groups which may
|
||||
also make it attractive for non-clustered use.
|
||||
|
||||
You'll want to install the ocfs2-tools package in order to at least
|
||||
get "mount.ocfs2" and "ocfs2_hb_ctl".
|
||||
|
||||
Project web page: http://oss.oracle.com/projects/ocfs2
|
||||
Tools web page: http://oss.oracle.com/projects/ocfs2-tools
|
||||
OCFS2 mailing lists: http://oss.oracle.com/projects/ocfs2/mailman/
|
||||
|
||||
All code copyright 2005 Oracle except when otherwise noted.
|
||||
|
||||
CREDITS:
|
||||
Lots of code taken from ext3 and other projects.
|
||||
|
||||
Authors in alphabetical order:
|
||||
Joel Becker <joel.becker@oracle.com>
|
||||
Zach Brown <zach.brown@oracle.com>
|
||||
Mark Fasheh <mark.fasheh@oracle.com>
|
||||
Kurt Hackel <kurt.hackel@oracle.com>
|
||||
Sunil Mushran <sunil.mushran@oracle.com>
|
||||
Manish Singh <manish.singh@oracle.com>
|
||||
|
||||
Caveats
|
||||
=======
|
||||
Features which OCFS2 does not support yet:
|
||||
- sparse files
|
||||
- extended attributes
|
||||
- shared writeable mmap
|
||||
- loopback is supported, but data written will not
|
||||
be cluster coherent.
|
||||
- quotas
|
||||
- cluster aware flock
|
||||
- Directory change notification (F_NOTIFY)
|
||||
- Distributed Caching (F_SETLEASE/F_GETLEASE/break_lease)
|
||||
- POSIX ACLs
|
||||
- readpages / writepages (not user visible)
|
||||
|
||||
Mount options
|
||||
=============
|
||||
|
||||
OCFS2 supports the following mount options:
|
||||
(*) == default
|
||||
|
||||
barrier=1 This enables/disables barriers. barrier=0 disables it,
|
||||
barrier=1 enables it.
|
||||
errors=remount-ro(*) Remount the filesystem read-only on an error.
|
||||
errors=panic Panic and halt the machine if an error occurs.
|
||||
intr (*) Allow signals to interrupt cluster operations.
|
||||
nointr Do not allow signals to interrupt cluster
|
||||
operations.
|
|
@ -162,9 +162,8 @@ get_sb() method fills in is the "s_op" field. This is a pointer to
|
|||
a "struct super_operations" which describes the next level of the
|
||||
filesystem implementation.
|
||||
|
||||
Usually, a filesystem uses generic one of the generic get_sb()
|
||||
implementations and provides a fill_super() method instead. The
|
||||
generic methods are:
|
||||
Usually, a filesystem uses one of the generic get_sb() implementations
|
||||
and provides a fill_super() method instead. The generic methods are:
|
||||
|
||||
get_sb_bdev: mount a filesystem residing on a block device
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ included in the kernel tree.
|
|||
What is covered within this file is mainly information to authors
|
||||
of modules. The author of an external modules should supply
|
||||
a makefile that hides most of the complexity so one only has to type
|
||||
'make' to buld the module. A complete example will be present in
|
||||
'make' to build the module. A complete example will be present in
|
||||
chapter ¤. Creating a kbuild file for an external module".
|
||||
|
||||
|
||||
|
@ -69,7 +69,7 @@ when building an external module.
|
|||
|
||||
--- 2.2 Available targets
|
||||
|
||||
$KDIR refers to path to kernel source top-level directory
|
||||
$KDIR refers to the path to the kernel source top-level directory
|
||||
|
||||
make -C $KDIR M=`pwd`
|
||||
Will build the module(s) located in current directory.
|
||||
|
@ -87,11 +87,11 @@ when building an external module.
|
|||
make -C $KDIR M=$PWD modules_install
|
||||
Install the external module(s).
|
||||
Installation default is in /lib/modules/<kernel-version>/extra,
|
||||
but may be prefixed with INSTALL_MOD_PATH - see separate chater.
|
||||
but may be prefixed with INSTALL_MOD_PATH - see separate chapter.
|
||||
|
||||
make -C $KDIR M=$PWD clean
|
||||
Remove all generated files for the module - the kernel
|
||||
source directory is not moddified.
|
||||
source directory is not modified.
|
||||
|
||||
make -C $KDIR M=`pwd` help
|
||||
help will list the available target when building external
|
||||
|
@ -99,7 +99,7 @@ when building an external module.
|
|||
|
||||
--- 2.3 Available options:
|
||||
|
||||
$KDIR refer to path to kernel src
|
||||
$KDIR refers to the path to the kernel source top-level directory
|
||||
|
||||
make -C $KDIR
|
||||
Used to specify where to find the kernel source.
|
||||
|
@ -206,11 +206,11 @@ following files:
|
|||
|
||||
KERNELDIR := /lib/modules/`uname -r`/build
|
||||
all::
|
||||
$(MAKE) -C $KERNELDIR M=`pwd` $@
|
||||
$(MAKE) -C $(KERNELDIR) M=`pwd` $@
|
||||
|
||||
# Module specific targets
|
||||
genbin:
|
||||
echo "X" > 8123_bini.o_shipped
|
||||
echo "X" > 8123_bin.o_shipped
|
||||
|
||||
endif
|
||||
|
||||
|
@ -341,13 +341,13 @@ directory and therefore needs to deal with this in their kbuild file.
|
|||
EXTRA_CFLAGS := -Iinclude
|
||||
8123-y := 8123_if.o 8123_pci.o 8123_bin.o
|
||||
|
||||
Note that in the assingment there is no space between -I and the path.
|
||||
This is a kbuild limitation and no space must be present.
|
||||
Note that in the assignment there is no space between -I and the path.
|
||||
This is a kbuild limitation: there must be no space present.
|
||||
|
||||
|
||||
=== 6. Module installation
|
||||
|
||||
Modules which are included in the kernel is installed in the directory:
|
||||
Modules which are included in the kernel are installed in the directory:
|
||||
|
||||
/lib/modules/$(KERNELRELEASE)/kernel
|
||||
|
||||
|
@ -384,7 +384,7 @@ External modules are installed in the directory:
|
|||
|
||||
=== 7. Module versioning
|
||||
|
||||
Module versioning are enabled by the CONFIG_MODVERSIONS tag.
|
||||
Module versioning is enabled by the CONFIG_MODVERSIONS tag.
|
||||
|
||||
Module versioning is used as a simple ABI consistency check. The Module
|
||||
versioning creates a CRC value of the full prototype for an exported symbol and
|
||||
|
|
|
@ -633,6 +633,14 @@ running once the system is up.
|
|||
inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
|
||||
Format: <irq>
|
||||
|
||||
combined_mode= [HW] control which driver uses IDE ports in combined
|
||||
mode: legacy IDE driver, libata, or both
|
||||
(in the libata case, libata.atapi_enabled=1 may be
|
||||
useful as well). Note that using the ide or libata
|
||||
options may affect your device naming (e.g. by
|
||||
changing hdc to sdb).
|
||||
Format: combined (default), ide, or libata
|
||||
|
||||
inttest= [IA64]
|
||||
|
||||
io7= [HW] IO7 for Marvel based alpha systems
|
||||
|
|
|
@ -860,24 +860,6 @@ The structure has a number of fields, some of which are mandatory:
|
|||
It is safe to sleep in this method.
|
||||
|
||||
|
||||
(*) int (*duplicate)(struct key *key, const struct key *source);
|
||||
|
||||
If this type of key can be duplicated, then this method should be
|
||||
provided. It is called to copy the payload attached to the source into the
|
||||
new key. The data length on the new key will have been updated and the
|
||||
quota adjusted already.
|
||||
|
||||
This method will be called with the source key's semaphore read-locked to
|
||||
prevent its payload from being changed, thus RCU constraints need not be
|
||||
applied to the source key.
|
||||
|
||||
This method does not have to lock the destination key in order to attach a
|
||||
payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
|
||||
prevents anything else from gaining access to the key.
|
||||
|
||||
It is safe to sleep in this method.
|
||||
|
||||
|
||||
(*) int (*update)(struct key *key, const void *data, size_t datalen);
|
||||
|
||||
If this type of key can be updated, then this method should be provided.
|
||||
|
|
|
@ -51,6 +51,30 @@ superblock can be autodetected and run at boot time.
|
|||
The kernel parameter "raid=partitionable" (or "raid=part") means
|
||||
that all auto-detected arrays are assembled as partitionable.
|
||||
|
||||
Boot time assembly of degraded/dirty arrays
|
||||
-------------------------------------------
|
||||
|
||||
If a raid5 or raid6 array is both dirty and degraded, it could have
|
||||
undetectable data corruption. This is because the fact that it is
|
||||
'dirty' means that the parity cannot be trusted, and the fact that it
|
||||
is degraded means that some datablocks are missing and cannot reliably
|
||||
be reconstructed (due to no parity).
|
||||
|
||||
For this reason, md will normally refuse to start such an array. This
|
||||
requires the sysadmin to take action to explicitly start the array
|
||||
desipite possible corruption. This is normally done with
|
||||
mdadm --assemble --force ....
|
||||
|
||||
This option is not really available if the array has the root
|
||||
filesystem on it. In order to support this booting from such an
|
||||
array, md supports a module parameter "start_dirty_degraded" which,
|
||||
when set to 1, bypassed the checks and will allows dirty degraded
|
||||
arrays to be started.
|
||||
|
||||
So, to boot with a root filesystem of a dirty degraded raid[56], use
|
||||
|
||||
md-mod.start_dirty_degraded=1
|
||||
|
||||
|
||||
Superblock formats
|
||||
------------------
|
||||
|
@ -141,6 +165,70 @@ All md devices contain:
|
|||
in a fully functional array. If this is not yet known, the file
|
||||
will be empty. If an array is being resized (not currently
|
||||
possible) this will contain the larger of the old and new sizes.
|
||||
Some raid level (RAID1) allow this value to be set while the
|
||||
array is active. This will reconfigure the array. Otherwise
|
||||
it can only be set while assembling an array.
|
||||
|
||||
chunk_size
|
||||
This is the size if bytes for 'chunks' and is only relevant to
|
||||
raid levels that involve striping (1,4,5,6,10). The address space
|
||||
of the array is conceptually divided into chunks and consecutive
|
||||
chunks are striped onto neighbouring devices.
|
||||
The size should be atleast PAGE_SIZE (4k) and should be a power
|
||||
of 2. This can only be set while assembling an array
|
||||
|
||||
component_size
|
||||
For arrays with data redundancy (i.e. not raid0, linear, faulty,
|
||||
multipath), all components must be the same size - or at least
|
||||
there must a size that they all provide space for. This is a key
|
||||
part or the geometry of the array. It is measured in sectors
|
||||
and can be read from here. Writing to this value may resize
|
||||
the array if the personality supports it (raid1, raid5, raid6),
|
||||
and if the component drives are large enough.
|
||||
|
||||
metadata_version
|
||||
This indicates the format that is being used to record metadata
|
||||
about the array. It can be 0.90 (traditional format), 1.0, 1.1,
|
||||
1.2 (newer format in varying locations) or "none" indicating that
|
||||
the kernel isn't managing metadata at all.
|
||||
|
||||
level
|
||||
The raid 'level' for this array. The name will often (but not
|
||||
always) be the same as the name of the module that implements the
|
||||
level. To be auto-loaded the module must have an alias
|
||||
md-$LEVEL e.g. md-raid5
|
||||
This can be written only while the array is being assembled, not
|
||||
after it is started.
|
||||
|
||||
new_dev
|
||||
This file can be written but not read. The value written should
|
||||
be a block device number as major:minor. e.g. 8:0
|
||||
This will cause that device to be attached to the array, if it is
|
||||
available. It will then appear at md/dev-XXX (depending on the
|
||||
name of the device) and further configuration is then possible.
|
||||
|
||||
sync_speed_min
|
||||
sync_speed_max
|
||||
This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
|
||||
however they only apply to the particular array.
|
||||
If no value has been written to these, of if the word 'system'
|
||||
is written, then the system-wide value is used. If a value,
|
||||
in kibibytes-per-second is written, then it is used.
|
||||
When the files are read, they show the currently active value
|
||||
followed by "(local)" or "(system)" depending on whether it is
|
||||
a locally set or system-wide value.
|
||||
|
||||
sync_completed
|
||||
This shows the number of sectors that have been completed of
|
||||
whatever the current sync_action is, followed by the number of
|
||||
sectors in total that could need to be processed. The two
|
||||
numbers are separated by a '/' thus effectively showing one
|
||||
value, a fraction of the process that is complete.
|
||||
|
||||
sync_speed
|
||||
This shows the current actual speed, in K/sec, of the current
|
||||
sync_action. It is averaged over the last 30 seconds.
|
||||
|
||||
|
||||
As component devices are added to an md array, they appear in the 'md'
|
||||
directory as new directories named
|
||||
|
@ -167,6 +255,38 @@ Each directory contains:
|
|||
of being recoverred to
|
||||
This list make grow in future.
|
||||
|
||||
errors
|
||||
An approximate count of read errors that have been detected on
|
||||
this device but have not caused the device to be evicted from
|
||||
the array (either because they were corrected or because they
|
||||
happened while the array was read-only). When using version-1
|
||||
metadata, this value persists across restarts of the array.
|
||||
|
||||
This value can be written while assembling an array thus
|
||||
providing an ongoing count for arrays with metadata managed by
|
||||
userspace.
|
||||
|
||||
slot
|
||||
This gives the role that the device has in the array. It will
|
||||
either be 'none' if the device is not active in the array
|
||||
(i.e. is a spare or has failed) or an integer less than the
|
||||
'raid_disks' number for the array indicating which possition
|
||||
it currently fills. This can only be set while assembling an
|
||||
array. A device for which this is set is assumed to be working.
|
||||
|
||||
offset
|
||||
This gives the location in the device (in sectors from the
|
||||
start) where data from the array will be stored. Any part of
|
||||
the device before this offset us not touched, unless it is
|
||||
used for storing metadata (Formats 1.1 and 1.2).
|
||||
|
||||
size
|
||||
The amount of the device, after the offset, that can be used
|
||||
for storage of data. This will normally be the same as the
|
||||
component_size. This can be written while assembling an
|
||||
array. If a value less than the current component_size is
|
||||
written, component_size will be reduced to this value.
|
||||
|
||||
|
||||
An active md device will also contain and entry for each active device
|
||||
in the array. These are named
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
The Gianfar Ethernet Driver
|
||||
Sysfs File description
|
||||
|
||||
Author: Andy Fleming <afleming@freescale.com>
|
||||
Updated: 2005-07-28
|
||||
|
||||
SYSFS
|
||||
|
||||
Several of the features of the gianfar driver are controlled
|
||||
through sysfs files. These are:
|
||||
|
||||
bd_stash:
|
||||
To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to
|
||||
bd_stash, echo 'off' or '0' to disable
|
||||
|
||||
rx_stash_len:
|
||||
To stash the first n bytes of the packet in L2, echo the number
|
||||
of bytes to buf_stash_len. echo 0 to disable.
|
||||
|
||||
WARNING: You could really screw these up if you set them too low or high!
|
||||
fifo_threshold:
|
||||
To change the number of bytes the controller needs in the
|
||||
fifo before it starts transmission, echo the number of bytes to
|
||||
fifo_thresh. Range should be 0-511.
|
||||
|
||||
fifo_starve:
|
||||
When the FIFO has less than this many bytes during a transmit, it
|
||||
enters starve mode, and increases the priority of TX memory
|
||||
transactions. To change, echo the number of bytes to
|
||||
fifo_starve. Range should be 0-511.
|
||||
|
||||
fifo_starve_off:
|
||||
Once in starve mode, the FIFO remains there until it has this
|
||||
many bytes. To change, echo the number of bytes to
|
||||
fifo_starve_off. Range should be 0-511.
|
||||
|
||||
CHECKSUM OFFLOADING
|
||||
|
||||
The eTSEC controller (first included in parts from late 2005 like
|
||||
the 8548) has the ability to perform TCP, UDP, and IP checksums
|
||||
in hardware. The Linux kernel only offloads the TCP and UDP
|
||||
checksums (and always performs the pseudo header checksums), so
|
||||
the driver only supports checksumming for TCP/IP and UDP/IP
|
||||
packets. Use ethtool to enable or disable this feature for RX
|
||||
and TX.
|
||||
|
||||
VLAN
|
||||
|
||||
In order to use VLAN, please consult Linux documentation on
|
||||
configuring VLANs. The gianfar driver supports hardware insertion and
|
||||
extraction of VLAN headers, but not filtering. Filtering will be
|
||||
done by the kernel.
|
||||
|
||||
MULTICASTING
|
||||
|
||||
The gianfar driver supports using the group hash table on the
|
||||
TSEC (and the extended hash table on the eTSEC) for multicast
|
||||
filtering. On the eTSEC, the exact-match MAC registers are used
|
||||
before the hash tables. See Linux documentation on how to join
|
||||
multicast groups.
|
||||
|
||||
PADDING
|
||||
|
||||
The gianfar driver supports padding received frames with 2 bytes
|
||||
to align the IP header to a 16-byte boundary, when supported by
|
||||
hardware.
|
||||
|
||||
ETHTOOL
|
||||
|
||||
The gianfar driver supports the use of ethtool for many
|
||||
configuration options. You must run ethtool only on currently
|
||||
open interfaces. See ethtool documentation for details.
|
|
@ -46,6 +46,29 @@ ipfrag_secret_interval - INTEGER
|
|||
for the hash secret) for IP fragments.
|
||||
Default: 600
|
||||
|
||||
ipfrag_max_dist - INTEGER
|
||||
ipfrag_max_dist is a non-negative integer value which defines the
|
||||
maximum "disorder" which is allowed among fragments which share a
|
||||
common IP source address. Note that reordering of packets is
|
||||
not unusual, but if a large number of fragments arrive from a source
|
||||
IP address while a particular fragment queue remains incomplete, it
|
||||
probably indicates that one or more fragments belonging to that queue
|
||||
have been lost. When ipfrag_max_dist is positive, an additional check
|
||||
is done on fragments before they are added to a reassembly queue - if
|
||||
ipfrag_max_dist (or more) fragments have arrived from a particular IP
|
||||
address between additions to any IP fragment queue using that source
|
||||
address, it's presumed that one or more fragments in the queue are
|
||||
lost. The existing fragment queue will be dropped, and a new one
|
||||
started. An ipfrag_max_dist value of zero disables this check.
|
||||
|
||||
Using a very small value, e.g. 1 or 2, for ipfrag_max_dist can
|
||||
result in unnecessarily dropping fragment queues when normal
|
||||
reordering of packets occurs, which could lead to poor application
|
||||
performance. Using a very large value, e.g. 50000, increases the
|
||||
likelihood of incorrectly reassembling IP fragments that originate
|
||||
from different IP datagrams, which could result in data corruption.
|
||||
Default: 64
|
||||
|
||||
INET peer storage:
|
||||
|
||||
inet_peer_threshold - INTEGER
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
This file details changes in 2.6 which affect PCMCIA card driver authors:
|
||||
|
||||
* Unify detach and REMOVAL event code, as well as attach and INSERTION
|
||||
code (as of 2.6.16)
|
||||
void (*remove) (struct pcmcia_device *dev);
|
||||
int (*probe) (struct pcmcia_device *dev);
|
||||
|
||||
* Move suspend, resume and reset out of event handler (as of 2.6.16)
|
||||
int (*suspend) (struct pcmcia_device *dev);
|
||||
int (*resume) (struct pcmcia_device *dev);
|
||||
should be initialized in struct pcmcia_driver, and handle
|
||||
(SUSPEND == RESET_PHYSICAL) and (RESUME == CARD_RESET) events
|
||||
|
||||
* event handler initialization in struct pcmcia_driver (as of 2.6.13)
|
||||
The event handler is notified of all events, and must be initialized
|
||||
as the event() callback in the driver's struct pcmcia_driver.
|
||||
|
|
|
@ -41,3 +41,14 @@ to. Writing to this file will accept one of
|
|||
It will only change to 'firmware' or 'platform' if the system supports
|
||||
it.
|
||||
|
||||
/sys/power/image_size controls the size of the image created by
|
||||
the suspend-to-disk mechanism. It can be written a string
|
||||
representing a non-negative integer that will be used as an upper
|
||||
limit of the image size, in megabytes. The suspend-to-disk mechanism will
|
||||
do its best to ensure the image size will not exceed that number. However,
|
||||
if this turns out to be impossible, it will try to suspend anyway using the
|
||||
smallest image possible. In particular, if "0" is written to this file, the
|
||||
suspend image will be as small as possible.
|
||||
|
||||
Reading from this file will display the current image size limit, which
|
||||
is set to 500 MB by default.
|
||||
|
|
|
@ -27,6 +27,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
|
|||
|
||||
echo platform > /sys/power/disk; echo disk > /sys/power/state
|
||||
|
||||
If you want to limit the suspend image size to N megabytes, do
|
||||
|
||||
echo N > /sys/power/image_size
|
||||
|
||||
before suspend (it is limited to 500 MB by default).
|
||||
|
||||
Encrypted suspend image:
|
||||
------------------------
|
||||
|
|
|
@ -115,7 +115,7 @@ Current PPC64 Linux EEH Implementation
|
|||
At this time, a generic EEH recovery mechanism has been implemented,
|
||||
so that individual device drivers do not need to be modified to support
|
||||
EEH recovery. This generic mechanism piggy-backs on the PCI hotplug
|
||||
infrastructure, and percolates events up through the hotplug/udev
|
||||
infrastructure, and percolates events up through the userspace/udev
|
||||
infrastructure. Followiing is a detailed description of how this is
|
||||
accomplished.
|
||||
|
||||
|
@ -172,7 +172,7 @@ A handler for the EEH notifier_block events is implemented in
|
|||
drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
|
||||
It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
|
||||
This last call causes the device driver for the card to be stopped,
|
||||
which causes hotplug events to go out to user space. This triggers
|
||||
which causes uevents to go out to user space. This triggers
|
||||
user-space scripts that might issue commands such as "ifdown eth0"
|
||||
for ethernet cards, and so on. This handler then sleeps for 5 seconds,
|
||||
hoping to give the user-space scripts enough time to complete.
|
||||
|
@ -264,23 +264,24 @@ rpa_php_unconfig_pci_adapter() { // in rpaphp_pci.c
|
|||
calls
|
||||
kobject_del() { //in /libs/kobject.c
|
||||
calls
|
||||
kobject_hotplug() { // in /libs/kobject.c
|
||||
kobject_uevent() { // in /libs/kobject.c
|
||||
calls
|
||||
kset_hotplug() { // in /lib/kobject.c
|
||||
kset_uevent() { // in /lib/kobject.c
|
||||
calls
|
||||
kset->hotplug_ops->hotplug() which is really just
|
||||
kset->uevent_ops->uevent() // which is really just
|
||||
a call to
|
||||
dev_hotplug() { // in /drivers/base/core.c
|
||||
dev_uevent() { // in /drivers/base/core.c
|
||||
calls
|
||||
dev->bus->hotplug() which is really just a call to
|
||||
pci_hotplug () { // in drivers/pci/hotplug.c
|
||||
dev->bus->uevent() which is really just a call to
|
||||
pci_uevent () { // in drivers/pci/hotplug.c
|
||||
which prints device name, etc....
|
||||
}
|
||||
}
|
||||
then kset_hotplug() calls
|
||||
call_usermodehelper () with
|
||||
argv[0]=hotplug_path[] which is "/sbin/hotplug"
|
||||
--> event to userspace,
|
||||
then kobject_uevent() sends a netlink uevent to userspace
|
||||
--> userspace uevent
|
||||
(during early boot, nobody listens to netlink events and
|
||||
kobject_uevent() executes uevent_helper[], which runs the
|
||||
event process /sbin/hotplug)
|
||||
}
|
||||
}
|
||||
kobject_del() then calls sysfs_remove_dir(), which would
|
||||
|
|
|
@ -1,3 +1,38 @@
|
|||
Release Date : Fri Nov 11 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.7 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
|
||||
|
||||
1. Sorted out PCI IDs to remove megaraid support overlaps.
|
||||
Based on the patch from Daniel, sorted out PCI IDs along with
|
||||
charactor node name change from 'megadev' to 'megadev_legacy' to avoid
|
||||
conflict.
|
||||
---
|
||||
Hopefully we'll be getting the build restriction zapped much sooner,
|
||||
but we should also be thinking about totally removing the hardware
|
||||
support overlap in the megaraid drivers.
|
||||
|
||||
This patch pencils in a date of Feb 06 for this, and performs some
|
||||
printk abuse in hope that existing legacy users might pick up on what's
|
||||
going on.
|
||||
|
||||
Signed-off-by: Daniel Drake <dsd@gentoo.org>
|
||||
---
|
||||
|
||||
2. Fixed a issue: megaraid always fails to reset handler.
|
||||
---
|
||||
I found that the megaraid driver always fails to reset the
|
||||
adapter with the following message:
|
||||
megaraid: resetting the host...
|
||||
megaraid mbox: reset sequence completed successfully
|
||||
megaraid: fast sync command timed out
|
||||
megaraid: reservation reset failed
|
||||
when the "Cluster mode" of the adapter BIOS is enabled.
|
||||
So, whenever the reset occurs, the adapter goes to
|
||||
offline and just become unavailable.
|
||||
|
||||
Jun'ichi Nomura [mailto:jnomura@mtc.biglobe.ne.jp]
|
||||
---
|
||||
|
||||
Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
|
||||
Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
|
||||
Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
|
||||
|
|
|
@ -150,7 +150,8 @@ scsi devices of which only the first 2 respond:
|
|||
LLD mid level LLD
|
||||
===-------------------=========--------------------===------
|
||||
scsi_host_alloc() -->
|
||||
scsi_add_host() --------+
|
||||
scsi_add_host() ---->
|
||||
scsi_scan_host() -------+
|
||||
|
|
||||
slave_alloc()
|
||||
slave_configure() --> scsi_adjust_queue_depth()
|
||||
|
@ -196,7 +197,7 @@ of the issues involved. See the section on reference counting below.
|
|||
|
||||
|
||||
The hotplug concept may be extended to SCSI devices. Currently, when an
|
||||
HBA is added, the scsi_add_host() function causes a scan for SCSI devices
|
||||
HBA is added, the scsi_scan_host() function causes a scan for SCSI devices
|
||||
attached to the HBA's SCSI transport. On newer SCSI transports the HBA
|
||||
may become aware of a new SCSI device _after_ the scan has completed.
|
||||
An LLD can use this sequence to make the mid level aware of a SCSI device:
|
||||
|
@ -372,7 +373,7 @@ names all start with "scsi_".
|
|||
Summary:
|
||||
scsi_activate_tcq - turn on tag command queueing
|
||||
scsi_add_device - creates new scsi device (lu) instance
|
||||
scsi_add_host - perform sysfs registration and SCSI bus scan.
|
||||
scsi_add_host - perform sysfs registration and set up transport class
|
||||
scsi_adjust_queue_depth - change the queue depth on a SCSI device
|
||||
scsi_assign_lock - replace default host_lock with given lock
|
||||
scsi_bios_ptable - return copy of block device's partition table
|
||||
|
@ -386,6 +387,7 @@ Summary:
|
|||
scsi_remove_device - detach and remove a SCSI device
|
||||
scsi_remove_host - detach and remove all SCSI devices owned by host
|
||||
scsi_report_bus_reset - report scsi _bus_ reset observed
|
||||
scsi_scan_host - scan SCSI bus
|
||||
scsi_track_queue_full - track successive QUEUE_FULL events
|
||||
scsi_unblock_requests - allow further commands to be queued to given host
|
||||
scsi_unregister - [calls scsi_host_put()]
|
||||
|
@ -425,10 +427,10 @@ void scsi_activate_tcq(struct scsi_device *sdev, int depth)
|
|||
* Might block: yes
|
||||
*
|
||||
* Notes: This call is usually performed internally during a scsi
|
||||
* bus scan when an HBA is added (i.e. scsi_add_host()). So it
|
||||
* bus scan when an HBA is added (i.e. scsi_scan_host()). So it
|
||||
* should only be called if the HBA becomes aware of a new scsi
|
||||
* device (lu) after scsi_add_host() has completed. If successful
|
||||
* this call we lead to slave_alloc() and slave_configure() callbacks
|
||||
* device (lu) after scsi_scan_host() has completed. If successful
|
||||
* this call can lead to slave_alloc() and slave_configure() callbacks
|
||||
* into the LLD.
|
||||
*
|
||||
* Defined in: drivers/scsi/scsi_scan.c
|
||||
|
@ -439,7 +441,7 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
|
|||
|
||||
|
||||
/**
|
||||
* scsi_add_host - perform sysfs registration and SCSI bus scan.
|
||||
* scsi_add_host - perform sysfs registration and set up transport class
|
||||
* @shost: pointer to scsi host instance
|
||||
* @dev: pointer to struct device of type scsi class
|
||||
*
|
||||
|
@ -448,7 +450,11 @@ struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
|
|||
* Might block: no
|
||||
*
|
||||
* Notes: Only required in "hotplug initialization model" after a
|
||||
* successful call to scsi_host_alloc().
|
||||
* successful call to scsi_host_alloc(). This function does not
|
||||
* scan the bus; this can be done by calling scsi_scan_host() or
|
||||
* in some other transport-specific way. The LLD must set up
|
||||
* the transport template before calling this function and may only
|
||||
* access the transport class data after this function has been called.
|
||||
*
|
||||
* Defined in: drivers/scsi/hosts.c
|
||||
**/
|
||||
|
@ -559,7 +565,7 @@ void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
|
|||
* area for the LLD's exclusive use.
|
||||
* Both associated refcounting objects have their refcount set to 1.
|
||||
* Full registration (in sysfs) and a bus scan are performed later when
|
||||
* scsi_add_host() is called.
|
||||
* scsi_add_host() and scsi_scan_host() are called.
|
||||
*
|
||||
* Defined in: drivers/scsi/hosts.c .
|
||||
**/
|
||||
|
@ -698,6 +704,19 @@ int scsi_remove_host(struct Scsi_Host *shost)
|
|||
void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_scan_host - scan SCSI bus
|
||||
* @shost: a pointer to a scsi host instance
|
||||
*
|
||||
* Might block: yes
|
||||
*
|
||||
* Notes: Should be called after scsi_add_host()
|
||||
*
|
||||
* Defined in: drivers/scsi/scsi_scan.c
|
||||
**/
|
||||
void scsi_scan_host(struct Scsi_Host *shost)
|
||||
|
||||
|
||||
/**
|
||||
* scsi_track_queue_full - track successive QUEUE_FULL events on given
|
||||
* device to determine if and when there is a need
|
||||
|
@ -1433,7 +1452,7 @@ The following people have contributed to this document:
|
|||
Christoph Hellwig <hch at infradead dot org>
|
||||
Doug Ledford <dledford at redhat dot com>
|
||||
Andries Brouwer <Andries dot Brouwer at cwi dot nl>
|
||||
Randy Dunlap <rddunlap at osdl dot org>
|
||||
Randy Dunlap <rdunlap at xenotime dot net>
|
||||
Alan Stern <stern at rowland dot harvard dot edu>
|
||||
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Each of top level sound card module takes the following options.
|
||||
|
||||
index - index (slot #) of sound card
|
||||
- Values: 0 through 7 or negative
|
||||
- Values: 0 through 31 or negative
|
||||
- If nonnegative, assign that index number
|
||||
- if negative, interpret as a bitmask of permissible
|
||||
indices; the first free permitted index is assigned
|
||||
|
@ -134,7 +134,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma2 - second DMA # for AD1816A chip (PnP setup)
|
||||
clockfreq - Clock frequency for AD1816A chip (default = 0, 33000Hz)
|
||||
|
||||
Module supports up to 8 cards, autoprobe and PnP.
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
Module snd-ad1848
|
||||
-----------------
|
||||
|
@ -145,9 +145,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ # for AD1848 chip
|
||||
dma1 - DMA # for AD1848 chip (0,1,3)
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. It does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-ad1889
|
||||
-----------------
|
||||
|
||||
|
@ -156,7 +158,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
ac97_quirk - AC'97 workaround for strange hardware
|
||||
See the description of intel8x0 module for details.
|
||||
|
||||
This module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-ali5451
|
||||
------------------
|
||||
|
@ -184,7 +186,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mpu_irq - IRQ # for MPU-401 (PnP setup)
|
||||
fm_port - port # for OPL3 FM (PnP setup)
|
||||
|
||||
Module supports up to 8 cards, autoprobe and PnP.
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-als4000
|
||||
------------------
|
||||
|
@ -194,7 +198,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
joystick_port - port # for legacy joystick support.
|
||||
0 = disabled (default), 1 = auto-detect
|
||||
|
||||
Module supports up to 8 cards, autoprobe and PnP.
|
||||
This module supports multiple cards, autoprobe and PnP.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-atiixp
|
||||
-----------------
|
||||
|
@ -213,6 +219,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
implementation depends on the motherboard, and you'll need to
|
||||
choose the correct one via spdif_aclink module option.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-atiixp-modem
|
||||
-----------------------
|
||||
|
||||
|
@ -223,6 +231,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-au8810, snd-au8820, snd-au8830
|
||||
-----------------------------------------
|
||||
|
||||
|
@ -263,7 +273,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma1 - 1st DMA # for AZT2320 (WSS) chip (PnP setup)
|
||||
dma2 - 2nd DMA # for AZT2320 (WSS) chip (PnP setup)
|
||||
|
||||
Module supports up to 8 cards, PnP and autoprobe.
|
||||
This module supports multiple cards, PnP and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-azt3328
|
||||
------------------
|
||||
|
@ -272,7 +284,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
joystick - Enable joystick (default off)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-bt87x
|
||||
----------------
|
||||
|
@ -282,7 +294,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
digital_rate - Override the default digital rate (Hz)
|
||||
load_all - Load the driver even if the card model isn't known
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
@ -292,7 +304,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for Creative Audigy LS and SB Live 24bit
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
|
||||
Module snd-cmi8330
|
||||
|
@ -308,7 +320,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
sbdma8 - 8bit DMA # for CMI8330 chip (SB16)
|
||||
sbdma16 - 16bit DMA # for CMI8330 chip (SB16)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-cmipci
|
||||
-----------------
|
||||
|
@ -321,7 +335,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
(default = 1)
|
||||
joystick_port - Joystick port address (0 = disable, 1 = auto-detect)
|
||||
|
||||
Module supports autoprobe and multiple chips (max 8).
|
||||
This module supports autoprobe and multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-cs4231
|
||||
-----------------
|
||||
|
@ -335,7 +351,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma1 - first DMA # for CS4231 chip
|
||||
dma2 - second DMA # for CS4231 chip
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -355,7 +371,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma2 - second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus main port must be specified!!! Other ports are optional.
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -376,7 +392,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma2 - second DMA # for CS4236 chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
(if ISA PnP is not used) thus main port and control port must be
|
||||
specified!!! Other ports are optional.
|
||||
|
||||
|
@ -389,7 +405,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
dual_codec - Secondary codec ID (0 = disable, default)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
@ -403,13 +419,20 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
thinkpad - Force to enable Thinkpad's CLKRUN control.
|
||||
mmap_valid - Support OSS mmap mode (default = 0).
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
Usually external amp and CLKRUN controls are detected automatically
|
||||
from PCI sub vendor/device ids. If they don't work, give the options
|
||||
above explicitly.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-cs5535audio
|
||||
----------------------
|
||||
|
||||
Module for multifunction CS5535 companion PCI device
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-dt019x
|
||||
-----------------
|
||||
|
||||
|
@ -423,9 +446,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mpu_irq - IRQ # for MPU-401 (PnP setup)
|
||||
dma8 - DMA # (PnP setup)
|
||||
|
||||
Module supports up to 8 cards. This module is enabled only with
|
||||
This module supports multiple cards. This module is enabled only with
|
||||
ISA PnP support.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-dummy
|
||||
----------------
|
||||
|
||||
|
@ -433,6 +458,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
or input, but you may use this module for any application which
|
||||
requires a sound card (like RealPlayer).
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-emu10k1
|
||||
------------------
|
||||
|
||||
|
@ -450,7 +477,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
given in MB unit. Default value is 128.
|
||||
enable_ir - enable IR
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Input & Output configurations [extin/extout]
|
||||
* Creative Card wo/Digital out [0x0003/0x1f03]
|
||||
|
@ -466,12 +493,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
* Creative Card 5.1 (c) 2003 [0x3fc3/0x7cff]
|
||||
* Creative Card all ins and outs [0x3fff/0x7fff]
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-emu10k1x
|
||||
-------------------
|
||||
|
||||
Module for Creative Emu10k1X (SB Live Dell OEM version)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-ens1370
|
||||
------------------
|
||||
|
@ -482,7 +511,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
joystick - Enable joystick (default off)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-ens1371
|
||||
------------------
|
||||
|
@ -495,7 +524,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
joystick_port - port # for joystick (0x200,0x208,0x210,0x218),
|
||||
0 = disable (default), 1 = auto-detect
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-es968
|
||||
----------------
|
||||
|
@ -506,7 +535,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ # for ES968 (SB8) chip (PnP setup)
|
||||
dma1 - DMA # for ES968 (SB8) chip (PnP setup)
|
||||
|
||||
Module supports up to 8 cards, PnP and autoprobe.
|
||||
This module supports multiple cards, PnP and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-es1688
|
||||
-----------------
|
||||
|
@ -519,7 +550,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mpu_irq - IRQ # for MPU-401 port (5,7,9,10)
|
||||
dma8 - DMA # for ES-1688 chip (0,1,3)
|
||||
|
||||
Module supports up to 8 cards and autoprobe (without MPU-401 port).
|
||||
This module supports multiple cards and autoprobe (without MPU-401 port).
|
||||
|
||||
Module snd-es18xx
|
||||
-----------------
|
||||
|
@ -534,8 +565,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma2 - first DMA # for ES-18xx chip (0,1,3)
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards ISA PnP and autoprobe (without MPU-401 port
|
||||
if native ISA PnP routines are not used).
|
||||
This module supports multiple cards, ISA PnP and autoprobe (without MPU-401
|
||||
port if native ISA PnP routines are not used).
|
||||
When dma2 is equal with dma1, the driver works as half-duplex.
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -545,7 +576,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-es1968
|
||||
-----------------
|
||||
|
@ -561,7 +594,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
enable_mpu - enable MPU401 (0 = off, 1 = on, 2 = auto (default))
|
||||
joystick - enable joystick (default off)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
@ -577,7 +610,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
- High 16-bits are video (radio) device number + 1
|
||||
- example: 0x10002 (MediaForte 256-PCPR, device 1)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-gusclassic
|
||||
---------------------
|
||||
|
@ -592,7 +627,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
voices - GF1 voices limit (14-32)
|
||||
pcm_voices - reserved PCM voices
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-gusextreme
|
||||
---------------------
|
||||
|
@ -611,7 +646,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
voices - GF1 voices limit (14-32)
|
||||
pcm_voices - reserved PCM voices
|
||||
|
||||
Module supports up to 8 cards and autoprobe (without MPU-401 port).
|
||||
This module supports multiple cards and autoprobe (without MPU-401 port).
|
||||
|
||||
Module snd-gusmax
|
||||
-----------------
|
||||
|
@ -626,7 +661,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
voices - GF1 voices limit (14-32)
|
||||
pcm_voices - reserved PCM voices
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-hda-intel
|
||||
--------------------
|
||||
|
@ -688,12 +723,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
(Usually SD_LPLIB register is more accurate than the
|
||||
position buffer.)
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-hdsp
|
||||
---------------
|
||||
|
||||
Module for RME Hammerfall DSP audio interface(s)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Note: The firmware data can be automatically loaded via hotplug
|
||||
when CONFIG_FW_LOADER is set. Otherwise, you need to load
|
||||
|
@ -751,7 +788,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
|
||||
in msec resolution, default value is 500 (0.5 sec)
|
||||
|
||||
Module supports up to 8 cards and autoprobe. Note: The consumer part
|
||||
This module supports multiple cards and autoprobe. Note: The consumer part
|
||||
is not used with all Envy24 based cards (for example in the MidiMan Delta
|
||||
serie).
|
||||
|
||||
|
@ -787,7 +824,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
aureon71, universe, k8x800, phase22, phase28, ms300,
|
||||
av710
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Note: The supported board is detected by reading EEPROM or PCI
|
||||
SSID (if EEPROM isn't available). You can override the
|
||||
|
@ -839,6 +876,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-interwave
|
||||
--------------------
|
||||
|
||||
|
@ -855,7 +894,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
effect - 1 = InterWave effects enable (default 0);
|
||||
requires 8 voices
|
||||
|
||||
Module supports up to 8 cards, autoprobe and ISA PnP.
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
Module snd-interwave-stb
|
||||
------------------------
|
||||
|
@ -875,14 +914,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
effect - 1 = InterWave effects enable (default 0);
|
||||
requires 8 voices
|
||||
|
||||
Module supports up to 8 cards, autoprobe and ISA PnP.
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
Module snd-korg1212
|
||||
-------------------
|
||||
|
||||
Module for Korg 1212 IO PCI card
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-maestro3
|
||||
-------------------
|
||||
|
@ -894,7 +933,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
-1 for default pin (8 for allegro, 1 for
|
||||
others)
|
||||
|
||||
Module supports autoprobe and multiple chips (max 8).
|
||||
This module supports autoprobe and multiple chips.
|
||||
|
||||
Note: the binding of amplifier is dependent on hardware.
|
||||
If there is no sound even though all channels are unmuted, try to
|
||||
|
@ -909,7 +948,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for Digigram miXart8 sound cards.
|
||||
|
||||
Module supports multiple cards.
|
||||
This module supports multiple cards.
|
||||
Note: One miXart8 board will be represented as 4 alsa cards.
|
||||
See MIXART.txt for details.
|
||||
|
||||
|
@ -928,7 +967,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ number or -1 (disable)
|
||||
pnp - PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports multiple devices (max 8) and PnP.
|
||||
This module supports multiple devices and PnP.
|
||||
|
||||
Module snd-mtpav
|
||||
----------------
|
||||
|
@ -1014,7 +1053,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma2 - second DMA # for Yamaha OPL3-SA chip (0,1,3), -1 = disable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards and ISA PnP. This module does not support
|
||||
This module supports multiple cards and ISA PnP. It does not support
|
||||
autoprobe (if ISA PnP is not used) thus all ports must be specified!!!
|
||||
|
||||
The power-management is supported.
|
||||
|
@ -1064,6 +1103,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
This module supports only one card, autoprobe and PnP.
|
||||
|
||||
Module snd-pcxhr
|
||||
----------------
|
||||
|
||||
Module for Digigram PCXHR boards
|
||||
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-powermac (on ppc only)
|
||||
---------------------------------
|
||||
|
||||
|
@ -1084,20 +1130,22 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
For ARM architecture only.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-rme32
|
||||
----------------
|
||||
|
||||
Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32,
|
||||
Prodif96 and Prodif Gold) sound cards.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-rme96
|
||||
----------------
|
||||
|
||||
Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-rme9652
|
||||
------------------
|
||||
|
@ -1107,7 +1155,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
precise_ptr - Enable precise pointer (doesn't work reliably).
|
||||
(default = 0)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Note: snd-page-alloc module does the job which snd-hammerfall-mem
|
||||
module did formerly. It will allocate the buffers in advance
|
||||
|
@ -1124,6 +1172,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Module supports only one card.
|
||||
Module has no enable and index options.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sb8
|
||||
--------------
|
||||
|
||||
|
@ -1135,7 +1185,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ # for SB DSP chip (5,7,9,10)
|
||||
dma8 - DMA # for SB DSP chip (1,3)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sb16 and snd-sbawe
|
||||
-----------------------------
|
||||
|
@ -1155,7 +1207,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
csp - ASP/CSP chip support - 0 = disable (default), 1 = enable
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards, autoprobe and ISA PnP.
|
||||
This module supports multiple cards, autoprobe and ISA PnP.
|
||||
|
||||
Note: To use Vibra16X cards in 16-bit half duplex mode, you must
|
||||
disable 16bit DMA with dma16 = -1 module parameter.
|
||||
|
@ -1163,6 +1215,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
half duplex mode through 8-bit DMA channel by disabling their
|
||||
16-bit DMA channel.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sgalaxy
|
||||
------------------
|
||||
|
||||
|
@ -1173,7 +1227,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
irq - IRQ # (7,9,10,11)
|
||||
dma1 - DMA #
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-sscape
|
||||
-----------------
|
||||
|
@ -1185,7 +1241,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mpu_irq - MPU-401 IRQ # (PnP setup)
|
||||
dma - DMA # (PnP setup)
|
||||
|
||||
Module supports up to 8 cards. ISA PnP must be enabled.
|
||||
This module supports multiple cards. ISA PnP must be enabled.
|
||||
You need sscape_ctl tool in alsa-tools package for loading
|
||||
the microcode.
|
||||
|
||||
|
@ -1194,21 +1250,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module for AMD7930 sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-sun-cs4231 (on sparc only)
|
||||
-------------------------------------
|
||||
|
||||
Module for CS4231 sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-sun-dbri (on sparc only)
|
||||
-----------------------------------
|
||||
|
||||
Module for DBRI sound chips found on Sparcs.
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-wavefront
|
||||
--------------------
|
||||
|
@ -1228,7 +1284,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
dma2 - DMA2 # for CS4232 PCM interface.
|
||||
isapnp - ISA PnP detection - 0 = disable, 1 = enable (default)
|
||||
|
||||
Module supports up to 8 cards and ISA PnP.
|
||||
This module supports multiple cards and ISA PnP.
|
||||
|
||||
Module snd-sonicvibes
|
||||
---------------------
|
||||
|
@ -1240,7 +1296,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
- SoundCard must have onboard SRAM for this.
|
||||
mge - Mic Gain Enable - 1 = enable, 0 = disable (default)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
Module snd-serial-u16550
|
||||
------------------------
|
||||
|
@ -1259,7 +1315,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
0 = Soundcanvas, 1 = MS-124T, 2 = MS-124W S/A,
|
||||
3 = MS-124W M/B, 4 = Generic
|
||||
|
||||
Module supports up to 8 cards. This module does not support autoprobe
|
||||
This module supports multiple cards. This module does not support autoprobe
|
||||
thus the main port must be specified!!! Other options are optional.
|
||||
|
||||
Module snd-trident
|
||||
|
@ -1278,7 +1334,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
pcm_channels - max channels (voices) reserved for PCM
|
||||
wavetable_size - max wavetable size in kB (4-?kb)
|
||||
|
||||
Module supports up to 8 cards and autoprobe.
|
||||
This module supports multiple cards and autoprobe.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
@ -1290,14 +1346,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
vid - Vendor ID for the device (optional)
|
||||
pid - Product ID for the device (optional)
|
||||
|
||||
This module supports up to 8 cards, autoprobe and hotplugging.
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
Module snd-usb-usx2y
|
||||
--------------------
|
||||
|
||||
Module for Tascam USB US-122, US-224 and US-428 devices.
|
||||
|
||||
This module supports up to 8 cards, autoprobe and hotplugging.
|
||||
This module supports multiple devices, autoprobe and hotplugging.
|
||||
|
||||
Note: you need to load the firmware via usx2yloader utility included
|
||||
in alsa-tools and alsa-firmware packages.
|
||||
|
@ -1356,6 +1412,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Note: for the MPU401 on VIA823x, use snd-mpu401 driver
|
||||
additionally. The mpu_port option is for VIA686 chips only.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-via82xx-modem
|
||||
------------------------
|
||||
|
||||
|
@ -1368,6 +1426,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Note: The default index value of this module is -2, i.e. the first
|
||||
slot is excluded.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-virmidi
|
||||
------------------
|
||||
|
||||
|
@ -1375,9 +1435,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
This module creates virtual rawmidi devices which communicate
|
||||
to the corresponding ALSA sequencer ports.
|
||||
|
||||
midi_devs - MIDI devices # (1-8, default=4)
|
||||
midi_devs - MIDI devices # (1-4, default=4)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
Module snd-vx222
|
||||
----------------
|
||||
|
@ -1387,7 +1447,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
mic - Enable Microphone on V222 Mic (NYI)
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards.
|
||||
This module supports multiple cards.
|
||||
|
||||
When the driver is compiled as a module and the hotplug firmware
|
||||
is supported, the firmware data is loaded via hotplug automatically.
|
||||
|
@ -1406,6 +1466,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
size is chosen. The possible IBL values can be found in
|
||||
/proc/asound/cardX/vx-status proc file.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-vxpocket
|
||||
-------------------
|
||||
|
||||
|
@ -1413,7 +1475,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
ibl - Capture IBL size. (default = 0, minimum size)
|
||||
|
||||
Module supports up to 8 cards. The module is compiled only when
|
||||
This module supports multiple cards. The module is compiled only when
|
||||
PCMCIA is supported on kernel.
|
||||
|
||||
With the older 2.6.x kernel, to activate the driver via the card
|
||||
|
@ -1434,6 +1496,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
|
||||
ALSA 1.0.10.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
Module snd-ymfpci
|
||||
-----------------
|
||||
|
||||
|
@ -1447,7 +1511,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
1 (auto-detect)
|
||||
rear_switch - enable shared rear/line-in switch (bool)
|
||||
|
||||
Module supports autoprobe and multiple chips (max 8).
|
||||
This module supports autoprobe and multiple chips.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
@ -1458,6 +1522,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Note: the driver is build only when CONFIG_ISA is set.
|
||||
|
||||
The power-management is supported.
|
||||
|
||||
|
||||
AC97 Quirk Option
|
||||
=================
|
||||
|
@ -1474,7 +1540,7 @@ the proper value with this option.
|
|||
|
||||
The following strings are accepted:
|
||||
- default Don't override the default setting
|
||||
- disable Disable the quirk
|
||||
- none Disable the quirk
|
||||
- hp_only Bind Master and Headphone controls as a single control
|
||||
- swap_hp Swap headphone and master controls
|
||||
- swap_surround Swap master and surround controls
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -138,6 +138,22 @@ card*/codec97#0/ac97#?-?+regs
|
|||
# echo 02 9f1f > /proc/asound/card0/codec97#0/ac97#0-0+regs
|
||||
|
||||
|
||||
USB Audio Streams
|
||||
-----------------
|
||||
|
||||
card*/stream*
|
||||
Shows the assignment and the current status of each audio stream
|
||||
of the given card. This information is very useful for debugging.
|
||||
|
||||
|
||||
HD-Audio Codecs
|
||||
---------------
|
||||
|
||||
card*/codec#*
|
||||
Shows the general codec information and the attribute of each
|
||||
widget node.
|
||||
|
||||
|
||||
Sequencer Information
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ The bus instance is created via snd_hda_bus_new(). You need to pass
|
|||
the card instance, the template, and the pointer to store the
|
||||
resultant bus instance.
|
||||
|
||||
int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
|
||||
int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp,
|
||||
struct hda_bus **busp);
|
||||
|
||||
It returns zero if successful. A negative return value means any
|
||||
|
@ -166,14 +166,14 @@ The ops field contains the following callback functions:
|
|||
|
||||
struct hda_pcm_ops {
|
||||
int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
unsigned int stream_tag, unsigned int format,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
|
||||
snd_pcm_substream_t *substream);
|
||||
struct snd_pcm_substream *substream);
|
||||
};
|
||||
|
||||
All are non-NULL, so you can call them safely without NULL check.
|
||||
|
@ -284,7 +284,7 @@ parameter, and PCI subsystem IDs. If the matching entry is found, it
|
|||
returns the config field value.
|
||||
|
||||
snd_hda_add_new_ctls() can be used to create and add control entries.
|
||||
Pass the zero-terminated array of snd_kcontrol_new_t. The same array
|
||||
Pass the zero-terminated array of struct snd_kcontrol_new. The same array
|
||||
can be passed to snd_hda_resume_ctls() for resume.
|
||||
Note that this will call control->put callback of these entries. So,
|
||||
put callback should check codec->in_resume and force to restore the
|
||||
|
@ -292,7 +292,7 @@ given value if it's non-zero even if the value is identical with the
|
|||
cached value.
|
||||
|
||||
Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be
|
||||
used for the entry of snd_kcontrol_new_t.
|
||||
used for the entry of struct snd_kcontrol_new.
|
||||
|
||||
The input MUX helper callbacks for such a control are provided, too:
|
||||
snd_hda_input_mux_info() and snd_hda_input_mux_put(). See
|
||||
|
|
|
@ -202,17 +202,13 @@ you must call __handle_sysrq_nolock instead.
|
|||
|
||||
* I have more questions, who can I ask?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
You may feel free to send email to myrdraal@deathsdoor.com, and I will
|
||||
respond as soon as possible.
|
||||
-Myrdraal
|
||||
|
||||
And I'll answer any questions about the registration system you got, also
|
||||
responding as soon as possible.
|
||||
-Crutcher
|
||||
|
||||
* Credits
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Written by Mydraal <myrdraal@deathsdoor.com>
|
||||
Written by Mydraal <vulpyne@vulpyne.net>
|
||||
Updated by Adam Sulmicki <adam@cfar.umd.edu>
|
||||
Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
|
||||
Added to by Crutcher Dunnavant <crutcher+kernel@datastacks.com>
|
||||
|
|
50
MAINTAINERS
50
MAINTAINERS
|
@ -258,6 +258,13 @@ P: Ivan Kokshaysky
|
|||
M: ink@jurassic.park.msu.ru
|
||||
S: Maintained for 2.4; PCI support for 2.6.
|
||||
|
||||
AMD GEODE PROCESSOR/CHIPSET SUPPORT
|
||||
P: Jordan Crouse
|
||||
M: info-linux@geode.amd.com
|
||||
L: info-linux@geode.amd.com
|
||||
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
|
||||
S: Supported
|
||||
|
||||
APM DRIVER
|
||||
P: Stephen Rothwell
|
||||
M: sfr@canb.auug.org.au
|
||||
|
@ -554,6 +561,11 @@ W: http://us1.samba.org/samba/Linux_CIFS_client.html
|
|||
T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
|
||||
S: Supported
|
||||
|
||||
CONFIGFS
|
||||
P: Joel Becker
|
||||
M: Joel Becker <joel.becker@oracle.com>
|
||||
S: Supported
|
||||
|
||||
CIRRUS LOGIC GENERIC FBDEV DRIVER
|
||||
P: Jeff Garzik
|
||||
M: jgarzik@pobox.com
|
||||
|
@ -650,6 +662,11 @@ L: linux-crypto@vger.kernel.org
|
|||
T: git kernel.org:/pub/scm/linux/kernel/git/herbert/crypto-2.6.git
|
||||
S: Maintained
|
||||
|
||||
CS5535 Audio ALSA driver
|
||||
P: Jaya Kumar
|
||||
M: jayakumar.alsa@gmail.com
|
||||
S: Maintained
|
||||
|
||||
CYBERPRO FB DRIVER
|
||||
P: Russell King
|
||||
M: rmk@arm.linux.org.uk
|
||||
|
@ -1225,7 +1242,7 @@ IEEE 1394 SUBSYSTEM
|
|||
P: Ben Collins
|
||||
M: bcollins@debian.org
|
||||
P: Jody McIntyre
|
||||
M: scjody@steamballoon.com
|
||||
M: scjody@modernduck.com
|
||||
L: linux1394-devel@lists.sourceforge.net
|
||||
W: http://www.linux1394.org/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
|
||||
|
@ -1235,14 +1252,14 @@ IEEE 1394 OHCI DRIVER
|
|||
P: Ben Collins
|
||||
M: bcollins@debian.org
|
||||
P: Jody McIntyre
|
||||
M: scjody@steamballoon.com
|
||||
M: scjody@modernduck.com
|
||||
L: linux1394-devel@lists.sourceforge.net
|
||||
W: http://www.linux1394.org/
|
||||
S: Maintained
|
||||
|
||||
IEEE 1394 PCILYNX DRIVER
|
||||
P: Jody McIntyre
|
||||
M: scjody@steamballoon.com
|
||||
M: scjody@modernduck.com
|
||||
L: linux1394-devel@lists.sourceforge.net
|
||||
W: http://www.linux1394.org/
|
||||
S: Maintained
|
||||
|
@ -1465,7 +1482,6 @@ P: Several
|
|||
L: kernel-janitors@osdl.org
|
||||
W: http://www.kerneljanitors.org/
|
||||
W: http://sf.net/projects/kernel-janitor/
|
||||
W: http://developer.osdl.org/rddunlap/kj-patches/
|
||||
S: Maintained
|
||||
|
||||
KERNEL NFSD
|
||||
|
@ -1476,17 +1492,11 @@ W: http://nfs.sourceforge.net/
|
|||
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
|
||||
S: Maintained
|
||||
|
||||
KERNEL EVENT LAYER (KOBJECT_UEVENT)
|
||||
P: Robert Love
|
||||
M: rml@novell.com
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
KEXEC
|
||||
P: Eric Biederman
|
||||
P: Randy Dunlap
|
||||
M: ebiederm@xmission.com
|
||||
M: rddunlap@osdl.org
|
||||
M: rdunlap@xenotime.net
|
||||
W: http://www.xmission.com/~ebiederm/files/kexec/
|
||||
L: linux-kernel@vger.kernel.org
|
||||
L: fastboot@osdl.org
|
||||
|
@ -1900,6 +1910,15 @@ M: ajoshi@shell.unixbox.com
|
|||
L: linux-nvidia@lists.surfsouth.com
|
||||
S: Maintained
|
||||
|
||||
ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
|
||||
P: Mark Fasheh
|
||||
M: mark.fasheh@oracle.com
|
||||
P: Kurt Hackel
|
||||
M: kurt.hackel@oracle.com
|
||||
L: ocfs2-devel@oss.oracle.com
|
||||
W: http://oss.oracle.com/projects/ocfs2/
|
||||
S: Supported
|
||||
|
||||
OLYMPIC NETWORK DRIVER
|
||||
P: Peter De Shrijver
|
||||
M: p2@ace.ulyssis.student.kuleuven.ac.be
|
||||
|
@ -2587,7 +2606,6 @@ S: Maintained
|
|||
UDF FILESYSTEM
|
||||
P: Ben Fennema
|
||||
M: bfennema@falcon.csc.calpoly.edu
|
||||
L: linux_udf@hpesjro.fc.hp.com
|
||||
W: http://linux-udf.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
|
@ -2640,6 +2658,12 @@ L: linux-usb-users@lists.sourceforge.net
|
|||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
USB ISP116X DRIVER
|
||||
P: Olav Kongas
|
||||
M: ok@artecdesign.ee
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
S: Maintained
|
||||
|
||||
USB KAWASAKI LSI DRIVER
|
||||
P: Oliver Neukum
|
||||
M: oliver@neukum.name
|
||||
|
@ -2651,7 +2675,7 @@ USB MASS STORAGE DRIVER
|
|||
P: Matthew Dharm
|
||||
M: mdharm-usb@one-eyed-alien.net
|
||||
L: linux-usb-users@lists.sourceforge.net
|
||||
L: linux-usb-devel@lists.sourceforge.net
|
||||
L: usb-storage@lists.one-eyed-alien.net
|
||||
S: Maintained
|
||||
W: http://www.one-eyed-alien.net/~mdharm/linux-usb/
|
||||
|
||||
|
|
26
Makefile
26
Makefile
|
@ -286,10 +286,6 @@ export quiet Q KBUILD_VERBOSE
|
|||
cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
|
||||
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
|
||||
|
||||
# For backward compatibility
|
||||
check_gcc = $(warning check_gcc is deprecated - use cc-option) \
|
||||
$(call cc-option, $(1),$(2))
|
||||
|
||||
# cc-option-yn
|
||||
# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
|
||||
cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
|
||||
|
@ -481,18 +477,20 @@ ifeq ($(dot-config),1)
|
|||
|
||||
# Read in dependencies to all Kconfig* files, make sure to run
|
||||
# oldconfig if changes are detected.
|
||||
-include .config.cmd
|
||||
-include .kconfig.d
|
||||
|
||||
include .config
|
||||
|
||||
# If .config needs to be updated, it will be done via the dependency
|
||||
# that autoconf has on .config.
|
||||
# To avoid any implicit rule to kick in, define an empty command
|
||||
.config: ;
|
||||
.config .kconfig.d: ;
|
||||
|
||||
# If .config is newer than include/linux/autoconf.h, someone tinkered
|
||||
# with it and forgot to run make oldconfig
|
||||
include/linux/autoconf.h: .config
|
||||
# with it and forgot to run make oldconfig.
|
||||
# If kconfig.d is missing then we are probarly in a cleaned tree so
|
||||
# we execute the config step to be sure to catch updated Kconfig files
|
||||
include/linux/autoconf.h: .kconfig.d .config
|
||||
$(Q)mkdir -p include/linux
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
|
||||
else
|
||||
|
@ -1066,7 +1064,7 @@ help:
|
|||
@echo ' all - Build all targets marked with [*]'
|
||||
@echo '* vmlinux - Build the bare kernel'
|
||||
@echo '* modules - Build all modules'
|
||||
@echo ' modules_install - Install all modules'
|
||||
@echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)'
|
||||
@echo ' dir/ - Build all files in dir and below'
|
||||
@echo ' dir/file.[ois] - Build specified target only'
|
||||
@echo ' dir/file.ko - Build module including final link'
|
||||
|
@ -1240,7 +1238,10 @@ cscope: FORCE
|
|||
quiet_cmd_TAGS = MAKE $@
|
||||
define cmd_TAGS
|
||||
rm -f $@; \
|
||||
ETAGSF=`etags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
|
||||
ETAGSF=`etags --version | grep -i exuberant >/dev/null && \
|
||||
echo "-I __initdata,__exitdata,__acquires,__releases \
|
||||
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
||||
--extra=+f --c-kinds=+px"`; \
|
||||
$(all-sources) | xargs etags $$ETAGSF -a
|
||||
endef
|
||||
|
||||
|
@ -1251,7 +1252,10 @@ TAGS: FORCE
|
|||
quiet_cmd_tags = MAKE $@
|
||||
define cmd_tags
|
||||
rm -f $@; \
|
||||
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_GPL --extra=+f"`; \
|
||||
CTAGSF=`ctags --version | grep -i exuberant >/dev/null && \
|
||||
echo "-I __initdata,__exitdata,__acquires,__releases \
|
||||
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
|
||||
--extra=+f --c-kinds=+px"`; \
|
||||
$(all-sources) | xargs ctags $$CTAGSF -a
|
||||
endef
|
||||
|
||||
|
|
|
@ -40,6 +40,19 @@ config GENERIC_IOMAP
|
|||
bool
|
||||
default n
|
||||
|
||||
config GENERIC_HARDIRQS
|
||||
bool
|
||||
default y
|
||||
|
||||
config GENERIC_IRQ_PROBE
|
||||
bool
|
||||
default y
|
||||
|
||||
config AUTO_IRQ_AFFINITY
|
||||
bool
|
||||
depends on SMP
|
||||
default y
|
||||
|
||||
source "init/Kconfig"
|
||||
|
||||
|
||||
|
|
|
@ -175,7 +175,6 @@ EXPORT_SYMBOL(up);
|
|||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
EXPORT_SYMBOL(synchronize_irq);
|
||||
EXPORT_SYMBOL(flush_tlb_mm);
|
||||
EXPORT_SYMBOL(flush_tlb_range);
|
||||
EXPORT_SYMBOL(flush_tlb_page);
|
||||
|
|
|
@ -32,214 +32,25 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* Controller mappings for all interrupt sources:
|
||||
*/
|
||||
irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
|
||||
[0 ... NR_IRQS-1] = {
|
||||
.handler = &no_irq_type,
|
||||
.lock = SPIN_LOCK_UNLOCKED
|
||||
}
|
||||
};
|
||||
|
||||
static void register_irq_proc(unsigned int irq);
|
||||
|
||||
volatile unsigned long irq_err_count;
|
||||
|
||||
/*
|
||||
* Special irq handlers.
|
||||
*/
|
||||
|
||||
irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic no controller code
|
||||
*/
|
||||
|
||||
static void no_irq_enable_disable(unsigned int irq) { }
|
||||
static unsigned int no_irq_startup(unsigned int irq) { return 0; }
|
||||
|
||||
static void
|
||||
no_irq_ack(unsigned int irq)
|
||||
void ack_bad_irq(unsigned int irq)
|
||||
{
|
||||
irq_err_count++;
|
||||
printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq);
|
||||
}
|
||||
|
||||
struct hw_interrupt_type no_irq_type = {
|
||||
.typename = "none",
|
||||
.startup = no_irq_startup,
|
||||
.shutdown = no_irq_enable_disable,
|
||||
.enable = no_irq_enable_disable,
|
||||
.disable = no_irq_enable_disable,
|
||||
.ack = no_irq_ack,
|
||||
.end = no_irq_enable_disable,
|
||||
};
|
||||
|
||||
int
|
||||
handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
|
||||
struct irqaction *action)
|
||||
{
|
||||
int status = 1; /* Force the "do bottom halves" bit */
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if (!(action->flags & SA_INTERRUPT))
|
||||
local_irq_enable();
|
||||
else
|
||||
local_irq_disable();
|
||||
|
||||
ret = action->handler(irq, action->dev_id, regs);
|
||||
if (ret == IRQ_HANDLED)
|
||||
status |= action->flags;
|
||||
action = action->next;
|
||||
} while (action);
|
||||
if (status & SA_SAMPLE_RANDOM)
|
||||
add_interrupt_randomness(irq);
|
||||
local_irq_disable();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic enable/disable code: this just calls
|
||||
* down into the PIC-specific version for the actual
|
||||
* hardware disable after having gotten the irq
|
||||
* controller lock.
|
||||
*/
|
||||
void inline
|
||||
disable_irq_nosync(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
if (!desc->depth++) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->handler->disable(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronous version of the above, making sure the IRQ is
|
||||
* no longer running on any other IRQ..
|
||||
*/
|
||||
void
|
||||
disable_irq(unsigned int irq)
|
||||
{
|
||||
disable_irq_nosync(irq);
|
||||
synchronize_irq(irq);
|
||||
}
|
||||
|
||||
void
|
||||
enable_irq(unsigned int irq)
|
||||
{
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
switch (desc->depth) {
|
||||
case 1: {
|
||||
unsigned int status = desc->status & ~IRQ_DISABLED;
|
||||
desc->status = status;
|
||||
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
|
||||
desc->status = status | IRQ_REPLAY;
|
||||
hw_resend_irq(desc->handler,irq);
|
||||
}
|
||||
desc->handler->enable(irq);
|
||||
/* fall-through */
|
||||
}
|
||||
default:
|
||||
desc->depth--;
|
||||
break;
|
||||
case 0:
|
||||
printk(KERN_ERR "enable_irq() unbalanced from %p\n",
|
||||
__builtin_return_address(0));
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
|
||||
int
|
||||
setup_irq(unsigned int irq, struct irqaction * new)
|
||||
{
|
||||
int shared = 0;
|
||||
struct irqaction *old, **p;
|
||||
unsigned long flags;
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
|
||||
if (desc->handler == &no_irq_type)
|
||||
return -ENOSYS;
|
||||
|
||||
/*
|
||||
* Some drivers like serial.c use request_irq() heavily,
|
||||
* so we have to be careful not to interfere with a
|
||||
* running system.
|
||||
*/
|
||||
if (new->flags & SA_SAMPLE_RANDOM) {
|
||||
/*
|
||||
* This function might sleep, we want to call it first,
|
||||
* outside of the atomic block.
|
||||
* Yes, this might clear the entropy pool if the wrong
|
||||
* driver is attempted to be loaded, without actually
|
||||
* installing a new handler, but is this really a problem,
|
||||
* only the sysadmin is able to do this.
|
||||
*/
|
||||
rand_initialize_irq(irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following block of code has to be executed atomically
|
||||
*/
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
p = &desc->action;
|
||||
if ((old = *p) != NULL) {
|
||||
/* Can't share interrupts unless both agree to */
|
||||
if (!(old->flags & new->flags & SA_SHIRQ)) {
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* add new interrupt at end of irq queue */
|
||||
do {
|
||||
p = &old->next;
|
||||
old = *p;
|
||||
} while (old);
|
||||
shared = 1;
|
||||
}
|
||||
|
||||
*p = new;
|
||||
|
||||
if (!shared) {
|
||||
desc->depth = 0;
|
||||
desc->status &=
|
||||
~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS);
|
||||
desc->handler->startup(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct proc_dir_entry * root_irq_dir;
|
||||
static struct proc_dir_entry * irq_dir[NR_IRQS];
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static struct proc_dir_entry * smp_affinity_entry[NR_IRQS];
|
||||
static char irq_user_affinity[NR_IRQS];
|
||||
static cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
|
||||
|
||||
static void
|
||||
select_smp_affinity(int irq)
|
||||
int
|
||||
select_smp_affinity(unsigned int irq)
|
||||
{
|
||||
static int last_cpu;
|
||||
int cpu = last_cpu + 1;
|
||||
|
||||
if (!irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
|
||||
return;
|
||||
return 1;
|
||||
|
||||
while (!cpu_possible(cpu))
|
||||
cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
|
||||
|
@ -247,208 +58,10 @@ select_smp_affinity(int irq)
|
|||
|
||||
irq_affinity[irq] = cpumask_of_cpu(cpu);
|
||||
irq_desc[irq].handler->set_affinity(irq, cpumask_of_cpu(cpu));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
irq_affinity_read_proc (char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
|
||||
if (count - len < 2)
|
||||
return -EINVAL;
|
||||
len += sprintf(page + len, "\n");
|
||||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
irq_affinity_write_proc(struct file *file, const char __user *buffer,
|
||||
unsigned long count, void *data)
|
||||
{
|
||||
int irq = (long) data, full_count = count, err;
|
||||
cpumask_t new_value;
|
||||
|
||||
if (!irq_desc[irq].handler->set_affinity)
|
||||
return -EIO;
|
||||
|
||||
err = cpumask_parse(buffer, count, new_value);
|
||||
|
||||
/* The special value 0 means release control of the
|
||||
affinity to kernel. */
|
||||
cpus_and(new_value, new_value, cpu_online_map);
|
||||
if (cpus_empty(new_value)) {
|
||||
irq_user_affinity[irq] = 0;
|
||||
select_smp_affinity(irq);
|
||||
}
|
||||
/* Do not allow disabling IRQs completely - it's a too easy
|
||||
way to make the system unusable accidentally :-) At least
|
||||
one online CPU still has to be targeted. */
|
||||
else {
|
||||
irq_affinity[irq] = new_value;
|
||||
irq_user_affinity[irq] = 1;
|
||||
irq_desc[irq].handler->set_affinity(irq, new_value);
|
||||
}
|
||||
|
||||
return full_count;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#define MAX_NAMELEN 10
|
||||
|
||||
static void
|
||||
register_irq_proc (unsigned int irq)
|
||||
{
|
||||
char name [MAX_NAMELEN];
|
||||
|
||||
if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
|
||||
irq_dir[irq])
|
||||
return;
|
||||
|
||||
memset(name, 0, MAX_NAMELEN);
|
||||
sprintf(name, "%d", irq);
|
||||
|
||||
/* create /proc/irq/1234 */
|
||||
irq_dir[irq] = proc_mkdir(name, root_irq_dir);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if (irq_desc[irq].handler->set_affinity) {
|
||||
struct proc_dir_entry *entry;
|
||||
/* create /proc/irq/1234/smp_affinity */
|
||||
entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
|
||||
|
||||
if (entry) {
|
||||
entry->nlink = 1;
|
||||
entry->data = (void *)(long)irq;
|
||||
entry->read_proc = irq_affinity_read_proc;
|
||||
entry->write_proc = irq_affinity_write_proc;
|
||||
}
|
||||
|
||||
smp_affinity_entry[irq] = entry;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
init_irq_proc (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* create /proc/irq */
|
||||
root_irq_dir = proc_mkdir("irq", NULL);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* create /proc/irq/prof_cpu_mask */
|
||||
create_prof_cpu_mask(root_irq_dir);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create entries for all existing IRQs.
|
||||
*/
|
||||
for (i = 0; i < ACTUAL_NR_IRQS; i++) {
|
||||
if (irq_desc[i].handler == &no_irq_type)
|
||||
continue;
|
||||
register_irq_proc(i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
|
||||
unsigned long irqflags, const char * devname, void *dev_id)
|
||||
{
|
||||
int retval;
|
||||
struct irqaction * action;
|
||||
|
||||
if (irq >= ACTUAL_NR_IRQS)
|
||||
return -EINVAL;
|
||||
if (!handler)
|
||||
return -EINVAL;
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* Sanity-check: shared interrupts should REALLY pass in
|
||||
* a real dev-ID, otherwise we'll have trouble later trying
|
||||
* to figure out which interrupt is which (messes up the
|
||||
* interrupt freeing logic etc).
|
||||
*/
|
||||
if ((irqflags & SA_SHIRQ) && !dev_id) {
|
||||
printk(KERN_ERR
|
||||
"Bad boy: %s (at %p) called us without a dev_id!\n",
|
||||
devname, __builtin_return_address(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
action = (struct irqaction *)
|
||||
kmalloc(sizeof(struct irqaction), GFP_KERNEL);
|
||||
if (!action)
|
||||
return -ENOMEM;
|
||||
|
||||
action->handler = handler;
|
||||
action->flags = irqflags;
|
||||
cpus_clear(action->mask);
|
||||
action->name = devname;
|
||||
action->next = NULL;
|
||||
action->dev_id = dev_id;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
select_smp_affinity(irq);
|
||||
#endif
|
||||
|
||||
retval = setup_irq(irq, action);
|
||||
if (retval)
|
||||
kfree(action);
|
||||
return retval;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(request_irq);
|
||||
|
||||
void
|
||||
free_irq(unsigned int irq, void *dev_id)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
struct irqaction **p;
|
||||
unsigned long flags;
|
||||
|
||||
if (irq >= ACTUAL_NR_IRQS) {
|
||||
printk(KERN_CRIT "Trying to free IRQ%d\n", irq);
|
||||
return;
|
||||
}
|
||||
|
||||
desc = irq_desc + irq;
|
||||
spin_lock_irqsave(&desc->lock,flags);
|
||||
p = &desc->action;
|
||||
for (;;) {
|
||||
struct irqaction * action = *p;
|
||||
if (action) {
|
||||
struct irqaction **pp = p;
|
||||
p = &action->next;
|
||||
if (action->dev_id != dev_id)
|
||||
continue;
|
||||
|
||||
/* Found - now remove it from the list of entries. */
|
||||
*pp = action->next;
|
||||
if (!desc->action) {
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->handler->shutdown(irq);
|
||||
}
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Wait to make sure it's not being used on
|
||||
another CPU. */
|
||||
while (desc->status & IRQ_INPROGRESS)
|
||||
barrier();
|
||||
#endif
|
||||
kfree(action);
|
||||
return;
|
||||
}
|
||||
printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
|
||||
spin_unlock_irqrestore(&desc->lock,flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(free_irq);
|
||||
|
||||
int
|
||||
show_interrupts(struct seq_file *p, void *v)
|
||||
{
|
||||
|
@ -531,10 +144,6 @@ handle_irq(int irq, struct pt_regs * regs)
|
|||
* 0 return value means that this irq is already being
|
||||
* handled by some other CPU. (or is disabled)
|
||||
*/
|
||||
int cpu = smp_processor_id();
|
||||
irq_desc_t *desc = irq_desc + irq;
|
||||
struct irqaction * action;
|
||||
unsigned int status;
|
||||
static unsigned int illegal_count=0;
|
||||
|
||||
if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) {
|
||||
|
@ -546,229 +155,8 @@ handle_irq(int irq, struct pt_regs * regs)
|
|||
}
|
||||
|
||||
irq_enter();
|
||||
kstat_cpu(cpu).irqs[irq]++;
|
||||
spin_lock_irq(&desc->lock); /* mask also the higher prio events */
|
||||
desc->handler->ack(irq);
|
||||
/*
|
||||
* REPLAY is when Linux resends an IRQ that was dropped earlier.
|
||||
* WAITING is used by probe to mark irqs that are being tested.
|
||||
*/
|
||||
status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
|
||||
status |= IRQ_PENDING; /* we _want_ to handle it */
|
||||
|
||||
/*
|
||||
* If the IRQ is disabled for whatever reason, we cannot
|
||||
* use the action we have.
|
||||
*/
|
||||
action = NULL;
|
||||
if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
|
||||
action = desc->action;
|
||||
status &= ~IRQ_PENDING; /* we commit to handling */
|
||||
status |= IRQ_INPROGRESS; /* we are handling it */
|
||||
}
|
||||
desc->status = status;
|
||||
|
||||
/*
|
||||
* If there is no IRQ handler or it was disabled, exit early.
|
||||
* Since we set PENDING, if another processor is handling
|
||||
* a different instance of this same irq, the other processor
|
||||
* will take care of it.
|
||||
*/
|
||||
if (!action)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Edge triggered interrupts need to remember pending events.
|
||||
* This applies to any hw interrupts that allow a second
|
||||
* instance of the same irq to arrive while we are in handle_irq
|
||||
* or in the handler. But the code here only handles the _second_
|
||||
* instance of the irq, not the third or fourth. So it is mostly
|
||||
* useful for irq hardware that does not mask cleanly in an
|
||||
* SMP environment.
|
||||
*/
|
||||
for (;;) {
|
||||
spin_unlock(&desc->lock);
|
||||
handle_IRQ_event(irq, regs, action);
|
||||
spin_lock(&desc->lock);
|
||||
|
||||
if (!(desc->status & IRQ_PENDING)
|
||||
|| (desc->status & IRQ_LEVEL))
|
||||
break;
|
||||
desc->status &= ~IRQ_PENDING;
|
||||
}
|
||||
desc->status &= ~IRQ_INPROGRESS;
|
||||
out:
|
||||
/*
|
||||
* The ->end() handler has to deal with interrupts which got
|
||||
* disabled while the handler was running.
|
||||
*/
|
||||
desc->handler->end(irq);
|
||||
spin_unlock(&desc->lock);
|
||||
|
||||
local_irq_disable();
|
||||
__do_IRQ(irq, regs);
|
||||
local_irq_enable();
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ autodetection code..
|
||||
*
|
||||
* This depends on the fact that any interrupt that
|
||||
* comes in on to an unassigned handler will get stuck
|
||||
* with "IRQ_WAITING" cleared and the interrupt
|
||||
* disabled.
|
||||
*/
|
||||
unsigned long
|
||||
probe_irq_on(void)
|
||||
{
|
||||
int i;
|
||||
irq_desc_t *desc;
|
||||
unsigned long delay;
|
||||
unsigned long val;
|
||||
|
||||
/* Something may have generated an irq long ago and we want to
|
||||
flush such a longstanding irq before considering it as spurious. */
|
||||
for (i = NR_IRQS-1; i >= 0; i--) {
|
||||
desc = irq_desc + i;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
if (!irq_desc[i].action)
|
||||
irq_desc[i].handler->startup(i);
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
/* Wait for longstanding interrupts to trigger. */
|
||||
for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
|
||||
/* about 20ms delay */ barrier();
|
||||
|
||||
/* enable any unassigned irqs (we must startup again here because
|
||||
if a longstanding irq happened in the previous stage, it may have
|
||||
masked itself) first, enable any unassigned irqs. */
|
||||
for (i = NR_IRQS-1; i >= 0; i--) {
|
||||
desc = irq_desc + i;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
if (!desc->action) {
|
||||
desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
|
||||
if (desc->handler->startup(i))
|
||||
desc->status |= IRQ_PENDING;
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for spurious interrupts to trigger
|
||||
*/
|
||||
for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
|
||||
/* about 100ms delay */ barrier();
|
||||
|
||||
/*
|
||||
* Now filter out any obviously spurious interrupts
|
||||
*/
|
||||
val = 0;
|
||||
for (i=0; i<NR_IRQS; i++) {
|
||||
irq_desc_t *desc = irq_desc + i;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
if (status & IRQ_AUTODETECT) {
|
||||
/* It triggered already - consider it spurious. */
|
||||
if (!(status & IRQ_WAITING)) {
|
||||
desc->status = status & ~IRQ_AUTODETECT;
|
||||
desc->handler->shutdown(i);
|
||||
} else
|
||||
if (i < 32)
|
||||
val |= 1 << i;
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(probe_irq_on);
|
||||
|
||||
/*
|
||||
* Return a mask of triggered interrupts (this
|
||||
* can handle only legacy ISA interrupts).
|
||||
*/
|
||||
unsigned int
|
||||
probe_irq_mask(unsigned long val)
|
||||
{
|
||||
int i;
|
||||
unsigned int mask;
|
||||
|
||||
mask = 0;
|
||||
for (i = 0; i < NR_IRQS; i++) {
|
||||
irq_desc_t *desc = irq_desc + i;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
if (status & IRQ_AUTODETECT) {
|
||||
/* We only react to ISA interrupts */
|
||||
if (!(status & IRQ_WAITING)) {
|
||||
if (i < 16)
|
||||
mask |= 1 << i;
|
||||
}
|
||||
|
||||
desc->status = status & ~IRQ_AUTODETECT;
|
||||
desc->handler->shutdown(i);
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
return mask & val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the result of the IRQ probe.. A negative result means that
|
||||
* we have several candidates (but we return the lowest-numbered
|
||||
* one).
|
||||
*/
|
||||
|
||||
int
|
||||
probe_irq_off(unsigned long val)
|
||||
{
|
||||
int i, irq_found, nr_irqs;
|
||||
|
||||
nr_irqs = 0;
|
||||
irq_found = 0;
|
||||
for (i=0; i<NR_IRQS; i++) {
|
||||
irq_desc_t *desc = irq_desc + i;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
status = desc->status;
|
||||
|
||||
if (status & IRQ_AUTODETECT) {
|
||||
if (!(status & IRQ_WAITING)) {
|
||||
if (!nr_irqs)
|
||||
irq_found = i;
|
||||
nr_irqs++;
|
||||
}
|
||||
desc->status = status & ~IRQ_AUTODETECT;
|
||||
desc->handler->shutdown(i);
|
||||
}
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
if (nr_irqs > 1)
|
||||
irq_found = -irq_found;
|
||||
return irq_found;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(probe_irq_off);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void synchronize_irq(unsigned int irq)
|
||||
{
|
||||
/* is there anything to synchronize with? */
|
||||
if (!irq_desc[irq].action)
|
||||
return;
|
||||
|
||||
while (irq_desc[irq].status & IRQ_INPROGRESS)
|
||||
barrier();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -45,7 +45,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
||||
static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
||||
{
|
||||
struct amba_device *pcdev = to_amba_device(dev);
|
||||
|
||||
|
@ -58,7 +58,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
|
|||
return 0;
|
||||
}
|
||||
#else
|
||||
#define amba_hotplug NULL
|
||||
#define amba_uevent NULL
|
||||
#endif
|
||||
|
||||
static int amba_suspend(struct device *dev, pm_message_t state)
|
||||
|
@ -88,7 +88,7 @@ static int amba_resume(struct device *dev)
|
|||
static struct bus_type amba_bustype = {
|
||||
.name = "amba",
|
||||
.match = amba_match,
|
||||
.hotplug = amba_hotplug,
|
||||
.uevent = amba_uevent,
|
||||
.suspend = amba_suspend,
|
||||
.resume = amba_resume,
|
||||
};
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <asm/arch/pxafb.h>
|
||||
#include <asm/arch/mmc.h>
|
||||
#include <asm/arch/irda.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
@ -393,6 +394,25 @@ static struct platform_device *platform_devices[] __initdata = {
|
|||
&mst_flash_device[1],
|
||||
};
|
||||
|
||||
static int mainstone_ohci_init(struct device *dev)
|
||||
{
|
||||
/* setup Port1 GPIO pin. */
|
||||
pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */
|
||||
pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */
|
||||
|
||||
/* Set the Power Control Polarity Low and Power Sense
|
||||
Polarity Low to active low. */
|
||||
UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) &
|
||||
~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pxaohci_platform_data mainstone_ohci_platform_data = {
|
||||
.port_mode = PMM_PERPORT_MODE,
|
||||
.init = mainstone_ohci_init,
|
||||
};
|
||||
|
||||
static void __init mainstone_init(void)
|
||||
{
|
||||
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
|
||||
|
@ -424,6 +444,7 @@ static void __init mainstone_init(void)
|
|||
|
||||
pxa_set_mci_info(&mainstone_mci_platform_data);
|
||||
pxa_set_ficp_info(&mainstone_ficp_platform_data);
|
||||
pxa_set_ohci_info(&mainstone_ohci_platform_data);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/arch/pxa-regs.h>
|
||||
#include <asm/arch/ohci.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
@ -194,6 +195,11 @@ static struct platform_device ohci_device = {
|
|||
.resource = pxa27x_ohci_resources,
|
||||
};
|
||||
|
||||
void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
|
||||
{
|
||||
ohci_device.dev.platform_data = info;
|
||||
}
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&ohci_device,
|
||||
};
|
||||
|
|
|
@ -46,10 +46,9 @@ typedef struct task_struct* PTASK;
|
|||
|
||||
#ifdef MODULE
|
||||
void fp_send_sig(unsigned long sig, PTASK p, int priv);
|
||||
#if LINUX_VERSION_CODE > 0x20115
|
||||
|
||||
MODULE_AUTHOR("Scott Bambrough <scottb@rebel.com>");
|
||||
MODULE_DESCRIPTION("NWFPE floating point emulator");
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define fp_send_sig send_sig
|
||||
|
|
|
@ -569,12 +569,6 @@ gdb_cris_strtol (const char *s, char **endptr, int base)
|
|||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
double_this(int x)
|
||||
{
|
||||
return 2 * x;
|
||||
}
|
||||
|
||||
/********************************* Register image ****************************/
|
||||
/* Copy the content of a register image into another. The size n is
|
||||
the size of the register image. Due to struct assignment generation of
|
||||
|
|
|
@ -20,3 +20,4 @@ obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o
|
|||
obj-$(CONFIG_PM) += pm.o cmode.o
|
||||
obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o
|
||||
obj-$(CONFIG_SYSCTL) += sysctl.o
|
||||
obj-$(CONFIG_FUTEX) += futex.o
|
||||
|
|
|
@ -1076,7 +1076,7 @@ __entry_work_notifysig:
|
|||
LEDS 0x6410
|
||||
ori.p gr4,#0,gr8
|
||||
call do_notify_resume
|
||||
bra __entry_return_direct
|
||||
bra __entry_resume_userspace
|
||||
|
||||
# perform syscall entry tracing
|
||||
__syscall_trace_entry:
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
/* futex.c: futex operations
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <asm/futex.h>
|
||||
#include <asm/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/*
|
||||
* the various futex operations; MMU fault checking is ignored under no-MMU
|
||||
* conditions
|
||||
*/
|
||||
static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" add %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" or %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" and %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
|
||||
{
|
||||
int oldval, ret;
|
||||
|
||||
asm("0: \n"
|
||||
" orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */
|
||||
" ckeq icc3,cc7 \n"
|
||||
"1: ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */
|
||||
" orcr cc7,cc7,cc3 \n" /* set CC3 to true */
|
||||
" xor %1,%3,%3 \n"
|
||||
"2: cst.p %3,%M0 ,cc3,#1 \n"
|
||||
" corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */
|
||||
" beq icc3,#0,0b \n"
|
||||
" setlos 0,%2 \n"
|
||||
"3: \n"
|
||||
".subsection 2 \n"
|
||||
"4: setlos %5,%2 \n"
|
||||
" bra 3b \n"
|
||||
".previous \n"
|
||||
".section __ex_table,\"a\" \n"
|
||||
" .balign 8 \n"
|
||||
" .long 1b,4b \n"
|
||||
" .long 2b,4b \n"
|
||||
".previous"
|
||||
: "+U"(*uaddr), "=&r"(oldval), "=&r"(ret), "=r"(oparg)
|
||||
: "3"(oparg), "i"(-EFAULT)
|
||||
: "memory", "cc7", "cc3", "icc3"
|
||||
);
|
||||
|
||||
*_oldval = oldval;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* do the futex operations
|
||||
*/
|
||||
int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
|
||||
{
|
||||
int op = (encoded_op >> 28) & 7;
|
||||
int cmp = (encoded_op >> 24) & 15;
|
||||
int oparg = (encoded_op << 8) >> 20;
|
||||
int cmparg = (encoded_op << 20) >> 20;
|
||||
int oldval = 0, ret;
|
||||
|
||||
if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
|
||||
oparg = 1 << oparg;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
inc_preempt_count();
|
||||
|
||||
switch (op) {
|
||||
case FUTEX_OP_SET:
|
||||
ret = atomic_futex_op_xchg_set(oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_ADD:
|
||||
ret = atomic_futex_op_xchg_add(oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_OR:
|
||||
ret = atomic_futex_op_xchg_or(oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_ANDN:
|
||||
ret = atomic_futex_op_xchg_and(~oparg, uaddr, &oldval);
|
||||
break;
|
||||
case FUTEX_OP_XOR:
|
||||
ret = atomic_futex_op_xchg_xor(oparg, uaddr, &oldval);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
dec_preempt_count();
|
||||
|
||||
if (!ret) {
|
||||
switch (cmp) {
|
||||
case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
|
||||
case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
|
||||
case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
|
||||
case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
|
||||
case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
|
||||
case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
|
||||
default: ret = -ENOSYS; break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end futex_atomic_op_inuser() */
|
|
@ -35,7 +35,7 @@ struct fdpic_func_descriptor {
|
|||
unsigned long GOT;
|
||||
};
|
||||
|
||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
|
||||
static int do_signal(sigset_t *oldset);
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
|
@ -55,7 +55,7 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
|||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(__frame, &saveset))
|
||||
if (do_signal(&saveset))
|
||||
/* return the signal number as the return value of this function
|
||||
* - this is an utterly evil hack. syscalls should not invoke do_signal()
|
||||
* as entry.S sets regs->gr8 to the return value of the system call
|
||||
|
@ -91,7 +91,7 @@ asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
|
|||
while (1) {
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
if (do_signal(__frame, &saveset))
|
||||
if (do_signal(&saveset))
|
||||
/* return the signal number as the return value of this function
|
||||
* - this is an utterly evil hack. syscalls should not invoke do_signal()
|
||||
* as entry.S sets regs->gr8 to the return value of the system call
|
||||
|
@ -276,13 +276,12 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
|
|||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
||||
/* Default to using normal stack */
|
||||
sp = regs->sp;
|
||||
sp = __frame->sp;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
|
@ -291,18 +290,19 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
|
|||
}
|
||||
|
||||
return (void __user *) ((sp - frame_size) & ~7UL);
|
||||
|
||||
} /* end get_sigframe() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int rsig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ka, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
|
@ -346,47 +346,51 @@ static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct p
|
|||
}
|
||||
|
||||
/* set up registers for signal handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->lr = (unsigned long) &frame->retcode;
|
||||
regs->gr8 = sig;
|
||||
__frame->sp = (unsigned long) frame;
|
||||
__frame->lr = (unsigned long) &frame->retcode;
|
||||
__frame->gr8 = sig;
|
||||
|
||||
if (get_personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor *) ka->sa.sa_handler;
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->gr15, &funcptr->GOT);
|
||||
__get_user(__frame->pc, &funcptr->text);
|
||||
__get_user(__frame->gr15, &funcptr->GOT);
|
||||
} else {
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->gr15 = 0;
|
||||
__frame->pc = (unsigned long) ka->sa.sa_handler;
|
||||
__frame->gr15 = 0;
|
||||
}
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
/* the tracer may want to single-step inside the handler */
|
||||
if (test_thread_flag(TIF_SINGLESTEP))
|
||||
ptrace_notify(SIGTRAP);
|
||||
|
||||
#if DEBUG_SIG
|
||||
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
|
||||
sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
|
||||
sig, current->comm, current->pid, frame, __frame->pc,
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
||||
} /* end setup_frame() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int rsig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ka, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
|
@ -409,7 +413,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
if (__put_user(0, &frame->uc.uc_flags) ||
|
||||
__put_user(0, &frame->uc.uc_link) ||
|
||||
__put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
|
||||
__put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags) ||
|
||||
__put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
|
||||
__put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
|
||||
goto give_sigsegv;
|
||||
|
||||
|
@ -440,34 +444,38 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
}
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->lr = (unsigned long) &frame->retcode;
|
||||
regs->gr8 = sig;
|
||||
regs->gr9 = (unsigned long) &frame->info;
|
||||
__frame->sp = (unsigned long) frame;
|
||||
__frame->lr = (unsigned long) &frame->retcode;
|
||||
__frame->gr8 = sig;
|
||||
__frame->gr9 = (unsigned long) &frame->info;
|
||||
|
||||
if (get_personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor *funcptr =
|
||||
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->gr15, &funcptr->GOT);
|
||||
__get_user(__frame->pc, &funcptr->text);
|
||||
__get_user(__frame->gr15, &funcptr->GOT);
|
||||
} else {
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->gr15 = 0;
|
||||
__frame->pc = (unsigned long) ka->sa.sa_handler;
|
||||
__frame->gr15 = 0;
|
||||
}
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
/* the tracer may want to single-step inside the handler */
|
||||
if (test_thread_flag(TIF_SINGLESTEP))
|
||||
ptrace_notify(SIGTRAP);
|
||||
|
||||
#if DEBUG_SIG
|
||||
printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n",
|
||||
sig, current->comm, current->pid, frame, regs->pc, frame->pretcode);
|
||||
sig, current->comm, current->pid, frame, __frame->pc,
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return;
|
||||
return 1;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
||||
} /* end setup_rt_frame() */
|
||||
|
||||
|
@ -475,43 +483,51 @@ give_sigsegv:
|
|||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
if (in_syscall(regs)) {
|
||||
if (in_syscall(__frame)) {
|
||||
/* If so, check system call restarting.. */
|
||||
switch (regs->gr8) {
|
||||
switch (__frame->gr8) {
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
case -ERESTARTNOHAND:
|
||||
regs->gr8 = -EINTR;
|
||||
__frame->gr8 = -EINTR;
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
regs->gr8 = -EINTR;
|
||||
__frame->gr8 = -EINTR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* fallthrough */
|
||||
case -ERESTARTNOINTR:
|
||||
regs->gr8 = regs->orig_gr8;
|
||||
regs->pc -= 4;
|
||||
__frame->gr8 = __frame->orig_gr8;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
ret = setup_rt_frame(sig, ka, info, oldset);
|
||||
else
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(sig, ka, oldset);
|
||||
|
||||
if (ret) {
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
sigorsets(¤t->blocked, ¤t->blocked,
|
||||
&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked, sig);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} /* end handle_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -520,7 +536,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
|||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||
* mistake.
|
||||
*/
|
||||
int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
static int do_signal(sigset_t *oldset)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
|
@ -532,7 +548,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||
* kernel mode. Just return without doing anything
|
||||
* if so.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
if (!user_mode(__frame))
|
||||
return 1;
|
||||
|
||||
if (try_to_freeze())
|
||||
|
@ -541,30 +557,29 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||
if (!oldset)
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
handle_signal(signr, &info, &ka, oldset, regs);
|
||||
return 1;
|
||||
}
|
||||
signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
|
||||
if (signr > 0)
|
||||
return handle_signal(signr, &info, &ka, oldset);
|
||||
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (regs->syscallno >= 0) {
|
||||
if (__frame->syscallno >= 0) {
|
||||
/* Restart the system call - no handlers present */
|
||||
if (regs->gr8 == -ERESTARTNOHAND ||
|
||||
regs->gr8 == -ERESTARTSYS ||
|
||||
regs->gr8 == -ERESTARTNOINTR) {
|
||||
regs->gr8 = regs->orig_gr8;
|
||||
regs->pc -= 4;
|
||||
if (__frame->gr8 == -ERESTARTNOHAND ||
|
||||
__frame->gr8 == -ERESTARTSYS ||
|
||||
__frame->gr8 == -ERESTARTNOINTR) {
|
||||
__frame->gr8 = __frame->orig_gr8;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
|
||||
if (regs->gr8 == -ERESTART_RESTARTBLOCK){
|
||||
regs->gr8 = __NR_restart_syscall;
|
||||
regs->pc -= 4;
|
||||
if (__frame->gr8 == -ERESTART_RESTARTBLOCK){
|
||||
__frame->gr8 = __NR_restart_syscall;
|
||||
__frame->pc -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} /* end do_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -580,6 +595,6 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
|
|||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(__frame, NULL);
|
||||
do_signal(NULL);
|
||||
|
||||
} /* end do_notify_resume() */
|
||||
|
|
|
@ -464,7 +464,6 @@ config NUMA
|
|||
depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI))
|
||||
default n if X86_PC
|
||||
default y if (X86_NUMAQ || X86_SUMMIT)
|
||||
select SPARSEMEM_STATIC
|
||||
|
||||
# Need comments to help the hapless user trying to turn on NUMA support
|
||||
comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
|
||||
|
@ -493,6 +492,10 @@ config HAVE_ARCH_ALLOC_REMAP
|
|||
depends on NUMA
|
||||
default y
|
||||
|
||||
config ARCH_FLATMEM_ENABLE
|
||||
def_bool y
|
||||
depends on (ARCH_SELECT_MEMORY_MODEL && X86_PC)
|
||||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
|
@ -503,7 +506,8 @@ config ARCH_DISCONTIGMEM_DEFAULT
|
|||
|
||||
config ARCH_SPARSEMEM_ENABLE
|
||||
def_bool y
|
||||
depends on NUMA
|
||||
depends on (NUMA || (X86_PC && EXPERIMENTAL))
|
||||
select SPARSEMEM_STATIC
|
||||
|
||||
config ARCH_SELECT_MEMORY_MODEL
|
||||
def_bool y
|
||||
|
|
|
@ -39,6 +39,7 @@ config M386
|
|||
- "Winchip-2" for IDT Winchip 2.
|
||||
- "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
|
||||
- "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
|
||||
- "Geode GX/LX" For AMD Geode GX and LX processors.
|
||||
- "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
|
||||
- "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
|
||||
|
||||
|
@ -171,6 +172,11 @@ config MGEODEGX1
|
|||
help
|
||||
Select this for a Geode GX1 (Cyrix MediaGX) chip.
|
||||
|
||||
config MGEODE_LX
|
||||
bool "Geode GX/LX"
|
||||
help
|
||||
Select this for AMD Geode GX and LX processors.
|
||||
|
||||
config MCYRIXIII
|
||||
bool "CyrixIII/VIA-C3"
|
||||
help
|
||||
|
@ -220,8 +226,8 @@ config X86_XADD
|
|||
config X86_L1_CACHE_SHIFT
|
||||
int
|
||||
default "7" if MPENTIUM4 || X86_GENERIC
|
||||
default "4" if X86_ELAN || M486 || M386
|
||||
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODEGX1
|
||||
default "4" if X86_ELAN || M486 || M386 || MGEODEGX1
|
||||
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
|
||||
default "6" if MK7 || MK8 || MPENTIUMM
|
||||
|
||||
config RWSEM_GENERIC_SPINLOCK
|
||||
|
@ -290,12 +296,12 @@ config X86_INTEL_USERCOPY
|
|||
|
||||
config X86_USE_PPRO_CHECKSUM
|
||||
bool
|
||||
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
|
||||
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX
|
||||
default y
|
||||
|
||||
config X86_USE_3DNOW
|
||||
bool
|
||||
depends on MCYRIXIII || MK7
|
||||
depends on MCYRIXIII || MK7 || MGEODE_LX
|
||||
default y
|
||||
|
||||
config X86_OOSTORE
|
||||
|
|
|
@ -42,6 +42,16 @@ config DEBUG_PAGEALLOC
|
|||
This results in a large slowdown, but helps to find certain types
|
||||
of memory corruptions.
|
||||
|
||||
config DEBUG_RODATA
|
||||
bool "Write protect kernel read-only data structures"
|
||||
depends on DEBUG_KERNEL
|
||||
help
|
||||
Mark the kernel read-only data as write-protected in the pagetables,
|
||||
in order to catch accidental (and incorrect) writes to such const
|
||||
data. This option may have a slight performance impact because a
|
||||
portion of the kernel code won't be covered by a 2MB TLB anymore.
|
||||
If in doubt, say "N".
|
||||
|
||||
config 4KSTACKS
|
||||
bool "Use 4Kb for kernel stacks instead of 8Kb"
|
||||
depends on DEBUG_KERNEL
|
||||
|
|
|
@ -721,7 +721,7 @@ static int __init apic_set_verbosity(char *str)
|
|||
apic_verbosity = APIC_VERBOSE;
|
||||
else
|
||||
printk(KERN_WARNING "APIC Verbosity level %s not recognised"
|
||||
" use apic=verbose or apic=debug", str);
|
||||
" use apic=verbose or apic=debug\n", str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -302,17 +302,6 @@ extern int (*console_blank_hook)(int);
|
|||
|
||||
#include "apm.h"
|
||||
|
||||
/*
|
||||
* Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is
|
||||
* supposed to provide limit information that it recognizes. Many machines
|
||||
* do this correctly, but many others do not restrict themselves to their
|
||||
* claimed limit. When this happens, they will cause a segmentation
|
||||
* violation in the kernel at boot time. Most BIOS's, however, will
|
||||
* respect a 64k limit, so we use that. If you want to be pedantic and
|
||||
* hold your BIOS to its claims, then undefine this.
|
||||
*/
|
||||
#define APM_RELAX_SEGMENTS
|
||||
|
||||
/*
|
||||
* Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
|
||||
* This patched by Chad Miller <cmiller@surfsouth.com>, original code by
|
||||
|
@ -1075,22 +1064,23 @@ static int apm_engage_power_management(u_short device, int enable)
|
|||
|
||||
static int apm_console_blank(int blank)
|
||||
{
|
||||
int error;
|
||||
int error, i;
|
||||
u_short state;
|
||||
static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
|
||||
|
||||
state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
|
||||
/* Blank the first display device */
|
||||
error = set_power_state(0x100, state);
|
||||
if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
|
||||
/* try to blank them all instead */
|
||||
error = set_power_state(0x1ff, state);
|
||||
if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
|
||||
/* try to blank device one instead */
|
||||
error = set_power_state(0x101, state);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev); i++) {
|
||||
error = set_power_state(dev[i], state);
|
||||
|
||||
if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
|
||||
return 1;
|
||||
if (error == APM_NOT_ENGAGED) {
|
||||
|
||||
if (error == APM_NOT_ENGAGED)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
|
||||
static int tried;
|
||||
int eng_error;
|
||||
if (tried++ == 0) {
|
||||
|
@ -2233,8 +2223,8 @@ static struct dmi_system_id __initdata apm_dmi_table[] = {
|
|||
static int __init apm_init(void)
|
||||
{
|
||||
struct proc_dir_entry *apm_proc;
|
||||
struct desc_struct *gdt;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
dmi_check_system(apm_dmi_table);
|
||||
|
||||
|
@ -2312,45 +2302,30 @@ static int __init apm_init(void)
|
|||
set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
|
||||
_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
|
||||
|
||||
/*
|
||||
* Set up the long jump entry point to the APM BIOS, which is called
|
||||
* from inline assembly.
|
||||
*/
|
||||
apm_bios_entry.offset = apm_info.bios.offset;
|
||||
apm_bios_entry.segment = APM_CS;
|
||||
|
||||
for (i = 0; i < NR_CPUS; i++) {
|
||||
struct desc_struct *gdt = get_cpu_gdt_table(i);
|
||||
/*
|
||||
* The APM 1.1 BIOS is supposed to provide limit information that it
|
||||
* recognizes. Many machines do this correctly, but many others do
|
||||
* not restrict themselves to their claimed limit. When this happens,
|
||||
* they will cause a segmentation violation in the kernel at boot time.
|
||||
* Most BIOS's, however, will respect a 64k limit, so we use that.
|
||||
*
|
||||
* Note we only set APM segments on CPU zero, since we pin the APM
|
||||
* code to that CPU.
|
||||
*/
|
||||
gdt = get_cpu_gdt_table(0);
|
||||
set_base(gdt[APM_CS >> 3],
|
||||
__va((unsigned long)apm_info.bios.cseg << 4));
|
||||
set_base(gdt[APM_CS_16 >> 3],
|
||||
__va((unsigned long)apm_info.bios.cseg_16 << 4));
|
||||
set_base(gdt[APM_DS >> 3],
|
||||
__va((unsigned long)apm_info.bios.dseg << 4));
|
||||
#ifndef APM_RELAX_SEGMENTS
|
||||
if (apm_info.bios.version == 0x100) {
|
||||
#endif
|
||||
/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
|
||||
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1);
|
||||
/* For some unknown machine. */
|
||||
_set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1);
|
||||
/* For the DEC Hinote Ultra CT475 (and others?) */
|
||||
_set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1);
|
||||
#ifndef APM_RELAX_SEGMENTS
|
||||
} else {
|
||||
_set_limit((char *)&gdt[APM_CS >> 3],
|
||||
(apm_info.bios.cseg_len - 1) & 0xffff);
|
||||
_set_limit((char *)&gdt[APM_CS_16 >> 3],
|
||||
(apm_info.bios.cseg_16_len - 1) & 0xffff);
|
||||
_set_limit((char *)&gdt[APM_DS >> 3],
|
||||
(apm_info.bios.dseg_len - 1) & 0xffff);
|
||||
/* workaround for broken BIOSes */
|
||||
if (apm_info.bios.cseg_len <= apm_info.bios.offset)
|
||||
_set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1);
|
||||
if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
|
||||
/* for the BIOS that assumes granularity = 1 */
|
||||
gdt[APM_DS >> 3].b |= 0x800000;
|
||||
printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
|
||||
if (apm_proc)
|
||||
|
|
|
@ -161,8 +161,13 @@ static void __init init_amd(struct cpuinfo_x86 *c)
|
|||
set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
if (c->x86_model == 10) {
|
||||
/* AMD Geode LX is model 10 */
|
||||
/* placeholder for any needed mods */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 6: /* An Athlon/Duron */
|
||||
|
||||
/* Bit 15 of Athlon specific MSR 15, needs to be 0
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
#include "cpu.h"
|
||||
|
||||
DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
|
||||
|
||||
DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
|
||||
EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
|
||||
|
||||
|
@ -598,11 +595,6 @@ void __devinit cpu_init(void)
|
|||
load_gdt(&cpu_gdt_descr[cpu]);
|
||||
load_idt(&idt_descr);
|
||||
|
||||
/*
|
||||
* Delete NT
|
||||
*/
|
||||
__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
|
||||
|
||||
/*
|
||||
* Set up and load the per-CPU TSS and LDT
|
||||
*/
|
||||
|
|
|
@ -177,9 +177,10 @@ static unsigned int nforce2_fsb_read(int bootfsb)
|
|||
*/
|
||||
static int nforce2_set_fsb(unsigned int fsb)
|
||||
{
|
||||
u32 pll, temp = 0;
|
||||
u32 temp = 0;
|
||||
unsigned int tfsb;
|
||||
int diff;
|
||||
int pll = 0;
|
||||
|
||||
if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
|
||||
printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb);
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
#define PFX "powernow-k8: "
|
||||
#define BFX PFX "BIOS error: "
|
||||
#define VERSION "version 1.50.4"
|
||||
#define VERSION "version 1.60.0"
|
||||
#include "powernow-k8.h"
|
||||
|
||||
/* serialize freq changes */
|
||||
|
@ -336,7 +336,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
|
|||
/* Phase 2 - core frequency transition */
|
||||
static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
|
||||
{
|
||||
u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid;
|
||||
u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid;
|
||||
|
||||
if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
|
||||
printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n",
|
||||
|
@ -359,9 +359,11 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
|
|||
: vcoreqfid - vcocurrfid;
|
||||
|
||||
while (vcofiddiff > 2) {
|
||||
(data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2);
|
||||
|
||||
if (reqfid > data->currfid) {
|
||||
if (data->currfid > LO_FID_TABLE_TOP) {
|
||||
if (write_new_fid(data, data->currfid + 2)) {
|
||||
if (write_new_fid(data, data->currfid + fid_interval)) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
|
@ -371,7 +373,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (write_new_fid(data, data->currfid - 2))
|
||||
if (write_new_fid(data, data->currfid - fid_interval))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -464,7 +466,7 @@ static int check_supported_cpu(unsigned int cpu)
|
|||
set_cpus_allowed(current, cpumask_of_cpu(cpu));
|
||||
|
||||
if (smp_processor_id() != cpu) {
|
||||
printk(KERN_ERR "limiting to cpu %u failed\n", cpu);
|
||||
printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -474,7 +476,7 @@ static int check_supported_cpu(unsigned int cpu)
|
|||
eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
|
||||
if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
|
||||
((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
|
||||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) {
|
||||
((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
|
||||
printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
|
||||
goto out;
|
||||
}
|
||||
|
@ -517,22 +519,24 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8
|
|||
printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j);
|
||||
return -ENODEV;
|
||||
}
|
||||
if ((pst[j].fid > MAX_FID)
|
||||
|| (pst[j].fid & 1)
|
||||
|| (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
|
||||
if (pst[j].fid > MAX_FID) {
|
||||
printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) {
|
||||
/* Only first fid is allowed to be in "low" range */
|
||||
printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
|
||||
printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (pst[j].fid < lastfid)
|
||||
lastfid = pst[j].fid;
|
||||
}
|
||||
if (lastfid & 1) {
|
||||
printk(KERN_ERR PFX "lastfid invalid\n");
|
||||
printk(KERN_ERR BFX "lastfid invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (lastfid > LO_FID_TABLE_TOP)
|
||||
printk(KERN_INFO PFX "first fid not from lo freq table\n");
|
||||
printk(KERN_INFO BFX "first fid not from lo freq table\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -631,7 +635,7 @@ static int find_psb_table(struct powernow_k8_data *data)
|
|||
|
||||
dprintk("table vers: 0x%x\n", psb->tableversion);
|
||||
if (psb->tableversion != PSB_VERSION_1_4) {
|
||||
printk(KERN_INFO BFX "PSB table is not v1.4\n");
|
||||
printk(KERN_ERR BFX "PSB table is not v1.4\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -689,7 +693,7 @@ static int find_psb_table(struct powernow_k8_data *data)
|
|||
* BIOS and Kernel Developer's Guide, which is available on
|
||||
* www.amd.com
|
||||
*/
|
||||
printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
|
||||
printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -912,7 +916,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
|
|||
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
|
||||
|
||||
if (smp_processor_id() != pol->cpu) {
|
||||
printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
|
||||
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
|
@ -982,6 +986,9 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
|||
cpumask_t oldmask = CPU_MASK_ALL;
|
||||
int rc, i;
|
||||
|
||||
if (!cpu_online(pol->cpu))
|
||||
return -ENODEV;
|
||||
|
||||
if (!check_supported_cpu(pol->cpu))
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -1021,7 +1028,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
|
|||
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
|
||||
|
||||
if (smp_processor_id() != pol->cpu) {
|
||||
printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu);
|
||||
printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
|
@ -1162,10 +1169,9 @@ static void __exit powernowk8_exit(void)
|
|||
cpufreq_unregister_driver(&cpufreq_amd64_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
|
||||
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com>");
|
||||
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
late_initcall(powernowk8_init);
|
||||
module_exit(powernowk8_exit);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ struct powernow_k8_data {
|
|||
#define CPUID_XFAM 0x0ff00000 /* extended family */
|
||||
#define CPUID_XFAM_K8 0
|
||||
#define CPUID_XMOD 0x000f0000 /* extended model */
|
||||
#define CPUID_XMOD_REV_F 0x00040000
|
||||
#define CPUID_XMOD_REV_G 0x00060000
|
||||
#define CPUID_USE_XFAM_XMOD 0x00000f00
|
||||
#define CPUID_GET_MAX_CAPABILITIES 0x80000000
|
||||
#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
|
||||
|
@ -86,13 +86,14 @@ struct powernow_k8_data {
|
|||
* low fid table
|
||||
* - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry
|
||||
* in the low fid table
|
||||
* - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid
|
||||
* - the parts can only step at <= 200 MHz intervals, odd fid values are
|
||||
* supported in revision G and later revisions.
|
||||
* - lowest frequency must be >= interprocessor hypertransport link speed
|
||||
* (only applies to MP systems obviously)
|
||||
*/
|
||||
|
||||
/* fids (frequency identifiers) are arranged in 2 tables - lo and hi */
|
||||
#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */
|
||||
#define LO_FID_TABLE_TOP 7 /* fid values marking the boundary */
|
||||
#define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */
|
||||
|
||||
#define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */
|
||||
|
@ -106,7 +107,7 @@ struct powernow_k8_data {
|
|||
#define MIN_FREQ 800 /* Min and max freqs, per spec */
|
||||
#define MAX_FREQ 5000
|
||||
|
||||
#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */
|
||||
#define INVALID_FID_MASK 0xffffffc0 /* not a valid fid if these bits are set */
|
||||
#define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */
|
||||
|
||||
#define VID_OFF 0x3f
|
||||
|
|
|
@ -40,6 +40,7 @@ static struct pci_dev *speedstep_chipset_dev;
|
|||
*/
|
||||
static unsigned int speedstep_processor = 0;
|
||||
|
||||
static u32 pmbase;
|
||||
|
||||
/*
|
||||
* There are only two frequency states for each processor. Values
|
||||
|
@ -55,6 +56,33 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
|
|||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-ich", msg)
|
||||
|
||||
|
||||
/**
|
||||
* speedstep_find_register - read the PMBASE address
|
||||
*
|
||||
* Returns: -ENODEV if no register could be found
|
||||
*/
|
||||
static int speedstep_find_register (void)
|
||||
{
|
||||
if (!speedstep_chipset_dev)
|
||||
return -ENODEV;
|
||||
|
||||
/* get PMBASE */
|
||||
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
|
||||
if (!(pmbase & 0x01)) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pmbase &= 0xFFFFFFFE;
|
||||
if (!pmbase) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dprintk("pmbase is 0x%x\n", pmbase);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* speedstep_set_state - set the SpeedStep state
|
||||
* @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH)
|
||||
|
@ -63,27 +91,13 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
|
|||
*/
|
||||
static void speedstep_set_state (unsigned int state)
|
||||
{
|
||||
u32 pmbase;
|
||||
u8 pm2_blk;
|
||||
u8 value;
|
||||
unsigned long flags;
|
||||
|
||||
if (!speedstep_chipset_dev || (state > 0x1))
|
||||
if (state > 0x1)
|
||||
return;
|
||||
|
||||
/* get PMBASE */
|
||||
pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase);
|
||||
if (!(pmbase & 0x01)) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pmbase &= 0xFFFFFFFE;
|
||||
if (!pmbase) {
|
||||
printk(KERN_ERR "speedstep-ich: could not find speedstep register\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable IRQs */
|
||||
local_irq_save(flags);
|
||||
|
||||
|
@ -315,10 +329,11 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
|
|||
cpus_allowed = current->cpus_allowed;
|
||||
set_cpus_allowed(current, policy->cpus);
|
||||
|
||||
/* detect low and high frequency */
|
||||
/* detect low and high frequency and transition latency */
|
||||
result = speedstep_get_freqs(speedstep_processor,
|
||||
&speedstep_freqs[SPEEDSTEP_LOW].frequency,
|
||||
&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
|
||||
&policy->cpuinfo.transition_latency,
|
||||
&speedstep_set_state);
|
||||
set_cpus_allowed(current, cpus_allowed);
|
||||
if (result)
|
||||
|
@ -335,7 +350,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
|
|||
|
||||
/* cpuinfo and default policy values */
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
|
||||
policy->cur = speed;
|
||||
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
|
||||
|
@ -400,6 +414,9 @@ static int __init speedstep_init(void)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (speedstep_find_register())
|
||||
return -ENODEV;
|
||||
|
||||
return cpufreq_register_driver(&speedstep_driver);
|
||||
}
|
||||
|
||||
|
|
|
@ -320,11 +320,13 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor);
|
|||
unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
unsigned int *low_speed,
|
||||
unsigned int *high_speed,
|
||||
unsigned int *transition_latency,
|
||||
void (*set_state) (unsigned int state))
|
||||
{
|
||||
unsigned int prev_speed;
|
||||
unsigned int ret = 0;
|
||||
unsigned long flags;
|
||||
struct timeval tv1, tv2;
|
||||
|
||||
if ((!processor) || (!low_speed) || (!high_speed) || (!set_state))
|
||||
return -EINVAL;
|
||||
|
@ -350,8 +352,17 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
|||
|
||||
dprintk("low speed is %u\n", *low_speed);
|
||||
|
||||
/* start latency measurement */
|
||||
if (transition_latency)
|
||||
do_gettimeofday(&tv1);
|
||||
|
||||
/* switch to high state */
|
||||
set_state(SPEEDSTEP_HIGH);
|
||||
|
||||
/* end latency measurement */
|
||||
if (transition_latency)
|
||||
do_gettimeofday(&tv2);
|
||||
|
||||
*high_speed = speedstep_get_processor_frequency(processor);
|
||||
if (!*high_speed) {
|
||||
ret = -EIO;
|
||||
|
@ -369,6 +380,25 @@ unsigned int speedstep_get_freqs(unsigned int processor,
|
|||
if (*high_speed != prev_speed)
|
||||
set_state(SPEEDSTEP_LOW);
|
||||
|
||||
if (transition_latency) {
|
||||
*transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC +
|
||||
tv2.tv_usec - tv1.tv_usec;
|
||||
dprintk("transition latency is %u uSec\n", *transition_latency);
|
||||
|
||||
/* convert uSec to nSec and add 20% for safety reasons */
|
||||
*transition_latency *= 1200;
|
||||
|
||||
/* check if the latency measurement is too high or too low
|
||||
* and set it to a safe value (500uSec) in that case
|
||||
*/
|
||||
if (*transition_latency > 10000000 || *transition_latency < 50000) {
|
||||
printk (KERN_WARNING "speedstep: frequency transition measured seems out of "
|
||||
"range (%u nSec), falling back to a safe one of %u nSec.\n",
|
||||
*transition_latency, 500000);
|
||||
*transition_latency = 500000;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
local_irq_restore(flags);
|
||||
return (ret);
|
||||
|
|
|
@ -44,4 +44,5 @@ extern unsigned int speedstep_get_processor_frequency(unsigned int processor);
|
|||
extern unsigned int speedstep_get_freqs(unsigned int processor,
|
||||
unsigned int *low_speed,
|
||||
unsigned int *high_speed,
|
||||
unsigned int *transition_latency,
|
||||
void (*set_state) (unsigned int state));
|
||||
|
|
|
@ -269,6 +269,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
|
|||
result = speedstep_get_freqs(speedstep_processor,
|
||||
&speedstep_freqs[SPEEDSTEP_LOW].frequency,
|
||||
&speedstep_freqs[SPEEDSTEP_HIGH].frequency,
|
||||
NULL,
|
||||
&speedstep_set_state);
|
||||
|
||||
if (result) {
|
||||
|
|
|
@ -342,6 +342,31 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle National Semiconductor branded processors
|
||||
*/
|
||||
static void __devinit init_nsc(struct cpuinfo_x86 *c)
|
||||
{
|
||||
/* There may be GX1 processors in the wild that are branded
|
||||
* NSC and not Cyrix.
|
||||
*
|
||||
* This function only handles the GX processor, and kicks every
|
||||
* thing else to the Cyrix init function above - that should
|
||||
* cover any processors that might have been branded differently
|
||||
* after NSC aquired Cyrix.
|
||||
*
|
||||
* If this breaks your GX1 horribly, please e-mail
|
||||
* info-linux@ldcmail.amd.com to tell us.
|
||||
*/
|
||||
|
||||
/* Handle the GX (Formally known as the GX2) */
|
||||
|
||||
if (c->x86 == 5 && c->x86_model == 5)
|
||||
display_cacheinfo(c);
|
||||
else
|
||||
init_cyrix(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
|
||||
* by the fact that they preserve the flags across the division of 5/2.
|
||||
|
@ -422,7 +447,7 @@ int __init cyrix_init_cpu(void)
|
|||
static struct cpu_dev nsc_cpu_dev __initdata = {
|
||||
.c_vendor = "NSC",
|
||||
.c_ident = { "Geode by NSC" },
|
||||
.c_init = init_cyrix,
|
||||
.c_init = init_nsc,
|
||||
.c_identify = generic_identify,
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
/*
|
||||
* Get CPU information for use by the procfs.
|
||||
|
@ -86,8 +87,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
seq_printf(m, "stepping\t: unknown\n");
|
||||
|
||||
if ( cpu_has(c, X86_FEATURE_TSC) ) {
|
||||
unsigned int freq = cpufreq_quick_get(n);
|
||||
if (!freq)
|
||||
freq = cpu_khz;
|
||||
seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
|
||||
cpu_khz / 1000, (cpu_khz % 1000));
|
||||
freq / 1000, (freq % 1000));
|
||||
}
|
||||
|
||||
/* Cache size */
|
||||
|
|
|
@ -117,14 +117,13 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
|
|||
{
|
||||
char __user *tmp = buf;
|
||||
u32 data[4];
|
||||
size_t rv;
|
||||
u32 reg = *ppos;
|
||||
int cpu = iminor(file->f_dentry->d_inode);
|
||||
|
||||
if (count % 16)
|
||||
return -EINVAL; /* Invalid chunk size */
|
||||
|
||||
for (rv = 0; count; count -= 16) {
|
||||
for (; count; count -= 16) {
|
||||
do_cpuid(cpu, reg, data);
|
||||
if (copy_to_user(tmp, &data, 16))
|
||||
return -EFAULT;
|
||||
|
|
|
@ -657,6 +657,7 @@ ENTRY(spurious_interrupt_bug)
|
|||
pushl $do_spurious_interrupt_bug
|
||||
jmp error_code
|
||||
|
||||
.section .rodata,"a"
|
||||
#include "syscall_table.S"
|
||||
|
||||
syscall_table_size=(.-sys_call_table)
|
||||
|
|
|
@ -504,19 +504,24 @@ ENTRY(cpu_gdt_table)
|
|||
.quad 0x0000000000000000 /* 0x80 TSS descriptor */
|
||||
.quad 0x0000000000000000 /* 0x88 LDT descriptor */
|
||||
|
||||
/* Segments used for calling PnP BIOS */
|
||||
.quad 0x00c09a0000000000 /* 0x90 32-bit code */
|
||||
.quad 0x00809a0000000000 /* 0x98 16-bit code */
|
||||
.quad 0x0080920000000000 /* 0xa0 16-bit data */
|
||||
.quad 0x0080920000000000 /* 0xa8 16-bit data */
|
||||
.quad 0x0080920000000000 /* 0xb0 16-bit data */
|
||||
/*
|
||||
* Segments used for calling PnP BIOS have byte granularity.
|
||||
* They code segments and data segments have fixed 64k limits,
|
||||
* the transfer segment sizes are set at run time.
|
||||
*/
|
||||
.quad 0x00409a000000ffff /* 0x90 32-bit code */
|
||||
.quad 0x00009a000000ffff /* 0x98 16-bit code */
|
||||
.quad 0x000092000000ffff /* 0xa0 16-bit data */
|
||||
.quad 0x0000920000000000 /* 0xa8 16-bit data */
|
||||
.quad 0x0000920000000000 /* 0xb0 16-bit data */
|
||||
|
||||
/*
|
||||
* The APM segments have byte granularity and their bases
|
||||
* and limits are set at run time.
|
||||
* are set at run time. All have 64k limits.
|
||||
*/
|
||||
.quad 0x00409a0000000000 /* 0xb8 APM CS code */
|
||||
.quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */
|
||||
.quad 0x0040920000000000 /* 0xc8 APM DS data */
|
||||
.quad 0x00409a000000ffff /* 0xb8 APM CS code */
|
||||
.quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
|
||||
.quad 0x004092000000ffff /* 0xc8 APM DS data */
|
||||
|
||||
.quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
|
||||
.quad 0x0000000000000000 /* 0xd8 - unused */
|
||||
|
@ -525,3 +530,5 @@ ENTRY(cpu_gdt_table)
|
|||
.quad 0x0000000000000000 /* 0xf0 - unused */
|
||||
.quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
|
||||
|
||||
/* Be sure this is zeroed to avoid false validations in Xen */
|
||||
.fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include <asm/checksum.h>
|
||||
#include <asm/desc.h>
|
||||
|
||||
/* This is definitely a GPL-only symbol */
|
||||
EXPORT_SYMBOL_GPL(cpu_gdt_table);
|
||||
EXPORT_SYMBOL_GPL(cpu_gdt_descr);
|
||||
|
||||
EXPORT_SYMBOL(__down_failed);
|
||||
EXPORT_SYMBOL(__down_failed_interruptible);
|
||||
|
|
|
@ -1722,8 +1722,8 @@ void disable_IO_APIC(void)
|
|||
entry.dest_mode = 0; /* Physical */
|
||||
entry.delivery_mode = dest_ExtINT; /* ExtInt */
|
||||
entry.vector = 0;
|
||||
entry.dest.physical.physical_dest = 0;
|
||||
|
||||
entry.dest.physical.physical_dest =
|
||||
GET_APIC_ID(apic_read(APIC_ID));
|
||||
|
||||
/*
|
||||
* Add it to the IO-APIC irq-routing table:
|
||||
|
|
|
@ -38,6 +38,12 @@
|
|||
int smp_found_config;
|
||||
unsigned int __initdata maxcpus = NR_CPUS;
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
#define CPU_HOTPLUG_ENABLED (1)
|
||||
#else
|
||||
#define CPU_HOTPLUG_ENABLED (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Various Linux-internal data structures created from the
|
||||
* MP-table.
|
||||
|
@ -219,14 +225,18 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
|
|||
cpu_set(num_processors, cpu_possible_map);
|
||||
num_processors++;
|
||||
|
||||
if ((num_processors > 8) &&
|
||||
((APIC_XAPIC(ver) &&
|
||||
(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) ||
|
||||
(boot_cpu_data.x86_vendor == X86_VENDOR_AMD)))
|
||||
def_to_bigsmp = 1;
|
||||
else
|
||||
if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
|
||||
switch (boot_cpu_data.x86_vendor) {
|
||||
case X86_VENDOR_INTEL:
|
||||
if (!APIC_XAPIC(ver)) {
|
||||
def_to_bigsmp = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
/* If P4 and above fall through */
|
||||
case X86_VENDOR_AMD:
|
||||
def_to_bigsmp = 1;
|
||||
}
|
||||
}
|
||||
bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,6 @@ static ssize_t msr_read(struct file *file, char __user * buf,
|
|||
{
|
||||
u32 __user *tmp = (u32 __user *) buf;
|
||||
u32 data[2];
|
||||
size_t rv;
|
||||
u32 reg = *ppos;
|
||||
int cpu = iminor(file->f_dentry->d_inode);
|
||||
int err;
|
||||
|
@ -180,7 +179,7 @@ static ssize_t msr_read(struct file *file, char __user * buf,
|
|||
if (count % 8)
|
||||
return -EINVAL; /* Invalid chunk size */
|
||||
|
||||
for (rv = 0; count; count -= 8) {
|
||||
for (; count; count -= 8) {
|
||||
err = do_rdmsr(cpu, reg, &data[0], &data[1]);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -308,9 +308,7 @@ void show_regs(struct pt_regs * regs)
|
|||
cr0 = read_cr0();
|
||||
cr2 = read_cr2();
|
||||
cr3 = read_cr3();
|
||||
if (current_cpu_data.x86 > 4) {
|
||||
cr4 = read_cr4();
|
||||
}
|
||||
cr4 = read_cr4_safe();
|
||||
printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
|
||||
show_trace(NULL, ®s->esp);
|
||||
}
|
||||
|
@ -404,17 +402,7 @@ void flush_thread(void)
|
|||
|
||||
void release_thread(struct task_struct *dead_task)
|
||||
{
|
||||
if (dead_task->mm) {
|
||||
// temporary debugging check
|
||||
if (dead_task->mm->context.size) {
|
||||
printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
|
||||
dead_task->comm,
|
||||
dead_task->mm->context.ldt,
|
||||
dead_task->mm->context.size);
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
BUG_ON(dead_task->mm);
|
||||
release_vm86_irqs(dead_task);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,9 +32,12 @@
|
|||
* in exit.c or in signal.c.
|
||||
*/
|
||||
|
||||
/* determines which flags the user has access to. */
|
||||
/* 1 = access 0 = no access */
|
||||
#define FLAG_MASK 0x00044dd5
|
||||
/*
|
||||
* Determines which flags the user has access to [1 = access, 0 = no access].
|
||||
* Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9).
|
||||
* Also masks reserved bits (31-22, 15, 5, 3, 1).
|
||||
*/
|
||||
#define FLAG_MASK 0x00054dd5
|
||||
|
||||
/* set's the trap flag. */
|
||||
#define TRAP_FLAG 0x100
|
||||
|
|
|
@ -111,12 +111,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
|
||||
},
|
||||
},
|
||||
{ /* Handle problems with rebooting on HP nc6120 */
|
||||
{ /* Handle problems with rebooting on HP laptops */
|
||||
.callback = set_bios_reboot,
|
||||
.ident = "HP Compaq nc6120",
|
||||
.ident = "HP Compaq Laptop",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
|
|
|
@ -954,6 +954,12 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init
|
||||
efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
|
||||
{
|
||||
memory_present(0, start, end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the highest page frame number we have available
|
||||
|
@ -965,6 +971,7 @@ void __init find_max_pfn(void)
|
|||
max_pfn = 0;
|
||||
if (efi_enabled) {
|
||||
efi_memmap_walk(efi_find_max_pfn, &max_pfn);
|
||||
efi_memmap_walk(efi_memory_present_wrapper, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -979,6 +986,7 @@ void __init find_max_pfn(void)
|
|||
continue;
|
||||
if (end > max_pfn)
|
||||
max_pfn = end;
|
||||
memory_present(0, start, end);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -903,6 +903,12 @@ static int __devinit do_boot_cpu(int apicid, int cpu)
|
|||
unsigned long start_eip;
|
||||
unsigned short nmi_high = 0, nmi_low = 0;
|
||||
|
||||
if (!cpu_gdt_descr[cpu].address &&
|
||||
!(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) {
|
||||
printk("Failed to allocate GDT for CPU %d\n", cpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
++cpucount;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
.data
|
||||
ENTRY(sys_call_table)
|
||||
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
|
||||
.long sys_exit
|
||||
|
|
|
@ -330,7 +330,9 @@ int recalibrate_cpu_khz(void)
|
|||
unsigned int cpu_khz_old = cpu_khz;
|
||||
|
||||
if (cpu_has_tsc) {
|
||||
local_irq_disable();
|
||||
init_cpu_khz();
|
||||
local_irq_enable();
|
||||
cpu_data[0].loops_per_jiffy =
|
||||
cpufreq_scale(cpu_data[0].loops_per_jiffy,
|
||||
cpu_khz_old,
|
||||
|
|
|
@ -306,14 +306,17 @@ void die(const char * str, struct pt_regs * regs, long err)
|
|||
.lock_owner_depth = 0
|
||||
};
|
||||
static int die_counter;
|
||||
unsigned long flags;
|
||||
|
||||
if (die.lock_owner != raw_smp_processor_id()) {
|
||||
console_verbose();
|
||||
spin_lock_irq(&die.lock);
|
||||
spin_lock_irqsave(&die.lock, flags);
|
||||
die.lock_owner = smp_processor_id();
|
||||
die.lock_owner_depth = 0;
|
||||
bust_spinlocks(1);
|
||||
}
|
||||
else
|
||||
local_save_flags(flags);
|
||||
|
||||
if (++die.lock_owner_depth < 3) {
|
||||
int nl = 0;
|
||||
|
@ -340,7 +343,7 @@ void die(const char * str, struct pt_regs * regs, long err)
|
|||
|
||||
bust_spinlocks(0);
|
||||
die.lock_owner = -1;
|
||||
spin_unlock_irq(&die.lock);
|
||||
spin_unlock_irqrestore(&die.lock, flags);
|
||||
|
||||
if (kexec_should_crash(current))
|
||||
crash_kexec(regs);
|
||||
|
@ -452,7 +455,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
|
|||
#endif
|
||||
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
|
||||
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
|
||||
DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
|
||||
DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip)
|
||||
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
|
||||
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
|
||||
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
|
||||
|
@ -1075,9 +1078,9 @@ void __init trap_init(void)
|
|||
set_trap_gate(0,÷_error);
|
||||
set_intr_gate(1,&debug);
|
||||
set_intr_gate(2,&nmi);
|
||||
set_system_intr_gate(3, &int3); /* int3-5 can be called from all */
|
||||
set_system_intr_gate(3, &int3); /* int3/4 can be called from all */
|
||||
set_system_gate(4,&overflow);
|
||||
set_system_gate(5,&bounds);
|
||||
set_trap_gate(5,&bounds);
|
||||
set_trap_gate(6,&invalid_op);
|
||||
set_trap_gate(7,&device_not_available);
|
||||
set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS);
|
||||
|
@ -1095,6 +1098,28 @@ void __init trap_init(void)
|
|||
#endif
|
||||
set_trap_gate(19,&simd_coprocessor_error);
|
||||
|
||||
if (cpu_has_fxsr) {
|
||||
/*
|
||||
* Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned.
|
||||
* Generates a compile-time "error: zero width for bit-field" if
|
||||
* the alignment is wrong.
|
||||
*/
|
||||
struct fxsrAlignAssert {
|
||||
int _:!(offsetof(struct task_struct,
|
||||
thread.i387.fxsave) & 15);
|
||||
};
|
||||
|
||||
printk(KERN_INFO "Enabling fast FPU save and restore... ");
|
||||
set_in_cr4(X86_CR4_OSFXSR);
|
||||
printk("done.\n");
|
||||
}
|
||||
if (cpu_has_xmm) {
|
||||
printk(KERN_INFO "Enabling unmasked SIMD FPU exception "
|
||||
"support... ");
|
||||
set_in_cr4(X86_CR4_OSXMMEXCPT);
|
||||
printk("done.\n");
|
||||
}
|
||||
|
||||
set_system_gate(SYSCALL_VECTOR,&system_call);
|
||||
|
||||
/*
|
||||
|
|
|
@ -735,6 +735,30 @@ void free_initmem(void)
|
|||
printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_RODATA
|
||||
|
||||
extern char __start_rodata, __end_rodata;
|
||||
void mark_rodata_ro(void)
|
||||
{
|
||||
unsigned long addr = (unsigned long)&__start_rodata;
|
||||
|
||||
for (; addr < (unsigned long)&__end_rodata; addr += PAGE_SIZE)
|
||||
change_page_attr(virt_to_page(addr), 1, PAGE_KERNEL_RO);
|
||||
|
||||
printk ("Write protecting the kernel read-only data: %luk\n",
|
||||
(unsigned long)(&__end_rodata - &__start_rodata) >> 10);
|
||||
|
||||
/*
|
||||
* change_page_attr() requires a global_flush_tlb() call after it.
|
||||
* We do this after the printk so that if something went wrong in the
|
||||
* change, the printk gets out at least to give a better debug hint
|
||||
* of who is the culprit.
|
||||
*/
|
||||
global_flush_tlb();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
void free_initrd_mem(unsigned long start, unsigned long end)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
static DEFINE_SPINLOCK(cpa_lock);
|
||||
static struct list_head df_list = LIST_HEAD_INIT(df_list);
|
||||
|
@ -36,7 +37,8 @@ pte_t *lookup_address(unsigned long address)
|
|||
return pte_offset_kernel(pmd, address);
|
||||
}
|
||||
|
||||
static struct page *split_large_page(unsigned long address, pgprot_t prot)
|
||||
static struct page *split_large_page(unsigned long address, pgprot_t prot,
|
||||
pgprot_t ref_prot)
|
||||
{
|
||||
int i;
|
||||
unsigned long addr;
|
||||
|
@ -54,7 +56,7 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot)
|
|||
pbase = (pte_t *)page_address(base);
|
||||
for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE) {
|
||||
set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT,
|
||||
addr == address ? prot : PAGE_KERNEL));
|
||||
addr == address ? prot : ref_prot));
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
@ -98,11 +100,18 @@ static void set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
|
|||
*/
|
||||
static inline void revert_page(struct page *kpte_page, unsigned long address)
|
||||
{
|
||||
pte_t *linear = (pte_t *)
|
||||
pgprot_t ref_prot;
|
||||
pte_t *linear;
|
||||
|
||||
ref_prot =
|
||||
((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
|
||||
? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE;
|
||||
|
||||
linear = (pte_t *)
|
||||
pmd_offset(pud_offset(pgd_offset_k(address), address), address);
|
||||
set_pmd_pte(linear, address,
|
||||
pfn_pte((__pa(address) & LARGE_PAGE_MASK) >> PAGE_SHIFT,
|
||||
PAGE_KERNEL_LARGE));
|
||||
ref_prot));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -123,10 +132,16 @@ __change_page_attr(struct page *page, pgprot_t prot)
|
|||
if ((pte_val(*kpte) & _PAGE_PSE) == 0) {
|
||||
set_pte_atomic(kpte, mk_pte(page, prot));
|
||||
} else {
|
||||
struct page *split = split_large_page(address, prot);
|
||||
pgprot_t ref_prot;
|
||||
struct page *split;
|
||||
|
||||
ref_prot =
|
||||
((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
|
||||
? PAGE_KERNEL_EXEC : PAGE_KERNEL;
|
||||
split = split_large_page(address, prot, ref_prot);
|
||||
if (!split)
|
||||
return -ENOMEM;
|
||||
set_pmd_pte(kpte,address,mk_pte(split, PAGE_KERNEL));
|
||||
set_pmd_pte(kpte,address,mk_pte(split, ref_prot));
|
||||
kpte_page = split;
|
||||
}
|
||||
get_page(kpte_page);
|
||||
|
|
|
@ -846,7 +846,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
|
|||
* reported by the device if possible.
|
||||
*/
|
||||
newirq = dev->irq;
|
||||
if (!((1 << newirq) & mask)) {
|
||||
if (newirq && !((1 << newirq) & mask)) {
|
||||
if ( pci_probe & PCI_USE_PIRQ_MASK) newirq = 0;
|
||||
else printk(KERN_WARNING "PCI: IRQ %i for device %s doesn't match PIRQ mask - try pci=usepirqmask\n", newirq, pci_name(dev));
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <linux/initrd.h>
|
||||
#include <linux/platform.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/cpufreq.h>
|
||||
|
||||
#include <asm/ia32.h>
|
||||
#include <asm/machvec.h>
|
||||
|
@ -517,6 +518,7 @@ show_cpuinfo (struct seq_file *m, void *v)
|
|||
char family[32], features[128], *cp, sep;
|
||||
struct cpuinfo_ia64 *c = v;
|
||||
unsigned long mask;
|
||||
unsigned long proc_freq;
|
||||
int i;
|
||||
|
||||
mask = c->features;
|
||||
|
@ -549,6 +551,10 @@ show_cpuinfo (struct seq_file *m, void *v)
|
|||
sprintf(cp, " 0x%lx", mask);
|
||||
}
|
||||
|
||||
proc_freq = cpufreq_quick_get(cpunum);
|
||||
if (!proc_freq)
|
||||
proc_freq = c->proc_freq / 1000;
|
||||
|
||||
seq_printf(m,
|
||||
"processor : %d\n"
|
||||
"vendor : %s\n"
|
||||
|
@ -565,7 +571,7 @@ show_cpuinfo (struct seq_file *m, void *v)
|
|||
"BogoMIPS : %lu.%02lu\n",
|
||||
cpunum, c->vendor, family, c->model, c->revision, c->archrev,
|
||||
features, c->ppn, c->number,
|
||||
c->proc_freq / 1000000, c->proc_freq % 1000000,
|
||||
proc_freq / 1000, proc_freq % 1000,
|
||||
c->itc_freq / 1000000, c->itc_freq % 1000000,
|
||||
lpj*HZ/500000, (lpj*HZ/5000) % 100);
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
|
@ -700,7 +700,7 @@ int ia64_pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
|
|||
*/
|
||||
int ia64_pci_legacy_write(struct pci_dev *bus, u16 port, u32 val, u8 size)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = size;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
|
|
|
@ -65,7 +65,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
|
|||
|
||||
}
|
||||
|
||||
static int tiocx_hotplug(struct device *dev, char **envp, int num_envp,
|
||||
static int tiocx_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
return -ENODEV;
|
||||
|
@ -79,7 +79,7 @@ static void tiocx_bus_release(struct device *dev)
|
|||
struct bus_type tiocx_bus_type = {
|
||||
.name = "tiocx",
|
||||
.match = tiocx_match,
|
||||
.hotplug = tiocx_hotplug,
|
||||
.uevent = tiocx_uevent,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -81,6 +81,12 @@ config PLAT_MAPPI2
|
|||
config PLAT_MAPPI3
|
||||
bool "Mappi-III(M3A-2170)"
|
||||
|
||||
config PLAT_M32104UT
|
||||
bool "M32104UT"
|
||||
help
|
||||
The M3T-M32104UT is an reference board based on uT-Engine
|
||||
specification. This board has a M32104 chip.
|
||||
|
||||
endchoice
|
||||
|
||||
choice
|
||||
|
@ -93,6 +99,10 @@ config CHIP_M32700
|
|||
config CHIP_M32102
|
||||
bool "M32102"
|
||||
|
||||
config CHIP_M32104
|
||||
bool "M32104"
|
||||
depends on PLAT_M32104UT
|
||||
|
||||
config CHIP_VDEC2
|
||||
bool "VDEC2"
|
||||
|
||||
|
@ -115,7 +125,7 @@ config TLB_ENTRIES
|
|||
|
||||
config ISA_M32R
|
||||
bool
|
||||
depends on CHIP_M32102
|
||||
depends on CHIP_M32102 || CHIP_M32104
|
||||
default y
|
||||
|
||||
config ISA_M32R2
|
||||
|
@ -140,6 +150,7 @@ config BUS_CLOCK
|
|||
default "50000000" if PLAT_MAPPI3
|
||||
default "50000000" if PLAT_M32700UT
|
||||
default "50000000" if PLAT_OPSPUT
|
||||
default "54000000" if PLAT_M32104UT
|
||||
default "33333333" if PLAT_OAKS32R
|
||||
default "20000000" if PLAT_MAPPI2
|
||||
|
||||
|
@ -157,6 +168,7 @@ config MEMORY_START
|
|||
default "08000000" if PLAT_USRV
|
||||
default "08000000" if PLAT_M32700UT
|
||||
default "08000000" if PLAT_OPSPUT
|
||||
default "04000000" if PLAT_M32104UT
|
||||
default "01000000" if PLAT_OAKS32R
|
||||
|
||||
config MEMORY_SIZE
|
||||
|
@ -166,6 +178,7 @@ config MEMORY_SIZE
|
|||
default "02000000" if PLAT_USRV
|
||||
default "01000000" if PLAT_M32700UT
|
||||
default "01000000" if PLAT_OPSPUT
|
||||
default "01000000" if PLAT_M32104UT
|
||||
default "00800000" if PLAT_OAKS32R
|
||||
|
||||
config NOHIGHMEM
|
||||
|
@ -174,21 +187,22 @@ config NOHIGHMEM
|
|||
|
||||
config ARCH_DISCONTIGMEM_ENABLE
|
||||
bool "Internal RAM Support"
|
||||
depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP
|
||||
depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104
|
||||
default y
|
||||
|
||||
source "mm/Kconfig"
|
||||
|
||||
config IRAM_START
|
||||
hex "Internal memory start address (hex)"
|
||||
default "00f00000"
|
||||
depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
|
||||
default "00f00000" if !CHIP_M32104
|
||||
default "00700000" if CHIP_M32104
|
||||
depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM
|
||||
|
||||
config IRAM_SIZE
|
||||
hex "Internal memory size (hex)"
|
||||
depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP) && DISCONTIGMEM
|
||||
depends on (CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP || CHIP_M32104) && DISCONTIGMEM
|
||||
default "00080000" if CHIP_M32700
|
||||
default "00010000" if CHIP_M32102 || CHIP_OPSP
|
||||
default "00010000" if CHIP_M32102 || CHIP_OPSP || CHIP_M32104
|
||||
default "00008000" if CHIP_VDEC2
|
||||
|
||||
#
|
||||
|
|
|
@ -143,6 +143,11 @@ startup:
|
|||
ldi r0, -2
|
||||
ldi r1, 0x0100 ; invalidate
|
||||
stb r1, @r0
|
||||
#elif defined(CONFIG_CHIP_M32104)
|
||||
/* Cache flush */
|
||||
ldi r0, -2
|
||||
ldi r1, 0x0700 ; invalidate i-cache, copy back d-cache
|
||||
sth r1, @r0
|
||||
#else
|
||||
#error "put your cache flush function, please"
|
||||
#endif
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
* linux/arch/m32r/boot/setup.S -- A setup code.
|
||||
*
|
||||
* Copyright (C) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* and Hitoshi Yamamoto
|
||||
* Copyright (C) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Hayato Fujiwara
|
||||
*
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/segment.h>
|
||||
|
@ -80,6 +79,20 @@ ENTRY(boot)
|
|||
ldi r1, #0x101 ; cache on (with invalidation)
|
||||
; ldi r1, #0x00 ; cache off
|
||||
st r1, @r0
|
||||
#elif defined(CONFIG_CHIP_M32104)
|
||||
ldi r0, #-96 ; DNCR0
|
||||
seth r1, #0x0060 ; from 0x00600000
|
||||
or3 r1, r1, #0x0005 ; size 2MB
|
||||
st r1, @r0
|
||||
seth r1, #0x0100 ; from 0x01000000
|
||||
or3 r1, r1, #0x0003 ; size 16MB
|
||||
st r1, @+r0
|
||||
seth r1, #0x0200 ; from 0x02000000
|
||||
or3 r1, r1, #0x0002 ; size 32MB
|
||||
st r1, @+r0
|
||||
ldi r0, #-4 ;LDIMM (r0, M32R_MCCR)
|
||||
ldi r1, #0x703 ; cache on (with invalidation)
|
||||
st r1, @r0
|
||||
#else
|
||||
#error unknown chip configuration
|
||||
#endif
|
||||
|
@ -115,10 +128,15 @@ mmu_on:
|
|||
st r1, @(MATM_offset,r0) ; Set MATM (T bit ON)
|
||||
ld r0, @(MATM_offset,r0) ; Check
|
||||
#else
|
||||
#if defined(CONFIG_CHIP_M32700)
|
||||
seth r0,#high(M32R_MCDCAR)
|
||||
or3 r0,r0,#low(M32R_MCDCAR)
|
||||
ld24 r1,#0x8080
|
||||
st r1,@r0
|
||||
#elif defined(CONFIG_CHIP_M32104)
|
||||
LDIMM (r2, eit_vector) ; set EVB(cr5)
|
||||
mvtc r2, cr5
|
||||
#endif
|
||||
#endif /* CONFIG_MMU */
|
||||
jmp r13
|
||||
nop
|
||||
|
|
|
@ -16,5 +16,6 @@ obj-$(CONFIG_PLAT_M32700UT) += setup_m32700ut.o io_m32700ut.o
|
|||
obj-$(CONFIG_PLAT_OPSPUT) += setup_opsput.o io_opsput.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
obj-$(CONFIG_PLAT_OAKS32R) += setup_oaks32r.o io_oaks32r.o
|
||||
obj-$(CONFIG_PLAT_M32104UT) += setup_m32104ut.o io_m32104ut.o
|
||||
|
||||
EXTRA_AFLAGS := -traditional
|
||||
|
|
|
@ -315,7 +315,7 @@ ENTRY(ei_handler)
|
|||
mv r1, sp ; arg1(regs)
|
||||
#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
|
||||
|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
|
||||
|| defined(CONFIG_CHIP_OPSP)
|
||||
|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
|
||||
|
||||
; GET_ICU_STATUS;
|
||||
seth r0, #shigh(M32R_ICU_ISTS_ADDR)
|
||||
|
@ -541,7 +541,20 @@ check_int2:
|
|||
bra check_end
|
||||
.fillinsn
|
||||
check_end:
|
||||
#endif /* CONFIG_PLAT_OPSPUT */
|
||||
#elif defined(CONFIG_PLAT_M32104UT)
|
||||
add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
|
||||
bnez r2, check_end
|
||||
; read ICU status register of PLD
|
||||
seth r0, #high(PLD_ICUISTS)
|
||||
or3 r0, r0, #low(PLD_ICUISTS)
|
||||
lduh r0, @r0
|
||||
slli r0, #21
|
||||
srli r0, #27 ; ISN
|
||||
addi r0, #(M32104UT_PLD_IRQ_BASE)
|
||||
bra check_end
|
||||
.fillinsn
|
||||
check_end:
|
||||
#endif /* CONFIG_PLAT_M32104UT */
|
||||
bl do_IRQ
|
||||
#endif /* CONFIG_SMP */
|
||||
ld r14, @sp+
|
||||
|
@ -651,8 +664,6 @@ ENTRY(rie_handler)
|
|||
/* void rie_handler(int error_code) */
|
||||
SWITCH_TO_KERNEL_STACK
|
||||
SAVE_ALL
|
||||
mvfc r0, bpc
|
||||
ld r1, @r0
|
||||
ldi r1, #0x20 ; error_code
|
||||
mv r0, sp ; pt_regs
|
||||
bl do_rie_handler
|
||||
|
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* linux/arch/m32r/kernel/io_m32104ut.c
|
||||
*
|
||||
* Typical I/O routines for M32104UT board.
|
||||
*
|
||||
* Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa,
|
||||
* Naoto Sugai, Hayato Fujiwara
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <asm/m32r.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
|
||||
#include <linux/types.h>
|
||||
|
||||
#define M32R_PCC_IOMAP_SIZE 0x1000
|
||||
|
||||
#define M32R_PCC_IOSTART0 0x1000
|
||||
#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
|
||||
|
||||
extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
|
||||
extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
|
||||
extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
|
||||
extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
|
||||
#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
|
||||
|
||||
#define PORT2ADDR(port) _port2addr(port)
|
||||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
|
||||
static inline void *__port2addr_ata(unsigned long port)
|
||||
{
|
||||
static int dummy_reg;
|
||||
|
||||
switch (port) {
|
||||
case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
|
||||
case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
|
||||
case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
|
||||
case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
|
||||
case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
|
||||
case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
|
||||
case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
|
||||
case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
|
||||
case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
|
||||
default: return (void *)&dummy_reg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* M32104T-LAN is located in the extended bus space
|
||||
* from 0x01000000 to 0x01ffffff on physical address.
|
||||
* The base address of LAN controller(LAN91C111) is 0x300.
|
||||
*/
|
||||
#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
|
||||
#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
{
|
||||
return (void *)(port + NONCACHE_OFFSET + 0x01000000);
|
||||
}
|
||||
|
||||
static inline void delay(void)
|
||||
{
|
||||
__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* NIC I/O function
|
||||
*/
|
||||
|
||||
#define PORT2ADDR_NE(port) _port2addr_ne(port)
|
||||
|
||||
static inline unsigned char _ne_inb(void *portp)
|
||||
{
|
||||
return *(volatile unsigned char *)portp;
|
||||
}
|
||||
|
||||
static inline unsigned short _ne_inw(void *portp)
|
||||
{
|
||||
return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
|
||||
}
|
||||
|
||||
static inline void _ne_insb(void *portp, void *addr, unsigned long count)
|
||||
{
|
||||
unsigned char *buf = (unsigned char *)addr;
|
||||
|
||||
while (count--)
|
||||
*buf++ = _ne_inb(portp);
|
||||
}
|
||||
|
||||
static inline void _ne_outb(unsigned char b, void *portp)
|
||||
{
|
||||
*(volatile unsigned char *)portp = b;
|
||||
}
|
||||
|
||||
static inline void _ne_outw(unsigned short w, void *portp)
|
||||
{
|
||||
*(volatile unsigned short *)portp = cpu_to_le16(w);
|
||||
}
|
||||
|
||||
unsigned char _inb(unsigned long port)
|
||||
{
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND)
|
||||
return _ne_inb(PORT2ADDR_NE(port));
|
||||
|
||||
return *(volatile unsigned char *)PORT2ADDR(port);
|
||||
}
|
||||
|
||||
unsigned short _inw(unsigned long port)
|
||||
{
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND)
|
||||
return _ne_inw(PORT2ADDR_NE(port));
|
||||
|
||||
return *(volatile unsigned short *)PORT2ADDR(port);
|
||||
}
|
||||
|
||||
unsigned long _inl(unsigned long port)
|
||||
{
|
||||
return *(volatile unsigned long *)PORT2ADDR(port);
|
||||
}
|
||||
|
||||
unsigned char _inb_p(unsigned long port)
|
||||
{
|
||||
unsigned char v = _inb(port);
|
||||
delay();
|
||||
return (v);
|
||||
}
|
||||
|
||||
unsigned short _inw_p(unsigned long port)
|
||||
{
|
||||
unsigned short v = _inw(port);
|
||||
delay();
|
||||
return (v);
|
||||
}
|
||||
|
||||
unsigned long _inl_p(unsigned long port)
|
||||
{
|
||||
unsigned long v = _inl(port);
|
||||
delay();
|
||||
return (v);
|
||||
}
|
||||
|
||||
void _outb(unsigned char b, unsigned long port)
|
||||
{
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND)
|
||||
_ne_outb(b, PORT2ADDR_NE(port));
|
||||
else
|
||||
*(volatile unsigned char *)PORT2ADDR(port) = b;
|
||||
}
|
||||
|
||||
void _outw(unsigned short w, unsigned long port)
|
||||
{
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND)
|
||||
_ne_outw(w, PORT2ADDR_NE(port));
|
||||
else
|
||||
*(volatile unsigned short *)PORT2ADDR(port) = w;
|
||||
}
|
||||
|
||||
void _outl(unsigned long l, unsigned long port)
|
||||
{
|
||||
*(volatile unsigned long *)PORT2ADDR(port) = l;
|
||||
}
|
||||
|
||||
void _outb_p(unsigned char b, unsigned long port)
|
||||
{
|
||||
_outb(b, port);
|
||||
delay();
|
||||
}
|
||||
|
||||
void _outw_p(unsigned short w, unsigned long port)
|
||||
{
|
||||
_outw(w, port);
|
||||
delay();
|
||||
}
|
||||
|
||||
void _outl_p(unsigned long l, unsigned long port)
|
||||
{
|
||||
_outl(l, port);
|
||||
delay();
|
||||
}
|
||||
|
||||
void _insb(unsigned int port, void *addr, unsigned long count)
|
||||
{
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND)
|
||||
_ne_insb(PORT2ADDR_NE(port), addr, count);
|
||||
else {
|
||||
unsigned char *buf = addr;
|
||||
unsigned char *portp = PORT2ADDR(port);
|
||||
while (count--)
|
||||
*buf++ = *(volatile unsigned char *)portp;
|
||||
}
|
||||
}
|
||||
|
||||
void _insw(unsigned int port, void *addr, unsigned long count)
|
||||
{
|
||||
unsigned short *buf = addr;
|
||||
unsigned short *portp;
|
||||
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND) {
|
||||
/*
|
||||
* This portion is only used by smc91111.c to read data
|
||||
* from the DATA_REG. Do not swap the data.
|
||||
*/
|
||||
portp = PORT2ADDR_NE(port);
|
||||
while (count--)
|
||||
*buf++ = *(volatile unsigned short *)portp;
|
||||
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
|
||||
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
|
||||
pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
|
||||
count, 1);
|
||||
#endif
|
||||
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
|
||||
} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
|
||||
portp = __port2addr_ata(port);
|
||||
while (count--)
|
||||
*buf++ = *(volatile unsigned short *)portp;
|
||||
#endif
|
||||
} else {
|
||||
portp = PORT2ADDR(port);
|
||||
while (count--)
|
||||
*buf++ = *(volatile unsigned short *)portp;
|
||||
}
|
||||
}
|
||||
|
||||
void _insl(unsigned int port, void *addr, unsigned long count)
|
||||
{
|
||||
unsigned long *buf = addr;
|
||||
unsigned long *portp;
|
||||
|
||||
portp = PORT2ADDR(port);
|
||||
while (count--)
|
||||
*buf++ = *(volatile unsigned long *)portp;
|
||||
}
|
||||
|
||||
void _outsb(unsigned int port, const void *addr, unsigned long count)
|
||||
{
|
||||
const unsigned char *buf = addr;
|
||||
unsigned char *portp;
|
||||
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND) {
|
||||
portp = PORT2ADDR_NE(port);
|
||||
while (count--)
|
||||
_ne_outb(*buf++, portp);
|
||||
} else {
|
||||
portp = PORT2ADDR(port);
|
||||
while (count--)
|
||||
*(volatile unsigned char *)portp = *buf++;
|
||||
}
|
||||
}
|
||||
|
||||
void _outsw(unsigned int port, const void *addr, unsigned long count)
|
||||
{
|
||||
const unsigned short *buf = addr;
|
||||
unsigned short *portp;
|
||||
|
||||
if (port >= LAN_IOSTART && port < LAN_IOEND) {
|
||||
/*
|
||||
* This portion is only used by smc91111.c to write data
|
||||
* into the DATA_REG. Do not swap the data.
|
||||
*/
|
||||
portp = PORT2ADDR_NE(port);
|
||||
while (count--)
|
||||
*(volatile unsigned short *)portp = *buf++;
|
||||
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
|
||||
} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
|
||||
portp = __port2addr_ata(port);
|
||||
while (count--)
|
||||
*(volatile unsigned short *)portp = *buf++;
|
||||
#endif
|
||||
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
|
||||
} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
|
||||
pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
|
||||
count, 1);
|
||||
#endif
|
||||
} else {
|
||||
portp = PORT2ADDR(port);
|
||||
while (count--)
|
||||
*(volatile unsigned short *)portp = *buf++;
|
||||
}
|
||||
}
|
||||
|
||||
void _outsl(unsigned int port, const void *addr, unsigned long count)
|
||||
{
|
||||
const unsigned long *buf = addr;
|
||||
unsigned char *portp;
|
||||
|
||||
portp = PORT2ADDR(port);
|
||||
while (count--)
|
||||
*(volatile unsigned long *)portp = *buf++;
|
||||
}
|
|
@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
|
|||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port + NONCACHE_OFFSET);
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
|
||||
|
@ -45,15 +45,15 @@ static inline void *__port2addr_ata(unsigned long port)
|
|||
static int dummy_reg;
|
||||
|
||||
switch (port) {
|
||||
case 0x1f0: return (void *)0xac002000;
|
||||
case 0x1f1: return (void *)0xac012800;
|
||||
case 0x1f2: return (void *)0xac012002;
|
||||
case 0x1f3: return (void *)0xac012802;
|
||||
case 0x1f4: return (void *)0xac012004;
|
||||
case 0x1f5: return (void *)0xac012804;
|
||||
case 0x1f6: return (void *)0xac012006;
|
||||
case 0x1f7: return (void *)0xac012806;
|
||||
case 0x3f6: return (void *)0xac01200e;
|
||||
case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
|
||||
case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
|
||||
case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
|
||||
case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
|
||||
case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
|
||||
case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
|
||||
case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
|
||||
case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
|
||||
case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
|
||||
default: return (void *)&dummy_reg;
|
||||
}
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ static inline void *__port2addr_ata(unsigned long port)
|
|||
* from 0x10000000 to 0x13ffffff on physical address.
|
||||
* The base address of LAN controller(LAN91C111) is 0x300.
|
||||
*/
|
||||
#define LAN_IOSTART 0xa0000300
|
||||
#define LAN_IOEND 0xa0000320
|
||||
#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
|
||||
#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
{
|
||||
return (void *)(port + 0x10000000);
|
||||
|
|
|
@ -31,7 +31,7 @@ extern void pcc_iowrite(int, unsigned long, void *, size_t, size_t, int);
|
|||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port | (NONCACHE_OFFSET));
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
|
|
|
@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
|
|||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port | (NONCACHE_OFFSET));
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
|
||||
|
@ -42,22 +42,22 @@ static inline void *__port2addr_ata(unsigned long port)
|
|||
static int dummy_reg;
|
||||
|
||||
switch (port) {
|
||||
case 0x1f0: return (void *)0xac002000;
|
||||
case 0x1f1: return (void *)0xac012800;
|
||||
case 0x1f2: return (void *)0xac012002;
|
||||
case 0x1f3: return (void *)0xac012802;
|
||||
case 0x1f4: return (void *)0xac012004;
|
||||
case 0x1f5: return (void *)0xac012804;
|
||||
case 0x1f6: return (void *)0xac012006;
|
||||
case 0x1f7: return (void *)0xac012806;
|
||||
case 0x3f6: return (void *)0xac01200e;
|
||||
case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);
|
||||
case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);
|
||||
case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);
|
||||
case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);
|
||||
case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);
|
||||
case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);
|
||||
case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);
|
||||
case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);
|
||||
case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);
|
||||
default: return (void *)&dummy_reg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define LAN_IOSTART 0xa0000300
|
||||
#define LAN_IOEND 0xa0000320
|
||||
#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
|
||||
#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
|
||||
#ifdef CONFIG_CHIP_OPSP
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
|
|||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port + NONCACHE_OFFSET);
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IDE)
|
||||
|
@ -43,33 +43,42 @@ static inline void *__port2addr_ata(unsigned long port)
|
|||
|
||||
switch (port) {
|
||||
/* IDE0 CF */
|
||||
case 0x1f0: return (void *)0xb4002000;
|
||||
case 0x1f1: return (void *)0xb4012800;
|
||||
case 0x1f2: return (void *)0xb4012002;
|
||||
case 0x1f3: return (void *)0xb4012802;
|
||||
case 0x1f4: return (void *)0xb4012004;
|
||||
case 0x1f5: return (void *)0xb4012804;
|
||||
case 0x1f6: return (void *)0xb4012006;
|
||||
case 0x1f7: return (void *)0xb4012806;
|
||||
case 0x3f6: return (void *)0xb401200e;
|
||||
case 0x1f0: return (void *)(0x14002000 | NONCACHE_OFFSET);
|
||||
case 0x1f1: return (void *)(0x14012800 | NONCACHE_OFFSET);
|
||||
case 0x1f2: return (void *)(0x14012002 | NONCACHE_OFFSET);
|
||||
case 0x1f3: return (void *)(0x14012802 | NONCACHE_OFFSET);
|
||||
case 0x1f4: return (void *)(0x14012004 | NONCACHE_OFFSET);
|
||||
case 0x1f5: return (void *)(0x14012804 | NONCACHE_OFFSET);
|
||||
case 0x1f6: return (void *)(0x14012006 | NONCACHE_OFFSET);
|
||||
case 0x1f7: return (void *)(0x14012806 | NONCACHE_OFFSET);
|
||||
case 0x3f6: return (void *)(0x1401200e | NONCACHE_OFFSET);
|
||||
/* IDE1 IDE */
|
||||
case 0x170: return (void *)0xb4810000; /* Data 16bit */
|
||||
case 0x171: return (void *)0xb4810002; /* Features / Error */
|
||||
case 0x172: return (void *)0xb4810004; /* Sector count */
|
||||
case 0x173: return (void *)0xb4810006; /* Sector number */
|
||||
case 0x174: return (void *)0xb4810008; /* Cylinder low */
|
||||
case 0x175: return (void *)0xb481000a; /* Cylinder high */
|
||||
case 0x176: return (void *)0xb481000c; /* Device head */
|
||||
case 0x177: return (void *)0xb481000e; /* Command */
|
||||
case 0x376: return (void *)0xb480800c; /* Device control / Alt status */
|
||||
case 0x170: /* Data 16bit */
|
||||
return (void *)(0x14810000 | NONCACHE_OFFSET);
|
||||
case 0x171: /* Features / Error */
|
||||
return (void *)(0x14810002 | NONCACHE_OFFSET);
|
||||
case 0x172: /* Sector count */
|
||||
return (void *)(0x14810004 | NONCACHE_OFFSET);
|
||||
case 0x173: /* Sector number */
|
||||
return (void *)(0x14810006 | NONCACHE_OFFSET);
|
||||
case 0x174: /* Cylinder low */
|
||||
return (void *)(0x14810008 | NONCACHE_OFFSET);
|
||||
case 0x175: /* Cylinder high */
|
||||
return (void *)(0x1481000a | NONCACHE_OFFSET);
|
||||
case 0x176: /* Device head */
|
||||
return (void *)(0x1481000c | NONCACHE_OFFSET);
|
||||
case 0x177: /* Command */
|
||||
return (void *)(0x1481000e | NONCACHE_OFFSET);
|
||||
case 0x376: /* Device control / Alt status */
|
||||
return (void *)(0x1480800c | NONCACHE_OFFSET);
|
||||
|
||||
default: return (void *)&dummy_reg;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define LAN_IOSTART 0xa0000300
|
||||
#define LAN_IOEND 0xa0000320
|
||||
#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
|
||||
#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
{
|
||||
return (void *)(port + 0x10000000);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port | (NONCACHE_OFFSET));
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
|
|
|
@ -36,7 +36,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
|
|||
|
||||
static inline void *_port2addr(unsigned long port)
|
||||
{
|
||||
return (void *)(port | (NONCACHE_OFFSET));
|
||||
return (void *)(port | NONCACHE_OFFSET);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -44,8 +44,8 @@ static inline void *_port2addr(unsigned long port)
|
|||
* from 0x10000000 to 0x13ffffff on physical address.
|
||||
* The base address of LAN controller(LAN91C111) is 0x300.
|
||||
*/
|
||||
#define LAN_IOSTART 0xa0000300
|
||||
#define LAN_IOEND 0xa0000320
|
||||
#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)
|
||||
#define LAN_IOEND (0x320 | NONCACHE_OFFSET)
|
||||
static inline void *_port2addr_ne(unsigned long port)
|
||||
{
|
||||
return (void *)(port + 0x10000000);
|
||||
|
|
|
@ -320,6 +320,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
#elif defined(CONFIG_CHIP_MP)
|
||||
seq_printf(m, "cpu family\t: M32R-MP\n"
|
||||
"cache size\t: I-xxKB/D-xxKB\n");
|
||||
#elif defined(CONFIG_CHIP_M32104)
|
||||
seq_printf(m,"cpu family\t: M32104\n"
|
||||
"cache size\t: I-8KB/D-8KB\n");
|
||||
#else
|
||||
seq_printf(m, "cpu family\t: Unknown\n");
|
||||
#endif
|
||||
|
@ -340,6 +343,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
|
|||
seq_printf(m, "Machine\t\t: uServer\n");
|
||||
#elif defined(CONFIG_PLAT_OAKS32R)
|
||||
seq_printf(m, "Machine\t\t: OAKS32R\n");
|
||||
#elif defined(CONFIG_PLAT_M32104UT)
|
||||
seq_printf(m, "Machine\t\t: M3T-M32104UT uT Engine board\n");
|
||||
#else
|
||||
seq_printf(m, "Machine\t\t: Unknown\n");
|
||||
#endif
|
||||
|
@ -389,7 +394,7 @@ unsigned long cpu_initialized __initdata = 0;
|
|||
*/
|
||||
#if defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_XNUX2) \
|
||||
|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
|
||||
|| defined(CONFIG_CHIP_OPSP)
|
||||
|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
|
||||
void __init cpu_init (void)
|
||||
{
|
||||
int cpu_id = smp_processor_id();
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* linux/arch/m32r/kernel/setup_m32104ut.c
|
||||
*
|
||||
* Setup routines for M32104UT Board
|
||||
*
|
||||
* Copyright (c) 2002-2005 Hiroyuki Kondo, Hirokazu Takata,
|
||||
* Hitoshi Yamamoto, Mamoru Sakugawa,
|
||||
* Naoto Sugai, Hayato Fujiwara
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/m32r.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
|
||||
|
||||
icu_data_t icu_data[NR_IRQS];
|
||||
|
||||
static void disable_m32104ut_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long port, data;
|
||||
|
||||
port = irq2port(irq);
|
||||
data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
|
||||
outl(data, port);
|
||||
}
|
||||
|
||||
static void enable_m32104ut_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long port, data;
|
||||
|
||||
port = irq2port(irq);
|
||||
data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
|
||||
outl(data, port);
|
||||
}
|
||||
|
||||
static void mask_and_ack_m32104ut(unsigned int irq)
|
||||
{
|
||||
disable_m32104ut_irq(irq);
|
||||
}
|
||||
|
||||
static void end_m32104ut_irq(unsigned int irq)
|
||||
{
|
||||
enable_m32104ut_irq(irq);
|
||||
}
|
||||
|
||||
static unsigned int startup_m32104ut_irq(unsigned int irq)
|
||||
{
|
||||
enable_m32104ut_irq(irq);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void shutdown_m32104ut_irq(unsigned int irq)
|
||||
{
|
||||
unsigned long port;
|
||||
|
||||
port = irq2port(irq);
|
||||
outl(M32R_ICUCR_ILEVEL7, port);
|
||||
}
|
||||
|
||||
static struct hw_interrupt_type m32104ut_irq_type =
|
||||
{
|
||||
.typename = "M32104UT-IRQ",
|
||||
.startup = startup_m32104ut_irq,
|
||||
.shutdown = shutdown_m32104ut_irq,
|
||||
.enable = enable_m32104ut_irq,
|
||||
.disable = disable_m32104ut_irq,
|
||||
.ack = mask_and_ack_m32104ut,
|
||||
.end = end_m32104ut_irq
|
||||
};
|
||||
|
||||
void __init init_IRQ(void)
|
||||
{
|
||||
static int once = 0;
|
||||
|
||||
if (once)
|
||||
return;
|
||||
else
|
||||
once++;
|
||||
|
||||
#if defined(CONFIG_SMC91X)
|
||||
/* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/
|
||||
irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
|
||||
irq_desc[M32R_IRQ_INT0].handler = &m32104ut_irq_type;
|
||||
irq_desc[M32R_IRQ_INT0].action = 0;
|
||||
irq_desc[M32R_IRQ_INT0].depth = 1;
|
||||
icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11; /* "H" level sense */
|
||||
disable_m32104ut_irq(M32R_IRQ_INT0);
|
||||
#endif /* CONFIG_SMC91X */
|
||||
|
||||
/* MFT2 : system timer */
|
||||
irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
|
||||
irq_desc[M32R_IRQ_MFT2].handler = &m32104ut_irq_type;
|
||||
irq_desc[M32R_IRQ_MFT2].action = 0;
|
||||
irq_desc[M32R_IRQ_MFT2].depth = 1;
|
||||
icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
|
||||
disable_m32104ut_irq(M32R_IRQ_MFT2);
|
||||
|
||||
#ifdef CONFIG_SERIAL_M32R_SIO
|
||||
/* SIO0_R : uart receive data */
|
||||
irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
|
||||
irq_desc[M32R_IRQ_SIO0_R].handler = &m32104ut_irq_type;
|
||||
irq_desc[M32R_IRQ_SIO0_R].action = 0;
|
||||
irq_desc[M32R_IRQ_SIO0_R].depth = 1;
|
||||
icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN;
|
||||
disable_m32104ut_irq(M32R_IRQ_SIO0_R);
|
||||
|
||||
/* SIO0_S : uart send data */
|
||||
irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
|
||||
irq_desc[M32R_IRQ_SIO0_S].handler = &m32104ut_irq_type;
|
||||
irq_desc[M32R_IRQ_SIO0_S].action = 0;
|
||||
irq_desc[M32R_IRQ_SIO0_S].depth = 1;
|
||||
icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN;
|
||||
disable_m32104ut_irq(M32R_IRQ_SIO0_S);
|
||||
#endif /* CONFIG_SERIAL_M32R_SIO */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SMC91X)
|
||||
|
||||
#define LAN_IOSTART 0x300
|
||||
#define LAN_IOEND 0x320
|
||||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = (LAN_IOSTART),
|
||||
.end = (LAN_IOEND),
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = M32R_IRQ_INT0,
|
||||
.end = M32R_IRQ_INT0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device smc91x_device = {
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(smc91x_resources),
|
||||
.resource = smc91x_resources,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init platform_init(void)
|
||||
{
|
||||
#if defined(CONFIG_SMC91X)
|
||||
platform_device_register(&smc91x_device);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(platform_init);
|
|
@ -26,15 +26,7 @@
|
|||
*/
|
||||
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
typedef struct {
|
||||
unsigned long icucr; /* ICU Control Register */
|
||||
} icu_data_t;
|
||||
static icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
|
||||
#else
|
||||
icu_data_t icu_data[M32700UT_NUM_CPU_IRQ];
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
||||
static void disable_m32700ut_irq(unsigned int irq)
|
||||
{
|
||||
|
|
|
@ -19,12 +19,6 @@
|
|||
|
||||
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
typedef struct {
|
||||
unsigned long icucr; /* ICU Control Register */
|
||||
} icu_data_t;
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
icu_data_t icu_data[NR_IRQS];
|
||||
|
||||
static void disable_mappi_irq(unsigned int irq)
|
||||
|
|
|
@ -19,12 +19,6 @@
|
|||
|
||||
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
typedef struct {
|
||||
unsigned long icucr; /* ICU Control Register */
|
||||
} icu_data_t;
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
icu_data_t icu_data[NR_IRQS];
|
||||
|
||||
static void disable_mappi2_irq(unsigned int irq)
|
||||
|
|
|
@ -19,12 +19,6 @@
|
|||
|
||||
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
typedef struct {
|
||||
unsigned long icucr; /* ICU Control Register */
|
||||
} icu_data_t;
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
icu_data_t icu_data[NR_IRQS];
|
||||
|
||||
static void disable_mappi3_irq(unsigned int irq)
|
||||
|
|
|
@ -18,12 +18,6 @@
|
|||
|
||||
#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
|
||||
|
||||
#ifndef CONFIG_SMP
|
||||
typedef struct {
|
||||
unsigned long icucr; /* ICU Control Register */
|
||||
} icu_data_t;
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
icu_data_t icu_data[NR_IRQS];
|
||||
|
||||
static void disable_oaks32r_irq(unsigned int irq)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue