Merge branch 'master'

This commit is contained in:
Jeff Garzik 2005-11-18 19:54:12 -05:00
commit 625876f32e
56 changed files with 1323 additions and 1141 deletions

12
CREDITS
View File

@ -611,8 +611,7 @@ S: USA
N: Randolph Chung
E: tausq@debian.org
D: Linux/PA-RISC hacker
S: Los Altos, CA 94022
S: USA
S: Hong Kong
N: Juan Jose Ciarlante
W: http://juanjox.kernelnotes.org/
@ -3405,6 +3404,15 @@ S: Chudenicka 8
S: 10200 Prague 10, Hostivar
S: Czech Republic
N: Thibaut Varene
E: T-Bone@parisc-linux.org
W: http://www.parisc-linux.org/
P: 1024D/B7D2F063 E67C 0D43 A75E 12A5 BB1C FA2F 1E32 C3DA B7D2 F063
D: PA-RISC port minion, PDC and GSCPS2 drivers, debuglocks and other bits
D: Some bits in an ARM port, S1D13XXX FB driver, random patches here and there
D: AD1889 sound driver
S: Paris, France
N: Heikki Vatiainen
E: hessu@cs.tut.fi
D: Co-author of Multi-Protocol Over ATM (MPOA), some LANE hacks

View File

@ -24,6 +24,8 @@ DMA-mapping.txt
- info for PCI drivers using DMA portably across all platforms.
DocBook/
- directory with DocBook templates etc. for kernel documentation.
HOWTO
- The process and procedures of how to do Linux kernel development.
IO-mapping.txt
- how to access I/O mapped memory from within device drivers.
IPMI.txt
@ -256,6 +258,10 @@ specialix.txt
- info on hardware/driver for specialix IO8+ multiport serial card.
spinlocks.txt
- info on using spinlocks to provide exclusive access in kernel.
stable_api_nonsense.txt
- info on why the kernel does not have a stable in-kernel api or abi.
stable_kernel_rules.txt
- rules and procedures for the -stable kernel releases.
stallion.txt
- info on using the Stallion multiport serial driver.
svga.txt

618
Documentation/HOWTO Normal file
View File

@ -0,0 +1,618 @@
HOWTO do Linux kernel development
---------------------------------
This is the be-all, end-all document on this topic. It contains
instructions on how to become a Linux kernel developer and how to learn
to work with the Linux kernel development community. It tries to not
contain anything related to the technical aspects of kernel programming,
but will help point you in the right direction for that.
If anything in this document becomes out of date, please send in patches
to the maintainer of this file, who is listed at the bottom of the
document.
Introduction
------------
So, you want to learn how to become a Linux kernel developer? Or you
have been told by your manager, "Go write a Linux driver for this
device." This document's goal is to teach you everything you need to
know to achieve this by describing the process you need to go through,
and hints on how to work with the community. It will also try to
explain some of the reasons why the community works like it does.
The kernel is written mostly in C, with some architecture-dependent
parts written in assembly. A good understanding of C is required for
kernel development. Assembly (any architecture) is not required unless
you plan to do low-level development for that architecture. Though they
are not a good substitute for a solid C education and/or years of
experience, the following books are good for, if anything, reference:
- "The C Programming Language" by Kernighan and Ritchie [Prentice Hall]
- "Practical C Programming" by Steve Oualline [O'Reilly]
The kernel is written using GNU C and the GNU toolchain. While it
adheres to the ISO C89 standard, it uses a number of extensions that are
not featured in the standard. The kernel is a freestanding C
environment, with no reliance on the standard C library, so some
portions of the C standard are not supported. Arbitrary long long
divisions and floating point are not allowed. It can sometimes be
difficult to understand the assumptions the kernel has on the toolchain
and the extensions that it uses, and unfortunately there is no
definitive reference for them. Please check the gcc info pages (`info
gcc`) for some information on them.
Please remember that you are trying to learn how to work with the
existing development community. It is a diverse group of people, with
high standards for coding, style and procedure. These standards have
been created over time based on what they have found to work best for
such a large and geographically dispersed team. Try to learn as much as
possible about these standards ahead of time, as they are well
documented; do not expect people to adapt to you or your company's way
of doing things.
Legal Issues
------------
The Linux kernel source code is released under the GPL. Please see the
file, COPYING, in the main directory of the source tree, for details on
the license. If you have further questions about the license, please
contact a lawyer, and do not ask on the Linux kernel mailing list. The
people on the mailing lists are not lawyers, and you should not rely on
their statements on legal matters.
For common questions and answers about the GPL, please see:
http://www.gnu.org/licenses/gpl-faq.html
Documentation
------------
The Linux kernel source tree has a large range of documents that are
invaluable for learning how to interact with the kernel community. When
new features are added to the kernel, it is recommended that new
documentation files are also added which explain how to use the feature.
When a kernel change causes the interface that the kernel exposes to
userspace to change, it is recommended that you send the information or
a patch to the manual pages explaining the change to the manual pages
maintainer at mtk-manpages@gmx.net.
Here is a list of files that are in the kernel source tree that are
required reading:
README
This file gives a short background on the Linux kernel and describes
what is necessary to do to configure and build the kernel. People
who are new to the kernel should start here.
Documentation/Changes
This file gives a list of the minimum levels of various software
packages that are necessary to build and run the kernel
successfully.
Documentation/CodingStyle
This describes the Linux kernel coding style, and some of the
rationale behind it. All new code is expected to follow the
guidelines in this document. Most maintainers will only accept
patches if these rules are followed, and many people will only
review code if it is in the proper style.
Documentation/SubmittingPatches
Documentation/SubmittingDrivers
These files describe in explicit detail how to successfully create
and send a patch, including (but not limited to):
- Email contents
- Email format
- Who to send it to
Following these rules will not guarantee success (as all patches are
subject to scrutiny for content and style), but not following them
will almost always prevent it.
Other excellent descriptions of how to create patches properly are:
"The Perfect Patch"
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
"Linux kernel patch submission format"
http://linux.yyz.us/patch-format.html
Documentation/stable_api_nonsense.txt
This file describes the rationale behind the conscious decision to
not have a stable API within the kernel, including things like:
- Subsystem shim-layers (for compatibility?)
- Driver portability between Operating Systems.
- Mitigating rapid change within the kernel source tree (or
preventing rapid change)
This document is crucial for understanding the Linux development
philosophy and is very important for people moving to Linux from
development on other Operating Systems.
Documentation/SecurityBugs
If you feel you have found a security problem in the Linux kernel,
please follow the steps in this document to help notify the kernel
developers, and help solve the issue.
Documentation/ManagementStyle
This document describes how Linux kernel maintainers operate and the
shared ethos behind their methodologies. This is important reading
for anyone new to kernel development (or anyone simply curious about
it), as it resolves a lot of common misconceptions and confusion
about the unique behavior of kernel maintainers.
Documentation/stable_kernel_rules.txt
This file describes the rules on how the stable kernel releases
happen, and what to do if you want to get a change into one of these
releases.
Documentation/kernel-docs.txt
A list of external documentation that pertains to kernel
development. Please consult this list if you do not find what you
are looking for within the in-kernel documentation.
Documentation/applying-patches.txt
A good introduction describing exactly what a patch is and how to
apply it to the different development branches of the kernel.
The kernel also has a large number of documents that can be
automatically generated from the source code itself. This includes a
full description of the in-kernel API, and rules on how to handle
locking properly. The documents will be created in the
Documentation/DocBook/ directory and can be generated as PDF,
Postscript, HTML, and man pages by running:
make pdfdocs
make psdocs
make htmldocs
make mandocs
respectively from the main kernel source directory.
Becoming A Kernel Developer
---------------------------
If you do not know anything about Linux kernel development, you should
look at the Linux KernelNewbies project:
http://kernelnewbies.org
It consists of a helpful mailing list where you can ask almost any type
of basic kernel development question (make sure to search the archives
first, before asking something that has already been answered in the
past.) It also has an IRC channel that you can use to ask questions in
real-time, and a lot of helpful documentation that is useful for
learning about Linux kernel development.
The website has basic information about code organization, subsystems,
and current projects (both in-tree and out-of-tree). It also describes
some basic logistical information, like how to compile a kernel and
apply a patch.
If you do not know where you want to start, but you want to look for
some task to start doing to join into the kernel development community,
go to the Linux Kernel Janitor's project:
http://janitor.kernelnewbies.org/
It is a great place to start. It describes a list of relatively simple
problems that need to be cleaned up and fixed within the Linux kernel
source tree. Working with the developers in charge of this project, you
will learn the basics of getting your patch into the Linux kernel tree,
and possibly be pointed in the direction of what to go work on next, if
you do not already have an idea.
If you already have a chunk of code that you want to put into the kernel
tree, but need some help getting it in the proper form, the
kernel-mentors project was created to help you out with this. It is a
mailing list, and can be found at:
http://selenic.com/mailman/listinfo/kernel-mentors
Before making any actual modifications to the Linux kernel code, it is
imperative to understand how the code in question works. For this
purpose, nothing is better than reading through it directly (most tricky
bits are commented well), perhaps even with the help of specialized
tools. One such tool that is particularly recommended is the Linux
Cross-Reference project, which is able to present source code in a
self-referential, indexed webpage format. An excellent up-to-date
repository of the kernel code may be found at:
http://sosdg.org/~coywolf/lxr/
The development process
-----------------------
Linux kernel development process currently consists of a few different
main kernel "branches" and lots of different subsystem-specific kernel
branches. These different branches are:
- main 2.6.x kernel tree
- 2.6.x.y -stable kernel tree
- 2.6.x -git kernel patches
- 2.6.x -mm kernel patches
- subsystem specific kernel trees and patches
2.6.x kernel tree
-----------------
2.6.x kernels are maintained by Linus Torvalds, and can be found on
kernel.org in the pub/linux/kernel/v2.6/ directory. Its development
process is as follows:
- As soon as a new kernel is released a two weeks window is open,
during this period of time maintainers can submit big diffs to
Linus, usually the patches that have already been included in the
-mm kernel for a few weeks. The preferred way to submit big changes
is using git (the kernel's source management tool, more information
can be found at http://git.or.cz/) but plain patches are also just
fine.
- After two weeks a -rc1 kernel is released it is now possible to push
only patches that do not include new features that could affect the
stability of the whole kernel. Please note that a whole new driver
(or filesystem) might be accepted after -rc1 because there is no
risk of causing regressions with such a change as long as the change
is self-contained and does not affect areas outside of the code that
is being added. git can be used to send patches to Linus after -rc1
is released, but the patches need to also be sent to a public
mailing list for review.
- A new -rc is released whenever Linus deems the current git tree to
be in a reasonably sane state adequate for testing. The goal is to
release a new -rc kernel every week.
- Process continues until the kernel is considered "ready", the
process should last around 6 weeks.
It is worth mentioning what Andrew Morton wrote on the linux-kernel
mailing list about kernel releases:
"Nobody knows when a kernel will be released, because it's
released according to perceived bug status, not according to a
preconceived timeline."
2.6.x.y -stable kernel tree
---------------------------
Kernels with 4 digit versions are -stable kernels. They contain
relatively small and critical fixes for security problems or significant
regressions discovered in a given 2.6.x kernel.
This is the recommended branch for users who want the most recent stable
kernel and are not interested in helping test development/experimental
versions.
If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
kernel is the current stable kernel.
2.6.x.y are maintained by the "stable" team <stable@kernel.org>, and are
released almost every other week.
The file Documentation/stable_kernel_rules.txt in the kernel tree
documents what kinds of changes are acceptable for the -stable tree, and
how the release process works.
2.6.x -git patches
------------------
These are daily snapshots of Linus' kernel tree which are managed in a
git repository (hence the name.) These patches are usually released
daily and represent the current state of Linus' tree. They are more
experimental than -rc kernels since they are generated automatically
without even a cursory glance to see if they are sane.
2.6.x -mm kernel patches
------------------------
These are experimental kernel patches released by Andrew Morton. Andrew
takes all of the different subsystem kernel trees and patches and mushes
them together, along with a lot of patches that have been plucked from
the linux-kernel mailing list. This tree serves as a proving ground for
new features and patches. Once a patch has proved its worth in -mm for
a while Andrew or the subsystem maintainer pushes it on to Linus for
inclusion in mainline.
It is heavily encouraged that all new patches get tested in the -mm tree
before they are sent to Linus for inclusion in the main kernel tree.
These kernels are not appropriate for use on systems that are supposed
to be stable and they are more risky to run than any of the other
branches.
If you wish to help out with the kernel development process, please test
and use these kernel releases and provide feedback to the linux-kernel
mailing list if you have any problems, and if everything works properly.
In addition to all the other experimental patches, these kernels usually
also contain any changes in the mainline -git kernels available at the
time of release.
The -mm kernels are not released on a fixed schedule, but usually a few
-mm kernels are released in between each -rc kernel (1 to 3 is common).
Subsystem Specific kernel trees and patches
-------------------------------------------
A number of the different kernel subsystem developers expose their
development trees so that others can see what is happening in the
different areas of the kernel. These trees are pulled into the -mm
kernel releases as described above.
Here is a list of some of the different kernel trees available:
git trees:
- Kbuild development tree, Sam Ravnborg <sam@ravnborg.org>
kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
- ACPI development tree, Len Brown <len.brown@intel.com>
kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
- Block development tree, Jens Axboe <axboe@suse.de>
kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
- DRM development tree, Dave Airlie <airlied@linux.ie>
kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
- ia64 development tree, Tony Luck <tony.luck@intel.com>
kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
- ieee1394 development tree, Jody McIntyre <scjody@modernduck.com>
kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
- infiniband, Roland Dreier <rolandd@cisco.com>
kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
- libata, Jeff Garzik <jgarzik@pobox.com>
kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
- network drivers, Jeff Garzik <jgarzik@pobox.com>
kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
- pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
- SCSI, James Bottomley <James.Bottomley@SteelEye.com>
kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
Other git kernel trees can be found listed at http://kernel.org/git
quilt trees:
- USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
Bug Reporting
-------------
bugzilla.kernel.org is where the Linux kernel developers track kernel
bugs. Users are encouraged to report all bugs that they find in this
tool. For details on how to use the kernel bugzilla, please see:
http://test.kernel.org/bugzilla/faq.html
The file REPORTING-BUGS in the main kernel source directory has a good
template for how to report a possible kernel bug, and details what kind
of information is needed by the kernel developers to help track down the
problem.
Mailing lists
-------------
As some of the above documents describe, the majority of the core kernel
developers participate on the Linux Kernel Mailing list. Details on how
to subscribe and unsubscribe from the list can be found at:
http://vger.kernel.org/vger-lists.html#linux-kernel
There are archives of the mailing list on the web in many different
places. Use a search engine to find these archives. For example:
http://dir.gmane.org/gmane.linux.kernel
It is highly recommended that you search the archives about the topic
you want to bring up, before you post it to the list. A lot of things
already discussed in detail are only recorded at the mailing list
archives.
Most of the individual kernel subsystems also have their own separate
mailing list where they do their development efforts. See the
MAINTAINERS file for a list of what these lists are for the different
groups.
Many of the lists are hosted on kernel.org. Information on them can be
found at:
http://vger.kernel.org/vger-lists.html
Please remember to follow good behavioral habits when using the lists.
Though a bit cheesy, the following URL has some simple guidelines for
interacting with the list (or any list):
http://www.albion.com/netiquette/
If multiple people respond to your mail, the CC: list of recipients may
get pretty large. Don't remove anybody from the CC: list without a good
reason, or don't reply only to the list address. Get used to receiving the
mail twice, one from the sender and the one from the list, and don't try
to tune that by adding fancy mail-headers, people will not like it.
Remember to keep the context and the attribution of your replies intact,
keep the "John Kernelhacker wrote ...:" lines at the top of your reply, and
add your statements between the individual quoted sections instead of
writing at the top of the mail.
If you add patches to your mail, make sure they are plain readable text
as stated in Documentation/SubmittingPatches. Kernel developers don't
want to deal with attachments or compressed patches; they may want
to comment on individual lines of your patch, which works only that way.
Make sure you use a mail program that does not mangle spaces and tab
characters. A good first test is to send the mail to yourself and try
to apply your own patch by yourself. If that doesn't work, get your
mail program fixed or change it until it works.
Above all, please remember to show respect to other subscribers.
Working with the community
--------------------------
The goal of the kernel community is to provide the best possible kernel
there is. When you submit a patch for acceptance, it will be reviewed
on its technical merits and those alone. So, what should you be
expecting?
- criticism
- comments
- requests for change
- requests for justification
- silence
Remember, this is part of getting your patch into the kernel. You have
to be able to take criticism and comments about your patches, evaluate
them at a technical level and either rework your patches or provide
clear and concise reasoning as to why those changes should not be made.
If there are no responses to your posting, wait a few days and try
again, sometimes things get lost in the huge volume.
What should you not do?
- expect your patch to be accepted without question
- become defensive
- ignore comments
- resubmit the patch without making any of the requested changes
In a community that is looking for the best technical solution possible,
there will always be differing opinions on how beneficial a patch is.
You have to be cooperative, and willing to adapt your idea to fit within
the kernel. Or at least be willing to prove your idea is worth it.
Remember, being wrong is acceptable as long as you are willing to work
toward a solution that is right.
It is normal that the answers to your first patch might simply be a list
of a dozen things you should correct. This does _not_ imply that your
patch will not be accepted, and it is _not_ meant against you
personally. Simply correct all issues raised against your patch and
resend it.
Differences between the kernel community and corporate structures
-----------------------------------------------------------------
The kernel community works differently than most traditional corporate
development environments. Here are a list of things that you can try to
do to try to avoid problems:
Good things to say regarding your proposed changes:
- "This solves multiple problems."
- "This deletes 2000 lines of code."
- "Here is a patch that explains what I am trying to describe."
- "I tested it on 5 different architectures..."
- "Here is a series of small patches that..."
- "This increases performance on typical machines..."
Bad things you should avoid saying:
- "We did it this way in AIX/ptx/Solaris, so therefore it must be
good..."
- "I've being doing this for 20 years, so..."
- "This is required for my company to make money"
- "This is for our Enterprise product line."
- "Here is my 1000 page design document that describes my idea"
- "I've been working on this for 6 months..."
- "Here's a 5000 line patch that..."
- "I rewrote all of the current mess, and here it is..."
- "I have a deadline, and this patch needs to be applied now."
Another way the kernel community is different than most traditional
software engineering work environments is the faceless nature of
interaction. One benefit of using email and irc as the primary forms of
communication is the lack of discrimination based on gender or race.
The Linux kernel work environment is accepting of women and minorities
because all you are is an email address. The international aspect also
helps to level the playing field because you can't guess gender based on
a person's name. A man may be named Andrea and a woman may be named Pat.
Most women who have worked in the Linux kernel and have expressed an
opinion have had positive experiences.
The language barrier can cause problems for some people who are not
comfortable with English. A good grasp of the language can be needed in
order to get ideas across properly on mailing lists, so it is
recommended that you check your emails to make sure they make sense in
English before sending them.
Break up your changes
---------------------
The Linux kernel community does not gladly accept large chunks of code
dropped on it all at once. The changes need to be properly introduced,
discussed, and broken up into tiny, individual portions. This is almost
the exact opposite of what companies are used to doing. Your proposal
should also be introduced very early in the development process, so that
you can receive feedback on what you are doing. It also lets the
community feel that you are working with them, and not simply using them
as a dumping ground for your feature. However, don't send 50 emails at
one time to a mailing list, your patch series should be smaller than
that almost all of the time.
The reasons for breaking things up are the following:
1) Small patches increase the likelihood that your patches will be
applied, since they don't take much time or effort to verify for
correctness. A 5 line patch can be applied by a maintainer with
barely a second glance. However, a 500 line patch may take hours to
review for correctness (the time it takes is exponentially
proportional to the size of the patch, or something).
Small patches also make it very easy to debug when something goes
wrong. It's much easier to back out patches one by one than it is
to dissect a very large patch after it's been applied (and broken
something).
2) It's important not only to send small patches, but also to rewrite
and simplify (or simply re-order) patches before submitting them.
Here is an analogy from kernel developer Al Viro:
"Think of a teacher grading homework from a math student. The
teacher does not want to see the student's trials and errors
before they came up with the solution. They want to see the
cleanest, most elegant answer. A good student knows this, and
would never submit her intermediate work before the final
solution."
The same is true of kernel development. The maintainers and
reviewers do not want to see the thought process behind the
solution to the problem one is solving. They want to see a
simple and elegant solution."
It may be challenging to keep the balance between presenting an elegant
solution and working together with the community and discussing your
unfinished work. Therefore it is good to get early in the process to
get feedback to improve your work, but also keep your changes in small
chunks that they may get already accepted, even when your whole task is
not ready for inclusion now.
Also realize that it is not acceptable to send patches for inclusion
that are unfinished and will be "fixed up later."
Justify your change
-------------------
Along with breaking up your patches, it is very important for you to let
the Linux community know why they should add this change. New features
must be justified as being needed and useful.
Document your change
--------------------
When sending in your patches, pay special attention to what you say in
the text in your email. This information will become the ChangeLog
information for the patch, and will be preserved for everyone to see for
all time. It should describe the patch completely, containing:
- why the change is necessary
- the overall design approach in the patch
- implementation details
- testing results
For more details on what this should all look like, please see the
ChangeLog section of the document:
"The Perfect Patch"
http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt
All of these things are sometimes very hard to do. It can take years to
perfect these practices (if at all). It's a continuous process of
improvement that requires a lot of patience and determination. But
don't give up, it's possible. Many have done it before, and each had to
start exactly where you are now.
----------
Thanks to Paolo Ciarrocchi who allowed the "Development Process" section
to be based on text he had written, and to Randy Dunlap and Gerrit
Huizenga for some of the list of things you should and should not say.
Also thanks to Pat Mochel, Hanna Linder, Randy Dunlap, Kay Sievers,
Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook, Andrew Morton, Andi
Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk, Keri Harris, Frans Pop,
David A. Wheeler, Junio Hamano, Michael Kerrisk, and Alex Shepard for
their review, comments, and contributions. Without their help, this
document would not have been possible.
Maintainer: Greg Kroah-Hartman <greg@kroah.com>

View File

@ -58,6 +58,7 @@ P: Person
M: Mail patches to
L: Mailing list that is relevant to this area
W: Web-page with status/info
T: SCM tree type and URL. Type is one of: git, hg, quilt.
S: Status, one of the following:
Supported: Someone is actually paid to look after this.
@ -183,6 +184,7 @@ P: Len Brown
M: len.brown@intel.com
L: acpi-devel@lists.sourceforge.net
W: http://acpi.sourceforge.net/
T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
S: Maintained
AD1816 SOUND DRIVER
@ -418,6 +420,7 @@ BLOCK LAYER
P: Jens Axboe
M: axboe@suse.de
L: linux-kernel@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
S: Maintained
BLUETOOTH SUBSYSTEM
@ -803,12 +806,14 @@ DRIVER CORE, KOBJECTS, AND SYSFS
P: Greg Kroah-Hartman
M: gregkh@suse.de
L: linux-kernel@vger.kernel.org
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
DRM DRIVERS
P: David Airlie
M: airlied@linux.ie
L: dri-devel@lists.sourceforge.net
T: git kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
S: Maintained
DSCC4 DRIVER
@ -1113,6 +1118,7 @@ P: Jean Delvare
M: khali@linux-fr.org
L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.nu/
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Maintained
I2O
@ -1145,6 +1151,7 @@ P: Tony Luck
M: tony.luck@intel.com
L: linux-ia64@vger.kernel.org
W: http://www.ia64-linux.org/
T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
S: Maintained
SN-IA64 (Itanium) SUB-PLATFORM
@ -1212,6 +1219,7 @@ P: Jody McIntyre
M: scjody@steamballoon.com
L: linux1394-devel@lists.sourceforge.net
W: http://www.linux1394.org/
T: git kernel.org:/pub/scm/linux/kernel/git/scjody/ieee1394.git
S: Maintained
IEEE 1394 OHCI DRIVER
@ -1263,6 +1271,7 @@ P: Hal Rosenstock
M: halr@voltaire.com
L: openib-general@openib.org
W: http://www.openib.org/
T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
S: Supported
INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
@ -1436,6 +1445,7 @@ P: Kai Germaschewski
M: kai@germaschewski.name
P: Sam Ravnborg
M: sam@ravnborg.org
T: git kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
S: Maintained
KERNEL JANITORS
@ -1782,6 +1792,7 @@ M: akpm@osdl.org
P: Jeff Garzik
M: jgarzik@pobox.com
L: netdev@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
S: Maintained
NETWORKING [GENERAL]
@ -1959,6 +1970,7 @@ P: Greg Kroah-Hartman
M: gregkh@suse.de
L: linux-kernel@vger.kernel.org
L: linux-pci@atrey.karlin.mff.cuni.cz
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
PCI HOTPLUG CORE
@ -1980,6 +1992,7 @@ S: Maintained
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: http://lists.infradead.org/mailman/listinfo/linux-pcmcia
T: git kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
S: Maintained
PCNET32 NETWORK DRIVER
@ -2189,6 +2202,7 @@ SCSI SUBSYSTEM
P: James E.J. Bottomley
M: James.Bottomley@SteelEye.com
L: linux-scsi@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
S: Maintained
SCSI TAPE DRIVER
@ -2228,6 +2242,7 @@ SERIAL ATA (SATA) SUBSYSTEM:
P: Jeff Garzik
M: jgarzik@pobox.com
L: linux-ide@vger.kernel.org
T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
S: Supported
SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER
@ -2749,6 +2764,7 @@ M: gregkh@suse.de
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-usb.org
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
S: Supported
USB UHCI DRIVER

View File

@ -91,16 +91,17 @@ ENTRY(vhpt_miss)
* (the "original") TLB miss, which may either be caused by an instruction
* fetch or a data access (or non-access).
*
* What we do here is normal TLB miss handing for the _original_ miss, followed
* by inserting the TLB entry for the virtual page table page that the VHPT
* walker was attempting to access. The latter gets inserted as long
* as both L1 and L2 have valid mappings for the faulting address.
* The TLB entry for the original miss gets inserted only if
* the L3 entry indicates that the page is present.
* What we do here is normal TLB miss handing for the _original_ miss,
* followed by inserting the TLB entry for the virtual page table page
* that the VHPT walker was attempting to access. The latter gets
* inserted as long as page table entry above pte level have valid
* mappings for the faulting address. The TLB entry for the original
* miss gets inserted only if the pte entry indicates that the page is
* present.
*
* do_page_fault gets invoked in the following cases:
* - the faulting virtual address uses unimplemented address bits
* - the faulting virtual address has no L1, L2, or L3 mapping
* - the faulting virtual address has no valid page table mapping
*/
mov r16=cr.ifa // get address that caused the TLB miss
#ifdef CONFIG_HUGETLB_PAGE
@ -126,7 +127,7 @@ ENTRY(vhpt_miss)
#endif
;;
cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5?
shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address
shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit
;;
(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
@ -137,38 +138,38 @@ ENTRY(vhpt_miss)
(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
;;
(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8
(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
#ifdef CONFIG_PGTABLE_4
shr.u r28=r22,PUD_SHIFT // shift L2 index into position
shr.u r28=r22,PUD_SHIFT // shift pud index into position
#else
shr.u r18=r22,PMD_SHIFT // shift L3 index into position
shr.u r18=r22,PMD_SHIFT // shift pmd index into position
#endif
;;
ld8 r17=[r17] // fetch the L1 entry (may be 0)
ld8 r17=[r17] // get *pgd (may be 0)
;;
(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL?
(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
#ifdef CONFIG_PGTABLE_4
dep r28=r28,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr)
;;
shr.u r18=r22,PMD_SHIFT // shift L3 index into position
(p7) ld8 r29=[r28] // fetch the L2 entry (may be 0)
shr.u r18=r22,PMD_SHIFT // shift pmd index into position
(p7) ld8 r29=[r28] // get *pud (may be 0)
;;
(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was L2 entry NULL?
dep r17=r18,r29,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL?
dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
#else
dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr)
#endif
;;
(p7) ld8 r20=[r17] // fetch the L3 entry (may be 0)
shr.u r19=r22,PAGE_SHIFT // shift L4 index into position
(p7) ld8 r20=[r17] // get *pmd (may be 0)
shr.u r19=r22,PAGE_SHIFT // shift pte index into position
;;
(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L3 entry NULL?
dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L4 page table entry
(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL?
dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr)
;;
(p7) ld8 r18=[r21] // read the L4 PTE
mov r19=cr.isr // cr.isr bit 0 tells us if this is an insn miss
(p7) ld8 r18=[r21] // read *pte
mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss
;;
(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared?
mov r22=cr.iha // get the VHPT address that caused the TLB miss
@ -202,25 +203,33 @@ ENTRY(vhpt_miss)
dv_serialize_data
/*
* Re-check L2 and L3 pagetable. If they changed, we may have received a ptc.g
* Re-check pagetable entry. If they changed, we may have received a ptc.g
* between reading the pagetable and the "itc". If so, flush the entry we
* inserted and retry.
* inserted and retry. At this point, we have:
*
* r28 = equivalent of pud_offset(pgd, ifa)
* r17 = equivalent of pmd_offset(pud, ifa)
* r21 = equivalent of pte_offset(pmd, ifa)
*
* r29 = *pud
* r20 = *pmd
* r18 = *pte
*/
ld8 r25=[r21] // read L4 entry again
ld8 r26=[r17] // read L3 PTE again
ld8 r25=[r21] // read *pte again
ld8 r26=[r17] // read *pmd again
#ifdef CONFIG_PGTABLE_4
ld8 r18=[r28] // read L2 entry again
ld8 r19=[r28] // read *pud again
#endif
cmp.ne p6,p7=r0,r0
;;
cmp.ne.or.andcm p6,p7=r26,r20 // did L3 entry change
cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change
#ifdef CONFIG_PGTABLE_4
cmp.ne.or.andcm p6,p7=r29,r18 // did L4 PTE change
cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change
#endif
mov r27=PAGE_SHIFT<<2
;;
(p6) ptc.l r22,r27 // purge PTE page translation
(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did L4 PTE change
(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change
;;
(p6) ptc.l r16,r27 // purge translation
#endif
@ -235,19 +244,19 @@ END(vhpt_miss)
ENTRY(itlb_miss)
DBG_FAULT(1)
/*
* The ITLB handler accesses the L3 PTE via the virtually mapped linear
* The ITLB handler accesses the PTE via the virtually mapped linear
* page table. If a nested TLB miss occurs, we switch into physical
* mode, walk the page table, and then re-execute the L3 PTE read
* and go on normally after that.
* mode, walk the page table, and then re-execute the PTE read and
* go on normally after that.
*/
mov r16=cr.ifa // get virtual address
mov r29=b0 // save b0
mov r31=pr // save predicates
.itlb_fault:
mov r17=cr.iha // get virtual address of L3 PTE
mov r17=cr.iha // get virtual address of PTE
movl r30=1f // load nested fault continuation point
;;
1: ld8 r18=[r17] // read L3 PTE
1: ld8 r18=[r17] // read *pte
;;
mov b0=r29
tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
@ -262,7 +271,7 @@ ENTRY(itlb_miss)
*/
dv_serialize_data
ld8 r19=[r17] // read L3 PTE again and see if same
ld8 r19=[r17] // read *pte again and see if same
mov r20=PAGE_SHIFT<<2 // setup page size for purge
;;
cmp.ne p7,p0=r18,r19
@ -279,19 +288,19 @@ END(itlb_miss)
ENTRY(dtlb_miss)
DBG_FAULT(2)
/*
* The DTLB handler accesses the L3 PTE via the virtually mapped linear
* The DTLB handler accesses the PTE via the virtually mapped linear
* page table. If a nested TLB miss occurs, we switch into physical
* mode, walk the page table, and then re-execute the L3 PTE read
* and go on normally after that.
* mode, walk the page table, and then re-execute the PTE read and
* go on normally after that.
*/
mov r16=cr.ifa // get virtual address
mov r29=b0 // save b0
mov r31=pr // save predicates
dtlb_fault:
mov r17=cr.iha // get virtual address of L3 PTE
mov r17=cr.iha // get virtual address of PTE
movl r30=1f // load nested fault continuation point
;;
1: ld8 r18=[r17] // read L3 PTE
1: ld8 r18=[r17] // read *pte
;;
mov b0=r29
tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared?
@ -306,7 +315,7 @@ dtlb_fault:
*/
dv_serialize_data
ld8 r19=[r17] // read L3 PTE again and see if same
ld8 r19=[r17] // read *pte again and see if same
mov r20=PAGE_SHIFT<<2 // setup page size for purge
;;
cmp.ne p7,p0=r18,r19
@ -420,7 +429,7 @@ ENTRY(nested_dtlb_miss)
* r30: continuation address
* r31: saved pr
*
* Output: r17: physical address of L3 PTE of faulting address
* Output: r17: physical address of PTE of faulting address
* r29: saved b0
* r30: continuation address
* r31: saved pr
@ -450,33 +459,33 @@ ENTRY(nested_dtlb_miss)
(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT
(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3
;;
(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8
(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5
(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4]
cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
#ifdef CONFIG_PGTABLE_4
shr.u r18=r22,PUD_SHIFT // shift L2 index into position
shr.u r18=r22,PUD_SHIFT // shift pud index into position
#else
shr.u r18=r22,PMD_SHIFT // shift L3 index into position
shr.u r18=r22,PMD_SHIFT // shift pmd index into position
#endif
;;
ld8 r17=[r17] // fetch the L1 entry (may be 0)
ld8 r17=[r17] // get *pgd (may be 0)
;;
(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL?
dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL?
dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr)
;;
#ifdef CONFIG_PGTABLE_4
(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0)
shr.u r18=r22,PMD_SHIFT // shift L3 index into position
(p7) ld8 r17=[r17] // get *pud (may be 0)
shr.u r18=r22,PMD_SHIFT // shift pmd index into position
;;
(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL?
dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL?
dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr)
;;
#endif
(p7) ld8 r17=[r17] // fetch the L3 entry (may be 0)
shr.u r19=r22,PAGE_SHIFT // shift L4 index into position
(p7) ld8 r17=[r17] // get *pmd (may be 0)
shr.u r19=r22,PAGE_SHIFT // shift pte index into position
;;
(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L3 entry NULL?
dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L4 page table entry
(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL?
dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr);
(p6) br.cond.spnt page_fault
mov b0=r30
br.sptk.many b0 // return to continuation point

View File

@ -499,8 +499,12 @@ alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path)
dev = create_parisc_device(mod_path);
if (dev->id.hw_type != HPHW_FAULTY) {
printk("Two devices have hardware path %s. Please file a bug with HP.\n"
"In the meantime, you could try rearranging your cards.\n", parisc_pathname(dev));
printk(KERN_ERR "Two devices have hardware path [%s]. "
"IODC data for second device: "
"%02x%02x%02x%02x%02x%02x\n"
"Rearranging GSC cards sometimes helps\n",
parisc_pathname(dev), iodc_data[0], iodc_data[1],
iodc_data[3], iodc_data[4], iodc_data[5], iodc_data[6]);
return NULL;
}

View File

@ -1846,6 +1846,7 @@ sys_clone_wrapper:
ldo -16(%r30),%r29 /* Reference param save area */
#endif
/* WARNING - Clobbers r19 and r21, userspace must save these! */
STREG %r2,PT_GR19(%r1) /* save for child */
STREG %r30,PT_GR21(%r1)
BL sys_clone,%r2

View File

@ -188,7 +188,7 @@ pat_query_module(ulong pcell_loc, ulong mod_index)
temp = pa_pdc_cell.cba;
dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);
if (!dev) {
return PDC_NE_MOD;
return PDC_OK;
}
/* alloc_pa_dev sets dev->hpa */

View File

@ -19,536 +19,6 @@
#define CODE
#include "compat_ioctl.c"
/* Use this to get at 32-bit user passed pointers.
See sys_sparc32.c for description about these. */
#define A(__x) ((unsigned long)(__x))
/* The same for use with copy_from_user() and copy_to_user(). */
#define B(__x) ((void *)(unsigned long)(__x))
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
/* This really belongs in include/linux/drm.h -DaveM */
#include "../../../drivers/char/drm/drm.h"
typedef struct drm32_version {
int version_major; /* Major version */
int version_minor; /* Minor version */
int version_patchlevel;/* Patch level */
int name_len; /* Length of name buffer */
u32 name; /* Name of driver */
int date_len; /* Length of date buffer */
u32 date; /* User-space buffer to hold date */
int desc_len; /* Length of desc buffer */
u32 desc; /* User-space buffer to hold desc */
} drm32_version_t;
#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t)
static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_version_t *uversion = (drm32_version_t *)arg;
char *name_ptr, *date_ptr, *desc_ptr;
u32 tmp1, tmp2, tmp3;
drm_version_t kversion;
mm_segment_t old_fs;
int ret;
memset(&kversion, 0, sizeof(kversion));
if (get_user(kversion.name_len, &uversion->name_len) ||
get_user(kversion.date_len, &uversion->date_len) ||
get_user(kversion.desc_len, &uversion->desc_len) ||
get_user(tmp1, &uversion->name) ||
get_user(tmp2, &uversion->date) ||
get_user(tmp3, &uversion->desc))
return -EFAULT;
name_ptr = (char *) A(tmp1);
date_ptr = (char *) A(tmp2);
desc_ptr = (char *) A(tmp3);
ret = -ENOMEM;
if (kversion.name_len && name_ptr) {
kversion.name = kmalloc(kversion.name_len, GFP_KERNEL);
if (!kversion.name)
goto out;
}
if (kversion.date_len && date_ptr) {
kversion.date = kmalloc(kversion.date_len, GFP_KERNEL);
if (!kversion.date)
goto out;
}
if (kversion.desc_len && desc_ptr) {
kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL);
if (!kversion.desc)
goto out;
}
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion);
set_fs(old_fs);
if (!ret) {
if ((kversion.name &&
copy_to_user(name_ptr, kversion.name, kversion.name_len)) ||
(kversion.date &&
copy_to_user(date_ptr, kversion.date, kversion.date_len)) ||
(kversion.desc &&
copy_to_user(desc_ptr, kversion.desc, kversion.desc_len)))
ret = -EFAULT;
if (put_user(kversion.version_major, &uversion->version_major) ||
put_user(kversion.version_minor, &uversion->version_minor) ||
put_user(kversion.version_patchlevel, &uversion->version_patchlevel) ||
put_user(kversion.name_len, &uversion->name_len) ||
put_user(kversion.date_len, &uversion->date_len) ||
put_user(kversion.desc_len, &uversion->desc_len))
ret = -EFAULT;
}
out:
kfree(kversion.name);
kfree(kversion.date);
kfree(kversion.desc);
return ret;
}
typedef struct drm32_unique {
int unique_len; /* Length of unique */
u32 unique; /* Unique name for driver instantiation */
} drm32_unique_t;
#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t)
#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t)
static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_unique_t *uarg = (drm32_unique_t *)arg;
drm_unique_t karg;
mm_segment_t old_fs;
char *uptr;
u32 tmp;
int ret;
if (get_user(karg.unique_len, &uarg->unique_len))
return -EFAULT;
karg.unique = NULL;
if (get_user(tmp, &uarg->unique))
return -EFAULT;
uptr = (char *) A(tmp);
if (uptr) {
karg.unique = kmalloc(karg.unique_len, GFP_KERNEL);
if (!karg.unique)
return -ENOMEM;
if (cmd == DRM32_IOCTL_SET_UNIQUE &&
copy_from_user(karg.unique, uptr, karg.unique_len)) {
kfree(karg.unique);
return -EFAULT;
}
}
old_fs = get_fs();
set_fs(KERNEL_DS);
if (cmd == DRM32_IOCTL_GET_UNIQUE)
ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg);
else
ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg);
set_fs(old_fs);
if (!ret) {
if (cmd == DRM32_IOCTL_GET_UNIQUE &&
uptr != NULL &&
copy_to_user(uptr, karg.unique, karg.unique_len))
ret = -EFAULT;
if (put_user(karg.unique_len, &uarg->unique_len))
ret = -EFAULT;
}
kfree(karg.unique);
return ret;
}
typedef struct drm32_map {
u32 offset; /* Requested physical address (0 for SAREA)*/
u32 size; /* Requested physical size (bytes) */
drm_map_type_t type; /* Type of memory to map */
drm_map_flags_t flags; /* Flags */
u32 handle; /* User-space: "Handle" to pass to mmap */
/* Kernel-space: kernel-virtual address */
int mtrr; /* MTRR slot used */
/* Private data */
} drm32_map_t;
#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t)
static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_map_t *uarg = (drm32_map_t *) arg;
drm_map_t karg;
mm_segment_t old_fs;
u32 tmp;
int ret;
ret = get_user(karg.offset, &uarg->offset);
ret |= get_user(karg.size, &uarg->size);
ret |= get_user(karg.type, &uarg->type);
ret |= get_user(karg.flags, &uarg->flags);
ret |= get_user(tmp, &uarg->handle);
ret |= get_user(karg.mtrr, &uarg->mtrr);
if (ret)
return -EFAULT;
karg.handle = (void *) A(tmp);
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg);
set_fs(old_fs);
if (!ret) {
ret = put_user(karg.offset, &uarg->offset);
ret |= put_user(karg.size, &uarg->size);
ret |= put_user(karg.type, &uarg->type);
ret |= put_user(karg.flags, &uarg->flags);
tmp = (u32) (long)karg.handle;
ret |= put_user(tmp, &uarg->handle);
ret |= put_user(karg.mtrr, &uarg->mtrr);
if (ret)
ret = -EFAULT;
}
return ret;
}
typedef struct drm32_buf_info {
int count; /* Entries in list */
u32 list; /* (drm_buf_desc_t *) */
} drm32_buf_info_t;
#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t)
static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg;
drm_buf_desc_t *ulist;
drm_buf_info_t karg;
mm_segment_t old_fs;
int orig_count, ret;
u32 tmp;
if (get_user(karg.count, &uarg->count) ||
get_user(tmp, &uarg->list))
return -EFAULT;
ulist = (drm_buf_desc_t *) A(tmp);
orig_count = karg.count;
karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL);
if (!karg.list)
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg);
set_fs(old_fs);
if (!ret) {
if (karg.count <= orig_count &&
(copy_to_user(ulist, karg.list,
karg.count * sizeof(drm_buf_desc_t))))
ret = -EFAULT;
if (put_user(karg.count, &uarg->count))
ret = -EFAULT;
}
kfree(karg.list);
return ret;
}
typedef struct drm32_buf_free {
int count;
u32 list; /* (int *) */
} drm32_buf_free_t;
#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t)
static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg;
drm_buf_free_t karg;
mm_segment_t old_fs;
int *ulist;
int ret;
u32 tmp;
if (get_user(karg.count, &uarg->count) ||
get_user(tmp, &uarg->list))
return -EFAULT;
ulist = (int *) A(tmp);
karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL);
if (!karg.list)
return -ENOMEM;
ret = -EFAULT;
if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int))))
goto out;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg);
set_fs(old_fs);
out:
kfree(karg.list);
return ret;
}
typedef struct drm32_buf_pub {
int idx; /* Index into master buflist */
int total; /* Buffer size */
int used; /* Amount of buffer in use (for DMA) */
u32 address; /* Address of buffer (void *) */
} drm32_buf_pub_t;
typedef struct drm32_buf_map {
int count; /* Length of buflist */
u32 virtual; /* Mmaped area in user-virtual (void *) */
u32 list; /* Buffer information (drm_buf_pub_t *) */
} drm32_buf_map_t;
#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t)
static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg;
drm32_buf_pub_t *ulist;
drm_buf_map_t karg;
mm_segment_t old_fs;
int orig_count, ret, i;
u32 tmp1, tmp2;
if (get_user(karg.count, &uarg->count) ||
get_user(tmp1, &uarg->virtual) ||
get_user(tmp2, &uarg->list))
return -EFAULT;
karg.virtual = (void *) A(tmp1);
ulist = (drm32_buf_pub_t *) A(tmp2);
orig_count = karg.count;
karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL);
if (!karg.list)
return -ENOMEM;
ret = -EFAULT;
for (i = 0; i < karg.count; i++) {
if (get_user(karg.list[i].idx, &ulist[i].idx) ||
get_user(karg.list[i].total, &ulist[i].total) ||
get_user(karg.list[i].used, &ulist[i].used) ||
get_user(tmp1, &ulist[i].address))
goto out;
karg.list[i].address = (void *) A(tmp1);
}
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg);
set_fs(old_fs);
if (!ret) {
for (i = 0; i < orig_count; i++) {
tmp1 = (u32) (long) karg.list[i].address;
if (put_user(karg.list[i].idx, &ulist[i].idx) ||
put_user(karg.list[i].total, &ulist[i].total) ||
put_user(karg.list[i].used, &ulist[i].used) ||
put_user(tmp1, &ulist[i].address)) {
ret = -EFAULT;
goto out;
}
}
if (put_user(karg.count, &uarg->count))
ret = -EFAULT;
}
out:
kfree(karg.list);
return ret;
}
typedef struct drm32_dma {
/* Indices here refer to the offset into
buflist in drm_buf_get_t. */
int context; /* Context handle */
int send_count; /* Number of buffers to send */
u32 send_indices; /* List of handles to buffers (int *) */
u32 send_sizes; /* Lengths of data to send (int *) */
drm_dma_flags_t flags; /* Flags */
int request_count; /* Number of buffers requested */
int request_size; /* Desired size for buffers */
u32 request_indices; /* Buffer information (int *) */
u32 request_sizes; /* (int *) */
int granted_count; /* Number of buffers granted */
} drm32_dma_t;
#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t)
/* RED PEN The DRM layer blindly dereferences the send/request
* indice/size arrays even though they are userland
* pointers. -DaveM
*/
static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_dma_t *uarg = (drm32_dma_t *) arg;
int *u_si, *u_ss, *u_ri, *u_rs;
drm_dma_t karg;
mm_segment_t old_fs;
int ret;
u32 tmp1, tmp2, tmp3, tmp4;
karg.send_indices = karg.send_sizes = NULL;
karg.request_indices = karg.request_sizes = NULL;
if (get_user(karg.context, &uarg->context) ||
get_user(karg.send_count, &uarg->send_count) ||
get_user(tmp1, &uarg->send_indices) ||
get_user(tmp2, &uarg->send_sizes) ||
get_user(karg.flags, &uarg->flags) ||
get_user(karg.request_count, &uarg->request_count) ||
get_user(karg.request_size, &uarg->request_size) ||
get_user(tmp3, &uarg->request_indices) ||
get_user(tmp4, &uarg->request_sizes) ||
get_user(karg.granted_count, &uarg->granted_count))
return -EFAULT;
u_si = (int *) A(tmp1);
u_ss = (int *) A(tmp2);
u_ri = (int *) A(tmp3);
u_rs = (int *) A(tmp4);
if (karg.send_count) {
karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
ret = -ENOMEM;
if (!karg.send_indices || !karg.send_sizes)
goto out;
ret = -EFAULT;
if (copy_from_user(karg.send_indices, u_si,
(karg.send_count * sizeof(int))) ||
copy_from_user(karg.send_sizes, u_ss,
(karg.send_count * sizeof(int))))
goto out;
}
if (karg.request_count) {
karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
ret = -ENOMEM;
if (!karg.request_indices || !karg.request_sizes)
goto out;
ret = -EFAULT;
if (copy_from_user(karg.request_indices, u_ri,
(karg.request_count * sizeof(int))) ||
copy_from_user(karg.request_sizes, u_rs,
(karg.request_count * sizeof(int))))
goto out;
}
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg);
set_fs(old_fs);
if (!ret) {
if (put_user(karg.context, &uarg->context) ||
put_user(karg.send_count, &uarg->send_count) ||
put_user(karg.flags, &uarg->flags) ||
put_user(karg.request_count, &uarg->request_count) ||
put_user(karg.request_size, &uarg->request_size) ||
put_user(karg.granted_count, &uarg->granted_count))
ret = -EFAULT;
if (karg.send_count) {
if (copy_to_user(u_si, karg.send_indices,
(karg.send_count * sizeof(int))) ||
copy_to_user(u_ss, karg.send_sizes,
(karg.send_count * sizeof(int))))
ret = -EFAULT;
}
if (karg.request_count) {
if (copy_to_user(u_ri, karg.request_indices,
(karg.request_count * sizeof(int))) ||
copy_to_user(u_rs, karg.request_sizes,
(karg.request_count * sizeof(int))))
ret = -EFAULT;
}
}
out:
kfree(karg.send_indices);
kfree(karg.send_sizes);
kfree(karg.request_indices);
kfree(karg.request_sizes);
return ret;
}
typedef struct drm32_ctx_res {
int count;
u32 contexts; /* (drm_ctx_t *) */
} drm32_ctx_res_t;
#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t)
static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg)
{
drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg;
drm_ctx_t *ulist;
drm_ctx_res_t karg;
mm_segment_t old_fs;
int orig_count, ret;
u32 tmp;
karg.contexts = NULL;
if (get_user(karg.count, &uarg->count) ||
get_user(tmp, &uarg->contexts))
return -EFAULT;
ulist = (drm_ctx_t *) A(tmp);
orig_count = karg.count;
if (karg.count && ulist) {
karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL);
if (!karg.contexts)
return -ENOMEM;
if (copy_from_user(karg.contexts, ulist,
(karg.count * sizeof(drm_ctx_t)))) {
kfree(karg.contexts);
return -EFAULT;
}
}
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg);
set_fs(old_fs);
if (!ret) {
if (orig_count) {
if (copy_to_user(ulist, karg.contexts,
(orig_count * sizeof(drm_ctx_t))))
ret = -EFAULT;
}
if (put_user(karg.count, &uarg->count))
ret = -EFAULT;
}
kfree(karg.contexts);
return ret;
}
#endif
#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl)
@ -561,11 +31,6 @@ IOCTL_TABLE_START
#define DECLARES
#include "compat_ioctl.c"
/* PA-specific ioctls */
COMPATIBLE_IOCTL(PA_PERF_ON)
COMPATIBLE_IOCTL(PA_PERF_OFF)
COMPATIBLE_IOCTL(PA_PERF_VERSION)
/* And these ioctls need translation */
HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
@ -590,17 +55,6 @@ HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
COMPATIBLE_IOCTL(RTC_EPOCH_SET)
#endif
#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version);
HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique);
HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique);
HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap);
HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs);
HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs);
HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs);
HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma);
HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx);
#endif /* DRM */
IOCTL_TABLE_END
int ioctl_table_size = ARRAY_SIZE(ioctl_start);

View File

@ -30,6 +30,9 @@
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/smp.h>
#undef PARISC_IRQ_CR16_COUNTS
@ -43,26 +46,34 @@ extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
*/
static volatile unsigned long cpu_eiem = 0;
static void cpu_set_eiem(void *info)
{
set_eiem((unsigned long) info);
}
static inline void cpu_disable_irq(unsigned int irq)
static void cpu_disable_irq(unsigned int irq)
{
unsigned long eirr_bit = EIEM_MASK(irq);
cpu_eiem &= ~eirr_bit;
on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
/* Do nothing on the other CPUs. If they get this interrupt,
* The & cpu_eiem in the do_cpu_irq_mask() ensures they won't
* handle it, and the set_eiem() at the bottom will ensure it
* then gets disabled */
}
static void cpu_enable_irq(unsigned int irq)
{
unsigned long eirr_bit = EIEM_MASK(irq);
mtctl(eirr_bit, 23); /* clear EIRR bit before unmasking */
cpu_eiem |= eirr_bit;
on_each_cpu(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
/* FIXME: while our interrupts aren't nested, we cannot reset
* the eiem mask if we're already in an interrupt. Once we
* implement nested interrupts, this can go away
*/
if (!in_interrupt())
set_eiem(cpu_eiem);
/* This is just a simple NOP IPI. But what it does is cause
* all the other CPUs to do a set_eiem(cpu_eiem) at the end
* of the interrupt handler */
smp_send_all_nop();
}
static unsigned int cpu_startup_irq(unsigned int irq)
@ -74,6 +85,35 @@ static unsigned int cpu_startup_irq(unsigned int irq)
void no_ack_irq(unsigned int irq) { }
void no_end_irq(unsigned int irq) { }
#ifdef CONFIG_SMP
int cpu_check_affinity(unsigned int irq, cpumask_t *dest)
{
int cpu_dest;
/* timer and ipi have to always be received on all CPUs */
if (irq == TIMER_IRQ || irq == IPI_IRQ) {
/* Bad linux design decision. The mask has already
* been set; we must reset it */
irq_affinity[irq] = CPU_MASK_ALL;
return -EINVAL;
}
/* whatever mask they set, we just allow one CPU */
cpu_dest = first_cpu(*dest);
*dest = cpumask_of_cpu(cpu_dest);
return 0;
}
static void cpu_set_affinity_irq(unsigned int irq, cpumask_t dest)
{
if (cpu_check_affinity(irq, &dest))
return;
irq_affinity[irq] = dest;
}
#endif
static struct hw_interrupt_type cpu_interrupt_type = {
.typename = "CPU",
.startup = cpu_startup_irq,
@ -82,7 +122,9 @@ static struct hw_interrupt_type cpu_interrupt_type = {
.disable = cpu_disable_irq,
.ack = no_ack_irq,
.end = no_end_irq,
// .set_affinity = cpu_set_affinity_irq,
#ifdef CONFIG_SMP
.set_affinity = cpu_set_affinity_irq,
#endif
};
int show_interrupts(struct seq_file *p, void *v)
@ -219,6 +261,17 @@ int txn_alloc_irq(unsigned int bits_wide)
return -1;
}
unsigned long txn_affinity_addr(unsigned int irq, int cpu)
{
#ifdef CONFIG_SMP
irq_affinity[irq] = cpumask_of_cpu(cpu);
#endif
return cpu_data[cpu].txn_addr;
}
unsigned long txn_alloc_addr(unsigned int virt_irq)
{
static int next_cpu = -1;
@ -233,7 +286,7 @@ unsigned long txn_alloc_addr(unsigned int virt_irq)
if (next_cpu >= NR_CPUS)
next_cpu = 0; /* nothing else, assign monarch */
return cpu_data[next_cpu].txn_addr;
return txn_affinity_addr(virt_irq, next_cpu);
}
@ -250,10 +303,11 @@ void do_cpu_irq_mask(struct pt_regs *regs)
irq_enter();
/*
* Only allow interrupt processing to be interrupted by the
* timer tick
* Don't allow TIMER or IPI nested interrupts.
* Allowing any single interrupt to nest can lead to that CPU
* handling interrupts with all enabled interrupts unmasked.
*/
set_eiem(EIEM_MASK(TIMER_IRQ));
set_eiem(0UL);
/* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
* 2) We loop here on EIRR contents in order to avoid
@ -267,23 +321,41 @@ void do_cpu_irq_mask(struct pt_regs *regs)
if (!eirr_val)
break;
if (eirr_val & EIEM_MASK(TIMER_IRQ))
set_eiem(0);
mtctl(eirr_val, 23); /* reset bits we are going to process */
/* Work our way from MSb to LSb...same order we alloc EIRs */
for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
#ifdef CONFIG_SMP
cpumask_t dest = irq_affinity[irq];
#endif
if (!(bit & eirr_val))
continue;
/* clear bit in mask - can exit loop sooner */
eirr_val &= ~bit;
#ifdef CONFIG_SMP
/* FIXME: because generic set affinity mucks
* with the affinity before sending it to us
* we can get the situation where the affinity is
* wrong for our CPU type interrupts */
if (irq != TIMER_IRQ && irq != IPI_IRQ &&
!cpu_isset(smp_processor_id(), dest)) {
int cpu = first_cpu(dest);
printk(KERN_DEBUG "redirecting irq %d from CPU %d to %d\n",
irq, smp_processor_id(), cpu);
gsc_writel(irq + CPU_IRQ_BASE,
cpu_data[cpu].hpa);
continue;
}
#endif
__do_IRQ(irq, regs);
}
}
set_eiem(cpu_eiem);
set_eiem(cpu_eiem); /* restore original mask */
irq_exit();
}
@ -291,12 +363,14 @@ void do_cpu_irq_mask(struct pt_regs *regs)
static struct irqaction timer_action = {
.handler = timer_interrupt,
.name = "timer",
.flags = SA_INTERRUPT,
};
#ifdef CONFIG_SMP
static struct irqaction ipi_action = {
.handler = ipi_interrupt,
.name = "IPI",
.flags = SA_INTERRUPT,
};
#endif

View File

@ -196,8 +196,7 @@ static int perf_open(struct inode *inode, struct file *file);
static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos);
static ssize_t perf_write(struct file *file, const char __user *buf, size_t count,
loff_t *ppos);
static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg);
static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static void perf_start_counters(void);
static int perf_stop_counters(uint32_t *raddr);
static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num);
@ -438,48 +437,56 @@ static void perf_patch_images(void)
* must be running on the processor that you wish to change.
*/
static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long error_start;
uint32_t raddr[4];
int error = 0;
lock_kernel();
switch (cmd) {
case PA_PERF_ON:
/* Start the counters */
perf_start_counters();
return 0;
break;
case PA_PERF_OFF:
error_start = perf_stop_counters(raddr);
if (error_start != 0) {
printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start);
return -EFAULT;
error = -EFAULT;
break;
}
/* copy out the Counters */
if (copy_to_user((void __user *)arg, raddr,
sizeof (raddr)) != 0) {
return -EFAULT;
error = -EFAULT;
break;
}
return 0;
break;
case PA_PERF_VERSION:
/* Return the version # */
return put_user(PERF_VERSION, (int *)arg);
error = put_user(PERF_VERSION, (int *)arg);
break;
default:
break;
error = -ENOTTY;
}
return -ENOTTY;
unlock_kernel();
return error;
}
static struct file_operations perf_fops = {
.llseek = no_llseek,
.read = perf_read,
.write = perf_write,
.ioctl = perf_ioctl,
.unlocked_ioctl = perf_ioctl,
.compat_ioctl = perf_ioctl,
.open = perf_open,
.release = perf_release
};

View File

@ -264,6 +264,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
* sigkill. perhaps it should be put in the status
* that it wants to exit.
*/
ret = 0;
DBG("sys_ptrace(KILL)\n");
if (child->exit_state == EXIT_ZOMBIE) /* already dead */
goto out_tsk;
@ -344,11 +345,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
case PTRACE_GETEVENTMSG:
ret = put_user(child->ptrace_message, (unsigned int __user *) data);
goto out;
goto out_tsk;
default:
ret = ptrace_request(child, request, addr, data);
goto out;
goto out_tsk;
}
out_wake_notrap:

View File

@ -296,7 +296,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
struct rt_sigframe __user *frame;
unsigned long rp, usp;
unsigned long haddr, sigframe_size;
struct siginfo si;
int err = 0;
#ifdef __LP64__
compat_int_t compat_val;

View File

@ -181,12 +181,19 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
while (ops) {
unsigned long which = ffz(~ops);
ops &= ~(1 << which);
switch (which) {
case IPI_NOP:
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_NOP\n",this_cpu);
#endif /* kDEBUG */
break;
case IPI_RESCHEDULE:
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu);
#endif /* kDEBUG */
ops &= ~(1 << IPI_RESCHEDULE);
/*
* Reschedule callback. Everything to be
* done is done by the interrupt return path.
@ -197,7 +204,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu);
#endif /* kDEBUG */
ops &= ~(1 << IPI_CALL_FUNC);
{
volatile struct smp_call_struct *data;
void (*func)(void *info);
@ -231,7 +237,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu);
#endif /* kDEBUG */
ops &= ~(1 << IPI_CPU_START);
#ifdef ENTRY_SYS_CPUS
p->state = STATE_RUNNING;
#endif
@ -241,7 +246,6 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu);
#endif /* kDEBUG */
ops &= ~(1 << IPI_CPU_STOP);
#ifdef ENTRY_SYS_CPUS
#else
halt_processor();
@ -252,13 +256,11 @@ ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#if (kDEBUG>=100)
printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu);
#endif /* kDEBUG */
ops &= ~(1 << IPI_CPU_TEST);
break;
default:
printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
this_cpu, which);
ops &= ~(1 << which);
return IRQ_NONE;
} /* Switch */
} /* while (ops) */
@ -312,6 +314,12 @@ smp_send_start(void) { send_IPI_allbutself(IPI_CPU_START); }
void
smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); }
void
smp_send_all_nop(void)
{
send_IPI_allbutself(IPI_NOP);
}
/**
* Run a function on all other CPUs.
@ -339,6 +347,10 @@ smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
/* can also deadlock if IPIs are disabled */
WARN_ON((get_eiem() & (1UL<<(CPU_IRQ_MAX - IPI_IRQ))) == 0);
data.func = func;
data.info = info;
data.wait = wait;

View File

@ -164,7 +164,7 @@ linux_gateway_entry:
#endif
STREG %r2, TASK_PT_GR30(%r1) /* ... and save it */
STREG %r20, TASK_PT_GR20(%r1)
STREG %r20, TASK_PT_GR20(%r1) /* Syscall number */
STREG %r21, TASK_PT_GR21(%r1)
STREG %r22, TASK_PT_GR22(%r1)
STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */
@ -527,6 +527,7 @@ lws_compare_and_swap:
We *must* giveup this call and fail.
*/
ldw 4(%sr2,%r20), %r28 /* Load thread register */
/* WARNING: If cr27 cycles to the same value we have problems */
mfctl %cr27, %r21 /* Get current thread register */
cmpb,<>,n %r21, %r28, cas_lock /* Called recursive? */
b lws_exit /* Return error! */

View File

@ -1,6 +1,4 @@
/*
* linux/drivers/block/as-iosched.c
*
* Anticipatory & deadline i/o scheduler.
*
* Copyright (C) 2002 Jens Axboe <axboe@suse.de>

View File

@ -1,6 +1,4 @@
/*
* linux/drivers/block/cfq-iosched.c
*
* CFQ, or complete fairness queueing, disk scheduler.
*
* Based on ideas from a previously unfinished io

View File

@ -1,6 +1,4 @@
/*
* linux/drivers/block/deadline-iosched.c
*
* Deadline i/o scheduler.
*
* Copyright (C) 2002 Jens Axboe <axboe@suse.de>

View File

@ -1,6 +1,4 @@
/*
* linux/drivers/block/elevator.c
*
* Block device elevator/IO-scheduler.
*
* Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE

View File

@ -1,6 +1,4 @@
/*
* linux/drivers/block/ll_rw_blk.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994, Karl Keyte: Added support for disk statistics
* Elevator latency, (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE

View File

@ -1017,10 +1017,11 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
status = -ENOMEM;
goto cleanup1;
}
if (ioc->Request.Type.Direction == XFER_WRITE &&
copy_from_user(buff[sg_used], data_ptr, sz)) {
if (ioc->Request.Type.Direction == XFER_WRITE) {
if (copy_from_user(buff[sg_used], data_ptr, sz)) {
status = -ENOMEM;
goto cleanup1;
}
} else {
memset(buff[sg_used], 0, sz);
}
@ -1138,8 +1139,15 @@ static int revalidate_allvol(ctlr_info_t *host)
for(i=0; i< NWD; i++) {
struct gendisk *disk = host->gendisk[i];
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (disk) {
request_queue_t *q = disk->queue;
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (q)
blk_cleanup_queue(q);
put_disk(disk);
}
}
/*
@ -1453,10 +1461,13 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
* allows us to delete disk zero but keep the controller registered.
*/
if (h->gendisk[0] != disk){
if (disk->flags & GENHD_FL_UP){
blk_cleanup_queue(disk->queue);
del_gendisk(disk);
drv->queue = NULL;
if (disk) {
request_queue_t *q = disk->queue;
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (q)
blk_cleanup_queue(q);
put_disk(disk);
}
}
@ -3225,9 +3236,14 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
if (disk->flags & GENHD_FL_UP) {
del_gendisk(disk);
blk_cleanup_queue(disk->queue);
if (disk) {
request_queue_t *q = disk->queue;
if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (q)
blk_cleanup_queue(q);
put_disk(disk);
}
}

View File

@ -625,7 +625,7 @@ config BLK_DEV_NS87415
tristate "NS87415 chipset support"
help
This driver adds detection and support for the NS87415 chip
(used in SPARC64, among others).
(used mainly on SPARC64 and PA-RISC machines).
Please read the comments at the top of <file:drivers/ide/pci/ns87415.c>.

View File

@ -3328,8 +3328,8 @@ static ide_proc_entry_t idecd_proc[] = {
#endif
static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-cdrom",
.bus = &ide_bus_type,
.probe = ide_cd_probe,

View File

@ -1089,8 +1089,8 @@ static void ide_device_shutdown(struct device *dev)
}
static ide_driver_t idedisk_driver = {
.owner = THIS_MODULE,
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-disk",
.bus = &ide_bus_type,
.probe = ide_disk_probe,

View File

@ -1925,8 +1925,8 @@ static ide_proc_entry_t idefloppy_proc[] = {
static int ide_floppy_probe(struct device *);
static ide_driver_t idefloppy_driver = {
.owner = THIS_MODULE,
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-floppy",
.bus = &ide_bus_type,
.probe = ide_floppy_probe,

View File

@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
{
u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
if (on && drive->media == ide_disk) {
if (!PCI_DMA_BUS_IS_PHYS)
addr = BLK_BOUNCE_ANY;
else if (HWIF(drive)->pci_dev)
if (!PCI_DMA_BUS_IS_PHYS) {
addr = BLK_BOUNCE_ANY;
} else if (on && drive->media == ide_disk) {
if (HWIF(drive)->pci_dev)
addr = HWIF(drive)->pci_dev->dma_mask;
}

View File

@ -4748,8 +4748,8 @@ static ide_proc_entry_t idetape_proc[] = {
static int ide_tape_probe(struct device *);
static ide_driver_t idetape_driver = {
.owner = THIS_MODULE,
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-tape",
.bus = &ide_bus_type,
.probe = ide_tape_probe,

View File

@ -65,23 +65,6 @@ static struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
#define BUSCLOCK(D) \
((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D)))
#if 0
if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
(void) pci_read_config_byte(dev, 0x54, &art);
p += sprintf(p, "DMA Mode: %s(%s)",
(c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO",
(art&0x02)?"2":(art&0x01)?"1":"0");
p += sprintf(p, " %s(%s)",
(c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO",
(art&0x08)?"2":(art&0x04)?"1":"0");
p += sprintf(p, " %s(%s)",
(c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO",
(art&0x20)?"2":(art&0x10)?"1":"0");
p += sprintf(p, " %s(%s)\n",
(c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
(art&0x80)?"2":(art&0x40)?"1":"0");
} else {
#endif
/*
* TO DO: active tuning and correction of cards without a bios.
@ -112,13 +95,9 @@ static u8 aec62xx_ratemask (ide_drive_t *drive)
switch(hwif->pci_dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP865:
case PCI_DEVICE_ID_ARTOP_ATP865R:
#if 0
mode = (hwif->INB(hwif->dma_master) & 0x10) ? 4 : 3;
#else
mode = (hwif->INB(((hwif->channel) ?
hwif->mate->dma_status :
hwif->dma_status)) & 0x10) ? 4 : 3;
#endif
break;
case PCI_DEVICE_ID_ARTOP_ATP860:
case PCI_DEVICE_ID_ARTOP_ATP860R:
@ -263,35 +242,9 @@ static int aec62xx_irq_timeout (ide_drive_t *drive)
case PCI_DEVICE_ID_ARTOP_ATP865:
case PCI_DEVICE_ID_ARTOP_ATP865R:
printk(" AEC62XX time out ");
#if 0
{
int i = 0;
u8 reg49h = 0;
pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, &reg49h);
for (i=0;i<256;i++)
pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10);
pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10);
}
return 0;
#endif
default:
break;
}
#if 0
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u8 tmp1 = 0, tmp2 = 0, mode6 = 0;
pci_read_config_byte(dev, 0x44, &tmp1);
pci_read_config_byte(dev, 0x45, &tmp2);
printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2);
mode6 = HWIF(drive)->INB(((hwif->channel) ?
hwif->mate->dma_status :
hwif->dma_status));
printk(" AEC6280 133=%x ", (mode6 & 0x10));
}
#endif
return 0;
}

View File

@ -876,10 +876,15 @@ static ide_pci_device_t ali15x3_chipset __devinitdata = {
static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
static struct pci_device_id ati_rs100[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100) },
{ },
};
ide_pci_device_t *d = &ali15x3_chipset;
if(pci_find_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, NULL))
printk(KERN_ERR "Warning: ATI Radeon IGP Northbridge is not yet fully tested.\n");
if (pci_dev_present(ati_rs100))
printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
#if defined(CONFIG_SPARC64)
d->init_hwif = init_hwif_common_ali15x3;

View File

@ -222,10 +222,9 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
/* We must not grab the entire device, it has 'ISA' space in its
BARS too and we will freak out other bits of the kernel */
if(pci_enable_device_bars(dev, 1<<2))
{
if (pci_enable_device_bars(dev, 1<<2)) {
printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
return 1;
return -ENODEV;
}
pci_set_master(dev);
if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) {

View File

@ -6,7 +6,13 @@
*
* May be copied or modified under the terms of the GNU General Public License
*
* Documentation available under NDA only
* Documentation for CMD680:
* http://gkernel.sourceforge.net/specs/sii/sii-0680a-v1.31.pdf.bz2
*
* Documentation for SiI 3112:
* http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2
*
* Errata and other documentation only available under NDA.
*
*
* FAQ Items:

View File

@ -100,185 +100,14 @@ static struct via_isa_bridge {
{ NULL }
};
static struct via_isa_bridge *via_config;
static unsigned int via_80w;
static unsigned int via_clock;
static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100", "UDMA133" };
/*
* VIA /proc entry.
*/
#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
#include <linux/stat.h>
#include <linux/proc_fs.h>
static u8 via_proc = 0;
static unsigned long via_base;
static struct pci_dev *bmide_dev, *isa_dev;
static char *via_control3[] = { "No limit", "64", "128", "192" };
#define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg)
#define via_print_drive(name, format, arg...)\
p += sprintf(p, name); for (i = 0; i < 4; i++) p += sprintf(p, format, ## arg); p += sprintf(p, "\n");
/**
* via_get_info - generate via /proc file
* @buffer: buffer for data
* @addr: set to start of data to use
* @offset: current file offset
* @count: size of read
*
* Fills in buffer with the debugging/configuration information for
* the VIA chipset tuning and attached drives
*/
static int via_get_info(char *buffer, char **addr, off_t offset, int count)
struct via82cxxx_dev
{
int speed[4], cycle[4], setup[4], active[4], recover[4], den[4],
uen[4], udma[4], umul[4], active8b[4], recover8b[4];
struct pci_dev *dev = bmide_dev;
unsigned int v, u, i;
int len;
u16 c, w;
u8 t, x;
char *p = buffer;
via_print("----------VIA BusMastering IDE Configuration"
"----------------");
via_print("Driver Version: 3.38");
via_print("South Bridge: VIA %s",
via_config->name);
pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);
pci_read_config_byte(dev, PCI_REVISION_ID, &x);
via_print("Revision: ISA %#x IDE %#x", t, x);
via_print("Highest DMA rate: %s",
via_dma[via_config->flags & VIA_UDMA]);
via_print("BM-DMA base: %#lx", via_base);
via_print("PCI clock: %d.%dMHz",
via_clock / 1000, via_clock / 100 % 10);
pci_read_config_byte(dev, VIA_MISC_1, &t);
via_print("Master Read Cycle IRDY: %dws",
(t & 64) >> 6);
via_print("Master Write Cycle IRDY: %dws",
(t & 32) >> 5);
via_print("BM IDE Status Register Read Retry: %s",
(t & 8) ? "yes" : "no");
pci_read_config_byte(dev, VIA_MISC_3, &t);
via_print("Max DRDY Pulse Width: %s%s",
via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : "");
via_print("-----------------------Primary IDE"
"-------Secondary IDE------");
via_print("Read DMA FIFO flush: %10s%20s",
(t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no");
via_print("End Sector FIFO flush: %10s%20s",
(t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
pci_read_config_byte(dev, VIA_IDE_CONFIG, &t);
via_print("Prefetch Buffer: %10s%20s",
(t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no");
via_print("Post Write Buffer: %10s%20s",
(t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
pci_read_config_byte(dev, VIA_IDE_ENABLE, &t);
via_print("Enabled: %10s%20s",
(t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no");
c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8);
via_print("Simplex only: %10s%20s",
(c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no");
via_print("Cable Type: %10s%20s",
(via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w");
via_print("-------------------drive0----drive1"
"----drive2----drive3-----");
pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v);
pci_read_config_word(dev, VIA_8BIT_TIMING, &w);
if (via_config->flags & VIA_UDMA)
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
else u = 0;
for (i = 0; i < 4; i++) {
setup[i] = ((t >> ((3 - i) << 1)) & 0x3) + 1;
recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1;
active8b[i] = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1;
active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1;
udma[i] = ((u >> ((3 - i) << 3)) & 0x7) + 2;
umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2;
uen[i] = ((u >> ((3 - i) << 3)) & 0x20);
den[i] = (c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2));
speed[i] = 2 * via_clock / (active[i] + recover[i]);
cycle[i] = 1000000 * (active[i] + recover[i]) / via_clock;
if (!uen[i] || !den[i])
continue;
switch (via_config->flags & VIA_UDMA) {
case VIA_UDMA_33:
speed[i] = 2 * via_clock / udma[i];
cycle[i] = 1000000 * udma[i] / via_clock;
break;
case VIA_UDMA_66:
speed[i] = 4 * via_clock / (udma[i] * umul[i]);
cycle[i] = 500000 * (udma[i] * umul[i]) / via_clock;
break;
case VIA_UDMA_100:
speed[i] = 6 * via_clock / udma[i];
cycle[i] = 333333 * udma[i] / via_clock;
break;
case VIA_UDMA_133:
speed[i] = 8 * via_clock / udma[i];
cycle[i] = 250000 * udma[i] / via_clock;
break;
}
}
via_print_drive("Transfer Mode: ", "%10s",
den[i] ? (uen[i] ? "UDMA" : "DMA") : "PIO");
via_print_drive("Address Setup: ", "%8dns",
1000000 * setup[i] / via_clock);
via_print_drive("Cmd Active: ", "%8dns",
1000000 * active8b[i] / via_clock);
via_print_drive("Cmd Recovery: ", "%8dns",
1000000 * recover8b[i] / via_clock);
via_print_drive("Data Active: ", "%8dns",
1000000 * active[i] / via_clock);
via_print_drive("Data Recovery: ", "%8dns",
1000000 * recover[i] / via_clock);
via_print_drive("Cycle Time: ", "%8dns",
cycle[i]);
via_print_drive("Transfer Rate: ", "%4d.%dMB/s",
speed[i] / 1000, speed[i] / 100 % 10);
/* hoping it is less than 4K... */
len = (p - buffer) - offset;
*addr = buffer + offset;
return len > count ? count : len;
}
#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */
struct via_isa_bridge *via_config;
unsigned int via_80w;
};
/**
* via_set_speed - write timing registers
@ -289,11 +118,13 @@ static int via_get_info(char *buffer, char **addr, off_t offset, int count)
* via_set_speed writes timing values to the chipset registers
*/
static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing)
static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
{
struct pci_dev *dev = hwif->pci_dev;
struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif);
u8 t;
if (~via_config->flags & VIA_BAD_AST) {
if (~vdev->via_config->flags & VIA_BAD_AST) {
pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
@ -305,7 +136,7 @@ static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing)
pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
switch (via_config->flags & VIA_UDMA) {
switch (vdev->via_config->flags & VIA_UDMA) {
case VIA_UDMA_33: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
case VIA_UDMA_66: t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
@ -329,6 +160,7 @@ static void via_set_speed(struct pci_dev *dev, u8 dn, struct ide_timing *timing)
static int via_set_drive(ide_drive_t *drive, u8 speed)
{
ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
struct via82cxxx_dev *vdev = ide_get_hwifdata(drive->hwif);
struct ide_timing t, p;
unsigned int T, UT;
@ -337,7 +169,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
T = 1000000000 / via_clock;
switch (via_config->flags & VIA_UDMA) {
switch (vdev->via_config->flags & VIA_UDMA) {
case VIA_UDMA_33: UT = T; break;
case VIA_UDMA_66: UT = T/2; break;
case VIA_UDMA_100: UT = T/3; break;
@ -352,7 +184,7 @@ static int via_set_drive(ide_drive_t *drive, u8 speed)
ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
}
via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
via_set_speed(HWIF(drive), drive->dn, &t);
if (!drive->init_speed)
drive->init_speed = speed;
@ -390,20 +222,41 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio)
static int via82cxxx_ide_dma_check (ide_drive_t *drive)
{
u16 w80 = HWIF(drive)->udma_four;
ide_hwif_t *hwif = HWIF(drive);
struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif);
u16 w80 = hwif->udma_four;
u16 speed = ide_find_best_mode(drive,
XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
(via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
(w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
(w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
(w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
(vdev->via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0) |
(w80 && (vdev->via_config->flags & VIA_UDMA) >= VIA_UDMA_133 ? XFER_UDMA_133 : 0));
via_set_drive(drive, speed);
if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
return HWIF(drive)->ide_dma_on(drive);
return HWIF(drive)->ide_dma_off_quietly(drive);
return hwif->ide_dma_on(drive);
return hwif->ide_dma_off_quietly(drive);
}
static struct via_isa_bridge *via_config_find(struct pci_dev **isa)
{
struct via_isa_bridge *via_config;
u8 t;
for (via_config = via_isa_bridges; via_config->id; via_config++)
if ((*isa = pci_find_device(PCI_VENDOR_ID_VIA +
!!(via_config->flags & VIA_BAD_ID),
via_config->id, NULL))) {
pci_read_config_byte(*isa, PCI_REVISION_ID, &t);
if (t >= via_config->rev_min &&
t <= via_config->rev_max)
break;
}
return via_config;
}
/**
@ -418,82 +271,28 @@ static int via82cxxx_ide_dma_check (ide_drive_t *drive)
static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name)
{
struct pci_dev *isa = NULL;
struct via_isa_bridge *via_config;
u8 t, v;
unsigned int u;
int i;
/*
* Find the ISA bridge to see how good the IDE is.
*/
for (via_config = via_isa_bridges; via_config->id; via_config++)
if ((isa = pci_find_device(PCI_VENDOR_ID_VIA +
!!(via_config->flags & VIA_BAD_ID),
via_config->id, NULL))) {
pci_read_config_byte(isa, PCI_REVISION_ID, &t);
if (t >= via_config->rev_min &&
t <= via_config->rev_max)
break;
}
via_config = via_config_find(&isa);
if (!via_config->id) {
printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, disabling DMA.\n");
return -ENODEV;
}
/*
* Check 80-wire cable presence and setup Clk66.
* Setup or disable Clk66 if appropriate
*/
switch (via_config->flags & VIA_UDMA) {
case VIA_UDMA_66:
/* Enable Clk66 */
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
for (i = 24; i >= 0; i -= 8)
if (((u >> (i & 16)) & 8) &&
((u >> i) & 0x20) &&
(((u >> i) & 7) < 2)) {
/*
* 2x PCI clock and
* UDMA w/ < 3T/cycle
*/
via_80w |= (1 << (1 - (i >> 4)));
}
break;
case VIA_UDMA_100:
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
(((u >> i) & 7) < 4))) {
/* BIOS 80-wire bit or
* UDMA w/ < 60ns/cycle
*/
via_80w |= (1 << (1 - (i >> 4)));
}
break;
case VIA_UDMA_133:
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
(((u >> i) & 7) < 6))) {
/* BIOS 80-wire bit or
* UDMA w/ < 60ns/cycle
*/
via_80w |= (1 << (1 - (i >> 4)));
}
break;
}
/* Disable Clk66 */
if (via_config->flags & VIA_BAD_CLK66) {
if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) {
/* Enable Clk66 */
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008);
} else if (via_config->flags & VIA_BAD_CLK66) {
/* Would cause trouble on 596a and 686 */
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008);
@ -560,26 +359,78 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const
via_dma[via_config->flags & VIA_UDMA],
pci_name(dev));
/*
* Setup /proc/ide/via entry.
*/
#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
if (!via_proc) {
via_base = pci_resource_start(dev, 4);
bmide_dev = dev;
isa_dev = isa;
ide_pci_create_host_proc("via", via_get_info);
via_proc = 1;
}
#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */
return 0;
}
/*
* Check and handle 80-wire cable presence
*/
static void __devinit via_cable_detect(struct pci_dev *dev, struct via82cxxx_dev *vdev)
{
unsigned int u;
int i;
pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
switch (vdev->via_config->flags & VIA_UDMA) {
case VIA_UDMA_66:
for (i = 24; i >= 0; i -= 8)
if (((u >> (i & 16)) & 8) &&
((u >> i) & 0x20) &&
(((u >> i) & 7) < 2)) {
/*
* 2x PCI clock and
* UDMA w/ < 3T/cycle
*/
vdev->via_80w |= (1 << (1 - (i >> 4)));
}
break;
case VIA_UDMA_100:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
(((u >> i) & 7) < 4))) {
/* BIOS 80-wire bit or
* UDMA w/ < 60ns/cycle
*/
vdev->via_80w |= (1 << (1 - (i >> 4)));
}
break;
case VIA_UDMA_133:
for (i = 24; i >= 0; i -= 8)
if (((u >> i) & 0x10) ||
(((u >> i) & 0x20) &&
(((u >> i) & 7) < 6))) {
/* BIOS 80-wire bit or
* UDMA w/ < 60ns/cycle
*/
vdev->via_80w |= (1 << (1 - (i >> 4)));
}
break;
}
}
static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
{
struct via82cxxx_dev *vdev = kmalloc(sizeof(struct via82cxxx_dev),
GFP_KERNEL);
struct pci_dev *isa = NULL;
int i;
if (vdev == NULL) {
printk(KERN_ERR "VP_IDE: out of memory :(\n");
return;
}
memset(vdev, 0, sizeof(struct via82cxxx_dev));
ide_set_hwifdata(hwif, vdev);
vdev->via_config = via_config_find(&isa);
via_cable_detect(hwif->pci_dev, vdev);
hwif->autodma = 0;
hwif->tuneproc = &via82cxxx_tune_drive;
@ -594,7 +445,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
for (i = 0; i < 2; i++) {
hwif->drives[i].io_32bit = 1;
hwif->drives[i].unmask = (via_config->flags & VIA_NO_UNMASK) ? 0 : 1;
hwif->drives[i].unmask = (vdev->via_config->flags & VIA_NO_UNMASK) ? 0 : 1;
hwif->drives[i].autotune = 1;
hwif->drives[i].dn = hwif->channel * 2 + i;
}
@ -608,7 +459,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
hwif->swdma_mask = 0x07;
if (!hwif->udma_four)
hwif->udma_four = (via_80w >> hwif->channel) & 1;
hwif->udma_four = (vdev->via_80w >> hwif->channel) & 1;
hwif->ide_dma_check = &via82cxxx_ide_dma_check;
if (!noautodma)
hwif->autodma = 1;

View File

@ -1401,20 +1401,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
/* We probe the hwif now */
probe_hwif_init(hwif);
/* The code IDE code will have set hwif->present if we have devices attached,
* if we don't, the discard the interface except if we are on a media bay slot
*/
if (!hwif->present && !pmif->mediabay) {
printk(KERN_INFO "ide%d: Bus empty, interface released.\n",
hwif->index);
default_hwif_iops(hwif);
for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; ++i)
hwif->io_ports[i] = 0;
hwif->chipset = ide_unknown;
hwif->noprobe = 1;
return -ENODEV;
}
return 0;
}

View File

@ -787,7 +787,7 @@ static int pre_init = 1; /* Before first ordered IDE scan */
static LIST_HEAD(ide_pci_drivers);
/*
* __ide_register_pci_driver - attach IDE driver
* __ide_pci_register_driver - attach IDE driver
* @driver: pci driver
* @module: owner module of the driver
*

View File

@ -312,7 +312,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
int ret, length, hdr_len, copy_offset;
int rmpp_active = 0;
if (count < sizeof (struct ib_user_mad))
if (count < sizeof (struct ib_user_mad) + IB_MGMT_RMPP_HDR)
return -EINVAL;
length = count - sizeof (struct ib_user_mad);

View File

@ -730,14 +730,15 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
}
if (attr_mask & IB_QP_ACCESS_FLAGS) {
qp_context->params2 |=
cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ?
MTHCA_QP_BIT_RWE : 0);
/*
* Only enable RDMA/atomics if we have responder
* resources set to a non-zero value.
* Only enable RDMA reads and atomics if we have
* responder resources set to a non-zero value.
*/
if (qp->resp_depth) {
qp_context->params2 |=
cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ?
MTHCA_QP_BIT_RWE : 0);
qp_context->params2 |=
cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_READ ?
MTHCA_QP_BIT_RRE : 0);
@ -759,22 +760,19 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
if (qp->resp_depth && !attr->max_dest_rd_atomic) {
/*
* Lowering our responder resources to zero.
* Turn off RDMA/atomics as responder.
* (RWE/RRE/RAE in params2 already zero)
* Turn off reads RDMA and atomics as responder.
* (RRE/RAE in params2 already zero)
*/
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
MTHCA_QP_OPTPAR_RRE |
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE |
MTHCA_QP_OPTPAR_RAE);
}
if (!qp->resp_depth && attr->max_dest_rd_atomic) {
/*
* Increasing our responder resources from
* zero. Turn on RDMA/atomics as appropriate.
* zero. Turn on RDMA reads and atomics as
* appropriate.
*/
qp_context->params2 |=
cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_WRITE ?
MTHCA_QP_BIT_RWE : 0);
qp_context->params2 |=
cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_READ ?
MTHCA_QP_BIT_RRE : 0);
@ -782,8 +780,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_ATOMIC ?
MTHCA_QP_BIT_RAE : 0);
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE |
MTHCA_QP_OPTPAR_RRE |
qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE |
MTHCA_QP_OPTPAR_RAE);
}
@ -921,10 +918,12 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev,
else
qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE;
qp->sq.max_gs = max_data_size / sizeof (struct mthca_data_seg);
qp->rq.max_gs = (min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) -
sizeof (struct mthca_next_seg)) /
sizeof (struct mthca_data_seg);
qp->sq.max_gs = min_t(int, dev->limits.max_sg,
max_data_size / sizeof (struct mthca_data_seg));
qp->rq.max_gs = min_t(int, dev->limits.max_sg,
(min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) -
sizeof (struct mthca_next_seg)) /
sizeof (struct mthca_data_seg));
}
/*

View File

@ -802,13 +802,21 @@ static int srp_post_recv(struct srp_target_port *target)
/*
* Must be called with target->scsi_host->host_lock held to protect
* req_lim and tx_head.
* req_lim and tx_head. Lock cannot be dropped between call here and
* call to __srp_post_send().
*/
static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target)
{
if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
return NULL;
if (unlikely(target->req_lim < 1)) {
if (printk_ratelimit())
printk(KERN_DEBUG PFX "Target has req_lim %d\n",
target->req_lim);
return NULL;
}
return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
}
@ -823,11 +831,6 @@ static int __srp_post_send(struct srp_target_port *target,
struct ib_send_wr wr, *bad_wr;
int ret = 0;
if (target->req_lim < 1) {
printk(KERN_ERR PFX "Target has req_lim %d\n", target->req_lim);
return -EAGAIN;
}
list.addr = iu->dma;
list.length = len;
list.lkey = target->srp_host->mr->lkey;
@ -1417,6 +1420,8 @@ static ssize_t srp_create_target(struct class_device *class_dev,
if (!target_host)
return -ENOMEM;
target_host->max_lun = SRP_MAX_LUN;
target = host_to_target(target_host);
memset(target, 0, sizeof *target);

View File

@ -54,6 +54,7 @@ enum {
SRP_PORT_REDIRECT = 1,
SRP_DLID_REDIRECT = 2,
SRP_MAX_LUN = 512,
SRP_MAX_IU_LEN = 256,
SRP_RQ_SHIFT = 6,

View File

@ -110,7 +110,7 @@ config HISAX_16_3
config HISAX_TELESPCI
bool "Teles PCI"
depends on PCI && (BROKEN || !(SPARC64 || PPC))
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
help
This enables HiSax support for the Teles PCI.
See <file:Documentation/isdn/README.HiSax> on how to configure it.
@ -238,7 +238,7 @@ config HISAX_MIC
config HISAX_NETJET
bool "NETjet card"
depends on PCI && (BROKEN || !(SPARC64 || PPC))
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
help
This enables HiSax support for the NetJet from Traverse
Technologies.
@ -249,7 +249,7 @@ config HISAX_NETJET
config HISAX_NETJET_U
bool "NETspider U card"
depends on PCI && (BROKEN || !(SPARC64 || PPC))
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
help
This enables HiSax support for the Netspider U interface ISDN card
from Traverse Technologies.
@ -317,7 +317,7 @@ config HISAX_GAZEL
config HISAX_HFC_PCI
bool "HFC PCI-Bus cards"
depends on PCI && (BROKEN || !(SPARC64 || PPC))
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
help
This enables HiSax support for the HFC-S PCI 2BDS0 based cards.
@ -344,14 +344,14 @@ config HISAX_HFC_SX
config HISAX_ENTERNOW_PCI
bool "Formula-n enter:now PCI card"
depends on PCI && (BROKEN || !(SPARC64 || PPC))
depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K))
help
This enables HiSax support for the Formula-n enter:now PCI
ISDN card.
config HISAX_AMD7930
bool "Am7930 (EXPERIMENTAL)"
depends on EXPERIMENTAL && (SPARC32 || SPARC64)
depends on EXPERIMENTAL && SPARC
help
This enables HiSax support for the AMD7930 chips on some SPARCs.
This code is not finished yet.

View File

@ -3,7 +3,7 @@
#
config ISDN_DRV_PCBIT
tristate "PCBIT-D support"
depends on ISDN_I4L && ISA && (BROKEN || !PPC)
depends on ISDN_I4L && ISA && (BROKEN || X86)
help
This enables support for the PCBIT ISDN-card. This card is
manufactured in Portugal by Octal. For running this card,

View File

@ -700,6 +700,28 @@ static unsigned int iosapic_startup_irq(unsigned int irq)
return 0;
}
#ifdef CONFIG_SMP
static void iosapic_set_affinity_irq(unsigned int irq, cpumask_t dest)
{
struct vector_info *vi = iosapic_get_vector(irq);
u32 d0, d1, dummy_d0;
unsigned long flags;
if (cpu_check_affinity(irq, &dest))
return;
vi->txn_addr = txn_affinity_addr(irq, first_cpu(dest));
spin_lock_irqsave(&iosapic_lock, flags);
/* d1 contains the destination CPU, so only want to set that
* entry */
iosapic_rd_irt_entry(vi, &d0, &d1);
iosapic_set_irt_data(vi, &dummy_d0, &d1);
iosapic_wr_irt_entry(vi, d0, d1);
spin_unlock_irqrestore(&iosapic_lock, flags);
}
#endif
static struct hw_interrupt_type iosapic_interrupt_type = {
.typename = "IO-SAPIC-level",
.startup = iosapic_startup_irq,
@ -708,7 +730,9 @@ static struct hw_interrupt_type iosapic_interrupt_type = {
.disable = iosapic_disable_irq,
.ack = no_ack_irq,
.end = iosapic_end_irq,
// .set_affinity = iosapic_set_affinity_irq,
#ifdef CONFIG_SMP
.set_affinity = iosapic_set_affinity_irq,
#endif
};
int iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)

View File

@ -24,6 +24,9 @@
* Major changes to get basic interrupt infrastructure working to
* hopefully be able to support all SuperIO devices. Currently
* works with serial. -- John Marvin <jsm@fc.hp.com>
*
* Converted superio_init() to be a PCI_FIXUP_FINAL callee.
* -- Kyle McMartin <kyle@parisc-linux.org>
*/
@ -141,10 +144,10 @@ superio_interrupt(int parent_irq, void *devp, struct pt_regs *regs)
}
/* Initialize Super I/O device */
static void __devinit
superio_init(struct superio_device *sio)
static void
superio_init(struct pci_dev *pcidev)
{
struct superio_device *sio = &sio_dev;
struct pci_dev *pdev = sio->lio_pdev;
u16 word;
@ -160,8 +163,8 @@ superio_init(struct superio_device *sio)
/* ...then properly fixup the USB to point at suckyio PIC */
sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
printk (KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
pci_name(pdev),pdev->irq);
printk(KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
pci_name(pdev), pdev->irq);
pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
sio->sp1_base &= ~1;
@ -274,7 +277,7 @@ superio_init(struct superio_device *sio)
sio->suckyio_irq_enabled = 1;
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init);
static void superio_disable_irq(unsigned int irq)
{
@ -452,8 +455,10 @@ static void superio_fixup_pci(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci);
static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
static int __devinit
superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct superio_device *sio = &sio_dev;
/*
** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a
@ -466,7 +471,8 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_
dev->subsystem_vendor, dev->subsystem_device,
dev->class);
superio_init(&sio_dev);
if (!sio->suckyio_irq_enabled)
BUG(); /* Enabled by PCI_FIXUP_FINAL */
if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */
superio_parport_init();
@ -486,14 +492,16 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_
}
static struct pci_device_id superio_tbl[] = {
{ PCI_VENDOR_ID_NS, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_USB) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415) },
{ 0, }
};
static struct pci_driver superio_driver = {
.name = "SuperIO",
.id_table = superio_tbl,
.probe = superio_probe,
.name = "SuperIO",
.id_table = superio_tbl,
.probe = superio_probe,
};
static int __init superio_modinit(void)
@ -506,6 +514,5 @@ static void __exit superio_exit(void)
pci_unregister_driver(&superio_driver);
}
module_init(superio_modinit);
module_exit(superio_exit);

View File

@ -784,8 +784,8 @@ static ide_proc_entry_t idescsi_proc[] = {
#endif
static ide_driver_t idescsi_driver = {
.owner = THIS_MODULE,
.gen_driver = {
.owner = THIS_MODULE,
.name = "ide-scsi",
.bus = &ide_bus_type,
.probe = ide_scsi_probe,

View File

@ -2,6 +2,7 @@
* sata_mv.c - Marvell SATA support
*
* Copyright 2005: EMC Corporation, all rights reserved.
* Copyright 2005 Red Hat, Inc. All rights reserved.
*
* Please ALWAYS copy linux-ide@vger.kernel.org on emails.
*
@ -36,7 +37,7 @@
#include <asm/io.h>
#define DRV_NAME "sata_mv"
#define DRV_VERSION "0.25"
#define DRV_VERSION "0.5"
enum {
/* BAR's are enumerated in terms of pci_resource_start() terms */

View File

@ -5,17 +5,6 @@
*
* Based on preview driver from Silicon Image.
*
* NOTE: No NCQ/ATAPI support yet. The preview driver didn't support
* NCQ nor ATAPI, and, unfortunately, I couldn't find out how to make
* those work. Enabling those shouldn't be difficult. Basic
* structure is all there (in libata-dev tree). If you have any
* information about this hardware, please contact me or linux-ide.
* Info is needed on...
*
* - How to issue tagged commands and turn on sactive on issue accordingly.
* - Where to put an ATAPI command and how to tell the device to send it.
* - How to enable/use 64bit.
*
* 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, or (at your option) any
@ -42,7 +31,7 @@
#include <asm/io.h>
#define DRV_NAME "sata_sil24"
#define DRV_VERSION "0.22" /* Silicon Image's preview driver was 0.10 */
#define DRV_VERSION "0.23"
/*
* Port request block (PRB) 32 bytes
@ -221,11 +210,22 @@ enum {
IRQ_STAT_4PORTS = 0xf,
};
struct sil24_cmd_block {
struct sil24_ata_block {
struct sil24_prb prb;
struct sil24_sge sge[LIBATA_MAX_PRD];
};
struct sil24_atapi_block {
struct sil24_prb prb;
u8 cdb[16];
struct sil24_sge sge[LIBATA_MAX_PRD - 1];
};
union sil24_cmd_block {
struct sil24_ata_block ata;
struct sil24_atapi_block atapi;
};
/*
* ap->private_data
*
@ -233,7 +233,7 @@ struct sil24_cmd_block {
* here from the previous interrupt.
*/
struct sil24_port_priv {
struct sil24_cmd_block *cmd_block; /* 32 cmd blocks */
union sil24_cmd_block *cmd_block; /* 32 cmd blocks */
dma_addr_t cmd_block_dma; /* DMA base addr for them */
struct ata_taskfile tf; /* Cached taskfile registers */
};
@ -244,6 +244,7 @@ struct sil24_host_priv {
void __iomem *port_base; /* port registers (4 * 8192 bytes @BAR2) */
};
static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev);
static u8 sil24_check_status(struct ata_port *ap);
static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
@ -297,6 +298,8 @@ static struct scsi_host_template sil24_sht = {
static const struct ata_port_operations sil24_ops = {
.port_disable = ata_port_disable,
.dev_config = sil24_dev_config,
.check_status = sil24_check_status,
.check_altstatus = sil24_check_status,
.dev_select = ata_noop_dev_select,
@ -333,7 +336,7 @@ static struct ata_port_info sil24_port_info[] = {
{
.sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
ATA_FLAG_SRST | ATA_FLAG_MMIO |
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(4),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@ -344,7 +347,7 @@ static struct ata_port_info sil24_port_info[] = {
{
.sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
ATA_FLAG_SRST | ATA_FLAG_MMIO |
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(2),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@ -355,7 +358,7 @@ static struct ata_port_info sil24_port_info[] = {
{
.sht = &sil24_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
ATA_FLAG_SRST | ATA_FLAG_MMIO |
ATA_FLAG_PIO_DMA | SIL24_NPORTS2FLAG(1),
.pio_mask = 0x1f, /* pio0-4 */
.mwdma_mask = 0x07, /* mwdma0-2 */
@ -364,6 +367,16 @@ static struct ata_port_info sil24_port_info[] = {
},
};
static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
{
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
if (ap->cdb_len == 16)
writel(PORT_CS_CDB16, port + PORT_CTRL_STAT);
else
writel(PORT_CS_CDB16, port + PORT_CTRL_CLR);
}
static inline void sil24_update_tf(struct ata_port *ap)
{
struct sil24_port_priv *pp = ap->private_data;
@ -415,22 +428,73 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
*tf = pp->tf;
}
static int sil24_issue_SRST(struct ata_port *ap)
{
void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
struct sil24_port_priv *pp = ap->private_data;
struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
dma_addr_t paddr = pp->cmd_block_dma;
u32 irq_enable, irq_stat;
int cnt;
/* temporarily turn off IRQs during SRST */
irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
writel(irq_enable, port + PORT_IRQ_ENABLE_CLR);
/*
* XXX: Not sure whether the following sleep is needed or not.
* The original driver had it. So....
*/
msleep(10);
prb->ctrl = PRB_CTRL_SRST;
prb->fis[1] = 0; /* no PM yet */
writel((u32)paddr, port + PORT_CMD_ACTIVATE);
for (cnt = 0; cnt < 100; cnt++) {
irq_stat = readl(port + PORT_IRQ_STAT);
writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */
irq_stat >>= PORT_IRQ_RAW_SHIFT;
if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
break;
msleep(1);
}
/* restore IRQs */
writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
if (!(irq_stat & PORT_IRQ_COMPLETE))
return -1;
/* update TF */
sil24_update_tf(ap);
return 0;
}
static void sil24_phy_reset(struct ata_port *ap)
{
struct sil24_port_priv *pp = ap->private_data;
__sata_phy_reset(ap);
/*
* No ATAPI yet. Just unconditionally indicate ATA device.
* If ATAPI device is attached, it will fail ATA_CMD_ID_ATA
* and libata core will ignore the device.
*/
if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
ap->device[0].class = ATA_DEV_ATA;
if (ap->flags & ATA_FLAG_PORT_DISABLED)
return;
if (sil24_issue_SRST(ap) < 0) {
printk(KERN_ERR DRV_NAME
" ata%u: SRST failed, disabling port\n", ap->id);
ap->ops->port_disable(ap);
return;
}
ap->device->class = ata_dev_classify(&pp->tf);
}
static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
struct sil24_cmd_block *cb)
struct sil24_sge *sge)
{
struct sil24_sge *sge = cb->sge;
struct scatterlist *sg;
unsigned int idx = 0;
@ -451,23 +515,47 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
struct sil24_port_priv *pp = ap->private_data;
struct sil24_cmd_block *cb = pp->cmd_block + qc->tag;
struct sil24_prb *prb = &cb->prb;
union sil24_cmd_block *cb = pp->cmd_block + qc->tag;
struct sil24_prb *prb;
struct sil24_sge *sge;
switch (qc->tf.protocol) {
case ATA_PROT_PIO:
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
prb = &cb->ata.prb;
sge = cb->ata.sge;
prb->ctrl = 0;
break;
case ATA_PROT_ATAPI:
case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI_NODATA:
prb = &cb->atapi.prb;
sge = cb->atapi.sge;
memset(cb->atapi.cdb, 0, 32);
memcpy(cb->atapi.cdb, qc->cdb, ap->cdb_len);
if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
if (qc->tf.flags & ATA_TFLAG_WRITE)
prb->ctrl = PRB_CTRL_PACKET_WRITE;
else
prb->ctrl = PRB_CTRL_PACKET_READ;
} else
prb->ctrl = 0;
break;
default:
/* ATAPI isn't supported yet */
prb = NULL; /* shut up, gcc */
sge = NULL;
BUG();
}
ata_tf_to_fis(&qc->tf, prb->fis, 0);
if (qc->flags & ATA_QCFLAG_DMAMAP)
sil24_fill_sg(qc, cb);
sil24_fill_sg(qc, sge);
}
static int sil24_qc_issue(struct ata_queued_cmd *qc)
@ -486,6 +574,31 @@ static void sil24_irq_clear(struct ata_port *ap)
/* unused */
}
static int __sil24_restart_controller(void __iomem *port)
{
u32 tmp;
int cnt;
writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
/* Max ~10ms */
for (cnt = 0; cnt < 10000; cnt++) {
tmp = readl(port + PORT_CTRL_STAT);
if (tmp & PORT_CS_RDY)
return 0;
udelay(1);
}
return -1;
}
static void sil24_restart_controller(struct ata_port *ap)
{
if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr))
printk(KERN_ERR DRV_NAME
" ata%u: failed to restart controller\n", ap->id);
}
static int __sil24_reset_controller(void __iomem *port)
{
int cnt;
@ -505,7 +618,11 @@ static int __sil24_reset_controller(void __iomem *port)
if (tmp & PORT_CS_DEV_RST)
return -1;
return 0;
if (tmp & PORT_CS_RDY)
return 0;
return __sil24_restart_controller(port);
}
static void sil24_reset_controller(struct ata_port *ap)
@ -567,9 +684,15 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
if (serror)
writel(serror, port + PORT_SERROR);
printk(KERN_ERR DRV_NAME " ata%u: error interrupt on port%d\n"
" stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
/*
* Don't log ATAPI device errors. They're supposed to happen
* and any serious errors will be logged using sense data by
* the SCSI layer.
*/
if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB)
printk("ata%u: error interrupt on port%d\n"
" stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
/*
@ -577,6 +700,7 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
*/
sil24_update_tf(ap);
err_mask = ac_err_mask(pp->tf.command);
sil24_restart_controller(ap);
} else {
/*
* Other errors. libata currently doesn't have any
@ -584,12 +708,11 @@ static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
* ATA_ERR.
*/
err_mask = AC_ERR_OTHER;
sil24_reset_controller(ap);
}
if (qc)
ata_qc_complete(qc, err_mask);
sil24_reset_controller(ap);
}
static inline void sil24_host_intr(struct ata_port *ap)
@ -665,7 +788,7 @@ static int sil24_port_start(struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
struct sil24_port_priv *pp;
struct sil24_cmd_block *cb;
union sil24_cmd_block *cb;
size_t cb_size = sizeof(*cb);
dma_addr_t cb_dma;
int rc = -ENOMEM;

View File

@ -507,7 +507,7 @@ config SERIAL_SUNSU_CONSOLE
config SERIAL_MUX
tristate "Serial MUX support"
depends on PARISC
depends on GSC
select SERIAL_CORE
default y
---help---

View File

@ -65,8 +65,8 @@ static struct uart_driver mux_driver = {
static struct timer_list mux_timer;
#define UART_PUT_CHAR(p, c) __raw_writel((c), (unsigned long)(p)->membase + IO_DATA_REG_OFFSET)
#define UART_GET_FIFO_CNT(p) __raw_readl((unsigned long)(p)->membase + IO_DCOUNT_REG_OFFSET)
#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + IO_DATA_REG_OFFSET)
#define UART_GET_FIFO_CNT(p) __raw_readl((p)->membase + IO_DCOUNT_REG_OFFSET)
#define GET_MUX_PORTS(iodc_data) ((((iodc_data)[4] & 0xf0) >> 4) * 8) + 8
/**
@ -79,10 +79,7 @@ static struct timer_list mux_timer;
*/
static unsigned int mux_tx_empty(struct uart_port *port)
{
unsigned int cnt = __raw_readl((unsigned long)port->membase
+ IO_DCOUNT_REG_OFFSET);
return cnt ? 0 : TIOCSER_TEMT;
return UART_GET_FIFO_CNT(port) ? 0 : TIOCSER_TEMT;
}
/**
@ -218,8 +215,7 @@ static void mux_read(struct uart_port *port)
__u32 start_count = port->icount.rx;
while(1) {
data = __raw_readl((unsigned long)port->membase
+ IO_DATA_REG_OFFSET);
data = __raw_readl(port->membase + IO_DATA_REG_OFFSET);
if (MUX_STATUS(data))
continue;
@ -481,6 +477,13 @@ static int __init mux_probe(struct parisc_device *dev)
port->ops = &mux_pops;
port->flags = UPF_BOOT_AUTOCONF;
port->line = port_cnt;
/* The port->timeout needs to match what is present in
* uart_wait_until_sent in serial_core.c. Otherwise
* the time spent in msleep_interruptable will be very
* long, causing the appearance of a console hang.
*/
port->timeout = HZ / 50;
spin_lock_init(&port->lock);
status = uart_add_one_port(&mux_driver, port);
BUG_ON(status);

View File

@ -137,7 +137,7 @@
#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int)
#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int)
#define EXT3_IOC32_GETVERSION _IOR('f', 3, int)
#define EXT3_IOC32_SETVERSION _IOR('f', 4, int)
#define EXT3_IOC32_SETVERSION _IOW('f', 4, int)
#define EXT3_IOC32_GETRSVSZ _IOR('f', 5, int)
#define EXT3_IOC32_SETRSVSZ _IOW('f', 6, int)
#define EXT3_IOC32_GROUP_EXTEND _IOW('f', 7, unsigned int)

View File

@ -8,6 +8,7 @@
#define _ASM_PARISC_IRQ_H
#include <linux/config.h>
#include <linux/cpumask.h>
#include <asm/types.h>
#define NO_IRQ (-1)
@ -49,10 +50,10 @@ extern int txn_alloc_irq(unsigned int nbits);
extern int txn_claim_irq(int);
extern unsigned int txn_alloc_data(unsigned int);
extern unsigned long txn_alloc_addr(unsigned int);
extern unsigned long txn_affinity_addr(unsigned int irq, int cpu);
extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest);
/* soft power switch support (power.c) */
extern struct tasklet_struct power_tasklet;

View File

@ -29,6 +29,7 @@ extern cpumask_t cpu_online_map;
#define cpu_logical_map(cpu) (cpu)
extern void smp_send_reschedule(int cpu);
extern void smp_send_all_nop(void);
#endif /* !ASSEMBLY */
@ -53,7 +54,11 @@ extern unsigned long cpu_present_mask;
#define raw_smp_processor_id() (current_thread_info()->cpu)
#endif /* CONFIG_SMP */
#else /* CONFIG_SMP */
static inline void smp_send_all_nop(void) { return; }
#endif
#define NO_PROC_ID 0xFF /* No processor magic marker */
#define ANY_PROC_ID 0xFF /* Any processor magic marker */

View File

@ -11,18 +11,25 @@ static inline int __raw_spin_is_locked(raw_spinlock_t *x)
return *a == 0;
}
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
#define __raw_spin_lock(lock) __raw_spin_lock_flags(lock, 0)
#define __raw_spin_unlock_wait(x) \
do { cpu_relax(); } while (__raw_spin_is_locked(x))
static inline void __raw_spin_lock(raw_spinlock_t *x)
static inline void __raw_spin_lock_flags(raw_spinlock_t *x,
unsigned long flags)
{
volatile unsigned int *a;
mb();
a = __ldcw_align(x);
while (__ldcw(a) == 0)
while (*a == 0);
while (*a == 0)
if (flags & PSW_SM_I) {
local_irq_enable();
cpu_relax();
local_irq_disable();
} else
cpu_relax();
mb();
}
@ -60,26 +67,20 @@ static inline int __raw_spin_trylock(raw_spinlock_t *x)
static __inline__ void __raw_read_lock(raw_rwlock_t *rw)
{
unsigned long flags;
local_irq_save(flags);
__raw_spin_lock(&rw->lock);
rw->counter++;
__raw_spin_unlock(&rw->lock);
local_irq_restore(flags);
}
static __inline__ void __raw_read_unlock(raw_rwlock_t *rw)
{
unsigned long flags;
local_irq_save(flags);
__raw_spin_lock(&rw->lock);
rw->counter--;
__raw_spin_unlock(&rw->lock);
local_irq_restore(flags);
}
/* write_lock is less trivial. We optimistically grab the lock and check

View File

@ -12,21 +12,15 @@
* N class systems, only one PxTLB inter processor broadcast can be
* active at any one time on the Merced bus. This tlb purge
* synchronisation is fairly lightweight and harmless so we activate
* it on all SMP systems not just the N class. */
#ifdef CONFIG_SMP
* it on all SMP systems not just the N class. We also need to have
* preemption disabled on uniprocessor machines, and spin_lock does that
* nicely.
*/
extern spinlock_t pa_tlb_lock;
#define purge_tlb_start(x) spin_lock(&pa_tlb_lock)
#define purge_tlb_end(x) spin_unlock(&pa_tlb_lock)
#else
#define purge_tlb_start(x) do { } while(0)
#define purge_tlb_end(x) do { } while (0)
#endif
extern void flush_tlb_all(void);
/*
@ -88,7 +82,6 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */
flush_tlb_all();
else {
preempt_disable();
mtsp(vma->vm_mm->context,1);
purge_tlb_start();
if (split_tlb) {
@ -102,7 +95,6 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
pdtlb(start);
start += PAGE_SIZE;
}
preempt_enable();
}
purge_tlb_end();
}

View File

@ -10,8 +10,8 @@
typedef struct _cciss_pci_info_struct
{
unsigned char bus;
unsigned short domain;
unsigned char dev_fn;
unsigned short domain;
__u32 board_id;
} cciss_pci_info_struct;

View File

@ -1089,9 +1089,11 @@ enum {
/*
* Subdrivers support.
*
* The gendriver.owner field should be set to the module owner of this driver.
* The gendriver.name field should be set to the name of this driver
*/
typedef struct ide_driver_s {
struct module *owner;
const char *version;
u8 media;
unsigned supports_dsc_overlap : 1;

View File

@ -940,7 +940,9 @@ unsigned long max_sane_readahead(unsigned long nr);
/* Do stack extension */
extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
#ifdef CONFIG_IA64
extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
#endif
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);

View File

@ -1501,7 +1501,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
* PA-RISC uses this for its stack; IA64 for its Register Backing Store.
* vma is the last one with address > vma->vm_end. Have to extend vma.
*/
#ifdef CONFIG_STACK_GROWSUP
#ifndef CONFIG_IA64
static inline
#endif
int expand_upwards(struct vm_area_struct *vma, unsigned long address)