Merge branch 'master'
This commit is contained in:
commit
625876f32e
12
CREDITS
12
CREDITS
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
16
MAINTAINERS
16
MAINTAINERS
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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];
|
||||
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
|
||||
};
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
@ -338,6 +346,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;
|
||||
|
|
|
@ -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! */
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* linux/drivers/block/as-iosched.c
|
||||
*
|
||||
* Anticipatory & deadline i/o scheduler.
|
||||
*
|
||||
* Copyright (C) 2002 Jens Axboe <axboe@suse.de>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* linux/drivers/block/deadline-iosched.c
|
||||
*
|
||||
* Deadline i/o scheduler.
|
||||
*
|
||||
* Copyright (C) 2002 Jens Axboe <axboe@suse.de>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/*
|
||||
* linux/drivers/block/elevator.c
|
||||
*
|
||||
* Block device elevator/IO-scheduler.
|
||||
*
|
||||
* Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>.
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ®49h);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
@ -481,19 +487,21 @@ static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_
|
|||
DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n");
|
||||
}
|
||||
|
||||
/* Let appropriate other driver claim this device. */
|
||||
/* Let appropriate other driver claim this device. */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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---
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue