Merge branch 'master' into upstream
This commit is contained in:
Коммит
23930fa1ce
7
CREDITS
7
CREDITS
|
@ -2384,6 +2384,13 @@ N: Thomas Molina
|
|||
E: tmolina@cablespeed.com
|
||||
D: bug fixes, documentation, minor hackery
|
||||
|
||||
N: Paul Moore
|
||||
E: paul.moore@hp.com
|
||||
D: NetLabel author
|
||||
S: Hewlett-Packard
|
||||
S: 110 Spit Brook Road
|
||||
S: Nashua, NH 03062
|
||||
|
||||
N: James Morris
|
||||
E: jmorris@namei.org
|
||||
W: http://namei.org/
|
||||
|
|
|
@ -184,6 +184,8 @@ mtrr.txt
|
|||
- how to use PPro Memory Type Range Registers to increase performance.
|
||||
nbd.txt
|
||||
- info on a TCP implementation of a network block device.
|
||||
netlabel/
|
||||
- directory with information on the NetLabel subsystem.
|
||||
networking/
|
||||
- directory with info on various aspects of networking with Linux.
|
||||
nfsroot.txt
|
||||
|
|
|
@ -19,15 +19,14 @@ At the lowest level are algorithms, which register dynamically with the
|
|||
API.
|
||||
|
||||
'Transforms' are user-instantiated objects, which maintain state, handle all
|
||||
of the implementation logic (e.g. manipulating page vectors), provide an
|
||||
abstraction to the underlying algorithms, and handle common logical
|
||||
operations (e.g. cipher modes, HMAC for digests). However, at the user
|
||||
of the implementation logic (e.g. manipulating page vectors) and provide an
|
||||
abstraction to the underlying algorithms. However, at the user
|
||||
level they are very simple.
|
||||
|
||||
Conceptually, the API layering looks like this:
|
||||
|
||||
[transform api] (user interface)
|
||||
[transform ops] (per-type logic glue e.g. cipher.c, digest.c)
|
||||
[transform ops] (per-type logic glue e.g. cipher.c, compress.c)
|
||||
[algorithm api] (for registering algorithms)
|
||||
|
||||
The idea is to make the user interface and algorithm registration API
|
||||
|
@ -44,22 +43,27 @@ under development.
|
|||
Here's an example of how to use the API:
|
||||
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
struct scatterlist sg[2];
|
||||
char result[128];
|
||||
struct crypto_tfm *tfm;
|
||||
struct crypto_hash *tfm;
|
||||
struct hash_desc desc;
|
||||
|
||||
tfm = crypto_alloc_tfm("md5", 0);
|
||||
if (tfm == NULL)
|
||||
tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
|
||||
if (IS_ERR(tfm))
|
||||
fail();
|
||||
|
||||
/* ... set up the scatterlists ... */
|
||||
|
||||
crypto_digest_init(tfm);
|
||||
crypto_digest_update(tfm, &sg, 2);
|
||||
crypto_digest_final(tfm, result);
|
||||
desc.tfm = tfm;
|
||||
desc.flags = 0;
|
||||
|
||||
crypto_free_tfm(tfm);
|
||||
if (crypto_hash_digest(&desc, &sg, 2, result))
|
||||
fail();
|
||||
|
||||
crypto_free_hash(tfm);
|
||||
|
||||
|
||||
Many real examples are available in the regression test module (tcrypt.c).
|
||||
|
@ -126,7 +130,7 @@ might already be working on.
|
|||
BUGS
|
||||
|
||||
Send bug reports to:
|
||||
James Morris <jmorris@redhat.com>
|
||||
Herbert Xu <herbert@gondor.apana.org.au>
|
||||
Cc: David S. Miller <davem@redhat.com>
|
||||
|
||||
|
||||
|
@ -134,13 +138,14 @@ FURTHER INFORMATION
|
|||
|
||||
For further patches and various updates, including the current TODO
|
||||
list, see:
|
||||
http://samba.org/~jamesm/crypto/
|
||||
http://gondor.apana.org.au/~herbert/crypto/
|
||||
|
||||
|
||||
AUTHORS
|
||||
|
||||
James Morris
|
||||
David S. Miller
|
||||
Herbert Xu
|
||||
|
||||
|
||||
CREDITS
|
||||
|
@ -238,8 +243,11 @@ Anubis algorithm contributors:
|
|||
Tiger algorithm contributors:
|
||||
Aaron Grothe
|
||||
|
||||
VIA PadLock contributors:
|
||||
Michal Ludvig
|
||||
|
||||
Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
|
||||
|
||||
Please send any credits updates or corrections to:
|
||||
James Morris <jmorris@redhat.com>
|
||||
Herbert Xu <herbert@gondor.apana.org.au>
|
||||
|
||||
|
|
|
@ -1189,8 +1189,6 @@ running once the system is up.
|
|||
Mechanism 2.
|
||||
nommconf [IA-32,X86_64] Disable use of MMCONFIG for PCI
|
||||
Configuration
|
||||
mmconf [IA-32,X86_64] Force MMCONFIG. This is useful
|
||||
to override the builtin blacklist.
|
||||
nomsi [MSI] If the PCI_MSI kernel config parameter is
|
||||
enabled, this kernel boot option can be used to
|
||||
disable the use of MSI interrupts system-wide.
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
00-INDEX
|
||||
- this file.
|
||||
cipso_ipv4.txt
|
||||
- documentation on the IPv4 CIPSO protocol engine.
|
||||
draft-ietf-cipso-ipsecurity-01.txt
|
||||
- IETF draft of the CIPSO protocol, dated 16 July 1992.
|
||||
introduction.txt
|
||||
- NetLabel introduction, READ THIS FIRST.
|
||||
lsm_interface.txt
|
||||
- documentation on the NetLabel kernel security module API.
|
|
@ -0,0 +1,48 @@
|
|||
NetLabel CIPSO/IPv4 Protocol Engine
|
||||
==============================================================================
|
||||
Paul Moore, paul.moore@hp.com
|
||||
|
||||
May 17, 2006
|
||||
|
||||
* Overview
|
||||
|
||||
The NetLabel CIPSO/IPv4 protocol engine is based on the IETF Commercial IP
|
||||
Security Option (CIPSO) draft from July 16, 1992. A copy of this draft can be
|
||||
found in this directory, consult '00-INDEX' for the filename. While the IETF
|
||||
draft never made it to an RFC standard it has become a de-facto standard for
|
||||
labeled networking and is used in many trusted operating systems.
|
||||
|
||||
* Outbound Packet Processing
|
||||
|
||||
The CIPSO/IPv4 protocol engine applies the CIPSO IP option to packets by
|
||||
adding the CIPSO label to the socket. This causes all packets leaving the
|
||||
system through the socket to have the CIPSO IP option applied. The socket's
|
||||
CIPSO label can be changed at any point in time, however, it is recommended
|
||||
that it is set upon the socket's creation. The LSM can set the socket's CIPSO
|
||||
label by using the NetLabel security module API; if the NetLabel "domain" is
|
||||
configured to use CIPSO for packet labeling then a CIPSO IP option will be
|
||||
generated and attached to the socket.
|
||||
|
||||
* Inbound Packet Processing
|
||||
|
||||
The CIPSO/IPv4 protocol engine validates every CIPSO IP option it finds at the
|
||||
IP layer without any special handling required by the LSM. However, in order
|
||||
to decode and translate the CIPSO label on the packet the LSM must use the
|
||||
NetLabel security module API to extract the security attributes of the packet.
|
||||
This is typically done at the socket layer using the 'socket_sock_rcv_skb()'
|
||||
LSM hook.
|
||||
|
||||
* Label Translation
|
||||
|
||||
The CIPSO/IPv4 protocol engine contains a mechanism to translate CIPSO security
|
||||
attributes such as sensitivity level and category to values which are
|
||||
appropriate for the host. These mappings are defined as part of a CIPSO
|
||||
Domain Of Interpretation (DOI) definition and are configured through the
|
||||
NetLabel user space communication layer. Each DOI definition can have a
|
||||
different security attribute mapping table.
|
||||
|
||||
* Label Translation Cache
|
||||
|
||||
The NetLabel system provides a framework for caching security attribute
|
||||
mappings from the network labels to the corresponding LSM identifiers. The
|
||||
CIPSO/IPv4 protocol engine supports this caching mechanism.
|
|
@ -0,0 +1,791 @@
|
|||
IETF CIPSO Working Group
|
||||
16 July, 1992
|
||||
|
||||
|
||||
|
||||
COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
|
||||
|
||||
|
||||
|
||||
1. Status
|
||||
|
||||
This Internet Draft provides the high level specification for a Commercial
|
||||
IP Security Option (CIPSO). This draft reflects the version as approved by
|
||||
the CIPSO IETF Working Group. Distribution of this memo is unlimited.
|
||||
|
||||
This document is an Internet Draft. Internet Drafts are working documents
|
||||
of the Internet Engineering Task Force (IETF), its Areas, and its Working
|
||||
Groups. Note that other groups may also distribute working documents as
|
||||
Internet Drafts.
|
||||
|
||||
Internet Drafts are draft documents valid for a maximum of six months.
|
||||
Internet Drafts may be updated, replaced, or obsoleted by other documents
|
||||
at any time. It is not appropriate to use Internet Drafts as reference
|
||||
material or to cite them other than as a "working draft" or "work in
|
||||
progress."
|
||||
|
||||
Please check the I-D abstract listing contained in each Internet Draft
|
||||
directory to learn the current status of this or any other Internet Draft.
|
||||
|
||||
|
||||
|
||||
|
||||
2. Background
|
||||
|
||||
Currently the Internet Protocol includes two security options. One of
|
||||
these options is the DoD Basic Security Option (BSO) (Type 130) which allows
|
||||
IP datagrams to be labeled with security classifications. This option
|
||||
provides sixteen security classifications and a variable number of handling
|
||||
restrictions. To handle additional security information, such as security
|
||||
categories or compartments, another security option (Type 133) exists and
|
||||
is referred to as the DoD Extended Security Option (ESO). The values for
|
||||
the fixed fields within these two options are administered by the Defense
|
||||
Information Systems Agency (DISA).
|
||||
|
||||
Computer vendors are now building commercial operating systems with
|
||||
mandatory access controls and multi-level security. These systems are
|
||||
no longer built specifically for a particular group in the defense or
|
||||
intelligence communities. They are generally available commercial systems
|
||||
for use in a variety of government and civil sector environments.
|
||||
|
||||
The small number of ESO format codes can not support all the possible
|
||||
applications of a commercial security option. The BSO and ESO were
|
||||
designed to only support the United States DoD. CIPSO has been designed
|
||||
to support multiple security policies. This Internet Draft provides the
|
||||
format and procedures required to support a Mandatory Access Control
|
||||
security policy. Support for additional security policies shall be
|
||||
defined in future RFCs.
|
||||
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 1]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
|
||||
3. CIPSO Format
|
||||
|
||||
Option type: 134 (Class 0, Number 6, Copy on Fragmentation)
|
||||
Option length: Variable
|
||||
|
||||
This option permits security related information to be passed between
|
||||
systems within a single Domain of Interpretation (DOI). A DOI is a
|
||||
collection of systems which agree on the meaning of particular values
|
||||
in the security option. An authority that has been assigned a DOI
|
||||
identifier will define a mapping between appropriate CIPSO field values
|
||||
and their human readable equivalent. This authority will distribute that
|
||||
mapping to hosts within the authority's domain. These mappings may be
|
||||
sensitive, therefore a DOI authority is not required to make these
|
||||
mappings available to anyone other than the systems that are included in
|
||||
the DOI.
|
||||
|
||||
This option MUST be copied on fragmentation. This option appears at most
|
||||
once in a datagram. All multi-octet fields in the option are defined to be
|
||||
transmitted in network byte order. The format of this option is as follows:
|
||||
|
||||
+----------+----------+------//------+-----------//---------+
|
||||
| 10000110 | LLLLLLLL | DDDDDDDDDDDD | TTTTTTTTTTTTTTTTTTTT |
|
||||
+----------+----------+------//------+-----------//---------+
|
||||
|
||||
TYPE=134 OPTION DOMAIN OF TAGS
|
||||
LENGTH INTERPRETATION
|
||||
|
||||
|
||||
Figure 1. CIPSO Format
|
||||
|
||||
|
||||
3.1 Type
|
||||
|
||||
This field is 1 octet in length. Its value is 134.
|
||||
|
||||
|
||||
3.2 Length
|
||||
|
||||
This field is 1 octet in length. It is the total length of the option
|
||||
including the type and length fields. With the current IP header length
|
||||
restriction of 40 octets the value of this field MUST not exceed 40.
|
||||
|
||||
|
||||
3.3 Domain of Interpretation Identifier
|
||||
|
||||
This field is an unsigned 32 bit integer. The value 0 is reserved and MUST
|
||||
not appear as the DOI identifier in any CIPSO option. Implementations
|
||||
should assume that the DOI identifier field is not aligned on any particular
|
||||
byte boundary.
|
||||
|
||||
To conserve space in the protocol, security levels and categories are
|
||||
represented by numbers rather than their ASCII equivalent. This requires
|
||||
a mapping table within CIPSO hosts to map these numbers to their
|
||||
corresponding ASCII representations. Non-related groups of systems may
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 2]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
have their own unique mappings. For example, one group of systems may
|
||||
use the number 5 to represent Unclassified while another group may use the
|
||||
number 1 to represent that same security level. The DOI identifier is used
|
||||
to identify which mapping was used for the values within the option.
|
||||
|
||||
|
||||
3.4 Tag Types
|
||||
|
||||
A common format for passing security related information is necessary
|
||||
for interoperability. CIPSO uses sets of "tags" to contain the security
|
||||
information relevant to the data in the IP packet. Each tag begins with
|
||||
a tag type identifier followed by the length of the tag and ends with the
|
||||
actual security information to be passed. All multi-octet fields in a tag
|
||||
are defined to be transmitted in network byte order. Like the DOI
|
||||
identifier field in the CIPSO header, implementations should assume that
|
||||
all tags, as well as fields within a tag, are not aligned on any particular
|
||||
octet boundary. The tag types defined in this document contain alignment
|
||||
bytes to assist alignment of some information, however alignment can not
|
||||
be guaranteed if CIPSO is not the first IP option.
|
||||
|
||||
CIPSO tag types 0 through 127 are reserved for defining standard tag
|
||||
formats. Their definitions will be published in RFCs. Tag types whose
|
||||
identifiers are greater than 127 are defined by the DOI authority and may
|
||||
only be meaningful in certain Domains of Interpretation. For these tag
|
||||
types, implementations will require the DOI identifier as well as the tag
|
||||
number to determine the security policy and the format associated with the
|
||||
tag. Use of tag types above 127 are restricted to closed networks where
|
||||
interoperability with other networks will not be an issue. Implementations
|
||||
that support a tag type greater than 127 MUST support at least one DOI that
|
||||
requires only tag types 1 to 127.
|
||||
|
||||
Tag type 0 is reserved. Tag types 1, 2, and 5 are defined in this
|
||||
Internet Draft. Types 3 and 4 are reserved for work in progress.
|
||||
The standard format for all current and future CIPSO tags is shown below:
|
||||
|
||||
+----------+----------+--------//--------+
|
||||
| TTTTTTTT | LLLLLLLL | IIIIIIIIIIIIIIII |
|
||||
+----------+----------+--------//--------+
|
||||
TAG TAG TAG
|
||||
TYPE LENGTH INFORMATION
|
||||
|
||||
Figure 2: Standard Tag Format
|
||||
|
||||
In the three tag types described in this document, the length and count
|
||||
restrictions are based on the current IP limitation of 40 octets for all
|
||||
IP options. If the IP header is later expanded, then the length and count
|
||||
restrictions specified in this document may increase to use the full area
|
||||
provided for IP options.
|
||||
|
||||
|
||||
3.4.1 Tag Type Classes
|
||||
|
||||
Tag classes consist of tag types that have common processing requirements
|
||||
and support the same security policy. The three tags defined in this
|
||||
Internet Draft belong to the Mandatory Access Control (MAC) Sensitivity
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 3]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
class and support the MAC Sensitivity security policy.
|
||||
|
||||
|
||||
3.4.2 Tag Type 1
|
||||
|
||||
This is referred to as the "bit-mapped" tag type. Tag type 1 is included
|
||||
in the MAC Sensitivity tag type class. The format of this tag type is as
|
||||
follows:
|
||||
|
||||
+----------+----------+----------+----------+--------//---------+
|
||||
| 00000001 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCC |
|
||||
+----------+----------+----------+----------+--------//---------+
|
||||
|
||||
TAG TAG ALIGNMENT SENSITIVITY BIT MAP OF
|
||||
TYPE LENGTH OCTET LEVEL CATEGORIES
|
||||
|
||||
Figure 3. Tag Type 1 Format
|
||||
|
||||
|
||||
3.4.2.1 Tag Type
|
||||
|
||||
This field is 1 octet in length and has a value of 1.
|
||||
|
||||
|
||||
3.4.2.2 Tag Length
|
||||
|
||||
This field is 1 octet in length. It is the total length of the tag type
|
||||
including the type and length fields. With the current IP header length
|
||||
restriction of 40 bytes the value within this field is between 4 and 34.
|
||||
|
||||
|
||||
3.4.2.3 Alignment Octet
|
||||
|
||||
This field is 1 octet in length and always has the value of 0. Its purpose
|
||||
is to align the category bitmap field on an even octet boundary. This will
|
||||
speed many implementations including router implementations.
|
||||
|
||||
|
||||
3.4.2.4 Sensitivity Level
|
||||
|
||||
This field is 1 octet in length. Its value is from 0 to 255. The values
|
||||
are ordered with 0 being the minimum value and 255 representing the maximum
|
||||
value.
|
||||
|
||||
|
||||
3.4.2.5 Bit Map of Categories
|
||||
|
||||
The length of this field is variable and ranges from 0 to 30 octets. This
|
||||
provides representation of categories 0 to 239. The ordering of the bits
|
||||
is left to right or MSB to LSB. For example category 0 is represented by
|
||||
the most significant bit of the first byte and category 15 is represented
|
||||
by the least significant bit of the second byte. Figure 4 graphically
|
||||
shows this ordering. Bit N is binary 1 if category N is part of the label
|
||||
for the datagram, and bit N is binary 0 if category N is not part of the
|
||||
label. Except for the optimized tag 1 format described in the next section,
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 4]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
minimal encoding SHOULD be used resulting in no trailing zero octets in the
|
||||
category bitmap.
|
||||
|
||||
octet 0 octet 1 octet 2 octet 3 octet 4 octet 5
|
||||
XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX . . .
|
||||
bit 01234567 89111111 11112222 22222233 33333333 44444444
|
||||
number 012345 67890123 45678901 23456789 01234567
|
||||
|
||||
Figure 4. Ordering of Bits in Tag 1 Bit Map
|
||||
|
||||
|
||||
3.4.2.6 Optimized Tag 1 Format
|
||||
|
||||
Routers work most efficiently when processing fixed length fields. To
|
||||
support these routers there is an optimized form of tag type 1. The format
|
||||
does not change. The only change is to the category bitmap which is set to
|
||||
a constant length of 10 octets. Trailing octets required to fill out the 10
|
||||
octets are zero filled. Ten octets, allowing for 80 categories, was chosen
|
||||
because it makes the total length of the CIPSO option 20 octets. If CIPSO
|
||||
is the only option then the option will be full word aligned and additional
|
||||
filler octets will not be required.
|
||||
|
||||
|
||||
3.4.3 Tag Type 2
|
||||
|
||||
This is referred to as the "enumerated" tag type. It is used to describe
|
||||
large but sparsely populated sets of categories. Tag type 2 is in the MAC
|
||||
Sensitivity tag type class. The format of this tag type is as follows:
|
||||
|
||||
+----------+----------+----------+----------+-------------//-------------+
|
||||
| 00000010 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCCCCCCCCCCC |
|
||||
+----------+----------+----------+----------+-------------//-------------+
|
||||
|
||||
TAG TAG ALIGNMENT SENSITIVITY ENUMERATED
|
||||
TYPE LENGTH OCTET LEVEL CATEGORIES
|
||||
|
||||
Figure 5. Tag Type 2 Format
|
||||
|
||||
|
||||
3.4.3.1 Tag Type
|
||||
|
||||
This field is one octet in length and has a value of 2.
|
||||
|
||||
|
||||
3.4.3.2 Tag Length
|
||||
|
||||
This field is 1 octet in length. It is the total length of the tag type
|
||||
including the type and length fields. With the current IP header length
|
||||
restriction of 40 bytes the value within this field is between 4 and 34.
|
||||
|
||||
|
||||
3.4.3.3 Alignment Octet
|
||||
|
||||
This field is 1 octet in length and always has the value of 0. Its purpose
|
||||
is to align the category field on an even octet boundary. This will
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 5]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
speed many implementations including router implementations.
|
||||
|
||||
|
||||
3.4.3.4 Sensitivity Level
|
||||
|
||||
This field is 1 octet in length. Its value is from 0 to 255. The values
|
||||
are ordered with 0 being the minimum value and 255 representing the
|
||||
maximum value.
|
||||
|
||||
|
||||
3.4.3.5 Enumerated Categories
|
||||
|
||||
In this tag, categories are represented by their actual value rather than
|
||||
by their position within a bit field. The length of each category is 2
|
||||
octets. Up to 15 categories may be represented by this tag. Valid values
|
||||
for categories are 0 to 65534. Category 65535 is not a valid category
|
||||
value. The categories MUST be listed in ascending order within the tag.
|
||||
|
||||
|
||||
3.4.4 Tag Type 5
|
||||
|
||||
This is referred to as the "range" tag type. It is used to represent
|
||||
labels where all categories in a range, or set of ranges, are included
|
||||
in the sensitivity label. Tag type 5 is in the MAC Sensitivity tag type
|
||||
class. The format of this tag type is as follows:
|
||||
|
||||
+----------+----------+----------+----------+------------//-------------+
|
||||
| 00000101 | LLLLLLLL | 00000000 | LLLLLLLL | Top/Bottom | Top/Bottom |
|
||||
+----------+----------+----------+----------+------------//-------------+
|
||||
|
||||
TAG TAG ALIGNMENT SENSITIVITY CATEGORY RANGES
|
||||
TYPE LENGTH OCTET LEVEL
|
||||
|
||||
Figure 6. Tag Type 5 Format
|
||||
|
||||
|
||||
3.4.4.1 Tag Type
|
||||
|
||||
This field is one octet in length and has a value of 5.
|
||||
|
||||
|
||||
3.4.4.2 Tag Length
|
||||
|
||||
This field is 1 octet in length. It is the total length of the tag type
|
||||
including the type and length fields. With the current IP header length
|
||||
restriction of 40 bytes the value within this field is between 4 and 34.
|
||||
|
||||
|
||||
3.4.4.3 Alignment Octet
|
||||
|
||||
This field is 1 octet in length and always has the value of 0. Its purpose
|
||||
is to align the category range field on an even octet boundary. This will
|
||||
speed many implementations including router implementations.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 6]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
3.4.4.4 Sensitivity Level
|
||||
|
||||
This field is 1 octet in length. Its value is from 0 to 255. The values
|
||||
are ordered with 0 being the minimum value and 255 representing the maximum
|
||||
value.
|
||||
|
||||
|
||||
3.4.4.5 Category Ranges
|
||||
|
||||
A category range is a 4 octet field comprised of the 2 octet index of the
|
||||
highest numbered category followed by the 2 octet index of the lowest
|
||||
numbered category. These range endpoints are inclusive within the range of
|
||||
categories. All categories within a range are included in the sensitivity
|
||||
label. This tag may contain a maximum of 7 category pairs. The bottom
|
||||
category endpoint for the last pair in the tag MAY be omitted and SHOULD be
|
||||
assumed to be 0. The ranges MUST be non-overlapping and be listed in
|
||||
descending order. Valid values for categories are 0 to 65534. Category
|
||||
65535 is not a valid category value.
|
||||
|
||||
|
||||
3.4.5 Minimum Requirements
|
||||
|
||||
A CIPSO implementation MUST be capable of generating at least tag type 1 in
|
||||
the non-optimized form. In addition, a CIPSO implementation MUST be able
|
||||
to receive any valid tag type 1 even those using the optimized tag type 1
|
||||
format.
|
||||
|
||||
|
||||
4. Configuration Parameters
|
||||
|
||||
The configuration parameters defined below are required for all CIPSO hosts,
|
||||
gateways, and routers that support multiple sensitivity labels. A CIPSO
|
||||
host is defined to be the origination or destination system for an IP
|
||||
datagram. A CIPSO gateway provides IP routing services between two or more
|
||||
IP networks and may be required to perform label translations between
|
||||
networks. A CIPSO gateway may be an enhanced CIPSO host or it may just
|
||||
provide gateway services with no end system CIPSO capabilities. A CIPSO
|
||||
router is a dedicated IP router that routes IP datagrams between two or more
|
||||
IP networks.
|
||||
|
||||
An implementation of CIPSO on a host MUST have the capability to reject a
|
||||
datagram for reasons that the information contained can not be adequately
|
||||
protected by the receiving host or if acceptance may result in violation of
|
||||
the host or network security policy. In addition, a CIPSO gateway or router
|
||||
MUST be able to reject datagrams going to networks that can not provide
|
||||
adequate protection or may violate the network's security policy. To
|
||||
provide this capability the following minimal set of configuration
|
||||
parameters are required for CIPSO implementations:
|
||||
|
||||
HOST_LABEL_MAX - This parameter contains the maximum sensitivity label that
|
||||
a CIPSO host is authorized to handle. All datagrams that have a label
|
||||
greater than this maximum MUST be rejected by the CIPSO host. This
|
||||
parameter does not apply to CIPSO gateways or routers. This parameter need
|
||||
not be defined explicitly as it can be implicitly derived from the
|
||||
PORT_LABEL_MAX parameters for the associated interfaces.
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 7]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
|
||||
HOST_LABEL_MIN - This parameter contains the minimum sensitivity label that
|
||||
a CIPSO host is authorized to handle. All datagrams that have a label less
|
||||
than this minimum MUST be rejected by the CIPSO host. This parameter does
|
||||
not apply to CIPSO gateways or routers. This parameter need not be defined
|
||||
explicitly as it can be implicitly derived from the PORT_LABEL_MIN
|
||||
parameters for the associated interfaces.
|
||||
|
||||
PORT_LABEL_MAX - This parameter contains the maximum sensitivity label for
|
||||
all datagrams that may exit a particular network interface port. All
|
||||
outgoing datagrams that have a label greater than this maximum MUST be
|
||||
rejected by the CIPSO system. The label within this parameter MUST be
|
||||
less than or equal to the label within the HOST_LABEL_MAX parameter. This
|
||||
parameter does not apply to CIPSO hosts that support only one network port.
|
||||
|
||||
PORT_LABEL_MIN - This parameter contains the minimum sensitivity label for
|
||||
all datagrams that may exit a particular network interface port. All
|
||||
outgoing datagrams that have a label less than this minimum MUST be
|
||||
rejected by the CIPSO system. The label within this parameter MUST be
|
||||
greater than or equal to the label within the HOST_LABEL_MIN parameter.
|
||||
This parameter does not apply to CIPSO hosts that support only one network
|
||||
port.
|
||||
|
||||
PORT_DOI - This parameter is used to assign a DOI identifier value to a
|
||||
particular network interface port. All CIPSO labels within datagrams
|
||||
going out this port MUST use the specified DOI identifier. All CIPSO
|
||||
hosts and gateways MUST support either this parameter, the NET_DOI
|
||||
parameter, or the HOST_DOI parameter.
|
||||
|
||||
NET_DOI - This parameter is used to assign a DOI identifier value to a
|
||||
particular IP network address. All CIPSO labels within datagrams destined
|
||||
for the particular IP network MUST use the specified DOI identifier. All
|
||||
CIPSO hosts and gateways MUST support either this parameter, the PORT_DOI
|
||||
parameter, or the HOST_DOI parameter.
|
||||
|
||||
HOST_DOI - This parameter is used to assign a DOI identifier value to a
|
||||
particular IP host address. All CIPSO labels within datagrams destined for
|
||||
the particular IP host will use the specified DOI identifier. All CIPSO
|
||||
hosts and gateways MUST support either this parameter, the PORT_DOI
|
||||
parameter, or the NET_DOI parameter.
|
||||
|
||||
This list represents the minimal set of configuration parameters required
|
||||
to be compliant. Implementors are encouraged to add to this list to
|
||||
provide enhanced functionality and control. For example, many security
|
||||
policies may require both incoming and outgoing datagrams be checked against
|
||||
the port and host label ranges.
|
||||
|
||||
|
||||
4.1 Port Range Parameters
|
||||
|
||||
The labels represented by the PORT_LABEL_MAX and PORT_LABEL_MIN parameters
|
||||
MAY be in CIPSO or local format. Some CIPSO systems, such as routers, may
|
||||
want to have the range parameters expressed in CIPSO format so that incoming
|
||||
labels do not have to be converted to a local format before being compared
|
||||
against the range. If multiple DOIs are supported by one of these CIPSO
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 8]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
systems then multiple port range parameters would be needed, one set for
|
||||
each DOI supported on a particular port.
|
||||
|
||||
The port range will usually represent the total set of labels that may
|
||||
exist on the logical network accessed through the corresponding network
|
||||
interface. It may, however, represent a subset of these labels that are
|
||||
allowed to enter the CIPSO system.
|
||||
|
||||
|
||||
4.2 Single Label CIPSO Hosts
|
||||
|
||||
CIPSO implementations that support only one label are not required to
|
||||
support the parameters described above. These limited implementations are
|
||||
only required to support a NET_LABEL parameter. This parameter contains
|
||||
the CIPSO label that may be inserted in datagrams that exit the host. In
|
||||
addition, the host MUST reject any incoming datagram that has a label which
|
||||
is not equivalent to the NET_LABEL parameter.
|
||||
|
||||
|
||||
5. Handling Procedures
|
||||
|
||||
This section describes the processing requirements for incoming and
|
||||
outgoing IP datagrams. Just providing the correct CIPSO label format
|
||||
is not enough. Assumptions will be made by one system on how a
|
||||
receiving system will handle the CIPSO label. Wrong assumptions may
|
||||
lead to non-interoperability or even a security incident. The
|
||||
requirements described below represent the minimal set needed for
|
||||
interoperability and that provide users some level of confidence.
|
||||
Many other requirements could be added to increase user confidence,
|
||||
however at the risk of restricting creativity and limiting vendor
|
||||
participation.
|
||||
|
||||
|
||||
5.1 Input Procedures
|
||||
|
||||
All datagrams received through a network port MUST have a security label
|
||||
associated with them, either contained in the datagram or assigned to the
|
||||
receiving port. Without this label the host, gateway, or router will not
|
||||
have the information it needs to make security decisions. This security
|
||||
label will be obtained from the CIPSO if the option is present in the
|
||||
datagram. See section 4.1.2 for handling procedures for unlabeled
|
||||
datagrams. This label will be compared against the PORT (if appropriate)
|
||||
and HOST configuration parameters defined in section 3.
|
||||
|
||||
If any field within the CIPSO option, such as the DOI identifier, is not
|
||||
recognized the IP datagram is discarded and an ICMP "parameter problem"
|
||||
(type 12) is generated and returned. The ICMP code field is set to "bad
|
||||
parameter" (code 0) and the pointer is set to the start of the CIPSO field
|
||||
that is unrecognized.
|
||||
|
||||
If the contents of the CIPSO are valid but the security label is
|
||||
outside of the configured host or port label range, the datagram is
|
||||
discarded and an ICMP "destination unreachable" (type 3) is generated
|
||||
and returned. The code field of the ICMP is set to "communication with
|
||||
destination network administratively prohibited" (code 9) or to
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 9]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
"communication with destination host administratively prohibited"
|
||||
(code 10). The value of the code field used is dependent upon whether
|
||||
the originator of the ICMP message is acting as a CIPSO host or a CIPSO
|
||||
gateway. The recipient of the ICMP message MUST be able to handle either
|
||||
value. The same procedure is performed if a CIPSO can not be added to an
|
||||
IP packet because it is too large to fit in the IP options area.
|
||||
|
||||
If the error is triggered by receipt of an ICMP message, the message
|
||||
is discarded and no response is permitted (consistent with general ICMP
|
||||
processing rules).
|
||||
|
||||
|
||||
5.1.1 Unrecognized tag types
|
||||
|
||||
The default condition for any CIPSO implementation is that an
|
||||
unrecognized tag type MUST be treated as a "parameter problem" and
|
||||
handled as described in section 4.1. A CIPSO implementation MAY allow
|
||||
the system administrator to identify tag types that may safely be
|
||||
ignored. This capability is an allowable enhancement, not a
|
||||
requirement.
|
||||
|
||||
|
||||
5.1.2 Unlabeled Packets
|
||||
|
||||
A network port may be configured to not require a CIPSO label for all
|
||||
incoming datagrams. For this configuration a CIPSO label must be
|
||||
assigned to that network port and associated with all unlabeled IP
|
||||
datagrams. This capability might be used for single level networks or
|
||||
networks that have CIPSO and non-CIPSO hosts and the non-CIPSO hosts
|
||||
all operate at the same label.
|
||||
|
||||
If a CIPSO option is required and none is found, the datagram is
|
||||
discarded and an ICMP "parameter problem" (type 12) is generated and
|
||||
returned to the originator of the datagram. The code field of the ICMP
|
||||
is set to "option missing" (code 1) and the ICMP pointer is set to 134
|
||||
(the value of the option type for the missing CIPSO option).
|
||||
|
||||
|
||||
5.2 Output Procedures
|
||||
|
||||
A CIPSO option MUST appear only once in a datagram. Only one tag type
|
||||
from the MAC Sensitivity class MAY be included in a CIPSO option. Given
|
||||
the current set of defined tag types, this means that CIPSO labels at
|
||||
first will contain only one tag.
|
||||
|
||||
All datagrams leaving a CIPSO system MUST meet the following condition:
|
||||
|
||||
PORT_LABEL_MIN <= CIPSO label <= PORT_LABEL_MAX
|
||||
|
||||
If this condition is not satisfied the datagram MUST be discarded.
|
||||
If the CIPSO system only supports one port, the HOST_LABEL_MIN and the
|
||||
HOST_LABEL_MAX parameters MAY be substituted for the PORT parameters in
|
||||
the above condition.
|
||||
|
||||
The DOI identifier to be used for all outgoing datagrams is configured by
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 10]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
the administrator. If port level DOI identifier assignment is used, then
|
||||
the PORT_DOI configuration parameter MUST contain the DOI identifier to
|
||||
use. If network level DOI assignment is used, then the NET_DOI parameter
|
||||
MUST contain the DOI identifier to use. And if host level DOI assignment
|
||||
is employed, then the HOST_DOI parameter MUST contain the DOI identifier
|
||||
to use. A CIPSO implementation need only support one level of DOI
|
||||
assignment.
|
||||
|
||||
|
||||
5.3 DOI Processing Requirements
|
||||
|
||||
A CIPSO implementation MUST support at least one DOI and SHOULD support
|
||||
multiple DOIs. System and network administrators are cautioned to
|
||||
ensure that at least one DOI is common within an IP network to allow for
|
||||
broadcasting of IP datagrams.
|
||||
|
||||
CIPSO gateways MUST be capable of translating a CIPSO option from one
|
||||
DOI to another when forwarding datagrams between networks. For
|
||||
efficiency purposes this capability is only a desired feature for CIPSO
|
||||
routers.
|
||||
|
||||
|
||||
5.4 Label of ICMP Messages
|
||||
|
||||
The CIPSO label to be used on all outgoing ICMP messages MUST be equivalent
|
||||
to the label of the datagram that caused the ICMP message. If the ICMP was
|
||||
generated due to a problem associated with the original CIPSO label then the
|
||||
following responses are allowed:
|
||||
|
||||
a. Use the CIPSO label of the original IP datagram
|
||||
b. Drop the original datagram with no return message generated
|
||||
|
||||
In most cases these options will have the same effect. If you can not
|
||||
interpret the label or if it is outside the label range of your host or
|
||||
interface then an ICMP message with the same label will probably not be
|
||||
able to exit the system.
|
||||
|
||||
|
||||
6. Assignment of DOI Identifier Numbers =
|
||||
|
||||
Requests for assignment of a DOI identifier number should be addressed to
|
||||
the Internet Assigned Numbers Authority (IANA).
|
||||
|
||||
|
||||
7. Acknowledgements
|
||||
|
||||
Much of the material in this RFC is based on (and copied from) work
|
||||
done by Gary Winiger of Sun Microsystems and published as Commercial
|
||||
IP Security Option at the INTEROP 89, Commercial IPSO Workshop.
|
||||
|
||||
|
||||
8. Author's Address
|
||||
|
||||
To submit mail for distribution to members of the IETF CIPSO Working
|
||||
Group, send mail to: cipso@wdl1.wdl.loral.com.
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 11]
|
||||
|
||||
|
||||
|
||||
CIPSO INTERNET DRAFT 16 July, 1992
|
||||
|
||||
|
||||
|
||||
|
||||
To be added to or deleted from this distribution, send mail to:
|
||||
cipso-request@wdl1.wdl.loral.com.
|
||||
|
||||
|
||||
9. References
|
||||
|
||||
RFC 1038, "Draft Revised IP Security Option", M. St. Johns, IETF, January
|
||||
1988.
|
||||
|
||||
RFC 1108, "U.S. Department of Defense Security Options
|
||||
for the Internet Protocol", Stephen Kent, IAB, 1 March, 1991.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Internet Draft, Expires 15 Jan 93 [PAGE 12]
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
NetLabel Introduction
|
||||
==============================================================================
|
||||
Paul Moore, paul.moore@hp.com
|
||||
|
||||
August 2, 2006
|
||||
|
||||
* Overview
|
||||
|
||||
NetLabel is a mechanism which can be used by kernel security modules to attach
|
||||
security attributes to outgoing network packets generated from user space
|
||||
applications and read security attributes from incoming network packets. It
|
||||
is composed of three main components, the protocol engines, the communication
|
||||
layer, and the kernel security module API.
|
||||
|
||||
* Protocol Engines
|
||||
|
||||
The protocol engines are responsible for both applying and retrieving the
|
||||
network packet's security attributes. If any translation between the network
|
||||
security attributes and those on the host are required then the protocol
|
||||
engine will handle those tasks as well. Other kernel subsystems should
|
||||
refrain from calling the protocol engines directly, instead they should use
|
||||
the NetLabel kernel security module API described below.
|
||||
|
||||
Detailed information about each NetLabel protocol engine can be found in this
|
||||
directory, consult '00-INDEX' for filenames.
|
||||
|
||||
* Communication Layer
|
||||
|
||||
The communication layer exists to allow NetLabel configuration and monitoring
|
||||
from user space. The NetLabel communication layer uses a message based
|
||||
protocol built on top of the Generic NETLINK transport mechanism. The exact
|
||||
formatting of these NetLabel messages as well as the Generic NETLINK family
|
||||
names can be found in the the 'net/netlabel/' directory as comments in the
|
||||
header files as well as in 'include/net/netlabel.h'.
|
||||
|
||||
* Security Module API
|
||||
|
||||
The purpose of the NetLabel security module API is to provide a protocol
|
||||
independent interface to the underlying NetLabel protocol engines. In addition
|
||||
to protocol independence, the security module API is designed to be completely
|
||||
LSM independent which should allow multiple LSMs to leverage the same code
|
||||
base.
|
||||
|
||||
Detailed information about the NetLabel security module API can be found in the
|
||||
'include/net/netlabel.h' header file as well as the 'lsm_interface.txt' file
|
||||
found in this directory.
|
|
@ -0,0 +1,47 @@
|
|||
NetLabel Linux Security Module Interface
|
||||
==============================================================================
|
||||
Paul Moore, paul.moore@hp.com
|
||||
|
||||
May 17, 2006
|
||||
|
||||
* Overview
|
||||
|
||||
NetLabel is a mechanism which can set and retrieve security attributes from
|
||||
network packets. It is intended to be used by LSM developers who want to make
|
||||
use of a common code base for several different packet labeling protocols.
|
||||
The NetLabel security module API is defined in 'include/net/netlabel.h' but a
|
||||
brief overview is given below.
|
||||
|
||||
* NetLabel Security Attributes
|
||||
|
||||
Since NetLabel supports multiple different packet labeling protocols and LSMs
|
||||
it uses the concept of security attributes to refer to the packet's security
|
||||
labels. The NetLabel security attributes are defined by the
|
||||
'netlbl_lsm_secattr' structure in the NetLabel header file. Internally the
|
||||
NetLabel subsystem converts the security attributes to and from the correct
|
||||
low-level packet label depending on the NetLabel build time and run time
|
||||
configuration. It is up to the LSM developer to translate the NetLabel
|
||||
security attributes into whatever security identifiers are in use for their
|
||||
particular LSM.
|
||||
|
||||
* NetLabel LSM Protocol Operations
|
||||
|
||||
These are the functions which allow the LSM developer to manipulate the labels
|
||||
on outgoing packets as well as read the labels on incoming packets. Functions
|
||||
exist to operate both on sockets as well as the sk_buffs directly. These high
|
||||
level functions are translated into low level protocol operations based on how
|
||||
the administrator has configured the NetLabel subsystem.
|
||||
|
||||
* NetLabel Label Mapping Cache Operations
|
||||
|
||||
Depending on the exact configuration, translation between the network packet
|
||||
label and the internal LSM security identifier can be time consuming. The
|
||||
NetLabel label mapping cache is a caching mechanism which can be used to
|
||||
sidestep much of this overhead once a mapping has been established. Once the
|
||||
LSM has received a packet, used NetLabel to decode it's security attributes,
|
||||
and translated the security attributes into a LSM internal identifier the LSM
|
||||
can use the NetLabel caching functions to associate the LSM internal
|
||||
identifier with the network packet's label. This means that in the future
|
||||
when a incoming packet matches a cached value not only are the internal
|
||||
NetLabel translation mechanisms bypassed but the LSM translation mechanisms are
|
||||
bypassed as well which should result in a significant reduction in overhead.
|
|
@ -375,6 +375,41 @@ tcp_slow_start_after_idle - BOOLEAN
|
|||
be timed out after an idle period.
|
||||
Default: 1
|
||||
|
||||
CIPSOv4 Variables:
|
||||
|
||||
cipso_cache_enable - BOOLEAN
|
||||
If set, enable additions to and lookups from the CIPSO label mapping
|
||||
cache. If unset, additions are ignored and lookups always result in a
|
||||
miss. However, regardless of the setting the cache is still
|
||||
invalidated when required when means you can safely toggle this on and
|
||||
off and the cache will always be "safe".
|
||||
Default: 1
|
||||
|
||||
cipso_cache_bucket_size - INTEGER
|
||||
The CIPSO label cache consists of a fixed size hash table with each
|
||||
hash bucket containing a number of cache entries. This variable limits
|
||||
the number of entries in each hash bucket; the larger the value the
|
||||
more CIPSO label mappings that can be cached. When the number of
|
||||
entries in a given hash bucket reaches this limit adding new entries
|
||||
causes the oldest entry in the bucket to be removed to make room.
|
||||
Default: 10
|
||||
|
||||
cipso_rbm_optfmt - BOOLEAN
|
||||
Enable the "Optimized Tag 1 Format" as defined in section 3.4.2.6 of
|
||||
the CIPSO draft specification (see Documentation/netlabel for details).
|
||||
This means that when set the CIPSO tag will be padded with empty
|
||||
categories in order to make the packet data 32-bit aligned.
|
||||
Default: 0
|
||||
|
||||
cipso_rbm_structvalid - BOOLEAN
|
||||
If set, do a very strict check of the CIPSO option when
|
||||
ip_options_compile() is called. If unset, relax the checks done during
|
||||
ip_options_compile(). Either way is "safe" as errors are caught else
|
||||
where in the CIPSO processing code but setting this to 0 (False) should
|
||||
result in less work (i.e. it should be faster) but could cause problems
|
||||
with other implementations that require strict checking.
|
||||
Default: 0
|
||||
|
||||
IP Variables:
|
||||
|
||||
ip_local_port_range - 2 INTEGERS
|
||||
|
@ -730,6 +765,9 @@ conf/all/forwarding - BOOLEAN
|
|||
|
||||
This referred to as global forwarding.
|
||||
|
||||
proxy_ndp - BOOLEAN
|
||||
Do proxy ndp.
|
||||
|
||||
conf/interface/*:
|
||||
Change special settings per interface.
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
flowi structure:
|
||||
|
||||
The secid member in the flow structure is used in LSMs (e.g. SELinux) to indicate
|
||||
the label of the flow. This label of the flow is currently used in selecting
|
||||
matching labeled xfrm(s).
|
||||
|
||||
If this is an outbound flow, the label is derived from the socket, if any, or
|
||||
the incoming packet this flow is being generated as a response to (e.g. tcp
|
||||
resets, timewait ack, etc.). It is also conceivable that the label could be
|
||||
derived from other sources such as process context, device, etc., in special
|
||||
cases, as may be appropriate.
|
||||
|
||||
If this is an inbound flow, the label is derived from the IPSec security
|
||||
associations, if any, used by the packet.
|
|
@ -0,0 +1,56 @@
|
|||
**************************************************************************
|
||||
** History
|
||||
**
|
||||
** REV# DATE NAME DESCRIPTION
|
||||
** 1.00.00.00 3/31/2004 Erich Chen First release
|
||||
** 1.10.00.04 7/28/2004 Erich Chen modify for ioctl
|
||||
** 1.10.00.06 8/28/2004 Erich Chen modify for 2.6.x
|
||||
** 1.10.00.08 9/28/2004 Erich Chen modify for x86_64
|
||||
** 1.10.00.10 10/10/2004 Erich Chen bug fix for SMP & ioctl
|
||||
** 1.20.00.00 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error
|
||||
** 1.20.00.02 12/09/2004 Erich Chen bug fix with over 2T bytes RAID Volume
|
||||
** 1.20.00.04 1/09/2005 Erich Chen fits for Debian linux kernel version 2.2.xx
|
||||
** 1.20.00.05 2/20/2005 Erich Chen cleanly as look like a Linux driver at 2.6.x
|
||||
** thanks for peoples kindness comment
|
||||
** Kornel Wieliczek
|
||||
** Christoph Hellwig
|
||||
** Adrian Bunk
|
||||
** Andrew Morton
|
||||
** Christoph Hellwig
|
||||
** James Bottomley
|
||||
** Arjan van de Ven
|
||||
** 1.20.00.06 3/12/2005 Erich Chen fix with arcmsr_pci_unmap_dma "unsigned long" cast,
|
||||
** modify PCCB POOL allocated by "dma_alloc_coherent"
|
||||
** (Kornel Wieliczek's comment)
|
||||
** 1.20.00.07 3/23/2005 Erich Chen bug fix with arcmsr_scsi_host_template_init
|
||||
** occur segmentation fault,
|
||||
** if RAID adapter does not on PCI slot
|
||||
** and modprobe/rmmod this driver twice.
|
||||
** bug fix enormous stack usage (Adrian Bunk's comment)
|
||||
** 1.20.00.08 6/23/2005 Erich Chen bug fix with abort command,
|
||||
** in case of heavy loading when sata cable
|
||||
** working on low quality connection
|
||||
** 1.20.00.09 9/12/2005 Erich Chen bug fix with abort command handling, firmware version check
|
||||
** and firmware update notify for hardware bug fix
|
||||
** 1.20.00.10 9/23/2005 Erich Chen enhance sysfs function for change driver's max tag Q number.
|
||||
** add DMA_64BIT_MASK for backward compatible with all 2.6.x
|
||||
** add some useful message for abort command
|
||||
** add ioctl code 'ARCMSR_IOCTL_FLUSH_ADAPTER_CACHE'
|
||||
** customer can send this command for sync raid volume data
|
||||
** 1.20.00.11 9/29/2005 Erich Chen by comment of Arjan van de Ven fix incorrect msleep redefine
|
||||
** cast off sizeof(dma_addr_t) condition for 64bit pci_set_dma_mask
|
||||
** 1.20.00.12 9/30/2005 Erich Chen bug fix with 64bit platform's ccbs using if over 4G system memory
|
||||
** change 64bit pci_set_consistent_dma_mask into 32bit
|
||||
** increcct adapter count if adapter initialize fail.
|
||||
** miss edit at arcmsr_build_ccb....
|
||||
** psge += sizeof(struct _SG64ENTRY *) =>
|
||||
** psge += sizeof(struct _SG64ENTRY)
|
||||
** 64 bits sg entry would be incorrectly calculated
|
||||
** thanks Kornel Wieliczek give me kindly notify
|
||||
** and detail description
|
||||
** 1.20.00.13 11/15/2005 Erich Chen scheduling pending ccb with FIFO
|
||||
** change the architecture of arcmsr command queue list
|
||||
** for linux standard list
|
||||
** enable usage of pci message signal interrupt
|
||||
** follow Randy.Danlup kindness suggestion cleanup this code
|
||||
**************************************************************************
|
|
@ -11,38 +11,43 @@ the original).
|
|||
Supported Cards/Chipsets
|
||||
-------------------------
|
||||
PCI ID (pci.ids) OEM Product
|
||||
9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk)
|
||||
9005:0285:9005:028e Adaptec 2020SA (Skyhawk)
|
||||
9005:0285:9005:028b Adaptec 2025ZCR (Terminator)
|
||||
9005:0285:9005:028f Adaptec 2025SA (Terminator)
|
||||
9005:0285:9005:0286 Adaptec 2120S (Crusader)
|
||||
9005:0286:9005:028d Adaptec 2130S (Lancer)
|
||||
9005:0285:9005:0285 Adaptec 2200S (Vulcan)
|
||||
9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m)
|
||||
9005:0286:9005:028c Adaptec 2230S (Lancer)
|
||||
9005:0286:9005:028c Adaptec 2230SLP (Lancer)
|
||||
9005:0285:9005:0296 Adaptec 2240S (SabreExpress)
|
||||
9005:0285:9005:0290 Adaptec 2410SA (Jaguar)
|
||||
9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)
|
||||
9005:0285:103c:3227 Adaptec 2610SA (Bearcat HP release)
|
||||
9005:0285:9005:0292 Adaptec 2810SA (Corsair-8)
|
||||
9005:0285:9005:0294 Adaptec Prowler
|
||||
9005:0286:9005:029d Adaptec 2420SA (Intruder HP release)
|
||||
9005:0286:9005:029c Adaptec 2620SA (Intruder)
|
||||
9005:0286:9005:029b Adaptec 2820SA (Intruder)
|
||||
9005:0286:9005:02a7 Adaptec 2830SA (Skyray)
|
||||
9005:0286:9005:02a8 Adaptec 2430SA (Skyray)
|
||||
9005:0285:9005:0288 Adaptec 3230S (Harrier)
|
||||
9005:0285:9005:0289 Adaptec 3240S (Tornado)
|
||||
9005:0285:9005:0298 Adaptec 4000SAS (BlackBird)
|
||||
9005:0285:9005:0297 Adaptec 4005SAS (AvonPark)
|
||||
9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X)
|
||||
9005:0285:9005:029a Adaptec 4805SAS (Marauder-E)
|
||||
9005:0286:9005:02a2 Adaptec 3800SAS (Hurricane44)
|
||||
1011:0046:9005:0364 Adaptec 5400S (Mustang)
|
||||
1011:0046:9005:0365 Adaptec 5400S (Mustang)
|
||||
9005:0283:9005:0283 Adaptec Catapult (3210S with arc firmware)
|
||||
9005:0284:9005:0284 Adaptec Tomcat (3410S with arc firmware)
|
||||
9005:0285:9005:0285 Adaptec 2200S (Vulcan)
|
||||
9005:0285:9005:0286 Adaptec 2120S (Crusader)
|
||||
9005:0285:9005:0287 Adaptec 2200S (Vulcan-2m)
|
||||
9005:0285:9005:0288 Adaptec 3230S (Harrier)
|
||||
9005:0285:9005:0289 Adaptec 3240S (Tornado)
|
||||
9005:0285:9005:028a Adaptec 2020ZCR (Skyhawk)
|
||||
9005:0285:9005:028b Adaptec 2025ZCR (Terminator)
|
||||
9005:0286:9005:028c Adaptec 2230S (Lancer)
|
||||
9005:0286:9005:028c Adaptec 2230SLP (Lancer)
|
||||
9005:0286:9005:028d Adaptec 2130S (Lancer)
|
||||
9005:0285:9005:028e Adaptec 2020SA (Skyhawk)
|
||||
9005:0285:9005:028f Adaptec 2025SA (Terminator)
|
||||
9005:0285:9005:0290 Adaptec 2410SA (Jaguar)
|
||||
9005:0285:103c:3227 Adaptec 2610SA (Bearcat HP release)
|
||||
9005:0285:9005:0293 Adaptec 21610SA (Corsair-16)
|
||||
9005:0285:9005:0296 Adaptec 2240S (SabreExpress)
|
||||
9005:0285:9005:0292 Adaptec 2810SA (Corsair-8)
|
||||
9005:0285:9005:0294 Adaptec Prowler
|
||||
9005:0285:9005:0297 Adaptec 4005SAS (AvonPark)
|
||||
9005:0285:9005:0298 Adaptec 4000SAS (BlackBird)
|
||||
9005:0285:9005:0299 Adaptec 4800SAS (Marauder-X)
|
||||
9005:0285:9005:029a Adaptec 4805SAS (Marauder-E)
|
||||
9005:0286:9005:029b Adaptec 2820SA (Intruder)
|
||||
9005:0286:9005:029c Adaptec 2620SA (Intruder)
|
||||
9005:0286:9005:029d Adaptec 2420SA (Intruder HP release)
|
||||
9005:0286:9005:02a2 Adaptec 3800SAS (Hurricane44)
|
||||
9005:0286:9005:02a7 Adaptec 3805SAS (Hurricane80)
|
||||
9005:0286:9005:02a8 Adaptec 3400SAS (Hurricane40)
|
||||
9005:0286:9005:02ac Adaptec 1800SAS (Typhoon44)
|
||||
9005:0286:9005:02b3 Adaptec 2400SAS (Hurricane40lm)
|
||||
9005:0285:9005:02b5 Adaptec ASR5800 (Voodoo44)
|
||||
9005:0285:9005:02b6 Adaptec ASR5805 (Voodoo80)
|
||||
9005:0285:9005:02b7 Adaptec ASR5808 (Voodoo08)
|
||||
1011:0046:9005:0364 Adaptec 5400S (Mustang)
|
||||
1011:0046:9005:0365 Adaptec 5400S (Mustang)
|
||||
9005:0287:9005:0800 Adaptec Themisto (Jupiter)
|
||||
9005:0200:9005:0200 Adaptec Themisto (Jupiter)
|
||||
9005:0286:9005:0800 Adaptec Callisto (Jupiter)
|
||||
|
@ -64,18 +69,20 @@ Supported Cards/Chipsets
|
|||
9005:0285:9005:0290 IBM ServeRAID 7t (Jaguar)
|
||||
9005:0285:1014:02F2 IBM ServeRAID 8i (AvonPark)
|
||||
9005:0285:1014:0312 IBM ServeRAID 8i (AvonParkLite)
|
||||
9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora)
|
||||
9005:0286:1014:9540 IBM ServeRAID 8k/8k-l4 (AuroraLite)
|
||||
9005:0286:9005:029f ICP ICP9014R0 (Lancer)
|
||||
9005:0286:1014:9580 IBM ServeRAID 8k/8k-l8 (Aurora)
|
||||
9005:0286:1014:034d IBM ServeRAID 8s (Hurricane)
|
||||
9005:0286:9005:029e ICP ICP9024R0 (Lancer)
|
||||
9005:0286:9005:029f ICP ICP9014R0 (Lancer)
|
||||
9005:0286:9005:02a0 ICP ICP9047MA (Lancer)
|
||||
9005:0286:9005:02a1 ICP ICP9087MA (Lancer)
|
||||
9005:0286:9005:02a3 ICP ICP5445AU (Hurricane44)
|
||||
9005:0286:9005:02a4 ICP ICP9085LI (Marauder-X)
|
||||
9005:0286:9005:02a5 ICP ICP5085BR (Marauder-E)
|
||||
9005:0286:9005:02a3 ICP ICP5445AU (Hurricane44)
|
||||
9005:0286:9005:02a6 ICP ICP9067MA (Intruder-6)
|
||||
9005:0286:9005:02a9 ICP ICP5087AU (Skyray)
|
||||
9005:0286:9005:02aa ICP ICP5047AU (Skyray)
|
||||
9005:0286:9005:02a9 ICP ICP5085AU (Hurricane80)
|
||||
9005:0286:9005:02aa ICP ICP5045AU (Hurricane40)
|
||||
9005:0286:9005:02b4 ICP ICP5045AL (Hurricane40lm)
|
||||
|
||||
People
|
||||
-------------------------
|
||||
|
|
|
@ -0,0 +1,574 @@
|
|||
*******************************************************************************
|
||||
** ARECA FIRMWARE SPEC
|
||||
*******************************************************************************
|
||||
** Usage of IOP331 adapter
|
||||
** (All In/Out is in IOP331's view)
|
||||
** 1. Message 0 --> InitThread message and retrun code
|
||||
** 2. Doorbell is used for RS-232 emulation
|
||||
** inDoorBell : bit0 -- data in ready
|
||||
** (DRIVER DATA WRITE OK)
|
||||
** bit1 -- data out has been read
|
||||
** (DRIVER DATA READ OK)
|
||||
** outDooeBell: bit0 -- data out ready
|
||||
** (IOP331 DATA WRITE OK)
|
||||
** bit1 -- data in has been read
|
||||
** (IOP331 DATA READ OK)
|
||||
** 3. Index Memory Usage
|
||||
** offset 0xf00 : for RS232 out (request buffer)
|
||||
** offset 0xe00 : for RS232 in (scratch buffer)
|
||||
** offset 0xa00 : for inbound message code message_rwbuffer
|
||||
** (driver send to IOP331)
|
||||
** offset 0xa00 : for outbound message code message_rwbuffer
|
||||
** (IOP331 send to driver)
|
||||
** 4. RS-232 emulation
|
||||
** Currently 128 byte buffer is used
|
||||
** 1st uint32_t : Data length (1--124)
|
||||
** Byte 4--127 : Max 124 bytes of data
|
||||
** 5. PostQ
|
||||
** All SCSI Command must be sent through postQ:
|
||||
** (inbound queue port) Request frame must be 32 bytes aligned
|
||||
** #bit27--bit31 => flag for post ccb
|
||||
** #bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb
|
||||
** bit31 :
|
||||
** 0 : 256 bytes frame
|
||||
** 1 : 512 bytes frame
|
||||
** bit30 :
|
||||
** 0 : normal request
|
||||
** 1 : BIOS request
|
||||
** bit29 : reserved
|
||||
** bit28 : reserved
|
||||
** bit27 : reserved
|
||||
** ---------------------------------------------------------------------------
|
||||
** (outbount queue port) Request reply
|
||||
** #bit27--bit31
|
||||
** => flag for reply
|
||||
** #bit0--bit26
|
||||
** => real address (bit27--bit31) of reply arcmsr_cdb
|
||||
** bit31 : must be 0 (for this type of reply)
|
||||
** bit30 : reserved for BIOS handshake
|
||||
** bit29 : reserved
|
||||
** bit28 :
|
||||
** 0 : no error, ignore AdapStatus/DevStatus/SenseData
|
||||
** 1 : Error, error code in AdapStatus/DevStatus/SenseData
|
||||
** bit27 : reserved
|
||||
** 6. BIOS request
|
||||
** All BIOS request is the same with request from PostQ
|
||||
** Except :
|
||||
** Request frame is sent from configuration space
|
||||
** offset: 0x78 : Request Frame (bit30 == 1)
|
||||
** offset: 0x18 : writeonly to generate
|
||||
** IRQ to IOP331
|
||||
** Completion of request:
|
||||
** (bit30 == 0, bit28==err flag)
|
||||
** 7. Definition of SGL entry (structure)
|
||||
** 8. Message1 Out - Diag Status Code (????)
|
||||
** 9. Message0 message code :
|
||||
** 0x00 : NOP
|
||||
** 0x01 : Get Config
|
||||
** ->offset 0xa00 :for outbound message code message_rwbuffer
|
||||
** (IOP331 send to driver)
|
||||
** Signature 0x87974060(4)
|
||||
** Request len 0x00000200(4)
|
||||
** numbers of queue 0x00000100(4)
|
||||
** SDRAM Size 0x00000100(4)-->256 MB
|
||||
** IDE Channels 0x00000008(4)
|
||||
** vendor 40 bytes char
|
||||
** model 8 bytes char
|
||||
** FirmVer 16 bytes char
|
||||
** Device Map 16 bytes char
|
||||
** FirmwareVersion DWORD <== Added for checking of
|
||||
** new firmware capability
|
||||
** 0x02 : Set Config
|
||||
** ->offset 0xa00 :for inbound message code message_rwbuffer
|
||||
** (driver send to IOP331)
|
||||
** Signature 0x87974063(4)
|
||||
** UPPER32 of Request Frame (4)-->Driver Only
|
||||
** 0x03 : Reset (Abort all queued Command)
|
||||
** 0x04 : Stop Background Activity
|
||||
** 0x05 : Flush Cache
|
||||
** 0x06 : Start Background Activity
|
||||
** (re-start if background is halted)
|
||||
** 0x07 : Check If Host Command Pending
|
||||
** (Novell May Need This Function)
|
||||
** 0x08 : Set controller time
|
||||
** ->offset 0xa00 : for inbound message code message_rwbuffer
|
||||
** (driver to IOP331)
|
||||
** byte 0 : 0xaa <-- signature
|
||||
** byte 1 : 0x55 <-- signature
|
||||
** byte 2 : year (04)
|
||||
** byte 3 : month (1..12)
|
||||
** byte 4 : date (1..31)
|
||||
** byte 5 : hour (0..23)
|
||||
** byte 6 : minute (0..59)
|
||||
** byte 7 : second (0..59)
|
||||
*******************************************************************************
|
||||
*******************************************************************************
|
||||
** RS-232 Interface for Areca Raid Controller
|
||||
** The low level command interface is exclusive with VT100 terminal
|
||||
** --------------------------------------------------------------------
|
||||
** 1. Sequence of command execution
|
||||
** --------------------------------------------------------------------
|
||||
** (A) Header : 3 bytes sequence (0x5E, 0x01, 0x61)
|
||||
** (B) Command block : variable length of data including length,
|
||||
** command code, data and checksum byte
|
||||
** (C) Return data : variable length of data
|
||||
** --------------------------------------------------------------------
|
||||
** 2. Command block
|
||||
** --------------------------------------------------------------------
|
||||
** (A) 1st byte : command block length (low byte)
|
||||
** (B) 2nd byte : command block length (high byte)
|
||||
** note ..command block length shouldn't > 2040 bytes,
|
||||
** length excludes these two bytes
|
||||
** (C) 3rd byte : command code
|
||||
** (D) 4th and following bytes : variable length data bytes
|
||||
** depends on command code
|
||||
** (E) last byte : checksum byte (sum of 1st byte until last data byte)
|
||||
** --------------------------------------------------------------------
|
||||
** 3. Command code and associated data
|
||||
** --------------------------------------------------------------------
|
||||
** The following are command code defined in raid controller Command
|
||||
** code 0x10--0x1? are used for system level management,
|
||||
** no password checking is needed and should be implemented in separate
|
||||
** well controlled utility and not for end user access.
|
||||
** Command code 0x20--0x?? always check the password,
|
||||
** password must be entered to enable these command.
|
||||
** enum
|
||||
** {
|
||||
** GUI_SET_SERIAL=0x10,
|
||||
** GUI_SET_VENDOR,
|
||||
** GUI_SET_MODEL,
|
||||
** GUI_IDENTIFY,
|
||||
** GUI_CHECK_PASSWORD,
|
||||
** GUI_LOGOUT,
|
||||
** GUI_HTTP,
|
||||
** GUI_SET_ETHERNET_ADDR,
|
||||
** GUI_SET_LOGO,
|
||||
** GUI_POLL_EVENT,
|
||||
** GUI_GET_EVENT,
|
||||
** GUI_GET_HW_MONITOR,
|
||||
** // GUI_QUICK_CREATE=0x20, (function removed)
|
||||
** GUI_GET_INFO_R=0x20,
|
||||
** GUI_GET_INFO_V,
|
||||
** GUI_GET_INFO_P,
|
||||
** GUI_GET_INFO_S,
|
||||
** GUI_CLEAR_EVENT,
|
||||
** GUI_MUTE_BEEPER=0x30,
|
||||
** GUI_BEEPER_SETTING,
|
||||
** GUI_SET_PASSWORD,
|
||||
** GUI_HOST_INTERFACE_MODE,
|
||||
** GUI_REBUILD_PRIORITY,
|
||||
** GUI_MAX_ATA_MODE,
|
||||
** GUI_RESET_CONTROLLER,
|
||||
** GUI_COM_PORT_SETTING,
|
||||
** GUI_NO_OPERATION,
|
||||
** GUI_DHCP_IP,
|
||||
** GUI_CREATE_PASS_THROUGH=0x40,
|
||||
** GUI_MODIFY_PASS_THROUGH,
|
||||
** GUI_DELETE_PASS_THROUGH,
|
||||
** GUI_IDENTIFY_DEVICE,
|
||||
** GUI_CREATE_RAIDSET=0x50,
|
||||
** GUI_DELETE_RAIDSET,
|
||||
** GUI_EXPAND_RAIDSET,
|
||||
** GUI_ACTIVATE_RAIDSET,
|
||||
** GUI_CREATE_HOT_SPARE,
|
||||
** GUI_DELETE_HOT_SPARE,
|
||||
** GUI_CREATE_VOLUME=0x60,
|
||||
** GUI_MODIFY_VOLUME,
|
||||
** GUI_DELETE_VOLUME,
|
||||
** GUI_START_CHECK_VOLUME,
|
||||
** GUI_STOP_CHECK_VOLUME
|
||||
** };
|
||||
** Command description :
|
||||
** GUI_SET_SERIAL : Set the controller serial#
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x10
|
||||
** byte 3 : password length (should be 0x0f)
|
||||
** byte 4-0x13 : should be "ArEcATecHnoLogY"
|
||||
** byte 0x14--0x23 : Serial number string (must be 16 bytes)
|
||||
** GUI_SET_VENDOR : Set vendor string for the controller
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x11
|
||||
** byte 3 : password length (should be 0x08)
|
||||
** byte 4-0x13 : should be "ArEcAvAr"
|
||||
** byte 0x14--0x3B : vendor string (must be 40 bytes)
|
||||
** GUI_SET_MODEL : Set the model name of the controller
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x12
|
||||
** byte 3 : password length (should be 0x08)
|
||||
** byte 4-0x13 : should be "ArEcAvAr"
|
||||
** byte 0x14--0x1B : model string (must be 8 bytes)
|
||||
** GUI_IDENTIFY : Identify device
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x13
|
||||
** return "Areca RAID Subsystem "
|
||||
** GUI_CHECK_PASSWORD : Verify password
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x14
|
||||
** byte 3 : password length
|
||||
** byte 4-0x?? : user password to be checked
|
||||
** GUI_LOGOUT : Logout GUI (force password checking on next command)
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x15
|
||||
** GUI_HTTP : HTTP interface (reserved for Http proxy service)(0x16)
|
||||
**
|
||||
** GUI_SET_ETHERNET_ADDR : Set the ethernet MAC address
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x17
|
||||
** byte 3 : password length (should be 0x08)
|
||||
** byte 4-0x13 : should be "ArEcAvAr"
|
||||
** byte 0x14--0x19 : Ethernet MAC address (must be 6 bytes)
|
||||
** GUI_SET_LOGO : Set logo in HTTP
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x18
|
||||
** byte 3 : Page# (0/1/2/3) (0xff --> clear OEM logo)
|
||||
** byte 4/5/6/7 : 0x55/0xaa/0xa5/0x5a
|
||||
** byte 8 : TITLE.JPG data (each page must be 2000 bytes)
|
||||
** note page0 1st 2 byte must be
|
||||
** actual length of the JPG file
|
||||
** GUI_POLL_EVENT : Poll If Event Log Changed
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x19
|
||||
** GUI_GET_EVENT : Read Event
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x1a
|
||||
** byte 3 : Event Page (0:1st page/1/2/3:last page)
|
||||
** GUI_GET_HW_MONITOR : Get HW monitor data
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x1b
|
||||
** byte 3 : # of FANs(example 2)
|
||||
** byte 4 : # of Voltage sensor(example 3)
|
||||
** byte 5 : # of temperature sensor(example 2)
|
||||
** byte 6 : # of power
|
||||
** byte 7/8 : Fan#0 (RPM)
|
||||
** byte 9/10 : Fan#1
|
||||
** byte 11/12 : Voltage#0 original value in *1000
|
||||
** byte 13/14 : Voltage#0 value
|
||||
** byte 15/16 : Voltage#1 org
|
||||
** byte 17/18 : Voltage#1
|
||||
** byte 19/20 : Voltage#2 org
|
||||
** byte 21/22 : Voltage#2
|
||||
** byte 23 : Temp#0
|
||||
** byte 24 : Temp#1
|
||||
** byte 25 : Power indicator (bit0 : power#0,
|
||||
** bit1 : power#1)
|
||||
** byte 26 : UPS indicator
|
||||
** GUI_QUICK_CREATE : Quick create raid/volume set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x20
|
||||
** byte 3/4/5/6 : raw capacity
|
||||
** byte 7 : raid level
|
||||
** byte 8 : stripe size
|
||||
** byte 9 : spare
|
||||
** byte 10/11/12/13: device mask (the devices to create raid/volume)
|
||||
** This function is removed, application like
|
||||
** to implement quick create function
|
||||
** need to use GUI_CREATE_RAIDSET and GUI_CREATE_VOLUMESET function.
|
||||
** GUI_GET_INFO_R : Get Raid Set Information
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x20
|
||||
** byte 3 : raidset#
|
||||
** typedef struct sGUI_RAIDSET
|
||||
** {
|
||||
** BYTE grsRaidSetName[16];
|
||||
** DWORD grsCapacity;
|
||||
** DWORD grsCapacityX;
|
||||
** DWORD grsFailMask;
|
||||
** BYTE grsDevArray[32];
|
||||
** BYTE grsMemberDevices;
|
||||
** BYTE grsNewMemberDevices;
|
||||
** BYTE grsRaidState;
|
||||
** BYTE grsVolumes;
|
||||
** BYTE grsVolumeList[16];
|
||||
** BYTE grsRes1;
|
||||
** BYTE grsRes2;
|
||||
** BYTE grsRes3;
|
||||
** BYTE grsFreeSegments;
|
||||
** DWORD grsRawStripes[8];
|
||||
** DWORD grsRes4;
|
||||
** DWORD grsRes5; // Total to 128 bytes
|
||||
** DWORD grsRes6; // Total to 128 bytes
|
||||
** } sGUI_RAIDSET, *pGUI_RAIDSET;
|
||||
** GUI_GET_INFO_V : Get Volume Set Information
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x21
|
||||
** byte 3 : volumeset#
|
||||
** typedef struct sGUI_VOLUMESET
|
||||
** {
|
||||
** BYTE gvsVolumeName[16]; // 16
|
||||
** DWORD gvsCapacity;
|
||||
** DWORD gvsCapacityX;
|
||||
** DWORD gvsFailMask;
|
||||
** DWORD gvsStripeSize;
|
||||
** DWORD gvsNewFailMask;
|
||||
** DWORD gvsNewStripeSize;
|
||||
** DWORD gvsVolumeStatus;
|
||||
** DWORD gvsProgress; // 32
|
||||
** sSCSI_ATTR gvsScsi;
|
||||
** BYTE gvsMemberDisks;
|
||||
** BYTE gvsRaidLevel; // 8
|
||||
** BYTE gvsNewMemberDisks;
|
||||
** BYTE gvsNewRaidLevel;
|
||||
** BYTE gvsRaidSetNumber;
|
||||
** BYTE gvsRes0; // 4
|
||||
** BYTE gvsRes1[4]; // 64 bytes
|
||||
** } sGUI_VOLUMESET, *pGUI_VOLUMESET;
|
||||
** GUI_GET_INFO_P : Get Physical Drive Information
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x22
|
||||
** byte 3 : drive # (from 0 to max-channels - 1)
|
||||
** typedef struct sGUI_PHY_DRV
|
||||
** {
|
||||
** BYTE gpdModelName[40];
|
||||
** BYTE gpdSerialNumber[20];
|
||||
** BYTE gpdFirmRev[8];
|
||||
** DWORD gpdCapacity;
|
||||
** DWORD gpdCapacityX; // Reserved for expansion
|
||||
** BYTE gpdDeviceState;
|
||||
** BYTE gpdPioMode;
|
||||
** BYTE gpdCurrentUdmaMode;
|
||||
** BYTE gpdUdmaMode;
|
||||
** BYTE gpdDriveSelect;
|
||||
** BYTE gpdRaidNumber; // 0xff if not belongs to a raid set
|
||||
** sSCSI_ATTR gpdScsi;
|
||||
** BYTE gpdReserved[40]; // Total to 128 bytes
|
||||
** } sGUI_PHY_DRV, *pGUI_PHY_DRV;
|
||||
** GUI_GET_INFO_S : Get System Information
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x23
|
||||
** typedef struct sCOM_ATTR
|
||||
** {
|
||||
** BYTE comBaudRate;
|
||||
** BYTE comDataBits;
|
||||
** BYTE comStopBits;
|
||||
** BYTE comParity;
|
||||
** BYTE comFlowControl;
|
||||
** } sCOM_ATTR, *pCOM_ATTR;
|
||||
** typedef struct sSYSTEM_INFO
|
||||
** {
|
||||
** BYTE gsiVendorName[40];
|
||||
** BYTE gsiSerialNumber[16];
|
||||
** BYTE gsiFirmVersion[16];
|
||||
** BYTE gsiBootVersion[16];
|
||||
** BYTE gsiMbVersion[16];
|
||||
** BYTE gsiModelName[8];
|
||||
** BYTE gsiLocalIp[4];
|
||||
** BYTE gsiCurrentIp[4];
|
||||
** DWORD gsiTimeTick;
|
||||
** DWORD gsiCpuSpeed;
|
||||
** DWORD gsiICache;
|
||||
** DWORD gsiDCache;
|
||||
** DWORD gsiScache;
|
||||
** DWORD gsiMemorySize;
|
||||
** DWORD gsiMemorySpeed;
|
||||
** DWORD gsiEvents;
|
||||
** BYTE gsiMacAddress[6];
|
||||
** BYTE gsiDhcp;
|
||||
** BYTE gsiBeeper;
|
||||
** BYTE gsiChannelUsage;
|
||||
** BYTE gsiMaxAtaMode;
|
||||
** BYTE gsiSdramEcc; // 1:if ECC enabled
|
||||
** BYTE gsiRebuildPriority;
|
||||
** sCOM_ATTR gsiComA; // 5 bytes
|
||||
** sCOM_ATTR gsiComB; // 5 bytes
|
||||
** BYTE gsiIdeChannels;
|
||||
** BYTE gsiScsiHostChannels;
|
||||
** BYTE gsiIdeHostChannels;
|
||||
** BYTE gsiMaxVolumeSet;
|
||||
** BYTE gsiMaxRaidSet;
|
||||
** BYTE gsiEtherPort; // 1:if ether net port supported
|
||||
** BYTE gsiRaid6Engine; // 1:Raid6 engine supported
|
||||
** BYTE gsiRes[75];
|
||||
** } sSYSTEM_INFO, *pSYSTEM_INFO;
|
||||
** GUI_CLEAR_EVENT : Clear System Event
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x24
|
||||
** GUI_MUTE_BEEPER : Mute current beeper
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x30
|
||||
** GUI_BEEPER_SETTING : Disable beeper
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x31
|
||||
** byte 3 : 0->disable, 1->enable
|
||||
** GUI_SET_PASSWORD : Change password
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x32
|
||||
** byte 3 : pass word length ( must <= 15 )
|
||||
** byte 4 : password (must be alpha-numerical)
|
||||
** GUI_HOST_INTERFACE_MODE : Set host interface mode
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x33
|
||||
** byte 3 : 0->Independent, 1->cluster
|
||||
** GUI_REBUILD_PRIORITY : Set rebuild priority
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x34
|
||||
** byte 3 : 0/1/2/3 (low->high)
|
||||
** GUI_MAX_ATA_MODE : Set maximum ATA mode to be used
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x35
|
||||
** byte 3 : 0/1/2/3 (133/100/66/33)
|
||||
** GUI_RESET_CONTROLLER : Reset Controller
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x36
|
||||
** *Response with VT100 screen (discard it)
|
||||
** GUI_COM_PORT_SETTING : COM port setting
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x37
|
||||
** byte 3 : 0->COMA (term port),
|
||||
** 1->COMB (debug port)
|
||||
** byte 4 : 0/1/2/3/4/5/6/7
|
||||
** (1200/2400/4800/9600/19200/38400/57600/115200)
|
||||
** byte 5 : data bit
|
||||
** (0:7 bit, 1:8 bit : must be 8 bit)
|
||||
** byte 6 : stop bit (0:1, 1:2 stop bits)
|
||||
** byte 7 : parity (0:none, 1:off, 2:even)
|
||||
** byte 8 : flow control
|
||||
** (0:none, 1:xon/xoff, 2:hardware => must use none)
|
||||
** GUI_NO_OPERATION : No operation
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x38
|
||||
** GUI_DHCP_IP : Set DHCP option and local IP address
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x39
|
||||
** byte 3 : 0:dhcp disabled, 1:dhcp enabled
|
||||
** byte 4/5/6/7 : IP address
|
||||
** GUI_CREATE_PASS_THROUGH : Create pass through disk
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x40
|
||||
** byte 3 : device #
|
||||
** byte 4 : scsi channel (0/1)
|
||||
** byte 5 : scsi id (0-->15)
|
||||
** byte 6 : scsi lun (0-->7)
|
||||
** byte 7 : tagged queue (1 : enabled)
|
||||
** byte 8 : cache mode (1 : enabled)
|
||||
** byte 9 : max speed (0/1/2/3/4,
|
||||
** async/20/40/80/160 for scsi)
|
||||
** (0/1/2/3/4, 33/66/100/133/150 for ide )
|
||||
** GUI_MODIFY_PASS_THROUGH : Modify pass through disk
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x41
|
||||
** byte 3 : device #
|
||||
** byte 4 : scsi channel (0/1)
|
||||
** byte 5 : scsi id (0-->15)
|
||||
** byte 6 : scsi lun (0-->7)
|
||||
** byte 7 : tagged queue (1 : enabled)
|
||||
** byte 8 : cache mode (1 : enabled)
|
||||
** byte 9 : max speed (0/1/2/3/4,
|
||||
** async/20/40/80/160 for scsi)
|
||||
** (0/1/2/3/4, 33/66/100/133/150 for ide )
|
||||
** GUI_DELETE_PASS_THROUGH : Delete pass through disk
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x42
|
||||
** byte 3 : device# to be deleted
|
||||
** GUI_IDENTIFY_DEVICE : Identify Device
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x43
|
||||
** byte 3 : Flash Method
|
||||
** (0:flash selected, 1:flash not selected)
|
||||
** byte 4/5/6/7 : IDE device mask to be flashed
|
||||
** note .... no response data available
|
||||
** GUI_CREATE_RAIDSET : Create Raid Set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x50
|
||||
** byte 3/4/5/6 : device mask
|
||||
** byte 7-22 : raidset name (if byte 7 == 0:use default)
|
||||
** GUI_DELETE_RAIDSET : Delete Raid Set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x51
|
||||
** byte 3 : raidset#
|
||||
** GUI_EXPAND_RAIDSET : Expand Raid Set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x52
|
||||
** byte 3 : raidset#
|
||||
** byte 4/5/6/7 : device mask for expansion
|
||||
** byte 8/9/10 : (8:0 no change, 1 change, 0xff:terminate,
|
||||
** 9:new raid level,
|
||||
** 10:new stripe size
|
||||
** 0/1/2/3/4/5->4/8/16/32/64/128K )
|
||||
** byte 11/12/13 : repeat for each volume in the raidset
|
||||
** GUI_ACTIVATE_RAIDSET : Activate incomplete raid set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x53
|
||||
** byte 3 : raidset#
|
||||
** GUI_CREATE_HOT_SPARE : Create hot spare disk
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x54
|
||||
** byte 3/4/5/6 : device mask for hot spare creation
|
||||
** GUI_DELETE_HOT_SPARE : Delete hot spare disk
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x55
|
||||
** byte 3/4/5/6 : device mask for hot spare deletion
|
||||
** GUI_CREATE_VOLUME : Create volume set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x60
|
||||
** byte 3 : raidset#
|
||||
** byte 4-19 : volume set name
|
||||
** (if byte4 == 0, use default)
|
||||
** byte 20-27 : volume capacity (blocks)
|
||||
** byte 28 : raid level
|
||||
** byte 29 : stripe size
|
||||
** (0/1/2/3/4/5->4/8/16/32/64/128K)
|
||||
** byte 30 : channel
|
||||
** byte 31 : ID
|
||||
** byte 32 : LUN
|
||||
** byte 33 : 1 enable tag
|
||||
** byte 34 : 1 enable cache
|
||||
** byte 35 : speed
|
||||
** (0/1/2/3/4->async/20/40/80/160 for scsi)
|
||||
** (0/1/2/3/4->33/66/100/133/150 for IDE )
|
||||
** byte 36 : 1 to select quick init
|
||||
**
|
||||
** GUI_MODIFY_VOLUME : Modify volume Set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x61
|
||||
** byte 3 : volumeset#
|
||||
** byte 4-19 : new volume set name
|
||||
** (if byte4 == 0, not change)
|
||||
** byte 20-27 : new volume capacity (reserved)
|
||||
** byte 28 : new raid level
|
||||
** byte 29 : new stripe size
|
||||
** (0/1/2/3/4/5->4/8/16/32/64/128K)
|
||||
** byte 30 : new channel
|
||||
** byte 31 : new ID
|
||||
** byte 32 : new LUN
|
||||
** byte 33 : 1 enable tag
|
||||
** byte 34 : 1 enable cache
|
||||
** byte 35 : speed
|
||||
** (0/1/2/3/4->async/20/40/80/160 for scsi)
|
||||
** (0/1/2/3/4->33/66/100/133/150 for IDE )
|
||||
** GUI_DELETE_VOLUME : Delete volume set
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x62
|
||||
** byte 3 : volumeset#
|
||||
** GUI_START_CHECK_VOLUME : Start volume consistency check
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x63
|
||||
** byte 3 : volumeset#
|
||||
** GUI_STOP_CHECK_VOLUME : Stop volume consistency check
|
||||
** byte 0,1 : length
|
||||
** byte 2 : command code 0x64
|
||||
** ---------------------------------------------------------------------
|
||||
** 4. Returned data
|
||||
** ---------------------------------------------------------------------
|
||||
** (A) Header : 3 bytes sequence (0x5E, 0x01, 0x61)
|
||||
** (B) Length : 2 bytes
|
||||
** (low byte 1st, excludes length and checksum byte)
|
||||
** (C) status or data :
|
||||
** <1> If length == 1 ==> 1 byte status code
|
||||
** #define GUI_OK 0x41
|
||||
** #define GUI_RAIDSET_NOT_NORMAL 0x42
|
||||
** #define GUI_VOLUMESET_NOT_NORMAL 0x43
|
||||
** #define GUI_NO_RAIDSET 0x44
|
||||
** #define GUI_NO_VOLUMESET 0x45
|
||||
** #define GUI_NO_PHYSICAL_DRIVE 0x46
|
||||
** #define GUI_PARAMETER_ERROR 0x47
|
||||
** #define GUI_UNSUPPORTED_COMMAND 0x48
|
||||
** #define GUI_DISK_CONFIG_CHANGED 0x49
|
||||
** #define GUI_INVALID_PASSWORD 0x4a
|
||||
** #define GUI_NO_DISK_SPACE 0x4b
|
||||
** #define GUI_CHECKSUM_ERROR 0x4c
|
||||
** #define GUI_PASSWORD_REQUIRED 0x4d
|
||||
** <2> If length > 1 ==>
|
||||
** data block returned from controller
|
||||
** and the contents depends on the command code
|
||||
** (E) Checksum : checksum of length and status or data byte
|
||||
**************************************************************************
|
|
@ -0,0 +1,484 @@
|
|||
SAS Layer
|
||||
---------
|
||||
|
||||
The SAS Layer is a management infrastructure which manages
|
||||
SAS LLDDs. It sits between SCSI Core and SAS LLDDs. The
|
||||
layout is as follows: while SCSI Core is concerned with
|
||||
SAM/SPC issues, and a SAS LLDD+sequencer is concerned with
|
||||
phy/OOB/link management, the SAS layer is concerned with:
|
||||
|
||||
* SAS Phy/Port/HA event management (LLDD generates,
|
||||
SAS Layer processes),
|
||||
* SAS Port management (creation/destruction),
|
||||
* SAS Domain discovery and revalidation,
|
||||
* SAS Domain device management,
|
||||
* SCSI Host registration/unregistration,
|
||||
* Device registration with SCSI Core (SAS) or libata
|
||||
(SATA), and
|
||||
* Expander management and exporting expander control
|
||||
to user space.
|
||||
|
||||
A SAS LLDD is a PCI device driver. It is concerned with
|
||||
phy/OOB management, and vendor specific tasks and generates
|
||||
events to the SAS layer.
|
||||
|
||||
The SAS Layer does most SAS tasks as outlined in the SAS 1.1
|
||||
spec.
|
||||
|
||||
The sas_ha_struct describes the SAS LLDD to the SAS layer.
|
||||
Most of it is used by the SAS Layer but a few fields need to
|
||||
be initialized by the LLDDs.
|
||||
|
||||
After initializing your hardware, from the probe() function
|
||||
you call sas_register_ha(). It will register your LLDD with
|
||||
the SCSI subsystem, creating a SCSI host and it will
|
||||
register your SAS driver with the sysfs SAS tree it creates.
|
||||
It will then return. Then you enable your phys to actually
|
||||
start OOB (at which point your driver will start calling the
|
||||
notify_* event callbacks).
|
||||
|
||||
Structure descriptions:
|
||||
|
||||
struct sas_phy --------------------
|
||||
Normally this is statically embedded to your driver's
|
||||
phy structure:
|
||||
struct my_phy {
|
||||
blah;
|
||||
struct sas_phy sas_phy;
|
||||
bleh;
|
||||
};
|
||||
And then all the phys are an array of my_phy in your HA
|
||||
struct (shown below).
|
||||
|
||||
Then as you go along and initialize your phys you also
|
||||
initialize the sas_phy struct, along with your own
|
||||
phy structure.
|
||||
|
||||
In general, the phys are managed by the LLDD and the ports
|
||||
are managed by the SAS layer. So the phys are initialized
|
||||
and updated by the LLDD and the ports are initialized and
|
||||
updated by the SAS layer.
|
||||
|
||||
There is a scheme where the LLDD can RW certain fields,
|
||||
and the SAS layer can only read such ones, and vice versa.
|
||||
The idea is to avoid unnecessary locking.
|
||||
|
||||
enabled -- must be set (0/1)
|
||||
id -- must be set [0,MAX_PHYS)
|
||||
class, proto, type, role, oob_mode, linkrate -- must be set
|
||||
oob_mode -- you set this when OOB has finished and then notify
|
||||
the SAS Layer.
|
||||
|
||||
sas_addr -- this normally points to an array holding the sas
|
||||
address of the phy, possibly somewhere in your my_phy
|
||||
struct.
|
||||
|
||||
attached_sas_addr -- set this when you (LLDD) receive an
|
||||
IDENTIFY frame or a FIS frame, _before_ notifying the SAS
|
||||
layer. The idea is that sometimes the LLDD may want to fake
|
||||
or provide a different SAS address on that phy/port and this
|
||||
allows it to do this. At best you should copy the sas
|
||||
address from the IDENTIFY frame or maybe generate a SAS
|
||||
address for SATA directly attached devices. The Discover
|
||||
process may later change this.
|
||||
|
||||
frame_rcvd -- this is where you copy the IDENTIFY/FIS frame
|
||||
when you get it; you lock, copy, set frame_rcvd_size and
|
||||
unlock the lock, and then call the event. It is a pointer
|
||||
since there's no way to know your hw frame size _exactly_,
|
||||
so you define the actual array in your phy struct and let
|
||||
this pointer point to it. You copy the frame from your
|
||||
DMAable memory to that area holding the lock.
|
||||
|
||||
sas_prim -- this is where primitives go when they're
|
||||
received. See sas.h. Grab the lock, set the primitive,
|
||||
release the lock, notify.
|
||||
|
||||
port -- this points to the sas_port if the phy belongs
|
||||
to a port -- the LLDD only reads this. It points to the
|
||||
sas_port this phy is part of. Set by the SAS Layer.
|
||||
|
||||
ha -- may be set; the SAS layer sets it anyway.
|
||||
|
||||
lldd_phy -- you should set this to point to your phy so you
|
||||
can find your way around faster when the SAS layer calls one
|
||||
of your callbacks and passes you a phy. If the sas_phy is
|
||||
embedded you can also use container_of -- whatever you
|
||||
prefer.
|
||||
|
||||
|
||||
struct sas_port --------------------
|
||||
The LLDD doesn't set any fields of this struct -- it only
|
||||
reads them. They should be self explanatory.
|
||||
|
||||
phy_mask is 32 bit, this should be enough for now, as I
|
||||
haven't heard of a HA having more than 8 phys.
|
||||
|
||||
lldd_port -- I haven't found use for that -- maybe other
|
||||
LLDD who wish to have internal port representation can make
|
||||
use of this.
|
||||
|
||||
|
||||
struct sas_ha_struct --------------------
|
||||
It normally is statically declared in your own LLDD
|
||||
structure describing your adapter:
|
||||
struct my_sas_ha {
|
||||
blah;
|
||||
struct sas_ha_struct sas_ha;
|
||||
struct my_phy phys[MAX_PHYS];
|
||||
struct sas_port sas_ports[MAX_PHYS]; /* (1) */
|
||||
bleh;
|
||||
};
|
||||
|
||||
(1) If your LLDD doesn't have its own port representation.
|
||||
|
||||
What needs to be initialized (sample function given below).
|
||||
|
||||
pcidev
|
||||
sas_addr -- since the SAS layer doesn't want to mess with
|
||||
memory allocation, etc, this points to statically
|
||||
allocated array somewhere (say in your host adapter
|
||||
structure) and holds the SAS address of the host
|
||||
adapter as given by you or the manufacturer, etc.
|
||||
sas_port
|
||||
sas_phy -- an array of pointers to structures. (see
|
||||
note above on sas_addr).
|
||||
These must be set. See more notes below.
|
||||
num_phys -- the number of phys present in the sas_phy array,
|
||||
and the number of ports present in the sas_port
|
||||
array. There can be a maximum num_phys ports (one per
|
||||
port) so we drop the num_ports, and only use
|
||||
num_phys.
|
||||
|
||||
The event interface:
|
||||
|
||||
/* LLDD calls these to notify the class of an event. */
|
||||
void (*notify_ha_event)(struct sas_ha_struct *, enum ha_event);
|
||||
void (*notify_port_event)(struct sas_phy *, enum port_event);
|
||||
void (*notify_phy_event)(struct sas_phy *, enum phy_event);
|
||||
|
||||
When sas_register_ha() returns, those are set and can be
|
||||
called by the LLDD to notify the SAS layer of such events
|
||||
the SAS layer.
|
||||
|
||||
The port notification:
|
||||
|
||||
/* The class calls these to notify the LLDD of an event. */
|
||||
void (*lldd_port_formed)(struct sas_phy *);
|
||||
void (*lldd_port_deformed)(struct sas_phy *);
|
||||
|
||||
If the LLDD wants notification when a port has been formed
|
||||
or deformed it sets those to a function satisfying the type.
|
||||
|
||||
A SAS LLDD should also implement at least one of the Task
|
||||
Management Functions (TMFs) described in SAM:
|
||||
|
||||
/* Task Management Functions. Must be called from process context. */
|
||||
int (*lldd_abort_task)(struct sas_task *);
|
||||
int (*lldd_abort_task_set)(struct domain_device *, u8 *lun);
|
||||
int (*lldd_clear_aca)(struct domain_device *, u8 *lun);
|
||||
int (*lldd_clear_task_set)(struct domain_device *, u8 *lun);
|
||||
int (*lldd_I_T_nexus_reset)(struct domain_device *);
|
||||
int (*lldd_lu_reset)(struct domain_device *, u8 *lun);
|
||||
int (*lldd_query_task)(struct sas_task *);
|
||||
|
||||
For more information please read SAM from T10.org.
|
||||
|
||||
Port and Adapter management:
|
||||
|
||||
/* Port and Adapter management */
|
||||
int (*lldd_clear_nexus_port)(struct sas_port *);
|
||||
int (*lldd_clear_nexus_ha)(struct sas_ha_struct *);
|
||||
|
||||
A SAS LLDD should implement at least one of those.
|
||||
|
||||
Phy management:
|
||||
|
||||
/* Phy management */
|
||||
int (*lldd_control_phy)(struct sas_phy *, enum phy_func);
|
||||
|
||||
lldd_ha -- set this to point to your HA struct. You can also
|
||||
use container_of if you embedded it as shown above.
|
||||
|
||||
A sample initialization and registration function
|
||||
can look like this (called last thing from probe())
|
||||
*but* before you enable the phys to do OOB:
|
||||
|
||||
static int register_sas_ha(struct my_sas_ha *my_ha)
|
||||
{
|
||||
int i;
|
||||
static struct sas_phy *sas_phys[MAX_PHYS];
|
||||
static struct sas_port *sas_ports[MAX_PHYS];
|
||||
|
||||
my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0];
|
||||
|
||||
for (i = 0; i < MAX_PHYS; i++) {
|
||||
sas_phys[i] = &my_ha->phys[i].sas_phy;
|
||||
sas_ports[i] = &my_ha->sas_ports[i];
|
||||
}
|
||||
|
||||
my_ha->sas_ha.sas_phy = sas_phys;
|
||||
my_ha->sas_ha.sas_port = sas_ports;
|
||||
my_ha->sas_ha.num_phys = MAX_PHYS;
|
||||
|
||||
my_ha->sas_ha.lldd_port_formed = my_port_formed;
|
||||
|
||||
my_ha->sas_ha.lldd_dev_found = my_dev_found;
|
||||
my_ha->sas_ha.lldd_dev_gone = my_dev_gone;
|
||||
|
||||
my_ha->sas_ha.lldd_max_execute_num = lldd_max_execute_num; (1)
|
||||
|
||||
my_ha->sas_ha.lldd_queue_size = ha_can_queue;
|
||||
my_ha->sas_ha.lldd_execute_task = my_execute_task;
|
||||
|
||||
my_ha->sas_ha.lldd_abort_task = my_abort_task;
|
||||
my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set;
|
||||
my_ha->sas_ha.lldd_clear_aca = my_clear_aca;
|
||||
my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set;
|
||||
my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2)
|
||||
my_ha->sas_ha.lldd_lu_reset = my_lu_reset;
|
||||
my_ha->sas_ha.lldd_query_task = my_query_task;
|
||||
|
||||
my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port;
|
||||
my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha;
|
||||
|
||||
my_ha->sas_ha.lldd_control_phy = my_control_phy;
|
||||
|
||||
return sas_register_ha(&my_ha->sas_ha);
|
||||
}
|
||||
|
||||
(1) This is normally a LLDD parameter, something of the
|
||||
lines of a task collector. What it tells the SAS Layer is
|
||||
whether the SAS layer should run in Direct Mode (default:
|
||||
value 0 or 1) or Task Collector Mode (value greater than 1).
|
||||
|
||||
In Direct Mode, the SAS Layer calls Execute Task as soon as
|
||||
it has a command to send to the SDS, _and_ this is a single
|
||||
command, i.e. not linked.
|
||||
|
||||
Some hardware (e.g. aic94xx) has the capability to DMA more
|
||||
than one task at a time (interrupt) from host memory. Task
|
||||
Collector Mode is an optional feature for HAs which support
|
||||
this in their hardware. (Again, it is completely optional
|
||||
even if your hardware supports it.)
|
||||
|
||||
In Task Collector Mode, the SAS Layer would do _natural_
|
||||
coalescing of tasks and at the appropriate moment it would
|
||||
call your driver to DMA more than one task in a single HA
|
||||
interrupt. DMBS may want to use this by insmod/modprobe
|
||||
setting the lldd_max_execute_num to something greater than
|
||||
1.
|
||||
|
||||
(2) SAS 1.1 does not define I_T Nexus Reset TMF.
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
Events are _the only way_ a SAS LLDD notifies the SAS layer
|
||||
of anything. There is no other method or way a LLDD to tell
|
||||
the SAS layer of anything happening internally or in the SAS
|
||||
domain.
|
||||
|
||||
Phy events:
|
||||
PHYE_LOSS_OF_SIGNAL, (C)
|
||||
PHYE_OOB_DONE,
|
||||
PHYE_OOB_ERROR, (C)
|
||||
PHYE_SPINUP_HOLD.
|
||||
|
||||
Port events, passed on a _phy_:
|
||||
PORTE_BYTES_DMAED, (M)
|
||||
PORTE_BROADCAST_RCVD, (E)
|
||||
PORTE_LINK_RESET_ERR, (C)
|
||||
PORTE_TIMER_EVENT, (C)
|
||||
PORTE_HARD_RESET.
|
||||
|
||||
Host Adapter event:
|
||||
HAE_RESET
|
||||
|
||||
A SAS LLDD should be able to generate
|
||||
- at least one event from group C (choice),
|
||||
- events marked M (mandatory) are mandatory (only one),
|
||||
- events marked E (expander) if it wants the SAS layer
|
||||
to handle domain revalidation (only one such).
|
||||
- Unmarked events are optional.
|
||||
|
||||
Meaning:
|
||||
|
||||
HAE_RESET -- when your HA got internal error and was reset.
|
||||
|
||||
PORTE_BYTES_DMAED -- on receiving an IDENTIFY/FIS frame
|
||||
PORTE_BROADCAST_RCVD -- on receiving a primitive
|
||||
PORTE_LINK_RESET_ERR -- timer expired, loss of signal, loss
|
||||
of DWS, etc. (*)
|
||||
PORTE_TIMER_EVENT -- DWS reset timeout timer expired (*)
|
||||
PORTE_HARD_RESET -- Hard Reset primitive received.
|
||||
|
||||
PHYE_LOSS_OF_SIGNAL -- the device is gone (*)
|
||||
PHYE_OOB_DONE -- OOB went fine and oob_mode is valid
|
||||
PHYE_OOB_ERROR -- Error while doing OOB, the device probably
|
||||
got disconnected. (*)
|
||||
PHYE_SPINUP_HOLD -- SATA is present, COMWAKE not sent.
|
||||
|
||||
(*) should set/clear the appropriate fields in the phy,
|
||||
or alternatively call the inlined sas_phy_disconnected()
|
||||
which is just a helper, from their tasklet.
|
||||
|
||||
The Execute Command SCSI RPC:
|
||||
|
||||
int (*lldd_execute_task)(struct sas_task *, int num,
|
||||
unsigned long gfp_flags);
|
||||
|
||||
Used to queue a task to the SAS LLDD. @task is the tasks to
|
||||
be executed. @num should be the number of tasks being
|
||||
queued at this function call (they are linked listed via
|
||||
task::list), @gfp_mask should be the gfp_mask defining the
|
||||
context of the caller.
|
||||
|
||||
This function should implement the Execute Command SCSI RPC,
|
||||
or if you're sending a SCSI Task as linked commands, you
|
||||
should also use this function.
|
||||
|
||||
That is, when lldd_execute_task() is called, the command(s)
|
||||
go out on the transport *immediately*. There is *no*
|
||||
queuing of any sort and at any level in a SAS LLDD.
|
||||
|
||||
The use of task::list is two-fold, one for linked commands,
|
||||
the other discussed below.
|
||||
|
||||
It is possible to queue up more than one task at a time, by
|
||||
initializing the list element of struct sas_task, and
|
||||
passing the number of tasks enlisted in this manner in num.
|
||||
|
||||
Returns: -SAS_QUEUE_FULL, -ENOMEM, nothing was queued;
|
||||
0, the task(s) were queued.
|
||||
|
||||
If you want to pass num > 1, then either
|
||||
A) you're the only caller of this function and keep track
|
||||
of what you've queued to the LLDD, or
|
||||
B) you know what you're doing and have a strategy of
|
||||
retrying.
|
||||
|
||||
As opposed to queuing one task at a time (function call),
|
||||
batch queuing of tasks, by having num > 1, greatly
|
||||
simplifies LLDD code, sequencer code, and _hardware design_,
|
||||
and has some performance advantages in certain situations
|
||||
(DBMS).
|
||||
|
||||
The LLDD advertises if it can take more than one command at
|
||||
a time at lldd_execute_task(), by setting the
|
||||
lldd_max_execute_num parameter (controlled by "collector"
|
||||
module parameter in aic94xx SAS LLDD).
|
||||
|
||||
You should leave this to the default 1, unless you know what
|
||||
you're doing.
|
||||
|
||||
This is a function of the LLDD, to which the SAS layer can
|
||||
cater to.
|
||||
|
||||
int lldd_queue_size
|
||||
The host adapter's queue size. This is the maximum
|
||||
number of commands the lldd can have pending to domain
|
||||
devices on behalf of all upper layers submitting through
|
||||
lldd_execute_task().
|
||||
|
||||
You really want to set this to something (much) larger than
|
||||
1.
|
||||
|
||||
This _really_ has absolutely nothing to do with queuing.
|
||||
There is no queuing in SAS LLDDs.
|
||||
|
||||
struct sas_task {
|
||||
dev -- the device this task is destined to
|
||||
list -- must be initialized (INIT_LIST_HEAD)
|
||||
task_proto -- _one_ of enum sas_proto
|
||||
scatter -- pointer to scatter gather list array
|
||||
num_scatter -- number of elements in scatter
|
||||
total_xfer_len -- total number of bytes expected to be transfered
|
||||
data_dir -- PCI_DMA_...
|
||||
task_done -- callback when the task has finished execution
|
||||
};
|
||||
|
||||
When an external entity, entity other than the LLDD or the
|
||||
SAS Layer, wants to work with a struct domain_device, it
|
||||
_must_ call kobject_get() when getting a handle on the
|
||||
device and kobject_put() when it is done with the device.
|
||||
|
||||
This does two things:
|
||||
A) implements proper kfree() for the device;
|
||||
B) increments/decrements the kref for all players:
|
||||
domain_device
|
||||
all domain_device's ... (if past an expander)
|
||||
port
|
||||
host adapter
|
||||
pci device
|
||||
and up the ladder, etc.
|
||||
|
||||
DISCOVERY
|
||||
---------
|
||||
|
||||
The sysfs tree has the following purposes:
|
||||
a) It shows you the physical layout of the SAS domain at
|
||||
the current time, i.e. how the domain looks in the
|
||||
physical world right now.
|
||||
b) Shows some device parameters _at_discovery_time_.
|
||||
|
||||
This is a link to the tree(1) program, very useful in
|
||||
viewing the SAS domain:
|
||||
ftp://mama.indstate.edu/linux/tree/
|
||||
I expect user space applications to actually create a
|
||||
graphical interface of this.
|
||||
|
||||
That is, the sysfs domain tree doesn't show or keep state if
|
||||
you e.g., change the meaning of the READY LED MEANING
|
||||
setting, but it does show you the current connection status
|
||||
of the domain device.
|
||||
|
||||
Keeping internal device state changes is responsibility of
|
||||
upper layers (Command set drivers) and user space.
|
||||
|
||||
When a device or devices are unplugged from the domain, this
|
||||
is reflected in the sysfs tree immediately, and the device(s)
|
||||
removed from the system.
|
||||
|
||||
The structure domain_device describes any device in the SAS
|
||||
domain. It is completely managed by the SAS layer. A task
|
||||
points to a domain device, this is how the SAS LLDD knows
|
||||
where to send the task(s) to. A SAS LLDD only reads the
|
||||
contents of the domain_device structure, but it never creates
|
||||
or destroys one.
|
||||
|
||||
Expander management from User Space
|
||||
-----------------------------------
|
||||
|
||||
In each expander directory in sysfs, there is a file called
|
||||
"smp_portal". It is a binary sysfs attribute file, which
|
||||
implements an SMP portal (Note: this is *NOT* an SMP port),
|
||||
to which user space applications can send SMP requests and
|
||||
receive SMP responses.
|
||||
|
||||
Functionality is deceptively simple:
|
||||
|
||||
1. Build the SMP frame you want to send. The format and layout
|
||||
is described in the SAS spec. Leave the CRC field equal 0.
|
||||
open(2)
|
||||
2. Open the expander's SMP portal sysfs file in RW mode.
|
||||
write(2)
|
||||
3. Write the frame you built in 1.
|
||||
read(2)
|
||||
4. Read the amount of data you expect to receive for the frame you built.
|
||||
If you receive different amount of data you expected to receive,
|
||||
then there was some kind of error.
|
||||
close(2)
|
||||
All this process is shown in detail in the function do_smp_func()
|
||||
and its callers, in the file "expander_conf.c".
|
||||
|
||||
The kernel functionality is implemented in the file
|
||||
"sas_expander.c".
|
||||
|
||||
The program "expander_conf.c" implements this. It takes one
|
||||
argument, the sysfs file name of the SMP portal to the
|
||||
expander, and gives expander information, including routing
|
||||
tables.
|
||||
|
||||
The SMP portal gives you complete control of the expander,
|
||||
so please be careful.
|
|
@ -758,6 +758,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
|
||||
single_cmd - Use single immediate commands to communicate with
|
||||
codecs (for debugging only)
|
||||
disable_msi - Disable Message Signaled Interrupt (MSI)
|
||||
|
||||
This module supports one card and autoprobe.
|
||||
|
||||
|
@ -778,11 +779,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
6stack-digout 6-jack with a SPDIF out
|
||||
w810 3-jack
|
||||
z71v 3-jack (HP shared SPDIF)
|
||||
asus 3-jack
|
||||
asus 3-jack (ASUS Mobo)
|
||||
asus-w1v ASUS W1V
|
||||
asus-dig ASUS with SPDIF out
|
||||
asus-dig2 ASUS with SPDIF out (using GPIO2)
|
||||
uniwill 3-jack
|
||||
F1734 2-jack
|
||||
lg LG laptop (m1 express dual)
|
||||
lg-lw LG LW20 laptop
|
||||
lg-lw LG LW20/LW25 laptop
|
||||
tcl TCL S700
|
||||
clevo Clevo laptops (m520G, m665n)
|
||||
test for testing/debugging purpose, almost all controls can be
|
||||
adjusted. Appearing only when compiled with
|
||||
$CONFIG_SND_DEBUG=y
|
||||
|
@ -790,6 +796,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
ALC260
|
||||
hp HP machines
|
||||
hp-3013 HP machines (3013-variant)
|
||||
fujitsu Fujitsu S7020
|
||||
acer Acer TravelMate
|
||||
basic fixed pin assignment (old default model)
|
||||
|
@ -797,24 +804,32 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
ALC262
|
||||
fujitsu Fujitsu Laptop
|
||||
hp-bpc HP xw4400/6400/8400/9400 laptops
|
||||
benq Benq ED8
|
||||
basic fixed pin assignment w/o SPDIF
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC882/885
|
||||
3stack-dig 3-jack with SPDIF I/O
|
||||
6stck-dig 6-jack digital with SPDIF I/O
|
||||
arima Arima W820Di1
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC883/888
|
||||
3stack-dig 3-jack with SPDIF I/O
|
||||
6stack-dig 6-jack digital with SPDIF I/O
|
||||
6stack-dig-demo 6-stack digital for Intel demo board
|
||||
3stack-6ch 3-jack 6-channel
|
||||
3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
|
||||
6stack-dig-demo 6-jack digital for Intel demo board
|
||||
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
ALC861/660
|
||||
3stack 3-jack
|
||||
3stack-dig 3-jack with SPDIF I/O
|
||||
6stack-dig 6-jack with SPDIF I/O
|
||||
3stack-660 3-jack (for ALC660)
|
||||
uniwill-m31 Uniwill M31 laptop
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
CMI9880
|
||||
|
@ -843,10 +858,21 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
3stack-dig ditto with SPDIF
|
||||
laptop 3-jack with hp-jack automute
|
||||
laptop-dig ditto with SPDIF
|
||||
auto auto-confgi reading BIOS (default)
|
||||
auto auto-config reading BIOS (default)
|
||||
|
||||
STAC7661(?)
|
||||
STAC9200/9205/9220/9221/9254
|
||||
ref Reference board
|
||||
3stack D945 3stack
|
||||
5stack D945 5stack + SPDIF
|
||||
|
||||
STAC9227/9228/9229/927x
|
||||
ref Reference board
|
||||
3stack D965 3stack
|
||||
5stack D965 5stack + SPDIF
|
||||
|
||||
STAC9872
|
||||
vaio Setup for VAIO FE550G/SZ110
|
||||
vaio-ar Setup for VAIO AR
|
||||
|
||||
If the default configuration doesn't work and one of the above
|
||||
matches with your device, report it together with the PCI
|
||||
|
@ -1213,6 +1239,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
|
|||
|
||||
Module supports only 1 card. This module has no enable option.
|
||||
|
||||
Module snd-mts64
|
||||
----------------
|
||||
|
||||
Module for Ego Systems (ESI) Miditerminal 4140
|
||||
|
||||
This module supports multiple devices.
|
||||
Requires parport (CONFIG_PARPORT).
|
||||
|
||||
Module snd-nm256
|
||||
----------------
|
||||
|
||||
|
|
|
@ -1054,9 +1054,8 @@
|
|||
|
||||
<para>
|
||||
For a device which allows hotplugging, you can use
|
||||
<function>snd_card_free_in_thread</function>. This one will
|
||||
postpone the destruction and wait in a kernel-thread until all
|
||||
devices are closed.
|
||||
<function>snd_card_free_when_closed</function>. This one will
|
||||
postpone the destruction until all devices are closed.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
|
29
MAINTAINERS
29
MAINTAINERS
|
@ -298,6 +298,14 @@ L: info-linux@geode.amd.com
|
|||
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
|
||||
S: Supported
|
||||
|
||||
AMSO1100 RNIC DRIVER
|
||||
P: Tom Tucker
|
||||
M: tom@opengridcomputing.com
|
||||
P: Steve Wise
|
||||
M: swise@opengridcomputing.com
|
||||
L: openib-general@openib.org
|
||||
S: Maintained
|
||||
|
||||
AOA (Apple Onboard Audio) ALSA DRIVER
|
||||
P: Johannes Berg
|
||||
M: johannes@sipsolutions.net
|
||||
|
@ -991,6 +999,14 @@ EFS FILESYSTEM
|
|||
W: http://aeschi.ch.eu.org/efs/
|
||||
S: Orphan
|
||||
|
||||
EHCA (IBM GX bus InfiniBand adapter) DRIVER:
|
||||
P: Hoang-Nam Nguyen
|
||||
M: hnguyen@de.ibm.com
|
||||
P: Christoph Raisch
|
||||
M: raisch@de.ibm.com
|
||||
L: openib-general@openib.org
|
||||
S: Supported
|
||||
|
||||
EMU10K1 SOUND DRIVER
|
||||
P: James Courtier-Dutton
|
||||
M: James@superbug.demon.co.uk
|
||||
|
@ -1783,6 +1799,13 @@ W: http://www.penguinppc.org/
|
|||
L: linuxppc-embedded@ozlabs.org
|
||||
S: Maintained
|
||||
|
||||
LINUX FOR POWERPC PA SEMI PWRFICIENT
|
||||
P: Olof Johansson
|
||||
M: olof@lixom.net
|
||||
W: http://www.pasemi.com/
|
||||
L: linuxppc-dev@ozlabs.org
|
||||
S: Supported
|
||||
|
||||
LLC (802.2)
|
||||
P: Arnaldo Carvalho de Melo
|
||||
M: acme@conectiva.com.br
|
||||
|
@ -2445,6 +2468,8 @@ S: Maintained
|
|||
S390
|
||||
P: Martin Schwidefsky
|
||||
M: schwidefsky@de.ibm.com
|
||||
P: Heiko Carstens
|
||||
M: heiko.carstens@de.ibm.com
|
||||
M: linux390@de.ibm.com
|
||||
L: linux-390@vm.marist.edu
|
||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||
|
@ -2459,8 +2484,8 @@ W: http://www.ibm.com/developerworks/linux/linux390/
|
|||
S: Supported
|
||||
|
||||
S390 ZFCP DRIVER
|
||||
P: Andreas Herrmann
|
||||
M: aherrman@de.ibm.com
|
||||
P: Swen Schillig
|
||||
M: swen@vnet.ibm.com
|
||||
M: linux390@de.ibm.com
|
||||
L: linux-390@vm.marist.edu
|
||||
W: http://www.ibm.com/developerworks/linux/linux390/
|
||||
|
|
5
Makefile
5
Makefile
|
@ -1,8 +1,8 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 18
|
||||
EXTRAVERSION = -rc7
|
||||
NAME=Crazed Snow-Weasel
|
||||
EXTRAVERSION =
|
||||
NAME=Avast! A bilge rat!
|
||||
|
||||
# *DOCUMENTATION*
|
||||
# To see a list of typical targets execute "make help"
|
||||
|
@ -1082,6 +1082,7 @@ help:
|
|||
@echo 'Static analysers'
|
||||
@echo ' checkstack - Generate a list of stack hogs'
|
||||
@echo ' namespacecheck - Name space analysis on compiled kernel'
|
||||
@echo ' headers_check - Sanity check on exported headers'
|
||||
@echo ''
|
||||
@echo 'Kernel packaging:'
|
||||
@$(MAKE) $(build)=$(package-dir) help
|
||||
|
|
|
@ -108,11 +108,8 @@ Image: vmlinux
|
|||
bootstrap:
|
||||
$(Q)$(MAKEBOOT) bootstrap
|
||||
|
||||
archmrproper:
|
||||
$(Q)$(MAKE) $(build)=arch/frv/boot mrproper
|
||||
|
||||
archclean:
|
||||
$(Q)$(MAKE) $(build)=arch/frv/boot clean
|
||||
$(Q)$(MAKE) $(clean)=arch/frv/boot
|
||||
|
||||
archdep: scripts/mkdep symlinks
|
||||
$(Q)$(MAKE) $(build)=arch/frv/boot dep
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
# Copyright (C) 1995-2000 Russell King
|
||||
#
|
||||
|
||||
targets := Image zImage bootpImage
|
||||
|
||||
SYSTEM =$(TOPDIR)/$(LINUX)
|
||||
|
||||
ZTEXTADDR = 0x02080000
|
||||
|
@ -66,7 +68,6 @@ zinstall: $(CONFIGURE) zImage
|
|||
# miscellany
|
||||
#
|
||||
mrproper clean:
|
||||
$(RM) Image zImage bootpImage
|
||||
# @$(MAKE) -C compressed clean
|
||||
# @$(MAKE) -C bootp clean
|
||||
|
||||
|
|
|
@ -5,5 +5,8 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
|
||||
obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
|
||||
|
||||
aes-i586-y := aes-i586-asm.o aes.o
|
||||
twofish-i586-y := twofish-i586-asm.o twofish.o
|
||||
|
||||
|
|
|
@ -379,12 +379,13 @@ static void gen_tabs(void)
|
|||
}
|
||||
|
||||
static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
|
||||
unsigned int key_len, u32 *flags)
|
||||
unsigned int key_len)
|
||||
{
|
||||
int i;
|
||||
u32 ss[8];
|
||||
struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
const __le32 *key = (const __le32 *)in_key;
|
||||
u32 *flags = &tfm->crt_flags;
|
||||
|
||||
/* encryption schedule */
|
||||
|
||||
|
|
|
@ -0,0 +1,335 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2006 by Joachim Fritschi, <jfritschi@freenet.de> *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
.file "twofish-i586-asm.S"
|
||||
.text
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
|
||||
/* return adress at 0 */
|
||||
|
||||
#define in_blk 12 /* input byte array address parameter*/
|
||||
#define out_blk 8 /* output byte array address parameter*/
|
||||
#define tfm 4 /* Twofish context structure */
|
||||
|
||||
#define a_offset 0
|
||||
#define b_offset 4
|
||||
#define c_offset 8
|
||||
#define d_offset 12
|
||||
|
||||
/* Structure of the crypto context struct*/
|
||||
|
||||
#define s0 0 /* S0 Array 256 Words each */
|
||||
#define s1 1024 /* S1 Array */
|
||||
#define s2 2048 /* S2 Array */
|
||||
#define s3 3072 /* S3 Array */
|
||||
#define w 4096 /* 8 whitening keys (word) */
|
||||
#define k 4128 /* key 1-32 ( word ) */
|
||||
|
||||
/* define a few register aliases to allow macro substitution */
|
||||
|
||||
#define R0D %eax
|
||||
#define R0B %al
|
||||
#define R0H %ah
|
||||
|
||||
#define R1D %ebx
|
||||
#define R1B %bl
|
||||
#define R1H %bh
|
||||
|
||||
#define R2D %ecx
|
||||
#define R2B %cl
|
||||
#define R2H %ch
|
||||
|
||||
#define R3D %edx
|
||||
#define R3B %dl
|
||||
#define R3H %dh
|
||||
|
||||
|
||||
/* performs input whitening */
|
||||
#define input_whitening(src,context,offset)\
|
||||
xor w+offset(context), src;
|
||||
|
||||
/* performs input whitening */
|
||||
#define output_whitening(src,context,offset)\
|
||||
xor w+16+offset(context), src;
|
||||
|
||||
/*
|
||||
* a input register containing a (rotated 16)
|
||||
* b input register containing b
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
*/
|
||||
#define encrypt_round(a,b,c,d,round)\
|
||||
push d ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s1(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov s2(%ebp,%edi,4),%esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor s2(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%ebp,%edi,4),%esi;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s3(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $15, b ## D;\
|
||||
xor (%ebp,%edi,4), d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add d ## D, %esi;\
|
||||
add %esi, d ## D;\
|
||||
add k+round(%ebp), %esi;\
|
||||
xor %esi, c ## D;\
|
||||
rol $15, c ## D;\
|
||||
add k+4+round(%ebp),d ## D;\
|
||||
xor %edi, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a (rotated 16)
|
||||
* b input register containing b
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
* last round has different rotations for the output preparation
|
||||
*/
|
||||
#define encrypt_last_round(a,b,c,d,round)\
|
||||
push d ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s1(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov s2(%ebp,%edi,4),%esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor s2(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%ebp,%edi,4),%esi;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s3(%ebp,%edi,4),d ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%ebp,%edi,4), d ## D;\
|
||||
movzx a ## H, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add d ## D, %esi;\
|
||||
add %esi, d ## D;\
|
||||
add k+round(%ebp), %esi;\
|
||||
xor %esi, c ## D;\
|
||||
ror $1, c ## D;\
|
||||
add k+4+round(%ebp),d ## D;\
|
||||
xor %edi, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a
|
||||
* b input register containing b (rotated 16)
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
*/
|
||||
#define decrypt_round(a,b,c,d,round)\
|
||||
push c ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov (%ebp,%edi,4), c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s3(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s1(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx a ## B, %edi;\
|
||||
xor s2(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $15, a ## D;\
|
||||
xor s3(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
xor s2(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add %esi, c ## D;\
|
||||
add c ## D, %esi;\
|
||||
add k+round(%ebp), c ## D;\
|
||||
xor %edi, c ## D;\
|
||||
add k+4+round(%ebp),%esi;\
|
||||
xor %esi, d ## D;\
|
||||
rol $15, d ## D;
|
||||
|
||||
/*
|
||||
* a input register containing a
|
||||
* b input register containing b (rotated 16)
|
||||
* c input register containing c
|
||||
* d input register containing d (already rol $1)
|
||||
* operations on a and b are interleaved to increase performance
|
||||
* last round has different rotations for the output preparation
|
||||
*/
|
||||
#define decrypt_last_round(a,b,c,d,round)\
|
||||
push c ## D;\
|
||||
movzx a ## B, %edi;\
|
||||
mov (%ebp,%edi,4), c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
mov s3(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s1(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
ror $16, b ## D;\
|
||||
xor (%ebp,%edi,4), %esi;\
|
||||
movzx a ## B, %edi;\
|
||||
xor s2(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## B, %edi;\
|
||||
xor s1(%ebp,%edi,4),%esi;\
|
||||
movzx a ## H, %edi;\
|
||||
ror $16, a ## D;\
|
||||
xor s3(%ebp,%edi,4),c ## D;\
|
||||
movzx b ## H, %edi;\
|
||||
xor s2(%ebp,%edi,4),%esi;\
|
||||
pop %edi;\
|
||||
add %esi, c ## D;\
|
||||
add c ## D, %esi;\
|
||||
add k+round(%ebp), c ## D;\
|
||||
xor %edi, c ## D;\
|
||||
add k+4+round(%ebp),%esi;\
|
||||
xor %esi, d ## D;\
|
||||
ror $1, d ## D;
|
||||
|
||||
.align 4
|
||||
.global twofish_enc_blk
|
||||
.global twofish_dec_blk
|
||||
|
||||
twofish_enc_blk:
|
||||
push %ebp /* save registers according to calling convention*/
|
||||
push %ebx
|
||||
push %esi
|
||||
push %edi
|
||||
|
||||
mov tfm + 16(%esp), %ebp /* abuse the base pointer: set new base bointer to the crypto tfm */
|
||||
add $crypto_tfm_ctx_offset, %ebp /* ctx adress */
|
||||
mov in_blk+16(%esp),%edi /* input adress in edi */
|
||||
|
||||
mov (%edi), %eax
|
||||
mov b_offset(%edi), %ebx
|
||||
mov c_offset(%edi), %ecx
|
||||
mov d_offset(%edi), %edx
|
||||
input_whitening(%eax,%ebp,a_offset)
|
||||
ror $16, %eax
|
||||
input_whitening(%ebx,%ebp,b_offset)
|
||||
input_whitening(%ecx,%ebp,c_offset)
|
||||
input_whitening(%edx,%ebp,d_offset)
|
||||
rol $1, %edx
|
||||
|
||||
encrypt_round(R0,R1,R2,R3,0);
|
||||
encrypt_round(R2,R3,R0,R1,8);
|
||||
encrypt_round(R0,R1,R2,R3,2*8);
|
||||
encrypt_round(R2,R3,R0,R1,3*8);
|
||||
encrypt_round(R0,R1,R2,R3,4*8);
|
||||
encrypt_round(R2,R3,R0,R1,5*8);
|
||||
encrypt_round(R0,R1,R2,R3,6*8);
|
||||
encrypt_round(R2,R3,R0,R1,7*8);
|
||||
encrypt_round(R0,R1,R2,R3,8*8);
|
||||
encrypt_round(R2,R3,R0,R1,9*8);
|
||||
encrypt_round(R0,R1,R2,R3,10*8);
|
||||
encrypt_round(R2,R3,R0,R1,11*8);
|
||||
encrypt_round(R0,R1,R2,R3,12*8);
|
||||
encrypt_round(R2,R3,R0,R1,13*8);
|
||||
encrypt_round(R0,R1,R2,R3,14*8);
|
||||
encrypt_last_round(R2,R3,R0,R1,15*8);
|
||||
|
||||
output_whitening(%eax,%ebp,c_offset)
|
||||
output_whitening(%ebx,%ebp,d_offset)
|
||||
output_whitening(%ecx,%ebp,a_offset)
|
||||
output_whitening(%edx,%ebp,b_offset)
|
||||
mov out_blk+16(%esp),%edi;
|
||||
mov %eax, c_offset(%edi)
|
||||
mov %ebx, d_offset(%edi)
|
||||
mov %ecx, (%edi)
|
||||
mov %edx, b_offset(%edi)
|
||||
|
||||
pop %edi
|
||||
pop %esi
|
||||
pop %ebx
|
||||
pop %ebp
|
||||
mov $1, %eax
|
||||
ret
|
||||
|
||||
twofish_dec_blk:
|
||||
push %ebp /* save registers according to calling convention*/
|
||||
push %ebx
|
||||
push %esi
|
||||
push %edi
|
||||
|
||||
|
||||
mov tfm + 16(%esp), %ebp /* abuse the base pointer: set new base bointer to the crypto tfm */
|
||||
add $crypto_tfm_ctx_offset, %ebp /* ctx adress */
|
||||
mov in_blk+16(%esp),%edi /* input adress in edi */
|
||||
|
||||
mov (%edi), %eax
|
||||
mov b_offset(%edi), %ebx
|
||||
mov c_offset(%edi), %ecx
|
||||
mov d_offset(%edi), %edx
|
||||
output_whitening(%eax,%ebp,a_offset)
|
||||
output_whitening(%ebx,%ebp,b_offset)
|
||||
ror $16, %ebx
|
||||
output_whitening(%ecx,%ebp,c_offset)
|
||||
output_whitening(%edx,%ebp,d_offset)
|
||||
rol $1, %ecx
|
||||
|
||||
decrypt_round(R0,R1,R2,R3,15*8);
|
||||
decrypt_round(R2,R3,R0,R1,14*8);
|
||||
decrypt_round(R0,R1,R2,R3,13*8);
|
||||
decrypt_round(R2,R3,R0,R1,12*8);
|
||||
decrypt_round(R0,R1,R2,R3,11*8);
|
||||
decrypt_round(R2,R3,R0,R1,10*8);
|
||||
decrypt_round(R0,R1,R2,R3,9*8);
|
||||
decrypt_round(R2,R3,R0,R1,8*8);
|
||||
decrypt_round(R0,R1,R2,R3,7*8);
|
||||
decrypt_round(R2,R3,R0,R1,6*8);
|
||||
decrypt_round(R0,R1,R2,R3,5*8);
|
||||
decrypt_round(R2,R3,R0,R1,4*8);
|
||||
decrypt_round(R0,R1,R2,R3,3*8);
|
||||
decrypt_round(R2,R3,R0,R1,2*8);
|
||||
decrypt_round(R0,R1,R2,R3,1*8);
|
||||
decrypt_last_round(R2,R3,R0,R1,0);
|
||||
|
||||
input_whitening(%eax,%ebp,c_offset)
|
||||
input_whitening(%ebx,%ebp,d_offset)
|
||||
input_whitening(%ecx,%ebp,a_offset)
|
||||
input_whitening(%edx,%ebp,b_offset)
|
||||
mov out_blk+16(%esp),%edi;
|
||||
mov %eax, c_offset(%edi)
|
||||
mov %ebx, d_offset(%edi)
|
||||
mov %ecx, (%edi)
|
||||
mov %edx, b_offset(%edi)
|
||||
|
||||
pop %edi
|
||||
pop %esi
|
||||
pop %ebx
|
||||
pop %ebp
|
||||
mov $1, %eax
|
||||
ret
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Glue Code for optimized 586 assembler version of TWOFISH
|
||||
*
|
||||
* Originally Twofish for GPG
|
||||
* By Matthew Skala <mskala@ansuz.sooke.bc.ca>, July 26, 1998
|
||||
* 256-bit key length added March 20, 1999
|
||||
* Some modifications to reduce the text size by Werner Koch, April, 1998
|
||||
* Ported to the kerneli patch by Marc Mutz <Marc@Mutz.com>
|
||||
* Ported to CryptoAPI by Colin Slater <hoho@tacomeat.net>
|
||||
*
|
||||
* The original author has disclaimed all copyright interest in this
|
||||
* code and thus put it in the public domain. The subsequent authors
|
||||
* have put this under the GNU General Public License.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*
|
||||
* This code is a "clean room" implementation, written from the paper
|
||||
* _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey,
|
||||
* Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available
|
||||
* through http://www.counterpane.com/twofish.html
|
||||
*
|
||||
* For background information on multiplication in finite fields, used for
|
||||
* the matrix operations in the key schedule, see the book _Contemporary
|
||||
* Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the
|
||||
* Third Edition.
|
||||
*/
|
||||
|
||||
#include <crypto/twofish.h>
|
||||
#include <linux/crypto.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
|
||||
|
||||
static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_enc_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
|
||||
{
|
||||
twofish_dec_blk(tfm, dst, src);
|
||||
}
|
||||
|
||||
static struct crypto_alg alg = {
|
||||
.cra_name = "twofish",
|
||||
.cra_driver_name = "twofish-i586",
|
||||
.cra_priority = 200,
|
||||
.cra_flags = CRYPTO_ALG_TYPE_CIPHER,
|
||||
.cra_blocksize = TF_BLOCK_SIZE,
|
||||
.cra_ctxsize = sizeof(struct twofish_ctx),
|
||||
.cra_alignmask = 3,
|
||||
.cra_module = THIS_MODULE,
|
||||
.cra_list = LIST_HEAD_INIT(alg.cra_list),
|
||||
.cra_u = {
|
||||
.cipher = {
|
||||
.cia_min_keysize = TF_MIN_KEY_SIZE,
|
||||
.cia_max_keysize = TF_MAX_KEY_SIZE,
|
||||
.cia_setkey = twofish_setkey,
|
||||
.cia_encrypt = twofish_encrypt,
|
||||
.cia_decrypt = twofish_decrypt
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
return crypto_register_alg(&alg);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
crypto_unregister_alg(&alg);
|
||||
}
|
||||
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION ("Twofish Cipher Algorithm, i586 asm optimized");
|
||||
MODULE_ALIAS("twofish");
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/sched.h> /* current */
|
||||
#include <linux/dmi.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -387,6 +388,33 @@ static int acpi_cpufreq_early_init_acpi(void)
|
|||
return acpi_processor_preregister_performance(acpi_perf_data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some BIOSes do SW_ANY coordination internally, either set it up in hw
|
||||
* or do it in BIOS firmware and won't inform about it to OS. If not
|
||||
* detected, this has a side effect of making CPU run at a different speed
|
||||
* than OS intended it to run at. Detect it and handle it cleanly.
|
||||
*/
|
||||
static int bios_with_sw_any_bug;
|
||||
|
||||
static int __init sw_any_bug_found(struct dmi_system_id *d)
|
||||
{
|
||||
bios_with_sw_any_bug = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __initdata sw_any_bug_dmi_table[] = {
|
||||
{
|
||||
.callback = sw_any_bug_found,
|
||||
.ident = "Supermicro Server X6DLP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "080010"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static int
|
||||
acpi_cpufreq_cpu_init (
|
||||
struct cpufreq_policy *policy)
|
||||
|
@ -422,8 +450,17 @@ acpi_cpufreq_cpu_init (
|
|||
* coordination is required.
|
||||
*/
|
||||
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
|
||||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
|
||||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
|
||||
policy->cpus = perf->shared_cpu_map;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
dmi_check_system(sw_any_bug_dmi_table);
|
||||
if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
|
||||
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
|
||||
policy->cpus = cpu_core_map[cpu];
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
|
||||
acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
|
@ -52,18 +53,26 @@
|
|||
#define CPU_NEHEMIAH 5
|
||||
|
||||
static int cpu_model;
|
||||
static unsigned int numscales=16, numvscales;
|
||||
static unsigned int numscales=16;
|
||||
static unsigned int fsb;
|
||||
static int minvid, maxvid;
|
||||
|
||||
static struct mV_pos *vrm_mV_table;
|
||||
static unsigned char *mV_vrm_table;
|
||||
struct f_msr {
|
||||
unsigned char vrm;
|
||||
};
|
||||
static struct f_msr f_msr_table[32];
|
||||
|
||||
static unsigned int highest_speed, lowest_speed; /* kHz */
|
||||
static unsigned int minmult, maxmult;
|
||||
static int can_scale_voltage;
|
||||
static int vrmrev;
|
||||
static struct acpi_processor *pr = NULL;
|
||||
static struct acpi_processor_cx *cx = NULL;
|
||||
static int port22_en;
|
||||
|
||||
/* Module parameters */
|
||||
static int dont_scale_voltage;
|
||||
|
||||
static int scale_voltage;
|
||||
static int ignore_latency;
|
||||
|
||||
#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
|
||||
|
||||
|
@ -71,7 +80,6 @@ static int dont_scale_voltage;
|
|||
/* Clock ratios multiplied by 10 */
|
||||
static int clock_ratio[32];
|
||||
static int eblcr_table[32];
|
||||
static int voltage_table[32];
|
||||
static unsigned int highest_speed, lowest_speed; /* kHz */
|
||||
static int longhaul_version;
|
||||
static struct cpufreq_frequency_table *longhaul_table;
|
||||
|
@ -124,10 +132,9 @@ static int longhaul_get_cpu_mult(void)
|
|||
|
||||
/* For processor with BCR2 MSR */
|
||||
|
||||
static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
|
||||
static void do_longhaul1(unsigned int clock_ratio_index)
|
||||
{
|
||||
union msr_bcr2 bcr2;
|
||||
u32 t;
|
||||
|
||||
rdmsrl(MSR_VIA_BCR2, bcr2.val);
|
||||
/* Enable software clock multiplier */
|
||||
|
@ -136,13 +143,11 @@ static void do_longhaul1(int cx_address, unsigned int clock_ratio_index)
|
|||
|
||||
/* Sync to timer tick */
|
||||
safe_halt();
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
/* Change frequency on next halt or sleep */
|
||||
wrmsrl(MSR_VIA_BCR2, bcr2.val);
|
||||
/* Invoke C3 */
|
||||
inb(cx_address);
|
||||
/* Dummy op - must do something useless after P_LVL3 read */
|
||||
t = inl(acpi_fadt.xpm_tmr_blk.address);
|
||||
/* Invoke transition */
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
halt();
|
||||
|
||||
/* Disable software clock multiplier */
|
||||
local_irq_disable();
|
||||
|
@ -164,11 +169,16 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
|
|||
longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
|
||||
longhaul.bits.EnableSoftBusRatio = 1;
|
||||
|
||||
if (can_scale_voltage) {
|
||||
longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
|
||||
longhaul.bits.EnableSoftVID = 1;
|
||||
}
|
||||
|
||||
/* Sync to timer tick */
|
||||
safe_halt();
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
/* Change frequency on next halt or sleep */
|
||||
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
|
||||
ACPI_FLUSH_CPU_CACHE();
|
||||
/* Invoke C3 */
|
||||
inb(cx_address);
|
||||
/* Dummy op - must do something useless after P_LVL3 read */
|
||||
|
@ -227,10 +237,13 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
|||
outb(0xFF,0xA1); /* Overkill */
|
||||
outb(0xFE,0x21); /* TMR0 only */
|
||||
|
||||
/* Disable bus master arbitration */
|
||||
if (pr->flags.bm_check) {
|
||||
if (pr->flags.bm_control) {
|
||||
/* Disable bus master arbitration */
|
||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
|
||||
ACPI_MTX_DO_NOT_LOCK);
|
||||
} else if (port22_en) {
|
||||
/* Disable AGP and PCI arbiters */
|
||||
outb(3, 0x22);
|
||||
}
|
||||
|
||||
switch (longhaul_version) {
|
||||
|
@ -244,7 +257,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
|||
*/
|
||||
case TYPE_LONGHAUL_V1:
|
||||
case TYPE_LONGHAUL_V2:
|
||||
do_longhaul1(cx->address, clock_ratio_index);
|
||||
do_longhaul1(clock_ratio_index);
|
||||
break;
|
||||
|
||||
/*
|
||||
|
@ -259,14 +272,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
|
|||
* to work in practice.
|
||||
*/
|
||||
case TYPE_POWERSAVER:
|
||||
/* Don't allow wakeup */
|
||||
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
|
||||
ACPI_MTX_DO_NOT_LOCK);
|
||||
do_powersaver(cx->address, clock_ratio_index);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable bus master arbitration */
|
||||
if (pr->flags.bm_check) {
|
||||
if (pr->flags.bm_control) {
|
||||
/* Enable bus master arbitration */
|
||||
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
|
||||
ACPI_MTX_DO_NOT_LOCK);
|
||||
} else if (port22_en) {
|
||||
/* Enable arbiters */
|
||||
outb(0, 0x22);
|
||||
}
|
||||
|
||||
outb(pic2_mask,0xA1); /* restore mask */
|
||||
|
@ -446,53 +465,57 @@ static int __init longhaul_get_ranges(void)
|
|||
static void __init longhaul_setup_voltagescaling(void)
|
||||
{
|
||||
union msr_longhaul longhaul;
|
||||
struct mV_pos minvid, maxvid;
|
||||
unsigned int j, speed, pos, kHz_step, numvscales;
|
||||
|
||||
rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
|
||||
|
||||
if (!(longhaul.bits.RevisionID & 1))
|
||||
rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
|
||||
if (!(longhaul.bits.RevisionID & 1)) {
|
||||
printk(KERN_INFO PFX "Voltage scaling not supported by CPU.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
minvid = longhaul.bits.MinimumVID;
|
||||
maxvid = longhaul.bits.MaximumVID;
|
||||
vrmrev = longhaul.bits.VRMRev;
|
||||
if (!longhaul.bits.VRMRev) {
|
||||
printk (KERN_INFO PFX "VRM 8.5\n");
|
||||
vrm_mV_table = &vrm85_mV[0];
|
||||
mV_vrm_table = &mV_vrm85[0];
|
||||
} else {
|
||||
printk (KERN_INFO PFX "Mobile VRM\n");
|
||||
vrm_mV_table = &mobilevrm_mV[0];
|
||||
mV_vrm_table = &mV_mobilevrm[0];
|
||||
}
|
||||
|
||||
if (minvid == 0 || maxvid == 0) {
|
||||
minvid = vrm_mV_table[longhaul.bits.MinimumVID];
|
||||
maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
|
||||
numvscales = maxvid.pos - minvid.pos + 1;
|
||||
kHz_step = (highest_speed - lowest_speed) / numvscales;
|
||||
|
||||
if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
|
||||
printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
|
||||
"Voltage scaling disabled.\n",
|
||||
minvid/1000, minvid%1000, maxvid/1000, maxvid%1000);
|
||||
minvid.mV/1000, minvid.mV%1000, maxvid.mV/1000, maxvid.mV%1000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (minvid == maxvid) {
|
||||
if (minvid.mV == maxvid.mV) {
|
||||
printk (KERN_INFO PFX "Claims to support voltage scaling but min & max are "
|
||||
"both %d.%03d. Voltage scaling disabled\n",
|
||||
maxvid/1000, maxvid%1000);
|
||||
maxvid.mV/1000, maxvid.mV%1000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vrmrev==0) {
|
||||
dprintk ("VRM 8.5\n");
|
||||
memcpy (voltage_table, vrm85scales, sizeof(voltage_table));
|
||||
numvscales = (voltage_table[maxvid]-voltage_table[minvid])/25;
|
||||
} else {
|
||||
dprintk ("Mobile VRM\n");
|
||||
memcpy (voltage_table, mobilevrmscales, sizeof(voltage_table));
|
||||
numvscales = (voltage_table[maxvid]-voltage_table[minvid])/5;
|
||||
printk(KERN_INFO PFX "Max VID=%d.%03d Min VID=%d.%03d, %d possible voltage scales\n",
|
||||
maxvid.mV/1000, maxvid.mV%1000,
|
||||
minvid.mV/1000, minvid.mV%1000,
|
||||
numvscales);
|
||||
|
||||
j = 0;
|
||||
while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
|
||||
speed = longhaul_table[j].frequency;
|
||||
pos = (speed - lowest_speed) / kHz_step + minvid.pos;
|
||||
f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
|
||||
j++;
|
||||
}
|
||||
|
||||
/* Current voltage isn't readable at first, so we need to
|
||||
set it to a known value. The spec says to use maxvid */
|
||||
longhaul.bits.RevisionKey = longhaul.bits.RevisionID; /* FIXME: This is bad. */
|
||||
longhaul.bits.EnableSoftVID = 1;
|
||||
longhaul.bits.SoftVID = maxvid;
|
||||
wrmsrl (MSR_VIA_LONGHAUL, longhaul.val);
|
||||
|
||||
minvid = voltage_table[minvid];
|
||||
maxvid = voltage_table[maxvid];
|
||||
|
||||
dprintk ("Min VID=%d.%03d Max VID=%d.%03d, %d possible voltage scales\n",
|
||||
maxvid/1000, maxvid%1000, minvid/1000, minvid%1000, numvscales);
|
||||
|
||||
can_scale_voltage = 1;
|
||||
}
|
||||
|
||||
|
@ -540,21 +563,33 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* VIA don't support PM2 reg, but have something similar */
|
||||
static int enable_arbiter_disable(void)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
u8 pci_cmd;
|
||||
|
||||
/* Find PLE133 host bridge */
|
||||
dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, NULL);
|
||||
if (dev != NULL) {
|
||||
/* Enable access to port 0x22 */
|
||||
pci_read_config_byte(dev, 0x78, &pci_cmd);
|
||||
if ( !(pci_cmd & 1<<7) ) {
|
||||
pci_cmd |= 1<<7;
|
||||
pci_write_config_byte(dev, 0x78, pci_cmd);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpuinfo_x86 *c = cpu_data;
|
||||
char *cpuname=NULL;
|
||||
int ret;
|
||||
|
||||
/* Check ACPI support for C3 state */
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
||||
&longhaul_walk_callback, NULL, (void *)&pr);
|
||||
if (pr == NULL) goto err_acpi;
|
||||
|
||||
cx = &pr->power.states[ACPI_STATE_C3];
|
||||
if (cx->address == 0 || cx->latency > 1000) goto err_acpi;
|
||||
|
||||
/* Now check what we have on this motherboard */
|
||||
/* Check what we have on this motherboard */
|
||||
switch (c->x86_model) {
|
||||
case 6:
|
||||
cpu_model = CPU_SAMUEL;
|
||||
|
@ -636,12 +671,36 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
|
|||
break;
|
||||
};
|
||||
|
||||
/* Find ACPI data for processor */
|
||||
acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
|
||||
&longhaul_walk_callback, NULL, (void *)&pr);
|
||||
if (pr == NULL)
|
||||
goto err_acpi;
|
||||
|
||||
if (longhaul_version == TYPE_POWERSAVER) {
|
||||
/* Check ACPI support for C3 state */
|
||||
cx = &pr->power.states[ACPI_STATE_C3];
|
||||
if (cx->address == 0 ||
|
||||
(cx->latency > 1000 && ignore_latency == 0) )
|
||||
goto err_acpi;
|
||||
|
||||
} else {
|
||||
/* Check ACPI support for bus master arbiter disable */
|
||||
if (!pr->flags.bm_control) {
|
||||
if (!enable_arbiter_disable()) {
|
||||
printk(KERN_ERR PFX "No ACPI support. No VT8601 host bridge. Aborting.\n");
|
||||
return -ENODEV;
|
||||
} else
|
||||
port22_en = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = longhaul_get_ranges();
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
|
||||
(dont_scale_voltage==0))
|
||||
(scale_voltage != 0))
|
||||
longhaul_setup_voltagescaling();
|
||||
|
||||
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
|
||||
|
@ -729,8 +788,10 @@ static void __exit longhaul_exit(void)
|
|||
kfree(longhaul_table);
|
||||
}
|
||||
|
||||
module_param (dont_scale_voltage, int, 0644);
|
||||
MODULE_PARM_DESC(dont_scale_voltage, "Don't scale voltage of processor");
|
||||
module_param (scale_voltage, int, 0644);
|
||||
MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
|
||||
module_param(ignore_latency, int, 0644);
|
||||
MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
|
||||
|
||||
MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
|
||||
MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");
|
||||
|
@ -738,4 +799,3 @@ MODULE_LICENSE ("GPL");
|
|||
|
||||
late_initcall(longhaul_init);
|
||||
module_exit(longhaul_exit);
|
||||
|
||||
|
|
|
@ -450,17 +450,45 @@ static int __initdata nehemiah_c_eblcr[32] = {
|
|||
* Voltage scales. Div/Mod by 1000 to get actual voltage.
|
||||
* Which scale to use depends on the VRM type in use.
|
||||
*/
|
||||
static int __initdata vrm85scales[32] = {
|
||||
1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700,
|
||||
1650, 1600, 1550, 1500, 1450, 1400, 1350, 1300,
|
||||
1275, 1225, 1175, 1125, 1075, 1825, 1775, 1725,
|
||||
1675, 1625, 1575, 1525, 1475, 1425, 1375, 1325,
|
||||
|
||||
struct mV_pos {
|
||||
unsigned short mV;
|
||||
unsigned short pos;
|
||||
};
|
||||
|
||||
static int __initdata mobilevrmscales[32] = {
|
||||
2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
|
||||
1600, 1550, 1500, 1450, 1500, 1350, 1300, -1,
|
||||
1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
|
||||
1075, 1050, 1025, 1000, 975, 950, 925, -1,
|
||||
static struct mV_pos __initdata vrm85_mV[32] = {
|
||||
{1250, 8}, {1200, 6}, {1150, 4}, {1100, 2},
|
||||
{1050, 0}, {1800, 30}, {1750, 28}, {1700, 26},
|
||||
{1650, 24}, {1600, 22}, {1550, 20}, {1500, 18},
|
||||
{1450, 16}, {1400, 14}, {1350, 12}, {1300, 10},
|
||||
{1275, 9}, {1225, 7}, {1175, 5}, {1125, 3},
|
||||
{1075, 1}, {1825, 31}, {1775, 29}, {1725, 27},
|
||||
{1675, 25}, {1625, 23}, {1575, 21}, {1525, 19},
|
||||
{1475, 17}, {1425, 15}, {1375, 13}, {1325, 11}
|
||||
};
|
||||
|
||||
static unsigned char __initdata mV_vrm85[32] = {
|
||||
0x04, 0x14, 0x03, 0x13, 0x02, 0x12, 0x01, 0x11,
|
||||
0x00, 0x10, 0x0f, 0x1f, 0x0e, 0x1e, 0x0d, 0x1d,
|
||||
0x0c, 0x1c, 0x0b, 0x1b, 0x0a, 0x1a, 0x09, 0x19,
|
||||
0x08, 0x18, 0x07, 0x17, 0x06, 0x16, 0x05, 0x15
|
||||
};
|
||||
|
||||
static struct mV_pos __initdata mobilevrm_mV[32] = {
|
||||
{1750, 31}, {1700, 30}, {1650, 29}, {1600, 28},
|
||||
{1550, 27}, {1500, 26}, {1450, 25}, {1400, 24},
|
||||
{1350, 23}, {1300, 22}, {1250, 21}, {1200, 20},
|
||||
{1150, 19}, {1100, 18}, {1050, 17}, {1000, 16},
|
||||
{975, 15}, {950, 14}, {925, 13}, {900, 12},
|
||||
{875, 11}, {850, 10}, {825, 9}, {800, 8},
|
||||
{775, 7}, {750, 6}, {725, 5}, {700, 4},
|
||||
{675, 3}, {650, 2}, {625, 1}, {600, 0}
|
||||
};
|
||||
|
||||
static unsigned char __initdata mV_mobilevrm[32] = {
|
||||
0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
|
||||
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
|
||||
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
|
||||
};
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <acpi/processor.h>
|
||||
#endif
|
||||
|
||||
|
@ -377,6 +378,35 @@ static int centrino_cpu_early_init_acpi(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Some BIOSes do SW_ANY coordination internally, either set it up in hw
|
||||
* or do it in BIOS firmware and won't inform about it to OS. If not
|
||||
* detected, this has a side effect of making CPU run at a different speed
|
||||
* than OS intended it to run at. Detect it and handle it cleanly.
|
||||
*/
|
||||
static int bios_with_sw_any_bug;
|
||||
static int __init sw_any_bug_found(struct dmi_system_id *d)
|
||||
{
|
||||
bios_with_sw_any_bug = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct dmi_system_id sw_any_bug_dmi_table[] = {
|
||||
{
|
||||
.callback = sw_any_bug_found,
|
||||
.ident = "Supermicro Server X6DLP",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
|
||||
DMI_MATCH(DMI_BIOS_VERSION, "080010"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* centrino_cpu_init_acpi - register with ACPI P-States library
|
||||
*
|
||||
|
@ -398,14 +428,24 @@ static int centrino_cpu_init_acpi(struct cpufreq_policy *policy)
|
|||
dprintk(PFX "obtaining ACPI data failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
policy->shared_type = p->shared_type;
|
||||
/*
|
||||
* Will let policy->cpus know about dependency only when software
|
||||
* coordination is required.
|
||||
*/
|
||||
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL ||
|
||||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
|
||||
policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
|
||||
policy->cpus = p->shared_cpu_map;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
dmi_check_system(sw_any_bug_dmi_table);
|
||||
if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) {
|
||||
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
|
||||
policy->cpus = cpu_core_map[cpu];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* verify the acpi_data */
|
||||
if (p->state_count <= 1) {
|
||||
|
|
|
@ -956,6 +956,38 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks if the entire range <start,end> is mapped with type.
|
||||
*
|
||||
* Note: this function only works correct if the e820 table is sorted and
|
||||
* not-overlapping, which is the case
|
||||
*/
|
||||
int __init
|
||||
e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
|
||||
{
|
||||
u64 start = s;
|
||||
u64 end = e;
|
||||
int i;
|
||||
for (i = 0; i < e820.nr_map; i++) {
|
||||
struct e820entry *ei = &e820.map[i];
|
||||
if (type && ei->type != type)
|
||||
continue;
|
||||
/* is the region (part) in overlap with the current region ?*/
|
||||
if (ei->addr >= end || ei->addr + ei->size <= start)
|
||||
continue;
|
||||
/* if the region is at the beginning of <start,end> we move
|
||||
* start to the end of the region since it's ok until there
|
||||
*/
|
||||
if (ei->addr <= start)
|
||||
start = ei->addr + ei->size;
|
||||
/* if start is now at or beyond end, we're done, full
|
||||
* coverage */
|
||||
if (start >= end)
|
||||
return 1; /* we're done */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the highest page frame number we have available
|
||||
*/
|
||||
|
|
|
@ -237,11 +237,6 @@ char * __devinit pcibios_setup(char *str)
|
|||
pci_probe &= ~PCI_PROBE_MMCONF;
|
||||
return NULL;
|
||||
}
|
||||
/* override DMI blacklist */
|
||||
else if (!strcmp(str, "mmconf")) {
|
||||
pci_probe |= PCI_PROBE_MMCONF_FORCE;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(str, "noacpi")) {
|
||||
acpi_noirq_set();
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <asm/e820.h>
|
||||
#include "pci.h"
|
||||
|
||||
|
@ -188,31 +187,9 @@ static __init void unreachable_devices(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int disable_mcfg(struct dmi_system_id *d)
|
||||
{
|
||||
printk("PCI: %s detected. Disabling MCFG.\n", d->ident);
|
||||
pci_probe &= ~PCI_PROBE_MMCONF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id __initdata dmi_bad_mcfg[] = {
|
||||
/* Has broken MCFG table that makes the system hang when used */
|
||||
{
|
||||
.callback = disable_mcfg,
|
||||
.ident = "Intel D3C5105 SDV",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BIOS_VENDOR, "Intel"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "D26928"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
void __init pci_mmcfg_init(void)
|
||||
{
|
||||
dmi_check_system(dmi_bad_mcfg);
|
||||
|
||||
if ((pci_probe & (PCI_PROBE_MMCONF_FORCE|PCI_PROBE_MMCONF)) == 0)
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
return;
|
||||
|
||||
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
|
||||
|
@ -221,6 +198,15 @@ void __init pci_mmcfg_init(void)
|
|||
(pci_mmcfg_config[0].base_address == 0))
|
||||
return;
|
||||
|
||||
if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
|
||||
pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
|
||||
E820_RESERVED)) {
|
||||
printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
|
||||
pci_mmcfg_config[0].base_address);
|
||||
printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PCI: Using MMCONFIG\n");
|
||||
raw_pci_ops = &pci_mmcfg;
|
||||
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
#define PCI_PROBE_CONF1 0x0002
|
||||
#define PCI_PROBE_CONF2 0x0004
|
||||
#define PCI_PROBE_MMCONF 0x0008
|
||||
#define PCI_PROBE_MMCONF_FORCE 0x0010
|
||||
#define PCI_PROBE_MASK 0x00ff
|
||||
#define PCI_PROBE_MASK 0x000f
|
||||
|
||||
#define PCI_NO_SORT 0x0100
|
||||
#define PCI_BIOS_SORT 0x0200
|
||||
|
|
|
@ -417,6 +417,17 @@ config PPC_MAPLE
|
|||
This option enables support for the Maple 970FX Evaluation Board.
|
||||
For more informations, refer to <http://www.970eval.com>
|
||||
|
||||
config PPC_PASEMI
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
bool "PA Semi SoC-based platforms"
|
||||
default n
|
||||
select MPIC
|
||||
select PPC_UDBG_16550
|
||||
select GENERIC_TBSYNC
|
||||
help
|
||||
This option enables support for PA Semi's PWRficient line
|
||||
of SoC processors, including PA6T-1682M
|
||||
|
||||
config PPC_CELL
|
||||
bool
|
||||
default n
|
||||
|
@ -436,7 +447,8 @@ config PPC_IBM_CELL_BLADE
|
|||
select UDBG_RTAS_CONSOLE
|
||||
|
||||
config UDBG_RTAS_CONSOLE
|
||||
bool
|
||||
bool "RTAS based debug console"
|
||||
depends on PPC_RTAS
|
||||
default n
|
||||
|
||||
config XICS
|
||||
|
|
|
@ -18,6 +18,20 @@ config DEBUG_STACK_USAGE
|
|||
|
||||
This option will slow down process creation somewhat.
|
||||
|
||||
config HCALL_STATS
|
||||
bool "Hypervisor call instrumentation"
|
||||
depends on PPC_PSERIES && DEBUG_FS
|
||||
help
|
||||
Adds code to keep track of the number of hypervisor calls made and
|
||||
the amount of time spent in hypervisor callsr. Wall time spent in
|
||||
each call is always calculated, and if available CPU cycles spent
|
||||
are also calculated. A directory named hcall_inst is added at the
|
||||
root of the debugfs filesystem. Within the hcall_inst directory
|
||||
are files that contain CPU specific call statistics.
|
||||
|
||||
This option will add a small amount of overhead to all hypervisor
|
||||
calls.
|
||||
|
||||
config DEBUGGER
|
||||
bool "Enable debugger hooks"
|
||||
depends on DEBUG_KERNEL
|
||||
|
@ -74,6 +88,8 @@ config XMON
|
|||
very early during boot. 'xmon=on' will just enable the xmon
|
||||
debugger hooks. 'xmon=off' will disable the debugger hooks
|
||||
if CONFIG_XMON_DEFAULT is set.
|
||||
xmon will print a backtrace on the very first invocation.
|
||||
'xmon=nobt' will disable this autobacktrace.
|
||||
|
||||
config XMON_DEFAULT
|
||||
bool "Enable xmon by default"
|
||||
|
|
|
@ -36,11 +36,16 @@ zliblinuxheader := zlib.h zconf.h zutil.h
|
|||
$(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
|
||||
#$(addprefix $(obj)/,main.o): $(addprefix $(obj)/,zlib.h)
|
||||
|
||||
src-boot := crt0.S string.S prom.c stdio.c main.c div64.S
|
||||
src-boot-$(CONFIG_PPC_MULTIPLATFORM) := of.c
|
||||
src-boot := crt0.S string.S stdio.c main.c div64.S $(src-boot-y)
|
||||
src-boot += $(zlib)
|
||||
src-boot := $(addprefix $(obj)/, $(src-boot))
|
||||
obj-boot := $(addsuffix .o, $(basename $(src-boot)))
|
||||
|
||||
ifeq ($(call cc-option-yn, -fstack-protector),y)
|
||||
BOOTCFLAGS += -fno-stack-protector
|
||||
endif
|
||||
|
||||
BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
|
||||
|
||||
quiet_cmd_copy_zlib = COPY $@
|
||||
|
|
|
@ -214,10 +214,10 @@
|
|||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
b000 0 0 1 700 15 8
|
||||
b000 0 0 2 700 16 8
|
||||
b000 0 0 3 700 17 8
|
||||
b000 0 0 4 700 14 8>;
|
||||
c000 0 0 1 700 15 8
|
||||
c000 0 0 2 700 16 8
|
||||
c000 0 0 3 700 17 8
|
||||
c000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
|
@ -274,10 +274,10 @@
|
|||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
b000 0 0 1 700 15 8
|
||||
b000 0 0 2 700 16 8
|
||||
b000 0 0 3 700 17 8
|
||||
b000 0 0 4 700 14 8>;
|
||||
c000 0 0 1 700 15 8
|
||||
c000 0 0 2 700 16 8
|
||||
c000 0 0 3 700 17 8
|
||||
c000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLATDEVTREE_H
|
||||
#define FLATDEVTREE_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/* Definitions used by the flattened device tree */
|
||||
#define OF_DT_HEADER 0xd00dfeed /* marker */
|
||||
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
|
||||
#define OF_DT_END_NODE 0x2 /* End node */
|
||||
#define OF_DT_PROP 0x3 /* Property: name off, size, content */
|
||||
#define OF_DT_NOP 0x4 /* nop */
|
||||
#define OF_DT_END 0x9
|
||||
|
||||
#define OF_DT_VERSION 0x10
|
||||
|
||||
struct boot_param_header {
|
||||
u32 magic; /* magic word OF_DT_HEADER */
|
||||
u32 totalsize; /* total size of DT block */
|
||||
u32 off_dt_struct; /* offset to structure */
|
||||
u32 off_dt_strings; /* offset to strings */
|
||||
u32 off_mem_rsvmap; /* offset to memory reserve map */
|
||||
u32 version; /* format version */
|
||||
u32 last_comp_version; /* last compatible version */
|
||||
/* version 2 fields below */
|
||||
u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
|
||||
/* version 3 fields below */
|
||||
u32 dt_strings_size; /* size of the DT strings block */
|
||||
};
|
||||
|
||||
#endif /* FLATDEVTREE_H */
|
|
@ -14,17 +14,12 @@
|
|||
#include "page.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "prom.h"
|
||||
#include "zlib.h"
|
||||
#include "ops.h"
|
||||
#include "flatdevtree.h"
|
||||
|
||||
extern void flush_cache(void *, unsigned long);
|
||||
|
||||
|
||||
/* Value picked to match that used by yaboot */
|
||||
#define PROG_START 0x01400000 /* only used on 64-bit systems */
|
||||
#define RAM_END (512<<20) /* Fixme: use OF */
|
||||
#define ONE_MB 0x100000
|
||||
|
||||
extern char _start[];
|
||||
extern char __bss_start[];
|
||||
extern char _end[];
|
||||
|
@ -33,14 +28,6 @@ extern char _vmlinux_end[];
|
|||
extern char _initrd_start[];
|
||||
extern char _initrd_end[];
|
||||
|
||||
/* A buffer that may be edited by tools operating on a zImage binary so as to
|
||||
* edit the command line passed to vmlinux (by setting /chosen/bootargs).
|
||||
* The buffer is put in it's own section so that tools may locate it easier.
|
||||
*/
|
||||
static char builtin_cmdline[512]
|
||||
__attribute__((section("__builtin_cmdline")));
|
||||
|
||||
|
||||
struct addr_range {
|
||||
unsigned long addr;
|
||||
unsigned long size;
|
||||
|
@ -51,21 +38,16 @@ static struct addr_range vmlinuz;
|
|||
static struct addr_range initrd;
|
||||
|
||||
static unsigned long elfoffset;
|
||||
static int is_64bit;
|
||||
|
||||
static char scratch[46912]; /* scratch space for gunzip, from zlib_inflate_workspacesize() */
|
||||
/* scratch space for gunzip; 46912 is from zlib_inflate_workspacesize() */
|
||||
static char scratch[46912];
|
||||
static char elfheader[256];
|
||||
|
||||
|
||||
typedef void (*kernel_entry_t)( unsigned long,
|
||||
unsigned long,
|
||||
void *,
|
||||
void *);
|
||||
|
||||
typedef void (*kernel_entry_t)(unsigned long, unsigned long, void *);
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
static unsigned long claim_base;
|
||||
|
||||
#define HEAD_CRC 2
|
||||
#define EXTRA_FIELD 4
|
||||
#define ORIG_NAME 8
|
||||
|
@ -123,24 +105,6 @@ static void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
|
|||
zlib_inflateEnd(&s);
|
||||
}
|
||||
|
||||
static unsigned long try_claim(unsigned long size)
|
||||
{
|
||||
unsigned long addr = 0;
|
||||
|
||||
for(; claim_base < RAM_END; claim_base += ONE_MB) {
|
||||
#ifdef DEBUG
|
||||
printf(" trying: 0x%08lx\n\r", claim_base);
|
||||
#endif
|
||||
addr = (unsigned long)claim(claim_base, size, 0);
|
||||
if ((void *)addr != (void *)-1)
|
||||
break;
|
||||
}
|
||||
if (addr == 0)
|
||||
return 0;
|
||||
claim_base = PAGE_ALIGN(claim_base + size);
|
||||
return addr;
|
||||
}
|
||||
|
||||
static int is_elf64(void *hdr)
|
||||
{
|
||||
Elf64_Ehdr *elf64 = hdr;
|
||||
|
@ -169,16 +133,7 @@ static int is_elf64(void *hdr)
|
|||
vmlinux.size = (unsigned long)elf64ph->p_filesz + elfoffset;
|
||||
vmlinux.memsize = (unsigned long)elf64ph->p_memsz + elfoffset;
|
||||
|
||||
#if defined(PROG_START)
|
||||
/*
|
||||
* Maintain a "magic" minimum address. This keeps some older
|
||||
* firmware platforms running.
|
||||
*/
|
||||
|
||||
if (claim_base < PROG_START)
|
||||
claim_base = PROG_START;
|
||||
#endif
|
||||
|
||||
is_64bit = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -212,47 +167,9 @@ static int is_elf32(void *hdr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void export_cmdline(void* chosen_handle)
|
||||
{
|
||||
int len;
|
||||
char cmdline[2] = { 0, 0 };
|
||||
|
||||
if (builtin_cmdline[0] == 0)
|
||||
return;
|
||||
|
||||
len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
|
||||
if (len > 0 && cmdline[0] != 0)
|
||||
return;
|
||||
|
||||
setprop(chosen_handle, "bootargs", builtin_cmdline,
|
||||
strlen(builtin_cmdline) + 1);
|
||||
}
|
||||
|
||||
|
||||
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
|
||||
static void prep_kernel(unsigned long *a1, unsigned long *a2)
|
||||
{
|
||||
int len;
|
||||
kernel_entry_t kernel_entry;
|
||||
|
||||
memset(__bss_start, 0, _end - __bss_start);
|
||||
|
||||
prom = (int (*)(void *)) promptr;
|
||||
chosen_handle = finddevice("/chosen");
|
||||
if (chosen_handle == (void *) -1)
|
||||
exit();
|
||||
if (getprop(chosen_handle, "stdout", &stdout, sizeof(stdout)) != 4)
|
||||
exit();
|
||||
|
||||
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r", _start, sp);
|
||||
|
||||
/*
|
||||
* The first available claim_base must be above the end of the
|
||||
* the loaded kernel wrapper file (_start to _end includes the
|
||||
* initrd image if it is present) and rounded up to a nice
|
||||
* 1 MB boundary for good measure.
|
||||
*/
|
||||
|
||||
claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
|
||||
|
||||
vmlinuz.addr = (unsigned long)_vmlinux_start;
|
||||
vmlinuz.size = (unsigned long)(_vmlinux_end - _vmlinux_start);
|
||||
|
@ -263,43 +180,51 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
|
|||
gunzip(elfheader, sizeof(elfheader),
|
||||
(unsigned char *)vmlinuz.addr, &len);
|
||||
} else
|
||||
memcpy(elfheader, (const void *)vmlinuz.addr, sizeof(elfheader));
|
||||
memcpy(elfheader, (const void *)vmlinuz.addr,
|
||||
sizeof(elfheader));
|
||||
|
||||
if (!is_elf64(elfheader) && !is_elf32(elfheader)) {
|
||||
printf("Error: not a valid PPC32 or PPC64 ELF file!\n\r");
|
||||
exit();
|
||||
}
|
||||
if (platform_ops.image_hdr)
|
||||
platform_ops.image_hdr(elfheader);
|
||||
|
||||
/* We need to claim the memsize plus the file offset since gzip
|
||||
/* We need to alloc the memsize plus the file offset since gzip
|
||||
* will expand the header (file offset), then the kernel, then
|
||||
* possible rubbish we don't care about. But the kernel bss must
|
||||
* be claimed (it will be zero'd by the kernel itself)
|
||||
*/
|
||||
printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux.memsize);
|
||||
vmlinux.addr = try_claim(vmlinux.memsize);
|
||||
vmlinux.addr = (unsigned long)malloc(vmlinux.memsize);
|
||||
if (vmlinux.addr == 0) {
|
||||
printf("Can't allocate memory for kernel image !\n\r");
|
||||
exit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we try to claim memory for the initrd (and copy it there)
|
||||
* Now we try to alloc memory for the initrd (and copy it there)
|
||||
*/
|
||||
initrd.size = (unsigned long)(_initrd_end - _initrd_start);
|
||||
initrd.memsize = initrd.size;
|
||||
if ( initrd.size > 0 ) {
|
||||
printf("Allocating 0x%lx bytes for initrd ...\n\r", initrd.size);
|
||||
initrd.addr = try_claim(initrd.size);
|
||||
printf("Allocating 0x%lx bytes for initrd ...\n\r",
|
||||
initrd.size);
|
||||
initrd.addr = (unsigned long)malloc((u32)initrd.size);
|
||||
if (initrd.addr == 0) {
|
||||
printf("Can't allocate memory for initial ramdisk !\n\r");
|
||||
printf("Can't allocate memory for initial "
|
||||
"ramdisk !\n\r");
|
||||
exit();
|
||||
}
|
||||
a1 = initrd.addr;
|
||||
a2 = initrd.size;
|
||||
printf("initial ramdisk moving 0x%lx <- 0x%lx (0x%lx bytes)\n\r",
|
||||
initrd.addr, (unsigned long)_initrd_start, initrd.size);
|
||||
memmove((void *)initrd.addr, (void *)_initrd_start, initrd.size);
|
||||
printf("initrd head: 0x%lx\n\r", *((unsigned long *)initrd.addr));
|
||||
*a1 = initrd.addr;
|
||||
*a2 = initrd.size;
|
||||
printf("initial ramdisk moving 0x%lx <- 0x%lx "
|
||||
"(0x%lx bytes)\n\r", initrd.addr,
|
||||
(unsigned long)_initrd_start, initrd.size);
|
||||
memmove((void *)initrd.addr, (void *)_initrd_start,
|
||||
initrd.size);
|
||||
printf("initrd head: 0x%lx\n\r",
|
||||
*((unsigned long *)initrd.addr));
|
||||
}
|
||||
|
||||
/* Eventually gunzip the kernel */
|
||||
|
@ -311,11 +236,10 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
|
|||
(unsigned char *)vmlinuz.addr, &len);
|
||||
printf("done 0x%lx bytes\n\r", len);
|
||||
} else {
|
||||
memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
|
||||
memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,
|
||||
vmlinuz.size);
|
||||
}
|
||||
|
||||
export_cmdline(chosen_handle);
|
||||
|
||||
/* Skip over the ELF header */
|
||||
#ifdef DEBUG
|
||||
printf("... skipping 0x%lx bytes of ELF header\n\r",
|
||||
|
@ -324,23 +248,107 @@ void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
|
|||
vmlinux.addr += elfoffset;
|
||||
|
||||
flush_cache((void *)vmlinux.addr, vmlinux.size);
|
||||
|
||||
kernel_entry = (kernel_entry_t)vmlinux.addr;
|
||||
#ifdef DEBUG
|
||||
printf( "kernel:\n\r"
|
||||
" entry addr = 0x%lx\n\r"
|
||||
" a1 = 0x%lx,\n\r"
|
||||
" a2 = 0x%lx,\n\r"
|
||||
" prom = 0x%lx,\n\r"
|
||||
" bi_recs = 0x%lx,\n\r",
|
||||
(unsigned long)kernel_entry, a1, a2,
|
||||
(unsigned long)prom, NULL);
|
||||
#endif
|
||||
|
||||
kernel_entry(a1, a2, prom, NULL);
|
||||
|
||||
printf("Error: Linux kernel returned to zImage bootloader!\n\r");
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
void __attribute__ ((weak)) ft_init(void *dt_blob)
|
||||
{
|
||||
}
|
||||
|
||||
/* A buffer that may be edited by tools operating on a zImage binary so as to
|
||||
* edit the command line passed to vmlinux (by setting /chosen/bootargs).
|
||||
* The buffer is put in it's own section so that tools may locate it easier.
|
||||
*/
|
||||
static char builtin_cmdline[COMMAND_LINE_SIZE]
|
||||
__attribute__((__section__("__builtin_cmdline")));
|
||||
|
||||
static void get_cmdline(char *buf, int size)
|
||||
{
|
||||
void *devp;
|
||||
int len = strlen(builtin_cmdline);
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
|
||||
len = min(len, size-1);
|
||||
strncpy(buf, builtin_cmdline, len);
|
||||
buf[len] = '\0';
|
||||
}
|
||||
else if ((devp = finddevice("/chosen")))
|
||||
getprop(devp, "bootargs", buf, size);
|
||||
}
|
||||
|
||||
static void set_cmdline(char *buf)
|
||||
{
|
||||
void *devp;
|
||||
|
||||
if ((devp = finddevice("/chosen")))
|
||||
setprop(devp, "bootargs", buf, strlen(buf) + 1);
|
||||
}
|
||||
|
||||
/* Section where ft can be tacked on after zImage is built */
|
||||
union blobspace {
|
||||
struct boot_param_header hdr;
|
||||
char space[8*1024];
|
||||
} dt_blob __attribute__((__section__("__builtin_ft")));
|
||||
|
||||
struct platform_ops platform_ops;
|
||||
struct dt_ops dt_ops;
|
||||
struct console_ops console_ops;
|
||||
|
||||
void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
|
||||
{
|
||||
int have_dt = 0;
|
||||
kernel_entry_t kentry;
|
||||
char cmdline[COMMAND_LINE_SIZE];
|
||||
|
||||
memset(__bss_start, 0, _end - __bss_start);
|
||||
memset(&platform_ops, 0, sizeof(platform_ops));
|
||||
memset(&dt_ops, 0, sizeof(dt_ops));
|
||||
memset(&console_ops, 0, sizeof(console_ops));
|
||||
|
||||
/* Override the dt_ops and device tree if there was an flat dev
|
||||
* tree attached to the zImage.
|
||||
*/
|
||||
if (dt_blob.hdr.magic == OF_DT_HEADER) {
|
||||
have_dt = 1;
|
||||
ft_init(&dt_blob);
|
||||
}
|
||||
|
||||
if (platform_init(promptr))
|
||||
exit();
|
||||
if (console_ops.open && (console_ops.open() < 0))
|
||||
exit();
|
||||
if (platform_ops.fixups)
|
||||
platform_ops.fixups();
|
||||
|
||||
printf("\n\rzImage starting: loaded at 0x%p (sp: 0x%p)\n\r",
|
||||
_start, sp);
|
||||
|
||||
prep_kernel(&a1, &a2);
|
||||
|
||||
/* If cmdline came from zimage wrapper or if we can edit the one
|
||||
* in the dt, print it out and edit it, if possible.
|
||||
*/
|
||||
if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
|
||||
get_cmdline(cmdline, COMMAND_LINE_SIZE);
|
||||
printf("\n\rLinux/PowerPC load: %s", cmdline);
|
||||
if (console_ops.edit_cmdline)
|
||||
console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
|
||||
printf("\n\r");
|
||||
set_cmdline(cmdline);
|
||||
}
|
||||
|
||||
if (console_ops.close)
|
||||
console_ops.close();
|
||||
|
||||
kentry = (kernel_entry_t) vmlinux.addr;
|
||||
if (have_dt)
|
||||
kentry(dt_ops.ft_addr(), 0, NULL);
|
||||
else
|
||||
/* XXX initrd addr/size should be passed in properties */
|
||||
kentry(a1, a2, promptr);
|
||||
|
||||
/* console closed so printf below may not work */
|
||||
printf("Error: Linux kernel returned to zImage boot wrapper!\n\r");
|
||||
exit();
|
||||
}
|
||||
|
|
|
@ -8,15 +8,29 @@
|
|||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "types.h"
|
||||
#include "elf.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "prom.h"
|
||||
#include "page.h"
|
||||
#include "ops.h"
|
||||
|
||||
int (*prom)(void *);
|
||||
phandle chosen_handle;
|
||||
ihandle stdout;
|
||||
typedef void *ihandle;
|
||||
typedef void *phandle;
|
||||
|
||||
int call_prom(const char *service, int nargs, int nret, ...)
|
||||
extern char _end[];
|
||||
|
||||
/* Value picked to match that used by yaboot */
|
||||
#define PROG_START 0x01400000 /* only used on 64-bit systems */
|
||||
#define RAM_END (512<<20) /* Fixme: use OF */
|
||||
#define ONE_MB 0x100000
|
||||
|
||||
int (*prom) (void *);
|
||||
|
||||
|
||||
static unsigned long claim_base;
|
||||
|
||||
static int call_prom(const char *service, int nargs, int nret, ...)
|
||||
{
|
||||
int i;
|
||||
struct prom_args {
|
||||
|
@ -45,7 +59,7 @@ int call_prom(const char *service, int nargs, int nret, ...)
|
|||
return (nret > 0)? args.args[nargs]: 0;
|
||||
}
|
||||
|
||||
int call_prom_ret(const char *service, int nargs, int nret,
|
||||
static int call_prom_ret(const char *service, int nargs, int nret,
|
||||
unsigned int *rets, ...)
|
||||
{
|
||||
int i;
|
||||
|
@ -79,11 +93,6 @@ int call_prom_ret(const char *service, int nargs, int nret,
|
|||
return (nret > 0)? args.args[nargs]: 0;
|
||||
}
|
||||
|
||||
int write(void *handle, void *ptr, int nb)
|
||||
{
|
||||
return call_prom("write", 3, 1, handle, ptr, nb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Older OF's require that when claiming a specific range of addresses,
|
||||
* we claim the physical space in the /memory node and the virtual
|
||||
|
@ -142,7 +151,7 @@ static int check_of_version(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void *claim(unsigned long virt, unsigned long size, unsigned long align)
|
||||
static void *claim(unsigned long virt, unsigned long size, unsigned long align)
|
||||
{
|
||||
int ret;
|
||||
unsigned int result;
|
||||
|
@ -163,3 +172,112 @@ void *claim(unsigned long virt, unsigned long size, unsigned long align)
|
|||
0x12, size, virt, virt);
|
||||
return (void *) virt;
|
||||
}
|
||||
|
||||
static void *of_try_claim(u32 size)
|
||||
{
|
||||
unsigned long addr = 0;
|
||||
static u8 first_time = 1;
|
||||
|
||||
if (first_time) {
|
||||
claim_base = _ALIGN_UP((unsigned long)_end, ONE_MB);
|
||||
first_time = 0;
|
||||
}
|
||||
|
||||
for(; claim_base < RAM_END; claim_base += ONE_MB) {
|
||||
#ifdef DEBUG
|
||||
printf(" trying: 0x%08lx\n\r", claim_base);
|
||||
#endif
|
||||
addr = (unsigned long)claim(claim_base, size, 0);
|
||||
if ((void *)addr != (void *)-1)
|
||||
break;
|
||||
}
|
||||
if (addr == 0)
|
||||
return NULL;
|
||||
claim_base = PAGE_ALIGN(claim_base + size);
|
||||
return (void *)addr;
|
||||
}
|
||||
|
||||
static void of_image_hdr(const void *hdr)
|
||||
{
|
||||
const Elf64_Ehdr *elf64 = hdr;
|
||||
|
||||
if (elf64->e_ident[EI_CLASS] == ELFCLASS64) {
|
||||
/*
|
||||
* Maintain a "magic" minimum address. This keeps some older
|
||||
* firmware platforms running.
|
||||
*/
|
||||
if (claim_base < PROG_START)
|
||||
claim_base = PROG_START;
|
||||
}
|
||||
}
|
||||
|
||||
static void of_exit(void)
|
||||
{
|
||||
call_prom("exit", 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* OF device tree routines
|
||||
*/
|
||||
static void *of_finddevice(const char *name)
|
||||
{
|
||||
return (phandle) call_prom("finddevice", 1, 1, name);
|
||||
}
|
||||
|
||||
static int of_getprop(const void *phandle, const char *name, void *buf,
|
||||
const int buflen)
|
||||
{
|
||||
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
|
||||
}
|
||||
|
||||
static int of_setprop(const void *phandle, const char *name, const void *buf,
|
||||
const int buflen)
|
||||
{
|
||||
return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
|
||||
}
|
||||
|
||||
/*
|
||||
* OF console routines
|
||||
*/
|
||||
static void *of_stdout_handle;
|
||||
|
||||
static int of_console_open(void)
|
||||
{
|
||||
void *devp;
|
||||
|
||||
if (((devp = finddevice("/chosen")) != NULL)
|
||||
&& (getprop(devp, "stdout", &of_stdout_handle,
|
||||
sizeof(of_stdout_handle))
|
||||
== sizeof(of_stdout_handle)))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void of_console_write(char *buf, int len)
|
||||
{
|
||||
call_prom("write", 3, 1, of_stdout_handle, buf, len);
|
||||
}
|
||||
|
||||
int platform_init(void *promptr)
|
||||
{
|
||||
platform_ops.fixups = NULL;
|
||||
platform_ops.image_hdr = of_image_hdr;
|
||||
platform_ops.malloc = of_try_claim;
|
||||
platform_ops.free = NULL;
|
||||
platform_ops.exit = of_exit;
|
||||
|
||||
dt_ops.finddevice = of_finddevice;
|
||||
dt_ops.getprop = of_getprop;
|
||||
dt_ops.setprop = of_setprop;
|
||||
dt_ops.translate_addr = NULL;
|
||||
|
||||
console_ops.open = of_console_open;
|
||||
console_ops.write = of_console_write;
|
||||
console_ops.edit_cmdline = NULL;
|
||||
console_ops.close = NULL;
|
||||
console_ops.data = NULL;
|
||||
|
||||
prom = (int (*)(void *))promptr;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Global definition of all the bootwrapper operations.
|
||||
*
|
||||
* Author: Mark A. Greer <mgreer@mvista.com>
|
||||
*
|
||||
* 2006 (c) MontaVista Software, Inc. This file is licensed under
|
||||
* the terms of the GNU General Public License version 2. This program
|
||||
* is licensed "as is" without any warranty of any kind, whether express
|
||||
* or implied.
|
||||
*/
|
||||
#ifndef _PPC_BOOT_OPS_H_
|
||||
#define _PPC_BOOT_OPS_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define COMMAND_LINE_SIZE 512
|
||||
#define MAX_PATH_LEN 256
|
||||
#define MAX_PROP_LEN 256 /* What should this be? */
|
||||
|
||||
/* Platform specific operations */
|
||||
struct platform_ops {
|
||||
void (*fixups)(void);
|
||||
void (*image_hdr)(const void *);
|
||||
void * (*malloc)(u32 size);
|
||||
void (*free)(void *ptr, u32 size);
|
||||
void (*exit)(void);
|
||||
};
|
||||
extern struct platform_ops platform_ops;
|
||||
|
||||
/* Device Tree operations */
|
||||
struct dt_ops {
|
||||
void * (*finddevice)(const char *name);
|
||||
int (*getprop)(const void *node, const char *name, void *buf,
|
||||
const int buflen);
|
||||
int (*setprop)(const void *node, const char *name,
|
||||
const void *buf, const int buflen);
|
||||
u64 (*translate_addr)(const char *path, const u32 *in_addr,
|
||||
const u32 addr_len);
|
||||
unsigned long (*ft_addr)(void);
|
||||
};
|
||||
extern struct dt_ops dt_ops;
|
||||
|
||||
/* Console operations */
|
||||
struct console_ops {
|
||||
int (*open)(void);
|
||||
void (*write)(char *buf, int len);
|
||||
void (*edit_cmdline)(char *buf, int len);
|
||||
void (*close)(void);
|
||||
void *data;
|
||||
};
|
||||
extern struct console_ops console_ops;
|
||||
|
||||
/* Serial console operations */
|
||||
struct serial_console_data {
|
||||
int (*open)(void);
|
||||
void (*putc)(unsigned char c);
|
||||
unsigned char (*getc)(void);
|
||||
u8 (*tstc)(void);
|
||||
void (*close)(void);
|
||||
};
|
||||
|
||||
extern int platform_init(void *promptr);
|
||||
extern void simple_alloc_init(void);
|
||||
extern void ft_init(void *dt_blob);
|
||||
extern int serial_console_init(void);
|
||||
|
||||
static inline void *finddevice(const char *name)
|
||||
{
|
||||
return (dt_ops.finddevice) ? dt_ops.finddevice(name) : NULL;
|
||||
}
|
||||
|
||||
static inline int getprop(void *devp, const char *name, void *buf, int buflen)
|
||||
{
|
||||
return (dt_ops.getprop) ? dt_ops.getprop(devp, name, buf, buflen) : -1;
|
||||
}
|
||||
|
||||
static inline int setprop(void *devp, const char *name, void *buf, int buflen)
|
||||
{
|
||||
return (dt_ops.setprop) ? dt_ops.setprop(devp, name, buf, buflen) : -1;
|
||||
}
|
||||
|
||||
static inline void *malloc(u32 size)
|
||||
{
|
||||
return (platform_ops.malloc) ? platform_ops.malloc(size) : NULL;
|
||||
}
|
||||
|
||||
static inline void free(void *ptr, u32 size)
|
||||
{
|
||||
if (platform_ops.free)
|
||||
platform_ops.free(ptr, size);
|
||||
}
|
||||
|
||||
static inline void exit(void)
|
||||
{
|
||||
if (platform_ops.exit)
|
||||
platform_ops.exit();
|
||||
for(;;);
|
||||
}
|
||||
|
||||
#endif /* _PPC_BOOT_OPS_H_ */
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef _PPC_BOOT_PROM_H_
|
||||
#define _PPC_BOOT_PROM_H_
|
||||
|
||||
typedef void *phandle;
|
||||
typedef void *ihandle;
|
||||
|
||||
extern int (*prom) (void *);
|
||||
extern phandle chosen_handle;
|
||||
extern ihandle stdout;
|
||||
|
||||
int call_prom(const char *service, int nargs, int nret, ...);
|
||||
int call_prom_ret(const char *service, int nargs, int nret,
|
||||
unsigned int *rets, ...);
|
||||
|
||||
extern int write(void *handle, void *ptr, int nb);
|
||||
extern void *claim(unsigned long virt, unsigned long size, unsigned long aln);
|
||||
|
||||
static inline void exit(void)
|
||||
{
|
||||
call_prom("exit", 0, 0);
|
||||
}
|
||||
|
||||
static inline phandle finddevice(const char *name)
|
||||
{
|
||||
return (phandle) call_prom("finddevice", 1, 1, name);
|
||||
}
|
||||
|
||||
static inline int getprop(void *phandle, const char *name,
|
||||
void *buf, int buflen)
|
||||
{
|
||||
return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
|
||||
}
|
||||
|
||||
|
||||
static inline int setprop(void *phandle, const char *name,
|
||||
void *buf, int buflen)
|
||||
{
|
||||
return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
|
||||
}
|
||||
|
||||
#endif /* _PPC_BOOT_PROM_H_ */
|
|
@ -10,7 +10,7 @@
|
|||
#include <stddef.h>
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "prom.h"
|
||||
#include "ops.h"
|
||||
|
||||
size_t strnlen(const char * s, size_t count)
|
||||
{
|
||||
|
@ -320,6 +320,6 @@ printf(const char *fmt, ...)
|
|||
va_start(args, fmt);
|
||||
n = vsprintf(sprint_buf, fmt, args);
|
||||
va_end(args);
|
||||
write(stdout, sprint_buf, n);
|
||||
console_ops.write(sprint_buf, n);
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
#ifndef _PPC_BOOT_STDIO_H_
|
||||
#define _PPC_BOOT_STDIO_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define ENOMEM 12 /* Out of Memory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
|
||||
extern int printf(const char *fmt, ...);
|
||||
|
||||
#define fprintf(fmt, args...) printf(args)
|
||||
|
||||
extern int sprintf(char *buf, const char *fmt, ...);
|
||||
|
||||
extern int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef _TYPES_H_
|
||||
#define _TYPES_H_
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
#define min(x,y) ({ \
|
||||
typeof(x) _x = (x); \
|
||||
typeof(y) _y = (y); \
|
||||
(void) (&_x == &_y); \
|
||||
_x < _y ? _x : _y; })
|
||||
|
||||
#define max(x,y) ({ \
|
||||
typeof(x) _x = (x); \
|
||||
typeof(y) _y = (y); \
|
||||
(void) (&_x == &_y); \
|
||||
_x > _y ? _x : _y; })
|
||||
|
||||
#endif /* _TYPES_H_ */
|
|
@ -496,7 +496,7 @@ CONFIG_E1000=y
|
|||
# CONFIG_SKY2 is not set
|
||||
# CONFIG_SK98LIN is not set
|
||||
# CONFIG_VIA_VELOCITY is not set
|
||||
# CONFIG_TIGON3 is not set
|
||||
CONFIG_TIGON3=y
|
||||
# CONFIG_BNX2 is not set
|
||||
# CONFIG_MV643XX_ETH is not set
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
|
|||
obj-y += vdso32/
|
||||
obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
|
||||
signal_64.o ptrace32.o \
|
||||
paca.o cpu_setup_power4.o \
|
||||
paca.o cpu_setup_ppc970.o \
|
||||
firmware.o sysfs.o
|
||||
obj-$(CONFIG_PPC64) += vdso64/
|
||||
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
|
||||
|
@ -51,7 +51,7 @@ extra-$(CONFIG_8xx) := head_8xx.o
|
|||
extra-y += vmlinux.lds
|
||||
|
||||
obj-y += time.o prom.o traps.o setup-common.o \
|
||||
udbg.o misc.o
|
||||
udbg.o misc.o io.o
|
||||
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o
|
||||
obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
|
||||
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o
|
||||
|
|
|
@ -40,9 +40,10 @@
|
|||
#ifdef CONFIG_PPC64
|
||||
#include <asm/paca.h>
|
||||
#include <asm/lppaca.h>
|
||||
#include <asm/iseries/hv_lp_event.h>
|
||||
#include <asm/cache.h>
|
||||
#include <asm/compat.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/hvcall.h>
|
||||
#endif
|
||||
|
||||
#define DEFINE(sym, val) \
|
||||
|
@ -136,11 +137,18 @@ int main(void)
|
|||
DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr));
|
||||
DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
|
||||
DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
|
||||
DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
|
||||
DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
|
||||
|
||||
DEFINE(SLBSHADOW_STACKVSID,
|
||||
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid));
|
||||
DEFINE(SLBSHADOW_STACKESID,
|
||||
offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid));
|
||||
DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
|
||||
DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
|
||||
DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int));
|
||||
DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int));
|
||||
DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area));
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/* RTAS */
|
||||
|
@ -159,6 +167,12 @@ int main(void)
|
|||
/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
|
||||
DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
|
||||
DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
|
||||
|
||||
/* hcall statistics */
|
||||
DEFINE(HCALL_STAT_SIZE, sizeof(struct hcall_stats));
|
||||
DEFINE(HCALL_STAT_CALLS, offsetof(struct hcall_stats, num_calls));
|
||||
DEFINE(HCALL_STAT_TB, offsetof(struct hcall_stats, tb_total));
|
||||
DEFINE(HCALL_STAT_PURR, offsetof(struct hcall_stats, purr_total));
|
||||
#endif /* CONFIG_PPC64 */
|
||||
DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
|
||||
DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
|
||||
|
@ -240,6 +254,7 @@ int main(void)
|
|||
DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
|
||||
DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
|
||||
DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
|
||||
DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
|
||||
|
||||
#ifndef CONFIG_PPC64
|
||||
DEFINE(pbe_address, offsetof(struct pbe, address));
|
||||
|
|
|
@ -158,35 +158,35 @@ int btext_initialize(struct device_node *np)
|
|||
{
|
||||
unsigned int width, height, depth, pitch;
|
||||
unsigned long address = 0;
|
||||
u32 *prop;
|
||||
const u32 *prop;
|
||||
|
||||
prop = (u32 *)get_property(np, "linux,bootx-width", NULL);
|
||||
prop = get_property(np, "linux,bootx-width", NULL);
|
||||
if (prop == NULL)
|
||||
prop = (u32 *)get_property(np, "width", NULL);
|
||||
prop = get_property(np, "width", NULL);
|
||||
if (prop == NULL)
|
||||
return -EINVAL;
|
||||
width = *prop;
|
||||
prop = (u32 *)get_property(np, "linux,bootx-height", NULL);
|
||||
prop = get_property(np, "linux,bootx-height", NULL);
|
||||
if (prop == NULL)
|
||||
prop = (u32 *)get_property(np, "height", NULL);
|
||||
prop = get_property(np, "height", NULL);
|
||||
if (prop == NULL)
|
||||
return -EINVAL;
|
||||
height = *prop;
|
||||
prop = (u32 *)get_property(np, "linux,bootx-depth", NULL);
|
||||
prop = get_property(np, "linux,bootx-depth", NULL);
|
||||
if (prop == NULL)
|
||||
prop = (u32 *)get_property(np, "depth", NULL);
|
||||
prop = get_property(np, "depth", NULL);
|
||||
if (prop == NULL)
|
||||
return -EINVAL;
|
||||
depth = *prop;
|
||||
pitch = width * ((depth + 7) / 8);
|
||||
prop = (u32 *)get_property(np, "linux,bootx-linebytes", NULL);
|
||||
prop = get_property(np, "linux,bootx-linebytes", NULL);
|
||||
if (prop == NULL)
|
||||
prop = (u32 *)get_property(np, "linebytes", NULL);
|
||||
prop = get_property(np, "linebytes", NULL);
|
||||
if (prop)
|
||||
pitch = *prop;
|
||||
if (pitch == 1)
|
||||
pitch = 0x1000;
|
||||
prop = (u32 *)get_property(np, "address", NULL);
|
||||
prop = get_property(np, "address", NULL);
|
||||
if (prop)
|
||||
address = *prop;
|
||||
|
||||
|
@ -214,11 +214,11 @@ int btext_initialize(struct device_node *np)
|
|||
|
||||
int __init btext_find_display(int allow_nonstdout)
|
||||
{
|
||||
char *name;
|
||||
const char *name;
|
||||
struct device_node *np = NULL;
|
||||
int rc = -ENODEV;
|
||||
|
||||
name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
name = get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
if (name != NULL) {
|
||||
np = of_find_node_by_path(name);
|
||||
if (np != NULL) {
|
||||
|
|
|
@ -16,27 +16,12 @@
|
|||
#include <asm/asm-offsets.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
_GLOBAL(__970_cpu_preinit)
|
||||
/*
|
||||
* Do nothing if not running in HV mode
|
||||
*/
|
||||
_GLOBAL(__cpu_preinit_ppc970)
|
||||
/* Do nothing if not running in HV mode */
|
||||
mfmsr r0
|
||||
rldicl. r0,r0,4,63
|
||||
beqlr
|
||||
|
||||
/*
|
||||
* Deal only with PPC970 and PPC970FX.
|
||||
*/
|
||||
mfspr r0,SPRN_PVR
|
||||
srwi r0,r0,16
|
||||
cmpwi r0,0x39
|
||||
beq 1f
|
||||
cmpwi r0,0x3c
|
||||
beq 1f
|
||||
cmpwi r0,0x44
|
||||
bnelr
|
||||
1:
|
||||
|
||||
/* Make sure HID4:rm_ci is off before MMU is turned off, that large
|
||||
* pages are enabled with HID4:61 and clear HID5:DCBZ_size and
|
||||
* HID5:DCBZ32_ill
|
||||
|
@ -72,23 +57,6 @@ _GLOBAL(__970_cpu_preinit)
|
|||
isync
|
||||
blr
|
||||
|
||||
_GLOBAL(__setup_cpu_ppc970)
|
||||
mfspr r0,SPRN_HID0
|
||||
li r11,5 /* clear DOZE and SLEEP */
|
||||
rldimi r0,r11,52,8 /* set NAP and DPM */
|
||||
li r11,0
|
||||
rldimi r0,r11,32,31 /* clear EN_ATTN */
|
||||
mtspr SPRN_HID0,r0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
sync
|
||||
isync
|
||||
blr
|
||||
|
||||
/* Definitions for the table use to save CPU states */
|
||||
#define CS_HID0 0
|
||||
#define CS_HID1 8
|
||||
|
@ -103,33 +71,30 @@ cpu_state_storage:
|
|||
.balign L1_CACHE_BYTES,0
|
||||
.text
|
||||
|
||||
/* Called in normal context to backup CPU 0 state. This
|
||||
* does not include cache settings. This function is also
|
||||
* called for machine sleep. This does not include the MMU
|
||||
* setup, BATs, etc... but rather the "special" registers
|
||||
* like HID0, HID1, HID4, etc...
|
||||
*/
|
||||
_GLOBAL(__save_cpu_setup)
|
||||
/* Some CR fields are volatile, we back it up all */
|
||||
mfcr r7
|
||||
|
||||
/* Get storage ptr */
|
||||
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
||||
|
||||
/* We only deal with 970 for now */
|
||||
mfspr r0,SPRN_PVR
|
||||
srwi r0,r0,16
|
||||
cmpwi r0,0x39
|
||||
beq 1f
|
||||
cmpwi r0,0x3c
|
||||
beq 1f
|
||||
cmpwi r0,0x44
|
||||
bne 2f
|
||||
|
||||
1: /* skip if not running in HV mode */
|
||||
_GLOBAL(__setup_cpu_ppc970)
|
||||
/* Do nothing if not running in HV mode */
|
||||
mfmsr r0
|
||||
rldicl. r0,r0,4,63
|
||||
beq 2f
|
||||
beqlr
|
||||
|
||||
mfspr r0,SPRN_HID0
|
||||
li r11,5 /* clear DOZE and SLEEP */
|
||||
rldimi r0,r11,52,8 /* set NAP and DPM */
|
||||
li r11,0
|
||||
rldimi r0,r11,32,31 /* clear EN_ATTN */
|
||||
mtspr SPRN_HID0,r0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
mfspr r0,SPRN_HID0
|
||||
sync
|
||||
isync
|
||||
|
||||
/* Save away cpu state */
|
||||
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
||||
|
||||
/* Save HID0,1,4 and 5 */
|
||||
mfspr r3,SPRN_HID0
|
||||
|
@ -141,35 +106,19 @@ _GLOBAL(__save_cpu_setup)
|
|||
mfspr r3,SPRN_HID5
|
||||
std r3,CS_HID5(r5)
|
||||
|
||||
2:
|
||||
mtcr r7
|
||||
blr
|
||||
|
||||
/* Called with no MMU context (typically MSR:IR/DR off) to
|
||||
* restore CPU state as backed up by the previous
|
||||
* function. This does not include cache setting
|
||||
*/
|
||||
_GLOBAL(__restore_cpu_setup)
|
||||
/* Get storage ptr (FIXME when using anton reloc as we
|
||||
* are running with translation disabled here
|
||||
*/
|
||||
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
||||
|
||||
/* We only deal with 970 for now */
|
||||
mfspr r0,SPRN_PVR
|
||||
srwi r0,r0,16
|
||||
cmpwi r0,0x39
|
||||
beq 1f
|
||||
cmpwi r0,0x3c
|
||||
beq 1f
|
||||
cmpwi r0,0x44
|
||||
bnelr
|
||||
|
||||
1: /* skip if not running in HV mode */
|
||||
_GLOBAL(__restore_cpu_ppc970)
|
||||
/* Do nothing if not running in HV mode */
|
||||
mfmsr r0
|
||||
rldicl. r0,r0,4,63
|
||||
beqlr
|
||||
|
||||
LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
|
||||
/* Before accessing memory, we make sure rm_ci is clear */
|
||||
li r0,0
|
||||
mfspr r3,SPRN_HID4
|
|
@ -39,7 +39,10 @@ extern void __setup_cpu_7400(unsigned long offset, struct cpu_spec* spec);
|
|||
extern void __setup_cpu_7410(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec);
|
||||
#endif /* CONFIG_PPC32 */
|
||||
#ifdef CONFIG_PPC64
|
||||
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
|
||||
extern void __restore_cpu_ppc970(void);
|
||||
#endif /* CONFIG_PPC64 */
|
||||
|
||||
/* This table only contains "desktop" CPUs, it need to be filled with embedded
|
||||
* ones as well...
|
||||
|
@ -55,6 +58,9 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
|
|||
#define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
|
||||
PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
|
||||
PPC_FEATURE_TRUE_LE)
|
||||
#define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\
|
||||
PPC_FEATURE_TRUE_LE | \
|
||||
PPC_FEATURE_HAS_ALTIVEC_COMP)
|
||||
#define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
|
||||
PPC_FEATURE_BOOKE)
|
||||
|
||||
|
@ -184,6 +190,7 @@ struct cpu_spec cpu_specs[] = {
|
|||
.dcache_bsize = 128,
|
||||
.num_pmcs = 8,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970",
|
||||
.oprofile_type = PPC_OPROFILE_POWER4,
|
||||
.platform = "ppc970",
|
||||
|
@ -199,6 +206,7 @@ struct cpu_spec cpu_specs[] = {
|
|||
.dcache_bsize = 128,
|
||||
.num_pmcs = 8,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970",
|
||||
.oprofile_type = PPC_OPROFILE_POWER4,
|
||||
.platform = "ppc970",
|
||||
|
@ -214,6 +222,7 @@ struct cpu_spec cpu_specs[] = {
|
|||
.dcache_bsize = 128,
|
||||
.num_pmcs = 8,
|
||||
.cpu_setup = __setup_cpu_ppc970,
|
||||
.cpu_restore = __restore_cpu_ppc970,
|
||||
.oprofile_cpu_type = "ppc64/970",
|
||||
.oprofile_type = PPC_OPROFILE_POWER4,
|
||||
.platform = "ppc970",
|
||||
|
@ -280,6 +289,17 @@ struct cpu_spec cpu_specs[] = {
|
|||
.dcache_bsize = 128,
|
||||
.platform = "ppc-cell-be",
|
||||
},
|
||||
{ /* PA Semi PA6T */
|
||||
.pvr_mask = 0x7fff0000,
|
||||
.pvr_value = 0x00900000,
|
||||
.cpu_name = "PA6T",
|
||||
.cpu_features = CPU_FTRS_PA6T,
|
||||
.cpu_user_features = COMMON_USER_PA6T,
|
||||
.icache_bsize = 64,
|
||||
.dcache_bsize = 64,
|
||||
.num_pmcs = 6,
|
||||
.platform = "pa6t",
|
||||
},
|
||||
{ /* default match */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
|
@ -929,6 +949,7 @@ struct cpu_spec cpu_specs[] = {
|
|||
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.platform = "ppc405",
|
||||
},
|
||||
{ /* 405EP */
|
||||
.pvr_mask = 0xffff0000,
|
||||
|
|
|
@ -80,7 +80,7 @@ static int __init parse_savemaxmem(char *p)
|
|||
}
|
||||
__setup("savemaxmem=", parse_savemaxmem);
|
||||
|
||||
/*
|
||||
/**
|
||||
* copy_oldmem_page - copy one page from "oldmem"
|
||||
* @pfn: page frame number to be copied
|
||||
* @buf: target memory address for the copy; this can be in kernel address
|
||||
|
|
|
@ -35,10 +35,9 @@ int dma_supported(struct device *dev, u64 mask)
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
return dma_ops->dma_supported(dev, mask);
|
||||
BUG();
|
||||
return 0;
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
return dma_ops->dma_supported(dev, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_supported);
|
||||
|
||||
|
@ -66,10 +65,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
|
||||
BUG();
|
||||
return NULL;
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_alloc_coherent);
|
||||
|
||||
|
@ -78,10 +76,9 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
|
||||
else
|
||||
BUG();
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_free_coherent);
|
||||
|
||||
|
@ -90,10 +87,9 @@ dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
return dma_ops->map_single(dev, cpu_addr, size, direction);
|
||||
BUG();
|
||||
return (dma_addr_t)0;
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
return dma_ops->map_single(dev, cpu_addr, size, direction);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_single);
|
||||
|
||||
|
@ -102,10 +98,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
dma_ops->unmap_single(dev, dma_addr, size, direction);
|
||||
else
|
||||
BUG();
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
dma_ops->unmap_single(dev, dma_addr, size, direction);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_unmap_single);
|
||||
|
||||
|
@ -115,11 +110,10 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
return dma_ops->map_single(dev,
|
||||
(page_address(page) + offset), size, direction);
|
||||
BUG();
|
||||
return (dma_addr_t)0;
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
return dma_ops->map_single(dev, page_address(page) + offset, size,
|
||||
direction);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_page);
|
||||
|
||||
|
@ -128,10 +122,9 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
dma_ops->unmap_single(dev, dma_address, size, direction);
|
||||
else
|
||||
BUG();
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
dma_ops->unmap_single(dev, dma_address, size, direction);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_unmap_page);
|
||||
|
||||
|
@ -140,10 +133,9 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
return dma_ops->map_sg(dev, sg, nents, direction);
|
||||
BUG();
|
||||
return 0;
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
return dma_ops->map_sg(dev, sg, nents, direction);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_map_sg);
|
||||
|
||||
|
@ -152,9 +144,8 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
|
|||
{
|
||||
struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
if (dma_ops)
|
||||
dma_ops->unmap_sg(dev, sg, nhwentries, direction);
|
||||
else
|
||||
BUG();
|
||||
BUG_ON(!dma_ops);
|
||||
|
||||
dma_ops->unmap_sg(dev, sg, nhwentries, direction);
|
||||
}
|
||||
EXPORT_SYMBOL(dma_unmap_sg);
|
||||
|
|
|
@ -375,6 +375,14 @@ BEGIN_FTR_SECTION
|
|||
ld r7,KSP_VSID(r4) /* Get new stack's VSID */
|
||||
oris r0,r6,(SLB_ESID_V)@h
|
||||
ori r0,r0,(SLB_NUM_BOLTED-1)@l
|
||||
|
||||
/* Update the last bolted SLB */
|
||||
ld r9,PACA_SLBSHADOWPTR(r13)
|
||||
li r12,0
|
||||
std r12,SLBSHADOW_STACKESID(r9) /* Clear ESID */
|
||||
std r7,SLBSHADOW_STACKVSID(r9) /* Save VSID */
|
||||
std r0,SLBSHADOW_STACKESID(r9) /* Save ESID */
|
||||
|
||||
slbie r6
|
||||
slbie r6 /* Workaround POWER5 < DD2.1 issue */
|
||||
slbmte r7,r0
|
||||
|
|
|
@ -132,7 +132,7 @@ _GLOBAL(__secondary_hold)
|
|||
bne 100b
|
||||
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
|
||||
LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init)
|
||||
LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
|
||||
mtctr r4
|
||||
mr r3,r24
|
||||
bctr
|
||||
|
@ -1484,19 +1484,17 @@ fwnmi_data_area:
|
|||
. = 0x8000
|
||||
|
||||
/*
|
||||
* On pSeries, secondary processors spin in the following code.
|
||||
* On pSeries and most other platforms, secondary processors spin
|
||||
* in the following code.
|
||||
* At entry, r3 = this processor's number (physical cpu id)
|
||||
*/
|
||||
_GLOBAL(pSeries_secondary_smp_init)
|
||||
_GLOBAL(generic_secondary_smp_init)
|
||||
mr r24,r3
|
||||
|
||||
/* turn on 64-bit mode */
|
||||
bl .enable_64b_mode
|
||||
isync
|
||||
|
||||
/* Copy some CPU settings from CPU 0 */
|
||||
bl .__restore_cpu_setup
|
||||
|
||||
/* Set up a paca value for this processor. Since we have the
|
||||
* physical cpu id in r24, we need to search the pacas to find
|
||||
* which logical id maps to our physical one.
|
||||
|
@ -1522,15 +1520,28 @@ _GLOBAL(pSeries_secondary_smp_init)
|
|||
/* start. */
|
||||
sync
|
||||
|
||||
/* Create a temp kernel stack for use before relocation is on. */
|
||||
#ifndef CONFIG_SMP
|
||||
b 3b /* Never go on non-SMP */
|
||||
#else
|
||||
cmpwi 0,r23,0
|
||||
beq 3b /* Loop until told to go */
|
||||
|
||||
/* See if we need to call a cpu state restore handler */
|
||||
LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
|
||||
ld r23,0(r23)
|
||||
ld r23,CPU_SPEC_RESTORE(r23)
|
||||
cmpdi 0,r23,0
|
||||
beq 4f
|
||||
ld r23,0(r23)
|
||||
mtctr r23
|
||||
bctrl
|
||||
|
||||
4: /* Create a temp kernel stack for use before relocation is on. */
|
||||
ld r1,PACAEMERGSP(r13)
|
||||
subi r1,r1,STACK_FRAME_OVERHEAD
|
||||
|
||||
cmpwi 0,r23,0
|
||||
#ifdef CONFIG_SMP
|
||||
bne .__secondary_start
|
||||
b .__secondary_start
|
||||
#endif
|
||||
b 3b /* Loop until told to go */
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
_STATIC(__start_initialization_iSeries)
|
||||
|
@ -1611,7 +1622,16 @@ _GLOBAL(__start_initialization_multiplatform)
|
|||
bl .enable_64b_mode
|
||||
|
||||
/* Setup some critical 970 SPRs before switching MMU off */
|
||||
bl .__970_cpu_preinit
|
||||
mfspr r0,SPRN_PVR
|
||||
srwi r0,r0,16
|
||||
cmpwi r0,0x39 /* 970 */
|
||||
beq 1f
|
||||
cmpwi r0,0x3c /* 970FX */
|
||||
beq 1f
|
||||
cmpwi r0,0x44 /* 970MP */
|
||||
bne 2f
|
||||
1: bl .__cpu_preinit_ppc970
|
||||
2:
|
||||
|
||||
/* Switch off MMU if not already */
|
||||
LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
|
||||
|
@ -1728,7 +1748,7 @@ _STATIC(__after_prom_start)
|
|||
_GLOBAL(copy_and_flush)
|
||||
addi r5,r5,-8
|
||||
addi r6,r6,-8
|
||||
4: li r0,16 /* Use the least common */
|
||||
4: li r0,8 /* Use the smallest common */
|
||||
/* denominator cache line */
|
||||
/* size. This results in */
|
||||
/* extra cache line flushes */
|
||||
|
@ -1782,7 +1802,7 @@ _GLOBAL(pmac_secondary_start)
|
|||
isync
|
||||
|
||||
/* Copy some CPU settings from CPU 0 */
|
||||
bl .__restore_cpu_setup
|
||||
bl .__restore_cpu_ppc970
|
||||
|
||||
/* pSeries do that early though I don't think we really need it */
|
||||
mfmsr r3
|
||||
|
@ -1932,12 +1952,6 @@ _STATIC(start_here_multiplatform)
|
|||
mr r5,r26
|
||||
bl .identify_cpu
|
||||
|
||||
/* Save some low level config HIDs of CPU0 to be copied to
|
||||
* other CPUs later on, or used for suspend/resume
|
||||
*/
|
||||
bl .__save_cpu_setup
|
||||
sync
|
||||
|
||||
/* Do very early kernel initializations, including initial hash table,
|
||||
* stab and slb setup before we turn on relocation. */
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ static DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, ibmebusdev_show_name,
|
|||
NULL);
|
||||
|
||||
static struct ibmebus_dev* __devinit ibmebus_register_device_common(
|
||||
struct ibmebus_dev *dev, char *name)
|
||||
struct ibmebus_dev *dev, const char *name)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
|
@ -194,10 +194,10 @@ static struct ibmebus_dev* __devinit ibmebus_register_device_node(
|
|||
struct device_node *dn)
|
||||
{
|
||||
struct ibmebus_dev *dev;
|
||||
char *loc_code;
|
||||
const char *loc_code;
|
||||
int length;
|
||||
|
||||
loc_code = (char *)get_property(dn, "ibm,loc-code", NULL);
|
||||
loc_code = get_property(dn, "ibm,loc-code", NULL);
|
||||
if (!loc_code) {
|
||||
printk(KERN_WARNING "%s: node %s missing 'ibm,loc-code'\n",
|
||||
__FUNCTION__, dn->name ? dn->name : "<unknown>");
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* I/O string operations
|
||||
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
|
||||
* Copyright (C) 2006 IBM Corporation
|
||||
*
|
||||
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
|
||||
* and Paul Mackerras.
|
||||
*
|
||||
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
|
||||
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
|
||||
*
|
||||
* Rewritten in C by Stephen Rothwell.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/bug.h>
|
||||
|
||||
void _insb(volatile u8 __iomem *port, void *buf, long count)
|
||||
{
|
||||
u8 *tbuf = buf;
|
||||
u8 tmp;
|
||||
|
||||
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return;
|
||||
asm volatile("sync");
|
||||
do {
|
||||
tmp = *port;
|
||||
asm volatile("eieio");
|
||||
*tbuf++ = tmp;
|
||||
} while (--count != 0);
|
||||
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
|
||||
}
|
||||
EXPORT_SYMBOL(_insb);
|
||||
|
||||
void _outsb(volatile u8 __iomem *port, const void *buf, long count)
|
||||
{
|
||||
const u8 *tbuf = buf;
|
||||
|
||||
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return;
|
||||
asm volatile("sync");
|
||||
do {
|
||||
*port = *tbuf++;
|
||||
} while (--count != 0);
|
||||
asm volatile("sync");
|
||||
}
|
||||
EXPORT_SYMBOL(_outsb);
|
||||
|
||||
void _insw_ns(volatile u16 __iomem *port, void *buf, long count)
|
||||
{
|
||||
u16 *tbuf = buf;
|
||||
u16 tmp;
|
||||
|
||||
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return;
|
||||
asm volatile("sync");
|
||||
do {
|
||||
tmp = *port;
|
||||
asm volatile("eieio");
|
||||
*tbuf++ = tmp;
|
||||
} while (--count != 0);
|
||||
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
|
||||
}
|
||||
EXPORT_SYMBOL(_insw_ns);
|
||||
|
||||
void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count)
|
||||
{
|
||||
const u16 *tbuf = buf;
|
||||
|
||||
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return;
|
||||
asm volatile("sync");
|
||||
do {
|
||||
*port = *tbuf++;
|
||||
} while (--count != 0);
|
||||
asm volatile("sync");
|
||||
}
|
||||
EXPORT_SYMBOL(_outsw_ns);
|
||||
|
||||
void _insl_ns(volatile u32 __iomem *port, void *buf, long count)
|
||||
{
|
||||
u32 *tbuf = buf;
|
||||
u32 tmp;
|
||||
|
||||
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return;
|
||||
asm volatile("sync");
|
||||
do {
|
||||
tmp = *port;
|
||||
asm volatile("eieio");
|
||||
*tbuf++ = tmp;
|
||||
} while (--count != 0);
|
||||
asm volatile("twi 0,%0,0; isync" : : "r" (tmp));
|
||||
}
|
||||
EXPORT_SYMBOL(_insl_ns);
|
||||
|
||||
void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count)
|
||||
{
|
||||
const u32 *tbuf = buf;
|
||||
|
||||
BUG_ON(firmware_has_feature(FW_FEATURE_ISERIES));
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return;
|
||||
asm volatile("sync");
|
||||
do {
|
||||
*port = *tbuf++;
|
||||
} while (--count != 0);
|
||||
asm volatile("sync");
|
||||
}
|
||||
EXPORT_SYMBOL(_outsl_ns);
|
|
@ -52,6 +52,7 @@
|
|||
#include <linux/radix-tree.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/system.h>
|
||||
|
@ -875,12 +876,14 @@ int pci_enable_msi(struct pci_dev * pdev)
|
|||
else
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_enable_msi);
|
||||
|
||||
void pci_disable_msi(struct pci_dev * pdev)
|
||||
{
|
||||
if (ppc_md.disable_msi)
|
||||
ppc_md.disable_msi(pdev);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_disable_msi);
|
||||
|
||||
void pci_scan_msi_device(struct pci_dev *dev) {}
|
||||
int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
|
||||
|
@ -888,6 +891,8 @@ void pci_disable_msix(struct pci_dev *dev) {}
|
|||
void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
|
||||
void disable_msi_mode(struct pci_dev *dev, int pos, int type) {}
|
||||
void pci_no_msi(void) {}
|
||||
EXPORT_SYMBOL(pci_enable_msix);
|
||||
EXPORT_SYMBOL(pci_disable_msix);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -39,16 +39,17 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
|
|||
phys_addr_t taddr, unsigned long irq,
|
||||
upf_t flags, int irq_check_parent)
|
||||
{
|
||||
u32 *clk, *spd, clock = BASE_BAUD * 16;
|
||||
const u32 *clk, *spd;
|
||||
u32 clock = BASE_BAUD * 16;
|
||||
int index;
|
||||
|
||||
/* get clock freq. if present */
|
||||
clk = (u32 *)get_property(np, "clock-frequency", NULL);
|
||||
clk = get_property(np, "clock-frequency", NULL);
|
||||
if (clk && *clk)
|
||||
clock = *clk;
|
||||
|
||||
/* get default speed if present */
|
||||
spd = (u32 *)get_property(np, "current-speed", NULL);
|
||||
spd = get_property(np, "current-speed", NULL);
|
||||
|
||||
/* If we have a location index, then try to use it */
|
||||
if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS)
|
||||
|
@ -113,7 +114,7 @@ static int __init add_legacy_soc_port(struct device_node *np,
|
|||
struct device_node *soc_dev)
|
||||
{
|
||||
u64 addr;
|
||||
u32 *addrp;
|
||||
const u32 *addrp;
|
||||
upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
|
||||
struct device_node *tsi = of_get_parent(np);
|
||||
|
||||
|
@ -144,15 +145,15 @@ static int __init add_legacy_soc_port(struct device_node *np,
|
|||
static int __init add_legacy_isa_port(struct device_node *np,
|
||||
struct device_node *isa_brg)
|
||||
{
|
||||
u32 *reg;
|
||||
char *typep;
|
||||
const u32 *reg;
|
||||
const char *typep;
|
||||
int index = -1;
|
||||
u64 taddr;
|
||||
|
||||
DBG(" -> add_legacy_isa_port(%s)\n", np->full_name);
|
||||
|
||||
/* Get the ISA port number */
|
||||
reg = (u32 *)get_property(np, "reg", NULL);
|
||||
reg = get_property(np, "reg", NULL);
|
||||
if (reg == NULL)
|
||||
return -1;
|
||||
|
||||
|
@ -163,7 +164,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
|
|||
/* Now look for an "ibm,aix-loc" property that gives us ordering
|
||||
* if any...
|
||||
*/
|
||||
typep = (char *)get_property(np, "ibm,aix-loc", NULL);
|
||||
typep = get_property(np, "ibm,aix-loc", NULL);
|
||||
|
||||
/* If we have a location index, then use it */
|
||||
if (typep && *typep == 'S')
|
||||
|
@ -188,7 +189,7 @@ static int __init add_legacy_pci_port(struct device_node *np,
|
|||
struct device_node *pci_dev)
|
||||
{
|
||||
u64 addr, base;
|
||||
u32 *addrp;
|
||||
const u32 *addrp;
|
||||
unsigned int flags;
|
||||
int iotype, index = -1, lindex = 0;
|
||||
|
||||
|
@ -227,7 +228,7 @@ static int __init add_legacy_pci_port(struct device_node *np,
|
|||
* we get to their "reg" property
|
||||
*/
|
||||
if (np != pci_dev) {
|
||||
u32 *reg = (u32 *)get_property(np, "reg", NULL);
|
||||
const u32 *reg = get_property(np, "reg", NULL);
|
||||
if (reg && (*reg < 4))
|
||||
index = lindex = *reg;
|
||||
}
|
||||
|
@ -285,13 +286,13 @@ static void __init setup_legacy_serial_console(int console)
|
|||
void __init find_legacy_serial_ports(void)
|
||||
{
|
||||
struct device_node *np, *stdout = NULL;
|
||||
char *path;
|
||||
const char *path;
|
||||
int index;
|
||||
|
||||
DBG(" -> find_legacy_serial_port()\n");
|
||||
|
||||
/* Now find out if one of these is out firmware console */
|
||||
path = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
path = get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
if (path != NULL) {
|
||||
stdout = of_find_node_by_path(path);
|
||||
if (stdout)
|
||||
|
@ -491,8 +492,8 @@ static int __init check_legacy_serial_console(void)
|
|||
{
|
||||
struct device_node *prom_stdout = NULL;
|
||||
int speed = 0, offset = 0;
|
||||
char *name;
|
||||
u32 *spd;
|
||||
const char *name;
|
||||
const u32 *spd;
|
||||
|
||||
DBG(" -> check_legacy_serial_console()\n");
|
||||
|
||||
|
@ -513,7 +514,7 @@ static int __init check_legacy_serial_console(void)
|
|||
}
|
||||
/* We are getting a weird phandle from OF ... */
|
||||
/* ... So use the full path instead */
|
||||
name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
name = get_property(of_chosen, "linux,stdout-path", NULL);
|
||||
if (name == NULL) {
|
||||
DBG(" no linux,stdout-path !\n");
|
||||
return -ENODEV;
|
||||
|
@ -525,12 +526,12 @@ static int __init check_legacy_serial_console(void)
|
|||
}
|
||||
DBG("stdout is %s\n", prom_stdout->full_name);
|
||||
|
||||
name = (char *)get_property(prom_stdout, "name", NULL);
|
||||
name = get_property(prom_stdout, "name", NULL);
|
||||
if (!name) {
|
||||
DBG(" stdout package has no name !\n");
|
||||
goto not_found;
|
||||
}
|
||||
spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);
|
||||
spd = get_property(prom_stdout, "current-speed", NULL);
|
||||
if (spd)
|
||||
speed = *spd;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <asm/rtas.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/iseries/it_exp_vpd_panel.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/vdso_datapage.h>
|
||||
|
||||
|
@ -183,8 +182,14 @@ static unsigned int h_get_ppp(unsigned long *entitled,
|
|||
unsigned long *resource)
|
||||
{
|
||||
unsigned long rc;
|
||||
rc = plpar_hcall_4out(H_GET_PPP, 0, 0, 0, 0, entitled, unallocated,
|
||||
aggregation, resource);
|
||||
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
||||
|
||||
rc = plpar_hcall(H_GET_PPP, retbuf);
|
||||
|
||||
*entitled = retbuf[0];
|
||||
*unallocated = retbuf[1];
|
||||
*aggregation = retbuf[2];
|
||||
*resource = retbuf[3];
|
||||
|
||||
log_plpar_hcall_return(rc, "H_GET_PPP");
|
||||
|
||||
|
@ -194,8 +199,12 @@ static unsigned int h_get_ppp(unsigned long *entitled,
|
|||
static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
|
||||
{
|
||||
unsigned long rc;
|
||||
unsigned long dummy;
|
||||
rc = plpar_hcall(H_PIC, 0, 0, 0, 0, pool_idle_time, num_procs, &dummy);
|
||||
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
||||
|
||||
rc = plpar_hcall(H_PIC, retbuf);
|
||||
|
||||
*pool_idle_time = retbuf[0];
|
||||
*num_procs = retbuf[1];
|
||||
|
||||
if (rc != H_AUTHORITY)
|
||||
log_plpar_hcall_return(rc, "H_PIC");
|
||||
|
@ -310,12 +319,11 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v)
|
|||
int partition_potential_processors;
|
||||
int partition_active_processors;
|
||||
struct device_node *rtas_node;
|
||||
int *lrdrp = NULL;
|
||||
const int *lrdrp = NULL;
|
||||
|
||||
rtas_node = find_path_device("/rtas");
|
||||
if (rtas_node)
|
||||
lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity",
|
||||
NULL);
|
||||
lrdrp = get_property(rtas_node, "ibm,lrdr-capacity", NULL);
|
||||
|
||||
if (lrdrp == NULL) {
|
||||
partition_potential_processors = vdso_data->processorCount;
|
||||
|
@ -520,7 +528,8 @@ static int lparcfg_data(struct seq_file *m, void *v)
|
|||
const char *model = "";
|
||||
const char *system_id = "";
|
||||
const char *tmp;
|
||||
unsigned int *lp_index_ptr, lp_index = 0;
|
||||
const unsigned int *lp_index_ptr;
|
||||
unsigned int lp_index = 0;
|
||||
|
||||
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
|
||||
|
||||
|
@ -540,8 +549,7 @@ static int lparcfg_data(struct seq_file *m, void *v)
|
|||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
system_id += 4;
|
||||
}
|
||||
lp_index_ptr = (unsigned int *)
|
||||
get_property(rootdn, "ibm,partition-no", NULL);
|
||||
lp_index_ptr = get_property(rootdn, "ibm,partition-no", NULL);
|
||||
if (lp_index_ptr)
|
||||
lp_index = *lp_index_ptr;
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ int default_machine_kexec_prepare(struct kimage *image)
|
|||
unsigned long begin, end; /* limits of segment */
|
||||
unsigned long low, high; /* limits of blocked memory range */
|
||||
struct device_node *node;
|
||||
unsigned long *basep;
|
||||
unsigned int *sizep;
|
||||
const unsigned long *basep;
|
||||
const unsigned int *sizep;
|
||||
|
||||
if (!ppc_md.hpte_clear_all)
|
||||
return -ENOENT;
|
||||
|
@ -72,10 +72,8 @@ int default_machine_kexec_prepare(struct kimage *image)
|
|||
/* We also should not overwrite the tce tables */
|
||||
for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
|
||||
node = of_find_node_by_type(node, "pci")) {
|
||||
basep = (unsigned long *)get_property(node, "linux,tce-base",
|
||||
NULL);
|
||||
sizep = (unsigned int *)get_property(node, "linux,tce-size",
|
||||
NULL);
|
||||
basep = get_property(node, "linux,tce-base", NULL);
|
||||
sizep = get_property(node, "linux,tce-size", NULL);
|
||||
if (basep == NULL || sizep == NULL)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -43,162 +43,3 @@ _GLOBAL(add_reloc_offset)
|
|||
add r3,r3,r5
|
||||
mtlr r0
|
||||
blr
|
||||
|
||||
/*
|
||||
* I/O string operations
|
||||
*
|
||||
* insb(port, buf, len)
|
||||
* outsb(port, buf, len)
|
||||
* insw(port, buf, len)
|
||||
* outsw(port, buf, len)
|
||||
* insl(port, buf, len)
|
||||
* outsl(port, buf, len)
|
||||
* insw_ns(port, buf, len)
|
||||
* outsw_ns(port, buf, len)
|
||||
* insl_ns(port, buf, len)
|
||||
* outsl_ns(port, buf, len)
|
||||
*
|
||||
* The *_ns versions don't do byte-swapping.
|
||||
*/
|
||||
_GLOBAL(_insb)
|
||||
sync
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,1
|
||||
blelr-
|
||||
00: lbz r5,0(r3)
|
||||
eieio
|
||||
stbu r5,1(r4)
|
||||
bdnz 00b
|
||||
twi 0,r5,0
|
||||
isync
|
||||
blr
|
||||
|
||||
_GLOBAL(_outsb)
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,1
|
||||
blelr-
|
||||
sync
|
||||
00: lbzu r5,1(r4)
|
||||
stb r5,0(r3)
|
||||
bdnz 00b
|
||||
sync
|
||||
blr
|
||||
|
||||
_GLOBAL(_insw)
|
||||
sync
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,2
|
||||
blelr-
|
||||
00: lhbrx r5,0,r3
|
||||
eieio
|
||||
sthu r5,2(r4)
|
||||
bdnz 00b
|
||||
twi 0,r5,0
|
||||
isync
|
||||
blr
|
||||
|
||||
_GLOBAL(_outsw)
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,2
|
||||
blelr-
|
||||
sync
|
||||
00: lhzu r5,2(r4)
|
||||
sthbrx r5,0,r3
|
||||
bdnz 00b
|
||||
sync
|
||||
blr
|
||||
|
||||
_GLOBAL(_insl)
|
||||
sync
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,4
|
||||
blelr-
|
||||
00: lwbrx r5,0,r3
|
||||
eieio
|
||||
stwu r5,4(r4)
|
||||
bdnz 00b
|
||||
twi 0,r5,0
|
||||
isync
|
||||
blr
|
||||
|
||||
_GLOBAL(_outsl)
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,4
|
||||
blelr-
|
||||
sync
|
||||
00: lwzu r5,4(r4)
|
||||
stwbrx r5,0,r3
|
||||
bdnz 00b
|
||||
sync
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
_GLOBAL(__ide_mm_insw)
|
||||
#endif
|
||||
_GLOBAL(_insw_ns)
|
||||
sync
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,2
|
||||
blelr-
|
||||
00: lhz r5,0(r3)
|
||||
eieio
|
||||
sthu r5,2(r4)
|
||||
bdnz 00b
|
||||
twi 0,r5,0
|
||||
isync
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
_GLOBAL(__ide_mm_outsw)
|
||||
#endif
|
||||
_GLOBAL(_outsw_ns)
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,2
|
||||
blelr-
|
||||
sync
|
||||
00: lhzu r5,2(r4)
|
||||
sth r5,0(r3)
|
||||
bdnz 00b
|
||||
sync
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
_GLOBAL(__ide_mm_insl)
|
||||
#endif
|
||||
_GLOBAL(_insl_ns)
|
||||
sync
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,4
|
||||
blelr-
|
||||
00: lwz r5,0(r3)
|
||||
eieio
|
||||
stwu r5,4(r4)
|
||||
bdnz 00b
|
||||
twi 0,r5,0
|
||||
isync
|
||||
blr
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
_GLOBAL(__ide_mm_outsl)
|
||||
#endif
|
||||
_GLOBAL(_outsl_ns)
|
||||
cmpwi 0,r5,0
|
||||
mtctr r5
|
||||
subi r4,r4,4
|
||||
blelr-
|
||||
sync
|
||||
00: lwzu r5,4(r4)
|
||||
stw r5,0(r3)
|
||||
bdnz 00b
|
||||
sync
|
||||
blr
|
||||
|
||||
|
|
|
@ -189,27 +189,9 @@ void of_release_dev(struct device *dev)
|
|||
int of_device_register(struct of_device *ofdev)
|
||||
{
|
||||
int rc;
|
||||
struct of_device **odprop;
|
||||
|
||||
BUG_ON(ofdev->node == NULL);
|
||||
|
||||
odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
|
||||
if (!odprop) {
|
||||
struct property *new_prop;
|
||||
|
||||
new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
|
||||
GFP_KERNEL);
|
||||
if (new_prop == NULL)
|
||||
return -ENOMEM;
|
||||
new_prop->name = "linux,device";
|
||||
new_prop->length = sizeof(sizeof(struct of_device *));
|
||||
new_prop->value = (unsigned char *)&new_prop[1];
|
||||
odprop = (struct of_device **)new_prop->value;
|
||||
*odprop = NULL;
|
||||
prom_add_property(ofdev->node, new_prop);
|
||||
}
|
||||
*odprop = ofdev;
|
||||
|
||||
rc = device_register(&ofdev->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
@ -221,14 +203,8 @@ int of_device_register(struct of_device *ofdev)
|
|||
|
||||
void of_device_unregister(struct of_device *ofdev)
|
||||
{
|
||||
struct of_device **odprop;
|
||||
|
||||
device_remove_file(&ofdev->dev, &dev_attr_devspec);
|
||||
|
||||
odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
|
||||
if (odprop)
|
||||
*odprop = NULL;
|
||||
|
||||
device_unregister(&ofdev->dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <asm/lppaca.h>
|
||||
#include <asm/iseries/it_lp_reg_save.h>
|
||||
#include <asm/paca.h>
|
||||
#include <asm/mmu.h>
|
||||
|
||||
|
||||
/* This symbol is provided by the linker - let it fill in the paca
|
||||
|
@ -45,6 +46,17 @@ struct lppaca lppaca[] = {
|
|||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* 3 persistent SLBs are registered here. The buffer will be zero
|
||||
* initially, hence will all be invaild until we actually write them.
|
||||
*/
|
||||
struct slb_shadow slb_shadow[] __cacheline_aligned = {
|
||||
[0 ... (NR_CPUS-1)] = {
|
||||
.persistent = SLB_NUM_BOLTED,
|
||||
.buffer_length = sizeof(struct slb_shadow),
|
||||
},
|
||||
};
|
||||
|
||||
/* The Paca is an array with one entry per processor. Each contains an
|
||||
* lppaca, which contains the information shared between the
|
||||
* hypervisor and Linux.
|
||||
|
@ -59,7 +71,8 @@ struct lppaca lppaca[] = {
|
|||
.lock_token = 0x8000, \
|
||||
.paca_index = (number), /* Paca Index */ \
|
||||
.kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
|
||||
.hw_cpu_id = 0xffff,
|
||||
.hw_cpu_id = 0xffff, \
|
||||
.slb_shadow_ptr = &slb_shadow[number],
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
#define PACA_INIT_ISERIES(number) \
|
||||
|
|
|
@ -633,12 +633,12 @@ pcibios_alloc_controller(void)
|
|||
static void
|
||||
make_one_node_map(struct device_node* node, u8 pci_bus)
|
||||
{
|
||||
int *bus_range;
|
||||
const int *bus_range;
|
||||
int len;
|
||||
|
||||
if (pci_bus >= pci_bus_count)
|
||||
return;
|
||||
bus_range = (int *) get_property(node, "bus-range", &len);
|
||||
bus_range = get_property(node, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||
printk(KERN_WARNING "Can't get bus-range for %s, "
|
||||
"assuming it starts at 0\n", node->full_name);
|
||||
|
@ -648,13 +648,13 @@ make_one_node_map(struct device_node* node, u8 pci_bus)
|
|||
|
||||
for (node=node->child; node != 0;node = node->sibling) {
|
||||
struct pci_dev* dev;
|
||||
unsigned int *class_code, *reg;
|
||||
const unsigned int *class_code, *reg;
|
||||
|
||||
class_code = (unsigned int *) get_property(node, "class-code", NULL);
|
||||
class_code = get_property(node, "class-code", NULL);
|
||||
if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
|
||||
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
|
||||
continue;
|
||||
reg = (unsigned int *)get_property(node, "reg", NULL);
|
||||
reg = get_property(node, "reg", NULL);
|
||||
if (!reg)
|
||||
continue;
|
||||
dev = pci_find_slot(pci_bus, ((reg[0] >> 8) & 0xff));
|
||||
|
@ -669,7 +669,7 @@ pcibios_make_OF_bus_map(void)
|
|||
{
|
||||
int i;
|
||||
struct pci_controller* hose;
|
||||
u8* of_prop_map;
|
||||
struct property *map_prop;
|
||||
|
||||
pci_to_OF_bus_map = (u8*)kmalloc(pci_bus_count, GFP_KERNEL);
|
||||
if (!pci_to_OF_bus_map) {
|
||||
|
@ -691,9 +691,12 @@ pcibios_make_OF_bus_map(void)
|
|||
continue;
|
||||
make_one_node_map(node, hose->first_busno);
|
||||
}
|
||||
of_prop_map = get_property(find_path_device("/"), "pci-OF-bus-map", NULL);
|
||||
if (of_prop_map)
|
||||
memcpy(of_prop_map, pci_to_OF_bus_map, pci_bus_count);
|
||||
map_prop = of_find_property(find_path_device("/"),
|
||||
"pci-OF-bus-map", NULL);
|
||||
if (map_prop) {
|
||||
BUG_ON(pci_bus_count > map_prop->length);
|
||||
memcpy(map_prop->value, pci_to_OF_bus_map, pci_bus_count);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printk("PCI->OF bus map:\n");
|
||||
for (i=0; i<pci_bus_count; i++) {
|
||||
|
@ -712,7 +715,7 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
|
|||
struct device_node* sub_node;
|
||||
|
||||
for (; node != 0;node = node->sibling) {
|
||||
unsigned int *class_code;
|
||||
const unsigned int *class_code;
|
||||
|
||||
if (filter(node, data))
|
||||
return node;
|
||||
|
@ -722,7 +725,7 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
|
|||
* a fake root for all functions of a multi-function device,
|
||||
* we go down them as well.
|
||||
*/
|
||||
class_code = (unsigned int *) get_property(node, "class-code", NULL);
|
||||
class_code = get_property(node, "class-code", NULL);
|
||||
if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
|
||||
(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
|
||||
strcmp(node->name, "multifunc-device"))
|
||||
|
@ -737,10 +740,10 @@ scan_OF_pci_childs(struct device_node* node, pci_OF_scan_iterator filter, void*
|
|||
static int
|
||||
scan_OF_pci_childs_iterator(struct device_node* node, void* data)
|
||||
{
|
||||
unsigned int *reg;
|
||||
const unsigned int *reg;
|
||||
u8* fdata = (u8*)data;
|
||||
|
||||
reg = (unsigned int *) get_property(node, "reg", NULL);
|
||||
reg = get_property(node, "reg", NULL);
|
||||
if (reg && ((reg[0] >> 8) & 0xff) == fdata[1]
|
||||
&& ((reg[0] >> 16) & 0xff) == fdata[0])
|
||||
return 1;
|
||||
|
@ -841,7 +844,7 @@ find_OF_pci_device_filter(struct device_node* node, void* data)
|
|||
int
|
||||
pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
|
||||
{
|
||||
unsigned int *reg;
|
||||
const unsigned int *reg;
|
||||
struct pci_controller* hose;
|
||||
struct pci_dev* dev = NULL;
|
||||
|
||||
|
@ -854,7 +857,7 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn)
|
|||
if (!scan_OF_pci_childs(((struct device_node*)hose->arch_data)->child,
|
||||
find_OF_pci_device_filter, (void *)node))
|
||||
return -ENODEV;
|
||||
reg = (unsigned int *) get_property(node, "reg", NULL);
|
||||
reg = get_property(node, "reg", NULL);
|
||||
if (!reg)
|
||||
return -ENODEV;
|
||||
*bus = (reg[0] >> 16) & 0xff;
|
||||
|
@ -885,8 +888,8 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||
struct device_node *dev, int primary)
|
||||
{
|
||||
static unsigned int static_lc_ranges[256] __initdata;
|
||||
unsigned int *dt_ranges, *lc_ranges, *ranges, *prev;
|
||||
unsigned int size;
|
||||
const unsigned int *dt_ranges;
|
||||
unsigned int *lc_ranges, *ranges, *prev, size;
|
||||
int rlen = 0, orig_rlen;
|
||||
int memno = 0;
|
||||
struct resource *res;
|
||||
|
@ -897,7 +900,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||
* that can have more than 3 ranges, fortunately using contiguous
|
||||
* addresses -- BenH
|
||||
*/
|
||||
dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
|
||||
dt_ranges = get_property(dev, "ranges", &rlen);
|
||||
if (!dt_ranges)
|
||||
return;
|
||||
/* Sanity check, though hopefully that never happens */
|
||||
|
|
|
@ -185,34 +185,6 @@ static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
|
|||
spin_unlock(&hose_spinlock);
|
||||
}
|
||||
|
||||
static void add_linux_pci_domain(struct device_node *dev,
|
||||
struct pci_controller *phb)
|
||||
{
|
||||
struct property *of_prop;
|
||||
unsigned int size;
|
||||
|
||||
of_prop = (struct property *)
|
||||
get_property(dev, "linux,pci-domain", &size);
|
||||
if (of_prop != NULL)
|
||||
return;
|
||||
WARN_ON(of_prop && size < sizeof(int));
|
||||
if (of_prop && size < sizeof(int))
|
||||
of_prop = NULL;
|
||||
size = sizeof(struct property) + sizeof(int);
|
||||
if (of_prop == NULL) {
|
||||
if (mem_init_done)
|
||||
of_prop = kmalloc(size, GFP_KERNEL);
|
||||
else
|
||||
of_prop = alloc_bootmem(size);
|
||||
}
|
||||
memset(of_prop, 0, sizeof(struct property));
|
||||
of_prop->name = "linux,pci-domain";
|
||||
of_prop->length = sizeof(int);
|
||||
of_prop->value = (unsigned char *)&of_prop[1];
|
||||
*((int *)of_prop->value) = phb->global_number;
|
||||
prom_add_property(dev, of_prop);
|
||||
}
|
||||
|
||||
struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
|
||||
{
|
||||
struct pci_controller *phb;
|
||||
|
@ -226,22 +198,13 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
|
|||
pci_setup_pci_controller(phb);
|
||||
phb->arch_data = dev;
|
||||
phb->is_dynamic = mem_init_done;
|
||||
if (dev) {
|
||||
if (dev)
|
||||
PHB_SET_NODE(phb, of_node_to_nid(dev));
|
||||
add_linux_pci_domain(dev, phb);
|
||||
}
|
||||
return phb;
|
||||
}
|
||||
|
||||
void pcibios_free_controller(struct pci_controller *phb)
|
||||
{
|
||||
if (phb->arch_data) {
|
||||
struct device_node *np = phb->arch_data;
|
||||
int *domain = (int *)get_property(np,
|
||||
"linux,pci-domain", NULL);
|
||||
if (domain)
|
||||
*domain = -1;
|
||||
}
|
||||
if (phb->is_dynamic)
|
||||
kfree(phb);
|
||||
}
|
||||
|
@ -283,10 +246,10 @@ static void __init pcibios_claim_of_setup(void)
|
|||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
|
||||
{
|
||||
u32 *prop;
|
||||
const u32 *prop;
|
||||
int len;
|
||||
|
||||
prop = (u32 *) get_property(np, name, &len);
|
||||
prop = get_property(np, name, &len);
|
||||
if (prop && len >= 4)
|
||||
return *prop;
|
||||
return def;
|
||||
|
@ -315,10 +278,11 @@ static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev)
|
|||
u64 base, size;
|
||||
unsigned int flags;
|
||||
struct resource *res;
|
||||
u32 *addrs, i;
|
||||
const u32 *addrs;
|
||||
u32 i;
|
||||
int proplen;
|
||||
|
||||
addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
|
||||
addrs = get_property(node, "assigned-addresses", &proplen);
|
||||
if (!addrs)
|
||||
return;
|
||||
DBG(" parse addresses (%d bytes) @ %p\n", proplen, addrs);
|
||||
|
@ -418,7 +382,7 @@ void __devinit of_scan_bus(struct device_node *node,
|
|||
struct pci_bus *bus)
|
||||
{
|
||||
struct device_node *child = NULL;
|
||||
u32 *reg;
|
||||
const u32 *reg;
|
||||
int reglen, devfn;
|
||||
struct pci_dev *dev;
|
||||
|
||||
|
@ -426,7 +390,7 @@ void __devinit of_scan_bus(struct device_node *node,
|
|||
|
||||
while ((child = of_get_next_child(node, child)) != NULL) {
|
||||
DBG(" * %s\n", child->full_name);
|
||||
reg = (u32 *) get_property(child, "reg", ®len);
|
||||
reg = get_property(child, "reg", ®len);
|
||||
if (reg == NULL || reglen < 20)
|
||||
continue;
|
||||
devfn = (reg[0] >> 8) & 0xff;
|
||||
|
@ -450,7 +414,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
|
|||
struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
u32 *busrange, *ranges;
|
||||
const u32 *busrange, *ranges;
|
||||
int len, i, mode;
|
||||
struct resource *res;
|
||||
unsigned int flags;
|
||||
|
@ -459,13 +423,13 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
|
|||
DBG("of_scan_pci_bridge(%s)\n", node->full_name);
|
||||
|
||||
/* parse bus-range property */
|
||||
busrange = (u32 *) get_property(node, "bus-range", &len);
|
||||
busrange = get_property(node, "bus-range", &len);
|
||||
if (busrange == NULL || len != 8) {
|
||||
printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
|
||||
node->full_name);
|
||||
return;
|
||||
}
|
||||
ranges = (u32 *) get_property(node, "ranges", &len);
|
||||
ranges = get_property(node, "ranges", &len);
|
||||
if (ranges == NULL) {
|
||||
printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
|
||||
node->full_name);
|
||||
|
@ -929,13 +893,13 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
|
|||
unsigned int size;
|
||||
};
|
||||
|
||||
struct isa_range *range;
|
||||
const struct isa_range *range;
|
||||
unsigned long pci_addr;
|
||||
unsigned int isa_addr;
|
||||
unsigned int size;
|
||||
int rlen = 0;
|
||||
|
||||
range = (struct isa_range *) get_property(isa_node, "ranges", &rlen);
|
||||
range = get_property(isa_node, "ranges", &rlen);
|
||||
if (range == NULL || (rlen < sizeof(struct isa_range))) {
|
||||
printk(KERN_ERR "no ISA ranges or unexpected isa range size,"
|
||||
"mapping 64k\n");
|
||||
|
@ -976,7 +940,8 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
|
|||
void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
||||
struct device_node *dev, int prim)
|
||||
{
|
||||
unsigned int *ranges, pci_space;
|
||||
const unsigned int *ranges;
|
||||
unsigned int pci_space;
|
||||
unsigned long size;
|
||||
int rlen = 0;
|
||||
int memno = 0;
|
||||
|
@ -994,7 +959,7 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
|
|||
* (size depending on dev->n_addr_cells)
|
||||
* cells 4+5 or 5+6: the size of the range
|
||||
*/
|
||||
ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
|
||||
ranges = get_property(dev, "ranges", &rlen);
|
||||
if (ranges == NULL)
|
||||
return;
|
||||
hose->io_base_phys = 0;
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
|
||||
{
|
||||
struct pci_controller *phb = data;
|
||||
int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
|
||||
u32 *regs;
|
||||
const int *type = get_property(dn, "ibm,pci-config-space-type", NULL);
|
||||
const u32 *regs;
|
||||
struct pci_dn *pdn;
|
||||
|
||||
if (mem_init_done)
|
||||
|
@ -54,14 +54,14 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
|
|||
dn->data = pdn;
|
||||
pdn->node = dn;
|
||||
pdn->phb = phb;
|
||||
regs = (u32 *)get_property(dn, "reg", NULL);
|
||||
regs = get_property(dn, "reg", NULL);
|
||||
if (regs) {
|
||||
/* First register entry is addr (00BBSS00) */
|
||||
pdn->busno = (regs[0] >> 16) & 0xff;
|
||||
pdn->devfn = (regs[0] >> 8) & 0xff;
|
||||
}
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
|
||||
u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL);
|
||||
const u32 *busp = get_property(dn, "linux,subbus", NULL);
|
||||
if (busp)
|
||||
pdn->bussubno = *busp;
|
||||
}
|
||||
|
@ -96,10 +96,11 @@ void *traverse_pci_devices(struct device_node *start, traverse_func pre,
|
|||
|
||||
/* We started with a phb, iterate all childs */
|
||||
for (dn = start->child; dn; dn = nextdn) {
|
||||
u32 *classp, class;
|
||||
const u32 *classp;
|
||||
u32 class;
|
||||
|
||||
nextdn = NULL;
|
||||
classp = (u32 *)get_property(dn, "class-code", NULL);
|
||||
classp = get_property(dn, "class-code", NULL);
|
||||
class = classp ? *classp : 0;
|
||||
|
||||
if (pre && ((ret = pre(dn, data)) != NULL))
|
||||
|
|
|
@ -91,25 +91,10 @@ EXPORT_SYMBOL(__copy_tofrom_user);
|
|||
EXPORT_SYMBOL(__clear_user);
|
||||
EXPORT_SYMBOL(__strncpy_from_user);
|
||||
EXPORT_SYMBOL(__strnlen_user);
|
||||
|
||||
#ifndef __powerpc64__
|
||||
EXPORT_SYMBOL(__ide_mm_insl);
|
||||
EXPORT_SYMBOL(__ide_mm_outsw);
|
||||
EXPORT_SYMBOL(__ide_mm_insw);
|
||||
EXPORT_SYMBOL(__ide_mm_outsl);
|
||||
#ifdef CONFIG_PPC64
|
||||
EXPORT_SYMBOL(copy_4K_page);
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(_insb);
|
||||
EXPORT_SYMBOL(_outsb);
|
||||
EXPORT_SYMBOL(_insw);
|
||||
EXPORT_SYMBOL(_outsw);
|
||||
EXPORT_SYMBOL(_insl);
|
||||
EXPORT_SYMBOL(_outsl);
|
||||
EXPORT_SYMBOL(_insw_ns);
|
||||
EXPORT_SYMBOL(_outsw_ns);
|
||||
EXPORT_SYMBOL(_insl_ns);
|
||||
EXPORT_SYMBOL(_outsl_ns);
|
||||
|
||||
#if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE))
|
||||
EXPORT_SYMBOL(ppc_ide_md);
|
||||
#endif
|
||||
|
|
|
@ -757,24 +757,9 @@ static int __init early_init_dt_scan_root(unsigned long node,
|
|||
static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
|
||||
{
|
||||
cell_t *p = *cellp;
|
||||
unsigned long r;
|
||||
|
||||
/* Ignore more than 2 cells */
|
||||
while (s > sizeof(unsigned long) / 4) {
|
||||
p++;
|
||||
s--;
|
||||
}
|
||||
r = *p++;
|
||||
#ifdef CONFIG_PPC64
|
||||
if (s > 1) {
|
||||
r <<= 32;
|
||||
r |= *(p++);
|
||||
s--;
|
||||
}
|
||||
#endif
|
||||
|
||||
*cellp = p;
|
||||
return r;
|
||||
*cellp = p + s;
|
||||
return of_read_ulong(p, s);
|
||||
}
|
||||
|
||||
|
||||
|
@ -942,11 +927,11 @@ void __init early_init_devtree(void *params)
|
|||
int
|
||||
prom_n_addr_cells(struct device_node* np)
|
||||
{
|
||||
int* ip;
|
||||
const int *ip;
|
||||
do {
|
||||
if (np->parent)
|
||||
np = np->parent;
|
||||
ip = (int *) get_property(np, "#address-cells", NULL);
|
||||
ip = get_property(np, "#address-cells", NULL);
|
||||
if (ip != NULL)
|
||||
return *ip;
|
||||
} while (np->parent);
|
||||
|
@ -958,11 +943,11 @@ EXPORT_SYMBOL(prom_n_addr_cells);
|
|||
int
|
||||
prom_n_size_cells(struct device_node* np)
|
||||
{
|
||||
int* ip;
|
||||
const int* ip;
|
||||
do {
|
||||
if (np->parent)
|
||||
np = np->parent;
|
||||
ip = (int *) get_property(np, "#size-cells", NULL);
|
||||
ip = get_property(np, "#size-cells", NULL);
|
||||
if (ip != NULL)
|
||||
return *ip;
|
||||
} while (np->parent);
|
||||
|
@ -1034,7 +1019,7 @@ int device_is_compatible(struct device_node *device, const char *compat)
|
|||
const char* cp;
|
||||
int cplen, l;
|
||||
|
||||
cp = (char *) get_property(device, "compatible", &cplen);
|
||||
cp = get_property(device, "compatible", &cplen);
|
||||
if (cp == NULL)
|
||||
return 0;
|
||||
while (cplen > 0) {
|
||||
|
@ -1449,7 +1434,7 @@ static int of_finish_dynamic_node(struct device_node *node)
|
|||
{
|
||||
struct device_node *parent = of_get_parent(node);
|
||||
int err = 0;
|
||||
phandle *ibm_phandle;
|
||||
const phandle *ibm_phandle;
|
||||
|
||||
node->name = get_property(node, "name", NULL);
|
||||
node->type = get_property(node, "device_type", NULL);
|
||||
|
@ -1466,8 +1451,7 @@ static int of_finish_dynamic_node(struct device_node *node)
|
|||
return -ENODEV;
|
||||
|
||||
/* fix up new node's linux_phandle field */
|
||||
if ((ibm_phandle = (unsigned int *)get_property(node,
|
||||
"ibm,phandle", NULL)))
|
||||
if ((ibm_phandle = get_property(node, "ibm,phandle", NULL)))
|
||||
node->linux_phandle = *ibm_phandle;
|
||||
|
||||
out:
|
||||
|
@ -1528,7 +1512,7 @@ struct property *of_find_property(struct device_node *np, const char *name,
|
|||
* Find a property with a given name for a given node
|
||||
* and return the value.
|
||||
*/
|
||||
void *get_property(struct device_node *np, const char *name, int *lenp)
|
||||
const void *get_property(struct device_node *np, const char *name, int *lenp)
|
||||
{
|
||||
struct property *pp = of_find_property(np,name,lenp);
|
||||
return pp ? pp->value : NULL;
|
||||
|
@ -1658,16 +1642,16 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
|
|||
hardid = get_hard_smp_processor_id(cpu);
|
||||
|
||||
for_each_node_by_type(np, "cpu") {
|
||||
u32 *intserv;
|
||||
const u32 *intserv;
|
||||
unsigned int plen, t;
|
||||
|
||||
/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
|
||||
* fallback to "reg" property and assume no threads
|
||||
*/
|
||||
intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s",
|
||||
&plen);
|
||||
intserv = get_property(np, "ibm,ppc-interrupt-server#s",
|
||||
&plen);
|
||||
if (intserv == NULL) {
|
||||
u32 *reg = (u32 *)get_property(np, "reg", NULL);
|
||||
const u32 *reg = get_property(np, "reg", NULL);
|
||||
if (reg == NULL)
|
||||
continue;
|
||||
if (*reg == hardid) {
|
||||
|
|
|
@ -2033,16 +2033,22 @@ static void __init fixup_device_tree_maple(void)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_CHRP
|
||||
/* Pegasos lacks the "ranges" property in the isa node */
|
||||
/* Pegasos and BriQ lacks the "ranges" property in the isa node */
|
||||
static void __init fixup_device_tree_chrp(void)
|
||||
{
|
||||
phandle isa;
|
||||
u32 isa_ranges[6];
|
||||
u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
|
||||
char *name;
|
||||
int rc;
|
||||
|
||||
name = "/pci@80000000/isa@c";
|
||||
isa = call_prom("finddevice", 1, 1, ADDR(name));
|
||||
if (!PHANDLE_VALID(isa)) {
|
||||
name = "/pci@ff500000/isa@6";
|
||||
isa = call_prom("finddevice", 1, 1, ADDR(name));
|
||||
rloc = 0x01003000; /* IO space; PCI device = 6 */
|
||||
}
|
||||
if (!PHANDLE_VALID(isa))
|
||||
return;
|
||||
|
||||
|
@ -2054,7 +2060,7 @@ static void __init fixup_device_tree_chrp(void)
|
|||
|
||||
isa_ranges[0] = 0x1;
|
||||
isa_ranges[1] = 0x0;
|
||||
isa_ranges[2] = 0x01006000;
|
||||
isa_ranges[2] = rloc;
|
||||
isa_ranges[3] = 0x0;
|
||||
isa_ranges[4] = 0x0;
|
||||
isa_ranges[5] = 0x00010000;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
/* Debug utility */
|
||||
#ifdef DEBUG
|
||||
static void of_dump_addr(const char *s, u32 *addr, int na)
|
||||
static void of_dump_addr(const char *s, const u32 *addr, int na)
|
||||
{
|
||||
printk("%s", s);
|
||||
while(na--)
|
||||
|
@ -35,7 +35,7 @@ static void of_dump_addr(const char *s, u32 *addr, int na)
|
|||
printk("\n");
|
||||
}
|
||||
#else
|
||||
static void of_dump_addr(const char *s, u32 *addr, int na) { }
|
||||
static void of_dump_addr(const char *s, const u32 *addr, int na) { }
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -46,9 +46,10 @@ struct of_bus {
|
|||
int (*match)(struct device_node *parent);
|
||||
void (*count_cells)(struct device_node *child,
|
||||
int *addrc, int *sizec);
|
||||
u64 (*map)(u32 *addr, u32 *range, int na, int ns, int pna);
|
||||
u64 (*map)(u32 *addr, const u32 *range,
|
||||
int na, int ns, int pna);
|
||||
int (*translate)(u32 *addr, u64 offset, int na);
|
||||
unsigned int (*get_flags)(u32 *addr);
|
||||
unsigned int (*get_flags)(const u32 *addr);
|
||||
};
|
||||
|
||||
|
||||
|
@ -65,7 +66,8 @@ static void of_bus_default_count_cells(struct device_node *dev,
|
|||
*sizec = prom_n_size_cells(dev);
|
||||
}
|
||||
|
||||
static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna)
|
||||
static u64 of_bus_default_map(u32 *addr, const u32 *range,
|
||||
int na, int ns, int pna)
|
||||
{
|
||||
u64 cp, s, da;
|
||||
|
||||
|
@ -93,7 +95,7 @@ static int of_bus_default_translate(u32 *addr, u64 offset, int na)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int of_bus_default_get_flags(u32 *addr)
|
||||
static unsigned int of_bus_default_get_flags(const u32 *addr)
|
||||
{
|
||||
return IORESOURCE_MEM;
|
||||
}
|
||||
|
@ -118,7 +120,7 @@ static void of_bus_pci_count_cells(struct device_node *np,
|
|||
*sizec = 2;
|
||||
}
|
||||
|
||||
static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna)
|
||||
static u64 of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
|
||||
{
|
||||
u64 cp, s, da;
|
||||
|
||||
|
@ -143,7 +145,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
|
|||
return of_bus_default_translate(addr + 1, offset, na - 1);
|
||||
}
|
||||
|
||||
static unsigned int of_bus_pci_get_flags(u32 *addr)
|
||||
static unsigned int of_bus_pci_get_flags(const u32 *addr)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
u32 w = addr[0];
|
||||
|
@ -178,7 +180,7 @@ static void of_bus_isa_count_cells(struct device_node *child,
|
|||
*sizec = 1;
|
||||
}
|
||||
|
||||
static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna)
|
||||
static u64 of_bus_isa_map(u32 *addr, const u32 *range, int na, int ns, int pna)
|
||||
{
|
||||
u64 cp, s, da;
|
||||
|
||||
|
@ -203,7 +205,7 @@ static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
|
|||
return of_bus_default_translate(addr + 1, offset, na - 1);
|
||||
}
|
||||
|
||||
static unsigned int of_bus_isa_get_flags(u32 *addr)
|
||||
static unsigned int of_bus_isa_get_flags(const u32 *addr)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
u32 w = addr[0];
|
||||
|
@ -268,7 +270,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
|
|||
struct of_bus *pbus, u32 *addr,
|
||||
int na, int ns, int pna)
|
||||
{
|
||||
u32 *ranges;
|
||||
const u32 *ranges;
|
||||
unsigned int rlen;
|
||||
int rone;
|
||||
u64 offset = OF_BAD_ADDR;
|
||||
|
@ -285,7 +287,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
|
|||
* to translate addresses that aren't supposed to be translated in
|
||||
* the first place. --BenH.
|
||||
*/
|
||||
ranges = (u32 *)get_property(parent, "ranges", &rlen);
|
||||
ranges = get_property(parent, "ranges", &rlen);
|
||||
if (ranges == NULL || rlen == 0) {
|
||||
offset = of_read_number(addr, na);
|
||||
memset(addr, 0, pna * 4);
|
||||
|
@ -328,7 +330,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
|
|||
* that can be mapped to a cpu physical address). This is not really specified
|
||||
* that way, but this is traditionally the way IBM at least do things
|
||||
*/
|
||||
u64 of_translate_address(struct device_node *dev, u32 *in_addr)
|
||||
u64 of_translate_address(struct device_node *dev, const u32 *in_addr)
|
||||
{
|
||||
struct device_node *parent = NULL;
|
||||
struct of_bus *bus, *pbus;
|
||||
|
@ -405,10 +407,10 @@ u64 of_translate_address(struct device_node *dev, u32 *in_addr)
|
|||
}
|
||||
EXPORT_SYMBOL(of_translate_address);
|
||||
|
||||
u32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
||||
const u32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
||||
unsigned int *flags)
|
||||
{
|
||||
u32 *prop;
|
||||
const u32 *prop;
|
||||
unsigned int psize;
|
||||
struct device_node *parent;
|
||||
struct of_bus *bus;
|
||||
|
@ -425,7 +427,7 @@ u32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
|||
return NULL;
|
||||
|
||||
/* Get "reg" or "assigned-addresses" property */
|
||||
prop = (u32 *)get_property(dev, bus->addresses, &psize);
|
||||
prop = get_property(dev, bus->addresses, &psize);
|
||||
if (prop == NULL)
|
||||
return NULL;
|
||||
psize /= 4;
|
||||
|
@ -443,10 +445,10 @@ u32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
|||
}
|
||||
EXPORT_SYMBOL(of_get_address);
|
||||
|
||||
u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
|
||||
const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
|
||||
unsigned int *flags)
|
||||
{
|
||||
u32 *prop;
|
||||
const u32 *prop;
|
||||
unsigned int psize;
|
||||
struct device_node *parent;
|
||||
struct of_bus *bus;
|
||||
|
@ -467,7 +469,7 @@ u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
|
|||
return NULL;
|
||||
|
||||
/* Get "reg" or "assigned-addresses" property */
|
||||
prop = (u32 *)get_property(dev, bus->addresses, &psize);
|
||||
prop = get_property(dev, bus->addresses, &psize);
|
||||
if (prop == NULL)
|
||||
return NULL;
|
||||
psize /= 4;
|
||||
|
@ -485,7 +487,7 @@ u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
|
|||
}
|
||||
EXPORT_SYMBOL(of_get_pci_address);
|
||||
|
||||
static int __of_address_to_resource(struct device_node *dev, u32 *addrp,
|
||||
static int __of_address_to_resource(struct device_node *dev, const u32 *addrp,
|
||||
u64 size, unsigned int flags,
|
||||
struct resource *r)
|
||||
{
|
||||
|
@ -516,7 +518,7 @@ static int __of_address_to_resource(struct device_node *dev, u32 *addrp,
|
|||
int of_address_to_resource(struct device_node *dev, int index,
|
||||
struct resource *r)
|
||||
{
|
||||
u32 *addrp;
|
||||
const u32 *addrp;
|
||||
u64 size;
|
||||
unsigned int flags;
|
||||
|
||||
|
@ -530,7 +532,7 @@ EXPORT_SYMBOL_GPL(of_address_to_resource);
|
|||
int of_pci_address_to_resource(struct device_node *dev, int bar,
|
||||
struct resource *r)
|
||||
{
|
||||
u32 *addrp;
|
||||
const u32 *addrp;
|
||||
u64 size;
|
||||
unsigned int flags;
|
||||
|
||||
|
@ -541,13 +543,14 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
|
||||
|
||||
void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop,
|
||||
void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
|
||||
unsigned long *busno, unsigned long *phys, unsigned long *size)
|
||||
{
|
||||
u32 *dma_window, cells;
|
||||
unsigned char *prop;
|
||||
const u32 *dma_window;
|
||||
u32 cells;
|
||||
const unsigned char *prop;
|
||||
|
||||
dma_window = (u32 *)dma_window_prop;
|
||||
dma_window = dma_window_prop;
|
||||
|
||||
/* busno is always one cell */
|
||||
*busno = *(dma_window++);
|
||||
|
@ -576,13 +579,13 @@ static struct device_node *of_irq_dflt_pic;
|
|||
static struct device_node *of_irq_find_parent(struct device_node *child)
|
||||
{
|
||||
struct device_node *p;
|
||||
phandle *parp;
|
||||
const phandle *parp;
|
||||
|
||||
if (!of_node_get(child))
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
parp = (phandle *)get_property(child, "interrupt-parent", NULL);
|
||||
parp = get_property(child, "interrupt-parent", NULL);
|
||||
if (parp == NULL)
|
||||
p = of_get_parent(child);
|
||||
else {
|
||||
|
@ -639,11 +642,11 @@ void of_irq_map_init(unsigned int flags)
|
|||
|
||||
}
|
||||
|
||||
int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
||||
u32 *addr, struct of_irq *out_irq)
|
||||
int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
|
||||
const u32 *addr, struct of_irq *out_irq)
|
||||
{
|
||||
struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
|
||||
u32 *tmp, *imap, *imask;
|
||||
const u32 *tmp, *imap, *imask;
|
||||
u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
|
||||
int imaplen, match, i;
|
||||
|
||||
|
@ -657,7 +660,7 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
|||
* is none, we are nice and just walk up the tree
|
||||
*/
|
||||
do {
|
||||
tmp = (u32 *)get_property(ipar, "#interrupt-cells", NULL);
|
||||
tmp = get_property(ipar, "#interrupt-cells", NULL);
|
||||
if (tmp != NULL) {
|
||||
intsize = *tmp;
|
||||
break;
|
||||
|
@ -681,7 +684,7 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
|||
*/
|
||||
old = of_node_get(ipar);
|
||||
do {
|
||||
tmp = (u32 *)get_property(old, "#address-cells", NULL);
|
||||
tmp = get_property(old, "#address-cells", NULL);
|
||||
tnode = of_get_parent(old);
|
||||
of_node_put(old);
|
||||
old = tnode;
|
||||
|
@ -708,7 +711,7 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
|||
}
|
||||
|
||||
/* Now look for an interrupt-map */
|
||||
imap = (u32 *)get_property(ipar, "interrupt-map", &imaplen);
|
||||
imap = get_property(ipar, "interrupt-map", &imaplen);
|
||||
/* No interrupt map, check for an interrupt parent */
|
||||
if (imap == NULL) {
|
||||
DBG(" -> no map, getting parent\n");
|
||||
|
@ -718,7 +721,7 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
|||
imaplen /= sizeof(u32);
|
||||
|
||||
/* Look for a mask */
|
||||
imask = (u32 *)get_property(ipar, "interrupt-map-mask", NULL);
|
||||
imask = get_property(ipar, "interrupt-map-mask", NULL);
|
||||
|
||||
/* If we were passed no "reg" property and we attempt to parse
|
||||
* an interrupt-map, then #address-cells must be 0.
|
||||
|
@ -765,14 +768,14 @@ int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 ointsize,
|
|||
/* Get #interrupt-cells and #address-cells of new
|
||||
* parent
|
||||
*/
|
||||
tmp = (u32 *)get_property(newpar, "#interrupt-cells",
|
||||
tmp = get_property(newpar, "#interrupt-cells",
|
||||
NULL);
|
||||
if (tmp == NULL) {
|
||||
DBG(" -> parent lacks #interrupt-cells !\n");
|
||||
goto fail;
|
||||
}
|
||||
newintsize = *tmp;
|
||||
tmp = (u32 *)get_property(newpar, "#address-cells",
|
||||
tmp = get_property(newpar, "#address-cells",
|
||||
NULL);
|
||||
newaddrsize = (tmp == NULL) ? 0 : *tmp;
|
||||
|
||||
|
@ -818,14 +821,14 @@ EXPORT_SYMBOL_GPL(of_irq_map_raw);
|
|||
static int of_irq_map_oldworld(struct device_node *device, int index,
|
||||
struct of_irq *out_irq)
|
||||
{
|
||||
u32 *ints;
|
||||
const u32 *ints;
|
||||
int intlen;
|
||||
|
||||
/*
|
||||
* Old machines just have a list of interrupt numbers
|
||||
* and no interrupt-controller nodes.
|
||||
*/
|
||||
ints = (u32 *) get_property(device, "AAPL,interrupts", &intlen);
|
||||
ints = get_property(device, "AAPL,interrupts", &intlen);
|
||||
if (ints == NULL)
|
||||
return -EINVAL;
|
||||
intlen /= sizeof(u32);
|
||||
|
@ -850,7 +853,8 @@ static int of_irq_map_oldworld(struct device_node *device, int index,
|
|||
int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
|
||||
{
|
||||
struct device_node *p;
|
||||
u32 *intspec, *tmp, intsize, intlen, *addr;
|
||||
const u32 *intspec, *tmp, *addr;
|
||||
u32 intsize, intlen;
|
||||
int res;
|
||||
|
||||
DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
|
||||
|
@ -860,13 +864,13 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
|
|||
return of_irq_map_oldworld(device, index, out_irq);
|
||||
|
||||
/* Get the interrupts property */
|
||||
intspec = (u32 *)get_property(device, "interrupts", &intlen);
|
||||
intspec = get_property(device, "interrupts", &intlen);
|
||||
if (intspec == NULL)
|
||||
return -EINVAL;
|
||||
intlen /= sizeof(u32);
|
||||
|
||||
/* Get the reg property (if any) */
|
||||
addr = (u32 *)get_property(device, "reg", NULL);
|
||||
addr = get_property(device, "reg", NULL);
|
||||
|
||||
/* Look for the interrupt parent. */
|
||||
p = of_irq_find_parent(device);
|
||||
|
@ -874,7 +878,7 @@ int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq
|
|||
return -EINVAL;
|
||||
|
||||
/* Get size of interrupt specifier */
|
||||
tmp = (u32 *)get_property(p, "#interrupt-cells", NULL);
|
||||
tmp = get_property(p, "#interrupt-cells", NULL);
|
||||
if (tmp == NULL) {
|
||||
of_node_put(p);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -246,12 +246,12 @@ struct file_operations ppc_rtas_rmo_buf_ops = {
|
|||
|
||||
static int ppc_rtas_find_all_sensors(void);
|
||||
static void ppc_rtas_process_sensor(struct seq_file *m,
|
||||
struct individual_sensor *s, int state, int error, char *loc);
|
||||
struct individual_sensor *s, int state, int error, const char *loc);
|
||||
static char *ppc_rtas_process_error(int error);
|
||||
static void get_location_code(struct seq_file *m,
|
||||
struct individual_sensor *s, char *loc);
|
||||
static void check_location_string(struct seq_file *m, char *c);
|
||||
static void check_location(struct seq_file *m, char *c);
|
||||
struct individual_sensor *s, const char *loc);
|
||||
static void check_location_string(struct seq_file *m, const char *c);
|
||||
static void check_location(struct seq_file *m, const char *c);
|
||||
|
||||
static int __init proc_rtas_init(void)
|
||||
{
|
||||
|
@ -446,11 +446,11 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
|
|||
for (i=0; i<sensors.quant; i++) {
|
||||
struct individual_sensor *p = &sensors.sensor[i];
|
||||
char rstr[64];
|
||||
char *loc;
|
||||
const char *loc;
|
||||
int llen, offs;
|
||||
|
||||
sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
|
||||
loc = (char *) get_property(rtas_node, rstr, &llen);
|
||||
loc = get_property(rtas_node, rstr, &llen);
|
||||
|
||||
/* A sensor may have multiple instances */
|
||||
for (j = 0, offs = 0; j <= p->quant; j++) {
|
||||
|
@ -474,10 +474,10 @@ static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
|
|||
|
||||
static int ppc_rtas_find_all_sensors(void)
|
||||
{
|
||||
unsigned int *utmp;
|
||||
const unsigned int *utmp;
|
||||
int len, i;
|
||||
|
||||
utmp = (unsigned int *) get_property(rtas_node, "rtas-sensors", &len);
|
||||
utmp = get_property(rtas_node, "rtas-sensors", &len);
|
||||
if (utmp == NULL) {
|
||||
printk (KERN_ERR "error: could not get rtas-sensors\n");
|
||||
return 1;
|
||||
|
@ -530,7 +530,7 @@ static char *ppc_rtas_process_error(int error)
|
|||
*/
|
||||
|
||||
static void ppc_rtas_process_sensor(struct seq_file *m,
|
||||
struct individual_sensor *s, int state, int error, char *loc)
|
||||
struct individual_sensor *s, int state, int error, const char *loc)
|
||||
{
|
||||
/* Defined return vales */
|
||||
const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t",
|
||||
|
@ -682,7 +682,7 @@ static void ppc_rtas_process_sensor(struct seq_file *m,
|
|||
|
||||
/* ****************************************************************** */
|
||||
|
||||
static void check_location(struct seq_file *m, char *c)
|
||||
static void check_location(struct seq_file *m, const char *c)
|
||||
{
|
||||
switch (c[0]) {
|
||||
case LOC_PLANAR:
|
||||
|
@ -719,7 +719,7 @@ static void check_location(struct seq_file *m, char *c)
|
|||
* ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
|
||||
* the '.' may be an abbrevation
|
||||
*/
|
||||
static void check_location_string(struct seq_file *m, char *c)
|
||||
static void check_location_string(struct seq_file *m, const char *c)
|
||||
{
|
||||
while (*c) {
|
||||
if (isalpha(*c) || *c == '.')
|
||||
|
@ -733,7 +733,8 @@ static void check_location_string(struct seq_file *m, char *c)
|
|||
|
||||
/* ****************************************************************** */
|
||||
|
||||
static void get_location_code(struct seq_file *m, struct individual_sensor *s, char *loc)
|
||||
static void get_location_code(struct seq_file *m, struct individual_sensor *s,
|
||||
const char *loc)
|
||||
{
|
||||
if (!loc || !*loc) {
|
||||
seq_printf(m, "---");/* does not have a location */
|
||||
|
|
|
@ -177,10 +177,12 @@ void __init udbg_init_rtas_console(void)
|
|||
void rtas_progress(char *s, unsigned short hex)
|
||||
{
|
||||
struct device_node *root;
|
||||
int width, *p;
|
||||
int width;
|
||||
const int *p;
|
||||
char *os;
|
||||
static int display_character, set_indicator;
|
||||
static int display_width, display_lines, *row_width, form_feed;
|
||||
static int display_width, display_lines, form_feed;
|
||||
const static int *row_width;
|
||||
static DEFINE_SPINLOCK(progress_lock);
|
||||
static int current_line;
|
||||
static int pending_newline = 0; /* did last write end with unprinted newline? */
|
||||
|
@ -191,16 +193,16 @@ void rtas_progress(char *s, unsigned short hex)
|
|||
if (display_width == 0) {
|
||||
display_width = 0x10;
|
||||
if ((root = find_path_device("/rtas"))) {
|
||||
if ((p = (unsigned int *)get_property(root,
|
||||
if ((p = get_property(root,
|
||||
"ibm,display-line-length", NULL)))
|
||||
display_width = *p;
|
||||
if ((p = (unsigned int *)get_property(root,
|
||||
if ((p = get_property(root,
|
||||
"ibm,form-feed", NULL)))
|
||||
form_feed = *p;
|
||||
if ((p = (unsigned int *)get_property(root,
|
||||
if ((p = get_property(root,
|
||||
"ibm,display-number-of-lines", NULL)))
|
||||
display_lines = *p;
|
||||
row_width = (unsigned int *)get_property(root,
|
||||
row_width = get_property(root,
|
||||
"ibm,display-truncation-length", NULL);
|
||||
}
|
||||
display_character = rtas_token("display-character");
|
||||
|
@ -293,10 +295,10 @@ EXPORT_SYMBOL(rtas_progress); /* needed by rtas_flash module */
|
|||
|
||||
int rtas_token(const char *service)
|
||||
{
|
||||
int *tokp;
|
||||
const int *tokp;
|
||||
if (rtas.dev == NULL)
|
||||
return RTAS_UNKNOWN_SERVICE;
|
||||
tokp = (int *) get_property(rtas.dev, service, NULL);
|
||||
tokp = get_property(rtas.dev, service, NULL);
|
||||
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
|
||||
}
|
||||
EXPORT_SYMBOL(rtas_token);
|
||||
|
@ -626,6 +628,9 @@ void rtas_os_term(char *str)
|
|||
{
|
||||
int status;
|
||||
|
||||
if (panic_timeout)
|
||||
return;
|
||||
|
||||
if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
|
||||
return;
|
||||
|
||||
|
@ -687,15 +692,14 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
|
|||
int i;
|
||||
long state;
|
||||
long rc;
|
||||
unsigned long dummy;
|
||||
|
||||
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
||||
struct rtas_suspend_me_data data;
|
||||
|
||||
/* Make sure the state is valid */
|
||||
rc = plpar_hcall(H_VASI_STATE,
|
||||
((u64)args->args[0] << 32) | args->args[1],
|
||||
0, 0, 0,
|
||||
&state, &dummy, &dummy);
|
||||
rc = plpar_hcall(H_VASI_STATE, retbuf,
|
||||
((u64)args->args[0] << 32) | args->args[1]);
|
||||
|
||||
state = retbuf[0];
|
||||
|
||||
if (rc) {
|
||||
printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
|
||||
|
@ -845,15 +849,15 @@ void __init rtas_initialize(void)
|
|||
*/
|
||||
rtas.dev = of_find_node_by_name(NULL, "rtas");
|
||||
if (rtas.dev) {
|
||||
u32 *basep, *entryp;
|
||||
u32 *sizep;
|
||||
const u32 *basep, *entryp, *sizep;
|
||||
|
||||
basep = (u32 *)get_property(rtas.dev, "linux,rtas-base", NULL);
|
||||
sizep = (u32 *)get_property(rtas.dev, "rtas-size", NULL);
|
||||
basep = get_property(rtas.dev, "linux,rtas-base", NULL);
|
||||
sizep = get_property(rtas.dev, "rtas-size", NULL);
|
||||
if (basep != NULL && sizep != NULL) {
|
||||
rtas.base = *basep;
|
||||
rtas.size = *sizep;
|
||||
entryp = (u32 *)get_property(rtas.dev, "linux,rtas-entry", NULL);
|
||||
entryp = get_property(rtas.dev,
|
||||
"linux,rtas-entry", NULL);
|
||||
if (entryp == NULL) /* Ugh */
|
||||
rtas.entry = rtas.base;
|
||||
else
|
||||
|
@ -909,6 +913,11 @@ int __init early_init_dt_scan_rtas(unsigned long node,
|
|||
basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
|
||||
if (basep)
|
||||
rtas_getchar_token = *basep;
|
||||
|
||||
if (rtas_putchar_token != RTAS_UNKNOWN_SERVICE &&
|
||||
rtas_getchar_token != RTAS_UNKNOWN_SERVICE)
|
||||
udbg_init_rtas_console();
|
||||
|
||||
#endif
|
||||
|
||||
/* break now */
|
||||
|
|
|
@ -57,7 +57,7 @@ static inline int config_access_valid(struct pci_dn *dn, int where)
|
|||
|
||||
static int of_device_available(struct device_node * dn)
|
||||
{
|
||||
char * status;
|
||||
const char *status;
|
||||
|
||||
status = get_property(dn, "status", NULL);
|
||||
|
||||
|
@ -81,8 +81,7 @@ int rtas_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
|
|||
if (!config_access_valid(pdn, where))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
|
||||
(pdn->devfn << 8) | (where & 0xff);
|
||||
addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
|
||||
buid = pdn->phb->buid;
|
||||
if (buid) {
|
||||
ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
|
||||
|
@ -134,8 +133,7 @@ int rtas_write_config(struct pci_dn *pdn, int where, int size, u32 val)
|
|||
if (!config_access_valid(pdn, where))
|
||||
return PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
|
||||
addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
|
||||
(pdn->devfn << 8) | (where & 0xff);
|
||||
addr = rtas_config_addr(pdn->busno, pdn->devfn, where);
|
||||
buid = pdn->phb->buid;
|
||||
if (buid) {
|
||||
ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr,
|
||||
|
@ -178,7 +176,7 @@ struct pci_ops rtas_pci_ops = {
|
|||
|
||||
int is_python(struct device_node *dev)
|
||||
{
|
||||
char *model = (char *)get_property(dev, "model", NULL);
|
||||
const char *model = get_property(dev, "model", NULL);
|
||||
|
||||
if (model && strstr(model, "Python"))
|
||||
return 1;
|
||||
|
@ -234,7 +232,7 @@ void __init init_pci_config_tokens (void)
|
|||
unsigned long __devinit get_phb_buid (struct device_node *phb)
|
||||
{
|
||||
int addr_cells;
|
||||
unsigned int *buid_vals;
|
||||
const unsigned int *buid_vals;
|
||||
unsigned int len;
|
||||
unsigned long buid;
|
||||
|
||||
|
@ -247,7 +245,7 @@ unsigned long __devinit get_phb_buid (struct device_node *phb)
|
|||
if (phb->parent->parent)
|
||||
return 0;
|
||||
|
||||
buid_vals = (unsigned int *) get_property(phb, "reg", &len);
|
||||
buid_vals = get_property(phb, "reg", &len);
|
||||
if (buid_vals == NULL)
|
||||
return 0;
|
||||
|
||||
|
@ -264,10 +262,10 @@ unsigned long __devinit get_phb_buid (struct device_node *phb)
|
|||
static int phb_set_bus_ranges(struct device_node *dev,
|
||||
struct pci_controller *phb)
|
||||
{
|
||||
int *bus_range;
|
||||
const int *bus_range;
|
||||
unsigned int len;
|
||||
|
||||
bus_range = (int *) get_property(dev, "bus-range", &len);
|
||||
bus_range = get_property(dev, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -325,15 +323,15 @@ unsigned long __init find_and_init_phbs(void)
|
|||
* in chosen.
|
||||
*/
|
||||
if (of_chosen) {
|
||||
int *prop;
|
||||
const int *prop;
|
||||
|
||||
prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
|
||||
NULL);
|
||||
prop = get_property(of_chosen,
|
||||
"linux,pci-probe-only", NULL);
|
||||
if (prop)
|
||||
pci_probe_only = *prop;
|
||||
|
||||
prop = (int *)get_property(of_chosen,
|
||||
"linux,pci-assign-all-buses", NULL);
|
||||
prop = get_property(of_chosen,
|
||||
"linux,pci-assign-all-buses", NULL);
|
||||
if (prop)
|
||||
pci_assign_all_buses = *prop;
|
||||
}
|
||||
|
|
|
@ -304,19 +304,21 @@ struct seq_operations cpuinfo_op = {
|
|||
void __init check_for_initrd(void)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
unsigned long *prop;
|
||||
const unsigned int *prop;
|
||||
int len;
|
||||
|
||||
DBG(" -> check_for_initrd()\n");
|
||||
|
||||
if (of_chosen) {
|
||||
prop = (unsigned long *)get_property(of_chosen,
|
||||
"linux,initrd-start", NULL);
|
||||
prop = get_property(of_chosen, "linux,initrd-start", &len);
|
||||
if (prop != NULL) {
|
||||
initrd_start = (unsigned long)__va(*prop);
|
||||
prop = (unsigned long *)get_property(of_chosen,
|
||||
"linux,initrd-end", NULL);
|
||||
initrd_start = (unsigned long)
|
||||
__va(of_read_ulong(prop, len / 4));
|
||||
prop = get_property(of_chosen,
|
||||
"linux,initrd-end", &len);
|
||||
if (prop != NULL) {
|
||||
initrd_end = (unsigned long)__va(*prop);
|
||||
initrd_end = (unsigned long)
|
||||
__va(of_read_ulong(prop, len / 4));
|
||||
initrd_below_start_ok = 1;
|
||||
} else
|
||||
initrd_start = 0;
|
||||
|
@ -366,15 +368,14 @@ void __init smp_setup_cpu_maps(void)
|
|||
int cpu = 0;
|
||||
|
||||
while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
|
||||
int *intserv;
|
||||
const int *intserv;
|
||||
int j, len = sizeof(u32), nthreads = 1;
|
||||
|
||||
intserv = (int *)get_property(dn, "ibm,ppc-interrupt-server#s",
|
||||
&len);
|
||||
intserv = get_property(dn, "ibm,ppc-interrupt-server#s", &len);
|
||||
if (intserv)
|
||||
nthreads = len / sizeof(int);
|
||||
else {
|
||||
intserv = (int *) get_property(dn, "reg", NULL);
|
||||
intserv = get_property(dn, "reg", NULL);
|
||||
if (!intserv)
|
||||
intserv = &cpu; /* assume logical == phys */
|
||||
}
|
||||
|
@ -395,13 +396,12 @@ void __init smp_setup_cpu_maps(void)
|
|||
if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) &&
|
||||
(dn = of_find_node_by_path("/rtas"))) {
|
||||
int num_addr_cell, num_size_cell, maxcpus;
|
||||
unsigned int *ireg;
|
||||
const unsigned int *ireg;
|
||||
|
||||
num_addr_cell = prom_n_addr_cells(dn);
|
||||
num_size_cell = prom_n_size_cells(dn);
|
||||
|
||||
ireg = (unsigned int *)
|
||||
get_property(dn, "ibm,lrdr-capacity", NULL);
|
||||
ireg = get_property(dn, "ibm,lrdr-capacity", NULL);
|
||||
|
||||
if (!ireg)
|
||||
goto out;
|
||||
|
@ -444,6 +444,8 @@ void __init smp_setup_cpu_maps(void)
|
|||
|
||||
int __initdata do_early_xmon;
|
||||
#ifdef CONFIG_XMON
|
||||
extern int xmon_no_auto_backtrace;
|
||||
|
||||
static int __init early_xmon(char *p)
|
||||
{
|
||||
/* ensure xmon is enabled */
|
||||
|
@ -452,6 +454,8 @@ static int __init early_xmon(char *p)
|
|||
xmon_init(1);
|
||||
if (strncmp(p, "off", 3) == 0)
|
||||
xmon_init(0);
|
||||
if (strncmp(p, "nobt", 4) == 0)
|
||||
xmon_no_auto_backtrace = 1;
|
||||
if (strncmp(p, "early", 5) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/lmb.h>
|
||||
#include <asm/iseries/it_lp_naca.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/xmon.h>
|
||||
#include <asm/udbg.h>
|
||||
|
@ -79,10 +78,10 @@ u64 ppc64_pft_size;
|
|||
* before we've read this from the device tree.
|
||||
*/
|
||||
struct ppc64_caches ppc64_caches = {
|
||||
.dline_size = 0x80,
|
||||
.log_dline_size = 7,
|
||||
.iline_size = 0x80,
|
||||
.log_iline_size = 7
|
||||
.dline_size = 0x40,
|
||||
.log_dline_size = 6,
|
||||
.iline_size = 0x40,
|
||||
.log_iline_size = 6
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(ppc64_caches);
|
||||
|
||||
|
@ -107,7 +106,7 @@ static int smt_enabled_cmdline;
|
|||
static void check_smt_enabled(void)
|
||||
{
|
||||
struct device_node *dn;
|
||||
char *smt_option;
|
||||
const char *smt_option;
|
||||
|
||||
/* Allow the command line to overrule the OF option */
|
||||
if (smt_enabled_cmdline)
|
||||
|
@ -116,7 +115,7 @@ static void check_smt_enabled(void)
|
|||
dn = of_find_node_by_path("/options");
|
||||
|
||||
if (dn) {
|
||||
smt_option = (char *)get_property(dn, "ibm,smt-enabled", NULL);
|
||||
smt_option = get_property(dn, "ibm,smt-enabled", NULL);
|
||||
|
||||
if (smt_option) {
|
||||
if (!strcmp(smt_option, "on"))
|
||||
|
@ -293,7 +292,7 @@ static void __init initialize_cache_info(void)
|
|||
*/
|
||||
|
||||
if ( num_cpus == 1 ) {
|
||||
u32 *sizep, *lsizep;
|
||||
const u32 *sizep, *lsizep;
|
||||
u32 size, lsize;
|
||||
const char *dc, *ic;
|
||||
|
||||
|
@ -308,10 +307,10 @@ static void __init initialize_cache_info(void)
|
|||
|
||||
size = 0;
|
||||
lsize = cur_cpu_spec->dcache_bsize;
|
||||
sizep = (u32 *)get_property(np, "d-cache-size", NULL);
|
||||
sizep = get_property(np, "d-cache-size", NULL);
|
||||
if (sizep != NULL)
|
||||
size = *sizep;
|
||||
lsizep = (u32 *) get_property(np, dc, NULL);
|
||||
lsizep = get_property(np, dc, NULL);
|
||||
if (lsizep != NULL)
|
||||
lsize = *lsizep;
|
||||
if (sizep == 0 || lsizep == 0)
|
||||
|
@ -325,10 +324,10 @@ static void __init initialize_cache_info(void)
|
|||
|
||||
size = 0;
|
||||
lsize = cur_cpu_spec->icache_bsize;
|
||||
sizep = (u32 *)get_property(np, "i-cache-size", NULL);
|
||||
sizep = get_property(np, "i-cache-size", NULL);
|
||||
if (sizep != NULL)
|
||||
size = *sizep;
|
||||
lsizep = (u32 *)get_property(np, ic, NULL);
|
||||
lsizep = get_property(np, ic, NULL);
|
||||
if (lsizep != NULL)
|
||||
lsize = *lsizep;
|
||||
if (sizep == 0 || lsizep == 0)
|
||||
|
|
|
@ -60,7 +60,7 @@ static int smt_snooze_cmdline;
|
|||
static int __init smt_setup(void)
|
||||
{
|
||||
struct device_node *options;
|
||||
unsigned int *val;
|
||||
const unsigned int *val;
|
||||
unsigned int cpu;
|
||||
|
||||
if (!cpu_has_feature(CPU_FTR_SMT))
|
||||
|
@ -70,8 +70,7 @@ static int __init smt_setup(void)
|
|||
if (!options)
|
||||
return -ENODEV;
|
||||
|
||||
val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay",
|
||||
NULL);
|
||||
val = get_property(options, "ibm,smt-snooze-delay", NULL);
|
||||
if (!smt_snooze_cmdline && val) {
|
||||
for_each_possible_cpu(cpu)
|
||||
per_cpu(smt_snooze_delay, cpu) = *val;
|
||||
|
@ -231,7 +230,7 @@ static void register_cpu_online(unsigned int cpu)
|
|||
if (cur_cpu_spec->num_pmcs >= 8)
|
||||
sysdev_create_file(s, &attr_pmc8);
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
if (cpu_has_feature(CPU_FTR_PURR))
|
||||
sysdev_create_file(s, &attr_purr);
|
||||
}
|
||||
|
||||
|
@ -273,7 +272,7 @@ static void unregister_cpu_online(unsigned int cpu)
|
|||
if (cur_cpu_spec->num_pmcs >= 8)
|
||||
sysdev_remove_file(s, &attr_pmc8);
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_SMT))
|
||||
if (cpu_has_feature(CPU_FTR_PURR))
|
||||
sysdev_remove_file(s, &attr_purr);
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
|
|
@ -860,19 +860,17 @@ EXPORT_SYMBOL(do_settimeofday);
|
|||
static int __init get_freq(char *name, int cells, unsigned long *val)
|
||||
{
|
||||
struct device_node *cpu;
|
||||
unsigned int *fp;
|
||||
const unsigned int *fp;
|
||||
int found = 0;
|
||||
|
||||
/* The cpu node should have timebase and clock frequency properties */
|
||||
cpu = of_find_node_by_type(NULL, "cpu");
|
||||
|
||||
if (cpu) {
|
||||
fp = (unsigned int *)get_property(cpu, name, NULL);
|
||||
fp = get_property(cpu, name, NULL);
|
||||
if (fp) {
|
||||
found = 1;
|
||||
*val = 0;
|
||||
while (cells--)
|
||||
*val = (*val << 32) | *fp++;
|
||||
*val = of_read_ulong(fp, cells);
|
||||
}
|
||||
|
||||
of_node_put(cpu);
|
||||
|
|
|
@ -598,6 +598,9 @@ static void parse_fpe(struct pt_regs *regs)
|
|||
#define INST_STSWI 0x7c0005aa
|
||||
#define INST_STSWX 0x7c00052a
|
||||
|
||||
#define INST_POPCNTB 0x7c0000f4
|
||||
#define INST_POPCNTB_MASK 0xfc0007fe
|
||||
|
||||
static int emulate_string_inst(struct pt_regs *regs, u32 instword)
|
||||
{
|
||||
u8 rT = (instword >> 21) & 0x1f;
|
||||
|
@ -666,6 +669,23 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int emulate_popcntb_inst(struct pt_regs *regs, u32 instword)
|
||||
{
|
||||
u32 ra,rs;
|
||||
unsigned long tmp;
|
||||
|
||||
ra = (instword >> 16) & 0x1f;
|
||||
rs = (instword >> 21) & 0x1f;
|
||||
|
||||
tmp = regs->gpr[rs];
|
||||
tmp = tmp - ((tmp >> 1) & 0x5555555555555555ULL);
|
||||
tmp = (tmp & 0x3333333333333333ULL) + ((tmp >> 2) & 0x3333333333333333ULL);
|
||||
tmp = (tmp + (tmp >> 4)) & 0x0f0f0f0f0f0f0f0fULL;
|
||||
regs->gpr[ra] = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emulate_instruction(struct pt_regs *regs)
|
||||
{
|
||||
u32 instword;
|
||||
|
@ -703,6 +723,11 @@ static int emulate_instruction(struct pt_regs *regs)
|
|||
if ((instword & INST_STRING_GEN_MASK) == INST_STRING)
|
||||
return emulate_string_inst(regs, instword);
|
||||
|
||||
/* Emulate the popcntb (Population Count Bytes) instruction. */
|
||||
if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) {
|
||||
return emulate_popcntb_inst(regs, instword);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
unsigned char *dma_window;
|
||||
const unsigned char *dma_window;
|
||||
struct iommu_table *tbl;
|
||||
unsigned long offset, size;
|
||||
|
||||
|
@ -217,7 +217,7 @@ static void __devinit vio_dev_release(struct device *dev)
|
|||
struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
|
||||
{
|
||||
struct vio_dev *viodev;
|
||||
unsigned int *unit_address;
|
||||
const unsigned int *unit_address;
|
||||
|
||||
/* we need the 'device_type' property, in order to match with drivers */
|
||||
if (of_node->type == NULL) {
|
||||
|
@ -227,7 +227,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
|
||||
unit_address = get_property(of_node, "reg", NULL);
|
||||
if (unit_address == NULL) {
|
||||
printk(KERN_WARNING "%s: node %s missing 'reg'\n",
|
||||
__FUNCTION__,
|
||||
|
@ -249,7 +249,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
|
|||
viodev->type = of_node->type;
|
||||
viodev->unit_address = *unit_address;
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES)) {
|
||||
unit_address = (unsigned int *)get_property(of_node,
|
||||
unit_address = get_property(of_node,
|
||||
"linux,unit_address", NULL);
|
||||
if (unit_address != NULL)
|
||||
viodev->unit_address = *unit_address;
|
||||
|
@ -423,7 +423,7 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
|
|||
{
|
||||
const struct vio_dev *vio_dev = to_vio_dev(dev);
|
||||
struct device_node *dn = dev->platform_data;
|
||||
char *cp;
|
||||
const char *cp;
|
||||
int length;
|
||||
|
||||
if (!num_envp)
|
||||
|
@ -431,7 +431,7 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
|
|||
|
||||
if (!dn)
|
||||
return -ENODEV;
|
||||
cp = (char *)get_property(dn, "compatible", &length);
|
||||
cp = get_property(dn, "compatible", &length);
|
||||
if (!cp)
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -493,11 +493,11 @@ static struct vio_dev *vio_find_name(const char *kobj_name)
|
|||
*/
|
||||
struct vio_dev *vio_find_node(struct device_node *vnode)
|
||||
{
|
||||
uint32_t *unit_address;
|
||||
const uint32_t *unit_address;
|
||||
char kobj_name[BUS_ID_SIZE];
|
||||
|
||||
/* construct the kobject name from the device node */
|
||||
unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
|
||||
unit_address = get_property(vnode, "reg", NULL);
|
||||
if (!unit_address)
|
||||
return NULL;
|
||||
snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
|
||||
|
|
|
@ -14,7 +14,6 @@ endif
|
|||
obj-$(CONFIG_PPC64) += checksum_64.o copypage_64.o copyuser_64.o \
|
||||
memcpy_64.o usercopy_64.o mem_64.o string.o \
|
||||
strcase.o
|
||||
obj-$(CONFIG_PPC_ISERIES) += e2a.o
|
||||
obj-$(CONFIG_XMON) += sstep.o
|
||||
|
||||
ifeq ($(CONFIG_PPC64),y)
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* EBCDIC to ASCII conversion
|
||||
*
|
||||
* This function moved here from arch/powerpc/platforms/iseries/viopath.c
|
||||
*
|
||||
* (C) Copyright 2000-2004 IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) anyu later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
unsigned char e2a(unsigned char x)
|
||||
{
|
||||
switch (x) {
|
||||
case 0xF0:
|
||||
return '0';
|
||||
case 0xF1:
|
||||
return '1';
|
||||
case 0xF2:
|
||||
return '2';
|
||||
case 0xF3:
|
||||
return '3';
|
||||
case 0xF4:
|
||||
return '4';
|
||||
case 0xF5:
|
||||
return '5';
|
||||
case 0xF6:
|
||||
return '6';
|
||||
case 0xF7:
|
||||
return '7';
|
||||
case 0xF8:
|
||||
return '8';
|
||||
case 0xF9:
|
||||
return '9';
|
||||
case 0xC1:
|
||||
return 'A';
|
||||
case 0xC2:
|
||||
return 'B';
|
||||
case 0xC3:
|
||||
return 'C';
|
||||
case 0xC4:
|
||||
return 'D';
|
||||
case 0xC5:
|
||||
return 'E';
|
||||
case 0xC6:
|
||||
return 'F';
|
||||
case 0xC7:
|
||||
return 'G';
|
||||
case 0xC8:
|
||||
return 'H';
|
||||
case 0xC9:
|
||||
return 'I';
|
||||
case 0xD1:
|
||||
return 'J';
|
||||
case 0xD2:
|
||||
return 'K';
|
||||
case 0xD3:
|
||||
return 'L';
|
||||
case 0xD4:
|
||||
return 'M';
|
||||
case 0xD5:
|
||||
return 'N';
|
||||
case 0xD6:
|
||||
return 'O';
|
||||
case 0xD7:
|
||||
return 'P';
|
||||
case 0xD8:
|
||||
return 'Q';
|
||||
case 0xD9:
|
||||
return 'R';
|
||||
case 0xE2:
|
||||
return 'S';
|
||||
case 0xE3:
|
||||
return 'T';
|
||||
case 0xE4:
|
||||
return 'U';
|
||||
case 0xE5:
|
||||
return 'V';
|
||||
case 0xE6:
|
||||
return 'W';
|
||||
case 0xE7:
|
||||
return 'X';
|
||||
case 0xE8:
|
||||
return 'Y';
|
||||
case 0xE9:
|
||||
return 'Z';
|
||||
}
|
||||
return ' ';
|
||||
}
|
||||
EXPORT_SYMBOL(e2a);
|
||||
|
||||
unsigned char* strne2a(unsigned char *dest, const unsigned char *src, size_t n)
|
||||
{
|
||||
int i;
|
||||
|
||||
n = strnlen(src, n);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dest[i] = e2a(src[i]);
|
||||
|
||||
return dest;
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include <asm/hvcall.h>
|
||||
#include <asm/iseries/hv_call.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
void __spin_yield(raw_spinlock_t *lock)
|
||||
{
|
||||
|
@ -39,13 +40,12 @@ void __spin_yield(raw_spinlock_t *lock)
|
|||
rmb();
|
||||
if (lock->slock != lock_value)
|
||||
return; /* something has changed */
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
||||
((u64)holder_cpu << 32) | yield_count);
|
||||
#else
|
||||
plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
|
||||
yield_count);
|
||||
#endif
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
||||
((u64)holder_cpu << 32) | yield_count);
|
||||
else
|
||||
plpar_hcall_norets(H_CONFER,
|
||||
get_hard_smp_processor_id(holder_cpu), yield_count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -69,13 +69,12 @@ void __rw_yield(raw_rwlock_t *rw)
|
|||
rmb();
|
||||
if (rw->lock != lock_value)
|
||||
return; /* something has changed */
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
||||
((u64)holder_cpu << 32) | yield_count);
|
||||
#else
|
||||
plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
|
||||
yield_count);
|
||||
#endif
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
|
||||
((u64)holder_cpu << 32) | yield_count);
|
||||
else
|
||||
plpar_hcall_norets(H_CONFER,
|
||||
get_hard_smp_processor_id(holder_cpu), yield_count);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -159,12 +159,12 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
|
|||
{
|
||||
unsigned int hw_cpuid = get_hard_smp_processor_id(cpu);
|
||||
struct device_node *cpu_node = NULL;
|
||||
unsigned int *interrupt_server, *reg;
|
||||
const unsigned int *interrupt_server, *reg;
|
||||
int len;
|
||||
|
||||
while ((cpu_node = of_find_node_by_type(cpu_node, "cpu")) != NULL) {
|
||||
/* Try interrupt server first */
|
||||
interrupt_server = (unsigned int *)get_property(cpu_node,
|
||||
interrupt_server = get_property(cpu_node,
|
||||
"ibm,ppc-interrupt-server#s", &len);
|
||||
|
||||
len = len / sizeof(u32);
|
||||
|
@ -175,8 +175,7 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
|
|||
return cpu_node;
|
||||
}
|
||||
} else {
|
||||
reg = (unsigned int *)get_property(cpu_node,
|
||||
"reg", &len);
|
||||
reg = get_property(cpu_node, "reg", &len);
|
||||
if (reg && (len > 0) && (reg[0] == hw_cpuid))
|
||||
return cpu_node;
|
||||
}
|
||||
|
@ -186,9 +185,9 @@ static struct device_node * __cpuinit find_cpu_node(unsigned int cpu)
|
|||
}
|
||||
|
||||
/* must hold reference to node during call */
|
||||
static int *of_get_associativity(struct device_node *dev)
|
||||
static const int *of_get_associativity(struct device_node *dev)
|
||||
{
|
||||
return (unsigned int *)get_property(dev, "ibm,associativity", NULL);
|
||||
return get_property(dev, "ibm,associativity", NULL);
|
||||
}
|
||||
|
||||
/* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa
|
||||
|
@ -197,7 +196,7 @@ static int *of_get_associativity(struct device_node *dev)
|
|||
static int of_node_to_nid_single(struct device_node *device)
|
||||
{
|
||||
int nid = -1;
|
||||
unsigned int *tmp;
|
||||
const unsigned int *tmp;
|
||||
|
||||
if (min_common_depth == -1)
|
||||
goto out;
|
||||
|
@ -255,7 +254,7 @@ EXPORT_SYMBOL_GPL(of_node_to_nid);
|
|||
static int __init find_min_common_depth(void)
|
||||
{
|
||||
int depth;
|
||||
unsigned int *ref_points;
|
||||
const unsigned int *ref_points;
|
||||
struct device_node *rtas_root;
|
||||
unsigned int len;
|
||||
|
||||
|
@ -270,7 +269,7 @@ static int __init find_min_common_depth(void)
|
|||
* configuration (should be all 0's) and the second is for a normal
|
||||
* NUMA configuration.
|
||||
*/
|
||||
ref_points = (unsigned int *)get_property(rtas_root,
|
||||
ref_points = get_property(rtas_root,
|
||||
"ibm,associativity-reference-points", &len);
|
||||
|
||||
if ((len >= 1) && ref_points) {
|
||||
|
@ -297,7 +296,7 @@ static void __init get_n_mem_cells(int *n_addr_cells, int *n_size_cells)
|
|||
of_node_put(memory);
|
||||
}
|
||||
|
||||
static unsigned long __devinit read_n_cells(int n, unsigned int **buf)
|
||||
static unsigned long __devinit read_n_cells(int n, const unsigned int **buf)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
|
||||
|
@ -435,15 +434,13 @@ static int __init parse_numa_properties(void)
|
|||
unsigned long size;
|
||||
int nid;
|
||||
int ranges;
|
||||
unsigned int *memcell_buf;
|
||||
const unsigned int *memcell_buf;
|
||||
unsigned int len;
|
||||
|
||||
memcell_buf = (unsigned int *)get_property(memory,
|
||||
memcell_buf = get_property(memory,
|
||||
"linux,usable-memory", &len);
|
||||
if (!memcell_buf || len <= 0)
|
||||
memcell_buf =
|
||||
(unsigned int *)get_property(memory, "reg",
|
||||
&len);
|
||||
memcell_buf = get_property(memory, "reg", &len);
|
||||
if (!memcell_buf || len <= 0)
|
||||
continue;
|
||||
|
||||
|
@ -787,10 +784,10 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
|
|||
while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {
|
||||
unsigned long start, size;
|
||||
int ranges;
|
||||
unsigned int *memcell_buf;
|
||||
const unsigned int *memcell_buf;
|
||||
unsigned int len;
|
||||
|
||||
memcell_buf = (unsigned int *)get_property(memory, "reg", &len);
|
||||
memcell_buf = get_property(memory, "reg", &len);
|
||||
if (!memcell_buf || len <= 0)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <asm/paca.h>
|
||||
#include <asm/cputable.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/smp.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
|
@ -50,9 +52,32 @@ static inline unsigned long mk_vsid_data(unsigned long ea, unsigned long flags)
|
|||
return (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | flags;
|
||||
}
|
||||
|
||||
static inline void create_slbe(unsigned long ea, unsigned long flags,
|
||||
unsigned long entry)
|
||||
static inline void slb_shadow_update(unsigned long esid, unsigned long vsid,
|
||||
unsigned long entry)
|
||||
{
|
||||
/*
|
||||
* Clear the ESID first so the entry is not valid while we are
|
||||
* updating it.
|
||||
*/
|
||||
get_slb_shadow()->save_area[entry].esid = 0;
|
||||
barrier();
|
||||
get_slb_shadow()->save_area[entry].vsid = vsid;
|
||||
barrier();
|
||||
get_slb_shadow()->save_area[entry].esid = esid;
|
||||
|
||||
}
|
||||
|
||||
static inline void create_shadowed_slbe(unsigned long ea, unsigned long flags,
|
||||
unsigned long entry)
|
||||
{
|
||||
/*
|
||||
* Updating the shadow buffer before writing the SLB ensures
|
||||
* we don't get a stale entry here if we get preempted by PHYP
|
||||
* between these two statements.
|
||||
*/
|
||||
slb_shadow_update(mk_esid_data(ea, entry), mk_vsid_data(ea, flags),
|
||||
entry);
|
||||
|
||||
asm volatile("slbmte %0,%1" :
|
||||
: "r" (mk_vsid_data(ea, flags)),
|
||||
"r" (mk_esid_data(ea, entry))
|
||||
|
@ -77,6 +102,10 @@ void slb_flush_and_rebolt(void)
|
|||
if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET)
|
||||
ksp_esid_data &= ~SLB_ESID_V;
|
||||
|
||||
/* Only third entry (stack) may change here so only resave that */
|
||||
slb_shadow_update(ksp_esid_data,
|
||||
mk_vsid_data(ksp_esid_data, lflags), 2);
|
||||
|
||||
/* We need to do this all in asm, so we're sure we don't touch
|
||||
* the stack between the slbia and rebolting it. */
|
||||
asm volatile("isync\n"
|
||||
|
@ -209,9 +238,9 @@ void slb_initialize(void)
|
|||
asm volatile("isync":::"memory");
|
||||
asm volatile("slbmte %0,%0"::"r" (0) : "memory");
|
||||
asm volatile("isync; slbia; isync":::"memory");
|
||||
create_slbe(PAGE_OFFSET, lflags, 0);
|
||||
create_shadowed_slbe(PAGE_OFFSET, lflags, 0);
|
||||
|
||||
create_slbe(VMALLOC_START, vflags, 1);
|
||||
create_shadowed_slbe(VMALLOC_START, vflags, 1);
|
||||
|
||||
/* We don't bolt the stack for the time being - we're in boot,
|
||||
* so the stack is in the bolted segment. By the time it goes
|
||||
|
|
|
@ -146,6 +146,7 @@ void hpte_update(struct mm_struct *mm, unsigned long addr,
|
|||
psize = mmu_huge_psize;
|
||||
#else
|
||||
BUG();
|
||||
psize = pte_pagesize_index(pte); /* shutup gcc */
|
||||
#endif
|
||||
} else
|
||||
psize = pte_pagesize_index(pte);
|
||||
|
|
|
@ -60,8 +60,8 @@ static void __init mpc834x_itx_setup_arch(void)
|
|||
|
||||
np = of_find_node_by_type(NULL, "cpu");
|
||||
if (np != 0) {
|
||||
unsigned int *fp =
|
||||
(int *)get_property(np, "clock-frequency", NULL);
|
||||
const unsigned int *fp =
|
||||
get_property(np, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
|
|
|
@ -57,8 +57,8 @@ static void __init mpc834x_sys_setup_arch(void)
|
|||
|
||||
np = of_find_node_by_type(NULL, "cpu");
|
||||
if (np != 0) {
|
||||
unsigned int *fp =
|
||||
(int *)get_property(np, "clock-frequency", NULL);
|
||||
const unsigned int *fp =
|
||||
get_property(np, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
|
|
|
@ -59,7 +59,7 @@ int __init add_bridge(struct device_node *dev)
|
|||
int len;
|
||||
struct pci_controller *hose;
|
||||
struct resource rsrc;
|
||||
int *bus_range;
|
||||
const int *bus_range;
|
||||
int primary = 1, has_address = 0;
|
||||
phys_addr_t immr = get_immrbase();
|
||||
|
||||
|
@ -69,7 +69,7 @@ int __init add_bridge(struct device_node *dev)
|
|||
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
|
||||
|
||||
/* Get bus range if any */
|
||||
bus_range = (int *)get_property(dev, "bus-range", &len);
|
||||
bus_range = get_property(dev, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||
printk(KERN_WARNING "Can't get bus-range for %s, assume"
|
||||
" bus 0\n", dev->full_name);
|
||||
|
|
|
@ -121,9 +121,9 @@ static void __init mpc85xx_ads_setup_arch(void)
|
|||
|
||||
cpu = of_find_node_by_type(NULL, "cpu");
|
||||
if (cpu != 0) {
|
||||
unsigned int *fp;
|
||||
const unsigned int *fp;
|
||||
|
||||
fp = (int *)get_property(cpu, "clock-frequency", NULL);
|
||||
fp = get_property(cpu, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
|
|
|
@ -241,9 +241,9 @@ mpc85xx_cds_setup_arch(void)
|
|||
|
||||
cpu = of_find_node_by_type(NULL, "cpu");
|
||||
if (cpu != 0) {
|
||||
unsigned int *fp;
|
||||
const unsigned int *fp;
|
||||
|
||||
fp = (int *)get_property(cpu, "clock-frequency", NULL);
|
||||
fp = get_property(cpu, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
|
|
|
@ -41,7 +41,7 @@ int __init add_bridge(struct device_node *dev)
|
|||
int len;
|
||||
struct pci_controller *hose;
|
||||
struct resource rsrc;
|
||||
int *bus_range;
|
||||
const int *bus_range;
|
||||
int primary = 1, has_address = 0;
|
||||
phys_addr_t immr = get_immrbase();
|
||||
|
||||
|
@ -51,7 +51,7 @@ int __init add_bridge(struct device_node *dev)
|
|||
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
|
||||
|
||||
/* Get bus range if any */
|
||||
bus_range = (int *) get_property(dev, "bus-range", &len);
|
||||
bus_range = get_property(dev, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||
printk(KERN_WARNING "Can't get bus-range for %s, assume"
|
||||
" bus 0\n", dev->full_name);
|
||||
|
|
|
@ -347,9 +347,9 @@ mpc86xx_hpcn_setup_arch(void)
|
|||
|
||||
np = of_find_node_by_type(NULL, "cpu");
|
||||
if (np != 0) {
|
||||
unsigned int *fp;
|
||||
const unsigned int *fp;
|
||||
|
||||
fp = (int *)get_property(np, "clock-frequency", NULL);
|
||||
fp = get_property(np, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
|
|
|
@ -153,7 +153,7 @@ int __init add_bridge(struct device_node *dev)
|
|||
int len;
|
||||
struct pci_controller *hose;
|
||||
struct resource rsrc;
|
||||
int *bus_range;
|
||||
const int *bus_range;
|
||||
int has_address = 0;
|
||||
int primary = 0;
|
||||
|
||||
|
@ -163,7 +163,7 @@ int __init add_bridge(struct device_node *dev)
|
|||
has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
|
||||
|
||||
/* Get bus range if any */
|
||||
bus_range = (int *) get_property(dev, "bus-range", &len);
|
||||
bus_range = get_property(dev, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int))
|
||||
printk(KERN_WARNING "Can't get bus-range for %s, assume"
|
||||
" bus 0\n", dev->full_name);
|
||||
|
|
|
@ -13,5 +13,6 @@ obj-$(CONFIG_PPC_86xx) += 86xx/
|
|||
obj-$(CONFIG_PPC_PSERIES) += pseries/
|
||||
obj-$(CONFIG_PPC_ISERIES) += iseries/
|
||||
obj-$(CONFIG_PPC_MAPLE) += maple/
|
||||
obj-$(CONFIG_PPC_PASEMI) += pasemi/
|
||||
obj-$(CONFIG_PPC_CELL) += cell/
|
||||
obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
|
||||
|
|
|
@ -97,7 +97,7 @@ void __init cbe_regs_init(void)
|
|||
struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
|
||||
|
||||
/* That hack must die die die ! */
|
||||
struct address_prop {
|
||||
const struct address_prop {
|
||||
unsigned long address;
|
||||
unsigned int len;
|
||||
} __attribute__((packed)) *prop;
|
||||
|
@ -114,13 +114,11 @@ void __init cbe_regs_init(void)
|
|||
if (cbe_thread_map[i].cpu_node == cpu)
|
||||
cbe_thread_map[i].regs = map;
|
||||
|
||||
prop = (struct address_prop *)get_property(cpu, "pervasive",
|
||||
NULL);
|
||||
prop = get_property(cpu, "pervasive", NULL);
|
||||
if (prop != NULL)
|
||||
map->pmd_regs = ioremap(prop->address, prop->len);
|
||||
|
||||
prop = (struct address_prop *)get_property(cpu, "iic",
|
||||
NULL);
|
||||
prop = get_property(cpu, "iic", NULL);
|
||||
if (prop != NULL)
|
||||
map->iic_regs = ioremap(prop->address, prop->len);
|
||||
}
|
||||
|
|
|
@ -89,17 +89,17 @@ static struct irq_chip iic_chip = {
|
|||
/* Get an IRQ number from the pending state register of the IIC */
|
||||
static unsigned int iic_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
struct cbe_iic_pending_bits pending;
|
||||
struct iic *iic;
|
||||
struct cbe_iic_pending_bits pending;
|
||||
struct iic *iic;
|
||||
|
||||
iic = &__get_cpu_var(iic);
|
||||
*(unsigned long *) &pending =
|
||||
in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
|
||||
iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
|
||||
BUG_ON(iic->eoi_ptr > 15);
|
||||
iic = &__get_cpu_var(iic);
|
||||
*(unsigned long *) &pending =
|
||||
in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
|
||||
iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
|
||||
BUG_ON(iic->eoi_ptr > 15);
|
||||
if (pending.flags & CBE_IIC_IRQ_VALID)
|
||||
return irq_linear_revmap(iic->host,
|
||||
iic_pending_to_hwnum(pending));
|
||||
iic_pending_to_hwnum(pending));
|
||||
return NO_IRQ;
|
||||
}
|
||||
|
||||
|
@ -250,16 +250,15 @@ static int __init setup_iic(void)
|
|||
struct resource r0, r1;
|
||||
struct irq_host *host;
|
||||
int found = 0;
|
||||
u32 *np;
|
||||
const u32 *np;
|
||||
|
||||
for (dn = NULL;
|
||||
(dn = of_find_node_by_name(dn,"interrupt-controller")) != NULL;) {
|
||||
if (!device_is_compatible(dn,
|
||||
"IBM,CBEA-Internal-Interrupt-Controller"))
|
||||
continue;
|
||||
np = (u32 *)get_property(dn, "ibm,interrupt-server-ranges",
|
||||
NULL);
|
||||
if (np == NULL) {
|
||||
np = get_property(dn, "ibm,interrupt-server-ranges", NULL);
|
||||
if (np == NULL) {
|
||||
printk(KERN_WARNING "IIC: CPU association not found\n");
|
||||
of_node_put(dn);
|
||||
return -ENODEV;
|
||||
|
|
|
@ -308,15 +308,16 @@ static void cell_do_map_iommu(struct cell_iommu *iommu,
|
|||
|
||||
static void iommu_devnode_setup(struct device_node *d)
|
||||
{
|
||||
unsigned int *ioid;
|
||||
unsigned long *dma_window, map_start, map_size, token;
|
||||
const unsigned int *ioid;
|
||||
unsigned long map_start, map_size, token;
|
||||
const unsigned long *dma_window;
|
||||
struct cell_iommu *iommu;
|
||||
|
||||
ioid = (unsigned int *)get_property(d, "ioid", NULL);
|
||||
ioid = get_property(d, "ioid", NULL);
|
||||
if (!ioid)
|
||||
pr_debug("No ioid entry found !\n");
|
||||
|
||||
dma_window = (unsigned long *)get_property(d, "ibm,dma-window", NULL);
|
||||
dma_window = get_property(d, "ibm,dma-window", NULL);
|
||||
if (!dma_window)
|
||||
pr_debug("No ibm,dma-window entry found !\n");
|
||||
|
||||
|
@ -371,8 +372,9 @@ static int cell_map_iommu_hardcoded(int num_nodes)
|
|||
|
||||
static int cell_map_iommu(void)
|
||||
{
|
||||
unsigned int num_nodes = 0, *node_id;
|
||||
unsigned long *base, *mmio_base;
|
||||
unsigned int num_nodes = 0;
|
||||
const unsigned int *node_id;
|
||||
const unsigned long *base, *mmio_base;
|
||||
struct device_node *dn;
|
||||
struct cell_iommu *iommu = NULL;
|
||||
|
||||
|
@ -381,7 +383,7 @@ static int cell_map_iommu(void)
|
|||
for(dn = of_find_node_by_type(NULL, "cpu");
|
||||
dn;
|
||||
dn = of_find_node_by_type(dn, "cpu")) {
|
||||
node_id = (unsigned int *)get_property(dn, "node-id", NULL);
|
||||
node_id = get_property(dn, "node-id", NULL);
|
||||
|
||||
if (num_nodes < *node_id)
|
||||
num_nodes = *node_id;
|
||||
|
@ -396,9 +398,9 @@ static int cell_map_iommu(void)
|
|||
dn;
|
||||
dn = of_find_node_by_type(dn, "cpu")) {
|
||||
|
||||
node_id = (unsigned int *)get_property(dn, "node-id", NULL);
|
||||
base = (unsigned long *)get_property(dn, "ioc-cache", NULL);
|
||||
mmio_base = (unsigned long *)get_property(dn, "ioc-translation", NULL);
|
||||
node_id = get_property(dn, "node-id", NULL);
|
||||
base = get_property(dn, "ioc-cache", NULL);
|
||||
mmio_base = get_property(dn, "ioc-translation", NULL);
|
||||
|
||||
if (!base || !mmio_base || !node_id)
|
||||
return cell_map_iommu_hardcoded(num_nodes);
|
||||
|
|
|
@ -150,10 +150,6 @@ static int __init cell_probe(void)
|
|||
!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_UDBG_RTAS_CONSOLE
|
||||
udbg_init_rtas_console();
|
||||
#endif
|
||||
|
||||
hpte_init_native();
|
||||
|
||||
return 1;
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
*/
|
||||
static cpumask_t of_spin_map;
|
||||
|
||||
extern void pSeries_secondary_smp_init(unsigned long);
|
||||
extern void generic_secondary_smp_init(unsigned long);
|
||||
|
||||
/**
|
||||
* smp_startup_cpu() - start the given cpu
|
||||
|
@ -74,7 +74,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
|
|||
{
|
||||
int status;
|
||||
unsigned long start_here = __pa((u32)*((unsigned long *)
|
||||
pSeries_secondary_smp_init));
|
||||
generic_secondary_smp_init));
|
||||
unsigned int pcpu;
|
||||
int start_cpu;
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче